<?php
declare(strict_types=1);
require __DIR__.'/app/bootstrap.php';require_permission('payroll.view');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==='employee_create'){$s=$pdo->prepare("INSERT INTO employees(company_id,employee_no,full_name,job_title,branch_id,hire_date,employment_status,default_project_id,created_at,updated_at) VALUES (?,?,?,?,?,?,'active',?,NOW(),NOW())");$s->execute([$companyId,trim((string)$_POST['employee_no']),trim((string)$_POST['full_name']),trim((string)($_POST['job_title']??''))?:null,(int)user()['branch_id'],($_POST['hire_date']??'')?:null,(int)($_POST['project_id']??0)?:null]);audit('employee.create','employee',(string)$pdo->lastInsertId());flash('success','تم تسجيل الموظف.');
 }elseif($action==='payroll_create'){$periodId=(int)$_POST['fiscal_period_id'];$employeeIds=$_POST['employee_id']??[];$basics=$_POST['basic_salary']??[];$allowances=$_POST['allowances']??[];$deductions=$_POST['deductions']??[];$items=[];$gross=0;$dedTotal=0;$net=0;foreach($employeeIds as $i=>$employeeId){$basic=round((float)($basics[$i]??0),2);$allow=round((float)($allowances[$i]??0),2);$ded=round((float)($deductions[$i]??0),2);if(!$employeeId||$basic<=0)continue;$itemNet=$basic+$allow-$ded;if($itemNet<0)throw new RuntimeException('استقطاعات موظف تتجاوز مستحقاته.');$items[]=[(int)$employeeId,$basic,$allow,$ded,$itemNet];$gross+=$basic+$allow;$dedTotal+=$ded;$net+=$itemNet;}if(!$items)throw new RuntimeException('أضف موظفًا واحدًا على الأقل للمسير.');$period=$pdo->prepare("SELECT fp.* FROM fiscal_periods fp JOIN fiscal_years fy ON fy.id=fp.fiscal_year_id WHERE fp.id=? AND fy.company_id=? AND fp.status='open'");$period->execute([$periodId,$companyId]);$period=$period->fetch();if(!$period)throw new RuntimeException('الفترة غير مفتوحة.');$no='PAY-'.date('Ym',strtotime($period['ends_on']));$pdo->beginTransaction();$pdo->prepare("INSERT INTO payroll_runs(company_id,branch_id,fiscal_period_id,payroll_no,period_start,period_end,payment_date,status,gross_amount,deductions_amount,net_amount,prepared_by,created_at) VALUES (?,?,?,?,?,?,?,'calculated',?,?,?, ?,NOW())")->execute([$companyId,(int)user()['branch_id'],$periodId,$no,$period['starts_on'],$period['ends_on'],($_POST['payment_date']??'')?:null,$gross,$dedTotal,$net,$userId]);$runId=(int)$pdo->lastInsertId();$s=$pdo->prepare('INSERT INTO payroll_items(payroll_run_id,employee_id,basic_salary,allowances_amount,deductions_amount,net_salary) VALUES (?,?,?,?,?,?)');foreach($items as $item)$s->execute([$runId,$item[0],$item[1],$item[2],$item[3],$item[4]]);$pdo->commit();audit('payroll.calculate','payroll_run',(string)$runId,['net'=>$net]);flash('success','تم احتساب مسير الرواتب.');
 }elseif($action==='payroll_approve'){$s=$pdo->prepare("UPDATE payroll_runs SET status='approved',approved_by=? WHERE id=? AND company_id=? AND status='calculated'");$s->execute([$userId,(int)$_POST['id'],$companyId]);if(!$s->rowCount())throw new RuntimeException('تعذر اعتماد المسير.');flash('success','تم اعتماد مسير الرواتب.');
 }elseif($action==='custody_create'){$amount=round((float)$_POST['amount'],2);if($amount<=0)throw new RuntimeException('مبلغ العهدة يجب أن يكون موجبًا.');$no='CUS-'.date('Ym').'-'.str_pad((string)((int)scalar('SELECT COUNT(*)+1 FROM custodies WHERE company_id=?',[$companyId])),4,'0',STR_PAD_LEFT);$s=$pdo->prepare("INSERT INTO custodies(company_id,branch_id,employee_id,project_id,custody_no,custody_type,currency_id,approved_limit,issued_amount,outstanding_amount,issued_on,due_on,status,created_by,approved_by,created_at) VALUES (?,?,?,?,?,'temporary',?,?,?,?,?,?,'open',?,?,NOW())");$s->execute([$companyId,(int)user()['branch_id'],(int)$_POST['employee_id'],(int)($_POST['project_id']??0)?:null,$no,$currencyId,$amount,$amount,$amount,$_POST['issued_on'],($_POST['due_on']??'')?:null,$userId,$userId]);audit('custody.create','custody',(string)$pdo->lastInsertId());flash('success','تم إصدار العهدة: '.$no);
 }elseif($action==='custody_settle'){$custodyId=(int)$_POST['custody_id'];$expense=round((float)$_POST['expense_amount'],2);$returned=round((float)$_POST['returned_amount'],2);$c=$pdo->prepare("SELECT * FROM custodies WHERE id=? AND company_id=? AND status IN ('open','partially_settled')");$c->execute([$custodyId,$companyId]);$c=$c->fetch();if(!$c||$expense+$returned<=0||$expense+$returned>(float)$c['outstanding_amount']+0.01)throw new RuntimeException('بيانات التسوية غير صالحة.');$no='SET-'.$c['custody_no'].'-'.((int)scalar('SELECT COUNT(*)+1 FROM custody_settlements WHERE custody_id=?',[$custodyId]));$pdo->beginTransaction();$pdo->prepare("INSERT INTO custody_settlements(custody_id,settlement_no,settlement_date,total_expense_amount,amount_returned,status,prepared_by,approved_by,created_at) VALUES (?,?,?,?,?,'approved',?,?,NOW())")->execute([$custodyId,$no,$_POST['settlement_date'],$expense,$returned,$userId,$userId]);$settlementId=(int)$pdo->lastInsertId();if($expense>0)$pdo->prepare("INSERT INTO custody_settlement_lines(custody_settlement_id,project_id,expense_account_id,expense_date,description,amount_before_tax,total_amount) VALUES (?,?,?,?,?,?,?)")->execute([$settlementId,$c['project_id'],(int)$_POST['expense_account_id'],$_POST['settlement_date'],trim((string)$_POST['description']),$expense,$expense]);$newOutstanding=(float)$c['outstanding_amount']-$expense-$returned;$pdo->prepare("UPDATE custodies SET settled_amount=settled_amount+?,outstanding_amount=?,status=? WHERE id=?")->execute([$expense+$returned,$newOutstanding,$newOutstanding<=0.009?'settled':'partially_settled',$custodyId]);$pdo->commit();audit('custody.settle','custody',(string)$custodyId,['amount'=>$expense+$returned]);flash('success','تمت تسوية العهدة.');
 }}catch(Throwable $e){if($pdo->inTransaction())$pdo->rollBack();flash('error',$e instanceof PDOException?'الرقم مكرر أو البيانات غير صالحة.':$e->getMessage());}redirect('workforce.php');}
