@bisondesk/documents-sdk 1.0.513 → 1.0.515

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.
@@ -4,16 +4,13 @@ import { FinanceDocumentV1 } from '../types/legacy.js';
4
4
  export declare const documentGoesToAccounting: (doc: FinanceDocumentV2 | DocumentDraft<FinanceDocumentV2> | FinanceDocumentGenerateRequest | FinanceDocumentV1) => boolean;
5
5
  export declare const getAccountingDescription: (doc: FinanceDocumentV2) => string;
6
6
  export declare const getTotalExcl: <T extends FinanceDocument["lines"]>(lines: T, unitPrice: (line: T[0], index: number) => any) => Decimal;
7
- export declare const getTotalVat: <T extends FinanceDocument["lines"], L = T[0]>(lines: T, unitPrice: (doc: L, index: number) => any, vatCoefficient: (doc: L, index: number) => any) => Decimal;
7
+ export declare const getTotalVat: <T extends FinanceDocument["lines"], L = T[0]>(currency: string, lines: T, unitPrice: (doc: L, index: number) => any, vatCoefficient: (doc: L, index: number) => any) => Decimal;
8
8
  export declare const getDocumentTotals: (doc: FinanceDocument | DocumentDraft<FinanceDocumentV2> | NewDocumentDraft<FinanceDocumentV2> | FinanceDocumentGenerateRequest) => {
9
9
  totalExcl: Decimal;
10
10
  totalVat: Decimal;
11
11
  subTotal: Decimal;
12
12
  };
