zapamietanie akcji

This commit is contained in:
Mateusz Gruszczyński
2026-07-19 19:15:21 +02:00
parent 659f04f05f
commit 697ac6da30
11 changed files with 221 additions and 86 deletions
+1 -1
View File
@@ -9,7 +9,7 @@
<div class="col-12"><label class="form-label">Województwo dla LPG</label><select class="form-select" name="region" required>{% for region in regions %}<option value="{{region}}" {% if settings.region==region %}selected{% endif %}>{{region}}</option>{% endfor %}</select></div><div class="col-12"><button class="btn btn-primary">Zapisz ustawienia</button></div></form></div></div></div>
<div class="col-xl-6"><div class="card"><div class="card-body"><h2 class="h5">Dodaj użytkownika</h2><form method="post" action="/api/users" class="row g-3 ajax-form"><div class="col-md-6"><label class="form-label">Imię i nazwisko</label><input class="form-control" name="user_name" required></div><div class="col-md-6"><label class="form-label">E-mail</label><input class="form-control" type="email" name="email" required></div><div class="col-md-6"><label class="form-label">Hasło</label><input class="form-control" type="password" name="password" minlength="8" required></div><div class="col-md-6"><label class="form-label">Rola</label><select class="form-select" name="role"><option value="user">User</option><option value="boss">Szef</option><option value="admin">Admin</option></select></div><div class="col-12"><button class="btn btn-primary">Dodaj użytkownika</button></div></form></div></div></div></div>
<div class="row g-4 mt-1">
<div class="col-xl-5"><div class="card"><div class="card-body"><h2 class="h5">Ustawienia aplikacji</h2><form action="/api/app-settings" data-method="PUT" class="ajax-form row g-3"><div class="col-12"><label class="form-label">Motyw aplikacji</label><select class="form-select" name="theme">{% for key,item in themes.items() %}<option value="{{key}}" {% if app_theme_name==key %}selected{% endif %}>{{item.label}}</option>{% endfor %}</select></div><div class="col-12"><button class="btn btn-primary">Zapisz ustawienia aplikacji</button></div></form></div></div></div>
<div class="col-xl-5"><div class="card"><div class="card-body"><h2 class="h5">Ustawienia aplikacji</h2><form action="/api/app-settings" data-method="PUT" class="ajax-form row g-3"><div class="col-12"><label class="form-label">Motyw aplikacji</label><select class="form-select" name="theme">{% for key,item in themes.items() %}<option value="{{key}}" {% if app_theme_name==key %}selected{% endif %}>{{item.label}}</option>{% endfor %}</select><div class="form-text">Wybrany motyw jest ustawiany globalnie dla wszystkich użytkowników aplikacji.</div></div><div class="col-12"><button class="btn btn-primary">Zapisz ustawienia aplikacji</button></div></form></div></div></div>
<div class="col-xl-7"><div class="card"><div class="card-body"><h2 class="h5">Karty paliwowe firmy</h2><form action="/api/fuel-cards" class="ajax-form row g-2 mb-3"><div class="col-md-4"><input class="form-control" name="name" placeholder="Nazwa, np. UTA Polska" required></div><div class="col-md-3"><input class="form-control" name="provider" placeholder="Operator" required></div><div class="col-md-3"><input class="form-control" name="description" placeholder="Opis"></div><div class="col-md-2"><button class="btn btn-primary w-100">Dodaj</button></div></form><div class="list-group">{% for card in fuel_cards %}<div class="list-group-item d-flex justify-content-between align-items-center"><div><strong>{{card.name}}</strong><div class="small text-body-secondary">{{card.provider}}{% if card.description %} · {{card.description}}{% endif %}</div></div><span class="badge text-bg-{{'success' if card.active else 'secondary'}}">{{'aktywna' if card.active else 'nieaktywna'}}</span></div>{% else %}<div class="text-body-secondary">Brak kart paliwowych.</div>{% endfor %}</div></div></div></div>
</div>
{% if current_user.role=='admin' %}<div class="card mt-4"><div class="card-body"><div class="d-flex flex-column flex-md-row justify-content-between gap-3 mb-3"><div><h2 class="h5 mb-1">Użytkownicy</h2><small class="text-body-secondary">{{ users_page.total }} kont</small></div><form method="get" action="{{url_for('main.admin')}}" class="d-flex gap-2 ajax-nav-form"><input class="form-control" name="q" value="{{q}}" placeholder="Szukaj po nazwie lub e-mailu"><button class="btn btn-secondary">Szukaj</button></form></div><div class="table-responsive"><table class="table table-hover align-middle"><thead><tr><th>Nazwa</th><th>E-mail</th><th>Rola</th><th>Status</th><th class="text-end">Akcja</th></tr></thead><tbody>{% for u in users_page.items %}<tr><td>{{u.name}}</td><td>{{u.email}}</td><td><span class="badge text-bg-secondary">{{u.role}}</span></td><td>{% if u.active %}<span class="badge text-bg-success">Aktywny</span>{% else %}<span class="badge text-bg-danger">Nieaktywny</span>{% endif %}</td><td class="text-end"><button type="button" class="btn btn-sm btn-primary user-edit-btn" data-bs-toggle="modal" data-bs-target="#userEditModal" data-id="{{u.id}}" data-name="{{u.name|e}}" data-email="{{u.email|e}}" data-role="{{u.role}}" data-active="{{1 if u.active else 0}}" data-card="{{u.fuel_card_id or ''}}">Edytuj</button></td></tr>{% else %}<tr><td colspan="5" class="text-center text-body-secondary py-4">Brak użytkowników.</td></tr>{% endfor %}</tbody></table></div>{% if users_page.pages > 1 %}<nav><ul class="pagination mb-0">{% for p in users_page.iter_pages() %}{% if p %}<li class="page-item {% if p==users_page.page %}active{% endif %}"><a class="page-link ajax-nav-link" href="{{url_for('main.admin',page=p,q=q)}}">{{p}}</a></li>{% else %}<li class="page-item disabled"><span class="page-link"></span></li>{% endif %}{% endfor %}</ul></nav>{% endif %}</div></div>
+1 -1
View File
@@ -1,4 +1,4 @@
{% extends 'base.html' %}{% block title %}Ustawienia aplikacji{% endblock %}{% block content %}
<h1 class="h2 mb-3">Administracja</h1>{% include '_admin_nav.html' %}
<div class="card"><div class="card-body"><h2 class="h5">Wygląd aplikacji</h2><form action="/api/app-settings" data-method="PUT" class="ajax-form row g-3"><div class="col-md-6"><label class="form-label">Motyw Bootstrap</label><select class="form-select" name="theme">{% for key,t in themes.items() %}<option value="{{key}}" {% if key==app_theme_name %}selected{% endif %}>{{t.label}}</option>{% endfor %}</select></div><div class="col-12"><button class="btn btn-primary">Zapisz ustawienia aplikacji</button></div></form></div></div>
<div class="card"><div class="card-body"><h2 class="h5">Wygląd aplikacji</h2><form action="/api/app-settings" data-method="PUT" class="ajax-form row g-3"><div class="col-md-6"><label class="form-label">Motyw Bootstrap</label><select class="form-select" name="theme">{% for key,t in themes.items() %}<option value="{{key}}" {% if key==app_theme_name %}selected{% endif %}>{{t.label}}</option>{% endfor %}</select><div class="form-text">Wybrany motyw jest ustawiany globalnie dla wszystkich użytkowników aplikacji.</div></div><div class="col-12"><button class="btn btn-primary">Zapisz ustawienia aplikacji</button></div></form></div></div>
{% endblock %}
+13 -1
View File
@@ -9,7 +9,7 @@
<div class="col-lg-2 d-flex align-items-end"><button class="btn btn-primary w-100">Filtruj</button></div>
</form>
<div class="table-responsive"><table class="table table-hover align-middle"><thead><tr><th>Data</th><th>Pojazd</th><th>Użytkownik</th><th>Stacja</th><th>Litry</th><th>Cena</th><th>Licznik</th><th class="text-end">Akcja</th></tr></thead><tbody>
{% for e in entries_page.items %}<tr><td>{{e.fueled_at.strftime('%d.%m.%Y %H:%M')}}</td><td><strong>{{e.vehicle.name}}</strong><div class="small text-body-secondary">{{e.vehicle.registration}}</div></td><td>{{e.user.name}}</td><td>{{e.station or '—'}}</td><td>{{e.liters}}</td><td>{{e.price_per_liter}} zł/l</td><td>{{e.odometer}} km</td><td class="text-end"><button type="button" class="btn btn-sm btn-primary fuel-entry-edit-btn" data-bs-toggle="modal" data-bs-target="#fuelEntryEditModal" data-entry='{{ {"id":e.id,"vehicle_id":e.vehicle_id,"fueled_at":e.fueled_at.strftime("%Y-%m-%dT%H:%M"),"fuel_type":e.fuel_type,"liters":e.liters|string,"price_per_liter":e.price_per_liter|string,"odometer":e.odometer,"station_company_id":e.station_company_id or "","station":e.station or "","invoice_number":e.invoice_number or "","used_fuel_card":e.used_fuel_card,"fuel_card_id":e.fuel_card_id or "","wholesale_price":e.wholesale_price|string if e.wholesale_price is not none else "","wholesale_source":e.wholesale_source or ""}|tojson|forceescape }}'>Edytuj</button></td></tr>
{% for e in entries_page.items %}<tr><td>{{e.fueled_at.strftime('%d.%m.%Y %H:%M')}}</td><td><strong>{{e.vehicle.name}}</strong><div class="small text-body-secondary">{{e.vehicle.registration}}</div></td><td>{{e.user.name}}</td><td>{{e.station or '—'}}</td><td>{{e.liters}}</td><td>{{e.price_per_liter}} zł/l</td><td>{{e.odometer}} km</td><td class="text-end"><button type="button" class="btn btn-sm btn-primary fuel-entry-edit-btn" data-bs-toggle="modal" data-bs-target="#fuelEntryEditModal" data-entry='{{ {"id":e.id,"vehicle_id":e.vehicle_id,"fueled_at":e.fueled_at.strftime("%Y-%m-%dT%H:%M"),"fuel_type":e.fuel_type,"liters":e.liters|string,"price_per_liter":e.price_per_liter|string,"odometer":e.odometer,"station_company_id":e.station_company_id or "","station":e.station or "","invoice_number":e.invoice_number or "","used_fuel_card":e.used_fuel_card,"fuel_card_id":e.fuel_card_id or "","wholesale_price":e.wholesale_price|string if e.wholesale_price is not none else "","wholesale_source":e.wholesale_source or "","vat_action_applied":e.vat_action_applied,"vat_action_name":e.vat_action_name or "","vat_action_rate":e.vat_action_rate|string if e.vat_action_rate is not none else "","vat_action_start":e.vat_action_start.isoformat() if e.vat_action_start else "","vat_action_end":e.vat_action_end.isoformat() if e.vat_action_end else "","snapshot_vat_rate":e.snapshot_vat_rate|string if e.snapshot_vat_rate is not none else "","snapshot_vat_deduction_percent":e.snapshot_vat_deduction_percent|string if e.snapshot_vat_deduction_percent is not none else "","snapshot_uses_last_price":e.snapshot_uses_last_price,"snapshot_discount_percent":e.snapshot_discount_percent|string if e.snapshot_discount_percent is not none else "0","snapshot_surcharge_per_liter":e.snapshot_surcharge_per_liter|string if e.snapshot_surcharge_per_liter is not none else "0","snapshot_rule_source":e.snapshot_rule_source or "","settlement_migration_note":e.settlement_migration_note or ""}|tojson|forceescape }}'>Edytuj</button></td></tr>
{% else %}<tr><td colspan="8" class="text-center text-body-secondary py-4">Brak tankowań spełniających kryteria.</td></tr>{% endfor %}</tbody></table></div>
{% if entries_page.pages > 1 %}<nav><ul class="pagination mb-0">{% for p in entries_page.iter_pages() %}{% if p %}<li class="page-item {% if p==entries_page.page %}active{% endif %}"><a class="page-link ajax-nav-link" href="{{url_for('main.admin_fuel_entries',page=p,q=q,month=month,company_id=company_id)}}">{{p}}</a></li>{% else %}<li class="page-item disabled"><span class="page-link"></span></li>{% endif %}{% endfor %}</ul></nav>{% endif %}
</div></div>
@@ -24,5 +24,17 @@
<div class="col-md-6"><label class="form-label">Nazwa stacji</label><input class="form-control" name="station"></div><div class="col-md-6"><label class="form-label">Numer faktury</label><input class="form-control" name="invoice_number"></div>
<div class="col-md-6"><label class="form-label">Karta paliwowa</label><select class="form-select" name="fuel_card_id"><option value="">Brak</option>{% for c in fuel_cards %}<option value="{{c.id}}">{{c.name}} · {{c.provider}}</option>{% endfor %}</select><div class="form-check mt-2"><input class="form-check-input" type="checkbox" name="used_fuel_card" id="edit-used-card"><label class="form-check-label" for="edit-used-card">Użyto karty paliwowej</label></div></div>
<div class="col-md-3"><label class="form-label">Cena hurtowa</label><input class="form-control" type="number" step="0.0001" min="0" name="wholesale_price"></div><div class="col-md-3"><label class="form-label">Źródło ceny</label><input class="form-control" name="wholesale_source"></div>
<div class="col-12"><hr class="my-1"><div class="form-check"><input class="form-check-input" type="checkbox" name="vat_action_applied" id="edit-vat-action-applied"><label class="form-check-label fw-semibold" for="edit-vat-action-applied">Tankowanie objęte akcją</label></div><div class="form-text">Warunki są zapisywane wyłącznie dla tego tankowania i nie zmieniają ustawień globalnych.</div></div>
<div class="col-md-6 vat-action-field"><label class="form-label">Nazwa akcji</label><input class="form-control" name="vat_action_name"></div>
<div class="col-md-2 vat-action-field"><label class="form-label">Stawka VAT (%)</label><input class="form-control" type="number" step="0.001" min="0" max="100" name="vat_action_rate"></div>
<div class="col-md-2 vat-action-field"><label class="form-label">Od</label><input class="form-control" type="date" name="vat_action_start"></div>
<div class="col-md-2 vat-action-field"><label class="form-label">Do</label><input class="form-control" type="date" name="vat_action_end"></div>
<div class="col-12"><hr class="my-1"><h3 class="h6 mb-1">Warunki rozliczenia tego tankowania</h3><div class="form-text">Zmiana warunków automatycznie przeliczy i zapisze wszystkie kwoty historyczne. Nie zmienia ustawień firmy ani karty.</div><div class="alert alert-warning py-2 mt-2 mb-0 d-none" id="settlement-migration-warning"></div></div>
<div class="col-md-3"><label class="form-label">VAT (%)</label><input class="form-control" type="number" step="0.001" min="0" max="100" name="snapshot_vat_rate" required></div>
<div class="col-md-3"><label class="form-label">Odliczenie VAT (%)</label><input class="form-control" type="number" step="0.001" min="0" max="100" name="snapshot_vat_deduction_percent" required></div>
<div class="col-md-3"><label class="form-label">Rabat netto (%)</label><input class="form-control" type="number" step="0.001" min="0" max="100" name="snapshot_discount_percent" required></div>
<div class="col-md-3"><label class="form-label">Dopłata netto / l</label><input class="form-control" type="number" step="0.0001" name="snapshot_surcharge_per_liter" required></div>
<div class="col-md-6"><div class="form-check mt-4"><input class="form-check-input" type="checkbox" name="snapshot_uses_last_price" id="edit-snapshot-last-price"><label class="form-check-label" for="edit-snapshot-last-price">Użyj zapisanej ceny hurtowej jako Last Price</label></div></div>
<div class="col-md-6"><label class="form-label">Źródło / opis reguły</label><input class="form-control" name="snapshot_rule_source" maxlength="160"></div>
</div></div><div class="modal-footer"><button type="button" class="btn btn-danger me-auto" id="fuel-entry-delete-btn">Usuń tankowanie</button><button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Anuluj</button><button class="btn btn-primary">Zapisz zmiany</button></div></form></div></div></div>
{% endblock %}