<?php
declare(strict_types=1);
require __DIR__.'/app/bootstrap.php';require_permission('treasury.receipts.manage');require __DIR__.'/app/layout.php';
$pdo=db();$companyId=company_id();$userId=(int)user()['id'];$currencyId=(int)scalar('SELECT base_currency_id FROM companies WHERE id=?',[$companyId]);
if($_SERVER['REQUEST_METHOD']==='POST'){verify_csrf();try{$action=(string)($_POST['action']??'');
 if($action==='create'){$invoiceId=(int)($_POST['supplier_invoice_id']??0);$amount=round((float)($_POST['amount']??0),2);$inv=$pdo->prepare("SELECT si.*,s.partner_id,bp.legal_name_ar supplier_name FROM supplier_invoices si JOIN suppliers s ON s.id=si.supplier_id JOIN business_partners bp ON bp.id=s.partner_id WHERE si.id=? AND si.company_id=? AND si.status IN ('posted','partially_paid')");$inv->execute([$invoiceId,$companyId]);$inv=$inv->fetch();if(!$inv)throw new RuntimeException('فاتورة المورد غير متاحة للسداد.');$outstanding=round((float)$inv['total_amount']-(float)$inv['paid_amount'],2);if($amount<=0||$amount>$outstanding+0.001)throw new RuntimeException('مبلغ الدفعة يجب أن يكون موجبًا ولا يتجاوز المتبقي.');$method=(string)($_POST['payment_method']??'bank_transfer');$bankId=(int)($_POST['bank_account_id']??0);$cashboxId=(int)($_POST['cashbox_id']??0);if($method!=='cash'&&!$bankId)throw new RuntimeException('اختر الحساب البنكي لطريقة الدفع المحددة.');if($method==='cash'&&!$cashboxId)throw new RuntimeException('اختر الصندوق.');if(!in_array($method,['bank_transfer','cash','cheque','card','other'],true))throw new RuntimeException('طريقة الدفع غير صالحة.');$date=(string)($_POST['payment_date']??'');if(!$date)throw new RuntimeException('تاريخ الدفع مطلوب.');$no='PV-'.date('Ym',strtotime($date)).'-'.str_pad((string)((int)scalar('SELECT COUNT(*)+1 FROM payment_vouchers WHERE company_id=?',[$companyId])),5,'0',STR_PAD_LEFT);$pdo->beginTransaction();$s=$pdo->prepare("INSERT INTO payment_vouchers(company_id,branch_id,partner_id,payment_no,payment_date,payment_method,bank_account_id,cashbox_id,currency_id,amount,reference_no,description,status,created_by,created_at) VALUES (?,?,?,?,?,?,?,?,?,?,?,?, 'draft',?,NOW())");$s->execute([$companyId,$inv['branch_id'],$inv['partner_id'],$no,$date,$method,$bankId?:null,$cashboxId?:null,$currencyId,$amount,trim((string)($_POST['reference_no']??''))?:null,'سداد فاتورة '.$inv['internal_no'],$userId]);$voucherId=(int)$pdo->lastInsertId();$pdo->prepare("INSERT INTO payment_allocations(payment_voucher_id,supplier_invoice_id,allocation_type,allocated_amount,created_at) VALUES (?,?,'supplier_invoice',?,NOW())")->execute([$voucherId,$invoiceId,$amount]);$pdo->commit();audit('supplier_payment.create','payment_voucher',(string)$voucherId,['invoice'=>$inv['internal_no']]);flash('success','تم إنشاء سند الصرف كمسودة: '.$no);
 }elseif(in_array($action,['submit','approve','post'],true)){$id=(int)($_POST['id']??0);if($action==='submit'){$s=$pdo->prepare("UPDATE payment_vouchers SET status='submitted' WHERE id=? AND company_id=? AND status='draft' AND EXISTS(SELECT 1 FROM payment_allocations pa WHERE pa.payment_voucher_id=payment_vouchers.id AND pa.supplier_invoice_id IS NOT NULL)");$s->execute([$id,$companyId]);}elseif($action==='approve'){$s=$pdo->prepare("UPDATE payment_vouchers SET status='approved',approved_by=? WHERE id=? AND company_id=? AND status='submitted'");$s->execute([$userId,$id,$companyId]);}else{$pdo->beginTransaction();$q=$pdo->prepare("SELECT pv.*,pa.supplier_invoice_id,pa.allocated_amount FROM payment_vouchers pv JOIN payment_allocations pa ON pa.payment_voucher_id=pv.id AND pa.allocation_type='supplier_invoice' WHERE pv.id=? AND pv.company_id=? AND pv.status='approved' FOR UPDATE");$q->execute([$id,$companyId]);$voucher=$q->fetch();if(!$voucher)throw new RuntimeException('سند الصرف غير متاح للترحيل.');$iq=$pdo->prepare("SELECT * FROM supplier_invoices WHERE id=? AND company_id=? AND status IN ('posted','partially_paid') FOR UPDATE");$iq->execute([$voucher['supplier_invoice_id'],$companyId]);$inv=$iq->fetch();if(!$inv)throw new RuntimeException('الفاتورة غير متاحة للسداد.');$amount=(float)$voucher['allocated_amount'];$outstanding=round((float)$inv['total_amount']-(float)$inv['paid_amount'],2);if($amount>$outstanding+0.001)throw new RuntimeException('المبلغ أصبح أكبر من رصيد الفاتورة؛ راجع الدفعات السابقة.');$cashAccount=0;if($voucher['bank_account_id'])$cashAccount=(int)scalar('SELECT account_id FROM bank_accounts WHERE id=? AND company_id=?',[$voucher['bank_account_id'],$companyId]);elseif($voucher['cashbox_id'])$cashAccount=(int)scalar('SELECT account_id FROM cashboxes WHERE id=? AND company_id=?',[$voucher['cashbox_id'],$companyId]);if(!$cashAccount)throw new RuntimeException('يلزم ربط السند بحساب بنكي أو صندوق صالح.');$journalId=post_system_journal($voucher['payment_date'],'سداد مورد '.$voucher['payment_no'],'payment_voucher',$id,[['account_id'=>mapped_account('AP_CONTROL'),'debit'=>$amount,'project_id'=>$inv['project_id']],['account_id'=>$cashAccount,'credit'=>$amount,'project_id'=>$inv['project_id']]]);$s=$pdo->prepare("UPDATE payment_vouchers SET status='posted',journal_entry_id=? WHERE id=?");$s->execute([$journalId,$id]);$newPaid=round((float)$inv['paid_amount']+$amount,2);$newStatus=$newPaid+0.001>=(float)$inv['total_amount']?'paid':'partially_paid';$pdo->prepare('UPDATE supplier_invoices SET paid_amount=?,status=? WHERE id=?')->execute([$newPaid,$newStatus,$inv['id']]);$pdo->commit();}if(!$s->rowCount())throw new RuntimeException('تعذر تنفيذ الإجراء على سند الصرف.');audit('supplier_payment.'.$action,'payment_voucher',(string)$id);flash('success','تم تحديث دورة السداد بنجاح.');
 }}catch(Throwable $e){if($pdo->inTransaction())$pdo->rollBack();flash('error',$e instanceof PDOException?'تعذر حفظ السداد؛ تحقق من البيانات والمرجع.':$e->getMessage());}redirect('supplier_payments.php');}
