0.01) { $errors[] = ['code' => 'RULE_001', 'message_ar' => 'مجموع سطور الفاتورة لا يطابق المجموع الكلي']; } // Rule 002: Tax integrity (tax_amount = subtotal × tax_rate) foreach ($lines as $line) { $expectedTax = round($line['quantity'] * $line['unit_price'] * $line['tax_rate'], 3); if (abs($line['tax_amount'] - $expectedTax) > 0.01) { $errors[] = ['code' => 'RULE_002', 'message_ar' => "خطأ في حساب الضريبة للسطر {$line['line_number']}"]; } } // Rule 003: Invoice number required if (empty($invoice['invoice_number'])) { $errors[] = ['code' => 'RULE_003', 'message_ar' => 'رقم الفاتورة مطلوب']; } // Rule 004: No future dates if (strtotime($invoice['invoice_date']) > time()) { $errors[] = ['code' => 'RULE_004', 'message_ar' => 'تاريخ الفاتورة لا يمكن أن يكون في المستقبل']; } // Rule 005: Valid JO Tax Rates $validRates = [0.16, 0.10, 0.05, 0.04, 0.02, 0.00]; foreach ($lines as $line) { if (!in_array(round((float)$line['tax_rate'], 2), $validRates)) { $errors[] = ['code' => 'RULE_005', 'message_ar' => "نسبة الضريبة ({$line['tax_rate']}) غير صالحة في الأردن"]; } } // Rule 006: Buyer ID for large invoices (> 10,000 JOD) if ($invoice['grand_total'] > 10000 && empty($invoice['buyer_tin']) && empty($invoice['buyer_national_id'])) { $errors[] = ['code' => 'RULE_006', 'message_ar' => 'يجب تزويد الرقم الضريبي أو الوطني للمشتري للفواتير التي تتجاوز 10,000 دينار']; } // Rule 007: Discount integrity — subtotal - discount = Σ(line totals before tax) $lineSumBeforeTax = array_sum(array_map( fn($l) => round(($l['quantity'] * $l['unit_price']) - ($l['discount'] ?? 0), 3), $lines )); $expected = round($invoice['subtotal'] - $invoice['discount_total'], 3); if (abs($expected - $lineSumBeforeTax) > 0.01) { $errors[] = [ 'code' => 'RULE_007', 'message_ar' => "خطأ في حساب الخصومات: المتوقع {$expected} JOD، المحسوب {$lineSumBeforeTax} JOD", 'message_en' => "Discount integrity error" ]; } return [ 'is_valid' => empty($errors), 'errors' => $errors ]; } }