Phase 115 complete (vertical slice "zamowienie z NIP -> faktura PDF"):
- Task 1: InvoiceRepository + InvoiceService (dual-flow orchestrator) +
InvoiceIssueException + FakturowniaApiClient::createInvoice + buildPdfUrl
- Task 2: InvoiceController + OrdersController::toggleInvoiceRequested +
OrdersRepository::setInvoiceRequested + auto-import invoice_requested z
Allegro (invoice.required) i shopPRO (5-key flexible parser) + show.php
(toggle w zakladce Platnosci + warunkowy przycisk Wystaw fakture)
- Task 3: Lista wystawionych /settings/accounting/invoices/issued z filtrami
+ invoice_preview + invoice_pdf Dompdf template + hub link
- Task 3b (dodany): NIP lookup przez MF Biala Lista (publiczne API, bez
rejestracji) — MfWhitelistApiClient w src/Core/Http/ + /api/nip/lookup +
przycisk "Pobierz z GUS" w formularzu
Auto-fixes podczas smoke testu (5):
- GUS endpoint Fakturowni nie istnial (HTML 404 -> "json is not valid");
switch na MF Biala Liste
- PHP 8.5 curl_close() deprecation wycieka HTML przed JSON; usuniete z
MfWhitelistApiClient i FakturowniaApiClient (3 miejsca)
- Fakturownia 422 payment_to_kind_days (nieistniejace pole) -> usuniete
- Generic "error" w 422 -> parser plaskuje errors: {pole: [...]} +
error_log z 1000 znakow raw body
- Fakturownia security odrzuca seller_*/department_id jako "create new
department"; usuniete z payloadu (Fakturownia uzywa danych konta)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
145 lines
6.6 KiB
PHP
145 lines
6.6 KiB
PHP
<?php
|
|
$invoicesList = is_array($invoices ?? null) ? $invoices : [];
|
|
$configsList = is_array($configs ?? null) ? $configs : [];
|
|
$filtersData = is_array($filters ?? null) ? $filters : [];
|
|
$totalCount = (int) ($total ?? 0);
|
|
$pageNum = (int) ($page ?? 1);
|
|
$totalPagesNum = (int) ($totalPages ?? 1);
|
|
$perPageNum = (int) ($perPage ?? 50);
|
|
?>
|
|
|
|
<section class="card">
|
|
<div class="orders-head">
|
|
<div>
|
|
<a href="/settings/accounting" class="order-back-link">← Ksiegowosc</a>
|
|
<h2 class="section-title mt-12">Wystawione faktury</h2>
|
|
<div class="muted mt-4">Lacznie: <?= $e((string) $totalCount) ?></div>
|
|
</div>
|
|
</div>
|
|
|
|
<form method="get" action="/settings/accounting/invoices/issued" class="mt-12">
|
|
<div class="form-grid-2">
|
|
<div class="form-group">
|
|
<label class="form-label" for="search">Szukaj (numer, zamowienie)</label>
|
|
<input type="text" name="search" id="search" class="form-control" value="<?= $e((string) ($filtersData['search'] ?? '')) ?>">
|
|
</div>
|
|
<div class="form-group">
|
|
<label class="form-label" for="config_id">Konfiguracja</label>
|
|
<select name="config_id" id="config_id" class="form-control">
|
|
<option value="0">Wszystkie</option>
|
|
<?php foreach ($configsList as $cfg): ?>
|
|
<option value="<?= $e((string) ($cfg['id'] ?? '')) ?>" <?= ((int) ($filtersData['config_id'] ?? 0) === (int) ($cfg['id'] ?? 0)) ? 'selected' : '' ?>>
|
|
<?= $e((string) ($cfg['name'] ?? '')) ?>
|
|
</option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</div>
|
|
<div class="form-group">
|
|
<label class="form-label" for="mode">Tryb</label>
|
|
<select name="mode" id="mode" class="form-control">
|
|
<?php $modeVal = (string) ($filtersData['mode'] ?? ''); ?>
|
|
<option value="" <?= $modeVal === '' ? 'selected' : '' ?>>Wszystkie</option>
|
|
<option value="local" <?= $modeVal === 'local' ? 'selected' : '' ?>>Lokalnie</option>
|
|
<option value="delegated" <?= $modeVal === 'delegated' ? 'selected' : '' ?>>Fakturownia</option>
|
|
</select>
|
|
</div>
|
|
<div class="form-group">
|
|
<label class="form-label" for="date_from">Data od</label>
|
|
<input type="date" name="date_from" id="date_from" class="form-control" value="<?= $e((string) ($filtersData['date_from'] ?? '')) ?>">
|
|
</div>
|
|
<div class="form-group">
|
|
<label class="form-label" for="date_to">Data do</label>
|
|
<input type="date" name="date_to" id="date_to" class="form-control" value="<?= $e((string) ($filtersData['date_to'] ?? '')) ?>">
|
|
</div>
|
|
</div>
|
|
<div class="mt-12">
|
|
<button type="submit" class="btn btn--primary">Filtruj</button>
|
|
<a href="/settings/accounting/invoices/issued" class="btn btn--secondary ml-8">Wyczysc</a>
|
|
</div>
|
|
</form>
|
|
|
|
<div class="table-wrap mt-16">
|
|
<table class="table">
|
|
<thead>
|
|
<tr>
|
|
<th>Numer</th>
|
|
<th>Data wystawienia</th>
|
|
<th>Nabywca</th>
|
|
<th>Brutto</th>
|
|
<th>Tryb</th>
|
|
<th>Konfiguracja</th>
|
|
<th>Zamowienie</th>
|
|
<th>Akcje</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php if ($invoicesList === []): ?>
|
|
<tr><td colspan="8" class="muted">Brak faktur w wybranych filtrach</td></tr>
|
|
<?php endif; ?>
|
|
<?php foreach ($invoicesList as $inv): ?>
|
|
<?php
|
|
$buyer = json_decode((string) ($inv['buyer_data_json'] ?? '{}'), true);
|
|
$buyer = is_array($buyer) ? $buyer : [];
|
|
$buyerLabel = trim((string) ($buyer['company_name'] ?? '')) !== ''
|
|
? (string) $buyer['company_name']
|
|
: (string) ($buyer['name'] ?? '-');
|
|
$buyerNip = trim((string) ($buyer['tax_number'] ?? ''));
|
|
$isDelegated = trim((string) ($inv['external_invoice_id'] ?? '')) !== '';
|
|
$issueDate = (string) ($inv['issue_date'] ?? '');
|
|
$orderRef = (int) ($inv['order_id'] ?? 0);
|
|
$orderLabel = trim((string) ($inv['internal_order_number'] ?? '')) !== ''
|
|
? (string) $inv['internal_order_number']
|
|
: ('#' . $orderRef);
|
|
?>
|
|
<tr>
|
|
<td><strong><?= $e((string) ($inv['invoice_number'] ?? '')) ?></strong></td>
|
|
<td class="text-nowrap"><?= $e(strlen($issueDate) >= 16 ? substr($issueDate, 0, 16) : $issueDate) ?></td>
|
|
<td>
|
|
<?= $e($buyerLabel) ?>
|
|
<?php if ($buyerNip !== ''): ?>
|
|
<div class="muted">NIP: <?= $e($buyerNip) ?></div>
|
|
<?php endif; ?>
|
|
</td>
|
|
<td class="text-nowrap"><?= $e(number_format((float) ($inv['total_gross'] ?? 0), 2, '.', ' ')) ?> PLN</td>
|
|
<td>
|
|
<?php if ($isDelegated): ?>
|
|
<span class="badge badge--success">Fakturownia<?php if (trim((string) ($inv['account_prefix'] ?? '')) !== ''): ?>: <?= $e((string) $inv['account_prefix']) ?><?php endif; ?></span>
|
|
<?php else: ?>
|
|
<span class="badge badge--muted">Lokalnie</span>
|
|
<?php endif; ?>
|
|
</td>
|
|
<td><?= $e((string) ($inv['config_name'] ?? '-')) ?></td>
|
|
<td><a href="/orders/<?= $e((string) $orderRef) ?>"><?= $e($orderLabel) ?></a></td>
|
|
<td>
|
|
<a href="/orders/<?= $e((string) $orderRef) ?>/invoice/<?= $e((string) ($inv['id'] ?? '')) ?>" class="btn btn--sm btn--secondary">Podglad</a>
|
|
<?php if ($isDelegated && trim((string) ($inv['external_pdf_url'] ?? '')) !== ''): ?>
|
|
<a href="/orders/<?= $e((string) $orderRef) ?>/invoice/<?= $e((string) ($inv['id'] ?? '')) ?>/pdf" class="btn btn--sm btn--secondary" target="_blank" rel="noopener">PDF</a>
|
|
<?php else: ?>
|
|
<a href="/orders/<?= $e((string) $orderRef) ?>/invoice/<?= $e((string) ($inv['id'] ?? '')) ?>/pdf" class="btn btn--sm btn--secondary">PDF</a>
|
|
<?php endif; ?>
|
|
</td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<?php if ($totalPagesNum > 1): ?>
|
|
<div class="pagination mt-12">
|
|
<?php for ($p = 1; $p <= $totalPagesNum; $p++): ?>
|
|
<?php
|
|
$qs = http_build_query(array_merge(
|
|
$filtersData,
|
|
['page' => $p]
|
|
));
|
|
?>
|
|
<?php if ($p === $pageNum): ?>
|
|
<strong class="pagination__current"><?= $e((string) $p) ?></strong>
|
|
<?php else: ?>
|
|
<a class="pagination__page" href="/settings/accounting/invoices/issued?<?= $e($qs) ?>"><?= $e((string) $p) ?></a>
|
|
<?php endif; ?>
|
|
<?php endfor; ?>
|
|
</div>
|
|
<?php endif; ?>
|
|
</section>
|