13
- export declare const getRoundedDocumentTotal: (doc: FinanceDocument | DocumentDraft<FinanceDocumentV2> | NewDocumentDraft<FinanceDocumentV2> | FinanceDocumentGenerateRequest, currencyCode?: string, foreignCurrency?: {
14
- currencyCode: string;
15
- exchangeRate: string;
16
- }) => {
13
+ export declare const getRoundedDocumentTotal: (doc: FinanceDocument | DocumentDraft<FinanceDocumentV2> | NewDocumentDraft<FinanceDocumentV2> | FinanceDocumentGenerateRequest) => {
17
14
  amount: string;
18
15
  amountExcl: string;
19
16
  vatAmount: string;
@@ -26,6 +23,15 @@ export declare const getRoundedDocumentTotal: (doc: FinanceDocument | DocumentDr
26
23
  exchangeRate: string;
27
24
  } | undefined;
28
25
  };
26
+ export declare const getRoundedLinesTotals: (currency: string, lines: {
27
+ quantity: string;
28
+ unitPriceExcl: string;
29
+ vatPercentage: string;
30
+ }[], rate?: string) => {
31
+ totalWithoutVat: Decimal;
32
+ vatTotal: Decimal;
33
+ total: Decimal;
34
+ };
29
35
  export declare const getLineAmounts: (unitPriceExcl: string, quantity: string, vatRate: string) => {
30
36
  amount: string;
31
37
  amountExcl: string;
@@ -1 +1 @@
1
- {"version":3,"file":"finance.d.ts","sourceRoot":"/","sources":["utils/finance.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAGrC,OAAO,EAEL,aAAa,EACb,eAAe,EACf,8BAA8B,EAG9B,iBAAiB,EAGjB,gBAAgB,EACjB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,iBAAiB,EAAiB,MAAM,oBAAoB,CAAC;AAEtE,eAAO,MAAM,wBAAwB,QAE/B,iBAAiB,GACjB,aAAa,CAAC,iBAAiB,CAAC,GAChC,8BAA8B,GAC9B,iBAAiB,KACpB,OAOF,CAAC;AAEF,eAAO,MAAM,wBAAwB,QAAS,iBAAiB,KAAG,MAoCjE,CAAC;AAEF,eAAO,MAAM,YAAY,GAAI,CAAC,SAAS,eAAe,CAAC,OAAO,CAAC,SACtD,CAAC,aACG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,GAAG,YAK9C,CAAC;AAEF,eAAO,MAAM,WAAW,GAAI,CAAC,SAAS,eAAe,CAAC,OAAO,CAAC,EAAE,CAAC,gBACxD,CAAC,aACG,CAAC,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,GAAG,kBACzB,CAAC,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,GAAG,YAW/C,CAAC;AAEF,eAAO,MAAM,iBAAiB,QAExB,eAAe,GACf,aAAa,CAAC,iBAAiB,CAAC,GAChC,gBAAgB,CAAC,iBAAiB,CAAC,GACnC,8BAA8B;;;;CA0BnC,CAAC;AAEF,eAAO,MAAM,uBAAuB,QAE9B,eAAe,GACf,aAAa,CAAC,iBAAiB,CAAC,GAChC,gBAAgB,CAAC,iBAAiB,CAAC,GACnC,8BAA8B,iBACnB,MAAM,oBACH;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;CACtB;;;;;;;;;;;;CAuBF,CAAC;AAKF,eAAO,MAAM,cAAc,kBAAmB,MAAM,YAAY,MAAM,WAAW,MAAM;;;;;CAYtF,CAAC;AAEF,eAAO,MAAM,sBAAsB,QAAS,eAAe,YACC,CAAC;AAK7D,eAAO,MAAM,4BAA4B,QAClC,eAAe,YACV,MAAM,KACf,eAkCF,CAAC"}
1
+ {"version":3,"file":"finance.d.ts","sourceRoot":"/","sources":["utils/finance.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAGrC,OAAO,EAEL,aAAa,EACb,eAAe,EACf,8BAA8B,EAG9B,iBAAiB,EAIjB,gBAAgB,EACjB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,iBAAiB,EAAiB,MAAM,oBAAoB,CAAC;AAEtE,eAAO,MAAM,wBAAwB,QAE/B,iBAAiB,GACjB,aAAa,CAAC,iBAAiB,CAAC,GAChC,8BAA8B,GAC9B,iBAAiB,KACpB,OAOF,CAAC;AAEF,eAAO,MAAM,wBAAwB,QAAS,iBAAiB,KAAG,MAoCjE,CAAC;AAEF,eAAO,MAAM,YAAY,GAAI,CAAC,SAAS,eAAe,CAAC,OAAO,CAAC,SACtD,CAAC,aACG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,GAAG,YAK9C,CAAC;AAEF,eAAO,MAAM,WAAW,GAAI,CAAC,SAAS,eAAe,CAAC,OAAO,CAAC,EAAE,CAAC,mBACrD,MAAM,SACT,CAAC,aACG,CAAC,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,GAAG,kBACzB,CAAC,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,GAAG,YAY/C,CAAC;AAEF,eAAO,MAAM,iBAAiB,QAExB,eAAe,GACf,aAAa,CAAC,iBAAiB,CAAC,GAChC,gBAAgB,CAAC,iBAAiB,CAAC,GACnC,8BAA8B;;;;CA4BnC,CAAC;AAEF,eAAO,MAAM,uBAAuB,QAE9B,eAAe,GACf,aAAa,CAAC,iBAAiB,CAAC,GAChC,gBAAgB,CAAC,iBAAiB,CAAC,GACnC,8BAA8B;;;;;;;;;;;;CAgCnC,CAAC;AAEF,eAAO,MAAM,qBAAqB,aACtB,MAAM,SACT;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE,EAAE;;;;CAmB5E,CAAC;AAKF,eAAO,MAAM,cAAc,kBAAmB,MAAM,YAAY,MAAM,WAAW,MAAM;;;;;CAYtF,CAAC;AAEF,eAAO,MAAM,sBAAsB,QAAS,eAAe,YACC,CAAC;AAK7D,eAAO,MAAM,4BAA4B,QAClC,eAAe,YACV,MAAM,KACf,eAkCF,CAAC"}
@@ -3,7 +3,7 @@ import { roundMoney } from '@bisondesk/commons-sdk/money';
3
3
  import { Decimal } from 'decimal.js';
4
4
  import { uniqBy } from 'lodash-es';
5
5
  import { GENERATING_PLACEHOLDER_ATTACHMENT } from '../constants/index.js';
6
- import { FinanceDocumentSubtype, isFinanceDocumentV1, isFinanceDocumentV2, } from '../types/documents.js';
6
+ import { FinanceDocumentSubtype, isFinanceDocumentDraft, isFinanceDocumentV1, isFinanceDocumentV2, } from '../types/documents.js';
7
7
  export const documentGoesToAccounting = (doc) => {
8
8
  return (!!doc.subtype &&
9
9
  [FinanceDocumentSubtype.Invoice, FinanceDocumentSubtype.CreditNote].includes(doc.subtype));
@@ -38,24 +38,26 @@ export const getTotalExcl = (lines, unitPrice) => {
38
38
  ? new Decimal(0)
39
39
  : Decimal.sum(...lines.map((line, i) => Decimal.mul(line.quantity, unitPrice(line, i))));
40
40
  };
41
- export const getTotalVat = (lines, unitPrice, vatCoefficient) => {
41
+ export const getTotalVat = (currency, lines, unitPrice, vatCoefficient) => {
42
42
  return lines.length === 0
43
43
  ? new Decimal(0)
44
- : roundMoney(Decimal.sum(...lines.map((line, i) => Decimal.mul(line.quantity, unitPrice(line, i)).mul(vatCoefficient(line, i)))));
44
+ : roundMoney(currency, Decimal.sum(...lines.map((line, i) => Decimal.mul(line.quantity, unitPrice(line, i)).mul(vatCoefficient(line, i)))));
45
45
  };
46
46
  export const getDocumentTotals = (doc) => {
47
47
  let totalVat;
48
48
  let totalExcl;
49
49
  if (isFinanceDocumentV1(doc)) {
50
+ const v1Currency = 'EUR';
50
51
  const lines = doc.lines;
51
52
  const getUnitPriceExclusive = (line) => line.unitPriceExclusive;
52
- totalVat = getTotalVat(lines, getUnitPriceExclusive, (line) => line.vatCoefficient);
53
+ totalVat = getTotalVat(v1Currency, lines, getUnitPriceExclusive, (line) => line.vatCoefficient);
53
54
  totalExcl = getTotalExcl(lines, getUnitPriceExclusive);
54
55
  }
55
56
  else {
57
+ const currency = doc.total.currencyCode;
56
58
  const lines = doc.lines ?? [];
57
59
  const getUnitPriceExcl = (line) => line.unitPriceExcl;
58
- totalVat = getTotalVat(lines, getUnitPriceExcl, (line) => new Decimal(line.vatPercentage).div(100));
60
+ totalVat = getTotalVat(currency, lines, getUnitPriceExcl, (line) => new Decimal(line.vatPercentage).div(100));
59
61
  totalExcl = getTotalExcl(lines, getUnitPriceExcl);
60
62
  }
61
63
  return {
@@ -64,28 +66,50 @@ export const getDocumentTotals = (doc) => {
64
66
  subTotal: totalExcl.add(totalVat),
65
67
  };
66
68
  };
67
- export const getRoundedDocumentTotal = (doc, currencyCode, foreignCurrency) => {
69
+ export const getRoundedDocumentTotal = (doc) => {
70
+ let total;
71
+ if (isFinanceDocumentV2(doc) || isFinanceDocumentDraft(doc)) {
72
+ total = doc.total;
73
+ }
74
+ const currencyCode = total?.currencyCode ?? 'EUR';
75
+ const foreignCurrency = total?.foreign;
68
76
  const { subTotal, totalExcl, totalVat } = getDocumentTotals(doc);
69
77
  const rate = foreignCurrency?.exchangeRate ?? '1';
70
78
  const subTotalForeign = subTotal.div(rate).toString();
71
79
  const totalExclForeign = totalExcl.div(rate).toString();
72
80
  const totalVatForeign = totalVat.div(rate).toString();
73
81
  return {
74
- amount: roundMoney(subTotal).toString(),
75
- amountExcl: roundMoney(totalExcl).toString(),
76
- vatAmount: roundMoney(totalVat).toString(),
77
- currencyCode: currencyCode ?? 'EUR',
82
+ amount: roundMoney(currencyCode, subTotal).toString(),
83
+ amountExcl: roundMoney(currencyCode, totalExcl).toString(),
84
+ vatAmount: roundMoney(currencyCode, totalVat).toString(),
85
+ currencyCode: currencyCode,
78
86
  foreign: foreignCurrency
79
87
  ? {
80
- amount: roundMoney(subTotalForeign).toString(),
81
- amountExcl: roundMoney(totalExclForeign).toString(),
82
- vatAmount: roundMoney(totalVatForeign).toString(),
88
+ amount: roundMoney(foreignCurrency.currencyCode, subTotalForeign).toString(),
89
+ amountExcl: roundMoney(foreignCurrency.currencyCode, totalExclForeign).toString(),
90
+ vatAmount: roundMoney(foreignCurrency.currencyCode, totalVatForeign).toString(),
83
91
  currencyCode: foreignCurrency.currencyCode,
84
92
  exchangeRate: foreignCurrency.exchangeRate,
85
93
  }
86
94
  : undefined,
87
95
  };
88
96
  };
97
+ export const getRoundedLinesTotals = (currency, lines, rate = '1') => {
98
+ let totalWithoutVat = new Decimal('0');
99
+ let vatTotal = new Decimal('0');
100
+ for (const line of lines) {
101
+ const lineTotal = new Decimal(line.unitPriceExcl).times(new Decimal(line.quantity));
102
+ totalWithoutVat = totalWithoutVat.add(lineTotal);
103
+ vatTotal = vatTotal.add(lineTotal.mul(line.vatPercentage).div(100));
104
+ }
105
+ totalWithoutVat = totalWithoutVat.div(rate);
106
+ vatTotal = vatTotal.div(rate);
107
+ return {
108
+ totalWithoutVat: roundMoney(currency, totalWithoutVat),
109
+ vatTotal: roundMoney(currency, vatTotal),
110
+ total: roundMoney(currency, vatTotal.add(totalWithoutVat)),
111
+ };
112
+ };
89
113
  const getAmountExcl = (unitPriceExcl, quantity) => new Decimal(unitPriceExcl).times(new Decimal(quantity));
90
114
  export const getLineAmounts = (unitPriceExcl, quantity, vatRate) => {
91
115
  const amountExcl = getAmountExcl(unitPriceExcl, quantity);
@@ -1 +1 @@
1
- {"version":3,"file":"finance.js","sourceRoot":"/","sources":["utils/finance.ts"],"names":[],"mappings":"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","sourcesContent":["import { BusinessEntityIds } from '@bisondesk/commons-sdk/constants';\nimport { roundMoney } from '@bisondesk/commons-sdk/money';\nimport { Decimal } from 'decimal.js';\nimport { uniqBy } from 'lodash-es';\nimport { GENERATING_PLACEHOLDER_ATTACHMENT } from '../constants/index.js';\nimport {\n Association,\n DocumentDraft,\n FinanceDocument,\n FinanceDocumentGenerateRequest,\n FinanceDocumentLine,\n FinanceDocumentSubtype,\n FinanceDocumentV2,\n isFinanceDocumentV1,\n isFinanceDocumentV2,\n NewDocumentDraft,\n} from '../types/documents.js';\nimport { FinanceDocumentV1, FinanceLineV1 } from '../types/legacy.js';\n\nexport const documentGoesToAccounting = (\n doc:\n | FinanceDocumentV2\n | DocumentDraft<FinanceDocumentV2>\n | FinanceDocumentGenerateRequest\n | FinanceDocumentV1\n): boolean => {\n return (\n !!doc.subtype &&\n [FinanceDocumentSubtype.Invoice, FinanceDocumentSubtype.CreditNote].includes(\n doc.subtype as FinanceDocumentSubtype\n )\n );\n};\n\nexport const getAccountingDescription = (doc: FinanceDocumentV2): string => {\n if (!!doc.accountingDescription) {\n return doc.accountingDescription;\n }\n\n const associations = doc.lines\n ?.flatMap((line) => line.associations ?? [])\n .filter(Boolean) as Association[];\n\n // In the UI the user can only select one vehicle associations\n const equivalentEntityIds = {\n [BusinessEntityIds.ExternalVehicleSale]: BusinessEntityIds.Vehicles,\n };\n\n const uniqueAssociations = uniqBy(\n associations,\n (a) => `${equivalentEntityIds[a.businessEntityId] ?? a.businessEntityId}_${a.recordId}`\n );\n\n if (uniqueAssociations.length !== 1) {\n return doc.reference;\n }\n\n const firstAssociation = associations[0];\n if (\n [\n BusinessEntityIds.Vehicles,\n BusinessEntityIds.Opportunities,\n BusinessEntityIds.ExternalVehicleSale,\n ].includes(firstAssociation.businessEntityId) &&\n firstAssociation.tags != null\n ) {\n return `${firstAssociation.tags?.slice(0, 3).join(' ')} ${doc.reference}`.trim();\n }\n\n return doc.reference;\n};\n\nexport const getTotalExcl = <T extends FinanceDocument['lines']>(\n lines: T,\n unitPrice: (line: T[0], index: number) => any\n) => {\n return lines.length === 0\n ? new Decimal(0)\n : Decimal.sum(...lines.map((line, i) => Decimal.mul(line.quantity, unitPrice(line, i))));\n};\n\nexport const getTotalVat = <T extends FinanceDocument['lines'], L = T[0]>(\n lines: T,\n unitPrice: (doc: L, index: number) => any,\n vatCoefficient: (doc: L, index: number) => any\n) => {\n return lines.length === 0\n ? new Decimal(0)\n : roundMoney(\n Decimal.sum(\n ...lines.map((line, i) =>\n Decimal.mul(line.quantity, unitPrice(line, i)).mul(vatCoefficient(line, i))\n )\n )\n );\n};\n\nexport const getDocumentTotals = (\n doc:\n | FinanceDocument\n | DocumentDraft<FinanceDocumentV2>\n | NewDocumentDraft<FinanceDocumentV2>\n | FinanceDocumentGenerateRequest\n) => {\n let totalVat: Decimal;\n let totalExcl: Decimal;\n\n if (isFinanceDocumentV1(doc as FinanceDocumentV1)) {\n const lines = (doc as FinanceDocumentV1).lines;\n const getUnitPriceExclusive = (line: FinanceLineV1) => line.unitPriceExclusive;\n\n totalVat = getTotalVat(lines, getUnitPriceExclusive, (line) => line.vatCoefficient);\n totalExcl = getTotalExcl(lines, getUnitPriceExclusive);\n } else {\n const lines = (doc as FinanceDocumentV2).lines ?? [];\n const getUnitPriceExcl = (line: FinanceDocumentLine) => line.unitPriceExcl;\n\n totalVat = getTotalVat(lines, getUnitPriceExcl, (line) =>\n new Decimal(line.vatPercentage).div(100)\n );\n totalExcl = getTotalExcl(lines, getUnitPriceExcl);\n }\n\n return {\n totalExcl,\n totalVat,\n subTotal: totalExcl.add(totalVat),\n };\n};\n\nexport const getRoundedDocumentTotal = (\n doc:\n | FinanceDocument\n | DocumentDraft<FinanceDocumentV2>\n | NewDocumentDraft<FinanceDocumentV2>\n | FinanceDocumentGenerateRequest,\n currencyCode?: string,\n foreignCurrency?: {\n currencyCode: string;\n exchangeRate: string;\n }\n) => {\n const { subTotal, totalExcl, totalVat } = getDocumentTotals(doc);\n const rate = foreignCurrency?.exchangeRate ?? '1';\n const subTotalForeign = subTotal.div(rate).toString();\n const totalExclForeign = totalExcl.div(rate).toString();\n const totalVatForeign = totalVat.div(rate).toString();\n\n return {\n amount: roundMoney(subTotal).toString(),\n amountExcl: roundMoney(totalExcl).toString(),\n vatAmount: roundMoney(totalVat).toString(),\n currencyCode: currencyCode ?? 'EUR',\n foreign: foreignCurrency\n ? {\n amount: roundMoney(subTotalForeign).toString(),\n amountExcl: roundMoney(totalExclForeign).toString(),\n vatAmount: roundMoney(totalVatForeign).toString(),\n currencyCode: foreignCurrency.currencyCode,\n exchangeRate: foreignCurrency.exchangeRate,\n }\n : undefined,\n };\n};\n\nconst getAmountExcl = (unitPriceExcl: string, quantity: string) =>\n new Decimal(unitPriceExcl).times(new Decimal(quantity));\n\nexport const getLineAmounts = (unitPriceExcl: string, quantity: string, vatRate: string) => {\n const amountExcl = getAmountExcl(unitPriceExcl, quantity);\n const vatAmount = new Decimal(quantity)\n .times(new Decimal(unitPriceExcl))\n .times(new Decimal(vatRate).div(100));\n\n return {\n amount: amountExcl.add(vatAmount).toString(),\n amountExcl: amountExcl.toString(),\n unitPriceExcl,\n vatAmount: vatAmount.toString(),\n };\n};\n\nexport const isGeneratingAttachment = (doc: FinanceDocument) =>\n doc.attachment.id === GENERATING_PLACEHOLDER_ATTACHMENT.id;\n\n// returns a new finance document where\n// - all lines are filtered by the recordId\n// - the unit price is divided by the number of associations\nexport const filterDocumentLinesForRecord = (\n doc: FinanceDocument,\n recordId: string // vehicleId, opportunityId, or externalVehicleSaleId\n): FinanceDocument => {\n const filteredLines = isFinanceDocumentV2(doc)\n ? doc.lines\n .filter((line) => line.associations?.some((assoc) => assoc.recordId === recordId))\n .map((line) => ({\n ...line,\n amount: calculateDistributedPrice(line.amount, line.associations?.length || 1),\n amountExcl: calculateDistributedPrice(line.amountExcl, line.associations?.length || 1),\n unitPriceExcl: calculateDistributedPrice(\n line.unitPriceExcl,\n line.associations?.length || 1\n ),\n }))\n : doc.lines\n .filter((line) =>\n getAllV1Associations(line.associations).some(\n (assoc) =>\n assoc.vehicleId === recordId ||\n (assoc as FinanceLineV1['associations']['sales'][0]).opportunityId === recordId ||\n (assoc as FinanceLineV1['associations']['sales'][0]).id === recordId\n )\n )\n .map((line) => ({\n ...line,\n unitPriceExclusive: calculateDistributedPrice(\n line.unitPriceExclusive,\n getAllV1Associations(line.associations).length || 1\n ),\n }));\n\n return {\n ...doc,\n lines: filteredLines,\n } as FinanceDocument;\n};\n\nconst calculateDistributedPrice = (price: string, count: number): string => {\n return new Decimal(price).div(Math.max(1, count)).toString();\n};\n\nconst getAllV1Associations = (ass: FinanceLineV1['associations']) => {\n const allAss = uniqBy(\n [...(ass?.sales ?? []), ...(ass?.purchases ?? []), ...(ass.others ?? [])],\n (ass) => ass.vehicleId\n );\n return allAss;\n};\n"]}
1
+ {"version":3,"file":"finance.js","sourceRoot":"/","sources":["utils/finance.ts"],"names":[],"mappings":"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","sourcesContent":["import { BusinessEntityIds } from '@bisondesk/commons-sdk/constants';\nimport { roundMoney } from '@bisondesk/commons-sdk/money';\nimport { Decimal } from 'decimal.js';\nimport { uniqBy } from 'lodash-es';\nimport { GENERATING_PLACEHOLDER_ATTACHMENT } from '../constants/index.js';\nimport {\n Association,\n DocumentDraft,\n FinanceDocument,\n FinanceDocumentGenerateRequest,\n FinanceDocumentLine,\n FinanceDocumentSubtype,\n FinanceDocumentV2,\n isFinanceDocumentDraft,\n isFinanceDocumentV1,\n isFinanceDocumentV2,\n NewDocumentDraft,\n} from '../types/documents.js';\nimport { FinanceDocumentV1, FinanceLineV1 } from '../types/legacy.js';\n\nexport const documentGoesToAccounting = (\n doc:\n | FinanceDocumentV2\n | DocumentDraft<FinanceDocumentV2>\n | FinanceDocumentGenerateRequest\n | FinanceDocumentV1\n): boolean => {\n return (\n !!doc.subtype &&\n [FinanceDocumentSubtype.Invoice, FinanceDocumentSubtype.CreditNote].includes(\n doc.subtype as FinanceDocumentSubtype\n )\n );\n};\n\nexport const getAccountingDescription = (doc: FinanceDocumentV2): string => {\n if (!!doc.accountingDescription) {\n return doc.accountingDescription;\n }\n\n const associations = doc.lines\n ?.flatMap((line) => line.associations ?? [])\n .filter(Boolean) as Association[];\n\n // In the UI the user can only select one vehicle associations\n const equivalentEntityIds = {\n [BusinessEntityIds.ExternalVehicleSale]: BusinessEntityIds.Vehicles,\n };\n\n const uniqueAssociations = uniqBy(\n associations,\n (a) => `${equivalentEntityIds[a.businessEntityId] ?? a.businessEntityId}_${a.recordId}`\n );\n\n if (uniqueAssociations.length !== 1) {\n return doc.reference;\n }\n\n const firstAssociation = associations[0];\n if (\n [\n BusinessEntityIds.Vehicles,\n BusinessEntityIds.Opportunities,\n BusinessEntityIds.ExternalVehicleSale,\n ].includes(firstAssociation.businessEntityId) &&\n firstAssociation.tags != null\n ) {\n return `${firstAssociation.tags?.slice(0, 3).join(' ')} ${doc.reference}`.trim();\n }\n\n return doc.reference;\n};\n\nexport const getTotalExcl = <T extends FinanceDocument['lines']>(\n lines: T,\n unitPrice: (line: T[0], index: number) => any\n) => {\n return lines.length === 0\n ? new Decimal(0)\n : Decimal.sum(...lines.map((line, i) => Decimal.mul(line.quantity, unitPrice(line, i))));\n};\n\nexport const getTotalVat = <T extends FinanceDocument['lines'], L = T[0]>(\n currency: string,\n lines: T,\n unitPrice: (doc: L, index: number) => any,\n vatCoefficient: (doc: L, index: number) => any\n) => {\n return lines.length === 0\n ? new Decimal(0)\n : roundMoney(\n currency,\n Decimal.sum(\n ...lines.map((line, i) =>\n Decimal.mul(line.quantity, unitPrice(line, i)).mul(vatCoefficient(line, i))\n )\n )\n );\n};\n\nexport const getDocumentTotals = (\n doc:\n | FinanceDocument\n | DocumentDraft<FinanceDocumentV2>\n | NewDocumentDraft<FinanceDocumentV2>\n | FinanceDocumentGenerateRequest\n) => {\n let totalVat: Decimal;\n let totalExcl: Decimal;\n\n if (isFinanceDocumentV1(doc as FinanceDocumentV1)) {\n const v1Currency = 'EUR';\n const lines = (doc as FinanceDocumentV1).lines;\n const getUnitPriceExclusive = (line: FinanceLineV1) => line.unitPriceExclusive;\n\n totalVat = getTotalVat(v1Currency, lines, getUnitPriceExclusive, (line) => line.vatCoefficient);\n totalExcl = getTotalExcl(lines, getUnitPriceExclusive);\n } else {\n const currency = (doc as FinanceDocumentV2).total.currencyCode;\n const lines = (doc as FinanceDocumentV2).lines ?? [];\n const getUnitPriceExcl = (line: FinanceDocumentLine) => line.unitPriceExcl;\n\n totalVat = getTotalVat(currency, lines, getUnitPriceExcl, (line) =>\n new Decimal(line.vatPercentage).div(100)\n );\n totalExcl = getTotalExcl(lines, getUnitPriceExcl);\n }\n\n return {\n totalExcl,\n totalVat,\n subTotal: totalExcl.add(totalVat),\n };\n};\n\nexport const getRoundedDocumentTotal = (\n doc:\n | FinanceDocument\n | DocumentDraft<FinanceDocumentV2>\n | NewDocumentDraft<FinanceDocumentV2>\n | FinanceDocumentGenerateRequest\n) => {\n let total: FinanceDocumentV2['total'] | undefined;\n\n if (isFinanceDocumentV2(doc as FinanceDocument) || isFinanceDocumentDraft(doc as DocumentDraft)) {\n total = (doc as FinanceDocumentV2 | DocumentDraft<FinanceDocumentV2>).total;\n }\n\n const currencyCode = total?.currencyCode ?? 'EUR';\n const foreignCurrency = total?.foreign;\n\n const { subTotal, totalExcl, totalVat } = getDocumentTotals(doc);\n const rate = foreignCurrency?.exchangeRate ?? '1';\n const subTotalForeign = subTotal.div(rate).toString();\n const totalExclForeign = totalExcl.div(rate).toString();\n const totalVatForeign = totalVat.div(rate).toString();\n\n return {\n amount: roundMoney(currencyCode, subTotal).toString(),\n amountExcl: roundMoney(currencyCode, totalExcl).toString(),\n vatAmount: roundMoney(currencyCode, totalVat).toString(),\n currencyCode: currencyCode,\n foreign: foreignCurrency\n ? {\n amount: roundMoney(foreignCurrency.currencyCode, subTotalForeign).toString(),\n amountExcl: roundMoney(foreignCurrency.currencyCode, totalExclForeign).toString(),\n vatAmount: roundMoney(foreignCurrency.currencyCode, totalVatForeign).toString(),\n currencyCode: foreignCurrency.currencyCode,\n exchangeRate: foreignCurrency.exchangeRate,\n }\n : undefined,\n };\n};\n\nexport const getRoundedLinesTotals = (\n currency: string,\n lines: { quantity: string; unitPriceExcl: string; vatPercentage: string }[],\n rate = '1'\n) => {\n let totalWithoutVat = new Decimal('0');\n let vatTotal = new Decimal('0');\n for (const line of lines) {\n const lineTotal = new Decimal(line.unitPriceExcl).times(new Decimal(line.quantity));\n totalWithoutVat = totalWithoutVat.add(lineTotal);\n vatTotal = vatTotal.add(lineTotal.mul(line.vatPercentage).div(100));\n }\n\n totalWithoutVat = totalWithoutVat.div(rate);\n vatTotal = vatTotal.div(rate);\n\n return {\n totalWithoutVat: roundMoney(currency, totalWithoutVat),\n vatTotal: roundMoney(currency, vatTotal),\n total: roundMoney(currency, vatTotal.add(totalWithoutVat)),\n };\n};\n\nconst getAmountExcl = (unitPriceExcl: string, quantity: string) =>\n new Decimal(unitPriceExcl).times(new Decimal(quantity));\n\nexport const getLineAmounts = (unitPriceExcl: string, quantity: string, vatRate: string) => {\n const amountExcl = getAmountExcl(unitPriceExcl, quantity);\n const vatAmount = new Decimal(quantity)\n .times(new Decimal(unitPriceExcl))\n .times(new Decimal(vatRate).div(100));\n\n return {\n amount: amountExcl.add(vatAmount).toString(),\n amountExcl: amountExcl.toString(),\n unitPriceExcl,\n vatAmount: vatAmount.toString(),\n };\n};\n\nexport const isGeneratingAttachment = (doc: FinanceDocument) =>\n doc.attachment.id === GENERATING_PLACEHOLDER_ATTACHMENT.id;\n\n// returns a new finance document where\n// - all lines are filtered by the recordId\n// - the unit price is divided by the number of associations\nexport const filterDocumentLinesForRecord = (\n doc: FinanceDocument,\n recordId: string // vehicleId, opportunityId, or externalVehicleSaleId\n): FinanceDocument => {\n const filteredLines = isFinanceDocumentV2(doc)\n ? doc.lines\n .filter((line) => line.associations?.some((assoc) => assoc.recordId === recordId))\n .map((line) => ({\n ...line,\n amount: calculateDistributedPrice(line.amount, line.associations?.length || 1),\n amountExcl: calculateDistributedPrice(line.amountExcl, line.associations?.length || 1),\n unitPriceExcl: calculateDistributedPrice(\n line.unitPriceExcl,\n line.associations?.length || 1\n ),\n }))\n : doc.lines\n .filter((line) =>\n getAllV1Associations(line.associations).some(\n (assoc) =>\n assoc.vehicleId === recordId ||\n (assoc as FinanceLineV1['associations']['sales'][0]).opportunityId === recordId ||\n (assoc as FinanceLineV1['associations']['sales'][0]).id === recordId\n )\n )\n .map((line) => ({\n ...line,\n unitPriceExclusive: calculateDistributedPrice(\n line.unitPriceExclusive,\n getAllV1Associations(line.associations).length || 1\n ),\n }));\n\n return {\n ...doc,\n lines: filteredLines,\n } as FinanceDocument;\n};\n\nconst calculateDistributedPrice = (price: string, count: number): string => {\n return new Decimal(price).div(Math.max(1, count)).toString();\n};\n\nconst getAllV1Associations = (ass: FinanceLineV1['associations']) => {\n const allAss = uniqBy(\n [...(ass?.sales ?? []), ...(ass?.purchases ?? []), ...(ass.others ?? [])],\n (ass) => ass.vehicleId\n );\n return allAss;\n};\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bisondesk/documents-sdk",
3
- "version": "1.0.513",
3
+ "version": "1.0.515",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -11,6 +11,7 @@ import {
11
11
  FinanceDocumentLine,
12
12
  FinanceDocumentSubtype,
13
13
  FinanceDocumentV2,
14
+ isFinanceDocumentDraft,
14
15
  isFinanceDocumentV1,
15
16
  isFinanceDocumentV2,
16
17
  NewDocumentDraft,
@@ -80,6 +81,7 @@ export const getTotalExcl = <T extends FinanceDocument['lines']>(
80
81
  };
81
82
 
82
83
  export const getTotalVat = <T extends FinanceDocument['lines'], L = T[0]>(
84
+ currency: string,
83
85
  lines: T,
84
86
  unitPrice: (doc: L, index: number) => any,
85
87
  vatCoefficient: (doc: L, index: number) => any
@@ -87,6 +89,7 @@ export const getTotalVat = <T extends FinanceDocument['lines'], L = T[0]>(
87
89
  return lines.length === 0
88
90
  ? new Decimal(0)
89
91
  : roundMoney(
92
+ currency,
90
93
  Decimal.sum(
91
94
  ...lines.map((line, i) =>
92
95
  Decimal.mul(line.quantity, unitPrice(line, i)).mul(vatCoefficient(line, i))
@@ -106,16 +109,18 @@ export const getDocumentTotals = (
106
109
  let totalExcl: Decimal;
107
110
 
108
111
  if (isFinanceDocumentV1(doc as FinanceDocumentV1)) {
112
+ const v1Currency = 'EUR';
109
113
  const lines = (doc as FinanceDocumentV1).lines;
110
114
  const getUnitPriceExclusive = (line: FinanceLineV1) => line.unitPriceExclusive;
111
115
 
112
- totalVat = getTotalVat(lines, getUnitPriceExclusive, (line) => line.vatCoefficient);
116
+ totalVat = getTotalVat(v1Currency, lines, getUnitPriceExclusive, (line) => line.vatCoefficient);
113
117
  totalExcl = getTotalExcl(lines, getUnitPriceExclusive);
114
118
  } else {
119
+ const currency = (doc as FinanceDocumentV2).total.currencyCode;
115
120
  const lines = (doc as FinanceDocumentV2).lines ?? [];
116
121
  const getUnitPriceExcl = (line: FinanceDocumentLine) => line.unitPriceExcl;
117
122
 
118
- totalVat = getTotalVat(lines, getUnitPriceExcl, (line) =>
123
+ totalVat = getTotalVat(currency, lines, getUnitPriceExcl, (line) =>
119
124
  new Decimal(line.vatPercentage).div(100)
120
125
  );
121
126
  totalExcl = getTotalExcl(lines, getUnitPriceExcl);
@@ -133,13 +138,17 @@ export const getRoundedDocumentTotal = (
133
138
  | FinanceDocument
134
139
  | DocumentDraft<FinanceDocumentV2>
135
140
  | NewDocumentDraft<FinanceDocumentV2>
136
- | FinanceDocumentGenerateRequest,
137
- currencyCode?: string,
138
- foreignCurrency?: {
139
- currencyCode: string;
140
- exchangeRate: string;
141
- }
141
+ | FinanceDocumentGenerateRequest
142
142
  ) => {
143
+ let total: FinanceDocumentV2['total'] | undefined;
144
+
145
+ if (isFinanceDocumentV2(doc as FinanceDocument) || isFinanceDocumentDraft(doc as DocumentDraft)) {
146
+ total = (doc as FinanceDocumentV2 | DocumentDraft<FinanceDocumentV2>).total;
147
+ }
148
+
149
+ const currencyCode = total?.currencyCode ?? 'EUR';
150
+ const foreignCurrency = total?.foreign;
151
+
143
152
  const { subTotal, totalExcl, totalVat } = getDocumentTotals(doc);
144
153
  const rate = foreignCurrency?.exchangeRate ?? '1';
145
154
  const subTotalForeign = subTotal.div(rate).toString();
@@ -147,15 +156,15 @@ export const getRoundedDocumentTotal = (
147
156
  const totalVatForeign = totalVat.div(rate).toString();
148
157
 
149
158
  return {
150
- amount: roundMoney(subTotal).toString(),
151
- amountExcl: roundMoney(totalExcl).toString(),
152
- vatAmount: roundMoney(totalVat).toString(),
153
- currencyCode: currencyCode ?? 'EUR',
159
+ amount: roundMoney(currencyCode, subTotal).toString(),
160
+ amountExcl: roundMoney(currencyCode, totalExcl).toString(),
161
+ vatAmount: roundMoney(currencyCode, totalVat).toString(),
162
+ currencyCode: currencyCode,
154
163
  foreign: foreignCurrency
155
164
  ? {
156
- amount: roundMoney(subTotalForeign).toString(),
157
- amountExcl: roundMoney(totalExclForeign).toString(),
158
- vatAmount: roundMoney(totalVatForeign).toString(),
165
+ amount: roundMoney(foreignCurrency.currencyCode, subTotalForeign).toString(),
166
+ amountExcl: roundMoney(foreignCurrency.currencyCode, totalExclForeign).toString(),
167
+ vatAmount: roundMoney(foreignCurrency.currencyCode, totalVatForeign).toString(),
159
168
  currencyCode: foreignCurrency.currencyCode,
160
169
  exchangeRate: foreignCurrency.exchangeRate,
161
170
  }
@@ -163,6 +172,29 @@ export const getRoundedDocumentTotal = (
163
172
  };
164
173
  };
165
174
 
175
+ export const getRoundedLinesTotals = (
176
+ currency: string,
177
+ lines: { quantity: string; unitPriceExcl: string; vatPercentage: string }[],
178
+ rate = '1'
179
+ ) => {
180
+ let totalWithoutVat = new Decimal('0');
181
+ let vatTotal = new Decimal('0');
182
+ for (const line of lines) {
183
+ const lineTotal = new Decimal(line.unitPriceExcl).times(new Decimal(line.quantity));
184
+ totalWithoutVat = totalWithoutVat.add(lineTotal);
185
+ vatTotal = vatTotal.add(lineTotal.mul(line.vatPercentage).div(100));
186
+ }
187
+
188
+ totalWithoutVat = totalWithoutVat.div(rate);
189
+ vatTotal = vatTotal.div(rate);
190
+
191
+ return {
192
+ totalWithoutVat: roundMoney(currency, totalWithoutVat),
193
+ vatTotal: roundMoney(currency, vatTotal),
194
+ total: roundMoney(currency, vatTotal.add(totalWithoutVat)),
195
+ };
196
+ };
197
+
166
198
  const getAmountExcl = (unitPriceExcl: string, quantity: string) =>
167
199
  new Decimal(unitPriceExcl).times(new Decimal(quantity));
168
200