@placeshakr/config 10.29.4 → 10.31.0-alpha.2

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 (62) hide show
  1. package/dist/auth/policy.js +6 -0
  2. package/dist/auth/policy.js.map +1 -1
  3. package/dist/billing/index.js +9 -0
  4. package/dist/billing/index.js.map +1 -0
  5. package/dist/billing/pennylane.js +400 -0
  6. package/dist/billing/pennylane.js.map +1 -0
  7. package/dist/billing/permissions.js +27 -0
  8. package/dist/billing/permissions.js.map +1 -0
  9. package/dist/billing/prefill.js +208 -0
  10. package/dist/billing/prefill.js.map +1 -0
  11. package/dist/billing/types.js +3 -0
  12. package/dist/billing/types.js.map +1 -0
  13. package/dist/billing/validate.js +189 -0
  14. package/dist/billing/validate.js.map +1 -0
  15. package/dist/environment/base.js +28 -0
  16. package/dist/environment/base.js.map +1 -1
  17. package/dist/environment/decorators.js +2 -0
  18. package/dist/environment/decorators.js.map +1 -1
  19. package/dist/helpers/index.js +1 -0
  20. package/dist/helpers/index.js.map +1 -1
  21. package/dist/index.js +3 -1
  22. package/dist/index.js.map +1 -1
  23. package/dist/types/auth/policy.d.ts +2 -1
  24. package/dist/types/auth/policy.d.ts.map +1 -1
  25. package/dist/types/billing/index.d.ts +6 -0
  26. package/dist/types/billing/index.d.ts.map +1 -0
  27. package/dist/types/billing/pennylane.d.ts +191 -0
  28. package/dist/types/billing/pennylane.d.ts.map +1 -0
  29. package/dist/types/billing/permissions.d.ts +23 -0
  30. package/dist/types/billing/permissions.d.ts.map +1 -0
  31. package/dist/types/billing/prefill.d.ts +42 -0
  32. package/dist/types/billing/prefill.d.ts.map +1 -0
  33. package/dist/types/billing/types.d.ts +30 -0
  34. package/dist/types/billing/types.d.ts.map +1 -0
  35. package/dist/types/billing/validate.d.ts +48 -0
  36. package/dist/types/billing/validate.d.ts.map +1 -0
  37. package/dist/types/environment/base.d.ts.map +1 -1
  38. package/dist/types/environment/decorators.d.ts.map +1 -1
  39. package/dist/types/environment/types.d.ts +5 -0
  40. package/dist/types/environment/types.d.ts.map +1 -1
  41. package/dist/types/helpers/index.d.ts +1 -0
  42. package/dist/types/helpers/index.d.ts.map +1 -1
  43. package/dist/types/index.d.ts +2 -1
  44. package/dist/types/index.d.ts.map +1 -1
  45. package/dist/types/types.d.ts +491 -0
  46. package/dist/types/types.d.ts.map +1 -1
  47. package/dist/types.js +70 -1
  48. package/dist/types.js.map +1 -1
  49. package/package.json +2 -2
  50. package/src/auth/policy.ts +21 -1
  51. package/src/billing/index.ts +5 -0
  52. package/src/billing/pennylane.ts +530 -0
  53. package/src/billing/permissions.ts +25 -0
  54. package/src/billing/prefill.ts +309 -0
  55. package/src/billing/types.ts +32 -0
  56. package/src/billing/validate.ts +198 -0
  57. package/src/environment/base.ts +30 -0
  58. package/src/environment/decorators.ts +2 -0
  59. package/src/environment/types.ts +5 -0
  60. package/src/helpers/index.ts +2 -0
  61. package/src/index.ts +2 -0
  62. package/src/types.ts +524 -0
@@ -116,5 +116,11 @@ exports.acls = [
116
116
  'configuration.enterprise.payment.method.add',
117
117
  'configuration.enterprise.payment.method.delete',
118
118
  'configuration.enterprise.payment.history.view',
119
+ // accounting / PennyLane
120
+ 'accounting.pennylane.configure',
121
+ 'accounting.pennylane.push',
122
+ 'accounting.importedBills.view',
123
+ 'accounting.importedBills.assign',
124
+ 'accounting.importedBills.ignore',
119
125
  ];
