@lucianpacurar/iso20022.js 0.2.7 → 0.2.9

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.
package/dist/index.mjs CHANGED
@@ -7744,13 +7744,15 @@ class SEPACreditPaymentInitiation extends PaymentInitiation {
7744
7744
  CtrlSum: this.formattedPaymentSum,
7745
7745
  InitgPty: {
7746
7746
  Nm: this.initiatingParty.name,
7747
- Id: {
7748
- OrgId: {
7749
- Othr: {
7750
- Id: this.initiatingParty.id,
7747
+ ...(this.initiatingParty.id && {
7748
+ Id: {
7749
+ OrgId: {
7750
+ Othr: {
7751
+ Id: this.initiatingParty.id,
7752
+ },
7751
7753
  },
7752
7754
  },
7753
- },
7755
+ }),
7754
7756
  },
7755
7757
  },
7756
7758
  PmtInf: {
@@ -7838,6 +7840,311 @@ class SEPACreditPaymentInitiation extends PaymentInitiation {
7838
7840
  }
7839
7841
  }
7840
7842
 
7843
+ /**
7844
+ * Represents a SEPA Multi Credit Payment Initiation.
7845
+ * This class handles the creation and serialization of SEPA credit transfer messages
7846
+ * with multiple payment information blocks (multiple debtors) according to the ISO20022 standard.
7847
+ * @class
7848
+ * @extends PaymentInitiation
7849
+ * @param {SEPAMultiCreditPaymentInitiationConfig} config - The configuration for the SEPA Multi Credit Payment Initiation message.
7850
+ * @example
7851
+ * ```typescript
7852
+ * // Creating a SEPA multi-payment message
7853
+ * const payment = new SEPAMultiCreditPaymentInitiation({
7854
+ * initiatingParty: { name: 'Company Ltd', id: '12345' },
7855
+ * paymentInstructions: [
7856
+ * {
7857
+ * initiatingParty: debtor1,
7858
+ * payments: [payment1, payment2]
7859
+ * },
7860
+ * {
7861
+ * initiatingParty: debtor2,
7862
+ * payments: [payment3]
7863
+ * }
7864
+ * ]
7865
+ * });
7866
+ * ```
7867
+ */
7868
+ class SEPAMultiCreditPaymentInitiation extends PaymentInitiation {
7869
+ initiatingParty;
7870
+ messageId;
7871
+ creationDate;
7872
+ paymentInstructions;
7873
+ paymentInformationIdBase;
7874
+ formattedPaymentSum;
7875
+ totalTransactionCount;
7876
+ /**
7877
+ * Creates an instance of SEPAMultiCreditPaymentInitiation.
7878
+ * @param {SEPAMultiCreditPaymentInitiationConfig} config - The configuration object for the SEPA multi credit transfer.
7879
+ */
7880
+ constructor(config) {
7881
+ super({ type: "sepa" });
7882
+ this.initiatingParty = config.initiatingParty;
7883
+ this.paymentInstructions = config.paymentInstructions;
7884
+ this.messageId = config.messageId || v4().replace(/-/g, '');
7885
+ this.creationDate = config.creationDate || new Date();
7886
+ this.paymentInformationIdBase = sanitize(v4(), 35);
7887
+ this.totalTransactionCount = this.countAllTransactions();
7888
+ this.formattedPaymentSum = this.sumAllPayments();
7889
+ this.validate();
7890
+ }
7891
+ /**
7892
+ * Counts the total number of transactions across all payment instruction groups.
7893
+ * @private
7894
+ * @returns {number} The total count of all transactions.
7895
+ */
7896
+ countAllTransactions() {
7897
+ return this.paymentInstructions.reduce((total, group) => {
7898
+ return total + group.payments.length;
7899
+ }, 0);
7900
+ }
7901
+ /**
7902
+ * Calculates the sum of all payment instructions across all groups.
7903
+ * @private
7904
+ * @returns {string} The total sum formatted as a string with 2 decimal places.
7905
+ */
7906
+ sumAllPayments() {
7907
+ let totalAmount = 0;
7908
+ let currency = null;
7909
+ for (const group of this.paymentInstructions) {
7910
+ for (const payment of group.payments) {
7911
+ if (currency === null) {
7912
+ currency = payment.currency;
7913
+ }
7914
+ totalAmount += payment.amount;
7915
+ }
7916
+ }
7917
+ if (currency === null) {
7918
+ throw new Error('No payments found');
7919
+ }
7920
+ return Dinero({ amount: totalAmount, currency }).toFormat('0.00');
7921
+ }
7922
+ /**
7923
+ * Calculates the sum of payment instructions for a single group.
7924
+ * @private
7925
+ * @param {AtLeastOne<SEPACreditPaymentInstruction>} payments - Array of payment instructions.
7926
+ * @returns {string} The total sum formatted as a string with 2 decimal places.
7927
+ * @throws {Error} If payment instructions have different currencies.
7928
+ */
7929
+ sumPaymentInstructions(payments) {
7930
+ this.validateGroupInstructionsHaveSameCurrency(payments);
7931
+ const instructionDineros = payments.map(instruction => Dinero({ amount: instruction.amount, currency: instruction.currency }));
7932
+ return instructionDineros.reduce((acc, next) => {
7933
+ return acc.add(next);
7934
+ }, Dinero({ amount: 0, currency: payments[0].currency })).toFormat('0.00');
7935
+ }
7936
+ /**
7937
+ * Validates the payment initiation data according to SEPA requirements.
7938
+ * @private
7939
+ * @throws {Error} If messageId exceeds 35 characters.
7940
+ * @throws {Error} If any group's payment instructions have different currencies.
7941
+ */
7942
+ validate() {
7943
+ if (this.messageId.length > 35) {
7944
+ throw new Error('messageId must not exceed 35 characters');
7945
+ }
7946
+ // Validate each group has same currency within its payments
7947
+ for (const group of this.paymentInstructions) {
7948
+ this.validateGroupInstructionsHaveSameCurrency(group.payments);
7949
+ }
7950
+ }
7951
+ /**
7952
+ * Validates that all payment instructions in a group have the same currency.
7953
+ * @private
7954
+ * @param {AtLeastOne<SEPACreditPaymentInstruction>} payments - Array of payment instructions.
7955
+ * @throws {Error} If payment instructions have different currencies.
7956
+ */
7957
+ validateGroupInstructionsHaveSameCurrency(payments) {
7958
+ if (!payments.every((i) => { return i.currency === payments[0].currency; })) {
7959
+ throw new Error("In order to calculate the payment instructions sum, all payment instruction currencies within a group must be the same.");
7960
+ }
7961
+ }
7962
+ /**
7963
+ * Generates payment information for a single SEPA credit transfer instruction.
7964
+ * @param {SEPACreditPaymentInstruction} instruction - The payment instruction.
7965
+ * @returns {Object} The payment information object formatted according to SEPA specifications.
7966
+ */
7967
+ creditTransfer(instruction) {
7968
+ const paymentInstructionId = sanitize(instruction.id || v4(), 35);
7969
+ const endToEndId = sanitize(instruction.endToEndId || instruction.id || v4(), 35);
7970
+ const dinero = Dinero({ amount: instruction.amount, currency: instruction.currency });
7971
+ return {
7972
+ PmtId: {
7973
+ InstrId: paymentInstructionId,
7974
+ EndToEndId: endToEndId,
7975
+ },
7976
+ Amt: {
7977
+ InstdAmt: {
7978
+ '#': dinero.toFormat('0.00'),
7979
+ '@Ccy': instruction.currency,
7980
+ },
7981
+ },
7982
+ ...(instruction.creditor.agent && { CdtrAgt: this.agent(instruction.creditor.agent) }),
7983
+ Cdtr: this.party(instruction.creditor),
7984
+ CdtrAcct: {
7985
+ Id: { IBAN: instruction.creditor.account.iban },
7986
+ Ccy: instruction.currency,
7987
+ },
7988
+ RmtInf: instruction.remittanceInformation ? {
7989
+ Ustrd: instruction.remittanceInformation,
7990
+ } : undefined,
7991
+ };
7992
+ }
7993
+ /**
7994
+ * Serializes the SEPA multi credit transfer initiation to an XML string.
7995
+ * @returns {string} The XML representation of the SEPA multi credit transfer initiation.
7996
+ */
7997
+ serialize() {
7998
+ const builder = PaymentInitiation.getBuilder();
7999
+ // Generate multiple PmtInf entries, one per payment instruction group
8000
+ const paymentInfoEntries = this.paymentInstructions.map((group, index) => {
8001
+ const groupSum = this.sumPaymentInstructions(group.payments);
8002
+ const pmtInfId = sanitize(`${this.paymentInformationIdBase}-${index + 1}`, 35);
8003
+ return {
8004
+ PmtInfId: pmtInfId,
8005
+ PmtMtd: 'TRF',
8006
+ NbOfTxs: group.payments.length.toString(),
8007
+ CtrlSum: groupSum,
8008
+ PmtTpInf: {
8009
+ SvcLvl: { Cd: 'SEPA' },
8010
+ ...(group.categoryPurpose && {
8011
+ CtgyPurp: { Cd: group.categoryPurpose }
8012
+ }),
8013
+ },
8014
+ ReqdExctnDt: this.creationDate.toISOString().split('T')[0],
8015
+ Dbtr: this.party(group.initiatingParty),
8016
+ DbtrAcct: this.account(group.initiatingParty.account),
8017
+ DbtrAgt: this.agent(group.initiatingParty.agent),
8018
+ ChrgBr: 'SLEV',
8019
+ CdtTrfTxInf: group.payments.map(p => this.creditTransfer(p)),
8020
+ };
8021
+ });
8022
+ const xml = {
8023
+ '?xml': {
8024
+ '@version': '1.0',
8025
+ '@encoding': 'UTF-8'
8026
+ },
8027
+ Document: {
8028
+ '@xmlns': 'urn:iso:std:iso:20022:tech:xsd:pain.001.001.03',
8029
+ '@xmlns:xsi': 'http://www.w3.org/2001/XMLSchema-instance',
8030
+ CstmrCdtTrfInitn: {
8031
+ GrpHdr: {
8032
+ MsgId: this.messageId,
8033
+ CreDtTm: this.creationDate.toISOString(),
8034
+ NbOfTxs: this.totalTransactionCount.toString(),
8035
+ CtrlSum: this.formattedPaymentSum,
8036
+ InitgPty: {
8037
+ Nm: this.initiatingParty.name,
8038
+ ...(this.initiatingParty.id && {
8039
+ Id: {
8040
+ OrgId: {
8041
+ Othr: {
8042
+ Id: this.initiatingParty.id,
8043
+ },
8044
+ },
8045
+ },
8046
+ }),
8047
+ },
8048
+ },
8049
+ PmtInf: paymentInfoEntries,
8050
+ }
8051
+ },
8052
+ };
8053
+ return builder.build(xml);
8054
+ }
8055
+ /**
8056
+ * Parses an XML string and creates a SEPAMultiCreditPaymentInitiation instance.
8057
+ * Supports multiple PmtInf blocks in the XML document.
8058
+ * @param {string} rawXml - The XML string to parse.
8059
+ * @returns {SEPAMultiCreditPaymentInitiation} A new instance created from the XML data.
8060
+ * @throws {InvalidXmlError} If the XML format is invalid.
8061
+ * @throws {InvalidXmlNamespaceError} If the namespace is not pain.001.001.03.
8062
+ */
8063
+ static fromXML(rawXml) {
8064
+ const parser = new fxp.XMLParser({ ignoreAttributes: false });
8065
+ const xml = parser.parse(rawXml);
8066
+ // Validate XML structure
8067
+ if (!xml.Document) {
8068
+ throw new InvalidXmlError("Invalid XML format");
8069
+ }
8070
+ // Validate namespace
8071
+ const namespace = (xml.Document['@_xmlns'] || xml.Document['@_Xmlns']);
8072
+ if (!namespace.startsWith('urn:iso:std:iso:20022:tech:xsd:pain.001.001.03')) {
8073
+ throw new InvalidXmlNamespaceError('Invalid PAIN.001 namespace');
8074
+ }
8075
+ // Extract GrpHdr data
8076
+ const messageId = xml.Document.CstmrCdtTrfInitn.GrpHdr.MsgId;
8077
+ const creationDate = new Date(xml.Document.CstmrCdtTrfInitn.GrpHdr.CreDtTm);
8078
+ // Extract top-level initiating party from GrpHdr
8079
+ const topLevelInitiatingParty = {
8080
+ name: xml.Document.CstmrCdtTrfInitn.GrpHdr.InitgPty.Nm,
8081
+ id: xml.Document.CstmrCdtTrfInitn.GrpHdr.InitgPty.Id?.OrgId?.Othr?.Id,
8082
+ };
8083
+ // Normalize PmtInf to array (handle both single object and array cases)
8084
+ const rawPmtInf = Array.isArray(xml.Document.CstmrCdtTrfInitn.PmtInf)
8085
+ ? xml.Document.CstmrCdtTrfInitn.PmtInf
8086
+ : [xml.Document.CstmrCdtTrfInitn.PmtInf];
8087
+ // Map each PmtInf to SEPAMultiCreditPaymentInstructionGroup
8088
+ const paymentInstructions = rawPmtInf.map((pmtInf) => {
8089
+ // Extract debtor info as the group's initiating party
8090
+ const groupInitiatingParty = {
8091
+ name: pmtInf.Dbtr.Nm,
8092
+ id: pmtInf.Dbtr.Id?.OrgId?.Othr?.Id,
8093
+ agent: parseAgent(pmtInf.DbtrAgt),
8094
+ account: parseAccount(pmtInf.DbtrAcct),
8095
+ };
8096
+ // Extract optional category purpose
8097
+ const categoryPurpose = pmtInf.PmtTpInf?.CtgyPurp?.Cd;
8098
+ // Normalize CdtTrfTxInf to array
8099
+ const rawInstructions = Array.isArray(pmtInf.CdtTrfTxInf)
8100
+ ? pmtInf.CdtTrfTxInf
8101
+ : [pmtInf.CdtTrfTxInf];
8102
+ // Parse each CdtTrfTxInf to SEPACreditPaymentInstruction
8103
+ const payments = rawInstructions.map((inst) => {
8104
+ const currency = inst.Amt.InstdAmt['@_Ccy'];
8105
+ const amount = parseAmountToMinorUnits(Number(inst.Amt.InstdAmt['#text']), currency);
8106
+ const rawPostalAddress = inst.Cdtr.PstlAdr;
8107
+ return {
8108
+ ...(inst.PmtId.InstrId && { id: inst.PmtId.InstrId.toString() }),
8109
+ ...(inst.PmtId.EndToEndId && { endToEndId: inst.PmtId.EndToEndId.toString() }),
8110
+ type: 'sepa',
8111
+ direction: 'credit',
8112
+ amount: amount,
8113
+ currency: currency,
8114
+ creditor: {
8115
+ name: inst.Cdtr?.Nm,
8116
+ agent: parseAgent(inst.CdtrAgt),
8117
+ account: parseAccount(inst.CdtrAcct),
8118
+ ...((rawPostalAddress && (rawPostalAddress.StrtNm || rawPostalAddress.BldgNb || rawPostalAddress.PstCd || rawPostalAddress.TwnNm || rawPostalAddress.Ctry)) ? {
8119
+ address: {
8120
+ ...(rawPostalAddress.StrtNm && { streetName: rawPostalAddress.StrtNm.toString() }),
8121
+ ...(rawPostalAddress.BldgNb && { buildingNumber: rawPostalAddress.BldgNb.toString() }),
8122
+ ...(rawPostalAddress.TwnNm && { townName: rawPostalAddress.TwnNm.toString() }),
8123
+ ...(rawPostalAddress.CtrySubDvsn && { countrySubDivision: rawPostalAddress.CtrySubDvsn.toString() }),
8124
+ ...(rawPostalAddress.PstCd && { postalCode: rawPostalAddress.PstCd.toString() }),
8125
+ ...(rawPostalAddress.Ctry && { country: rawPostalAddress.Ctry }),
8126
+ }
8127
+ } : {}),
8128
+ },
8129
+ ...(inst.RmtInf?.Ustrd && { remittanceInformation: inst.RmtInf.Ustrd.toString() })
8130
+ };
8131
+ });
8132
+ return {
8133
+ initiatingParty: groupInitiatingParty,
8134
+ payments: payments,
8135
+ ...(categoryPurpose && { categoryPurpose }),
8136
+ };
8137
+ });
8138
+ // Return new instance
8139
+ return new SEPAMultiCreditPaymentInitiation({
8140
+ messageId: messageId,
8141
+ creationDate: creationDate,
8142
+ initiatingParty: topLevelInitiatingParty,
8143
+ paymentInstructions: paymentInstructions,
8144
+ });
8145
+ }
8146
+ }
8147
+
7841
8148
  /**
7842
8149
  * Represents a RTP Credit Payment Initiation.
7843
8150
  * This class handles the creation and serialization of RTP credit transfer messages
@@ -9565,6 +9872,45 @@ class ISO20022 {
9565
9872
  creationDate: config.creationDate,
9566
9873
  });
9567
9874
  }
9875
+ /**
9876
+ * Creates a SEPA Multi Credit Payment Initiation message with multiple payment information blocks.
9877
+ * @param {SEPAMultiCreditPaymentInitiationConfig} config - Configuration containing payment instruction groups and optional parameters.
9878
+ * @example
9879
+ * const payment = iso20022.createSEPAMultiCreditPaymentInitiation({
9880
+ * paymentInstructions: [
9881
+ * {
9882
+ * initiatingParty: debtor1,
9883
+ * payments: [
9884
+ * {
9885
+ * type: 'sepa',
9886
+ * direction: 'credit',
9887
+ * amount: 1000, // €10.00 Euros
9888
+ * currency: 'EUR',
9889
+ * creditor: {
9890
+ * name: 'Hans Schneider',
9891
+ * account: {
9892
+ * iban: 'DE1234567890123456',
9893
+ * },
9894
+ * },
9895
+ * remittanceInformation: 'Invoice payment #123',
9896
+ * },
9897
+ * ],
9898
+ * categoryPurpose: 'SALA', // Optional
9899
+ * },
9900
+ * ],
9901
+ * messageId: 'SEPA-MULTI-MSG-001', // Optional
9902
+ * creationDate: new Date('2025-03-01'), // Optional
9903
+ * });
9904
+ * @returns {SEPAMultiCreditPaymentInitiation} A new SEPA Multi Credit Payment Initiation object.
9905
+ */
9906
+ createSEPAMultiCreditPaymentInitiation(config) {
9907
+ return new SEPAMultiCreditPaymentInitiation({
9908
+ initiatingParty: this.initiatingParty,
9909
+ paymentInstructions: config.paymentInstructions,
9910
+ messageId: config.messageId,
9911
+ creationDate: config.creationDate,
9912
+ });
9913
+ }
9568
9914
  /**
9569
9915
  * Creates a RTP Credit Payment Initiation message.
9570
9916
  * @param {RTPCreditPaymentInitiationConfig} config - Configuration containing payment instructions and optional parameters.
@@ -10020,4 +10366,4 @@ class CashManagementEndOfDayReport {
10020
10366
  }
10021
10367
  registerISO20022Implementation(CashManagementEndOfDayReport);
10022
10368
 
10023
- export { ACHCreditPaymentInitiation, ACHLocalInstrumentCode, ACHLocalInstrumentCodeDescriptionMap, BalanceTypeCode, BalanceTypeCodeDescriptionMap, CashManagementEndOfDayReport, ISO20022, InvalidXmlError, InvalidXmlNamespaceError, Iso20022JsError, PaymentStatusCode, PaymentStatusReport, RTPCreditPaymentInitiation, SEPACreditPaymentInitiation, SWIFTCreditPaymentInitiation };
10369
+ export { ACHCreditPaymentInitiation, ACHLocalInstrumentCode, ACHLocalInstrumentCodeDescriptionMap, BalanceTypeCode, BalanceTypeCodeDescriptionMap, CashManagementEndOfDayReport, ISO20022, InvalidXmlError, InvalidXmlNamespaceError, Iso20022JsError, PaymentStatusCode, PaymentStatusReport, RTPCreditPaymentInitiation, SEPACreditPaymentInitiation, SEPAMultiCreditPaymentInitiation, SWIFTCreditPaymentInitiation };
@@ -48,6 +48,8 @@ export type { SWIFTCreditPaymentInitiationConfig } from './pain/001/swift-credit
48
48
  export { SWIFTCreditPaymentInitiation } from './pain/001/swift-credit-payment-initiation';
49
49
  export type { SEPACreditPaymentInitiationConfig } from './pain/001/sepa-credit-payment-initiation';
50
50
  export { SEPACreditPaymentInitiation } from './pain/001/sepa-credit-payment-initiation';
51
+ export type { SEPAMultiCreditPaymentInitiationConfig, SEPAMultiCreditPaymentInstructionGroup } from './pain/001/sepa-multi-credit-payment-initiation';
52
+ export { SEPAMultiCreditPaymentInitiation } from './pain/001/sepa-multi-credit-payment-initiation';
51
53
  export type { RTPCreditPaymentInitiationConfig } from './pain/001/rtp-credit-payment-initiation';
52
54
  export { RTPCreditPaymentInitiation } from './pain/001/rtp-credit-payment-initiation';
53
55
  export type { ACHCreditPaymentInitiationConfig } from './pain/001/ach-credit-payment-initiation';
@@ -1,6 +1,7 @@
1
1
  import { Party, SWIFTCreditPaymentInstruction, SEPACreditPaymentInstruction, RTPCreditPaymentInstruction, ACHCreditPaymentInstruction } from './lib/types.js';
2
2
  import { SWIFTCreditPaymentInitiation } from './pain/001/swift-credit-payment-initiation';
3
3
  import { SEPACreditPaymentInitiation } from './pain/001/sepa-credit-payment-initiation';
4
+ import { SEPAMultiCreditPaymentInitiation, SEPAMultiCreditPaymentInstructionGroup } from './pain/001/sepa-multi-credit-payment-initiation';
4
5
  import { RTPCreditPaymentInitiation } from './pain/001/rtp-credit-payment-initiation';
5
6
  import { ACHCreditPaymentInitiation } from './pain/001/ach-credit-payment-initiation';
6
7
  import { GenericISO20022Message, ISO20022MessageTypeName } from './lib/interfaces';
@@ -130,6 +131,53 @@ export interface SEPACreditPaymentInitiationConfig {
130
131
  */
131
132
  creationDate?: Date;
132
133
  }
134
+ /**
135
+ * Configuration interface for SEPA Multi Credit Payment Initiation.
136
+ * @interface SEPAMultiCreditPaymentInitiationConfig
137
+ * @example
138
+ * const config: SEPAMultiCreditPaymentInitiationConfig = {
139
+ * paymentInstructions: [
140
+ * {
141
+ * initiatingParty: debtor1,
142
+ * payments: [
143
+ * {
144
+ * type: 'sepa',
145
+ * direction: 'credit',
146
+ * amount: 1000, // €10.00 Euros
147
+ * currency: 'EUR',
148
+ * creditor: {
149
+ * name: 'Hans Schneider',
150
+ * account: {
151
+ * iban: 'DE1234567890123456',
152
+ * },
153
+ * },
154
+ * remittanceInformation: 'Invoice payment #123',
155
+ * },
156
+ * ],
157
+ * categoryPurpose: 'SALA', // Optional
158
+ * },
159
+ * ],
160
+ * messageId: 'MSGID123', // Optional
161
+ * creationDate: new Date(), // Optional
162
+ * };
163
+ */
164
+ export interface SEPAMultiCreditPaymentInitiationConfig {
165
+ /**
166
+ * An array of payment instruction groups, each with its own debtor.
167
+ * @type {AtLeastOne<SEPAMultiCreditPaymentInstructionGroup>}
168
+ */
169
+ paymentInstructions: AtLeastOne<SEPAMultiCreditPaymentInstructionGroup>;
170
+ /**
171
+ * Optional unique identifier for the message. If not provided, a UUID will be generated.
172
+ * @type {string}
173
+ */
174
+ messageId?: string;
175
+ /**
176
+ * Optional creation date for the message. If not provided, current date will be used.
177
+ * @type {Date}
178
+ */
179
+ creationDate?: Date;
180
+ }
133
181
  /**
134
182
  * Configuration interface for RTP Credit Payment Initiation.
135
183
  * @interface RTPCreditPaymentInitiationConfig
@@ -311,6 +359,38 @@ declare class ISO20022 {
311
359
  * @returns {SEPACreditPaymentInitiation} A new SEPA Credit Payment Initiation object.
312
360
  */
313
361
  createSEPACreditPaymentInitiation(config: SEPACreditPaymentInitiationConfig): SEPACreditPaymentInitiation;
362
+ /**
363
+ * Creates a SEPA Multi Credit Payment Initiation message with multiple payment information blocks.
364
+ * @param {SEPAMultiCreditPaymentInitiationConfig} config - Configuration containing payment instruction groups and optional parameters.
365
+ * @example
366
+ * const payment = iso20022.createSEPAMultiCreditPaymentInitiation({
367
+ * paymentInstructions: [
368
+ * {
369
+ * initiatingParty: debtor1,
370
+ * payments: [
371
+ * {
372
+ * type: 'sepa',
373
+ * direction: 'credit',
374
+ * amount: 1000, // €10.00 Euros
375
+ * currency: 'EUR',
376
+ * creditor: {
377
+ * name: 'Hans Schneider',
378
+ * account: {
379
+ * iban: 'DE1234567890123456',
380
+ * },
381
+ * },
382
+ * remittanceInformation: 'Invoice payment #123',
383
+ * },
384
+ * ],
385
+ * categoryPurpose: 'SALA', // Optional
386
+ * },
387
+ * ],
388
+ * messageId: 'SEPA-MULTI-MSG-001', // Optional
389
+ * creationDate: new Date('2025-03-01'), // Optional
390
+ * });
391
+ * @returns {SEPAMultiCreditPaymentInitiation} A new SEPA Multi Credit Payment Initiation object.
392
+ */
393
+ createSEPAMultiCreditPaymentInitiation(config: SEPAMultiCreditPaymentInitiationConfig): SEPAMultiCreditPaymentInitiation;
314
394
  /**
315
395
  * Creates a RTP Credit Payment Initiation message.
316
396
  * @param {RTPCreditPaymentInitiationConfig} config - Configuration containing payment instructions and optional parameters.
@@ -0,0 +1,167 @@
1
+ import type { ExternalCategoryPurpose, Party, SEPACreditPaymentInstruction } from "../../lib/types";
2
+ import { PaymentInitiation } from './payment-initiation';
3
+ type AtLeastOne<T> = [T, ...T[]];
4
+ /**
5
+ * Represents a group of payment instructions for a single debtor (PmtInf block).
6
+ *
7
+ * @property {Party} initiatingParty - The party (debtor) for this specific payment information block.
8
+ * @property {AtLeastOne<SEPACreditPaymentInstruction>} payments - An array containing at least one payment instruction for this debtor.
9
+ * @property {ExternalCategoryPurpose} [categoryPurpose] - Optional category purpose code for this payment information block.
10
+ */
11
+ export interface SEPAMultiCreditPaymentInstructionGroup {
12
+ /** The party (debtor) for this specific payment information block. */
13
+ initiatingParty: Party;
14
+ /** An array containing at least one payment instruction for this debtor. */
15
+ payments: AtLeastOne<SEPACreditPaymentInstruction>;
16
+ /** Optional category purpose code for this payment information block. */
17
+ categoryPurpose?: ExternalCategoryPurpose;
18
+ }
19
+ /**
20
+ * Configuration for SEPA Multi Credit Payment Initiation.
21
+ *
22
+ * @property {Party} initiatingParty - The top-level party initiating the message (used in GrpHdr).
23
+ * @property {AtLeastOne<SEPAMultiCreditPaymentInstructionGroup>} paymentInstructions - An array containing at least one payment instruction group.
24
+ * @property {string} [messageId] - Optional unique identifier for the message. If not provided, a UUID will be generated.
25
+ * @property {Date} [creationDate] - Optional creation date for the message. If not provided, current date will be used.
26
+ */
27
+ export interface SEPAMultiCreditPaymentInitiationConfig {
28
+ /** The top-level party initiating the message (used in GrpHdr). */
29
+ initiatingParty: Party;
30
+ /** An array containing at least one payment instruction group. */
31
+ paymentInstructions: AtLeastOne<SEPAMultiCreditPaymentInstructionGroup>;
32
+ /** Optional unique identifier for the message. If not provided, a UUID will be generated. */
33
+ messageId?: string;
34
+ /** Optional creation date for the message. If not provided, current date will be used. */
35
+ creationDate?: Date;
36
+ }
37
+ /**
38
+ * Represents a SEPA Multi Credit Payment Initiation.
39
+ * This class handles the creation and serialization of SEPA credit transfer messages
40
+ * with multiple payment information blocks (multiple debtors) according to the ISO20022 standard.
41
+ * @class
42
+ * @extends PaymentInitiation
43
+ * @param {SEPAMultiCreditPaymentInitiationConfig} config - The configuration for the SEPA Multi Credit Payment Initiation message.
44
+ * @example
45
+ * ```typescript
46
+ * // Creating a SEPA multi-payment message
47
+ * const payment = new SEPAMultiCreditPaymentInitiation({
48
+ * initiatingParty: { name: 'Company Ltd', id: '12345' },
49
+ * paymentInstructions: [
50
+ * {
51
+ * initiatingParty: debtor1,
52
+ * payments: [payment1, payment2]
53
+ * },
54
+ * {
55
+ * initiatingParty: debtor2,
56
+ * payments: [payment3]
57
+ * }
58
+ * ]
59
+ * });
60
+ * ```
61
+ */
62
+ export declare class SEPAMultiCreditPaymentInitiation extends PaymentInitiation {
63
+ initiatingParty: Party;
64
+ messageId: string;
65
+ creationDate: Date;
66
+ paymentInstructions: AtLeastOne<SEPAMultiCreditPaymentInstructionGroup>;
67
+ paymentInformationIdBase: string;
68
+ private formattedPaymentSum;
69
+ private totalTransactionCount;
70
+ /**
71
+ * Creates an instance of SEPAMultiCreditPaymentInitiation.
72
+ * @param {SEPAMultiCreditPaymentInitiationConfig} config - The configuration object for the SEPA multi credit transfer.
73
+ */
74
+ constructor(config: SEPAMultiCreditPaymentInitiationConfig);
75
+ /**
76
+ * Counts the total number of transactions across all payment instruction groups.
77
+ * @private
78
+ * @returns {number} The total count of all transactions.
79
+ */
80
+ private countAllTransactions;
81
+ /**
82
+ * Calculates the sum of all payment instructions across all groups.
83
+ * @private
84
+ * @returns {string} The total sum formatted as a string with 2 decimal places.
85
+ */
86
+ private sumAllPayments;
87
+ /**
88
+ * Calculates the sum of payment instructions for a single group.
89
+ * @private
90
+ * @param {AtLeastOne<SEPACreditPaymentInstruction>} payments - Array of payment instructions.
91
+ * @returns {string} The total sum formatted as a string with 2 decimal places.
92
+ * @throws {Error} If payment instructions have different currencies.
93
+ */
94
+ private sumPaymentInstructions;
95
+ /**
96
+ * Validates the payment initiation data according to SEPA requirements.
97
+ * @private
98
+ * @throws {Error} If messageId exceeds 35 characters.
99
+ * @throws {Error} If any group's payment instructions have different currencies.
100
+ */
101
+ private validate;
102
+ /**
103
+ * Validates that all payment instructions in a group have the same currency.
104
+ * @private
105
+ * @param {AtLeastOne<SEPACreditPaymentInstruction>} payments - Array of payment instructions.
106
+ * @throws {Error} If payment instructions have different currencies.
107
+ */
108
+ private validateGroupInstructionsHaveSameCurrency;
109
+ /**
110
+ * Generates payment information for a single SEPA credit transfer instruction.
111
+ * @param {SEPACreditPaymentInstruction} instruction - The payment instruction.
112
+ * @returns {Object} The payment information object formatted according to SEPA specifications.
113
+ */
114
+ creditTransfer(instruction: SEPACreditPaymentInstruction): {
115
+ Cdtr: any;
116
+ CdtrAcct: {
117
+ Id: {
118
+ IBAN: string;
119
+ };
120
+ Ccy: "EUR";
121
+ };
122
+ RmtInf: {
123
+ Ustrd: string;
124
+ } | undefined;
125
+ CdtrAgt?: {
126
+ FinInstnId: {
127
+ BIC: string;
128
+ ClrSysMmbId?: undefined;
129
+ };
130
+ } | {
131
+ FinInstnId: {
132
+ ClrSysMmbId: {
133
+ ClrSysId: {
134
+ Cd: string;
135
+ };
136
+ MmbId: string;
137
+ };
138
+ BIC?: undefined;
139
+ };
140
+ } | undefined;
141
+ PmtId: {
142
+ InstrId: string;
143
+ EndToEndId: string;
144
+ };
145
+ Amt: {
146
+ InstdAmt: {
147
+ '#': string;
148
+ '@Ccy': "EUR";
149
+ };
150
+ };
151
+ };
152
+ /**
153
+ * Serializes the SEPA multi credit transfer initiation to an XML string.
154
+ * @returns {string} The XML representation of the SEPA multi credit transfer initiation.
155
+ */
156
+ serialize(): string;
157
+ /**
158
+ * Parses an XML string and creates a SEPAMultiCreditPaymentInitiation instance.
159
+ * Supports multiple PmtInf blocks in the XML document.
160
+ * @param {string} rawXml - The XML string to parse.
161
+ * @returns {SEPAMultiCreditPaymentInitiation} A new instance created from the XML data.
162
+ * @throws {InvalidXmlError} If the XML format is invalid.
163
+ * @throws {InvalidXmlNamespaceError} If the namespace is not pain.001.001.03.
164
+ */
165
+ static fromXML(rawXml: string): SEPAMultiCreditPaymentInitiation;
166
+ }
167
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lucianpacurar/iso20022.js",
3
- "version": "0.2.7",
3
+ "version": "0.2.9",
4
4
  "readme": "README.md",
5
5
  "description": "Library to create payment messages.",
6
6
  "main": "dist/index.js",