Commit e670eba1 authored by Mahmoud Aglan's avatar Mahmoud Aglan

fixewsss

parent 7e6c0d93
......@@ -119,14 +119,24 @@ final class QueryBuilder
{
$clone = clone $this;
$dir = strtoupper($dir) === 'DESC' ? 'DESC' : 'ASC';
$clone->orderBys[] = "`{$col}` {$dir}";
if (str_contains($col, '.')) {
[$tbl, $c] = explode('.', $col, 2);
$clone->orderBys[] = "`{$tbl}`.`{$c}` {$dir}";
} else {
$clone->orderBys[] = "`{$col}` {$dir}";
}
return $clone;
}
public function groupBy(string $col): self
{
$clone = clone $this;
$clone->groupBys[] = "`{$col}`";
if (str_contains($col, '.')) {
[$tbl, $c] = explode('.', $col, 2);
$clone->groupBys[] = "`{$tbl}`.`{$c}`";
} else {
$clone->groupBys[] = "`{$col}`";
}
return $clone;
}
......
......@@ -57,25 +57,23 @@ class PurchaseOrderController extends Controller
'notes' => trim((string) $request->post('notes', '')) ?: null,
];
$itemIds = $request->post('item_ids', []);
$quantities = $request->post('quantities', []);
$unitPrices = $request->post('unit_prices', []);
$itemNotes = $request->post('item_notes', []);
$rawItems = $request->post('items', []);
if (!is_array($itemIds) || empty($itemIds)) {
if (!is_array($rawItems) || empty($rawItems)) {
return $this->redirect('/inventory/purchase-orders/create')->withError('يجب إضافة صنف واحد على الأقل');
}
$items = [];
foreach ($itemIds as $i => $itemId) {
$qty = $quantities[$i] ?? '0';
$price = $unitPrices[$i] ?? '0';
if ((int) $itemId > 0 && bccomp((string) $qty, '0', 3) > 0) {
foreach ($rawItems as $raw) {
$itemId = (int) ($raw['item_id'] ?? 0);
$qty = (string) ($raw['quantity_ordered'] ?? '0');
$price = (string) ($raw['unit_price'] ?? '0');
if ($itemId > 0 && bccomp($qty, '0', 3) > 0) {
$items[] = [
'item_id' => (int) $itemId,
'quantity_ordered' => (string) $qty,
'unit_price' => (string) $price,
'notes' => $itemNotes[$i] ?? null,
'item_id' => $itemId,
'quantity_ordered' => $qty,
'unit_price' => $price,
'notes' => $raw['notes'] ?? null,
];
}
}
......@@ -90,20 +88,24 @@ class PurchaseOrderController extends Controller
public function show(Request $request, string $id): Response
{
$po = PurchaseOrder::find((int) $id);
if (!$po) {
$db = App::getInstance()->db();
$order = $db->selectOne(
"SELECT po.*, s.`name_ar` as supplier_name, w.`name_ar` as warehouse_name
FROM `purchase_orders` po
JOIN `suppliers` s ON s.`id` = po.`supplier_id`
JOIN `warehouses` w ON w.`id` = po.`warehouse_id`
WHERE po.`id` = ?",
[(int) $id]
);
if (!$order) {
return $this->redirect('/inventory/purchase-orders')->withError('أمر الشراء غير موجود');
}
$items = PurchaseOrderItem::getForPO((int) $id);
$db = App::getInstance()->db();
$supplier = $db->selectOne("SELECT `name_ar`, `code`, `phone`, `email` FROM `suppliers` WHERE `id` = ?", [(int) $po->supplier_id]);
return $this->view('Inventory.Views.purchase_orders.show', [
'po' => $po,
'order' => $order,
'items' => $items,
'supplier' => $supplier,
'statuses' => PurchaseOrder::getStatuses(),
]);
}
......@@ -130,19 +132,27 @@ class PurchaseOrderController extends Controller
public function receiveForm(Request $request, string $id): Response
{
$po = PurchaseOrder::find((int) $id);
if (!$po) {
$db = App::getInstance()->db();
$order = $db->selectOne(
"SELECT po.*, s.`name_ar` as supplier_name, w.`name_ar` as warehouse_name
FROM `purchase_orders` po
JOIN `suppliers` s ON s.`id` = po.`supplier_id`
JOIN `warehouses` w ON w.`id` = po.`warehouse_id`
WHERE po.`id` = ?",
[(int) $id]
);
if (!$order) {
return $this->redirect('/inventory/purchase-orders')->withError('أمر الشراء غير موجود');
}
if (!in_array($po->status, ['approved', 'partially_received'], true)) {
if (!in_array($order['status'], ['approved', 'partially_received'], true)) {
return $this->redirect('/inventory/purchase-orders/' . $id)->withError('أمر الشراء ليس في حالة تسمح بالاستلام');
}
$items = PurchaseOrderItem::getForPO((int) $id);
return $this->view('Inventory.Views.purchase_orders.receive', [
'po' => $po,
'order' => $order,
'items' => $items,
]);
}
......
......@@ -127,7 +127,7 @@ class SupplierController extends Controller
'contact_person' => trim((string) $request->post('contact_person', '')) ?: null,
'phone' => trim((string) $request->post('phone', '')) ?: null,
'email' => trim((string) $request->post('email', '')) ?: null,
'address_ar' => trim((string) $request->post('address_ar', '')) ?: null,
'address' => trim((string) $request->post('address', '')) ?: null,
'tax_number' => trim((string) $request->post('tax_number', '')) ?: null,
'payment_terms' => trim((string) $request->post('payment_terms', '')) ?: null,
'rating' => ((int) $request->post('rating', 0)) ?: null,
......
......@@ -12,7 +12,7 @@ class AssetRegister extends Model
protected static string $table = 'asset_register';
protected static string $primaryKey = 'id';
protected static bool $timestamps = true;
protected static bool $softDelete = false;
protected static bool $softDelete = true;
protected static bool $autoTrackAuthor = true;
protected static array $fillable = [
......
......@@ -12,7 +12,7 @@ class PurchaseOrder extends Model
protected static string $table = 'purchase_orders';
protected static string $primaryKey = 'id';
protected static bool $timestamps = true;
protected static bool $softDelete = false;
protected static bool $softDelete = true;
protected static bool $autoTrackAuthor = true;
protected static array $fillable = [
......@@ -20,14 +20,18 @@ class PurchaseOrder extends Model
'supplier_id',
'warehouse_id',
'status',
'total_amount',
'order_date',
'expected_delivery',
'subtotal',
'tax_amount',
'grand_total',
'ordered_by',
'discount_amount',
'total_amount',
'currency',
'payment_terms',
'submitted_by',
'submitted_at',
'approved_by',
'approved_at',
'expected_delivery_date',
'received_at',
'notes',
];
......
......@@ -15,12 +15,12 @@ class PurchaseOrderItem extends Model
protected static bool $autoTrackAuthor = false;
protected static array $fillable = [
'po_id',
'purchase_order_id',
'item_id',
'quantity_ordered',
'quantity_received',
'unit_price',
'total_price',
'unit_cost',
'line_total',
'notes',
];
......@@ -34,7 +34,7 @@ class PurchaseOrderItem extends Model
"SELECT poi.*, i.`name_ar` as item_name, i.`sku`, i.`unit_of_measure`
FROM `purchase_order_items` poi
JOIN `inventory_items` i ON i.`id` = poi.`item_id`
WHERE poi.`po_id` = ?
WHERE poi.`purchase_order_id` = ?
ORDER BY i.`name_ar` ASC",
[$poId]
);
......
......@@ -12,7 +12,7 @@ class StockAudit extends Model
protected static string $table = 'stock_audits';
protected static string $primaryKey = 'id';
protected static bool $timestamps = true;
protected static bool $softDelete = false;
protected static bool $softDelete = true;
protected static bool $autoTrackAuthor = true;
protected static array $fillable = [
......
......@@ -12,7 +12,7 @@ class StockTransfer extends Model
protected static string $table = 'stock_transfers';
protected static string $primaryKey = 'id';
protected static bool $timestamps = true;
protected static bool $softDelete = false;
protected static bool $softDelete = true;
protected static bool $autoTrackAuthor = true;
protected static array $fillable = [
......
......@@ -22,7 +22,7 @@ class Supplier extends Model
'contact_person',
'phone',
'email',
'address_ar',
'address',
'tax_number',
'payment_terms',
'rating',
......
......@@ -55,19 +55,21 @@ final class PurchaseOrderService
$db->beginTransaction();
try {
$poId = $db->insert('purchase_orders', [
'po_number' => $poNumber,
'supplier_id' => $supplierId,
'warehouse_id' => $warehouseId,
'status' => 'draft',
'total_amount' => $totalAmount,
'tax_amount' => $taxAmount,
'grand_total' => $grandTotal,
'ordered_by' => $employee ? (int) $employee->id : null,
'expected_delivery_date' => $header['expected_delivery_date'] ?? null,
'notes' => $header['notes'] ?? null,
'created_by' => $employee ? (int) $employee->id : null,
'created_at' => date('Y-m-d H:i:s'),
'updated_at' => date('Y-m-d H:i:s'),
'po_number' => $poNumber,
'supplier_id' => $supplierId,
'warehouse_id' => $warehouseId,
'status' => 'draft',
'order_date' => date('Y-m-d'),
'expected_delivery' => $header['expected_delivery_date'] ?? null,
'subtotal' => $totalAmount,
'tax_amount' => $taxAmount,
'discount_amount' => '0.00',
'total_amount' => $grandTotal,
'submitted_by' => $employee ? (int) $employee->id : null,
'notes' => $header['notes'] ?? null,
'created_by' => $employee ? (int) $employee->id : null,
'created_at' => date('Y-m-d H:i:s'),
'updated_at' => date('Y-m-d H:i:s'),
]);
foreach ($items as $item) {
......@@ -76,13 +78,13 @@ final class PurchaseOrderService
$lineTotal = bcmul($qty, $price, 2);
$db->insert('purchase_order_items', [
'po_id' => $poId,
'item_id' => (int) $item['item_id'],
'quantity_ordered' => $qty,
'quantity_received' => '0',
'unit_price' => $price,
'total_price' => $lineTotal,
'notes' => $item['notes'] ?? null,
'purchase_order_id' => $poId,
'item_id' => (int) $item['item_id'],
'quantity_ordered' => $qty,
'quantity_received' => '0',
'unit_cost' => $price,
'line_total' => $lineTotal,
'notes' => $item['notes'] ?? null,
]);
}
......@@ -180,7 +182,7 @@ final class PurchaseOrderService
"SELECT poi.*, i.`tracking_type`
FROM `purchase_order_items` poi
JOIN `inventory_items` i ON i.`id` = poi.`item_id`
WHERE poi.`id` = ? AND poi.`po_id` = ?",
WHERE poi.`id` = ? AND poi.`purchase_order_id` = ?",
[$poItemId, $poId]
);
if (!$poItem) {
......@@ -202,7 +204,7 @@ final class PurchaseOrderService
'batch_number' => $received['batch_number'],
'expiry_date' => $received['expiry_date'],
'quantity' => $qtyReceived,
'unit_cost' => (string) $poItem['unit_price'],
'unit_cost' => (string) $poItem['unit_cost'],
'received_date' => date('Y-m-d'),
]);
}
......@@ -213,7 +215,7 @@ final class PurchaseOrderService
'movement_type' => 'purchase_in',
'direction' => 'in',
'quantity' => $qtyReceived,
'unit_cost' => (string) $poItem['unit_price'],
'unit_cost' => (string) $poItem['unit_cost'],
'batch_id' => $batchId,
'reference_type' => 'purchase_orders',
'reference_id' => $poId,
......@@ -223,7 +225,7 @@ final class PurchaseOrderService
// Determine new PO status
$allItems = $db->select(
"SELECT `quantity_ordered`, `quantity_received` FROM `purchase_order_items` WHERE `po_id` = ?",
"SELECT `quantity_ordered`, `quantity_received` FROM `purchase_order_items` WHERE `purchase_order_id` = ?",
[$poId]
);
......@@ -236,15 +238,10 @@ final class PurchaseOrderService
}
$newStatus = $allFullyReceived ? 'received' : 'partially_received';
$updateData = [
$db->update('purchase_orders', [
'status' => $newStatus,
'updated_at' => date('Y-m-d H:i:s'),
];
if ($newStatus === 'received') {
$updateData['received_at'] = date('Y-m-d H:i:s');
}
$db->update('purchase_orders', $updateData, '`id` = ?', [$poId]);
], '`id` = ?', [$poId]);
$db->commit();
} catch (\Throwable $e) {
......
......@@ -77,7 +77,7 @@ final class StockAuditService
throw $e;
}
Logger::info("Audit #{$auditId} ({$auditNumber}) created: {$auditType} for warehouse #{$warehouseId}, {$stockItems} items");
Logger::info("Audit #{$auditId} ({$auditNumber}) created: {$auditType} for warehouse #{$warehouseId}, " . count($stockItems) . " items");
return $auditId;
}
......
......@@ -102,7 +102,7 @@ $statusBgs = [
<?= e($stLabel) ?>
</span>
</td>
<td style="font-weight:700;direction:ltr;text-align:left;"><?= money($o['grand_total'] ?? 0) ?></td>
<td style="font-weight:700;direction:ltr;text-align:left;"><?= money($o['total_amount'] ?? 0) ?></td>
<td style="font-size:12px;"><?= e(substr($o['created_at'] ?? '', 0, 10)) ?></td>
<td>
<a href="/inventory/purchase-orders/<?= (int) $o['id'] ?>" class="btn btn-sm btn-outline" style="font-size:12px;padding:4px 10px;">
......
<?php $__template->layout('Layout.main'); ?>
<?php $__template->section('title'); ?>استلام أمر شراء <?= e($order->po_number) ?><?php $__template->endSection(); ?>
<?php $__template->section('title'); ?>استلام أمر شراء <?= e($order['po_number']) ?><?php $__template->endSection(); ?>
<?php $__template->section('page_actions'); ?>
<a href="/inventory/purchase-orders/<?= (int) $order->id ?>" 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/purchase-orders/<?= (int) $order['id'] ?>" class="btn btn-outline"><i data-lucide="arrow-right" style="width:15px;height:15px;vertical-align:middle;margin-left:4px;"></i> العودة لأمر الشراء</a>
<?php $__template->endSection(); ?>
<?php $__template->section('content'); ?>
......@@ -18,27 +18,27 @@
<div style="padding:12px;background:#F9FAFB;border-radius:8px;">
<div style="font-size:11px;color:#6B7280;">رقم الأمر</div>
<div style="font-weight:700;font-size:14px;">
<code style="font-size:12px;background:#F3F4F6;padding:2px 8px;border-radius:4px;"><?= e($order->po_number) ?></code>
<code style="font-size:12px;background:#F3F4F6;padding:2px 8px;border-radius:4px;"><?= e($order['po_number']) ?></code>
</div>
</div>
<div style="padding:12px;background:#F9FAFB;border-radius:8px;">
<div style="font-size:11px;color:#6B7280;">المورد</div>
<div style="font-weight:700;font-size:14px;"><?= e($order->supplier_name) ?></div>
<div style="font-weight:700;font-size:14px;"><?= e($order['supplier_name'] ?? '') ?></div>
</div>
<div style="padding:12px;background:#F9FAFB;border-radius:8px;">
<div style="font-size:11px;color:#6B7280;">المستودع</div>
<div style="font-weight:700;font-size:14px;"><?= e($order->warehouse_name) ?></div>
<div style="font-weight:700;font-size:14px;"><?= e($order['warehouse_name'] ?? '') ?></div>
</div>
<div style="padding:12px;background:#F0FDF4;border-radius:8px;">
<div style="font-size:11px;color:#6B7280;">الإجمالي</div>
<div style="font-weight:700;font-size:14px;color:#059669;direction:ltr;text-align:left;"><?= money($order->grand_total ?? 0) ?></div>
<div style="font-weight:700;font-size:14px;color:#059669;direction:ltr;text-align:left;"><?= money($order['total_amount'] ?? 0) ?></div>
</div>
</div>
</div>
</div>
<!-- Receive Form -->
<form method="POST" action="/inventory/purchase-orders/<?= (int) $order->id ?>/receive">
<form method="POST" action="/inventory/purchase-orders/<?= (int) $order['id'] ?>/receive">
<?= csrf_field() ?>
<div class="card" style="margin-bottom:20px;">
......@@ -81,7 +81,7 @@
<code style="font-size:10px;background:#F3F4F6;padding:1px 4px;border-radius:3px;"><?= e($item['sku']) ?></code>
</div>
<?php endif; ?>
<input type="hidden" name="items[<?= $idx ?>][po_item_id]" value="<?= (int) ($item['id'] ?? 0) ?>">
<input type="hidden" name="po_item_ids[]" value="<?= (int) ($item['id'] ?? 0) ?>">
</td>
<td style="font-weight:600;direction:ltr;text-align:left;"><?= number_format($qtyOrdered) ?></td>
<td style="direction:ltr;text-align:left;color:#2563EB;font-weight:600;"><?= number_format($qtyReceived) ?></td>
......@@ -94,7 +94,7 @@
</td>
<td>
<input type="number"
name="items[<?= $idx ?>][quantity_received]"
name="quantities_received[]"
class="form-input"
min="0"
max="<?= $remaining ?>"
......@@ -105,7 +105,7 @@
</td>
<td>
<input type="text"
name="items[<?= $idx ?>][batch_number]"
name="batch_numbers[]"
class="form-input"
placeholder="رقم الدفعة"
style="direction:ltr;text-align:left;"
......@@ -113,7 +113,7 @@
</td>
<td>
<input type="date"
name="items[<?= $idx ?>][expiry_date]"
name="expiry_dates[]"
class="form-input"
<?= $isFullyReceived ? 'disabled' : '' ?>>
</td>
......@@ -130,7 +130,7 @@
<i data-lucide="package-check" style="width:16px;height:16px;vertical-align:middle;margin-left:4px;"></i>
تأكيد الاستلام
</button>
<a href="/inventory/purchase-orders/<?= (int) $order->id ?>" class="btn btn-outline" style="padding:12px 30px;font-size:15px;">إلغاء</a>
<a href="/inventory/purchase-orders/<?= (int) $order['id'] ?>" class="btn btn-outline" style="padding:12px 30px;font-size:15px;">إلغاء</a>
</div>
</form>
......
<?php $__template->layout('Layout.main'); ?>
<?php $__template->section('title'); ?>أمر شراء <?= e($order->po_number) ?><?php $__template->endSection(); ?>
<?php $__template->section('title'); ?>أمر شراء <?= e($order['po_number']) ?><?php $__template->endSection(); ?>
<?php $__template->section('page_actions'); ?>
<?php if ($order->status === 'draft'): ?>
<form method="POST" action="/inventory/purchase-orders/<?= (int) $order->id ?>/submit" style="display:inline;">
<?php if ($order['status'] === 'draft'): ?>
<form method="POST" action="/inventory/purchase-orders/<?= (int) $order['id'] ?>/submit" style="display:inline;">
<?= csrf_field() ?>
<button type="submit" class="btn" style="background:#D97706;color:#fff;border:none;" onclick="return confirm('هل أنت متأكد من تقديم أمر الشراء؟');">
<i data-lucide="send" style="width:15px;height:15px;vertical-align:middle;margin-left:4px;"></i> تقديم
</button>
</form>
<?php endif; ?>
<?php if ($order->status === 'submitted'): ?>
<form method="POST" action="/inventory/purchase-orders/<?= (int) $order->id ?>/approve" style="display:inline;">
<?php if ($order['status'] === 'submitted'): ?>
<form method="POST" action="/inventory/purchase-orders/<?= (int) $order['id'] ?>/approve" style="display:inline;">
<?= csrf_field() ?>
<button type="submit" class="btn" style="background:#0D7377;color:#fff;border:none;" onclick="return confirm('هل أنت متأكد من اعتماد أمر الشراء؟');">
<i data-lucide="check-circle" style="width:15px;height:15px;vertical-align:middle;margin-left:4px;"></i> اعتماد
</button>
</form>
<?php endif; ?>
<?php if ($order->status === 'approved' || $order->status === 'partially_received'): ?>
<a href="/inventory/purchase-orders/<?= (int) $order->id ?>/receive" class="btn" style="background:#059669;color:#fff;border:none;">
<?php if ($order['status'] === 'approved' || $order['status'] === 'partially_received'): ?>
<a href="/inventory/purchase-orders/<?= (int) $order['id'] ?>/receive" class="btn" style="background:#059669;color:#fff;border:none;">
<i data-lucide="package-check" style="width:15px;height:15px;vertical-align:middle;margin-left:4px;"></i> استلام
</a>
<?php endif; ?>
<?php if ($order->status === 'draft' || $order->status === 'submitted'): ?>
<form method="POST" action="/inventory/purchase-orders/<?= (int) $order->id ?>/cancel" style="display:inline;">
<?php if ($order['status'] === 'draft' || $order['status'] === 'submitted'): ?>
<form method="POST" action="/inventory/purchase-orders/<?= (int) $order['id'] ?>/cancel" style="display:inline;">
<?= csrf_field() ?>
<button type="submit" class="btn" style="background:#FEE2E2;color:#DC2626;border:none;" onclick="return confirm('هل أنت متأكد من إلغاء أمر الشراء؟ لا يمكن التراجع عن هذا الإجراء.');">
<i data-lucide="x-circle" style="width:15px;height:15px;vertical-align:middle;margin-left:4px;"></i> إلغاء
......@@ -49,7 +49,7 @@ $statusColors = [
'received' => ['bg' => '#ECFDF5', 'color' => '#059669'],
'cancelled' => ['bg' => '#FEE2E2', 'color' => '#DC2626'],
];
$st = $order->status ?? 'draft';
$st = $order['status'] ?? 'draft';
$stColors = $statusColors[$st] ?? $statusColors['draft'];
$stLabel = $statusLabels[$st] ?? $st;
?>
......@@ -66,22 +66,22 @@ $stLabel = $statusLabels[$st] ?? $st;
<tr>
<td style="padding:10px 0;color:#6B7280;width:40%;">رقم الأمر</td>
<td style="padding:10px 0;font-weight:600;">
<code style="font-size:12px;background:#F3F4F6;padding:2px 8px;border-radius:4px;"><?= e($order->po_number) ?></code>
<code style="font-size:12px;background:#F3F4F6;padding:2px 8px;border-radius:4px;"><?= e($order['po_number']) ?></code>
</td>
</tr>
<tr>
<td style="padding:10px 0;color:#6B7280;">المورد</td>
<td style="padding:10px 0;font-weight:600;">
<a href="/inventory/suppliers/<?= (int) $order->supplier_id ?>" style="color:#0D7377;text-decoration:none;"><?= e($order->supplier_name) ?></a>
<a href="/inventory/suppliers/<?= (int) $order['supplier_id'] ?>" style="color:#0D7377;text-decoration:none;"><?= e($order['supplier_name'] ?? '') ?></a>
</td>
</tr>
<tr>
<td style="padding:10px 0;color:#6B7280;">المستودع</td>
<td style="padding:10px 0;font-weight:600;"><?= e($order->warehouse_name) ?></td>
<td style="padding:10px 0;font-weight:600;"><?= e($order['warehouse_name'] ?? '') ?></td>
</tr>
<tr>
<td style="padding:10px 0;color:#6B7280;">تاريخ التسليم المتوقع</td>
<td style="padding:10px 0;"><?= e($order->expected_delivery_date ?? '—') ?></td>
<td style="padding:10px 0;"><?= e($order['expected_delivery'] ?? '—') ?></td>
</tr>
</table>
<table style="width:100%;font-size:14px;">
......@@ -95,27 +95,21 @@ $stLabel = $statusLabels[$st] ?? $st;
</tr>
<tr>
<td style="padding:10px 0;color:#6B7280;">تاريخ الإنشاء</td>
<td style="padding:10px 0;"><?= e($order->created_at ?? '—') ?></td>
<td style="padding:10px 0;"><?= e($order['created_at'] ?? '—') ?></td>
</tr>
<?php if (!empty($order->approved_at)): ?>
<?php if (!empty($order['approved_at'])): ?>
<tr>
<td style="padding:10px 0;color:#6B7280;">تاريخ الاعتماد</td>
<td style="padding:10px 0;"><?= e($order->approved_at) ?></td>
</tr>
<?php endif; ?>
<?php if (!empty($order->received_at)): ?>
<tr>
<td style="padding:10px 0;color:#6B7280;">تاريخ الاستلام</td>
<td style="padding:10px 0;"><?= e($order->received_at) ?></td>
<td style="padding:10px 0;"><?= e($order['approved_at']) ?></td>
</tr>
<?php endif; ?>
</table>
</div>
<?php if (!empty($order->notes)): ?>
<?php if (!empty($order['notes'])): ?>
<div style="margin-top:20px;padding-top:15px;border-top:1px solid #F3F4F6;">
<div style="font-size:12px;color:#6B7280;margin-bottom:4px;">ملاحظات</div>
<div style="font-size:14px;color:#4B5563;line-height:1.7;"><?= e($order->notes) ?></div>
<div style="font-size:14px;color:#4B5563;line-height:1.7;"><?= e($order['notes']) ?></div>
</div>
<?php endif; ?>
</div>
......@@ -124,7 +118,7 @@ $stLabel = $statusLabels[$st] ?? $st;
<!-- Grand Total -->
<div class="card" style="margin-bottom:20px;padding:20px;text-align:center;background:linear-gradient(135deg, #0D737710, #0D737720);">
<div style="font-size:14px;color:#6B7280;margin-bottom:6px;">الإجمالي الكلي</div>
<div style="font-size:36px;font-weight:800;color:#0D7377;direction:ltr;"><?= money($order->grand_total ?? 0) ?></div>
<div style="font-size:36px;font-weight:800;color:#0D7377;direction:ltr;"><?= money($order['total_amount'] ?? 0) ?></div>
</div>
<!-- Items Table -->
......@@ -170,8 +164,8 @@ $stLabel = $statusLabels[$st] ?? $st;
<span style="font-size:11px;font-weight:600;color:<?= $pctColor ?>;min-width:35px;"><?= $pct ?>%</span>
</div>
</td>
<td style="direction:ltr;text-align:left;"><?= money($item['unit_price'] ?? 0) ?></td>
<td style="font-weight:700;direction:ltr;text-align:left;"><?= money($item['total_price'] ?? 0) ?></td>
<td style="direction:ltr;text-align:left;"><?= money($item['unit_cost'] ?? 0) ?></td>
<td style="font-weight:700;direction:ltr;text-align:left;"><?= money($item['line_total'] ?? 0) ?></td>
</tr>
<?php endforeach; ?>
</tbody>
......
......@@ -42,7 +42,7 @@ $statusLabels = [
<?php
$totalAmount = 0;
foreach ($orders as $o) {
$totalAmount = bcadd((string) $totalAmount, (string) ($o['grand_total'] ?? 0), 2);
$totalAmount = bcadd((string) $totalAmount, (string) ($o['total_amount'] ?? 0), 2);
}
?>
......@@ -90,7 +90,7 @@ $statusLabels = [
<?= e($st['label']) ?>
</span>
</td>
<td style="font-weight:700;direction:ltr;text-align:right;"><?= money($order['grand_total'] ?? 0) ?></td>
<td style="font-weight:700;direction:ltr;text-align:right;"><?= money($order['total_amount'] ?? 0) ?></td>
<td style="font-size:13px;color:#6B7280;white-space:nowrap;"><?= e($order['created_at'] ?? '—') ?></td>
</tr>
<?php endforeach; ?>
......
......@@ -53,7 +53,7 @@ $__template->layout('Layout.main');
</div>
<div class="form-group" style="margin-top:15px;">
<label class="form-label">العنوان</label>
<textarea name="address_ar" class="form-input" rows="2" placeholder="عنوان المورد بالتفصيل..."><?= e(old('address_ar', $supplier->address_ar ?? '')) ?></textarea>
<textarea name="address" class="form-input" rows="2" placeholder="عنوان المورد بالتفصيل..."><?= e(old('address', $supplier->address ?? '')) ?></textarea>
</div>
</div>
</div>
......
......@@ -54,7 +54,7 @@
<table style="width:100%;font-size:14px;">
<tr>
<td style="padding:10px 0;color:#6B7280;width:40%;">العنوان</td>
<td style="padding:10px 0;"><?= e($supplier->address_ar ?? '—') ?></td>
<td style="padding:10px 0;"><?= e($supplier->address ?? '—') ?></td>
</tr>
<tr>
<td style="padding:10px 0;color:#6B7280;">الرقم الضريبي</td>
......@@ -139,7 +139,7 @@
<?= e($poLabel) ?>
</span>
</td>
<td style="font-weight:700;direction:ltr;text-align:left;"><?= money($po['grand_total'] ?? 0) ?></td>
<td style="font-weight:700;direction:ltr;text-align:left;"><?= money($po['total_amount'] ?? 0) ?></td>
<td style="font-size:13px;"><?= e(substr($po['created_at'] ?? '', 0, 10)) ?></td>
<td>
<a href="/inventory/purchase-orders/<?= (int) $po['id'] ?>" class="btn btn-sm btn-outline" style="font-size:12px;padding:4px 10px;">
......
......@@ -12,7 +12,7 @@ class Package extends Model
protected static string $table = 'packages';
protected static string $primaryKey = 'id';
protected static bool $timestamps = true;
protected static bool $softDelete = false;
protected static bool $softDelete = true;
protected static bool $autoTrackAuthor = true;
protected static array $fillable = [
......
......@@ -12,7 +12,7 @@ class Sale extends Model
protected static string $table = 'sales';
protected static string $primaryKey = 'id';
protected static bool $timestamps = true;
protected static bool $softDelete = false;
protected static bool $softDelete = true;
protected static bool $autoTrackAuthor = true;
protected static array $fillable = [
......
......@@ -293,15 +293,14 @@ final class SaleService
}
if ($customerType === 'player' && $playerId) {
$result = PaymentService::processPayment([
'member_id' => 0,
'player_id' => $playerId,
// Players don't have member_id — use guest payment flow with player reference
$result = InventoryPaymentService::processGuestPayment([
'amount' => $amount,
'payment_type' => 'inventory_sale',
'payment_method' => $method,
'guest_name' => 'لاعب #' . $playerId,
'related_entity_type' => 'sales',
'related_entity_id' => $saleId,
'description' => 'مبيعات مخزون — فاتورة ' . $invoiceNumber,
'description' => 'مبيعات مخزون (لاعب) — فاتورة ' . $invoiceNumber,
]);
return $result['success'] ? $result : null;
}
......
......@@ -102,11 +102,11 @@
<tr>
<td><?= $i + 1 ?></td>
<td style="font-family:monospace;font-weight:600;"><?= e($sale['invoice_number'] ?? '—') ?></td>
<td><?= e($sale['customer_name'] ?? 'عميل نقدي') ?></td>
<td><?= e($sale['guest_name'] ?? ($sale['customer_type'] === 'member' ? 'عضو' : ($sale['customer_type'] === 'player' ? 'لاعب' : 'زائر'))) ?></td>
<td style="font-weight:600;direction:ltr;text-align:right;"><?= money($sale['subtotal'] ?? 0) ?></td>
<td style="color:#D97706;direction:ltr;text-align:right;"><?= money($sale['discount'] ?? 0) ?></td>
<td style="color:#2563EB;direction:ltr;text-align:right;"><?= money($sale['tax'] ?? 0) ?></td>
<td style="font-weight:700;color:#059669;direction:ltr;text-align:right;"><?= money($sale['grand_total'] ?? 0) ?></td>
<td style="color:#D97706;direction:ltr;text-align:right;"><?= money($sale['discount_amount'] ?? 0) ?></td>
<td style="color:#2563EB;direction:ltr;text-align:right;"><?= money($sale['tax_amount'] ?? 0) ?></td>
<td style="font-weight:700;color:#059669;direction:ltr;text-align:right;"><?= money($sale['total_amount'] ?? 0) ?></td>
<td style="font-size:13px;"><?= e($methodLabels[$sale['payment_method'] ?? ''] ?? ($sale['payment_method'] ?? '—')) ?></td>
<td style="font-size:13px;color:#6B7280;white-space:nowrap;"><?= e($sale['created_at'] ?? '—') ?></td>
</tr>
......
<?php $__template->layout('Layout.main'); ?>
<?php $__template->section('title'); ?>مشتريات العضو <?= e($member['full_name_ar'] ?? '—') ?><?php $__template->endSection(); ?>
<?php $__template->section('page_actions'); ?>
<a href="/sales" class="btn btn-outline"><i data-lucide="arrow-right" style="width:15px;height:15px;vertical-align:middle;margin-left:4px;"></i> العودة للمبيعات</a>
<?php $__template->endSection(); ?>
<?php $__template->section('content'); ?>
<?php
$statusColors = [
'completed' => ['bg' => '#ECFDF5', 'color' => '#059669'],
'partially_refunded' => ['bg' => '#FFF7ED', 'color' => '#D97706'],
'fully_refunded' => ['bg' => '#FEE2E2', 'color' => '#DC2626'],
'voided' => ['bg' => '#FEE2E2', 'color' => '#DC2626'],
];
$statusLabels = [
'completed' => 'مكتملة',
'partially_refunded' => 'مسترد جزئي',
'fully_refunded' => 'مسترد كلي',
'voided' => 'ملغاة',
];
?>
<!-- Member Info -->
<?php if ($member): ?>
<div class="card" style="margin-bottom:20px;">
<div style="padding:20px;display:flex;align-items:center;gap:12px;">
<div style="width:48px;height:48px;border-radius:50%;background:#0D737720;display:flex;align-items:center;justify-content:center;">
<i data-lucide="user" style="width:22px;height:22px;color:#0D7377;"></i>
</div>
<div>
<div style="font-weight:700;font-size:16px;color:#1F2937;"><?= e($member['full_name_ar']) ?></div>
<div style="font-size:13px;color:#6B7280;">سجل المشتريات</div>
</div>
<div style="margin-right:auto;padding:6px 16px;background:#F3F4F6;border-radius:8px;">
<div style="font-size:11px;color:#6B7280;">عدد المبيعات</div>
<div style="font-weight:700;font-size:18px;color:#0D7377;"><?= count($sales) ?></div>
</div>
</div>
</div>
<?php endif; ?>
<!-- Sales List -->
<div class="card">
<div style="padding:15px 20px;border-bottom:1px solid #E5E7EB;display:flex;align-items:center;gap:8px;">
<i data-lucide="receipt" style="width:18px;height:18px;color:#0D7377;"></i>
<h3 style="margin:0;color:#0D7377;font-size:15px;">المبيعات</h3>
</div>
<?php if (!empty($sales)): ?>
<div class="table-responsive">
<table class="data-table">
<thead>
<tr>
<th>رقم الفاتورة</th>
<th>التاريخ</th>
<th>الإجمالي</th>
<th>طريقة الدفع</th>
<th>الحالة</th>
<th></th>
</tr>
</thead>
<tbody>
<?php foreach ($sales as $sale): ?>
<?php
$st = $sale['status'] ?? 'completed';
$stColors = $statusColors[$st] ?? ['bg' => '#F3F4F6', 'color' => '#6B7280'];
$stLabel = $statusLabels[$st] ?? $st;
?>
<tr>
<td style="font-weight:600;">
<a href="/sales/<?= (int) $sale['id'] ?>" style="color:#0D7377;text-decoration:none;">
<code style="font-size:12px;background:#F3F4F6;padding:2px 8px;border-radius:4px;"><?= e($sale['invoice_number'] ?? '') ?></code>
</a>
</td>
<td style="font-size:13px;"><?= e(substr($sale['sale_date'] ?? '', 0, 10)) ?></td>
<td style="font-weight:700;direction:ltr;text-align:left;"><?= money($sale['total_amount'] ?? 0) ?></td>
<td style="font-size:13px;"><?= e($sale['payment_method'] ?? '—') ?></td>
<td>
<span style="display:inline-block;padding:3px 10px;border-radius:10px;font-size:12px;font-weight:600;background:<?= $stColors['bg'] ?>;color:<?= $stColors['color'] ?>;">
<?= e($stLabel) ?>
</span>
</td>
<td>
<a href="/sales/<?= (int) $sale['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>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php else: ?>
<div style="padding:60px 20px;text-align:center;color:#9CA3AF;">
<i data-lucide="shopping-bag" style="width:40px;height:40px;color:#D1D5DB;margin-bottom:12px;"></i>
<p style="margin:0;font-size:15px;">لا توجد مبيعات لهذا العضو</p>
</div>
<?php endif; ?>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
if (typeof lucide !== 'undefined') {
lucide.createIcons();
}
});
</script>
<?php $__template->endSection(); ?>
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