mindee 3.5.0 → 3.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/CHANGELOG.md +63 -39
  2. package/package.json +3 -3
  3. package/src/api/{response.d.ts → documentResponse.d.ts} +2 -2
  4. package/src/api/endpoint.d.ts +32 -5
  5. package/src/api/endpoint.js +104 -34
  6. package/src/api/index.d.ts +3 -2
  7. package/src/api/index.js +5 -3
  8. package/src/api/predictResponse.d.ts +33 -0
  9. package/src/api/predictResponse.js +52 -0
  10. package/src/cli.js +210 -50
  11. package/src/client.d.ts +20 -4
  12. package/src/client.js +75 -23
  13. package/src/documents/custom/fields.js +1 -1
  14. package/src/documents/custom/lineitems.d.ts +41 -0
  15. package/src/documents/custom/lineitems.js +127 -0
  16. package/src/documents/document.d.ts +1 -1
  17. package/src/documents/documentConfig.d.ts +14 -6
  18. package/src/documents/documentConfig.js +59 -28
  19. package/src/documents/eu/licensePlate/licensePlateV1.js +4 -2
  20. package/src/documents/financialDocument/financialDocumentV0.d.ts +28 -0
  21. package/src/documents/financialDocument/financialDocumentV0.js +140 -0
  22. package/src/documents/financialDocument/financialDocumentV1.d.ts +44 -15
  23. package/src/documents/financialDocument/financialDocumentV1.js +154 -110
  24. package/src/documents/fr/bankAccountDetails/bankAccountDetailsV1.js +3 -2
  25. package/src/documents/fr/carteVitale/carteVitaleV1.js +2 -2
  26. package/src/documents/fr/idCard/idCardV1.js +10 -10
  27. package/src/documents/index.d.ts +5 -1
  28. package/src/documents/index.js +10 -2
  29. package/src/documents/invoice/invoiceV4.d.ts +3 -2
  30. package/src/documents/invoice/invoiceV4.js +85 -86
  31. package/src/documents/invoiceSplitter/invoiceSplitterV1.d.ts +3 -3
  32. package/src/documents/invoiceSplitter/invoiceSplitterV1.js +1 -0
  33. package/src/documents/mindeeVision/mindeeVisionV1.d.ts +8 -0
  34. package/src/documents/mindeeVision/mindeeVisionV1.js +29 -0
  35. package/src/documents/proofOfAddress/proofOfAddressV1.d.ts +24 -0
  36. package/src/documents/proofOfAddress/proofOfAddressV1.js +77 -0
  37. package/src/documents/receipt/receiptV3.d.ts +2 -2
  38. package/src/documents/receipt/receiptV3.js +1 -2
  39. package/src/documents/receipt/receiptV4.d.ts +3 -4
  40. package/src/documents/receipt/receiptV4.js +53 -65
  41. package/src/documents/{shipping_container → shippingContainer}/shippingContainerV1.js +2 -2
  42. package/src/fields/classification.d.ts +8 -0
  43. package/src/fields/classification.js +11 -0
  44. package/src/fields/field.d.ts +2 -2
  45. package/src/fields/field.js +1 -6
  46. package/src/fields/index.d.ts +1 -0
  47. package/src/fields/index.js +3 -1
  48. package/src/geometry.d.ts +18 -4
  49. package/src/geometry.js +40 -3
  50. package/src/index.d.ts +2 -2
  51. package/src/index.js +3 -1
  52. package/src/math/index.d.ts +1 -0
  53. package/src/math/index.js +5 -0
  54. package/src/math/precision.d.ts +1 -0
  55. package/src/math/precision.js +13 -0
  56. /package/src/api/{response.js → documentResponse.js} +0 -0
  57. /package/src/documents/{shipping_container → shippingContainer}/shippingContainerV1.d.ts +0 -0
