zmiana waluty w .env

This commit is contained in:
Mateusz Gruszczyński
2026-04-02 08:25:07 +02:00
parent d07651ad67
commit 4c9d665ae2
20 changed files with 86 additions and 36 deletions

View File

@@ -195,4 +195,10 @@ UPLOADS_CACHE_CONTROL="max-age=3600, immutable"
# UWAGA: wielkość liter w nazwach jest zachowywana, ale porównywanie odbywa się
# bez rozróżniania wielkości liter (case-insensitive).
# Domyślnie: poniższa lista
DEFAULT_CATEGORIES="Spożywcze,Budowlane,Zabawki,Chemia,Inne,Elektronika,Odzież i obuwie,Artykuły biurowe,Kosmetyki i higiena,Motoryzacja,Ogród i rośliny,Zwierzęta,Sprzęt sportowy,Książki i prasa,Narzędzia i majsterkowanie,RTV / AGD,Apteka i suplementy,Artykuły dekoracyjne,Gry i hobby,Usługi,Pieczywo"
DEFAULT_CATEGORIES="Spożywcze,Budowlane,Zabawki,Chemia,Inne,Elektronika,Odzież i obuwie,Artykuły biurowe,Kosmetyki i higiena,Motoryzacja,Ogród i rośliny,Zwierzęta,Sprzęt sportowy,Książki i prasa,Narzędzia i majsterkowanie,RTV / AGD,Apteka i suplementy,Artykuły dekoracyjne,Gry i hobby,Usługi,Pieczywo"
# Waluta używana w całej aplikacji (kwoty, paragony, analizy)
# Użyj kodu ISO 4217 (np. PLN, EUR, USD, GBP)
# Domyślnie: PLN (jeśli zmienna nie jest ustawiona)
CURRENCY_CODE=PLN

View File

@@ -91,6 +91,8 @@ class Config:
DEBUG_MODE = env_bool("DEBUG_MODE", True)
DISABLE_ROBOTS = env_bool("DISABLE_ROBOTS", False)
CURRENCY_CODE = env_str("CURRENCY_CODE", "PLN").strip().upper() or "PLN"
JS_CACHE_CONTROL = env_str("JS_CACHE_CONTROL", "no-cache")
CSS_CACHE_CONTROL = env_str("CSS_CACHE_CONTROL", "no-cache")
LIB_JS_CACHE_CONTROL = env_str("LIB_JS_CACHE_CONTROL", "max-age=604800")

View File

@@ -2,6 +2,25 @@ from .deps import *
from .app_setup import *
from .models import *
def get_currency_code() -> str:
code = str(app.config.get("CURRENCY_CODE", "PLN") or "PLN").strip().upper()
return code or "PLN"
def format_currency(amount, include_code: bool = True) -> str:
try:
normalized = float(amount or 0)
except (TypeError, ValueError):
normalized = 0.0
formatted = f"{normalized:.2f}"
return f"{formatted} {get_currency_code()}" if include_code else formatted
def currency_placeholder(prefix: str = "Kwota") -> str:
return f"{prefix} ({get_currency_code()})"
def get_setting(key: str, default: str | None = None) -> str | None:
s = db.session.get(AppSetting, key)
return s.value if s else default

View File

