Compare commits

..

6 Commits

3 changed files with 117 additions and 51 deletions

View File

@@ -38,9 +38,11 @@ def add_participants_view(request):
return HttpResponse("Не указан параметр lottery_id", status=400) return HttpResponse("Не указан параметр lottery_id", status=400)
lottery = get_object_or_404(Lottery, id=lottery_id) lottery = get_object_or_404(Lottery, id=lottery_id)
# Все доступные счета, не участвующие в этой лотерее
used_invoice_ids = LotteryParticipant.objects.filter(lottery=lottery).values_list("invoice_id", flat=True) used_invoice_ids = LotteryParticipant.objects.filter(lottery=lottery).values_list("invoice_id", flat=True)
qs = Invoice.objects.filter(used=False).exclude(id__in=used_invoice_ids) qs = Invoice.objects.filter(used=False).exclude(id__in=used_invoice_ids)
# Фильтрация
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_after = request.GET.get("created_after")
@@ -50,6 +52,7 @@ def add_participants_view(request):
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: if created_after:
try: try:
dt = parse_date(created_after) dt = parse_date(created_after)
@@ -57,6 +60,7 @@ def add_participants_view(request):
qs = qs.filter(created_at__date__gte=dt) qs = qs.filter(created_at__date__gte=dt)
except ValueError: except ValueError:
pass pass
if created_before: if created_before:
try: try:
dt = parse_date(created_before) dt = parse_date(created_before)
@@ -64,39 +68,121 @@ def add_participants_view(request):
qs = qs.filter(created_at__date__lte=dt) qs = qs.filter(created_at__date__lte=dt)
except ValueError: except ValueError:
pass pass
if request.GET.get("without_bonus"): if request.GET.get("without_bonus"):
qs = qs.filter(Q(bonus__isnull=True) | Q(bonus=0)) qs = qs.filter(Q(bonus__isnull=True) | Q(bonus=0))
if request.GET.get("without_fd"): if request.GET.get("without_fd"):
qs = qs.filter(Q(start_bonus__isnull=True) | Q(start_bonus=0)) qs = qs.filter(Q(start_bonus__isnull=True) | Q(start_bonus=0))
# Обработка формы
if request.method == "POST": if request.method == "POST":
selected_ids = request.POST.getlist("invoices") form = AddParticipantsForm(request.POST)
selected_invoices = qs.filter(id__in=selected_ids) form.fields["invoices"].queryset = qs
added_count = 0 if form.is_valid():
for invoice in selected_invoices: selected_invoices = form.cleaned_data["invoices"]
if not LotteryParticipant.objects.filter(lottery=lottery, invoice=invoice).exists(): for invoice in selected_invoices:
invoice.used = True invoice.used = True
invoice.save() invoice.save()
LotteryParticipant.objects.create(lottery=lottery, invoice=invoice) LotteryParticipant.objects.create(lottery=lottery, invoice=invoice)
added_count += 1 messages.success(request, "Участники успешно добавлены.")
messages.success(request, f"Добавлено {added_count} участников.") return redirect("admin:draw_lotteryparticipant_changelist")
return redirect("admin:draw_lotteryparticipant_changelist") else:
form = AddParticipantsForm()
form.fields["invoices"].queryset = qs
context = { context = {
"form": form,
"lottery": lottery, "lottery": lottery,
"invoices": qs.order_by("-created_at"), "invoice_count": qs.count(), # Для отображения числа найденных
"invoice_count": qs.count(),
"request": request,
} }
return render(request, "admin/add_participants.html", context) return render(request, "admin/add_participants.html", context)
def get_client_by_invoice(invoice): def get_client_by_invoice(invoice):
try: try:
return Client.objects.get(club_card_number=invoice.client_club_card_number) return Client.objects.get(club_card_number=invoice.client_club_card_number)
except Client.DoesNotExist: except Client.DoesNotExist:
return None return None
# def start_draw(request, lottery_id):
# lottery = get_object_or_404(Lottery, id=lottery_id)
# logger.info("Запуск розыгрыша для лотереи: %s", lottery.name)
# if lottery.finished:
# messages.warning(request, "Розыгрыш уже завершён.")
# return redirect("..")
# notifier = NotificationService(bot=create_bot_instance())
# async_to_sync(notifier.notify_draw_start)(lottery)
# 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():
# logger.info("Обработка приза: %s", prize.prize_place)
# if prize.winner:
# try:
# draw_result = lottery.draw_results.get(prize=prize)
# draw_result.participant = prize.winner
# draw_result.drawn_at = timezone.now()
# draw_result.confirmed = False
# draw_result.save()
# except DrawResult.DoesNotExist:
# DrawResult.objects.create(
# lottery=lottery,
# prize=prize,
# participant=prize.winner,
# confirmed=False,
# drawn_at=timezone.now()
# )
# continue
# try:
# draw_result = lottery.draw_results.get(prize=prize)
# if draw_result.confirmed:
# continue
# except DrawResult.DoesNotExist:
# draw_result = None
# participants = list(
# lottery.participants.filter(used=False).exclude(invoice_id__in=manually_assigned_invoice_ids)
# )
# if not participants:
# continue
# winner_participant = random.choice(participants)
# winner_participant.used = True
# winner_participant.save()
# if draw_result:
# draw_result.participant = winner_participant
# draw_result.drawn_at = timezone.now()
# draw_result.confirmed = False
# draw_result.save()
# else:
# DrawResult.objects.create(
# lottery=lottery,
# prize=prize,
# participant=winner_participant,
# confirmed=False,
# drawn_at=timezone.now()
# )
# draw_results = lottery.draw_results.all()
# async_to_sync(notifier.notify_draw_results)(lottery, draw_results)
# if not lottery.prizes.filter(winner__isnull=True).exists():
# lottery.finished = True
# lottery.save()
# return render(request, "admin/draw_result.html", {"lottery": lottery, "draw_results": draw_results})
def start_draw(request, lottery_id): 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)

