<?php
declare(strict_types=1);
require __DIR__.'/app/bootstrap.php';require_permission('tax.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'){$poId=(int)($_POST['purchase_order_id']??0);$po=$pdo->prepare("SELECT * FROM purchase_orders WHERE id=? AND company_id=? AND status IN ('partially_received','received','partially_invoiced')");$po->execute([$poId,$companyId]);$po=$po->fetch();if(!$po)throw new RuntimeException('أمر الشراء غير متاح للمطابقة.');$supplierNo=trim((string)($_POST['invoice_no']??''));if(!$supplierNo)throw new RuntimeException('رقم فاتورة المورد مطلوب.');$ids=$_POST['po_item_id']??[];$qtys=$_POST['quantity']??[];$prices=$_POST['unit_price']??[];$taxPcts=$_POST['tax_pct']??[];$lines=[];$subtotal=0;$taxTotal=0;$exception=false;
  foreach($ids as $i=>$id){$qty=round((float)($qtys[$i]??0),4);if($qty<=0)continue;$s=$pdo->prepare('SELECT * FROM purchase_order_items WHERE id=? AND purchase_order_id=?');$s->execute([(int)$id,$poId]);$item=$s->fetch();if(!$item)throw new RuntimeException('بند أمر شراء غير صحيح.');$available=(float)$item['received_qty']-(float)$item['invoiced_qty'];if($qty>$available+0.00001)throw new RuntimeException('كمية الفاتورة تتجاوز الكمية المستلمة المتاحة.');$price=round((float)($prices[$i]??0),4);if($price<0)throw new RuntimeException('سعر الفاتورة غير صحيح.');$taxPct=max(0,(float)($taxPcts[$i]??15));$base=round($qty*$price,2);$tax=round($base*$taxPct/100,2);$priceVariance=round($price-(float)$item['unit_price'],4);if(abs($priceVariance)>0.0001)$exception=true;$lines[]=[$item,$qty,$price,$tax,$base+$tax,$priceVariance];$subtotal+=$base;$taxTotal+=$tax;}
  if(!$lines)throw new RuntimeException('أدخل كمية فاتورة لبند واحد على الأقل.');$internal='SI-'.date('Ym').'-'.str_pad((string)((int)scalar('SELECT COUNT(*)+1 FROM supplier_invoices WHERE company_id=?',[$companyId])),5,'0',STR_PAD_LEFT);$pdo->beginTransaction();$status=$exception?'disputed':'matched';$matching=$exception?'exception':'matched';$s=$pdo->prepare("INSERT INTO supplier_invoices(company_id,branch_id,project_id,supplier_id,purchase_order_id,invoice_no,internal_no,invoice_date,due_date,currency_id,subtotal,tax_amount,total_amount,status,matching_status,created_by,created_at,updated_at) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,NOW(),NOW())");$s->execute([$companyId,$po['branch_id'],$po['project_id'],$po['supplier_id'],$poId,$supplierNo,$internal,$_POST['invoice_date'],($_POST['due_date']??'')?:null,$currencyId,$subtotal,$taxTotal,$subtotal+$taxTotal,$status,$matching,$userId]);$invoiceId=(int)$pdo->lastInsertId();$ins=$pdo->prepare('INSERT INTO supplier_invoice_items(supplier_invoice_id,purchase_order_item_id,item_id,description,quantity,unit_code,unit_price,discount_amount,tax_amount,line_total,cost_code_id) VALUES (?,?,?,?,?,?,?,?,?,?,?)');foreach($lines as [$item,$qty,$price,$tax,$total]){$ins->execute([$invoiceId,$item['id'],$item['item_id'],$item['description'],$qty,$item['unit_code'],$price,0,$tax,$total,$item['cost_code_id']]);$pdo->prepare('UPDATE purchase_order_items SET invoiced_qty=invoiced_qty+? WHERE id=?')->execute([$qty,$item['id']]);}$pdo->prepare("UPDATE purchase_orders SET status='partially_invoiced' WHERE id=?")->execute([$poId]);$pdo->commit();audit('supplier_invoice.match','supplier_invoice',(string)$invoiceId,['matching_status'=>$matching]);flash($exception?'error':'success',$exception?'سُجلت الفاتورة مع وجود فرق سعر وتحتاج مراجعة.':'تمت المطابقة الثلاثية بنجاح: '.$internal);
 }elseif(in_array($action,['accept_exception','submit','approve','post'],true)){$id=(int)($_POST['id']??0);if($action==='accept_exception'){$s=$pdo->prepare("UPDATE supplier_invoices SET matching_status='matched',status='matched' WHERE id=? AND company_id=? AND status='disputed' AND matching_status='exception'");$s->execute([$id,$companyId]);}elseif($action==='submit'){$s=$pdo->prepare("UPDATE supplier_invoices SET status='submitted' WHERE id=? AND company_id=? AND status='matched' AND matching_status='matched'");$s->execute([$id,$companyId]);}elseif($action==='approve'){$s=$pdo->prepare("UPDATE supplier_invoices SET status='approved',approved_by=?,approved_at=NOW() WHERE id=? AND company_id=? AND status='submitted' AND matching_status='matched'");$s->execute([$userId,$id,$companyId]);}else{$q=$pdo->prepare("SELECT * FROM supplier_invoices WHERE id=? AND company_id=? AND status='approved' AND matching_status='matched'");$q->execute([$id,$companyId]);$inv=$q->fetch();if(!$inv)throw new RuntimeException('الفاتورة غير متاحة للترحيل.');$pdo->beginTransaction();$journalId=post_system_journal($inv['invoice_date'],'فاتورة مورد '.$inv['internal_no'],'supplier_invoice',$id,[['account_id'=>mapped_account('PROJECT_MATERIAL_COST'),'debit'=>$inv['subtotal'],'project_id'=>$inv['project_id']],['account_id'=>mapped_account('VAT_INPUT'),'debit'=>$inv['tax_amount'],'project_id'=>$inv['project_id']],['account_id'=>mapped_account('AP_CONTROL'),'credit'=>$inv['total_amount'],'project_id'=>$inv['project_id']]]);$s=$pdo->prepare("UPDATE supplier_invoices SET status='posted',journal_entry_id=? WHERE id=?");$s->execute([$journalId,$id]);$remaining=(int)scalar('SELECT COUNT(*) FROM purchase_order_items WHERE purchase_order_id=? AND invoiced_qty<received_qty',[$inv['purchase_order_id']]);$pdo->prepare('UPDATE purchase_orders SET status=? WHERE id=?')->execute([$remaining?'partially_invoiced':'invoiced',$inv['purchase_order_id']]);$pdo->commit();}if(!$s->rowCount())throw new RuntimeException('تعذر تنفيذ الإجراء على الفاتورة.');audit('supplier_invoice.'.$action,'supplier_invoice',(string)$id);flash('success','تم تحديث دورة فاتورة المورد.');
 }}catch(Throwable $e){if($pdo->inTransaction())$pdo->rollBack();flash('error',$e instanceof PDOException?'رقم فاتورة المورد مكرر أو البيانات غير متوافقة.':$e->getMessage());}redirect('payables.php');}