@@ -0,0 +1,127 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getLineItems = exports.LineItems = exports.Line = void 0;
4
+ const handler_1 = require("../../errors/handler");
5
+ const errors_1 = require("../../errors");
6
+ const geometry_1 = require("../../geometry");
7
+ const fields_1 = require("./fields");
8
+ const math_1 = require("../../math");
9
+ class Line {
10
+ constructor(rowNumber, heightTolerance) {
11
+ this.rowNumber = rowNumber;
12
+ this.bbox = [1, 1, 0, 0];
13
+ this.fields = new Map();
14
+ this.heightTolerance = heightTolerance;
15
+ }
16
+ /**
17
+ * Extends the current bbox of the line with the bbox.
18
+ */
19
+ extendWithBbox(bbox) {
20
+ this.bbox = (0, geometry_1.mergeBbox)(this.bbox, bbox);
21
+ }
22
+ /**
23
+ * Extends the current bbox of the line with the polygon.
24
+ */
25
+ extendWith(polygon) {
26
+ this.bbox = (0, geometry_1.mergeBbox)(this.bbox, (0, geometry_1.getBbox)(polygon));
27
+ }
28
+ /**
29
+ * Check if the bbox fits the current line.
30
+ */
31
+ contains(bbox) {
32
+ return (0, math_1.precisionEquals)(this.bbox[1], bbox[1], this.heightTolerance);
33
+ }
34
+ updateField(name, fieldValue) {
35
+ if (!this.fields.has(name)) {
36
+ this.fields.set(name, fieldValue);
37
+ }
38
+ else {
39
+ const existingField = this.fields.get(name);
40
+ if (existingField === undefined) {
41
+ handler_1.errorHandler.throw(new errors_1.MindeeError(`The field '${name}' should exist but was not found.`));
42
+ return;
43
+ }
44
+ const mergedContent = existingField?.content === undefined
45
+ ? fieldValue.content
46
+ : existingField.content + " " + fieldValue.content;
47
+ const mergedBbox = (0, geometry_1.getBBoxForPolygons)([
48
+ existingField.polygon,
49
+ fieldValue.polygon,
50
+ ]);
51
+ this.fields.set(name, new fields_1.ListFieldValue({
52
+ content: mergedContent,
53
+ confidence: existingField.confidence * fieldValue.confidence,
54
+ polygon: (0, geometry_1.getBoundingBoxFromBBox)(mergedBbox),
55
+ }));
56
+ }
57
+ }
58
+ }
59
+ exports.Line = Line;
60
+ class LineItems {
61
+ constructor(lines) {
62
+ this.rows = [];
63
+ this.rows = lines;
64
+ }
65
+ }
66
+ exports.LineItems = LineItems;
67
+ function getLineItems(anchorNames, heigthLineTolerance, fieldNamesTargeted, fields) {
68
+ const fieldsToTransformIntoLines = new Map([...fields].filter(([k]) => fieldNamesTargeted.includes(k)));
69
+ const anchorName = findBestAnchor(anchorNames, fieldsToTransformIntoLines);
70
+ const lineItemsPrepared = prepare(anchorName, fieldsToTransformIntoLines, heigthLineTolerance);
71
+ lineItemsPrepared.rows.forEach((currentLine) => {
72
+ fieldsToTransformIntoLines.forEach((field, fieldName) => {
73
+ field.values.forEach((listFieldValue) => {
74
+ const minYCurrentValue = (0, geometry_1.getMinMaxY)(listFieldValue.polygon).min;
75
+ if (minYCurrentValue < currentLine.bbox[3] &&
76
+ minYCurrentValue >= currentLine.bbox[1]) {
77
+ currentLine.updateField(fieldName, listFieldValue);
78
+ }
79
+ });
80
+ });
81
+ });
82
+ return lineItemsPrepared;
83
+ }
84
+ exports.getLineItems = getLineItems;
85
+ function findBestAnchor(possibleAnchorNames, fields) {
86
+ let anchorName = "";
87
+ let anchorRows = 0;
88
+ possibleAnchorNames.forEach((fieldName) => {
89
+ const fieldValues = fields.get(fieldName)?.values;
90
+ if (fieldValues !== undefined && fieldValues.length > anchorRows) {
91
+ anchorRows = fieldValues.length;
92
+ anchorName = fieldName;
93
+ }
94
+ });
95
+ if (anchorName === "") {
96
+ handler_1.errorHandler.throw(new errors_1.MindeeError("No anchor was found."));
97
+ }
98
+ return anchorName;
99
+ }
100
+ function prepare(anchorName, fields, heigthLineTolerance) {
101
+ const lineItemsPrepared = [];
102
+ const anchorField = fields.get(anchorName);
103
+ if (anchorField === undefined || anchorField.values.length === 0) {
104
+ handler_1.errorHandler.throw(new errors_1.MindeeError("No lines have been detected."));
105
+ }
106
+ let currentLineNumber = 1;
107
+ let currentLine = new Line(currentLineNumber, heigthLineTolerance);
108
+ let currentValue = anchorField.values[0];
109
+ currentLine.extendWith(currentValue.polygon);
110
+ if (anchorField !== undefined) {
111
+ for (let index = 1; index < anchorField.values.length; index++) {
112
+ currentValue = anchorField.values[index];
113
+ const currentFieldBbox = (0, geometry_1.getBbox)(currentValue.polygon);
114
+ if (!currentLine.contains(currentFieldBbox)) {
115
+ lineItemsPrepared.push(currentLine);
116
+ currentLineNumber++;
117
+ currentLine = new Line(currentLineNumber, heigthLineTolerance);
118
+ }
119
+ currentLine.extendWithBbox(currentFieldBbox);
120
+ }
121
+ if (lineItemsPrepared.filter((line) => line.rowNumber === currentLineNumber)
122
+ .length === 0) {
123
+ lineItemsPrepared.push(currentLine);
124
+ }
125
+ }
126
+ return new LineItems(lineItemsPrepared);
127
+ }
@@ -1,7 +1,7 @@
1
1
  import { InputSource } from "../inputs";
