diff --git a/README.md b/README.md
index 93807df..2a7b440 100644
--- a/README.md
+++ b/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).
---
\ No newline at end of file
diff --git a/backend/auction/admin.py b/backend/auction/admin.py
index 21e50de..adf954c 100644
--- a/backend/auction/admin.py
+++ b/backend/auction/admin.py
@@ -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'{obj.product.name} ({obj.product_id})')
+ return format_html('{} ({})', 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' {count} users ')
+ return format_html(' {} users ', 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' {count} bets ')
+ return format_html(' {} bets ', 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' {count} ΠΏΠΎΠ±Π΅Π΄ΠΈΡΠ΅Π»Π΅ΠΉ ')
+ return format_html(' {} ΠΏΠΎΠ±Π΅Π΄ΠΈΡΠ΅Π»Π΅ΠΉ ', 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' {count} auctions ')
+ return format_html(' {} auctions ', 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'{obj.user}')
+ return format_html('{}', 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'{obj.auction}')
+ return format_html('{}', 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' {count} transactions ')
+ return format_html(' {} transactions ', url, count)
view_transactions_link.short_description = 'Π’ΡΠ°Π½Π·Π°ΠΊΡΠΈΠΈ'
diff --git a/backend/clicks/admin.py b/backend/clicks/admin.py
index 4657d44..2b1add1 100644
--- a/backend/clicks/admin.py
+++ b/backend/clicks/admin.py
@@ -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'{obj.user}')
+ return format_html('{}', 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'{obj.transaction}')
+ return format_html('{}', url, obj.transaction)
view_transaction_link.short_description = 'Π’ΡΠ°Π½Π·Π°ΠΊΡΠΈΡ'
diff --git a/backend/users/admin.py b/backend/users/admin.py
index c0ec8ec..8acefbf 100644
--- a/backend/users/admin.py
+++ b/backend/users/admin.py
@@ -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'{obj.user.username} ({obj.user_id})')
+ return format_html('{} ({})', 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'{obj.referred_by.username} ({obj.referred_by.tg_id})')
+ return format_html('{} ({})', 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' {count} users ')
+ return format_html(' {} users ', 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' Π²ΡΠ΅ // '
- f' ΠΊΠ»ΠΈΠΊΠΈ // '
- f' ΡΡΠ°Π²ΠΊΠΈ // '
- f' ΠΊΠΎΠΌΠΈΡΡΠΈΠΈ // '
- f' ΡΠ΅ΡΠ΅ΡΠ°Π»ΡΠ½Π°Ρ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΠ° '
+ ' Π²ΡΠ΅ // '
+ ' ΠΊΠ»ΠΈΠΊΠΈ // '
+ ' ΡΡΠ°Π²ΠΊΠΈ // '
+ ' ΠΊΠΎΠΌΠΈΡΡΠΈΠΈ // '
+ ' ΡΠ΅ΡΠ΅ΡΠ°Π»ΡΠ½Π°Ρ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΠ° ',
+ 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' {count} clicks ')
+ return format_html(' {} clicks ', 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'{obj.user}')
+ return format_html('{}', 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'{obj.mailing_list}')
+ return format_html('{}', 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' {count} ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Π΅ΠΉ ')
+ return format_html(' {} ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Π΅ΠΉ ', 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' {count} ΠΏΠΎΠ»ΡΡΠ°ΡΠ΅Π»Π΅ΠΉ ')
+ return format_html(' {} ΠΏΠΎΠ»ΡΡΠ°ΡΠ΅Π»Π΅ΠΉ ', 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' ΠΠ½ΠΎΠΏΠΊΠ° β{obj.main_button_id}')
+ return format_html(' ΠΠ½ΠΎΠΏΠΊΠ° β{}', 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' ΠΠ½ΠΎΠΏΠΊΠ° β{obj.webapp_button_id}')
+ return format_html(' ΠΠ½ΠΎΠΏΠΊΠ° β{}', 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'{obj.user}')
+ return format_html('{}', 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' {obj.click}')
+ return format_html(' {}', 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'{obj.bet}')
+ return format_html('{}', 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' {obj.commission} ')
+ return format_html(' {} ', 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' {obj.refunded_by} ')
+ return format_html(' {} ', 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' {obj.refund_to} ')
+ return format_html(' {} ', 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' {obj.parent_transaction} ')
+ return format_html(' {} ', 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'{obj.user}')
+ return format_html('{}', url, obj.user)
view_user_link.short_description = 'ΠΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Ρ'
def view_type(self, obj):