Merge branch 'dev' into issue/6
This commit is contained in:
commit
95e74edb8e
51
README.md
51
README.md
|
@ -17,11 +17,11 @@ This clicker bot combines fun and strategy, making it a unique experience for Te
|
|||
|
||||
Our project leverages a modern technology stack to ensure scalability, performance, and seamless user interactions:
|
||||
|
||||
- **Frontend**: [React.js, Vue.js, etc.]
|
||||
- **Frontend**: [React, Typescript]
|
||||
- **Backend**: [Django, Flask, etc.]
|
||||
- **Database**: [PostgreSQL, MongoDB, MySQL, etc.]
|
||||
- **Database**: [PostgreSQL]
|
||||
- **Authentication**: [JWT, OAuth, etc.]
|
||||
- **Deployment**: [Docker, Kubernetes, AWS, etc.]
|
||||
- **Deployment**: [Docker]
|
||||
|
||||
We have structured our architecture for flexibility and ease of integration with future features.
|
||||
|
||||
|
@ -29,9 +29,9 @@ We have structured our architecture for flexibility and ease of integration with
|
|||
|
||||
The project is a collaboration of skilled and passionate individuals:
|
||||
|
||||
2. **Michael Kostochka**: [Role: Backend Developer] - Ensures smooth operations behind the scenes with efficient APIs.
|
||||
3. **Sitnikov Arseniy**: [Role: Database Architect] - Responsible for managing data flows and ensuring high performance.
|
||||
4. **Vakulenkov Danila**: [Role: DevOps Engineer] - Orchestrates deployment, monitoring, and infrastructure management.
|
||||
2. **Michael Kostochka**: [Role: Backend Developer, Database Architect]
|
||||
3. **Sitnikov Arseniy**: [Role: Frontend Developer, Database Architect]
|
||||
4. **Vakulenkov Danila**: [Role: Backend Engineer, Database Architect]
|
||||
|
||||
## 🎨 **Visuals**
|
||||
|
||||
|
@ -49,51 +49,22 @@ git clone https://github.com/Danya-Djan/db_kyc_project.git
|
|||
cd db_kyc_project
|
||||
```
|
||||
|
||||
### **2. Install Dependencies**
|
||||
### **2. Environment Setup**
|
||||
|
||||
Ensure you have [Node.js](https://nodejs.org/) and [Docker](https://www.docker.com/) installed.
|
||||
Create a `.env` file in the root of the project and add the needed variables
|
||||
|
||||
For **Frontend**:
|
||||
|
||||
```bash
|
||||
cd frontend
|
||||
```
|
||||
|
||||
For **Backend**:
|
||||
|
||||
```bash
|
||||
cd backend
|
||||
```
|
||||
|
||||
### **3. Environment Setup**
|
||||
|
||||
Create a `.env` file in the root of the project and add the following variables:
|
||||
|
||||
```
|
||||
DB_HOST=localhost
|
||||
DB_USER=[your-db-user]
|
||||
DB_PASS=[your-db-password]
|
||||
JWT_SECRET=[your-secret]
|
||||
```
|
||||
|
||||
### **4. Run the Project**
|
||||
### **3. Run the Project**
|
||||
|
||||
To start both frontend and backend servers in development mode:
|
||||
|
||||
For **Frontend and Backend**:
|
||||
|
||||
```bash
|
||||
docker-compose up
|
||||
docker-compose up --build
|
||||
```
|
||||
|
||||
You can access the application at `http://localhost:3000`.
|
||||
|
||||
## 🤝 **Contributing**
|
||||
|
||||
We welcome contributions! Please read our [CONTRIBUTING.md](link_to_contributing_file) for details on our code of conduct and the process for submitting pull requests.
|
||||
|
||||
## 📜 **License**
|
||||
|
||||
This project is licensed under the [MIPT License](link_to_license_file).
|
||||
This project is licensed under the [MIPT License](https://github.com/MIPT-ILab/MDSP/blob/master/LICENSE).
|
||||
|
||||
---
|
|
@ -44,26 +44,26 @@ class AuctionAdmin(admin.ModelAdmin):
|
|||
|
||||
def view_product_link(self, obj):
|
||||
url = reverse("admin:auction_product_change", args=[obj.product_id])
|
||||
return format_html(f'<a href="{url}">{obj.product.name} ({obj.product_id})</a>')
|
||||
return format_html('<a href="{}">{} ({})</a>', url, obj.product.name, obj.product_id)
|
||||
view_product_link.short_description = 'Товар'
|
||||
|
||||
def view_betters_link(self, obj):
|
||||
count = obj.betters.distinct().count()
|
||||
url = reverse('admin:users_tguser_changelist') + '?' + urlencode({'betters__pk': f'{obj.pk}'})
|
||||
return format_html(f'<a href="{url}"> {count} users </a>')
|
||||
return format_html('<a href="{}"> {} users </a>', url, count)
|
||||
view_betters_link.short_description = 'Пользователи, сделавшие ставки'
|
||||
|
||||
def view_bets_link(self, obj):
|
||||
count = obj.bets.count()
|
||||
url = reverse('admin:auction_bet_changelist') + '?' + urlencode({'auction_id': f'{obj.pk}'})
|
||||
return format_html(f'<a href="{url}"> {count} bets </a>')
|
||||
return format_html('<a href="{}"> {} bets </a>', url, count)
|
||||
view_bets_link.short_description = 'Ставки'
|
||||
|
||||
def view_winners_link(self, obj):
|
||||
winning_user_ids = obj.bets.filter(_is_winning=True).values_list('user_id', flat=True)
|
||||
count = winning_user_ids.count()
|
||||
url = reverse('admin:users_tguser_changelist') + '?' + urlencode({'pk__in': ','.join(map(str, winning_user_ids))})
|
||||
return format_html(f'<a href="{url}"> {count} победителей </a>')
|
||||
return format_html('<a href="{}"> {} победителей </a>', url, count)
|
||||
view_winners_link.short_description = 'Победители'
|
||||
|
||||
|
||||
|
@ -86,7 +86,7 @@ class ProductAdmin(admin.ModelAdmin):
|
|||
def view_auctions_link(self, obj):
|
||||
count = obj.auctions.count()
|
||||
url = reverse('admin:auction_auction_changelist') + '?' + urlencode({'product_id': f'{obj.pk}'})
|
||||
return format_html(f'<a href="{url}"> {count} auctions </a>')
|
||||
return format_html('<a href="{}"> {} auctions </a>', url, count)
|
||||
view_auctions_link.short_description = 'Аукционы'
|
||||
|
||||
|
||||
|
@ -132,16 +132,16 @@ class BetAdmin(admin.ModelAdmin):
|
|||
|
||||
def view_user_link(self, obj):
|
||||
url = reverse("admin:users_tguser_change", args=[obj.user_id])
|
||||
return format_html(f'<a href="{url}">{obj.user}</a>')
|
||||
return format_html('<a href="{}">{}</a>', url, obj.user)
|
||||
view_user_link.short_description = 'Пользователь'
|
||||
|
||||
def view_auction_link(self, obj):
|
||||
url = reverse("admin:auction_auction_change", args=[obj.auction_id])
|
||||
return format_html(f'<a href="{url}">{obj.auction}</a>')
|
||||
return format_html('<a href="{}">{}</a>', url, obj.auction)
|
||||
view_auction_link.short_description = 'Аукцион'
|
||||
|
||||
def view_transactions_link(self, obj):
|
||||
count = obj.transactions.count()
|
||||
url = reverse('admin:users_bettransaction_changelist') + '?' + urlencode({'bet_id': f'{obj.pk}'})
|
||||
return format_html(f'<a href="{url}"> {count} transactions </a>')
|
||||
return format_html('<a href="{}"> {} transactions </a>', url, count)
|
||||
view_transactions_link.short_description = 'Транзакции'
|
||||
|
|
|
@ -28,10 +28,10 @@ class ClickAdmin(admin.ModelAdmin):
|
|||
|
||||
def view_user_link(self, obj):
|
||||
url = reverse("admin:users_tguser_change", args=[obj.user_id])
|
||||
return format_html(f'<a href="{url}">{obj.user}</a>')
|
||||
return format_html('<a href="{}">{}</a>', url, obj.user)
|
||||
view_user_link.short_description = 'Пользователь'
|
||||
|
||||
def view_transaction_link(self, obj):
|
||||
url = reverse("admin:users_clicktransaction_change", args=[obj.transaction.id])
|
||||
return format_html(f'<a href="{url}">{obj.transaction}</a>')
|
||||
return format_html('<a href="{}">{}</a>', url, obj.transaction)
|
||||
view_transaction_link.short_description = 'Транзакция'
|
||||
|
|
|
@ -58,20 +58,20 @@ class TGUserAdmin(admin.ModelAdmin):
|
|||
|
||||
def view_user_link(self, obj):
|
||||
url = reverse("admin:auth_user_change", args=[obj.user_id])
|
||||
return format_html(f'<a href="{url}">{obj.user.username} ({obj.user_id})</a>')
|
||||
return format_html('<a href="{}">{} ({})</a>', url, obj.user.username, obj.user_id)
|
||||
view_user_link.short_description = 'Системный пользователь'
|
||||
|
||||
def view_referred_by_link(self, obj):
|
||||
if not obj.referred_by:
|
||||
return
|
||||
url = reverse("admin:users_tguser_change", args=[obj.referred_by.tg_id])
|
||||
return format_html(f'<a href="{url}">{obj.referred_by.username} ({obj.referred_by.tg_id})</a>')
|
||||
return format_html('<a href="{}">{} ({})</a>', url, obj.referred_by.username, obj.referred_by.tg_id)
|
||||
view_referred_by_link.short_description = 'Кем был приглашен'
|
||||
|
||||
def view_referred_users_link(self, obj):
|
||||
count = obj.referrees.count()
|
||||
url = reverse('admin:users_tguser_changelist') + '?' + urlencode({'referred_by__tg_id': f'{obj.tg_id}'})
|
||||
return format_html(f'<a href="{url}"> {count} users </a>')
|
||||
return format_html('<a href="{}"> {} users </a>', url, count)
|
||||
view_referred_users_link.short_description = 'Приглашенные пользователи'
|
||||
|
||||
def view_transactions(self, obj):
|
||||
|
@ -82,26 +82,25 @@ class TGUserAdmin(admin.ModelAdmin):
|
|||
referral_url = reverse('admin:users_referraltransaction_changelist') + '?' + urlencode({'user_id': f'{obj.tg_id}'})
|
||||
|
||||
return format_html(
|
||||
f'<a href="{all_url}"> все </a> // '
|
||||
f'<a href="{click_url}"> клики </a> // '
|
||||
f'<a href="{bet_url}"> ставки </a> // '
|
||||
f'<a href="{commission_url}"> комиссии </a> // '
|
||||
f'<a href="{referral_url}"> реферальная программа </a>'
|
||||
'<a href="{}"> все </a> // '
|
||||
'<a href="{}"> клики </a> // '
|
||||
'<a href="{}"> ставки </a> // '
|
||||
'<a href="{}"> комиссии </a> // '
|
||||
'<a href="{}"> реферальная программа </a>',
|
||||
all_url, click_url, bet_url, commission_url, referral_url
|
||||
)
|
||||
view_transactions.short_description = 'Транзакции'
|
||||
|
||||
def view_clicks_link(self, obj):
|
||||
count = obj.clicks.count()
|
||||
url = reverse('admin:clicks_click_changelist') + '?' + urlencode({'user_id': f'{obj.tg_id}'})
|
||||
return format_html(f'<a href="{url}"> {count} clicks </a>')
|
||||
return format_html('<a href="{}"> {} clicks </a>', url, count)
|
||||
view_clicks_link.short_description = 'Клики'
|
||||
|
||||
@admin.action(description="Создать рассылку для выбранных пользователей")
|
||||
def create_mailing_list(self, request, queryset):
|
||||
request.session['user_ids'] = list(queryset.values_list('pk', flat=True))
|
||||
return HttpResponseRedirect(
|
||||
f'/admin/users/mailinglist/add/'
|
||||
)
|
||||
return HttpResponseRedirect(reverse('admin:users_mailinglist_add'))
|
||||
|
||||
|
||||
class MailingListAdminForm(forms.ModelForm):
|
||||
|
@ -162,14 +161,14 @@ class MailingListReceiverInfoAdmin(admin.ModelAdmin):
|
|||
if not obj.user:
|
||||
return None
|
||||
link = reverse("admin:users_tguser_change", args=[obj.user.tg_id])
|
||||
return format_html(f'<a href="{link}">{obj.user}</a>')
|
||||
return format_html('<a href="{}">{}</a>', link, obj.user)
|
||||
view_user_link.short_description = 'Пользователь'
|
||||
|
||||
def view_mailing_list_link(self, obj):
|
||||
if not obj.mailing_list:
|
||||
return None
|
||||
link = reverse("admin:users_mailinglist_change", args=[obj.mailing_list.pk])
|
||||
return format_html(f'<a href="{link}">{obj.mailing_list}</a>')
|
||||
return format_html('<a href="{}">{}</a>', link, obj.mailing_list)
|
||||
view_mailing_list_link.short_description = 'Рассылка'
|
||||
|
||||
|
||||
|
@ -205,28 +204,28 @@ class MailingListAdmin(admin.ModelAdmin):
|
|||
count = obj.users.count()
|
||||
url = reverse('admin:users_tguser_changelist') + '?' + urlencode(
|
||||
{'mailing_lists__id': f'{obj.id}'})
|
||||
return format_html(f'<a href="{url}"> {count} пользователей </a>')
|
||||
return format_html('<a href="{}"> {} пользователей </a>', url, count)
|
||||
view_users_link.short_description = 'Пользователи'
|
||||
|
||||
def view_mailing_list_receiver_infos_link(self, obj):
|
||||
count = obj.mailing_list_receiver_infos.count()
|
||||
url = reverse('admin:users_mailinglistreceiverinfo_changelist') + '?' + urlencode(
|
||||
{'mailing_list_id': f'{obj.id}'})
|
||||
return format_html(f'<a href="{url}"> {count} получателей </a>')
|
||||
return format_html('<a href="{}"> {} получателей </a>', url, count)
|
||||
view_mailing_list_receiver_infos_link.short_description = 'Информация о получателях'
|
||||
|
||||
def view_main_button_link(self, obj):
|
||||
if not obj.main_button:
|
||||
return
|
||||
url = reverse("admin:misc_button_change", args=[obj.main_button_id])
|
||||
return format_html(f'<a href="{url}"> Кнопка №{obj.main_button_id}</a>')
|
||||
return format_html('<a href="{}"> Кнопка №{}</a>', url, obj.main_button_id)
|
||||
view_main_button_link.short_description = 'Основная кнопка'
|
||||
|
||||
def view_webapp_button_link(self, obj):
|
||||
if not obj.webapp_button:
|
||||
return
|
||||
url = reverse("admin:misc_button_change", args=[obj.webapp_button_id])
|
||||
return format_html(f'<a href="{url}"> Кнопка №{obj.webapp_button_id}</a>')
|
||||
return format_html('<a href="{}"> Кнопка №{}</a>', url, obj.webapp_button_id)
|
||||
view_webapp_button_link.short_description = 'Кнопка, открывающая вебапп'
|
||||
|
||||
|
||||
|
@ -242,7 +241,7 @@ class TransactionChildAdmin(PolymorphicChildModelAdmin):
|
|||
if not obj.user:
|
||||
return
|
||||
url = reverse("admin:users_tguser_change", args=[obj.user.tg_id])
|
||||
return format_html(f'<a href="{url}">{obj.user}</a>')
|
||||
return format_html('<a href="{}">{}</a>', url, obj.user)
|
||||
view_user_link.short_description = 'Пользователь'
|
||||
|
||||
def has_delete_permission(self, request, obj=None):
|
||||
|
@ -269,7 +268,7 @@ class ClickTransactionAdmin(TransactionChildAdmin):
|
|||
|
||||
def view_click_link(self, obj):
|
||||
link = reverse("admin:clicks_click_change", args=[obj.click_id])
|
||||
return format_html(f'<a href="{link}"> {obj.click}</a>')
|
||||
return format_html('<a href="{}"> {}</a>', link, obj.click)
|
||||
view_click_link.short_description = 'Клик'
|
||||
|
||||
|
||||
|
@ -293,7 +292,7 @@ class BetTransactionAdmin(TransactionChildAdmin):
|
|||
|
||||
def view_bet_link(self, obj):
|
||||
link = reverse("admin:auction_bet_change", args=[obj.bet_id])
|
||||
return format_html(f'<a href="{link}">{obj.bet}</a>')
|
||||
return format_html('<a href="{}">{}</a>', link, obj.bet)
|
||||
view_bet_link.short_description = 'Ставка'
|
||||
|
||||
def view_commission_link(self, obj):
|
||||
|
@ -302,7 +301,7 @@ class BetTransactionAdmin(TransactionChildAdmin):
|
|||
except ObjectDoesNotExist:
|
||||
return None
|
||||
link = reverse("admin:users_commissiontransaction_change", args=[obj.commission.id])
|
||||
return format_html(f'<a href="{link}"> {obj.commission} </a>')
|
||||
return format_html('<a href="{}"> {} </a>', link, obj.commission)
|
||||
view_commission_link.short_description = 'Комиссия'
|
||||
|
||||
def view_refunded_by_link(self, obj):
|
||||
|
@ -311,14 +310,14 @@ class BetTransactionAdmin(TransactionChildAdmin):
|
|||
except ObjectDoesNotExist:
|
||||
return None
|
||||
link = reverse("admin:users_bettransaction_change", args=[obj.refunded_by.id])
|
||||
return format_html(f'<a href="{link}"> {obj.refunded_by} </a>')
|
||||
return format_html('<a href="{}"> {} </a>', link, obj.refunded_by)
|
||||
view_refunded_by_link.short_description = 'Чем компенсирована'
|
||||
|
||||
def view_refund_to_link(self, obj):
|
||||
if not obj.refund_to:
|
||||
return None
|
||||
link = reverse("admin:users_bettransaction_change", args=[obj.refund_to_id])
|
||||
return format_html(f'<a href="{link}"> {obj.refund_to} </a>')
|
||||
return format_html('<a href="{}"> {} </a>', link, obj.refund_to)
|
||||
view_refund_to_link.short_description = 'Что компенсирует'
|
||||
|
||||
|
||||
|
@ -339,7 +338,7 @@ class CommissionTransactionAdmin(TransactionChildAdmin):
|
|||
|
||||
def view_bet_transaction_link(self, obj):
|
||||
link = reverse("admin:users_bettransaction_change", args=[obj.parent_transaction])
|
||||
return format_html(f'<a href="{link}"> {obj.parent_transaction} </a>')
|
||||
return format_html('<a href="{}"> {} </a>', link, obj.parent_transaction)
|
||||
view_bet_transaction_link.short_description = 'Родительская транзакция'
|
||||
|
||||
|
||||
|
@ -389,7 +388,7 @@ class TransactionParentAdmin(PolymorphicParentModelAdmin):
|
|||
if not obj.user:
|
||||
return
|
||||
url = reverse("admin:users_tguser_change", args=[obj.user.tg_id])
|
||||
return format_html(f'<a href="{url}">{obj.user}</a>')
|
||||
return format_html('<a href="{}">{}</a>', url, obj.user)
|
||||
view_user_link.short_description = 'Пользователь'
|
||||
|
||||
def view_type(self, obj):
|
||||
|
|
Loading…
Reference in New Issue
Block a user