@@ -453,7 +453,7 @@ def handle_add_expense(data):
)
db.session.add(new_expense)
log_list_activity(list_id, 'expense_added', item_name=None, actor=current_user if current_user.is_authenticated else None, actor_name=current_user.username if current_user.is_authenticated else 'Gość', details=f'kwota: {float(amount):.2f} PLN')
log_list_activity(list_id, 'expense_added', item_name=None, actor=current_user if current_user.is_authenticated else None, actor_name=current_user.username if current_user.is_authenticated else 'Gość', details=f'kwota: {format_currency(amount)}')
db.session.commit()
total = (

View File

@@ -123,7 +123,7 @@ document.addEventListener("DOMContentLoaded", function () {
data: {
labels: data.labels || [],
datasets: [{
label: "Suma wydatków [PLN]",
label: `Suma wydatków [${getCurrencyCode()}]`,
data: data.expenses || [],
}],
},

View File

@@ -28,7 +28,7 @@ document.addEventListener('DOMContentLoaded', () => {
total += parseFloat(cb.dataset.amount);
}
});
totalEl.textContent = total.toFixed(2) + ' PLN';
totalEl.textContent = formatCurrencyAmount(total);
}
function getISOWeek(date) {

View File

@@ -1,3 +1,19 @@
function getCurrencyCode() {
return window.CURRENCY_CODE || 'PLN';
}
function formatCurrencyAmount(amount, options = {}) {
const includeCode = options.includeCode !== false;
const numeric = Number(amount || 0);
const safe = Number.isFinite(numeric) ? numeric : 0;
const formatted = safe.toFixed(2);
return includeCode ? `${formatted} ${getCurrencyCode()}` : formatted;
}
function currencyLabel(prefix = 'Kwota') {
return `${prefix} (${getCurrencyCode()})`;
}
function updateItemState(itemId, isChecked) {
const checkbox = document.querySelector(`#item-${itemId} input[type='checkbox']`);
if (checkbox) {

View File

@@ -113,7 +113,7 @@ function setupList(listId, username) {
socket.on('expense_added', data => {
const badgeEl = document.getElementById('total-expense1');
if (badgeEl) {
badgeEl.innerHTML = `💸 ${data.total.toFixed(2)} PLN`;
badgeEl.innerHTML = `💸 ${formatCurrencyAmount(data.total)}`;
badgeEl.classList.remove('bg-secondary');
badgeEl.classList.add('bg-success');
badgeEl.style.display = '';
@@ -121,10 +121,10 @@ function setupList(listId, username) {
const summaryEl = document.getElementById('total-expense2');
if (summaryEl) {
summaryEl.innerHTML = `<b>💸 Łącznie wydano:</b> ${data.total.toFixed(2)} PLN`;
summaryEl.innerHTML = `<b>💸 Łącznie wydano:</b> ${formatCurrencyAmount(data.total)}`;
}
showToast(`Dodano wydatek: ${data.amount.toFixed(2)} PLN`, 'info');
showToast(`Dodano wydatek: ${formatCurrencyAmount(data.amount)}`, 'info');
});

View File

@@ -99,7 +99,7 @@ document.addEventListener("DOMContentLoaded", function () {
summary.innerHTML = `
<p class="mb-1">📦 <strong>${totalCount}</strong> produktów</p>
<p class="mb-1">✅ Kupione: <strong>${purchasedCount}</strong> (${percent}%)</p>
<p class="mb-0">💸 Wydatek: <strong>${totalExpense.toFixed(2)}</strong></p>`;
<p class="mb-0">💸 Wydatek: <strong>${formatCurrencyAmount(totalExpense)}</strong></p>`;
productList.appendChild(summary);
const purchased = createSection("✔️ Kupione");

View File

@@ -22,7 +22,7 @@ async function analyzeReceipts(listId) {
let html = `<div class="card bg-dark text-white border-secondary p-3">`;
html += `<p class="text-secondary"><small>⏱ Czas analizy OCR: ${duration} sek.</small></p>`;
html += `<p><b>📊 Łącznie wykryto:</b> ${data.total.toFixed(2)} PLN</p>`;
html += `<p><b>📊 Łącznie wykryto:</b> ${formatCurrencyAmount(data.total)}</p>`;
data.results.forEach((r, i) => {
const disabled = r.already_added ? "disabled" : "";

View File

@@ -12,7 +12,7 @@ document.addEventListener('DOMContentLoaded', () => {
total += parseFloat(cb.dataset.amount);
}
});
totalEl.textContent = total.toFixed(2) + ' PLN';
totalEl.textContent = formatCurrencyAmount(total);
}
selectAllBtn.addEventListener('click', () => {

View File

@@ -27,7 +27,7 @@
<span class="progress-label main-list-progress__label small fw-bold {% if percent < 51 %}text-white{% else %}text-dark{% endif %}">
Produkty: {{ purchased_count }}/{{ total_count }} ({{ percent|round(0)|int }}%)
{% if total_expense > 0 %} — 💸 {{ '%.2f'|format(total_expense) }} PLN{% endif %}
{% if total_expense > 0 %} — 💸 {{ format_currency(total_expense) }}{% endif %}
</span>
</div>
</div>

View File

@@ -51,7 +51,7 @@
</tr>
<tr>
<td>💸 Średnia kwota na listę</td>
<td class="text-end fw-bold">{{ avg_list_expense }}</td>
<td class="text-end fw-bold">{{ format_currency(avg_list_expense) }}</td>
</tr>
</tbody>
</table>
@@ -115,30 +115,30 @@
<tbody>
<tr>
<td>Wszystkie</td>
<td>{{ '%.2f'|format(expense_summary.all.month) }} PLN</td>
<td>{{ '%.2f'|format(expense_summary.all.year) }} PLN</td>
<td>{{ '%.2f'|format(expense_summary.all.total) }} PLN</td>
<td>{{ format_currency(expense_summary.all.month) }}</td>
<td>{{ format_currency(expense_summary.all.year) }}</td>
<td>{{ format_currency(expense_summary.all.total) }}</td>
<!-- <td>{{ '%.2f'|format(expense_summary.all.avg) }} PLN</td> -->
</tr>
<tr>
<td>Aktywne</td>
<td>{{ '%.2f'|format(expense_summary.active.month) }} PLN</td>
<td>{{ '%.2f'|format(expense_summary.active.year) }} PLN</td>
<td>{{ '%.2f'|format(expense_summary.active.total) }} PLN</td>
<td>{{ format_currency(expense_summary.active.month) }}</td>
<td>{{ format_currency(expense_summary.active.year) }}</td>
<td>{{ format_currency(expense_summary.active.total) }}</td>
<!-- <td>{{ '%.2f'|format(expense_summary.active.avg) }} PLN</td> -->
</tr>
<tr>
<td>Archiwalne</td>
<td>{{ '%.2f'|format(expense_summary.archived.month) }} PLN</td>
<td>{{ '%.2f'|format(expense_summary.archived.year) }} PLN</td>
<td>{{ '%.2f'|format(expense_summary.archived.total) }} PLN</td>
<td>{{ format_currency(expense_summary.archived.month) }}</td>
<td>{{ format_currency(expense_summary.archived.year) }}</td>
<td>{{ format_currency(expense_summary.archived.total) }}</td>
<!-- <td>{{ '%.2f'|format(expense_summary.archived.avg) }} PLN</td> -->
</tr>
<tr>
<td>Wygasłe</td>
<td>{{ '%.2f'|format(expense_summary.expired.month) }} PLN</td>
<td>{{ '%.2f'|format(expense_summary.expired.year) }} PLN</td>
<td>{{ '%.2f'|format(expense_summary.expired.total) }} PLN</td>
<td>{{ format_currency(expense_summary.expired.month) }}</td>
<td>{{ format_currency(expense_summary.expired.year) }}</td>
<td>{{ format_currency(expense_summary.expired.total) }}</td>
<!-- <td>{{ '%.2f'|format(expense_summary.expired.avg) }} PLN</td> -->
</tr>
</tbody>
@@ -282,7 +282,7 @@
{% if e.total_expense >= 500 %}text-danger
{% elif e.total_expense > 0 %}text-success{% endif %}">
{% if e.total_expense > 0 %}
{{ '%.2f'|format(e.total_expense) }} PLN
{{ format_currency(e.total_expense) }}
{% else %}
-
{% endif %}

View File

@@ -25,7 +25,7 @@
<!-- Wydatek i właściciel -->
<div class="row mb-3">
<div class="col-md-6">
<label for="amount" class="form-label">💰 Całkowity wydatek (PLN)</label>
<label for="amount" class="form-label">💰 Całkowity wydatek ({{ CURRENCY_CODE }})</label>
<input type="number" step="0.01" min="0" class="form-control bg-dark text-white border-secondary ui-consistent-input"
id="amount" name="amount" value="{{ '%.2f'|format(total_expense) }}">
</div>

View File

@@ -173,6 +173,10 @@
});
</script>
<script>
window.CURRENCY_CODE = {{ CURRENCY_CODE|tojson }};
</script>
{% if request.endpoint != 'system_auth' %}
<script src="{{ static_asset_url('static_bp.serve_js_lib', 'glightbox.min.js') }}"></script>
<script src="{{ static_asset_url('static_bp.serve_js_lib', 'socket.io.min.js') }}"></script>

View File

@@ -88,7 +88,7 @@
<button id="deselectAllBtn" class="btn btn-sm btn-outline-light active" style="display: none;">Odznacz
wszystko</button>
</div>
<h5 class="text-success m-0">💰 Suma: <span id="listsTotal">0.00 PLN</span></h5>
<h5 class="text-success m-0">💰 Suma: <span id="listsTotal">{{ format_currency(0) }}</span></h5>
</div>
<!-- Tabela list z możliwością filtrowania -->
@@ -101,7 +101,7 @@
<th>Nazwa listy</th>
<th>Właściciel</th>
<th>Data</th>
<th>Wydatki (PLN)</th>
<th>Wydatki ({{ CURRENCY_CODE }})</th>
</tr>
</thead>
<tbody id="listsTableBody">

View File

@@ -96,11 +96,11 @@
<br>
{% if total_expense > 0 %}
<div id="total-expense2" class="text-success fw-bold mb-3">
💸 Łącznie wydano: {{ '%.2f'|format(total_expense) }} PLN
💸 Łącznie wydano: {{ format_currency(total_expense) }}
</div>
{% else %}
<div id="total-expense2" class="text-success fw-bold mb-3">
💸 Łącznie wydano: 0.00 PLN
💸 Łącznie wydano: {{ format_currency(0) }}
</div>
{% endif %}

View File

@@ -12,11 +12,11 @@
{% if total_expense > 0 %}
<span id="total-expense1" class="badge rounded-pill bg-success ms-2">
💸 {{ '%.2f'|format(total_expense) }} PLN
💸 {{ format_currency(total_expense) }}
</span>
{% else %}
<span id="total-expense" class="badge rounded-pill bg-secondary ms-2" style="display: none;">
💸 0.00 PLN
💸 {{ format_currency(0) }}
</span>
{% endif %}
@@ -114,7 +114,7 @@
<span>💰 Dodaj wydatek</span>
<span class="badge rounded-pill bg-success" id="total-expense2">
💸 Łączna suma: {{ '%.2f'|format(total_expense) }} PLN
💸 Łączna suma: {{ format_currency(total_expense) }}
</span>
</div>
@@ -123,7 +123,7 @@
<div class="input-group mb-0 shopping-compact-input-group shopping-expense-input-group">
<input id="expenseAmount" type="number" step="0.01" min="0"
class="form-control bg-dark text-white border-secondary shopping-expense-amount-input"
placeholder="Kwota (PLN)">
placeholder="{{ currency_placeholder() }}">
<button onclick="submitExpense({{ list.id }})"
class="btn btn-outline-primary share-submit-btn share-submit-btn--expense shopping-compact-submit">
@@ -135,7 +135,7 @@
{% endif %}
<p id="total-expense2" style="display: none;">
<b>💸 Łącznie wydano:</b> {{ '%.2f'|format(total_expense) }} PLN
<b>💸 Łącznie wydano:</b> {{ format_currency(total_expense) }}
</p>
<button id="toggleReceiptBtn" type="button" class="receipt-disclosure mb-3"

View File

@@ -101,7 +101,7 @@
</div>
<div class="main-summary-stat">
<span class="main-summary-stat__label">Wydatki</span>
<strong>{{ '%.2f'|format(summary.total_expense) }} PLN</strong>
<strong>{{ format_currency(summary.total_expense) }}</strong>
</div>
</div>
</div>

View File

@@ -26,6 +26,9 @@ def inject_version():
return {
"APP_VERSION": app.config["APP_VERSION"],
"CURRENCY_CODE": get_currency_code(),
"format_currency": format_currency,
"currency_placeholder": currency_placeholder,
"static_asset_url": static_asset_url,
}