120
126
  //# sourceMappingURL=policy.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"policy.js","sourceRoot":"","sources":["../../src/auth/policy.ts"],"names":[],"mappings":";;;AA4Ia,QAAA,IAAI,GAAa;IAC5B,cAAc;IACd,cAAc;IACd,gBAAgB;IAChB,gBAAgB;IAChB,uBAAuB;IAEvB,eAAe;IACf,oBAAoB;IACpB,sBAAsB;IACtB,uBAAuB;IACvB,uBAAuB;IACvB,sBAAsB;IACtB,wBAAwB;IACxB,yBAAyB;IACzB,yBAAyB;IAEzB,gBAAgB;IAChB,kBAAkB;IAClB,qBAAqB;IACrB,yBAAyB;IACzB,gCAAgC;IAChC,qBAAqB;IACrB,oBAAoB;IAEpB,QAAQ;IACR,sBAAsB;IACtB,oBAAoB;IACpB,sBAAsB;IAEtB,QAAQ;IACR,mBAAmB;IACnB,qBAAqB;IACrB,mBAAmB;IACnB,qBAAqB;IAErB,YAAY;IACZ,uBAAuB;IACvB,yBAAyB;IACzB,uBAAuB;IACvB,yBAAyB;IAEzB,SAAS;IACT,oBAAoB;IACpB,sBAAsB;IACtB,oBAAoB;IACpB,sBAAsB;IAEtB,SAAS;IACT,oBAAoB;IACpB,sBAAsB;IACtB,oBAAoB;IAEpB;;OAEG;IAEH,cAAc;IACd,YAAY;IACZ,YAAY;IACZ,cAAc;IACd,mBAAmB;IACnB,kBAAkB;IAClB,gBAAgB;IAChB,4BAA4B;IAE5B;;OAEG;IACH,oBAAoB;IAEpB,SAAS;IACT,2BAA2B;IAC3B,6BAA6B;IAC7B,2BAA2B;IAC3B,6BAA6B;IAE7B,YAAY;IACZ,6BAA6B;IAC7B,6BAA6B;IAC7B,+BAA+B;IAC/B,+BAA+B;IAE/B,qBAAqB;IACrB,sCAAsC;IACtC,sCAAsC;IACtC,wCAAwC;IACxC,wCAAwC;IAExC,YAAY;IACZ,6BAA6B;IAC7B,6BAA6B;IAC7B,+BAA+B;IAC/B,+BAA+B;IAE/B,aAAa;IACb,8BAA8B;IAC9B,8BAA8B;IAC9B,gCAAgC;IAChC,gCAAgC;IAEhC,kBAAkB;IAClB,mCAAmC;IACnC,mCAAmC;IACnC,qCAAqC;IACrC,qCAAqC;IAErC,OAAO;IACP,yBAAyB;IAEzB,cAAc;IACd,wBAAwB;IACxB,0BAA0B;IAC1B,0BAA0B;IAC1B,wBAAwB;IAExB,gBAAgB;IAChB,0BAA0B;IAC1B,4BAA4B;IAC5B,4BAA4B;IAC5B,0BAA0B;IAE1B,iBAAiB;IACjB,0BAA0B;IAC1B,4BAA4B;IAC5B,4BAA4B;IAC5B,0BAA0B;IAE1B,aAAa;IACb,+BAA+B;IAC/B,iCAAiC;IACjC,iCAAiC;IACjC,+BAA+B;IAC/B,6CAA6C;IAC7C,gDAAgD;IAChD,+CAA+C;CAChD,CAAC"}