$invoices=$pdo->prepare("SELECT si.id,si.internal_no,si.invoice_no,si.invoice_date,si.due_date,si.total_amount,si.paid_amount,si.total_amount-si.paid_amount outstanding,bp.legal_name_ar supplier_name,p.name_ar project_name FROM supplier_invoices si JOIN suppliers s ON s.id=si.supplier_id JOIN business_partners bp ON bp.id=s.partner_id LEFT JOIN projects p ON p.id=si.project_id WHERE si.company_id=? AND si.status IN ('posted','partially_paid') AND si.paid_amount<si.total_amount ORDER BY COALESCE(si.due_date,si.invoice_date),si.id");$invoices->execute([$companyId]);$invoices=$invoices->fetchAll();$selectedInvoice=(int)($_GET['invoice_id']??0);$selected=null;foreach($invoices as $i)if((int)$i['id']===$selectedInvoice)$selected=$i;$banks=$pdo->prepare('SELECT id,code,bank_name FROM bank_accounts WHERE company_id=? AND is_active=1 ORDER BY code');$banks->execute([$companyId]);$banks=$banks->fetchAll();$cashboxes=$pdo->prepare('SELECT id,code,name_ar FROM cashboxes WHERE company_id=? AND is_active=1 ORDER BY code');$cashboxes->execute([$companyId]);$cashboxes=$cashboxes->fetchAll();$payments=$pdo->prepare("SELECT pv.*,pa.supplier_invoice_id,pa.allocated_amount,si.internal_no,bp.legal_name_ar supplier_name FROM payment_vouchers pv JOIN payment_allocations pa ON pa.payment_voucher_id=pv.id AND pa.allocation_type='supplier_invoice' JOIN supplier_invoices si ON si.id=pa.supplier_invoice_id JOIN business_partners bp ON bp.id=pv.partner_id WHERE pv.company_id=? ORDER BY pv.id DESC LIMIT 100");$payments->execute([$companyId]);$payments=$payments->fetchAll();
render_header('supplier_payments','سداد الموردين','دفعات جزئية أو كاملة مرتبطة بفواتير الموردين المرحلة.');?>
<section class="panel data-card"><header><h2>الفواتير المستحقة</h2></header><div class="responsive-table"><table><thead><tr><th>الفاتورة</th><th>المورد</th><th>المشروع</th><th>الاستحقاق</th><th>الإجمالي</th><th>المدفوع</th><th>المتبقي</th><th></th></tr></thead><tbody><?php foreach($invoices as $i):?><tr><td><?= e($i['internal_no'].' / '.$i['invoice_no']) ?></td><td><?= e($i['supplier_name']) ?></td><td><?= e($i['project_name']?:'عام') ?></td><td><?= e($i['due_date']?:'—') ?></td><td><?= number_format((float)$i['total_amount'],2) ?></td><td><?= number_format((float)$i['paid_amount'],2) ?></td><td><?= number_format((float)$i['outstanding'],2) ?></td><td><a href="?invoice_id=<?= (int)$i['id'] ?>">إنشاء دفعة</a></td></tr><?php endforeach;?></tbody></table></div></section>
<?php if($selected):?><details class="panel quick-add" open><summary>＋ سند صرف للفاتورة <?= e($selected['internal_no']) ?></summary><form method="post"><?= csrf_field() ?><input type="hidden" name="action" value="create"><input type="hidden" name="supplier_invoice_id" value="<?= (int)$selected['id'] ?>"><div class="form-grid"><label>المبلغ المتبقي<input value="<?= number_format((float)$selected['outstanding'],2,'.','') ?>" readonly></label><label>مبلغ الدفعة<input type="number" step="0.01" min="0.01" max="<?= e((string)$selected['outstanding']) ?>" name="amount" value="<?= e((string)$selected['outstanding']) ?>" required></label><label>تاريخ الدفع<input type="date" name="payment_date" value="<?= date('Y-m-d') ?>" required></label><label>طريقة الدفع<select name="payment_method"><option value="bank_transfer">تحويل بنكي</option><option value="cash">نقدي</option><option value="cheque">شيك</option><option value="card">بطاقة</option><option value="other">أخرى</option></select></label><label>الحساب البنكي<select name="bank_account_id"><option value="0">—</option><?php foreach($banks as $b):?><option value="<?= (int)$b['id'] ?>"><?= e($b['code'].' — '.$b['bank_name']) ?></option><?php endforeach;?></select></label><label>الصندوق<select name="cashbox_id"><option value="0">—</option><?php foreach($cashboxes as $c):?><option value="<?= (int)$c['id'] ?>"><?= e($c['code'].' — '.$c['name_ar']) ?></option><?php endforeach;?></select></label><label>مرجع التحويل أو الشيك<input name="reference_no"></label></div><button class="primary-btn">حفظ سند الصرف</button></form></details><?php endif;?>
<section class="panel data-card"><header><h2>دفعات الموردين</h2></header><div class="responsive-table"><table><thead><tr><th>السند</th><th>الفاتورة</th><th>المورد</th><th>التاريخ</th><th>المبلغ</th><th>الطريقة</th><th>الحالة</th><th>الإجراء</th></tr></thead><tbody><?php foreach($payments as $r):?><tr><td><?= e($r['payment_no']) ?></td><td><?= e($r['internal_no']) ?></td><td><?= e($r['supplier_name']) ?></td><td><?= e($r['payment_date']) ?></td><td><?= number_format((float)$r['allocated_amount'],2) ?></td><td><?= e($r['payment_method']) ?></td><td><span class="chip"><?= e($r['status']) ?></span></td><td><?php $next=$r['status']==='draft'?'submit':($r['status']==='submitted'?'approve':($r['status']==='approved'?'post':''));$label=['submit'=>'تقديم','approve'=>'اعتماد','post'=>'ترحيل'];if($next):?><form method="post"><?= csrf_field() ?><input type="hidden" name="action" value="<?= $next ?>"><input type="hidden" name="id" value="<?= (int)$r['id'] ?>"><button><?= e($label[$next]) ?></button></form><?php endif;?></td></tr><?php endforeach;?></tbody></table></div></section>
<?php render_footer();
