Compare commits
2 Commits
0fae6ce3f6
...
515f5924f3
| Author | SHA1 | Date | |
|---|---|---|---|
| 515f5924f3 | |||
| 1d659ea5ee |
@@ -13,6 +13,9 @@ from webapp.models import Invoice, Client, BindingRequest
|
|||||||
from bot.notifications import NotificationService
|
from bot.notifications import NotificationService
|
||||||
from bot.utils import create_bot_instance
|
from bot.utils import create_bot_instance
|
||||||
from .views import view_draw_results
|
from .views import view_draw_results
|
||||||
|
from django import forms
|
||||||
|
from django.utils.dateparse import parse_datetime, parse_date
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
# Настройка логгера
|
# Настройка логгера
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@@ -37,11 +40,30 @@ def add_participants_view(request):
|
|||||||
|
|
||||||
deposit_min = request.GET.get("deposit_min")
|
deposit_min = request.GET.get("deposit_min")
|
||||||
deposit_max = request.GET.get("deposit_max")
|
deposit_max = request.GET.get("deposit_max")
|
||||||
|
created_after = request.GET.get("created_after")
|
||||||
|
created_before = request.GET.get("created_before")
|
||||||
|
|
||||||
if deposit_min:
|
if deposit_min:
|
||||||
qs = qs.filter(deposit_sum__gte=deposit_min)
|
qs = qs.filter(deposit_sum__gte=deposit_min)
|
||||||
if deposit_max:
|
if deposit_max:
|
||||||
qs = qs.filter(deposit_sum__lte=deposit_max)
|
qs = qs.filter(deposit_sum__lte=deposit_max)
|
||||||
|
|
||||||
|
if created_after:
|
||||||
|
try:
|
||||||
|
dt = parse_date(created_after)
|
||||||
|
if dt:
|
||||||
|
qs = qs.filter(created_at__gte=dt)
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if created_before:
|
||||||
|
try:
|
||||||
|
dt = parse_date(created_before)
|
||||||
|
if dt:
|
||||||
|
qs = qs.filter(created_at__lte=dt)
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
form = AddParticipantsForm(request.POST)
|
form = AddParticipantsForm(request.POST)
|
||||||
form.fields["invoices"].queryset = qs
|
form.fields["invoices"].queryset = qs
|
||||||
@@ -77,7 +99,6 @@ def start_draw(request, lottery_id):
|
|||||||
lottery = get_object_or_404(Lottery, id=lottery_id)
|
lottery = get_object_or_404(Lottery, id=lottery_id)
|
||||||
logger.info("Запуск розыгрыша для лотереи: %s", lottery.name)
|
logger.info("Запуск розыгрыша для лотереи: %s", lottery.name)
|
||||||
|
|
||||||
# Если лотерея уже завершена, кнопку запускать не показываем
|
|
||||||
if lottery.finished:
|
if lottery.finished:
|
||||||
messages.warning(request, "Розыгрыш уже завершён.")
|
messages.warning(request, "Розыгрыш уже завершён.")
|
||||||
return redirect("..")
|
return redirect("..")
|
||||||
@@ -85,10 +106,19 @@ def start_draw(request, lottery_id):
|
|||||||
notifier = NotificationService(bot=create_bot_instance())
|
notifier = NotificationService(bot=create_bot_instance())
|
||||||
async_to_sync(notifier.notify_draw_start)(lottery)
|
async_to_sync(notifier.notify_draw_start)(lottery)
|
||||||
|
|
||||||
|
# Собираем ID счетов вручную назначенных победителей
|
||||||
|
manually_assigned_invoice_ids = set()
|
||||||
|
for prize in lottery.prizes.all():
|
||||||
|
if prize.winner and prize.winner.invoice:
|
||||||
|
manually_assigned_invoice_ids.add(prize.winner.invoice_id)
|
||||||
|
# Помечаем вручную выбранного участника как использованного
|
||||||
|
prize.winner.used = True
|
||||||
|
prize.winner.save()
|
||||||
|
|
||||||
for prize in lottery.prizes.all():
|
for prize in lottery.prizes.all():
|
||||||
logger.info("Обработка приза: %s", prize.prize_place)
|
logger.info("Обработка приза: %s", prize.prize_place)
|
||||||
|
|
||||||
# Если для приза уже назначен победитель вручную, сохраняем его в таблице результатов
|
# Если у приза уже установлен победитель вручную — сохраняем его в таблицу результатов
|
||||||
if prize.winner:
|
if prize.winner:
|
||||||
logger.info("Приз '%s' имеет установленного вручную победителя. Сохраняем в таблице результатов.", prize.prize_place)
|
logger.info("Приз '%s' имеет установленного вручную победителя. Сохраняем в таблице результатов.", prize.prize_place)
|
||||||
try:
|
try:
|
||||||
@@ -115,7 +145,10 @@ def start_draw(request, lottery_id):
|
|||||||
except DrawResult.DoesNotExist:
|
except DrawResult.DoesNotExist:
|
||||||
draw_result = None
|
draw_result = None
|
||||||
|
|
||||||
participants = list(lottery.participants.filter(used=False))
|
# Получаем всех неиспользованных участников, исключая вручную выбранных
|
||||||
|
participants = list(
|
||||||
|
lottery.participants.filter(used=False).exclude(invoice_id__in=manually_assigned_invoice_ids)
|
||||||
|
)
|
||||||
logger.info("Найдено свободных участников для приза '%s': %d", prize.prize_place, len(participants))
|
logger.info("Найдено свободных участников для приза '%s': %d", prize.prize_place, len(participants))
|
||||||
if not participants:
|
if not participants:
|
||||||
logger.warning("Нет свободных участников для приза '%s'.", prize.prize_place)
|
logger.warning("Нет свободных участников для приза '%s'.", prize.prize_place)
|
||||||
@@ -145,7 +178,6 @@ def start_draw(request, lottery_id):
|
|||||||
draw_results = lottery.draw_results.all()
|
draw_results = lottery.draw_results.all()
|
||||||
async_to_sync(notifier.notify_draw_results)(lottery, draw_results)
|
async_to_sync(notifier.notify_draw_results)(lottery, draw_results)
|
||||||
|
|
||||||
# Если все призы розыгрыша подтверждены, устанавливаем флаг завершения лотереи
|
|
||||||
if not lottery.prizes.filter(winner__isnull=True).exists():
|
if not lottery.prizes.filter(winner__isnull=True).exists():
|
||||||
lottery.finished = True
|
lottery.finished = True
|
||||||
lottery.save()
|
lottery.save()
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
const selectAllCheckbox = document.getElementById("select-all");
|
const selectAllCheckbox = document.getElementById("select-all");
|
||||||
if (selectAllCheckbox) {
|
if (selectAllCheckbox) {
|
||||||
selectAllCheckbox.addEventListener("click", function(){
|
selectAllCheckbox.addEventListener("click", function(){
|
||||||
const checkboxes = document.querySelectorAll("input[name='invoices']");
|
const checkboxes = document.querySelectorAll("input[name='invoices[]']");
|
||||||
checkboxes.forEach(chk => chk.checked = selectAllCheckbox.checked);
|
checkboxes.forEach(chk => chk.checked = selectAllCheckbox.checked);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -23,24 +23,38 @@
|
|||||||
{% endblock extrahead %}
|
{% endblock extrahead %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="container-fluid">
|
<div class="container-fluid custom-container">
|
||||||
<h1>Добавление участников лотереи: {{ lottery.name }}</h1>
|
<h1>Добавление участников лотереи: {{ lottery.name }}</h1>
|
||||||
<p>{{ lottery.description }}</p>
|
<p>{{ lottery.description }}</p>
|
||||||
|
|
||||||
<!-- Форма фильтрации -->
|
<!-- Форма фильтрации -->
|
||||||
<form method="get" class="form-inline mb-3">
|
<form method="get" class="mb-4">
|
||||||
<input type="hidden" name="lottery_id" value="{{ lottery.id }}">
|
<input type="hidden" name="lottery_id" value="{{ lottery.id }}">
|
||||||
<div class="form-group mr-3">
|
<div class="row">
|
||||||
<label for="id_deposit_min" class="mr-2">Минимальный депозит:</label>
|
<div class="col-md-3">
|
||||||
<input type="number" step="0.01" name="deposit_min" id="id_deposit_min" class="form-control">
|
<label>Минимальная сумма депозита:</label>
|
||||||
|
<input type="number" step="0.01" name="deposit_min" value="{{ request.GET.deposit_min }}" class="form-control">
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group mr-3">
|
<div class="col-md-3">
|
||||||
<label for="id_deposit_max" class="mr-2">Максимальный депозит:</label>
|
<label>Максимальная сумма депозита:</label>
|
||||||
<input type="number" step="0.01" name="deposit_max" id="id_deposit_max" class="form-control">
|
<input type="number" step="0.01" name="deposit_max" value="{{ request.GET.deposit_max }}" class="form-control">
|
||||||
|
</div>
|
||||||
|
<div class="col-md-3">
|
||||||
|
<label>Дата создания от:</label>
|
||||||
|
<input type="date" name="created_after" value="{{ request.GET.created_after }}" class="form-control">
|
||||||
|
</div>
|
||||||
|
<div class="col-md-3">
|
||||||
|
<label>Дата создания до:</label>
|
||||||
|
<input type="date" name="created_before" value="{{ request.GET.created_before }}" class="form-control">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="mt-3">
|
||||||
|
<button type="submit" class="btn btn-primary">Применить фильтр</button>
|
||||||
</div>
|
</div>
|
||||||
<button type="submit" class="btn btn-info">Фильтровать</button>
|
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
<p><strong>Найдено подходящих счетов: {{ invoice_count }}</strong></p>
|
||||||
|
|
||||||
<!-- Форма добавления участников -->
|
<!-- Форма добавления участников -->
|
||||||
<form method="post">
|
<form method="post">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
@@ -49,30 +63,42 @@
|
|||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th><input type="checkbox" id="select-all" /></th>
|
<th><input type="checkbox" id="select-all" /></th>
|
||||||
|
<th>Создан</th>
|
||||||
|
<th>Закрыт</th>
|
||||||
<th>Счет</th>
|
<th>Счет</th>
|
||||||
<th>Владелец счета</th>
|
<th>Клиент</th>
|
||||||
|
<th>Номер клиента</th>
|
||||||
|
<th>Сумма счета</th>
|
||||||
|
<th>Бонус</th>
|
||||||
|
<th>ФД</th>
|
||||||
<th>Депозит</th>
|
<th>Депозит</th>
|
||||||
|
<th>Примечание</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for invoice in form.fields.invoices.queryset %}
|
{% for invoice in form.fields.invoices.queryset %}
|
||||||
<tr>
|
<tr>
|
||||||
|
<input type="checkbox" name="invoices" value="{{ invoice.id }}">
|
||||||
|
<td>{{ invoice.created_at|date:"d.m.Y H:i" }}</td>
|
||||||
<td>
|
<td>
|
||||||
<input type="checkbox" name="invoices" value="{{ invoice.id }}" />
|
{% if invoice.closed_at %}
|
||||||
</td>
|
{{ invoice.closed_at|date:"d.m.Y H:i" }}
|
||||||
<td>{{ invoice.ext_id }}</td>
|
|
||||||
<td>
|
|
||||||
{% if invoice.client_name %}
|
|
||||||
{{ invoice.client_name }}
|
|
||||||
{% else %}
|
{% else %}
|
||||||
Не указан
|
—
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
<td>{{ invoice.deposit_sum }}</td>
|
<td>{{ invoice.ext_id|default:"—" }}</td>
|
||||||
|
<td>{{ invoice.client.name|default:"Не указан" }}</td>
|
||||||
|
<td>{{ invoice.client.club_card_number|default:"—" }}</td>
|
||||||
|
<td>{{ invoice.sum|default:"—" }}</td>
|
||||||
|
<td>{{ invoice.bonus|default:"—" }}</td>
|
||||||
|
<td>{{ invoice.start_bonus|default:"—" }}</td>
|
||||||
|
<td>{{ invoice.deposit_sum|default:"—" }}</td>
|
||||||
|
<td>{{ invoice.notes|default:"—" }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% empty %}
|
{% empty %}
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="5" class="text-center">Нет доступных счетов</td>
|
<td colspan="11" class="text-center">Нет доступных счетов</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
@@ -81,6 +107,8 @@
|
|||||||
<button type="submit" class="btn btn-primary">Добавить выбранные счета</button>
|
<button type="submit" class="btn btn-primary">Добавить выбранные счета</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a href="{% url 'admin:draw_lotteryparticipant_changelist' %}" class="btn btn-secondary mt-3">Вернуться к списку участников</a>
|
<a href="{% url 'admin:draw_lotteryparticipant_changelist' %}" class="btn btn-secondary mt-3">Вернуться к списку участников</a>
|
||||||
</div>
|
</div>
|
||||||
{% endblock content %}
|
{% endblock content %}
|
||||||
|
|||||||
@@ -95,14 +95,19 @@ class API_SYNC:
|
|||||||
self.logger.warning("Запись клиента %s пропущена: отсутствует club_card_num. Запись: %s", index, item)
|
self.logger.warning("Запись клиента %s пропущена: отсутствует club_card_num. Запись: %s", index, item)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Используем update_or_create для обновления существующей записи
|
|
||||||
obj, created = Client.objects.update_or_create(
|
|
||||||
club_card_number=club_card_number,
|
|
||||||
defaults = {
|
defaults = {
|
||||||
'name': item.get("name"),
|
'name': item.get("name"),
|
||||||
'telegram_id': item.get("telegram_id"),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
telegram_id = item.get("telegram_id")
|
||||||
|
if telegram_id:
|
||||||
|
defaults['telegram_id'] = telegram_id # Обновим только если значение есть
|
||||||
|
|
||||||
|
obj, created = Client.objects.update_or_create(
|
||||||
|
club_card_number=club_card_number,
|
||||||
|
defaults=defaults
|
||||||
)
|
)
|
||||||
|
|
||||||
new_or_updated += 1
|
new_or_updated += 1
|
||||||
if created:
|
if created:
|
||||||
self.logger.info("Запись клиента %s создана: club_card_num %s.", index, club_card_number)
|
self.logger.info("Запись клиента %s создана: club_card_num %s.", index, club_card_number)
|
||||||
@@ -112,6 +117,7 @@ class API_SYNC:
|
|||||||
self.logger.error("Запись клиента %s имеет неожиданный тип: %s. Значение: %s", index, type(item), item)
|
self.logger.error("Запись клиента %s имеет неожиданный тип: %s. Значение: %s", index, type(item), item)
|
||||||
return new_or_updated
|
return new_or_updated
|
||||||
|
|
||||||
|
|
||||||
def sync_invoices(self):
|
def sync_invoices(self):
|
||||||
api_client = APIClient()
|
api_client = APIClient()
|
||||||
data = api_client.get_invoices()
|
data = api_client.get_invoices()
|
||||||
|
|||||||
Reference in New Issue
Block a user