Commit 72d9ec28 authored by DevPilot's avatar DevPilot

fix(ui): buttons that led nowhere, across the financial screens

Swept every link and form action in the financial modules against the real
route patterns. The asset problem was not a one-off.

**Screens you could reach but not use.** Three edit screens existed, worked, and
had nothing linking to them: vendor invoices, return-to-vendor, and the legacy
pricing configs. Buttons added on both the list and the detail page, gated on
the same status the controller already enforces — draft only, since neither
document should change once verified or submitted.

**Links pointing at routes that do not exist.**

  - Asset custody was entirely unusable: both the transfer button and the
    transfer form posted to /inventory/assets/{id}/transfer, but the route is
    /inventory/assets/custody/{id}/transfer. Nobody could ever hand over an
    asset.
  - Pricing configs was broken at both ends — the list linked to
    /pricing/{id}/edit and the form posted to /pricing/{id}, while the routes
    are under /pricing/configs. The edit screen was unreachable and unsavable.
  - Quote comparison posted to /select-winner, which was never built; the
    endpoint is /procurement/quotes/evaluate.
  - The quotes list "عرض" pointed at a detail page that does not exist. It now
    opens the response screen, which is what a quote is actually for.
  - "تظلم" on a fine was an <a>, so it issued a GET against a POST-only route.
    It is a form now, with a confirmation, since it records something.

**Buttons for things that were never built.** BOM edit had no route and no
controller method — a guaranteed 404 in two places. Removed rather than faked;
creating and viewing a BOM both work, and editing one is a feature nobody has
written yet. Settlements had exactly one action and it opened a detail page that
does not exist either; replaced with اعتماد, the action that does exist and the
only thing a draft settlement is waiting on.

Not changed, having checked: vouchers and budgets flagged in the sweep were
artifacts of my own parser — PHP unescapes '\\d+' in single quotes, and the
budgets links emit a query string from inside the PHP tag. Both resolve fine.

