InvoicePosting::class, 'credit_note' => CreditNotePosting::class, 'purchase_invoice' => PurchaseInvoicePosting::class, 'supplier_credit_note' => SupplierCreditNotePosting::class, 'receipt' => ReceiptPosting::class, 'payment' => PaymentPosting::class, 'purchase_order' => PurchasePosting::class, ]; $is_asset_source = AssetPosting::isAssetSource($doc_type); if ((!isset($posting_map[$doc_type]) && !$is_asset_source) || $id <= 0) { $answer['message'] = 'Invalid doc_type or id.'; exit(json_encode($answer)); } try { if ($is_asset_source) { // Asset Management entries carry their own reference and "[Asset Mgmt]" description. $built = (new AssetPosting($pdo2, $company_id))->build($doc_type, $id); $meta = [ 'journal_date' => $built['doc_date'], 'reference' => $built['reference'], 'description' => $built['description'], ]; } else { $posting_class = $posting_map[$doc_type]; $posting = new $posting_class($pdo2, $company_id); $built = $posting->build($id, $formula_id); $meta = ['journal_date' => $built['doc_date'] ?? null]; } $guard = new PostingWindowGuard($pdo1, $company_id); $gl = new GlManager($pdo2, $company_id, $guard); $pdo2->beginTransaction(); $existing = $gl->getBySource($doc_type, $id); if ($existing) { $gl->replace($doc_type, $id, $built['formula_id'], $built['period'], $built['lines'], $meta); } else { $gl->post($doc_type, $id, $built['formula_id'], $built['period'], $built['lines'], $meta); } $pdo2->commit(); $answer['success'] = 1; $answer['message'] = $existing ? 'GL entry replaced.' : 'GL entry posted.'; $has_revenue = false; $has_expense = false; foreach ($built['lines'] as $line) { $code = (int)($line['account_code'] ?? 0); if ($code >= 4000 && $code < 5000) $has_revenue = true; if ($code >= 5000) $has_expense = true; } notify_node('gl_posted', [ 'doc_type' => $doc_type, 'id' => $id, 'action' => $existing ? 'replaced' : 'posted', 'has_revenue' => $has_revenue, 'has_expense' => $has_expense, ], $company_id); } catch (Exception $e) { if ($pdo2->inTransaction()) $pdo2->rollBack(); $answer['message'] = $e->getMessage(); } exit(json_encode($answer));