View File

@@ -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);
}); });
} }
@@ -27,6 +27,7 @@
<h1>Добавление участников лотереи: {{ lottery.name }}</h1> <h1>Добавление участников лотереи: {{ lottery.name }}</h1>
<p>{{ lottery.description }}</p> <p>{{ lottery.description }}</p>
<!-- Форма фильтрации -->
<form method="get" class="mb-4"> <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="row"> <div class="row">
@@ -66,6 +67,7 @@
<p><strong>Найдено подходящих счетов: {{ invoice_count }}</strong></p> <p><strong>Найдено подходящих счетов: {{ invoice_count }}</strong></p>
<!-- Форма добавления участников -->
<form method="post"> <form method="post">
{% csrf_token %} {% csrf_token %}
<div class="table-responsive"> <div class="table-responsive">
@@ -86,27 +88,29 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for invoice in invoices %} {% for invoice in form.fields.invoices.queryset %}
<tr> <tr>
<td><input type="checkbox" name="invoices" value="{{ invoice.id }}"></td> <td><input type="checkbox" name="invoices[]" value="{{ invoice.id }}"></td>
<td>{{ invoice.created_at|date:"Y-m-d H:i" }}</td> <td>{{ invoice.created_at|date:"d.m.Y H:i" }}</td>
<td>{% if invoice.closed_at %}{{ invoice.closed_at|date:"Y-m-d H:i" }}{% else %}—{% endif %}</td> <td>{% if invoice.closed_at %}{{ invoice.closed_at|date:"d.m.Y H:i"}}{% else %}—{% endif %}</td>
<td>{{ invoice.ext_id|default:"—" }}</td> <td>{{ invoice.ext_id|default:"—" }}</td>
<td>{{ invoice.client.name|default:"Не указан" }}</td> <td>{{ invoice.client.name|default:"Не указан" }}</td>
<td>{{ invoice.client.club_card_number|default:"—" }}</td> <td>{{ invoice.client.club_card_number|default:"—" }}</td>
<td>{{ invoice.sum|floatformat:2|default:"—" }}</td> <td>{{ invoice.sum|default:"—" }}</td>
<td>{{ invoice.bonus|floatformat:2|default:"—" }}</td> <td>{{ invoice.bonus|default:"—" }}</td>
<td>{{ invoice.start_bonus|floatformat:2|default:"—" }}</td> <td>{{ invoice.start_bonus|default:"—" }}</td>
<td>{{ invoice.deposit_sum|floatformat:2|default:"—" }}</td> <td>{{ invoice.deposit_sum|default:"—" }}</td>
<td>{{ invoice.notes|default:"—" }}</td> <td>{{ invoice.notes|default:"—" }}</td>
</tr> </tr>
{% empty %} {% empty %}
<tr><td colspan="11" class="text-center">Нет доступных счетов</td></tr> <tr>
<td colspan="11" class="text-center">Нет доступных счетов</td>
</tr>
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> </table>
</div> </div>
<button type="submit" class="btn btn-success">Добавить выбранные счета</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>

View File

@@ -4,35 +4,11 @@
{% block object-tools %} {% block object-tools %}
{{ block.super }} {{ block.super }}
{% if original %} {% if original %}
<div class="container-fluid"> <li>
<a class="btn btn-warning d-block w-100 text-center my-2" <a class="button"
href="{% url 'admin:botconfig-restart' original.pk %}"> href="{% url 'admin:botconfig-restart' original.pk %}">
Перезапустить бота 🔁 Перезапустить бота
</a> </a>
</div> </li>
{% endif %} {% endif %}
{% endblock %} {% endblock %}
{% block extrahead %}
{{ block.super }}
<style>
.container-fluid {
margin-top: 20px;
}
</style>
{% endblock %}
{% block footer %}
{{ block.super }}
<script>
document.addEventListener("DOMContentLoaded", function() {
const restartButton = document.querySelector('.btn-warning');
if (restartButton) {
restartButton.addEventListener('click', function(event) {
if (!confirm('Вы уверены, что хотите перезапустить бота?')) {
event.preventDefault();
}
});
}
});
</script>
{% endblock %}