🚀 Multi-invoice extraction and detailed validation feedback
This commit is contained in:
@@ -28,7 +28,7 @@ export class GeminiExtractorService {
|
||||
}
|
||||
|
||||
/**
|
||||
* استخراج البيانات من صورة الفاتورة
|
||||
* استخراج البيانات من صورة الفاتورة (يدعم فواتير متعددة في ملف واحد)
|
||||
*/
|
||||
async extractInvoiceData(filePath: string, storageRoot: string): Promise<any> {
|
||||
try {
|
||||
@@ -36,40 +36,50 @@ export class GeminiExtractorService {
|
||||
const fileData = fs.readFileSync(fullPath);
|
||||
|
||||
const prompt = `
|
||||
You are a Jordanian tax expert. Extract all details from this invoice image for the Jordan National Invoicing System (JoFotara / JoInvoice).
|
||||
The output MUST be a strict JSON object following this schema:
|
||||
You are a Jordanian tax expert. Extract all details from this file (image or PDF).
|
||||
The file may contain ONE or MULTIPLE distinct invoices.
|
||||
Extract EACH invoice separately.
|
||||
|
||||
The output MUST be a strict JSON object with this schema:
|
||||
{
|
||||
"invoice_number": "string",
|
||||
"invoice_date": "YYYY-MM-DD",
|
||||
"invoice_type": "cash" | "credit",
|
||||
"supplier_name": "string",
|
||||
"supplier_tin": "string (10 digits)",
|
||||
"buyer_name": "string (optional)",
|
||||
"buyer_tin": "string (optional)",
|
||||
"subtotal": number (before discount and tax),
|
||||
"discount_total": number (total discount),
|
||||
"tax_amount": number (total tax),
|
||||
"grand_total": number (final amount),
|
||||
"currency_code": "JOD",
|
||||
"lines": [
|
||||
"invoices": [
|
||||
{
|
||||
"line_number": number,
|
||||
"description": "string",
|
||||
"quantity": number,
|
||||
"unit_price": number,
|
||||
"discount": number,
|
||||
"tax_rate": number (e.g. 0.16 for 16%),
|
||||
"line_total": number (quantity * unit_price - discount)
|
||||
"invoice_number": "string",
|
||||
"invoice_date": "YYYY-MM-DD",
|
||||
"invoice_type": "cash" | "credit",
|
||||
"invoice_category": "standard" | "simplified",
|
||||
"supplier_name": "string",
|
||||
"supplier_tin": "string (10 digits)",
|
||||
"buyer_name": "string (optional)",
|
||||
"buyer_tin": "string (optional)",
|
||||
"subtotal": number (before discount and tax),
|
||||
"discount_total": number (total discount),
|
||||
"tax_amount": number (total tax),
|
||||
"grand_total": number (final amount),
|
||||
"currency_code": "JOD",
|
||||
"lines": [
|
||||
{
|
||||
"line_number": number,
|
||||
"description": "string",
|
||||
"quantity": number,
|
||||
"unit_price": number,
|
||||
"discount": number,
|
||||
"tax_rate": number (e.g. 0.16 for 16%),
|
||||
"line_total": number (quantity * unit_price - discount)
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
Pay close attention to Jordanian Tax Rules:
|
||||
- Standard Rate: 0.16 (16%)
|
||||
- Reduced Rate: 0.04 (4%)
|
||||
- Zero Rate: 0.00 (0%)
|
||||
- Exempt: null or 0 with explanation.
|
||||
|
||||
JoFotara Specific Rules:
|
||||
- invoice_category: "simplified" if the buyer is a regular person (no TIN), "standard" if B2B (buyer has TIN).
|
||||
- Prices in Jordan (JOD) often have 3 decimal places (e.g. 2.800).
|
||||
- Standard VAT Rate: 0.16 (16%)
|
||||
- The formula MUST hold: Subtotal - Discount + Tax = Grand Total.
|
||||
Return ONLY the JSON. No markdown formatting. If a field is missing, return null.
|
||||
- If multiple invoices are in the PDF, ensure the "invoices" array contains all of them.
|
||||
|
||||
Return ONLY the JSON. No markdown formatting.
|
||||
`;
|
||||
|
||||
// Detect MIME type based on extension
|
||||
@@ -93,9 +103,10 @@ export class GeminiExtractorService {
|
||||
// Clean up markdown if any
|
||||
const cleanedJson = responseText.replace(/```json|```/g, '').trim();
|
||||
|
||||
return JSON.parse(cleanedJson);
|
||||
const data = JSON.parse(cleanedJson);
|
||||
return data.invoices || [];
|
||||
} catch (error: any) {
|
||||
this.logger.error(`AI Extraction failed: ${error.message}`);
|
||||
this.logger.error(\`AI Extraction failed: \${error.message}\`);
|
||||
throw new InternalServerErrorException('AI Extraction failed');
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user