package pain import ( "fmt" "strings" ) type DrctDbtTxInf struct { Id PaymentId `xml:"PmtId"` Amount CurrencyWithAmount `xml:"InstdAmt"` Transaction DrctDbtTx `xml:"DrctDbtTx"` Agent DbtrAgt `xml:"DbtrAgt"` Debtor Dbtr `xml:"Dbtr"` Account DbtrAcct `xml:"DbtrAcct"` Info RmtInf `xml:"RmtInf"` } func NewDirectDebitTransaction(debtor Dbtr, account DbtrAcct, mandateInfo MndtRltdInf, amount float64, additionalInfo string) DrctDbtTxInf { e2eid := fmt.Sprintf("%v%4d", time.Now().Format("20060102"), 4) // TODO: inform this function of current number of transactions return DrctDbtTxInf{ Id: PaymentId{ InstrumentId: "asdfasdf", EndToEndId: e2eid, }, Amount: CurrencyWithAmount{ Currency: "EUR", Value: fmt.Sprintf("%.2f", amount), }, Transaction: DrctDbtTx{ MandateRelatedInfo: mandateInfo, }, Agent: DbtrAgt{ InstitutionId: FinInstnId{ BIC: "KNABNL2H", // fixme }, }, Debtor: debtor, Account: account, Info: additionalInfo, } } func (d *DrctDbtTxInf) Valid() error { var err []string if e := d.Id.Valid(); e != nil { err = append(err, fmt.Sprintf("%v", e)) } if e := d.Amount.Valid(); e != nil { err = append(err, fmt.Sprintf("%v", e)) } if e := d.Transaction.Valid(); e != nil { err = append(err, fmt.Sprintf("%v", e)) } if e := d.Agent.Valid(); e != nil { err = append(err, fmt.Sprintf("%v", e)) } if e := d.Debtor.Valid(); e != nil { err = append(err, fmt.Sprintf("%v", e)) } if e := d.Account.Valid(); e != nil { err = append(err, fmt.Sprintf("%v", e)) } if len(err) > 0 { return fmt.Errorf("direct debit transaction information not valid: %v", strings.Join(err, ", ")) } return nil } type CurrencyWithAmount struct { Currency string `xml:"Ccy,attr"` Value string `xml:",innerxml"` } func (c *CurrencyWithAmount) Valid() error { var err []string if c.Currency != "EUR" { err = append(err, "expected Ccy EUR") } if !SEPARegexps["InstdAmnt"].MatchString(c.Value) { err = append(err, "value does not match format") } if len(err) > 0 { return fmt.Errorf("currency with amount not valid: %v", strings.Join(err, ", ")) } return nil } type PaymentId struct { InstrumentId string `xml:"InstrId"` EndToEndId string `xml:"EndToEndId"` } func (p *PaymentId) Valid() error { var err []string if !SEPARegexps["InstrId"].MatchString(p.InstrumentId) { err = append(err, "instrument id does not match format") } if !SEPARegexps["EndToEndId"].MatchString(p.EndToEndId) { err = append(err, "end-to-end id does not match format") } if len(err) > 0 { return fmt.Errorf("payment id not valid: %v", strings.Join(err, ", ")) } return nil } type MndtRltdInf struct { Id string `xml:"MndtId"` SignatureDate string `xml:"DtOfSgntr"` IsAmended bool `xml:"AmdmntInd"` //AmdmntInfDtls is optional //ElctrncSgntr is optional } func (m *MndtRltdInf) Valid() error { var err []string if !SEPARegexps["MndtId"].MatchString(m.Id) { err = append(err, "mandate id does not match format") } if !SEPARegexps["DtOfSgntr"].MatchString(m.SignatureDate) { err = append(err, "date of signature does not match format") } if len(err) > 0 { return fmt.Errorf("mandate related information is not valid: %v", strings.Join(err, ", ")) } return nil } type DrctDbtTx struct { MandateRelatedInfo MndtRltdInf `xml:"MndtRltdInf"` //CdtrSchemeId is optional } func (d *DrctDbtTx) Valid() error { return d.MandateRelatedInfo.Valid() } type DbtrAgt struct { InstitutionId FinInstnId `xml:"FinInstnId"` } func (d *DbtrAgt) Valid() error { return d.InstitutionId.Valid() } type Dbtr struct { Name string `xml:"Nm"` Address PstlAdr `xml:"PstlAdr"` } func (d *Dbtr) Valid() error { var err []string if !SEPARegexps["Nm"].MatchString(d.Name) { err = append(err, "name does not match format") } if e := d.Address.Valid(); e != nil { err = append(err, fmt.Sprintf("%v", e)) } if len(err) > 0 { return fmt.Errorf("dbtr not valid: %v", strings.Join(err, ", ")) } return nil } type DbtrAcct struct { Id IBAN `xml:"IBAN"` } func (d *DbtrAcct) Valid() error { return d.Id.Valid() } type RmtInf struct { Value string `xml:"Ustrd"` } func (r *RmtInf) Valid() error { if !SEPARegexps["Ustrd"].MatchString(r.Value) { return fmt.Errorf("remittance information does not match format") } return nil }