2
2
  import { PositionField, FullText, OrientationField, StringDict } from "../fields";
3
3
  export type DocumentSig<DocType extends Document> = {
4
- new ({ prediction, orientation, extras, inputSource, pageId, fullText, documentType, }: DocumentConstructorProps): DocType;
4
+ new ({ prediction, orientation, extras, pageId, fullText, documentType, inputSource, }: DocumentConstructorProps): DocType;
5
5
  };
6
6
  export interface DocumentConstructorProps extends BaseDocumentConstructorProps {
7
7
  /** JSON parsed prediction from HTTP response */
@@ -1,6 +1,6 @@
1
1
  import { InputSource } from "../inputs";
2
- import { Response, Endpoint, predictResponse } from "../api";
3
- import { Document, FinancialDocumentV1, CustomV1, DocumentSig } from "./index";
2
+ import { Response, Endpoint, EndpointResponse, AsyncPredictResponse } from "../api";
3
+ import { Document, FinancialDocumentV0, CustomV1, DocumentSig } from "./index";
4
4
  import { PageOptions } from "../inputs";
5
5
  interface CustomDocConstructor {
6
6
  endpointName: string;
@@ -13,22 +13,30 @@ export declare class DocumentConfig<DocType extends Document> {
13
13
  readonly endpoints: Array<Endpoint>;
14
14
  readonly documentClass: DocumentSig<DocType>;
15
15
  constructor(documentClass: DocumentSig<DocType>, endpoints: Array<Endpoint>, documentType?: string);
16
- protected predictRequest(inputDoc: InputSource, includeWords: boolean, cropping: boolean): Promise<predictResponse>;
17
- buildResult(inputFile: InputSource, response: predictResponse): Response<DocType>;
18
16
  predict(params: {
19
17
  inputDoc: InputSource;
20
18
  includeWords: boolean;
21
19
  pageOptions?: PageOptions;
22
20
  cropper: boolean;
23
21
  }): Promise<Response<DocType>>;
22
+ asyncPredict(params: {
23
+ inputDoc: InputSource;
24
+ includeWords: boolean;
25
+ pageOptions?: PageOptions;
26
+ cropper: boolean;
27
+ }): Promise<AsyncPredictResponse<DocType>>;
28
+ getQueuedDocument(queuId: string): Promise<AsyncPredictResponse<DocType>>;
24
29
  cutDocPages(inputDoc: InputSource, pageOptions: PageOptions): Promise<void>;
30
+ protected predictRequest(inputDoc: InputSource, includeWords: boolean, cropping: boolean): Promise<EndpointResponse>;
31
+ protected handleError(response: EndpointResponse, statusCode?: number): void;
32
+ protected buildResult(response: EndpointResponse, inputFile?: InputSource): Response<DocType>;
25
33
  protected checkApiKeys(): void;
26
34
  }
27
35
  export declare class CustomDocConfig extends DocumentConfig<CustomV1> {
28
36
  constructor({ endpointName, accountName, version, apiKey, }: CustomDocConstructor);
29
37
  }
30
- export declare class FinancialDocV1Config extends DocumentConfig<FinancialDocumentV1> {
38
+ export declare class FinancialDocV0Config extends DocumentConfig<FinancialDocumentV0> {
31
39
  constructor(apiKey: string);
32
- protected predictRequest(inputDoc: InputSource, includeWords: boolean, cropping: boolean): Promise<predictResponse>;
40
+ protected predictRequest(inputDoc: InputSource, includeWords: boolean, cropping: boolean): Promise<EndpointResponse>;
33
41
  }
34
42
  export {};
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.FinancialDocV1Config = exports.CustomDocConfig = exports.DocumentConfig = void 0;
3
+ exports.FinancialDocV0Config = exports.CustomDocConfig = exports.DocumentConfig = void 0;
4
4
  const api_1 = require("../api");
5
5
  const index_1 = require("./index");
6
6
  const handler_1 = require("../errors/handler");
@@ -10,28 +10,6 @@ class DocumentConfig {
10
10
  this.endpoints = endpoints;
11
11
  this.documentClass = documentClass;
12
12
  }
13
- async predictRequest(inputDoc, includeWords, cropping) {
14
- return await this.endpoints[0].predictReqPost(inputDoc, includeWords, cropping);
15
- }
16
- buildResult(inputFile, response) {
17
- const statusCode = response.messageObj.statusCode;
18
- if (statusCode === undefined || statusCode > 201) {
19
- const errorMessage = JSON.stringify(response.data, null, 2);
20
- handler_1.errorHandler.throw(new Error(`${this.endpoints[0].urlName} API ${statusCode} HTTP error: ${errorMessage}`));
21
- return new api_1.Response(this.documentClass, {
22
- httpResponse: response,
23
- documentType: this.documentType,
24
- input: inputFile,
25
- error: true,
26
- });
27
- }
28
- return new api_1.Response(this.documentClass, {
29
- httpResponse: response,
30
- documentType: this.documentType,
31
- input: inputFile,
32
- error: false,
33
- });
34
- }
35
13
  async predict(params) {
36
14
  this.checkApiKeys();
37
15
  await params.inputDoc.init();
@@ -39,17 +17,70 @@ class DocumentConfig {
39
17
  await this.cutDocPages(params.inputDoc, params.pageOptions);
40
18
  }
41
19
  const response = await this.predictRequest(params.inputDoc, params.includeWords, params.cropper);
42
- return this.buildResult(params.inputDoc, response);
20
+ return this.buildResult(response, params.inputDoc);
21
+ }
22
+ async asyncPredict(params) {
23
+ this.checkApiKeys();
24
+ await params.inputDoc.init();
25
+ if (params.pageOptions !== undefined) {
26
+ await this.cutDocPages(params.inputDoc, params.pageOptions);
27
+ }
28
+ const response = await this.endpoints[0].predictAsyncReqPost(params.inputDoc, params.includeWords, params.cropper);
29
+ const statusCode = response.messageObj.statusCode;
30
+ if (statusCode === undefined || statusCode >= 202) {
31
+ this.handleError(response, statusCode);
32
+ }
33
+ return new api_1.AsyncPredictResponse(response.data);
34
+ }
35
+ async getQueuedDocument(queuId) {
36
+ this.checkApiKeys();
37
+ const queueResponse = await this.endpoints[0].documentQueueReqGet(queuId);
38
+ const queueStatusCode = queueResponse.messageObj.statusCode;
39
+ if (queueStatusCode === undefined ||
40
+ queueStatusCode < 200 ||
41
+ queueStatusCode > 302) {
42
+ this.handleError(queueResponse, queueStatusCode);
43
+ }
44
+ if (queueStatusCode === 302 &&
45
+ queueResponse.messageObj.headers.location !== undefined) {
46
+ const docId = queueResponse.messageObj.headers.location.split("/").pop();
47
+ if (docId !== undefined) {
48
+ const docResponse = await this.endpoints[0].documentGetReq(docId);
49
+ const document = this.buildResult(docResponse);
50
+ return new api_1.AsyncPredictResponse(docResponse.data, document);
51
+ }
52
+ }
53
+ return new api_1.AsyncPredictResponse(queueResponse.data);
43
54
  }
44
55
  async cutDocPages(inputDoc, pageOptions) {
45
56
  if (inputDoc.isPdf()) {
46
57
  await inputDoc.cutPdf(pageOptions);
47
58
  }
48
59
  }
60
+ // this is only a separate function because of financial docs
61
+ async predictRequest(inputDoc, includeWords, cropping) {
62
+ return await this.endpoints[0].predictReqPost(inputDoc, includeWords, cropping);
63
+ }
64
+ handleError(response, statusCode) {
65
+ const errorMessage = JSON.stringify(response.data, null, 2);
66
+ handler_1.errorHandler.throw(new Error(`${this.endpoints[0].urlName} API ${statusCode} HTTP error: ${errorMessage}`));
67
+ }
68
+ buildResult(response, inputFile) {
69
+ const statusCode = response.messageObj.statusCode;
70
+ if (statusCode === undefined || statusCode > 201) {
71
+ this.handleError(response, statusCode);
72
+ }
73
+ return new api_1.Response(this.documentClass, {
74
+ httpResponse: response,
75
+ documentType: this.documentType,
76
+ error: false,
77
+ input: inputFile,
78
+ });
79
+ }
49
80
  checkApiKeys() {
50
81
  this.endpoints.forEach((endpoint) => {
51
82
  if (!endpoint.apiKey) {
52
- throw new Error(`Missing API key for '${this.documentType}', check your Client configuration.
83
+ throw new Error(`Missing API key for '${endpoint.urlName} ${endpoint.version}', check your Client configuration.
53
84
  You can set this using the '${api_1.API_KEY_ENVVAR_NAME}' environment variable.\n`);
54
85
  }
55
86
  });
@@ -65,13 +96,13 @@ class CustomDocConfig extends DocumentConfig {
65
96
  }
66
97
  }
67
98
  exports.CustomDocConfig = CustomDocConfig;
68
- class FinancialDocV1Config extends DocumentConfig {
99
+ class FinancialDocV0Config extends DocumentConfig {
69
100
  constructor(apiKey) {
70
101
  const endpoints = [
71
102
  new api_1.StandardEndpoint("invoices", "3", apiKey),
72
103
  new api_1.StandardEndpoint("expense_receipts", "3", apiKey),
73
104
  ];
74
- super(index_1.FinancialDocumentV1, endpoints);
105
+ super(index_1.FinancialDocumentV0, endpoints);
75
106
  }
76
107
  async predictRequest(inputDoc, includeWords, cropping) {
77
108
  let endpoint;
@@ -84,4 +115,4 @@ class FinancialDocV1Config extends DocumentConfig {
84
115
  return await endpoint.predictReqPost(inputDoc, includeWords, cropping);
85
116
  }
86
117
  }
87
- exports.FinancialDocV1Config = FinancialDocV1Config;
118
+ exports.FinancialDocV0Config = FinancialDocV0Config;
@@ -19,9 +19,11 @@ class LicensePlateV1 extends document_1.Document {
19
19
  })));
20
20
  }
21
21
  toString() {
22
- const outStr = `----- EU License plate V1 -----
22
+ const outStr = `----- EU License Plate V1 -----
23
23
  Filename: ${this.filename}
24
- License plates: ${this.licensePlates.map((plate) => plate.value).join(", ")}
24
+ License Plates: ${this.licensePlates
25
+ .map((plate) => plate.value)
26
+ .join("\n ")}
25
27
  ----------------------
26
28
  `;
27
29
  return LicensePlateV1.cleanOutString(outStr);
@@ -0,0 +1,28 @@
1
+ import { Document, DocumentConstructorProps } from "../document";
2
+ import { TaxField, TextField, Amount, Locale, DateField as Date, CompanyRegistration } from "../../fields";
3
+ /**
4
+ * @deprecated You should use FinancialDocumentV1 instead.
5
+ */
6
+ export declare class FinancialDocumentV0 extends Document {
7
+ #private;
8
+ pageId: number | undefined;
9
+ locale: Locale;
10
+ totalIncl: Amount;
11
+ date: Date;
12
+ dueDate: Date;
13
+ category: TextField;
14
+ time: TextField;
15
+ taxes: TaxField[];
16
+ totalTax: Amount;
17
+ totalExcl: Amount;
18
+ supplier: TextField;
19
+ supplierAddress: TextField;
20
+ invoiceNumber: TextField;
21
+ companyRegistration: CompanyRegistration[];
22
+ customerName: TextField;
23
+ customerAddress: TextField;
24
+ paymentDetails: TextField[];
25
+ customerCompanyRegistration: CompanyRegistration[];
26
+ constructor({ prediction, orientation, extras, inputSource, fullText, pageId, }: DocumentConstructorProps);
27
+ toString(): string;
28
+ }
@@ -0,0 +1,140 @@
1
+ "use strict";
2
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
3
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
4
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
5
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
6
+ };
7
+ var _FinancialDocumentV0_instances, _FinancialDocumentV0_initFromApiPrediction, _FinancialDocumentV0_checklist, _FinancialDocumentV0_taxesMatchTotalIncl;
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.FinancialDocumentV0 = void 0;
10
+ const document_1 = require("../document");
11
+ const invoiceV3_1 = require("../invoice/invoiceV3");
12
+ const receiptV3_1 = require("../receipt/receiptV3");
13
+ const fields_1 = require("../../fields");
14
+ /**
15
+ * @deprecated You should use FinancialDocumentV1 instead.
16
+ */
17
+ class FinancialDocumentV0 extends document_1.Document {
18
+ constructor({ prediction, orientation = undefined, extras = undefined, inputSource = undefined, fullText = undefined, pageId = undefined, }) {
19
+ super({
20
+ inputSource: inputSource,
21
+ pageId: pageId,
22
+ orientation: orientation,
23
+ fullText: fullText,
24
+ extras: extras,
25
+ });
26
+ _FinancialDocumentV0_instances.add(this);
27
+ this.taxes = [];
28
+ this.companyRegistration = [];
29
+ this.paymentDetails = [];
30
+ this.customerCompanyRegistration = [];
31
+ __classPrivateFieldGet(this, _FinancialDocumentV0_instances, "m", _FinancialDocumentV0_initFromApiPrediction).call(this, prediction, inputSource, pageId, orientation, extras);
32
+ __classPrivateFieldGet(this, _FinancialDocumentV0_instances, "m", _FinancialDocumentV0_checklist).call(this);
33
+ }
34
+ toString() {
35
+ const outStr = `-----Financial document-----
36
+ Filename: ${this.filename}
37
+ Total amount: ${this.totalIncl.value}
38
+ Date: ${this.date.value}
39
+ Supplier: ${this.supplier.value}
40
+ Total taxes: ${this.totalTax.value}
41
+ ----------------------
42
+ `;
43
+ return FinancialDocumentV0.cleanOutString(outStr);
44
+ }
45
+ }
46
+ exports.FinancialDocumentV0 = FinancialDocumentV0;
47
+ _FinancialDocumentV0_instances = new WeakSet(), _FinancialDocumentV0_initFromApiPrediction = function _FinancialDocumentV0_initFromApiPrediction(prediction, inputFile, pageNumber, orientation, extras) {
48
+ if (Object.keys(prediction).includes("invoice_number")) {
49
+ const invoice = new invoiceV3_1.InvoiceV3({
50
+ prediction: prediction,
51
+ inputSource: inputFile,
52
+ pageId: pageNumber,
53
+ orientation: orientation,
54
+ extras: extras,
55
+ });
56
+ this.locale = invoice.locale;
57
+ this.totalIncl = invoice.totalIncl;
58
+ this.totalExcl = invoice.totalExcl;
59
+ this.date = invoice.date;
60
+ this.invoiceNumber = invoice.invoiceNumber;
61
+ this.dueDate = invoice.dueDate;
62
+ this.taxes = invoice.taxes;
63
+ this.supplier = invoice.supplier;
64
+ this.supplierAddress = invoice.supplierAddress;
65
+ this.paymentDetails = invoice.paymentDetails;
66
+ this.companyRegistration = invoice.customerCompanyRegistration;
67
+ this.orientation = invoice.orientation;
68
+ this.totalTax = invoice.totalTax;
69
+ this.time = new fields_1.TextField({
70
+ prediction: { value: undefined, confidence: 0.0 },
71
+ });
72
+ this.customerName = invoice.customerName;
73
+ this.customerAddress = invoice.customerAddress;
74
+ this.customerCompanyRegistration = invoice.customerCompanyRegistration;
75
+ }
76
+ else {
77
+ const receipt = new receiptV3_1.ReceiptV3({
78
+ prediction: prediction,
79
+ inputSource: inputFile,
80
+ pageId: pageNumber,
81
+ orientation: orientation,
82
+ extras: extras,
83
+ });
84
+ this.orientation = receipt.orientation;
85
+ this.date = receipt.date;
86
+ this.dueDate = receipt.date;
87
+ this.taxes = receipt.taxes;
88
+ this.locale = receipt.locale;
89
+ this.totalIncl = receipt.totalIncl;
90
+ this.totalExcl = receipt.totalExcl;
91
+ this.supplier = receipt.merchantName;
92
+ this.supplierAddress = new fields_1.TextField({
93
+ prediction: { value: undefined, confidence: 0.0 },
94
+ });
95
+ this.time = receipt.time;
96
+ this.totalTax = receipt.totalTax;
97
+ this.invoiceNumber = new fields_1.TextField({
98
+ prediction: { value: undefined, confidence: 0.0 },
99
+ });
100
+ this.customerName = new fields_1.TextField({
101
+ prediction: { value: undefined, confidence: 0.0 },
102
+ });
103
+ this.customerAddress = new fields_1.TextField({
104
+ prediction: { value: undefined, confidence: 0.0 },
105
+ });
106
+ }
107
+ }, _FinancialDocumentV0_checklist = function _FinancialDocumentV0_checklist() {
108
+ this.checklist = {
109
+ taxesMatchTotalIncl: __classPrivateFieldGet(this, _FinancialDocumentV0_instances, "m", _FinancialDocumentV0_taxesMatchTotalIncl).call(this),
110
+ };
111
+ }, _FinancialDocumentV0_taxesMatchTotalIncl = function _FinancialDocumentV0_taxesMatchTotalIncl() {
112
+ // Check taxes and total include exist
113
+ if (this.taxes.length === 0 || this.totalIncl.value === undefined)
114
+ return false;
115
+ // Reconstruct totalIncl from taxes
116
+ let totalVat = 0;
117
+ let reconstructedTotal = 0;
118
+ this.taxes.forEach((tax) => {
119
+ if (tax.value === undefined || !tax.rate)
120
+ return false;
121
+ totalVat += tax.value;
122
+ reconstructedTotal += tax.value + (100 * tax.value) / tax.rate;
123
+ });
124
+ // Sanity check
125
+ if (totalVat <= 0)
126
+ return false;
127
+ // Crate epsilon
128
+ const eps = 1 / (100 * totalVat);
129
+ if (this.totalIncl.value * (1 - eps) - 0.02 <= reconstructedTotal &&
130
+ reconstructedTotal <= this.totalIncl.value * (1 + eps) + 0.02) {
131
+ this.taxes = this.taxes.map((tax) => ({
132
+ ...tax,
133
+ confidence: 1.0,
134
+ }));
135
+ this.totalTax.confidence = 1.0;
136
+ this.totalIncl.confidence = 1.0;
137
+ return true;
138
+ }
139
+ return false;
140
+ };
@@ -1,25 +1,54 @@
1
1
  import { Document, DocumentConstructorProps } from "../document";
2
- import { TaxField, TextField, Amount, Locale, DateField as Date, CompanyRegistration } from "../../fields";
2
+ import { TaxField, PaymentDetails, Locale, Amount, TextField, DateField, CompanyRegistration, BaseField } from "../../fields";
3
+ import { InvoiceLineItem } from "../invoice/invoiceLineItem";
4
+ /**
5
+ * Financial Document.
6
+ */
3
7
  export declare class FinancialDocumentV1 extends Document {
4
- #private;
5
- pageId: number | undefined;
8
+ /** Locale information. */
6
9
  locale: Locale;
7
- totalIncl: Amount;
8
- date: Date;
9
- dueDate: Date;
10
- category: TextField;
11
- time: TextField;
12
- taxes: TaxField[];
13
- totalTax: Amount;
14
- totalExcl: Amount;
15
- supplier: TextField;
10
+ /** The nature of the document. */
11
+ documentType: BaseField;
12
+ /** List of Reference numbers including PO number. */
13
+ referenceNumbers: TextField[];
14
+ /** The creation date of the invoice or the purchase date. */
15
+ date: DateField;
16
+ /** The due date of the invoice. */
17
+ dueDate: DateField;
18
+ /** The supplier name. */
19
+ supplierName: TextField;
20
+ /** The supplier address. */
16
21
  supplierAddress: TextField;
22
+ /** The payment information. */
23
+ supplierPaymentDetails: PaymentDetails[];
24
+ /** The supplier company registration information. */
25
+ supplierCompanyRegistrations: CompanyRegistration[];
26
+ /** The invoice number. */
17
27
  invoiceNumber: TextField;
18
- companyRegistration: CompanyRegistration[];
28
+ /** The name of the customer. */
19
29
  customerName: TextField;
30
+ /** The address of the customer. */
20
31
  customerAddress: TextField;
21
- paymentDetails: TextField[];
22
- customerCompanyRegistration: CompanyRegistration[];
32
+ /** The company registration information for the customer. */
33
+ customerCompanyRegistrations: CompanyRegistration[];
34
+ /** The list of the taxes. */
35
+ taxes: TaxField[];
36
+ /** Line items details. */
37
+ lineItems: InvoiceLineItem[];
38
+ /** The receipt category among predefined classes. */
39
+ category: TextField;
40
+ /** The receipt sub-category among predefined classes. */
41
+ subCategory: TextField;
42
+ /** Time as seen on the receipt in HH:MM format. */
43
+ time: TextField;
44
+ /** Total amount of tip and gratuity. */
45
+ tip: Amount;
46
+ /** total spent including taxes, discounts, fees, tips, and gratuity. */
47
+ totalAmount: Amount;
48
+ /** Total amount of the purchase excluding taxes. */
49
+ totalNet: Amount;
50
+ /** Total tax amount of the purchase. */
51
+ totalTax: Amount;
23
52
  constructor({ prediction, orientation, extras, inputSource, fullText, pageId, }: DocumentConstructorProps);
24
53
  toString(): string;
25
54
  }