$employees=$pdo->prepare("SELECT e.*,p.name_ar project_name FROM employees e LEFT JOIN projects p ON p.id=e.default_project_id WHERE e.company_id=? AND e.employment_status='active' ORDER BY e.employee_no");$employees->execute([$companyId]);$employees=$employees->fetchAll();$projects=$pdo->prepare("SELECT id,project_no,name_ar FROM projects WHERE company_id=? AND deleted_at IS NULL ORDER BY project_no");$projects->execute([$companyId]);$projects=$projects->fetchAll();$periods=$pdo->prepare("SELECT fp.id,fp.name,fy.name year_name FROM fiscal_periods fp JOIN fiscal_years fy ON fy.id=fp.fiscal_year_id WHERE fy.company_id=? AND fp.status='open' ORDER BY fp.starts_on");$periods->execute([$companyId]);$periods=$periods->fetchAll();$accounts=$pdo->prepare("SELECT id,code,name_ar FROM accounts WHERE company_id=? AND is_postable=1 AND status='active' ORDER BY code");$accounts->execute([$companyId]);$accounts=$accounts->fetchAll();$runs=$pdo->prepare('SELECT pr.*,fp.name period_name FROM payroll_runs pr JOIN fiscal_periods fp ON fp.id=pr.fiscal_period_id WHERE pr.company_id=? ORDER BY pr.id DESC');$runs->execute([$companyId]);$runs=$runs->fetchAll();$custodies=$pdo->prepare("SELECT c.*,e.full_name,p.name_ar project_name FROM custodies c JOIN employees e ON e.id=c.employee_id LEFT JOIN projects p ON p.id=c.project_id WHERE c.company_id=? ORDER BY c.id DESC");$custodies->execute([$companyId]);$custodies=$custodies->fetchAll();
render_header('workforce','الموظفون والرواتب والعهد','سجل الموظفين ومسيرات الرواتب والعهد التشغيلية.');?>
<details class="panel quick-add"><summary>＋ موظف</summary><form method="post"><?= csrf_field() ?><input type="hidden" name="action" value="employee_create"><div class="form-grid"><label>الرقم الوظيفي<input name="employee_no" required></label><label>الاسم<input name="full_name" required></label><label>المسمى<input name="job_title"></label><label>تاريخ التعيين<input type="date" name="hire_date"></label><label>المشروع الافتراضي<select name="project_id"><option value="0">الإدارة</option><?php foreach($projects as $p):?><option value="<?= (int)$p['id'] ?>"><?= e($p['project_no'].' — '.$p['name_ar']) ?></option><?php endforeach;?></select></label></div><button class="primary-btn">حفظ الموظف</button></form></details>
<details class="panel quick-add" open><summary>＋ مسير رواتب</summary><form method="post" id="payrollForm"><?= csrf_field() ?><input type="hidden" name="action" value="payroll_create"><label>الفترة<select name="fiscal_period_id"><?php foreach($periods as $p):?><option value="<?= (int)$p['id'] ?>"><?= e($p['year_name'].' — '.$p['name']) ?></option><?php endforeach;?></select></label><div class="responsive-table"><table id="payrollLines"><thead><tr><th>الموظف</th><th>الأساسي</th><th>البدلات</th><th>الاستقطاعات</th><th></th></tr></thead><tbody><tr><td><select name="employee_id[]"><?php foreach($employees as $e):?><option value="<?= (int)$e['id'] ?>"><?= e($e['employee_no'].' — '.$e['full_name']) ?></option><?php endforeach;?></select></td><td><input type="number" name="basic_salary[]" step="0.01"></td><td><input type="number" name="allowances[]" step="0.01" value="0"></td><td><input type="number" name="deductions[]" step="0.01" value="0"></td><td><button type="button" onclick="this.closest('tr').remove()">×</button></td></tr></tbody></table></div><button type="button" id="addPayroll" class="secondary-btn">إضافة موظف</button> <button class="primary-btn">احتساب المسير</button></form></details>
<section class="panel data-card"><header><h2>مسيرات الرواتب</h2></header><table><thead><tr><th>المسير</th><th>الفترة</th><th>الإجمالي</th><th>الاستقطاعات</th><th>الصافي</th><th>الحالة</th><th></th></tr></thead><tbody><?php foreach($runs as $r):?><tr><td><?= e($r['payroll_no']) ?></td><td><?= e($r['period_name']) ?></td><td><?= number_format((float)$r['gross_amount'],2) ?></td><td><?= number_format((float)$r['deductions_amount'],2) ?></td><td><?= number_format((float)$r['net_amount'],2) ?></td><td><?= e($r['status']) ?></td><td><?php if($r['status']==='calculated'):?><form method="post"><?= csrf_field() ?><input type="hidden" name="action" value="payroll_approve"><input type="hidden" name="id" value="<?= (int)$r['id'] ?>"><button>اعتماد</button></form><?php endif;?></td></tr><?php endforeach;?></tbody></table></section>
<div class="settings-grid"><details class="panel quick-add"><summary>＋ إصدار عهدة</summary><form method="post"><?= csrf_field() ?><input type="hidden" name="action" value="custody_create"><label>الموظف<select name="employee_id"><?php foreach($employees as $e):?><option value="<?= (int)$e['id'] ?>"><?= e($e['full_name']) ?></option><?php endforeach;?></select></label><label>المشروع<select name="project_id"><option value="0">عام</option><?php foreach($projects as $p):?><option value="<?= (int)$p['id'] ?>"><?= e($p['name_ar']) ?></option><?php endforeach;?></select></label><label>المبلغ<input type="number" step="0.01" name="amount"></label><label>تاريخ الإصدار<input type="date" name="issued_on" value="<?= date('Y-m-d') ?>"></label><label>الاستحقاق<input type="date" name="due_on"></label><button class="primary-btn">إصدار</button></form></details><details class="panel quick-add"><summary>＋ تسوية عهدة</summary><form method="post"><?= csrf_field() ?><input type="hidden" name="action" value="custody_settle"><label>العهدة<select name="custody_id"><?php foreach($custodies as $c):if(in_array($c['status'],['open','partially_settled'],true)):?><option value="<?= (int)$c['id'] ?>"><?= e($c['custody_no'].' — '.$c['full_name'].' — '.$c['outstanding_amount']) ?></option><?php endif;endforeach;?></select></label><label>تاريخ التسوية<input type="date" name="settlement_date" value="<?= date('Y-m-d') ?>"></label><label>مصروفات<input type="number" step="0.01" name="expense_amount" value="0"></label><label>مبلغ معاد<input type="number" step="0.01" name="returned_amount" value="0"></label><label>حساب المصروف<select name="expense_account_id"><?php foreach($accounts as $a):?><option value="<?= (int)$a['id'] ?>"><?= e($a['code'].' — '.$a['name_ar']) ?></option><?php endforeach;?></select></label><label>البيان<input name="description"></label><button class="primary-btn">تسوية</button></form></details></div>
<template id="payrollTemplate"><tr><td><select name="employee_id[]"><?php foreach($employees as $e):?><option value="<?= (int)$e['id'] ?>"><?= e($e['employee_no'].' — '.$e['full_name']) ?></option><?php endforeach;?></select></td><td><input type="number" name="basic_salary[]" step="0.01"></td><td><input type="number" name="allowances[]" step="0.01" value="0"></td><td><input type="number" name="deductions[]" step="0.01" value="0"></td><td><button type="button" onclick="this.closest('tr').remove()">×</button></td></tr></template><script>addPayroll.onclick=()=>document.querySelector('#payrollLines tbody').append(payrollTemplate.content.cloneNode(true));</script>
<?php render_footer();
