mirror of
https://github.com/OCA/bank-payment.git
synced 2025-02-02 10:37:31 +02:00
Merge pull request #517 from acsone/11.0-expand-pain-support-sbi
[11.0] expand pain support
This commit is contained in:
@@ -55,6 +55,111 @@ class AccountPaymentLine(models.Model):
|
||||
], string="Category Purpose",
|
||||
help="If neither your bank nor your local regulations oblige you to "
|
||||
"set the category purpose, leave the field empty.")
|
||||
purpose = fields.Selection(
|
||||
# Full category purpose list found on:
|
||||
# https://www.iso20022.org/external_code_list.page
|
||||
# Document "External Code Sets spreadsheet" version 31 August, 2018
|
||||
selection=[
|
||||
('ACCT', 'Account Management'),
|
||||
('CASH', 'Cash Management Transfer'),
|
||||
('COLL', 'Collection Payment'),
|
||||
('INTC', 'Intra Company Payment'),
|
||||
('LIMA', 'Liquidity Management'),
|
||||
('NETT', 'Netting'),
|
||||
('AGRT', 'Agricultural Transfer'),
|
||||
('BEXP', 'Business Expenses'),
|
||||
('COMC', 'Commercial Payment'),
|
||||
('CPYR', 'Copyright'),
|
||||
('GDDS', 'Purchase Sale Of Goods'),
|
||||
('LICF', 'License Fee'),
|
||||
('ROYA', 'Royalties'),
|
||||
('SCVE', 'Purchase Sale Of Services'),
|
||||
('SUBS', 'Subscription'),
|
||||
('SUPP', 'Supplier Payment'),
|
||||
('TRAD', 'Trade Services'),
|
||||
('CHAR', 'Charity Payment'),
|
||||
('COMT', 'Consumer Third Party Consolidated Payment'),
|
||||
('CLPR', 'Car Loan Principal Repayment'),
|
||||
('GOVI', 'Government Insurance'),
|
||||
('HLRP', 'Housing Loan Repayment'),
|
||||
('INSU', 'Insurance Premium'),
|
||||
('INTE', 'Interest'),
|
||||
('LBRI', 'Labor Insurance'),
|
||||
('LIFI', 'Life Insurance'),
|
||||
('LOAN', 'Loan'),
|
||||
('LOAR', 'Loan Repayment'),
|
||||
('PPTI', 'Property Insurance'),
|
||||
('RINP', 'Recurring Installment Payment'),
|
||||
('TRFD', 'Trust Fund'),
|
||||
('ADVA', 'Advance Payment'),
|
||||
('CCRD', 'Credit Card Payment '),
|
||||
('CFEE', 'Cancellation Fee'),
|
||||
('COST', 'Costs'),
|
||||
('DCRD', 'Debit Card Payment'),
|
||||
('GOVT', 'Government Payment'),
|
||||
('IHRP', 'Instalment Hire Purchase Agreement'),
|
||||
('INSM', 'Installment'),
|
||||
('MSVC', 'Multiple Service Types'),
|
||||
('NOWS', 'Not Otherwise Specified'),
|
||||
('OFEE', 'Opening Fee'),
|
||||
('OTHR', 'Other'),
|
||||
('PADD', 'Preauthorized debit'),
|
||||
('PTSP', 'Payment Terms'),
|
||||
('RCPT', 'Receipt Payment'),
|
||||
('RENT', 'Rent'),
|
||||
('STDY', 'Study'),
|
||||
('ANNI', 'Annuity'),
|
||||
('CMDT', 'Commodity Transfer'),
|
||||
('DERI', 'Derivatives'),
|
||||
('DIVD', 'Dividend'),
|
||||
('FREX', 'Foreign Exchange'),
|
||||
('HEDG', 'Hedging'),
|
||||
('PRME', 'Precious Metal'),
|
||||
('SAVG', 'Savings'),
|
||||
('SECU', 'Securities'),
|
||||
('TREA', 'Treasury Payment'),
|
||||
('ANTS', 'Anesthesia Services'),
|
||||
('CVCF', 'Convalescent Care Facility'),
|
||||
('DMEQ', 'Durable Medicale Equipment'),
|
||||
('DNTS', 'Dental Services'),
|
||||
('HLTC', 'Home Health Care'),
|
||||
('HLTI', 'Health Insurance'),
|
||||
('HSPC', 'Hospital Care'),
|
||||
('ICRF', 'Intermediate Care Facility'),
|
||||
('LTCF', 'Long Term Care Facility'),
|
||||
('MDCS', 'Medical Services'),
|
||||
('VIEW', 'Vision Care'),
|
||||
('ALMY', 'Alimony Payment'),
|
||||
('BECH', 'Child Benefit'),
|
||||
('BENE', 'Unemployment Disability Benefit'),
|
||||
('BONU', 'Bonus Payment.'),
|
||||
('COMM', 'Commission'),
|
||||
('PENS', 'Pension Payment'),
|
||||
('PRCP', 'Price Payment'),
|
||||
('SALA', 'Salary Payment'),
|
||||
('SSBE', 'Social Security Benefit'),
|
||||
('ESTX', 'Estate Tax'),
|
||||
('HSTX', 'Housing Tax'),
|
||||
('INTX', 'Income Tax'),
|
||||
('TAXS', 'Tax Payment'),
|
||||
('VATX', 'Value Added Tax Payment'),
|
||||
('AIRB', 'Air'),
|
||||
('BUSB', 'Bus'),
|
||||
('FERB', 'Ferry'),
|
||||
('RLWY', 'Railway'),
|
||||
('CBTV', 'Cable TV Bill'),
|
||||
('ELEC', 'Electricity Bill'),
|
||||
('ENRG', 'Energies'),
|
||||
('GASB', 'Gas Bill'),
|
||||
('NWCH', 'Network Charge'),
|
||||
('NWCM', 'Network Communication'),
|
||||
('OTLC', 'Other Telecom Related Bill'),
|
||||
('PHON', 'Telephone Bill'),
|
||||
('WTER', 'Water Bill'),
|
||||
],
|
||||
help="If neither your bank nor your local regulations oblige you to "
|
||||
"set the category purpose, leave the field empty.",
|
||||
)
|
||||
# PAIN allows 140 characters
|
||||
communication = fields.Char(size=140)
|
||||
# The field struct_communication_type has been dropped in v9
|
||||
|
||||
@@ -27,3 +27,9 @@ class AccountPaymentMode(models.Model):
|
||||
"- Country code (2, optional)\n"
|
||||
"- Company idenfier (N, VAT)\n"
|
||||
"- Service suffix (N, issued by bank)")
|
||||
initiating_party_scheme = fields.Char(
|
||||
string='Initiating Party Scheme', size=35,
|
||||
help="This will be used as the 'Initiating Party Scheme Name' in "
|
||||
"the PAIN files generated by Odoo. This value is determined by the "
|
||||
"financial institution that will process the file. If not defined, "
|
||||
"no scheme will be used.\n")
|
||||
|
||||
@@ -284,6 +284,9 @@ class AccountPaymentOrder(models.Model):
|
||||
initiating_party_issuer = (
|
||||
self.payment_mode_id.initiating_party_issuer or
|
||||
self.payment_mode_id.company_id.initiating_party_issuer)
|
||||
initiating_party_scheme = (
|
||||
self.payment_mode_id.initiating_party_scheme or
|
||||
self.payment_mode_id.company_id.initiating_party_scheme)
|
||||
# in pain.008.001.02.ch.01.xsd files they use
|
||||
# initiating_party_identifier but not initiating_party_issuer
|
||||
if initiating_party_identifier:
|
||||
@@ -292,6 +295,12 @@ class AccountPaymentOrder(models.Model):
|
||||
iniparty_org_other = etree.SubElement(iniparty_org_id, 'Othr')
|
||||
iniparty_org_other_id = etree.SubElement(iniparty_org_other, 'Id')
|
||||
iniparty_org_other_id.text = initiating_party_identifier
|
||||
if initiating_party_scheme:
|
||||
iniparty_org_other_scheme = etree.SubElement(
|
||||
iniparty_org_other, 'SchmeNm')
|
||||
iniparty_org_other_scheme_name = etree.SubElement(
|
||||
iniparty_org_other_scheme, 'Prtry')
|
||||
iniparty_org_other_scheme_name.text = initiating_party_scheme
|
||||
if initiating_party_issuer:
|
||||
iniparty_org_other_issuer = etree.SubElement(
|
||||
iniparty_org_other, 'Issr')
|
||||
@@ -341,6 +350,16 @@ class AccountPaymentOrder(models.Model):
|
||||
# as per the guidelines of the EPC
|
||||
return True
|
||||
|
||||
@api.model
|
||||
def generate_party_id(
|
||||
self, parent_node, party_type, partner):
|
||||
"""Generate an Id element for partner inside the parent node.
|
||||
party_type can currently be Cdtr or Dbtr. Notably, the initiating
|
||||
party orgid is generated with another mechanism and configured
|
||||
at the company or payment mode level.
|
||||
"""
|
||||
return
|
||||
|
||||
@api.model
|
||||
def generate_party_acc_number(
|
||||
self, parent_node, party_type, order, partner_bank, gen_args,
|
||||
@@ -390,6 +409,19 @@ class AccountPaymentOrder(models.Model):
|
||||
partner = partner_bank.partner_id
|
||||
if partner.country_id:
|
||||
postal_address = etree.SubElement(party, 'PstlAdr')
|
||||
if gen_args.get('pain_flavor').startswith(
|
||||
'pain.001.001.') or gen_args.get('pain_flavor').startswith(
|
||||
'pain.008.001.'):
|
||||
if partner.zip:
|
||||
pstcd = etree.SubElement(postal_address, 'PstCd')
|
||||
pstcd.text = self._prepare_field(
|
||||
'Postal Code', 'partner.zip',
|
||||
{'partner': partner}, 16, gen_args=gen_args)
|
||||
if partner.city:
|
||||
twnnm = etree.SubElement(postal_address, 'TwnNm')
|
||||
twnnm.text = self._prepare_field(
|
||||
'Town Name', 'partner.city',
|
||||
{'partner': partner}, 35, gen_args=gen_args)
|
||||
country = etree.SubElement(postal_address, 'Ctry')
|
||||
country.text = self._prepare_field(
|
||||
'Country', 'partner.country_id.code',
|
||||
@@ -399,11 +431,8 @@ class AccountPaymentOrder(models.Model):
|
||||
adrline1.text = self._prepare_field(
|
||||
'Adress Line1', 'partner.street',
|
||||
{'partner': partner}, 70, gen_args=gen_args)
|
||||
if partner.city and partner.zip:
|
||||
adrline2 = etree.SubElement(postal_address, 'AdrLine')
|
||||
adrline2.text = self._prepare_field(
|
||||
'Address Line2', "partner.zip + ' ' + partner.city",
|
||||
{'partner': partner}, 70, gen_args=gen_args)
|
||||
|
||||
self.generate_party_id(party, party_type, partner)
|
||||
|
||||
self.generate_party_acc_number(
|
||||
parent_node, party_type, order, partner_bank, gen_args,
|
||||
|
||||
@@ -14,10 +14,12 @@ class BankPaymentLine(models.Model):
|
||||
string='Local Instrument')
|
||||
category_purpose = fields.Selection(
|
||||
related='payment_line_ids.category_purpose', string='Category Purpose')
|
||||
purpose = fields.Selection(
|
||||
related='payment_line_ids.purpose')
|
||||
|
||||
@api.model
|
||||
def same_fields_payment_line_and_bank_payment_line(self):
|
||||
res = super(BankPaymentLine, self).\
|
||||
same_fields_payment_line_and_bank_payment_line()
|
||||
res += ['priority', 'local_instrument', 'category_purpose']
|
||||
res += ['priority', 'local_instrument', 'category_purpose', 'purpose']
|
||||
return res
|
||||
|
||||
@@ -20,6 +20,10 @@ class ResCompany(models.Model):
|
||||
string='Initiating Party Identifier', size=35,
|
||||
help="This will be used as the 'Initiating Party Identifier' in "
|
||||
"the PAIN files generated by Odoo.")
|
||||
initiating_party_scheme = fields.Char(
|
||||
string='Initiating Party Scheme', size=35,
|
||||
help="This will be used as the 'Initiating Party Scheme Name' in "
|
||||
"the PAIN files generated by Odoo.")
|
||||
|
||||
def _default_initiating_party(self):
|
||||
'''This method is called from post_install.py'''
|
||||
|
||||
@@ -12,6 +12,8 @@ class ResConfigSettings(models.TransientModel):
|
||||
related='company_id.initiating_party_issuer')
|
||||
initiating_party_identifier = fields.Char(
|
||||
related='company_id.initiating_party_identifier')
|
||||
initiating_party_scheme = fields.Char(
|
||||
related='company_id.initiating_party_scheme')
|
||||
group_pain_multiple_identifier = fields.Boolean(
|
||||
string='Multiple identifiers',
|
||||
implied_group='account_banking_pain_base.'
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
<field name="priority"/>
|
||||
<field name="local_instrument"/>
|
||||
<field name="category_purpose"/>
|
||||
<field name="purpose"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
<group name="main" position="inside">
|
||||
<field name="initiating_party_identifier" groups="account_banking_pain_base.group_pain_multiple_identifier"/>
|
||||
<field name="initiating_party_issuer" groups="account_banking_pain_base.group_pain_multiple_identifier"/>
|
||||
<field name="initiating_party_scheme" groups="account_banking_pain_base.group_pain_multiple_identifier"/>
|
||||
</group>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
<field name="priority"/>
|
||||
<field name="local_instrument"/>
|
||||
<field name="category_purpose"/>
|
||||
<field name="purpose"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
@@ -130,6 +130,11 @@ class AccountPaymentOrder(models.Model):
|
||||
payment_info, 'CdtTrfTxInf')
|
||||
payment_identification = etree.SubElement(
|
||||
credit_transfer_transaction_info, 'PmtId')
|
||||
instruction_identification = etree.SubElement(
|
||||
payment_identification, 'InstrId')
|
||||
instruction_identification.text = self._prepare_field(
|
||||
'Instruction Identification', 'line.name',
|
||||
{'line': line}, 35, gen_args=gen_args)
|
||||
end2end_identification = etree.SubElement(
|
||||
payment_identification, 'EndToEndId')
|
||||
end2end_identification.text = self._prepare_field(
|
||||
@@ -153,6 +158,10 @@ class AccountPaymentOrder(models.Model):
|
||||
self.generate_party_block(
|
||||
credit_transfer_transaction_info, 'Cdtr',
|
||||
'C', line.partner_bank_id, gen_args, line)
|
||||
if line.purpose:
|
||||
purpose = etree.SubElement(
|
||||
credit_transfer_transaction_info, 'Purp')
|
||||
etree.SubElement(purpose, 'Cd').text = line.purpose
|
||||
self.generate_remittance_info_block(
|
||||
credit_transfer_transaction_info, line, gen_args)
|
||||
if not pain_flavor.startswith('pain.001.001.02'):
|
||||
|
||||
@@ -156,12 +156,11 @@ class AccountPaymentOrder(models.Model):
|
||||
payment_info, 'DrctDbtTxInf')
|
||||
payment_identification = etree.SubElement(
|
||||
dd_transaction_info, 'PmtId')
|
||||
if pain_flavor == 'pain.008.001.02.ch.01':
|
||||
instruction_identification = etree.SubElement(
|
||||
payment_identification, 'InstrId')
|
||||
instruction_identification.text = self._prepare_field(
|
||||
'Intruction Identification', 'line.name',
|
||||
{'line': line}, 35, gen_args=gen_args)
|
||||
instruction_identification = etree.SubElement(
|
||||
payment_identification, 'InstrId')
|
||||
instruction_identification.text = self._prepare_field(
|
||||
'Instruction Identification', 'line.name',
|
||||
{'line': line}, 35, gen_args=gen_args)
|
||||
end2end_identification = etree.SubElement(
|
||||
payment_identification, 'EndToEndId')
|
||||
end2end_identification.text = self._prepare_field(
|
||||
@@ -215,6 +214,11 @@ class AccountPaymentOrder(models.Model):
|
||||
dd_transaction_info, 'Dbtr', 'C',
|
||||
line.partner_bank_id, gen_args, line)
|
||||
|
||||
if line.purpose:
|
||||
purpose = etree.SubElement(
|
||||
dd_transaction_info, 'Purp')
|
||||
etree.SubElement(purpose, 'Cd').text = line.purpose
|
||||
|
||||
self.generate_remittance_info_block(
|
||||
dd_transaction_info, line, gen_args)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user