feat(fees): reminder status column — sent/read tracking
Some checks are pending
NordaBiz Tests / Unit & Integration Tests (push) Waiting to run
NordaBiz Tests / E2E Tests (Playwright) (push) Blocked by required conditions
NordaBiz Tests / Smoke Tests (Production) (push) Blocked by required conditions
NordaBiz Tests / Send Failure Notification (push) Blocked by required conditions
Some checks are pending
NordaBiz Tests / Unit & Integration Tests (push) Waiting to run
NordaBiz Tests / E2E Tests (Playwright) (push) Blocked by required conditions
NordaBiz Tests / Smoke Tests (Production) (push) Blocked by required conditions
NordaBiz Tests / Send Failure Notification (push) Blocked by required conditions
New "Przypomnienie" column in yearly fee view shows: - Empty: no reminder sent yet → button "Przypomnij" - "✉ Wysłano 20.03": sent but not read → button "Ponów" - "✓ Odczytano 20.03": sent and read → button "Ponów" Status derived from last PrivateMessage with "przypomnienie o składce". Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
49fcdbdfb5
commit
069280870f
@ -667,7 +667,8 @@ def admin_fees():
|
||||
'status': fee.status if fee else 'brak'
|
||||
})
|
||||
else:
|
||||
company_data = {'company': company, 'months': {}, 'monthly_rate': 0, 'has_data': False}
|
||||
company_data = {'company': company, 'months': {}, 'monthly_rate': 0, 'has_data': False, 'reminder': None}
|
||||
has_unpaid = False
|
||||
for m in range(1, 13):
|
||||
fee = fees.get((company.id, m))
|
||||
company_data['months'][m] = fee
|
||||
@ -675,6 +676,23 @@ def admin_fees():
|
||||
company_data['has_data'] = True
|
||||
if not company_data['monthly_rate']:
|
||||
company_data['monthly_rate'] = int(fee.amount)
|
||||
if fee.status in ('pending', 'partial', 'overdue'):
|
||||
has_unpaid = True
|
||||
# Find last reminder message for this company
|
||||
if has_unpaid:
|
||||
from database import PrivateMessage, UserCompany
|
||||
manager = db.query(UserCompany).filter(UserCompany.company_id == company.id).first()
|
||||
if manager:
|
||||
last_reminder = db.query(PrivateMessage).filter(
|
||||
PrivateMessage.recipient_id == manager.user_id,
|
||||
PrivateMessage.subject.ilike('%przypomnienie o składce%'),
|
||||
).order_by(PrivateMessage.created_at.desc()).first()
|
||||
if last_reminder:
|
||||
company_data['reminder'] = {
|
||||
'sent_at': last_reminder.created_at,
|
||||
'is_read': last_reminder.is_read,
|
||||
'read_at': last_reminder.read_at,
|
||||
}
|
||||
companies_fees.append(company_data)
|
||||
|
||||
# Sort: companies with fee data first, then without
|
||||
|
||||
@ -356,6 +356,7 @@
|
||||
{% else %}
|
||||
<th>Sty</th><th>Lut</th><th>Mar</th><th>Kwi</th><th>Maj</th><th>Cze</th>
|
||||
<th>Lip</th><th>Sie</th><th>Wrz</th><th>Paz</th><th>Lis</th><th>Gru</th>
|
||||
<th>Przypomnienie</th>
|
||||
<th></th>
|
||||
{% endif %}
|
||||
</tr>
|
||||
@ -365,7 +366,7 @@
|
||||
{% for cf in companies_fees %}
|
||||
{% if not month and not cf.has_data and not ns.separator_shown %}
|
||||
{% set ns.separator_shown = true %}
|
||||
<tr><td colspan="13" style="background: var(--border); padding: var(--spacing-xs); text-align: center; font-size: var(--font-size-sm); color: var(--text-secondary); font-weight: 600;">Firmy bez danych o składkach</td></tr>
|
||||
<tr><td colspan="15" style="background: var(--border); padding: var(--spacing-xs); text-align: center; font-size: var(--font-size-sm); color: var(--text-secondary); font-weight: 600;">Firmy bez danych o składkach</td></tr>
|
||||
{% endif %}
|
||||
<tr{% if not month and not cf.has_data %} style="opacity: 0.5;"{% endif %}>
|
||||
{% if month %}
|
||||
@ -422,9 +423,18 @@
|
||||
{% endif %}
|
||||
</td>
|
||||
{% endfor %}
|
||||
<td style="font-size:11px;white-space:nowrap;">
|
||||
{% if cf.reminder %}
|
||||
{% if cf.reminder.is_read %}
|
||||
<span style="color:var(--success);" title="Odczytano {{ cf.reminder.read_at.strftime('%d.%m %H:%M') if cf.reminder.read_at else '' }}">✓ Odczytano {{ cf.reminder.sent_at.strftime('%d.%m') }}</span>
|
||||
{% else %}
|
||||
<span style="color:var(--text-secondary);" title="Wysłano {{ cf.reminder.sent_at.strftime('%d.%m.%Y %H:%M') }}">✉ Wysłano {{ cf.reminder.sent_at.strftime('%d.%m') }}</span>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if cf.has_data and cf.months.values()|selectattr('status', 'in', ['pending', 'partial', 'overdue'])|list %}
|
||||
<button class="btn btn-small" style="font-size:11px;padding:2px 8px;background:var(--warning);color:white;border:none;" onclick="openReminderModal({{ cf.company.id }}, '{{ cf.company.name|e }}', {{ year }})">Przypomnij</button>
|
||||
<button class="btn btn-small" style="font-size:11px;padding:2px 8px;background:var(--warning);color:white;border:none;" onclick="openReminderModal({{ cf.company.id }}, '{{ cf.company.name|e }}', {{ year }})">{{ 'Ponów' if cf.reminder else 'Przypomnij' }}</button>
|
||||
{% endif %}
|
||||
</td>
|
||||
{% endif %}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user