$pos=$pdo->prepare("SELECT po.id,po.po_no,bp.legal_name_ar supplier_name FROM purchase_orders po JOIN suppliers s ON s.id=po.supplier_id JOIN business_partners bp ON bp.id=s.partner_id WHERE po.company_id=? AND po.status IN ('partially_received','received','partially_invoiced') AND EXISTS(SELECT 1 FROM purchase_order_items pi WHERE pi.purchase_order_id=po.id AND pi.received_qty>pi.invoiced_qty) ORDER BY po.id DESC");$pos->execute([$companyId]);$pos=$pos->fetchAll();$selectedPo=(int)($_GET['po_id']??0);$poLines=[];if($selectedPo){$s=$pdo->prepare('SELECT *,received_qty-invoiced_qty available_qty FROM purchase_order_items WHERE purchase_order_id=? AND received_qty>invoiced_qty ORDER BY id');$s->execute([$selectedPo]);$poLines=$s->fetchAll();}$invoices=$pdo->prepare("SELECT si.*,po.po_no,bp.legal_name_ar supplier_name,COALESCE((SELECT SUM((sii.unit_price-poi.unit_price)*sii.quantity) FROM supplier_invoice_items sii JOIN purchase_order_items poi ON poi.id=sii.purchase_order_item_id WHERE sii.supplier_invoice_id=si.id),0) price_variance 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 purchase_orders po ON po.id=si.purchase_order_id WHERE si.company_id=? ORDER BY si.id DESC LIMIT 100");$invoices->execute([$companyId]);$invoices=$invoices->fetchAll();
render_header('payables','مطابقة فواتير الموردين','مطابقة أمر الشراء والاستلام والفاتورة قبل الاعتماد والترحيل.');?>
<section class="panel form-card"><form method="get"><label>أمر الشراء المستلم<select name="po_id" onchange="this.form.submit()"><option value="0">اختر أمر الشراء</option><?php foreach($pos as $po):?><option value="<?= (int)$po['id'] ?>" <?= $selectedPo===(int)$po['id']?'selected':'' ?>><?= e($po['po_no'].' — '.$po['supplier_name']) ?></option><?php endforeach;?></select></label></form><?php if($selectedPo&&$poLines):?><form method="post"><?= csrf_field() ?><input type="hidden" name="action" value="create"><input type="hidden" name="purchase_order_id" value="<?= $selectedPo ?>"><div class="form-grid"><label>رقم فاتورة المورد<input name="invoice_no" required></label><label>تاريخ الفاتورة<input type="date" name="invoice_date" value="<?= date('Y-m-d') ?>" required></label><label>الاستحقاق<input type="date" name="due_date"></label></div><div class="responsive-table"><table><thead><tr><th>البند</th><th>سعر الأمر</th><th>المستلم غير المفوتر</th><th>كمية الفاتورة</th><th>سعر الفاتورة</th><th>الضريبة %</th></tr></thead><tbody><?php foreach($poLines as $l):?><tr><td><?= e($l['description']) ?><input type="hidden" name="po_item_id[]" value="<?= (int)$l['id'] ?>"></td><td><?= number_format((float)$l['unit_price'],4) ?></td><td><?= number_format((float)$l['available_qty'],4) ?></td><td><input type="number" step="0.0001" min="0" max="<?= e((string)$l['available_qty']) ?>" name="quantity[]" value="<?= e((string)$l['available_qty']) ?>"></td><td><input type="number" step="0.0001" min="0" name="unit_price[]" value="<?= e((string)$l['unit_price']) ?>"></td><td><input type="number" step="0.01" min="0" name="tax_pct[]" value="15"></td></tr><?php endforeach;?></tbody></table></div><button class="primary-btn">فحص المطابقة وتسجيل الفاتورة</button></form><?php endif;?></section>
<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><th>الإجراء</th></tr></thead><tbody><?php foreach($invoices as $r):?><tr><td><?= e($r['internal_no']) ?></td><td><?= e($r['invoice_no']) ?></td><td><?= e($r['supplier_name']) ?></td><td><?= e($r['po_no']?:'—') ?></td><td><?= number_format((float)$r['total_amount'],2) ?></td><td><?= number_format((float)$r['price_variance'],2) ?></td><td><span class="chip"><?= e($r['matching_status']) ?></span></td><td><span class="chip"><?= e($r['status']) ?></span></td><td><?php $next=$r['status']==='disputed'?'accept_exception':($r['status']==='matched'?'submit':($r['status']==='submitted'?'approve':($r['status']==='approved'?'post':'')));$labels=['accept_exception'=>'قبول الفرق','submit'=>'تقديم','approve'=>'اعتماد','post'=>'ترحيل'];if($next):?><form method="post" <?= $next==='accept_exception'?'onsubmit="return confirm(\'قبول فرق السعر مسؤولية المعتمد. متابعة؟\')"':'' ?>><?= csrf_field() ?><input type="hidden" name="action" value="<?= $next ?>"><input type="hidden" name="id" value="<?= (int)$r['id'] ?>"><button><?= e($labels[$next]) ?></button></form><?php endif;?></td></tr><?php endforeach;?></tbody></table></div></section>
<?php render_footer();