Verified: 1503 routes resolve, 255 controllers instantiate, 243 services load,
zero orphaned edit screens remain, and every screen touched renders.
Co-Authored-By: 's avatarClaude Opus 5 <noreply@anthropic.com>
parent 39ee2678
...@@ -54,7 +54,17 @@ ...@@ -54,7 +54,17 @@
<td><?= e($s['description'] ?? '—') ?></td> <td><?= e($s['description'] ?? '—') ?></td>
<td style="direction:ltr;text-align:right;font-weight:600;"><?= money($s['amount'] ?? 0) ?></td> <td style="direction:ltr;text-align:right;font-weight:600;"><?= money($s['amount'] ?? 0) ?></td>
<td><span style="color:<?= $statusColor ?>;font-weight:600;"><?= $statusLabel ?></span></td> <td><span style="color:<?= $statusColor ?>;font-weight:600;"><?= $statusLabel ?></span></td>
<td><a href="/accounting/settlements/<?= (int)$s['id'] ?>" class="btn btn-sm btn-outline">عرض</a></td> <td>
<?php if (($s['status'] ?? '') === 'draft' && can('accounting.settlements.approve')): ?>
<form method="POST" action="/accounting/settlements/<?= (int)$s['id'] ?>/approve" style="display:inline;"
onsubmit="return confirm('هيتم اعتماد التسوية دي وترحيل قيدها. متأكد؟');">
<?= csrf_field() ?>
<button type="submit" class="btn btn-sm btn-primary">اعتماد</button>
</form>
<?php else: ?>
<span style="color:#9CA3AF;"></span>
<?php endif; ?>
</td>
</tr> </tr>
<?php endforeach; ?> <?php endforeach; ?>
<?php if (empty($settlements)): ?> <?php if (empty($settlements)): ?>
......
...@@ -26,7 +26,11 @@ ...@@ -26,7 +26,11 @@
</form> </form>
<?php endif; ?> <?php endif; ?>
<?php if ($r['status'] === 'imposed' && !$r['appeal_submitted']): ?> <?php if ($r['status'] === 'imposed' && !$r['appeal_submitted']): ?>
<a href="/fines/<?= (int) $r['id'] ?>/appeal" class="btn btn-sm btn-outline">تظلم</a> <form method="POST" action="/fines/<?= (int) $r['id'] ?>/appeal" style="display:inline;"
onsubmit="return confirm('هيتسجّل تظلم على الغرامة دي. متأكد؟');">
<?= csrf_field() ?>
<button type="submit" class="btn btn-sm btn-outline">تظلم</button>
</form>
<?php endif; ?> <?php endif; ?>
<?php if ($r['status'] === 'appealed' && can('fine.waive')): ?> <?php if ($r['status'] === 'appealed' && can('fine.waive')): ?>
<form method="POST" action="/fines/<?= (int) $r['id'] ?>/appeal-decide" style="display:flex;gap:3px;"> <form method="POST" action="/fines/<?= (int) $r['id'] ?>/appeal-decide" style="display:flex;gap:3px;">
......
...@@ -48,7 +48,7 @@ ...@@ -48,7 +48,7 @@
<td><?= e($asset['custody_date'] ?? '—') ?></td> <td><?= e($asset['custody_date'] ?? '—') ?></td>
<td> <td>
<?php if (can('asset.manage')): ?> <?php if (can('asset.manage')): ?>
<a href="/inventory/assets/<?= (int) $asset['id'] ?>/transfer" class="btn btn-sm btn-primary" style="font-size:12px;"> <a href="/inventory/assets/custody/<?= (int) $asset['id'] ?>/transfer" class="btn btn-sm btn-primary" style="font-size:12px;">
<i data-lucide="arrow-left-right" style="width:13px;height:13px;vertical-align:middle;margin-left:3px;"></i> نقل العهدة <i data-lucide="arrow-left-right" style="width:13px;height:13px;vertical-align:middle;margin-left:3px;"></i> نقل العهدة
</a> </a>
<?php endif; ?> <?php endif; ?>
......
...@@ -36,7 +36,7 @@ ...@@ -36,7 +36,7 @@
</div> </div>
<!-- Transfer Form --> <!-- Transfer Form -->
<form method="POST" action="/inventory/assets/<?= (int) $asset['id'] ?>/transfer" id="transferForm"> <form method="POST" action="/inventory/assets/custody/<?= (int) $asset['id'] ?>/transfer" id="transferForm">
<?= csrf_field() ?> <?= csrf_field() ?>
<div class="card" style="margin-bottom:20px;"> <div class="card" style="margin-bottom:20px;">
......
...@@ -46,9 +46,6 @@ ...@@ -46,9 +46,6 @@
<a href="/inventory/bom/<?= (int) $bom['id'] ?>" class="btn btn-sm btn-outline" style="font-size:12px;"> <a href="/inventory/bom/<?= (int) $bom['id'] ?>" class="btn btn-sm btn-outline" style="font-size:12px;">
<i data-lucide="eye" style="width:13px;height:13px;vertical-align:middle;margin-left:3px;"></i> عرض <i data-lucide="eye" style="width:13px;height:13px;vertical-align:middle;margin-left:3px;"></i> عرض
</a> </a>
<a href="/inventory/bom/<?= (int) $bom['id'] ?>/edit" class="btn btn-sm btn-outline" style="font-size:12px;">
<i data-lucide="edit-3" style="width:13px;height:13px;vertical-align:middle;margin-left:3px;"></i> تعديل
</a>
</div> </div>
</td> </td>
</tr> </tr>
......
...@@ -3,9 +3,6 @@ ...@@ -3,9 +3,6 @@
<?php $__template->section('page_actions'); ?> <?php $__template->section('page_actions'); ?>
<a href="/inventory/bom" class="btn btn-outline"><i data-lucide="arrow-right" style="width:15px;height:15px;vertical-align:middle;margin-left:4px;"></i> العودة للقائمة</a> <a href="/inventory/bom" class="btn btn-outline"><i data-lucide="arrow-right" style="width:15px;height:15px;vertical-align:middle;margin-left:4px;"></i> العودة للقائمة</a>
<?php if (can('inventory.manage')): ?>
<a href="/inventory/bom/<?= (int) $bom['id'] ?>/edit" class="btn btn-primary"><i data-lucide="edit-3" style="width:15px;height:15px;vertical-align:middle;margin-left:4px;"></i> تعديل</a>
<?php endif; ?>
<?php $__template->endSection(); ?> <?php $__template->endSection(); ?>
<?php $__template->section('content'); ?> <?php $__template->section('content'); ?>
......
<?php $__template->layout('Layout.main'); ?> <?php $__template->layout('Layout.main'); ?>
<?php $__template->section('title'); ?>تعديل التسعير<?php $__template->endSection(); ?> <?php $__template->section('title'); ?>تعديل التسعير<?php $__template->endSection(); ?>
<?php $__template->section('content'); ?> <?php $__template->section('content'); ?>
<form method="POST" action="/pricing/<?= (int) $config->id ?>"> <form method="POST" action="/pricing/configs/<?= (int) $config->id ?>">
<?= csrf_field() ?> <?= csrf_field() ?>
<div class="card" style="padding:20px;"> <div class="card" style="padding:20px;">
<div style="display:grid;grid-template-columns:1fr 1fr;gap:20px;"> <div style="display:grid;grid-template-columns:1fr 1fr;gap:20px;">
...@@ -24,6 +24,6 @@ ...@@ -24,6 +24,6 @@
</div> </div>
</div> </div>
<button type="submit" class="btn btn-primary" style="margin-top:20px;">حفظ</button> <button type="submit" class="btn btn-primary" style="margin-top:20px;">حفظ</button>
<a href="/pricing" class="btn btn-outline" style="margin-top:20px;">إلغاء</a> <a href="/pricing/configs" class="btn btn-outline" style="margin-top:20px;">إلغاء</a>
</form> </form>
<?php $__template->endSection(); ?> <?php $__template->endSection(); ?>
\ No newline at end of file
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
<td style="font-weight:700;direction:ltr;text-align:right;"><?= money($c['price']) ?></td> <td style="font-weight:700;direction:ltr;text-align:right;"><?= money($c['price']) ?></td>
<td style="font-size:12px;"><?= e($c['effective_from']) ?></td> <td style="font-size:12px;"><?= e($c['effective_from']) ?></td>
<td style="font-size:12px;"><?= e($c['effective_to'] ?? '—') ?></td> <td style="font-size:12px;"><?= e($c['effective_to'] ?? '—') ?></td>
<td><?php if (can('pricing.edit')): ?><a href="/pricing/<?= (int) $c['id'] ?>/edit" class="btn btn-sm btn-outline">تعديل</a><?php endif; ?></td> <td><?php if (can('pricing.edit')): ?><a href="/pricing/configs/<?= (int) $c['id'] ?>/edit" class="btn btn-sm btn-outline">تعديل</a><?php endif; ?></td>
</tr> </tr>
<?php endforeach; ?> <?php endforeach; ?>
<?php if (empty($configs)): ?> <?php if (empty($configs)): ?>
......
...@@ -108,10 +108,15 @@ $matchBgs = ['unmatched' => '#F3F4F6', 'matched' => '#ECFDF5', 'discrepancy' => ...@@ -108,10 +108,15 @@ $matchBgs = ['unmatched' => '#F3F4F6', 'matched' => '#ECFDF5', 'discrepancy' =>
</td> </td>
<td style="font-weight:700;direction:ltr;text-align:left;"><?= money($inv['total_amount'] ?? 0) ?></td> <td style="font-weight:700;direction:ltr;text-align:left;"><?= money($inv['total_amount'] ?? 0) ?></td>
<td style="font-size:12px;"><?= e($inv['due_date'] ?? '—') ?></td> <td style="font-size:12px;"><?= e($inv['due_date'] ?? '—') ?></td>
<td> <td style="white-space:nowrap;">
<a href="/procurement/invoices/<?= (int) $inv['id'] ?>" class="btn btn-sm btn-outline" style="font-size:12px;padding:4px 10px;"> <a href="/procurement/invoices/<?= (int) $inv['id'] ?>" class="btn btn-sm btn-outline" style="font-size:12px;padding:4px 10px;">
<i data-lucide="eye" style="width:13px;height:13px;vertical-align:middle;"></i> عرض <i data-lucide="eye" style="width:13px;height:13px;vertical-align:middle;"></i> عرض
</a> </a>
<?php if (($inv['status'] ?? '') === 'draft' && can('procurement.invoice.create')): ?>
<a href="/procurement/invoices/<?= (int) $inv['id'] ?>/edit" class="btn btn-sm btn-outline" style="font-size:12px;padding:4px 10px;">
<i data-lucide="pencil" style="width:13px;height:13px;vertical-align:middle;"></i> تعديل
</a>
<?php endif; ?>
</td> </td>
</tr> </tr>
<?php endforeach; ?> <?php endforeach; ?>
......
...@@ -4,6 +4,9 @@ ...@@ -4,6 +4,9 @@
<?php $__template->section('page_actions'); ?> <?php $__template->section('page_actions'); ?>
<?php if ($invoice['status'] === 'draft'): ?> <?php if ($invoice['status'] === 'draft'): ?>
<?php if (can('procurement.invoice.create')): ?> <?php if (can('procurement.invoice.create')): ?>
<a href="/procurement/invoices/<?= (int) $invoice['id'] ?>/edit" class="btn btn-outline">
<i data-lucide="pencil" style="width:15px;height:15px;vertical-align:middle;margin-left:4px;"></i> تعديل
</a>
<form method="POST" action="/procurement/invoices/<?= (int) $invoice['id'] ?>/verify" style="display:inline;"> <form method="POST" action="/procurement/invoices/<?= (int) $invoice['id'] ?>/verify" style="display:inline;">
<?= csrf_field() ?> <?= csrf_field() ?>
<button type="submit" class="btn" style="background:#D97706;color:#fff;border:none;"> <button type="submit" class="btn" style="background:#D97706;color:#fff;border:none;">
......
...@@ -88,7 +88,8 @@ $suppliers = $comparison['suppliers'] ?? []; ...@@ -88,7 +88,8 @@ $suppliers = $comparison['suppliers'] ?? [];
<!-- Winner Selection Form --> <!-- Winner Selection Form -->
<div class="card" style="padding:20px;"> <div class="card" style="padding:20px;">
<h3 style="margin:0 0 15px;font-size:15px;"><i data-lucide="award" style="width:18px;height:18px;vertical-align:middle;margin-left:6px;color:#D97706;"></i> اختيار العرض الفائز</h3> <h3 style="margin:0 0 15px;font-size:15px;"><i data-lucide="award" style="width:18px;height:18px;vertical-align:middle;margin-left:6px;color:#D97706;"></i> اختيار العرض الفائز</h3>
<form method="POST" action="/procurement/quotes/<?= (int) ($requisition['id'] ?? 0) ?>/select-winner"> <form method="POST" action="/procurement/quotes/evaluate">
<input type="hidden" name="requisition_id" value="<?= (int) ($requisition['id'] ?? 0) ?>">
<?= csrf_field() ?> <?= csrf_field() ?>
<div style="margin-bottom:15px;"> <div style="margin-bottom:15px;">
<label class="form-label">المورد الفائز</label> <label class="form-label">المورد الفائز</label>
......
...@@ -73,8 +73,8 @@ $statusLabels = [ ...@@ -73,8 +73,8 @@ $statusLabels = [
</span> </span>
</td> </td>
<td> <td>
<a href="/procurement/quotes/<?= (int) $q['id'] ?>" class="btn btn-sm btn-outline" style="font-size:12px;padding:4px 10px;"> <a href="/procurement/quotes/<?= (int) $q['id'] ?>/response" class="btn btn-sm btn-outline" style="font-size:12px;padding:4px 10px;">
<i data-lucide="eye" style="width:13px;height:13px;vertical-align:middle;"></i> عرض <i data-lucide="eye" style="width:13px;height:13px;vertical-align:middle;"></i> عرض / تسجيل الرد
</a> </a>
</td> </td>
</tr> </tr>
......
...@@ -47,7 +47,12 @@ $statusBgs = ['draft' => '#F3F4F6', 'submitted' => '#FFF7ED', 'approved' => '#F0 ...@@ -47,7 +47,12 @@ $statusBgs = ['draft' => '#F3F4F6', 'submitted' => '#FFF7ED', 'approved' => '#F0
<td><span style="display:inline-block;padding:3px 10px;border-radius:10px;font-size:12px;font-weight:600;background:<?= $statusBgs[$st] ?? '#F3F4F6' ?>;color:<?= $statusColors[$st] ?? '#6B7280' ?>;"><?= e($statuses[$st] ?? $st) ?></span></td> <td><span style="display:inline-block;padding:3px 10px;border-radius:10px;font-size:12px;font-weight:600;background:<?= $statusBgs[$st] ?? '#F3F4F6' ?>;color:<?= $statusColors[$st] ?? '#6B7280' ?>;"><?= e($statuses[$st] ?? $st) ?></span></td>
<td style="font-weight:700;direction:ltr;text-align:left;"><?= money($r['total_amount'] ?? 0) ?></td> <td style="font-weight:700;direction:ltr;text-align:left;"><?= money($r['total_amount'] ?? 0) ?></td>
<td style="font-size:12px;"><?= e($r['return_date'] ?? '') ?></td> <td style="font-size:12px;"><?= e($r['return_date'] ?? '') ?></td>
<td><a href="/procurement/rtv/<?= (int) $r['id'] ?>" class="btn btn-sm btn-outline" style="font-size:12px;padding:4px 10px;"><i data-lucide="eye" style="width:13px;height:13px;vertical-align:middle;"></i> عرض</a></td> <td style="white-space:nowrap;">
<a href="/procurement/rtv/<?= (int) $r['id'] ?>" class="btn btn-sm btn-outline" style="font-size:12px;padding:4px 10px;"><i data-lucide="eye" style="width:13px;height:13px;vertical-align:middle;"></i> عرض</a>
<?php if ($st === 'draft' && can('procurement.rtv.create')): ?>
<a href="/procurement/rtv/<?= (int) $r['id'] ?>/edit" class="btn btn-sm btn-outline" style="font-size:12px;padding:4px 10px;"><i data-lucide="pencil" style="width:13px;height:13px;vertical-align:middle;"></i> تعديل</a>
<?php endif; ?>
</td>
</tr> </tr>
<?php endforeach; ?> <?php endforeach; ?>
</tbody> </tbody>
......
...@@ -3,6 +3,11 @@ ...@@ -3,6 +3,11 @@
<?php $__template->section('page_actions'); ?> <?php $__template->section('page_actions'); ?>
<?php if ($rtv['status'] === 'draft'): ?> <?php if ($rtv['status'] === 'draft'): ?>
<?php if (can('procurement.rtv.create')): ?>
<a href="/procurement/rtv/<?= (int) $rtv['id'] ?>/edit" class="btn btn-outline">
<i data-lucide="pencil" style="width:15px;height:15px;vertical-align:middle;margin-left:4px;"></i> تعديل
</a>
<?php endif; ?>
<form method="POST" action="/procurement/rtv/<?= (int) $rtv['id'] ?>/submit" style="display:inline;"><?= csrf_field() ?><button type="submit" class="btn" style="background:#D97706;color:#fff;border:none;"><i data-lucide="send" style="width:15px;height:15px;vertical-align:middle;margin-left:4px;"></i> تقديم</button></form> <form method="POST" action="/procurement/rtv/<?= (int) $rtv['id'] ?>/submit" style="display:inline;"><?= csrf_field() ?><button type="submit" class="btn" style="background:#D97706;color:#fff;border:none;"><i data-lucide="send" style="width:15px;height:15px;vertical-align:middle;margin-left:4px;"></i> تقديم</button></form>
<?php endif; ?> <?php endif; ?>
<?php if ($rtv['status'] === 'submitted'): ?> <?php if ($rtv['status'] === 'submitted'): ?>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment