Phase 08 — DB Foundation: - 3 new tables: receipt_configs, receipts, receipt_number_counters - company_settings extended with BDO, REGON, KRS, logo fields Phase 09 — Receipt Config: - CRUD for receipt configurations (Settings > Accounting) - ReceiptConfigController + ReceiptConfigRepository Phase 10 — Receipt Issuing: - ReceiptRepository with atomic numbering (INSERT ON DUPLICATE KEY UPDATE) - ReceiptController with snapshot pattern (seller/buyer/items as JSON) - "Wystaw paragon" button in order view - Documents tab showing both receipts and marketplace documents - Activity log entry on receipt creation Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
159 lines
8.8 KiB
PHP
159 lines
8.8 KiB
PHP
<?php
|
|
$configs = is_array($configs ?? null) ? $configs : [];
|
|
$ec = is_array($editConfig ?? null) ? $editConfig : null;
|
|
$isEdit = $ec !== null;
|
|
?>
|
|
|
|
<section class="card">
|
|
<h2 class="section-title"><?= $e($t('settings.accounting.title')) ?></h2>
|
|
<p class="muted mt-12"><?= $e($t('settings.accounting.description')) ?></p>
|
|
|
|
<?php if (!empty($errorMessage)): ?>
|
|
<div class="alert alert--danger mt-12" role="alert"><?= $e((string) $errorMessage) ?></div>
|
|
<?php endif; ?>
|
|
<?php if (!empty($successMessage)): ?>
|
|
<div class="alert alert--success mt-12" role="status"><?= $e((string) $successMessage) ?></div>
|
|
<?php endif; ?>
|
|
</section>
|
|
|
|
<section class="card mt-16">
|
|
<h3 class="section-title"><?= $e($t('settings.accounting.table.heading')) ?></h3>
|
|
|
|
<?php if (count($configs) === 0): ?>
|
|
<p class="muted mt-12"><?= $e($t('settings.accounting.table.empty')) ?></p>
|
|
<?php else: ?>
|
|
<div class="table-wrap mt-12">
|
|
<table class="table">
|
|
<thead>
|
|
<tr>
|
|
<th><?= $e($t('settings.accounting.table.name')) ?></th>
|
|
<th><?= $e($t('settings.accounting.table.number_format')) ?></th>
|
|
<th><?= $e($t('settings.accounting.table.numbering_type')) ?></th>
|
|
<th><?= $e($t('settings.accounting.table.status')) ?></th>
|
|
<th><?= $e($t('settings.accounting.table.actions')) ?></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ($configs as $cfg): ?>
|
|
<tr>
|
|
<td><?= $e((string) ($cfg['name'] ?? '')) ?></td>
|
|
<td><code><?= $e((string) ($cfg['number_format'] ?? '')) ?></code></td>
|
|
<td><?= $e($t('settings.accounting.options.numbering_type.' . ($cfg['numbering_type'] ?? 'monthly'))) ?></td>
|
|
<td>
|
|
<?php if (((int) ($cfg['is_active'] ?? 0)) === 1): ?>
|
|
<span class="badge badge--success"><?= $e($t('settings.accounting.options.active')) ?></span>
|
|
<?php else: ?>
|
|
<span class="badge badge--muted"><?= $e($t('settings.accounting.options.inactive')) ?></span>
|
|
<?php endif; ?>
|
|
</td>
|
|
<td style="white-space:nowrap">
|
|
<a href="/settings/accounting?edit=<?= (int) ($cfg['id'] ?? 0) ?>" class="btn btn--sm btn--secondary"><?= $e($t('settings.accounting.actions.edit')) ?></a>
|
|
<form action="/settings/accounting/toggle" method="post" style="display:inline">
|
|
<input type="hidden" name="_token" value="<?= $e($csrfToken ?? '') ?>">
|
|
<input type="hidden" name="id" value="<?= (int) ($cfg['id'] ?? 0) ?>">
|
|
<button type="submit" class="btn btn--sm btn--secondary">
|
|
<?= ((int) ($cfg['is_active'] ?? 0)) === 1 ? $e($t('settings.accounting.actions.deactivate')) : $e($t('settings.accounting.actions.activate')) ?>
|
|
</button>
|
|
</form>
|
|
<form action="/settings/accounting/delete" method="post" style="display:inline" class="js-confirm-delete">
|
|
<input type="hidden" name="_token" value="<?= $e($csrfToken ?? '') ?>">
|
|
<input type="hidden" name="id" value="<?= (int) ($cfg['id'] ?? 0) ?>">
|
|
<button type="button" class="btn btn--sm btn--danger js-delete-btn"><?= $e($t('settings.accounting.actions.delete')) ?></button>
|
|
</form>
|
|
</td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<?php endif; ?>
|
|
</section>
|
|
|
|
<section class="card mt-16">
|
|
<h3 class="section-title"><?= $isEdit ? $e($t('settings.accounting.form.edit_heading')) : $e($t('settings.accounting.form.add_heading')) ?></h3>
|
|
|
|
<form action="/settings/accounting/save" method="post" novalidate class="mt-12">
|
|
<input type="hidden" name="_token" value="<?= $e($csrfToken ?? '') ?>">
|
|
<?php if ($isEdit): ?>
|
|
<input type="hidden" name="id" value="<?= (int) ($ec['id'] ?? 0) ?>">
|
|
<?php endif; ?>
|
|
|
|
<div class="form-grid-2">
|
|
<label class="form-field">
|
|
<span class="field-label"><?= $e($t('settings.accounting.fields.name')) ?> *</span>
|
|
<input class="form-control" type="text" name="name" maxlength="128" required value="<?= $e((string) ($ec['name'] ?? '')) ?>">
|
|
</label>
|
|
<label class="form-field">
|
|
<span class="field-label"><?= $e($t('settings.accounting.fields.number_format')) ?> *</span>
|
|
<input class="form-control" type="text" name="number_format" maxlength="64" required placeholder="PAR/%N/%M/%Y" value="<?= $e((string) ($ec['number_format'] ?? 'PAR/%N/%M/%Y')) ?>">
|
|
<small class="field-hint"><?= $e($t('settings.accounting.fields.number_format_hint')) ?></small>
|
|
</label>
|
|
</div>
|
|
|
|
<div class="form-grid-3 mt-0">
|
|
<label class="form-field">
|
|
<span class="field-label"><?= $e($t('settings.accounting.fields.numbering_type')) ?></span>
|
|
<select class="form-control" name="numbering_type">
|
|
<option value="monthly"<?= ((string) ($ec['numbering_type'] ?? 'monthly')) === 'monthly' ? ' selected' : '' ?>><?= $e($t('settings.accounting.options.numbering_type.monthly')) ?></option>
|
|
<option value="yearly"<?= ((string) ($ec['numbering_type'] ?? '')) === 'yearly' ? ' selected' : '' ?>><?= $e($t('settings.accounting.options.numbering_type.yearly')) ?></option>
|
|
</select>
|
|
</label>
|
|
<label class="form-field">
|
|
<span class="field-label"><?= $e($t('settings.accounting.fields.sale_date_source')) ?></span>
|
|
<select class="form-control" name="sale_date_source">
|
|
<option value="issue_date"<?= ((string) ($ec['sale_date_source'] ?? 'issue_date')) === 'issue_date' ? ' selected' : '' ?>><?= $e($t('settings.accounting.options.sale_date_source.issue_date')) ?></option>
|
|
<option value="order_date"<?= ((string) ($ec['sale_date_source'] ?? '')) === 'order_date' ? ' selected' : '' ?>><?= $e($t('settings.accounting.options.sale_date_source.order_date')) ?></option>
|
|
<option value="payment_date"<?= ((string) ($ec['sale_date_source'] ?? '')) === 'payment_date' ? ' selected' : '' ?>><?= $e($t('settings.accounting.options.sale_date_source.payment_date')) ?></option>
|
|
</select>
|
|
</label>
|
|
<label class="form-field">
|
|
<span class="field-label"><?= $e($t('settings.accounting.fields.order_reference')) ?></span>
|
|
<select class="form-control" name="order_reference">
|
|
<option value="none"<?= ((string) ($ec['order_reference'] ?? 'none')) === 'none' ? ' selected' : '' ?>><?= $e($t('settings.accounting.options.order_reference.none')) ?></option>
|
|
<option value="orderpro"<?= ((string) ($ec['order_reference'] ?? '')) === 'orderpro' ? ' selected' : '' ?>><?= $e($t('settings.accounting.options.order_reference.orderpro')) ?></option>
|
|
<option value="integration"<?= ((string) ($ec['order_reference'] ?? '')) === 'integration' ? ' selected' : '' ?>><?= $e($t('settings.accounting.options.order_reference.integration')) ?></option>
|
|
</select>
|
|
</label>
|
|
</div>
|
|
|
|
<div class="form-grid-2 mt-0">
|
|
<label class="form-field" style="display:flex;align-items:center;gap:6px;flex-direction:row">
|
|
<input type="checkbox" name="is_named" value="1"<?= ((int) ($ec['is_named'] ?? 0)) === 1 ? ' checked' : '' ?>>
|
|
<span class="field-label" style="margin:0"><?= $e($t('settings.accounting.fields.is_named')) ?></span>
|
|
</label>
|
|
<label class="form-field" style="display:flex;align-items:center;gap:6px;flex-direction:row">
|
|
<input type="checkbox" name="is_active" value="1"<?= $isEdit ? (((int) ($ec['is_active'] ?? 0)) === 1 ? ' checked' : '') : ' checked' ?>>
|
|
<span class="field-label" style="margin:0"><?= $e($t('settings.accounting.fields.is_active')) ?></span>
|
|
</label>
|
|
</div>
|
|
|
|
<div class="form-actions mt-16">
|
|
<button type="submit" class="btn btn--primary"><?= $isEdit ? $e($t('settings.accounting.actions.save_edit')) : $e($t('settings.accounting.actions.save_new')) ?></button>
|
|
<?php if ($isEdit): ?>
|
|
<a href="/settings/accounting" class="btn btn--secondary"><?= $e($t('settings.accounting.actions.cancel')) ?></a>
|
|
<?php endif; ?>
|
|
</div>
|
|
</form>
|
|
</section>
|
|
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
document.querySelectorAll('.js-delete-btn').forEach(function(btn) {
|
|
btn.addEventListener('click', function() {
|
|
var form = this.closest('form');
|
|
if (window.OrderProAlerts && window.OrderProAlerts.confirm) {
|
|
window.OrderProAlerts.confirm(
|
|
'<?= $e($t('settings.accounting.confirm.delete_title')) ?>',
|
|
'<?= $e($t('settings.accounting.confirm.delete_message')) ?>',
|
|
function() { form.submit(); }
|
|
);
|
|
} else {
|
|
if (confirm('<?= $e($t('settings.accounting.confirm.delete_message')) ?>')) {
|
|
form.submit();
|
|
}
|
|
}
|
|
});
|
|
});
|
|
});
|
|
</script>
|