1
+ {"version":3,"file":"policy.js","sourceRoot":"","sources":["../../src/auth/policy.ts"],"names":[],"mappings":";;;AAyJa,QAAA,IAAI,GAAa;IAC5B,cAAc;IACd,cAAc;IACd,gBAAgB;IAChB,gBAAgB;IAChB,uBAAuB;IAEvB,eAAe;IACf,oBAAoB;IACpB,sBAAsB;IACtB,uBAAuB;IACvB,uBAAuB;IACvB,sBAAsB;IACtB,wBAAwB;IACxB,yBAAyB;IACzB,yBAAyB;IAEzB,gBAAgB;IAChB,kBAAkB;IAClB,qBAAqB;IACrB,yBAAyB;IACzB,gCAAgC;IAChC,qBAAqB;IACrB,oBAAoB;IAEpB,QAAQ;IACR,sBAAsB;IACtB,oBAAoB;IACpB,sBAAsB;IAEtB,QAAQ;IACR,mBAAmB;IACnB,qBAAqB;IACrB,mBAAmB;IACnB,qBAAqB;IAErB,YAAY;IACZ,uBAAuB;IACvB,yBAAyB;IACzB,uBAAuB;IACvB,yBAAyB;IAEzB,SAAS;IACT,oBAAoB;IACpB,sBAAsB;IACtB,oBAAoB;IACpB,sBAAsB;IAEtB,SAAS;IACT,oBAAoB;IACpB,sBAAsB;IACtB,oBAAoB;IAEpB;;OAEG;IAEH,cAAc;IACd,YAAY;IACZ,YAAY;IACZ,cAAc;IACd,mBAAmB;IACnB,kBAAkB;IAClB,gBAAgB;IAChB,4BAA4B;IAE5B;;OAEG;IACH,oBAAoB;IAEpB,SAAS;IACT,2BAA2B;IAC3B,6BAA6B;IAC7B,2BAA2B;IAC3B,6BAA6B;IAE7B,YAAY;IACZ,6BAA6B;IAC7B,6BAA6B;IAC7B,+BAA+B;IAC/B,+BAA+B;IAE/B,qBAAqB;IACrB,sCAAsC;IACtC,sCAAsC;IACtC,wCAAwC;IACxC,wCAAwC;IAExC,YAAY;IACZ,6BAA6B;IAC7B,6BAA6B;IAC7B,+BAA+B;IAC/B,+BAA+B;IAE/B,aAAa;IACb,8BAA8B;IAC9B,8BAA8B;IAC9B,gCAAgC;IAChC,gCAAgC;IAEhC,kBAAkB;IAClB,mCAAmC;IACnC,mCAAmC;IACnC,qCAAqC;IACrC,qCAAqC;IAErC,OAAO;IACP,yBAAyB;IAEzB,cAAc;IACd,wBAAwB;IACxB,0BAA0B;IAC1B,0BAA0B;IAC1B,wBAAwB;IAExB,gBAAgB;IAChB,0BAA0B;IAC1B,4BAA4B;IAC5B,4BAA4B;IAC5B,0BAA0B;IAE1B,iBAAiB;IACjB,0BAA0B;IAC1B,4BAA4B;IAC5B,4BAA4B;IAC5B,0BAA0B;IAE1B,aAAa;IACb,+BAA+B;IAC/B,iCAAiC;IACjC,iCAAiC;IACjC,+BAA+B;IAC/B,6CAA6C;IAC7C,gDAAgD;IAChD,+CAA+C;IAE/C,yBAAyB;IACzB,gCAAgC;IAChC,2BAA2B;IAC3B,+BAA+B;IAC/B,iCAAiC;IACjC,iCAAiC;CAClC,CAAC"}
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ tslib_1.__exportStar(require("./types"), exports);
5
+ tslib_1.__exportStar(require("./permissions"), exports);
6
+ tslib_1.__exportStar(require("./validate"), exports);
7
+ tslib_1.__exportStar(require("./prefill"), exports);
8
+ tslib_1.__exportStar(require("./pennylane"), exports);
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/billing/index.ts"],"names":[],"mappings":";;;AAAA,kDAAwB;AACxB,wDAA8B;AAC9B,qDAA2B;AAC3B,oDAA0B;AAC1B,sDAA4B"}
@@ -0,0 +1,400 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isSupplierIgnored = exports.findMatchingIgnoredSupplier = exports.normalizeRegNo = exports.normalizeSupplierName = exports.getPennylaneInvoiceUrl = exports.ENTERPRISE_PENNYLANE_COMPANY_IDS = exports.billIssuedToPennylanePayload = exports.formatPennylaneErrorMessage = exports.getBillBlockers = exports.isBillIssuedSentToPennylane = exports.toVatRateCode = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const articho = tslib_1.__importStar(require("../types"));
6
+ const validate_1 = require("./validate");
7
+ /** Días que añade cada condición de pago a la fecha de la factura. */
8
+ const TERM_DAYS = {
9
+ [articho.TermsOfPayment.UPON_RECEIPT]: 0,
10
+ [articho.TermsOfPayment.MONTH_END]: 30,
11
+ [articho.TermsOfPayment.DAYS_10]: 10,
12
+ [articho.TermsOfPayment.DAYS_20]: 20,
13
+ [articho.TermsOfPayment.DAYS_30]: 30,
14
+ [articho.TermsOfPayment.DAYS_30_END_MONTH]: 30,
15
+ [articho.TermsOfPayment.DAYS_45]: 45,
16
+ [articho.TermsOfPayment.DAYS_60]: 60,
17
+ [articho.TermsOfPayment.DAYS_60_END_MONTH]: 60,
18
+ [articho.TermsOfPayment.DAYS_90]: 90,
19
+ [articho.TermsOfPayment.DAYS_90_END_MONTH]: 90,
20
+ [articho.TermsOfPayment.DAYS_120]: 120,
21
+ };
22
+ /** Condición de pago de Articho → la que entiende PennyLane. */
23
+ const PAYMENT_CONDITIONS = {
24
+ [articho.TermsOfPayment.UPON_RECEIPT]: articho.BillingPaymentConditions.UPON_RECEIPT,
25
+ [articho.TermsOfPayment.DAYS_10]: articho.BillingPaymentConditions.DAYS_7,
26
+ [articho.TermsOfPayment.DAYS_20]: articho.BillingPaymentConditions.DAYS_15,
27
+ [articho.TermsOfPayment.DAYS_30]: articho.BillingPaymentConditions.DAYS_30,
28
+ [articho.TermsOfPayment.MONTH_END]: articho.BillingPaymentConditions.DAYS_30_EOM,
29
+ [articho.TermsOfPayment.DAYS_30_END_MONTH]: articho.BillingPaymentConditions.DAYS_30_EOM,
30
+ [articho.TermsOfPayment.DAYS_45]: articho.BillingPaymentConditions.DAYS_45,
31
+ [articho.TermsOfPayment.DAYS_60]: articho.BillingPaymentConditions.DAYS_60,
32
+ [articho.TermsOfPayment.DAYS_60_END_MONTH]: articho.BillingPaymentConditions.DAYS_60,
33
+ [articho.TermsOfPayment.DAYS_90]: articho.BillingPaymentConditions.DAYS_60,
34
+ [articho.TermsOfPayment.DAYS_90_END_MONTH]: articho.BillingPaymentConditions.DAYS_60,
35
+ [articho.TermsOfPayment.DAYS_120]: articho.BillingPaymentConditions.DAYS_60,
36
+ };
37
+ /**
38
+ * Porcentaje de IVA → código de PennyLane.
39
+ * @param {number} rate Porcentaje (20, 10, 5.5, 0).
40
+ * @param {boolean} hasTva false cuando la factura va sin IVA.
41
+ * @return {string} Código de IVA.
42
+ */
43
+ const toVatRateCode = (rate, hasTva = true) => {
44
+ if (!hasTva)
45
+ return 'exempt';
46
+ switch (Math.round((rate ?? 0) * 10) / 10) {
47
+ case 20:
48
+ return 'FR_200';
49
+ case 10:
50
+ return 'FR_100';
51
+ case 5.5:
52
+ return 'FR_055';
53
+ case 2.1:
54
+ return 'FR_021';
55
+ case 0:
56
+ return 'exempt';
57
+ default:
58
+ return 'any';
59
+ }
60
+ };
61
+ exports.toVatRateCode = toVatRateCode;
62
+ const toISODate = (value) => new Date(value).toISOString().slice(0, 10);
63
+ const toDiscount = (value, type) => {
64
+ if (!value)
65
+ return undefined;
66
+ return {
67
+ type: type === articho.BillDiscountType.PERCENT ? 'relative' : 'absolute',
68
+ value,
69
+ };
70
+ };
71
+ /**
72
+ * Determina si una factura emitida ya está sincronizada o enviada a PennyLane.
73
+ *
74
+ * Casos especiales:
75
+ * 1. Si el estado es FAILED, NO se considera enviada para permitir reintentar tras corregir el error.
76
+ * 2. Si fue importada desde PennyLane, ya existe en PennyLane.
77
+ * 3. Para avoirs (CREDIT_NOTE), invoiceId puede haber sido copiado de la factura origen.
78
+ * Solo se considera verdaderamente enviada si está SYNCED, tiene un invoiceId propio y
79
+ * un creditedInvoiceId distinto de su propio invoiceId.
80
+ *
81
+ * @param {articho.BillIssued} [bill] Factura emitida.
82
+ * @return {boolean} true si ya está enviada/sincronizada en PennyLane.
83
+ */
84
+ const isBillIssuedSentToPennylane = (bill) => {
85
+ if (!bill)
86
+ return false;
87
+ const isFailed = bill.metadata?.pennylane?.status === 'FAILED';
88
+ if (isFailed)
89
+ return false;
90
+ if (bill.imported === true ||
91
+ bill.source === 'pennylane' ||
92
+ Boolean(bill.metadata?.pennylane?.importedBillId)) {
93
+ return true;
94
+ }
95
+ const isCreditNote = bill.subType === articho.BillIssuedType.CREDIT_NOTE;
96
+ if (isCreditNote) {
97
+ return Boolean(bill.metadata?.pennylane?.status === 'SYNCED' &&
98
+ bill.metadata?.pennylane?.invoiceId &&
99
+ bill.metadata?.pennylane?.creditedInvoiceId &&
100
+ String(bill.metadata.pennylane.invoiceId) !==
101
+ String(bill.metadata.pennylane.creditedInvoiceId));
102
+ }
103
+ return Boolean(bill.metadata?.pennylane?.status === 'SYNCED' ||
104
+ bill.metadata?.pennylane?.invoiceId ||
105
+ bill.metadata?.sentToPennyLane);
106
+ };
107
+ exports.isBillIssuedSentToPennylane = isBillIssuedSentToPennylane;
108
+ /**
109
+ * Motivos por los que una factura de Articho no se puede enviar a PennyLane.
110
+ * @param {articho.BillIssued} bill Factura emitida.
111
+ * @return {string[]} Claves de traducción de los bloqueos encontrados.
112
+ */
113
+ const getBillBlockers = (bill) => {
114
+ const blockers = [];
115
+ if (!bill?.elements?.length)
116
+ blockers.push('pennylane.blocker.noElements');
117
+ if (bill?.subType === articho.BillIssuedType.CREDIT_NOTE) {
118
+ // Un avoir solo se puede enviar si tiene una factura de origen asociada
119
+ if (!bill?.billSource?.id) {
120
+ blockers.push('pennylane.blocker.creditNoteWithoutSource');
121
+ }
122
+ }
123
+ if ((0, exports.isBillIssuedSentToPennylane)(bill)) {
124
+ blockers.push('pennylane.blocker.alreadySent');
125
+ }
126
+ const withoutLabel = bill?.elements?.some((element) => !element?.description?.trim());
127
+ if (withoutLabel)
128
+ blockers.push('pennylane.blocker.elementWithoutLabel');
129
+ return blockers;
130
+ };
131
+ exports.getBillBlockers = getBillBlockers;
132
+ /**
133
+ * Traduce o formatea de forma legible los mensajes de error devueltos por PennyLane
134
+ * para que el usuario en la interfaz comprenda qué ocurrió sin ver códigos HTTP crudos.
135
+ *
136
+ * @param {string} [rawMessage] Mensaje de error recibido.
137
+ * @return {string} Mensaje traducido y formateado.
138
+ */
139
+ const formatPennylaneErrorMessage = (rawMessage) => {
140
+ if (!rawMessage)
141
+ return '';
142
+ const msg = rawMessage.trim();
143
+ // Si el mensaje ya está estructurado y traducido en francés, conservarlo
144
+ if (msg.includes('Authentification échouée') ||
145
+ msg.includes('Accès refusé par PennyLane') ||
146
+ msg.includes('Ressource introuvable sur PennyLane') ||
147
+ msg.includes('Données rejetées par PennyLane') ||
148
+ msg.includes('Limite de requêtes atteinte') ||
149
+ msg.includes('Le service PennyLane est temporairement indisponible')) {
150
+ return msg;
151
+ }
152
+ // Mapeo según patrones o códigos HTTP
153
+ if (msg.includes('401') || msg.toLowerCase().includes('unauthorized')) {
154
+ return "Authentification échouée auprès de PennyLane (401). Le jeton API est manquant, invalide ou a expiré.";
155
+ }
156
+ if (msg.includes('403') || msg.toLowerCase().includes('forbidden')) {
157
+ return "Accès refusé par PennyLane (403). La clé API ne dispose pas des droits nécessaires pour cette entreprise.";
158
+ }
159
+ if (msg.includes('404') || msg.toLowerCase().includes('not found')) {
160
+ return "Ressource introuvable sur PennyLane (404) : le client, le tiers ou la facture d'origine n'existe pas.";
161
+ }
162
+ if (msg.includes('409') || msg.toLowerCase().includes('conflict')) {
163
+ return "Conflit sur PennyLane (409) : une facture ou ressource similaire existe déjà.";
164
+ }
165
+ if (msg.includes('413') || msg.toLowerCase().includes('too large')) {
166
+ return "Le document envoyé dépasse la limite de taille autorisée par PennyLane (100 Mo max).";
167
+ }
168
+ if (msg.includes('422') || msg.toLowerCase().includes('unprocessable')) {
169
+ return msg.length > 40 && !msg.startsWith('PennyLane 422')
170
+ ? msg
171
+ : "Les données envoyées ne respectent pas les règles comptables de PennyLane (422) : vérifiez les montants, lignes et TVA.";
172
+ }
173
+ if (msg.includes('429') || msg.toLowerCase().includes('rate limit')) {
174
+ return "Limite de requêtes atteinte sur PennyLane (429). Veuillez patienter quelques instants avant de réessayer.";
175
+ }
176
+ if (msg.includes('500') ||
177
+ msg.includes('502') ||
178
+ msg.includes('503') ||
179
+ msg.includes('504') ||
180
+ msg.toLowerCase().includes('internal server error')) {
181
+ return "Le service PennyLane est temporairement indisponible ou rencontre une erreur interne. Veuillez réessayer dans quelques instants.";
182
+ }
183
+ return msg;
184
+ };
185
+ exports.formatPennylaneErrorMessage = formatPennylaneErrorMessage;
186
+ /**
187
+ * Traduce una factura emitida de Articho a la entrada del callable de PennyLane.
188
+ *
189
+ * Cada `BillElement` se convierte en una línea: PennyLane calcula los totales
190
+ * a partir de ellas, así que no se envían ni el total ni el número de factura
191
+ * —ese lo asigna PennyLane, que es justo lo que se busca—.
192
+ *
193
+ * Para avoirs (`CREDIT_NOTE`), los precios unitarios se invierten a negativo
194
+ * según la especificación de PennyLane v2 y se vincula `credited_invoice_id`.
195
+ *
196
+ * @param {articho.BillIssued} bill Factura emitida.
197
+ * @param {object} context Destinatario y opciones de envío.
198
+ * @return {PennylaneInvoicePayload} Carga útil para el callable.
199
+ */
200
+ const billIssuedToPennylanePayload = (bill, context) => {
201
+ const isCreditNote = bill?.subType === articho.BillIssuedType.CREDIT_NOTE;
202
+ const date = bill?.date ?? Date.now();
203
+ const termDays = isCreditNote ? 0 : (TERM_DAYS[bill?.termsOfPayment ?? ''] ?? 30);
204
+ const deadline = date + termDays * 24 * 60 * 60 * 1000;
205
+ const { billing } = context;
206
+ const creditedInvoiceId = context.creditedInvoiceId !== undefined && context.creditedInvoiceId !== null
207
+ ? Number(context.creditedInvoiceId)
208
+ : undefined;
209
+ const displayLabel = isCreditNote
210
+ ? bill?.billSource?.reference
211
+ ? `Avoir sur facture ${bill.billSource.reference}`
212
+ : bill?.title || 'Avoir'
213
+ : bill?.title;
214
+ return {
215
+ // Si ya sabemos el id en PennyLane lo usamos y nos ahorramos la búsqueda.
216
+ customerId: billing?.pennylaneCustomerId ? Number(billing.pennylaneCustomerId) : null,
217
+ customer: {
218
+ // En un particular la razón social no existe: se compone del nombre.
219
+ name: (0, validate_1.billingDisplayName)(billing),
220
+ ...(billing.legalType ? { legalType: billing.legalType } : {}),
221
+ ...(billing.legalType === 'individual'
222
+ ? {
223
+ firstName: billing.firstName ?? '',
224
+ lastName: billing.lastName ?? '',
225
+ }
226
+ : {}),
227
+ billingAddress: {
228
+ address: billing.address.address,
229
+ postalCode: billing.address.postalCode,
230
+ city: billing.address.city,
231
+ countryAlpha2: (billing.address.countryAlpha2 || 'FR').toUpperCase(),
232
+ },
233
+ // Un particular no tiene ninguno de los dos. Si algo se coló en la
234
+ // ficha, no viaja: PennyLane rechazaría la creación del tercero.
235
+ ...(billing.legalType !== 'individual' && billing.registrationNumber
236
+ ? { regNo: billing.registrationNumber }
237
+ : {}),
238
+ ...(billing.legalType !== 'individual' && billing.vatNumber
239
+ ? { vatNumber: billing.vatNumber }
240
+ : {}),
241
+ ...(billing.emails?.length ? { emails: billing.emails } : {}),
242
+ ...(billing.phone ? { phone: billing.phone } : {}),
243
+ ...(billing.recipient ? { recipient: billing.recipient } : {}),
244
+ ...(billing.notes ? { notes: billing.notes } : {}),
245
+ paymentConditions: billing.paymentConditions ??
246
+ PAYMENT_CONDITIONS[bill?.termsOfPayment ?? ''] ??
247
+ articho.BillingPaymentConditions.DAYS_30,
248
+ billingLanguage: billing.language ?? articho.BillingLanguage.FR,
249
+ ...(context.entityId ? { archiId: context.entityId } : {}),
250
+ },
251
+ date: toISODate(date),
252
+ deadline: toISODate(deadline),
253
+ lines: [...(bill?.elements ?? [])]
254
+ .sort((a, b) => (a?.order ?? 0) - (b?.order ?? 0))
255
+ .map((element) => {
256
+ const rawPrice = element.priceHT ?? 0;
257
+ const unitPrice = isCreditNote ? -Math.abs(rawPrice) : rawPrice;
258
+ return {
259
+ label: element.description,
260
+ quantity: element.quantity ?? 1,
261
+ unit: 'piece',
262
+ unitPrice,
263
+ vatRate: (0, exports.toVatRateCode)(element.tva, bill?.tva !== false),
264
+ ...(toDiscount(element.discount, element.discountType)
265
+ ? { discount: toDiscount(element.discount, element.discountType) }
266
+ : {}),
267
+ };
268
+ }),
269
+ draft: context.draft ?? false,
270
+ currency: 'EUR',
271
+ language: billing.language ?? articho.BillingLanguage.FR,
272
+ label: displayLabel,
273
+ externalReference: bill?.id ? `articho:${bill.id}` : undefined,
274
+ pdfInvoiceSubject: displayLabel,
275
+ ...(bill?.comments ? { specialMention: bill.comments } : {}),
276
+ ...(toDiscount(bill?.discount, bill?.discountType)
277
+ ? { discount: toDiscount(bill?.discount, bill?.discountType) }
278
+ : {}),
279
+ sendToPa: context.sendToPa ?? false,
280
+ projectId: context.projectId ?? null,
281
+ billId: bill?.id ?? null,
282
+ ...(creditedInvoiceId ? { creditedInvoiceId } : {}),
283
+ };
284
+ };
285
+ exports.billIssuedToPennylanePayload = billIssuedToPennylanePayload;
286
+ /** Known PennyLane company IDs mapped by Articho enterprise ID. Used as fallback when not configured in Firestore. */
287
+ exports.ENTERPRISE_PENNYLANE_COMPANY_IDS = {
288
+ '45106373900119': '156553',
289
+ };
290
+ /**
291
+ * Generates a direct URL to view an invoice in the PennyLane web application.
292
+ * Returns null if the invoice ID or company ID is missing.
293
+ *
294
+ * Examples:
295
+ * - Customer (Ventes):
296
+ * https://app.pennylane.com/companies/156553/clients/customer_invoices?invoice_id=28823318994944
297
+ * - Supplier (Achats):
298
+ * https://app.pennylane.com/companies/156553/supplier_invoices?invoice_id=28645132099584
299
+ *
300
+ * @param {object} options
301
+ * @param {string | number} [options.invoiceId] PennyLane invoice ID (or prefixed ID like 'pl_123').
302
+ * @param {string | number} [options.companyId] PennyLane company ID (e.g. '156553', from Firestore config).
303
+ * @param {string} [options.enterpriseId] Articho enterprise ID.
304
+ * @param {'customer' | 'supplier'} [options.type] 'customer' for customer invoices (ventes), 'supplier' for supplier invoices (achats).
305
+ * @return {string | null} Full PennyLane app URL or null if cannot be formed.
306
+ */
307
+ const getPennylaneInvoiceUrl = (options) => {
308
+ if (!options?.invoiceId) {
309
+ return null;
310
+ }
311
+ const companyId = options?.companyId ||
312
+ (options?.enterpriseId ? exports.ENTERPRISE_PENNYLANE_COMPANY_IDS[options.enterpriseId] : undefined) ||
313
+ exports.ENTERPRISE_PENNYLANE_COMPANY_IDS['45106373900119'];
314
+ if (!companyId) {
315
+ return null;
316
+ }
317
+ const base = 'https://app.pennylane.com';
318
+ const section = options?.type === 'customer' ? 'clients/customer_invoices' : 'supplier_invoices';
319
+ const cleanId = String(options.invoiceId).replace(/^pl_/, '').trim();
320
+ return `${base}/companies/${companyId}/${section}?invoice_id=${cleanId}`;
321
+ };
322
+ exports.getPennylaneInvoiceUrl = getPennylaneInvoiceUrl;
323
+ /**
324
+ * Normalizes a string for loose comparison (lowercase, trimmed, collapsed whitespace, accent-free).
325
+ *
326
+ * @param {string | null | undefined} val Input string.
327
+ * @return {string} Normalized string.
328
+ */
329
+ const normalizeSupplierName = (val) => {
330
+ return (val ?? '')
331
+ .trim()
332
+ .toLowerCase()
333
+ .normalize('NFD')
334
+ .replace(/[\u0300-\u036f]/g, '')
335
+ .replace(/\s+/g, ' ');
336
+ };
337
+ exports.normalizeSupplierName = normalizeSupplierName;
338
+ /**
339
+ * Normalizes a SIREN / SIRET registration number (digits only).
340
+ *
341
+ * @param {string | null | undefined} val Registration number.
342
+ * @return {string} Normalized digits only.
343
+ */
344
+ const normalizeRegNo = (val) => {
345
+ return (val ?? '').replace(/\D/g, '');
346
+ };
347
+ exports.normalizeRegNo = normalizeRegNo;
348
+ /**
349
+ * Checks whether a counterparty matches any entry in the enterprise's ignored suppliers list.
350
+ *
351
+ * Match criteria:
352
+ * 1. Matching PennyLane supplier ID
353
+ * 2. Matching SIREN/SIRET registration number (at least 9 digits / SIREN match)
354
+ * 3. Matching normalized supplier name
355
+ *
356
+ * @param {object} [counterparty] Counterparty details from imported bill or invoice.
357
+ * @param {articho.PennylaneIgnoredSupplier[]} [ignoredSuppliers] Enterprise ignored suppliers list.
358
+ * @return {articho.PennylaneIgnoredSupplier | null} The matching rule if found, or null.
359
+ */
360
+ const findMatchingIgnoredSupplier = (counterparty, ignoredSuppliers) => {
361
+ if (!counterparty || !ignoredSuppliers || ignoredSuppliers.length === 0)
362
+ return null;
363
+ const plId = counterparty.pennylaneId ? String(counterparty.pennylaneId).trim() : null;
364
+ const regNo = (0, exports.normalizeRegNo)(counterparty.regNo);
365
+ const name = (0, exports.normalizeSupplierName)(counterparty.name);
366
+ for (const rule of ignoredSuppliers) {
367
+ // 1. Match by PennyLane ID
368
+ if (plId && rule.pennylaneId && String(rule.pennylaneId).trim() === plId) {
369
+ return rule;
370
+ }
371
+ // 2. Match by SIREN / SIRET (at least 9 digits)
372
+ if (regNo.length >= 9 && rule.regNo) {
373
+ const ruleRegNo = (0, exports.normalizeRegNo)(rule.regNo);
374
+ if (ruleRegNo.length >= 9 && regNo.substring(0, 9) === ruleRegNo.substring(0, 9)) {
375
+ return rule;
376
+ }
377
+ }
378
+ // 3. Match by normalized name (exact normalized string match)
379
+ if (name && rule.name) {
380
+ const ruleName = (0, exports.normalizeSupplierName)(rule.name);
381
+ if (name === ruleName) {
382
+ return rule;
383
+ }
384
+ }
385
+ }
386
+ return null;
387
+ };
388
+ exports.findMatchingIgnoredSupplier = findMatchingIgnoredSupplier;
389
+ /**
390
+ * Returns true if the counterparty is ignored by the enterprise configuration.
391
+ *
392
+ * @param {object} [counterparty] Counterparty details.
393
+ * @param {articho.PennylaneIgnoredSupplier[]} [ignoredSuppliers] List of ignored suppliers.
394
+ * @return {boolean} True if ignored.
395
+ */
396
+ const isSupplierIgnored = (counterparty, ignoredSuppliers) => {
397
+ return Boolean((0, exports.findMatchingIgnoredSupplier)(counterparty, ignoredSuppliers));
398
+ };
399
+ exports.isSupplierIgnored = isSupplierIgnored;
400
+ //# sourceMappingURL=pennylane.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pennylane.js","sourceRoot":"","sources":["../../src/billing/pennylane.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.canSendToPennylane = exports.PENNYLANE_SENDER_ROLES = void 0;
4
+ const auth_1 = require("../auth");
5
+ /**
6
+ * Roles que pueden enviar una factura a PennyLane.
7
+ *
8
+ * Deliberadamente corto: enviar una factura crea un asiento en la contabilidad
9
+ * real de la empresa y, cuando se transmite a la plataforma agréée, sale de
10
+ * Articho hacia un tercero. No es una acción reversible desde aquí.
11
+ *
12
+ * Un agent puede preparar la factura y rellenar los datos del tercero; el
13
+ * envío lo hace un administrador.
14
+ */
15
+ exports.PENNYLANE_SENDER_ROLES = [auth_1.ROLE.ADMIN, auth_1.ROLE.OWNER, auth_1.ROLE.SUPERADMIN];
16
+ /**
17
+ * Única fuente de verdad sobre quién puede enviar a PennyLane. La usan tanto
18
+ * la interfaz (para no mostrar el botón) como las Cloud Functions (para
19
+ * rechazar la llamada). Si divergieran, el botón aparecería para gente a la
20
+ * que después le rebotaría el envío.
21
+ *
22
+ * @param {ROLE} role Rol del perfil que intenta enviar.
23
+ * @return {boolean} true si puede enviar.
24
+ */
25
+ const canSendToPennylane = (role) => !!role && exports.PENNYLANE_SENDER_ROLES.includes(role);
26
+ exports.canSendToPennylane = canSendToPennylane;
27
+ //# sourceMappingURL=permissions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"permissions.js","sourceRoot":"","sources":["../../src/billing/permissions.ts"],"names":[],"mappings":";;;AAAA,kCAA+B;AAE/B;;;;;;;;;GASG;AACU,QAAA,sBAAsB,GAAW,CAAC,WAAI,CAAC,KAAK,EAAE,WAAI,CAAC,KAAK,EAAE,WAAI,CAAC,UAAU,CAAC,CAAC;AAExF;;;;;;;;GAQG;AACI,MAAM,kBAAkB,GAAG,CAAC,IAA2B,EAAW,EAAE,CACzE,CAAC,CAAC,IAAI,IAAI,8BAAsB,CAAC,QAAQ,CAAC,IAAY,CAAC,CAAC;AAD7C,QAAA,kBAAkB,sBAC2B"}