diff --git a/account_banking_ach_base/README.rst b/account_banking_ach_base/README.rst new file mode 100644 index 00000000..cbc66185 --- /dev/null +++ b/account_banking_ach_base/README.rst @@ -0,0 +1,86 @@ +===================================================== +Localizations for North American Banking & Financials +===================================================== + +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fl10n--usa-lightgray.png?logo=github + :target: https://github.com/OCA/l10n-usa/tree/14.0/account_banking_ach_base + :alt: OCA/l10n-usa +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/l10n-usa-14-0/l10n-usa-14-0-account_banking_ach_base + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png + :target: https://runbot.odoo-community.org/runbot/203/14.0 + :alt: Try me on Runbot + +|badge1| |badge2| |badge3| |badge4| |badge5| + +Add fields to Bank, Partner and Company required for ACH transactions in USA. + +**Table of contents** + +.. contents:: + :local: + +Usage +===== + +Add `routing_number` on Bank records. + +Add Legal ID on Partner and Company records. + +Add Mandate URL field to Company record. Use in email templates to provide customer with an easy +way to access your Mandate Authorization form to streamline ACH authorizations. + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smashing it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* Thinkwell Designs + +Contributors +~~~~~~~~~~~~ + +* Dave Burkholder +* Maxime Chambreuil +* Serpent Consulting Services Pvt. Ltd. +* Murtaza Mithaiwala + +Maintainers +~~~~~~~~~~~ + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +This module is part of the `OCA/l10n-usa `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/account_banking_ach_base/__init__.py b/account_banking_ach_base/__init__.py new file mode 100644 index 00000000..83e553ac --- /dev/null +++ b/account_banking_ach_base/__init__.py @@ -0,0 +1,3 @@ +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from . import models diff --git a/account_banking_ach_base/__manifest__.py b/account_banking_ach_base/__manifest__.py new file mode 100644 index 00000000..9c9abbe6 --- /dev/null +++ b/account_banking_ach_base/__manifest__.py @@ -0,0 +1,25 @@ +# Copyright 2018 Thinkwell Designs +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +{ + "name": "Localizations for North American Banking & Financials", + "summary": "Add fields required for North American Banking & Financials", + "version": "16.0.1.0.1", + "license": "AGPL-3", + "author": "Thinkwell Designs, Odoo Community Association (OCA)", + "website": "https://github.com/OCA/l10n-usa", + "category": "Banking addons", + "depends": [ + "account_payment_order", + "account_banking_mandate", + "l10n_us_partner_legal_number", + ], + "data": [ + "views/account_banking_mandate.xml", + "views/account_move.xml", + "views/res_bank.xml", + "views/res_company.xml", + ], + "external_dependencies": {"python": ["python-stdnum", "ach"]}, + "installable": True, +} diff --git a/account_banking_ach_base/i18n/account_banking_ach_base.pot b/account_banking_ach_base/i18n/account_banking_ach_base.pot new file mode 100644 index 00000000..0ae702c9 --- /dev/null +++ b/account_banking_ach_base/i18n/account_banking_ach_base.pot @@ -0,0 +1,194 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * account_banking_ach_base +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 14.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: account_banking_ach_base +#: code:addons/account_banking_ach_base/models/account_payment_order.py:0 +#, python-format +msgid "%s account number has no Bank assigned" +msgstr "" + +#. module: account_banking_ach_base +#: code:addons/account_banking_ach_base/models/account_payment_order.py:0 +#, python-format +msgid "%s does not have a Routing Number assigned!" +msgstr "" + +#. module: account_banking_ach_base +#: code:addons/account_banking_ach_base/models/account_payment_order.py:0 +#, python-format +msgid "%s does not have an EIN / SSN / BN assigned!" +msgstr "" + +#. module: account_banking_ach_base +#: code:addons/account_banking_ach_base/models/account_payment_order.py:0 +#, python-format +msgid "%s has no routing number specified" +msgstr "" + +#. module: account_banking_ach_base +#: code:addons/account_banking_ach_base/models/res_bank.py:0 +#, python-format +msgid "%s is not a valid Canadian routing number!" +msgstr "" + +#. module: account_banking_ach_base +#: code:addons/account_banking_ach_base/models/res_bank.py:0 +#, python-format +msgid "%s is not a valid US routing number!" +msgstr "" + +#. module: account_banking_ach_base +#: model:ir.model,name:account_banking_ach_base.model_account_banking_mandate +msgid "A generic banking mandate" +msgstr "" + +#. module: account_banking_ach_base +#: model:ir.model,name:account_banking_ach_base.model_res_bank +msgid "Bank" +msgstr "" + +#. module: account_banking_ach_base +#: model:ir.model,name:account_banking_ach_base.model_res_company +msgid "Companies" +msgstr "" + +#. module: account_banking_ach_base +#: model:ir.model.fields,field_description:account_banking_ach_base.field_account_banking_mandate__delay_days +msgid "Delay Days" +msgstr "" + +#. module: account_banking_ach_base +#: code:addons/account_banking_ach_base/models/account_banking_mandate.py:0 +#, python-format +msgid "Delay days must be specified, and greater than 0." +msgstr "" + +#. module: account_banking_ach_base +#: model:ir.model.fields,field_description:account_banking_ach_base.field_account_banking_mandate__display_name +#: model:ir.model.fields,field_description:account_banking_ach_base.field_account_move__display_name +#: model:ir.model.fields,field_description:account_banking_ach_base.field_account_payment_order__display_name +#: model:ir.model.fields,field_description:account_banking_ach_base.field_res_bank__display_name +#: model:ir.model.fields,field_description:account_banking_ach_base.field_res_company__display_name +msgid "Display Name" +msgstr "" + +#. module: account_banking_ach_base +#: model_terms:ir.ui.view,arch_db:account_banking_ach_base.view_company_legal_id_number +msgid "EIN / SSN / BN" +msgstr "" + +#. module: account_banking_ach_base +#: model:ir.model.fields,help:account_banking_ach_base.field_res_company__legal_id_number +msgid "" +"For US entities, enter valid EIN or Social Security Number.\n" +" Canadian entities, enter Canadian Business Number.\n" +" " +msgstr "" + +#. module: account_banking_ach_base +#: model:ir.model.fields,help:account_banking_ach_base.field_res_company__mandate_url +msgid "" +"Full URL to download ACH Mandate /\n" +" Authorization form. Useful to include in email\n" +" templates for customer to access and\n" +" complete the Mandate form." +msgstr "" + +#. module: account_banking_ach_base +#: model:ir.model.fields,field_description:account_banking_ach_base.field_account_banking_mandate__id +#: model:ir.model.fields,field_description:account_banking_ach_base.field_account_move__id +#: model:ir.model.fields,field_description:account_banking_ach_base.field_account_payment_order__id +#: model:ir.model.fields,field_description:account_banking_ach_base.field_res_bank__id +#: model:ir.model.fields,field_description:account_banking_ach_base.field_res_company__id +msgid "ID" +msgstr "" + +#. module: account_banking_ach_base +#: model:ir.model,name:account_banking_ach_base.model_account_move +msgid "Journal Entry" +msgstr "" + +#. module: account_banking_ach_base +#: model:ir.model.fields,field_description:account_banking_ach_base.field_account_banking_mandate____last_update +#: model:ir.model.fields,field_description:account_banking_ach_base.field_account_move____last_update +#: model:ir.model.fields,field_description:account_banking_ach_base.field_account_payment_order____last_update +#: model:ir.model.fields,field_description:account_banking_ach_base.field_res_bank____last_update +#: model:ir.model.fields,field_description:account_banking_ach_base.field_res_company____last_update +msgid "Last Modified on" +msgstr "" + +#. module: account_banking_ach_base +#: model:ir.model.fields,field_description:account_banking_ach_base.field_res_company__legal_id_number +msgid "Legal ID" +msgstr "" + +#. module: account_banking_ach_base +#: model:ir.model.fields,field_description:account_banking_ach_base.field_res_company__mandate_url +msgid "Mandate URL" +msgstr "" + +#. module: account_banking_ach_base +#: code:addons/account_banking_ach_base/models/account_payment_order.py:0 +#, python-format +msgid "" +"Missing ACH Direct Debit mandate on the bank payment line with partner '%s' " +"(reference '%s')." +msgstr "" + +#. module: account_banking_ach_base +#: model:ir.model.fields,help:account_banking_ach_base.field_account_banking_mandate__delay_days +msgid "" +"Number of days to wait after invoice\n" +" date before including an invoice in Payment\n" +" Order for processing." +msgstr "" + +#. module: account_banking_ach_base +#: model:ir.model,name:account_banking_ach_base.model_account_payment_order +msgid "Payment Order" +msgstr "" + +#. module: account_banking_ach_base +#: model_terms:ir.ui.view,arch_db:account_banking_ach_base.view_account_invoice_filter_valid_mandate_id +msgid "Ready for Payment Order" +msgstr "" + +#. module: account_banking_ach_base +#: model:ir.model.fields,field_description:account_banking_ach_base.field_res_bank__routing_number +msgid "Routing Number" +msgstr "" + +#. module: account_banking_ach_base +#: code:addons/account_banking_ach_base/models/account_payment_order.py:0 +#, python-format +msgid "" +"The ACH Direct Debit mandate with reference '%s' for partner '%s' has " +"expired." +msgstr "" + +#. module: account_banking_ach_base +#: code:addons/account_banking_ach_base/models/account_payment_order.py:0 +#, python-format +msgid "" +"The mandate with reference '%s' for partner '%s' has type set to 'One-Off' " +"and it has a last debit date set to '%s', so we can't use it." +msgstr "" + +#. module: account_banking_ach_base +#: code:addons/account_banking_ach_base/models/account_move.py:0 +#, python-format +msgid "" +"To satisfy payment mandate, cannot add invoice %s to Debit Order until %s!" +msgstr "" diff --git a/account_banking_ach_base/models/__init__.py b/account_banking_ach_base/models/__init__.py new file mode 100644 index 00000000..73f08acf --- /dev/null +++ b/account_banking_ach_base/models/__init__.py @@ -0,0 +1,8 @@ +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from . import account_banking_mandate +from . import account_move +from . import account_payment_order +from . import res_bank +from . import res_company +from . import account_payment_method diff --git a/account_banking_ach_base/models/account_banking_mandate.py b/account_banking_ach_base/models/account_banking_mandate.py new file mode 100644 index 00000000..e12148d0 --- /dev/null +++ b/account_banking_ach_base/models/account_banking_mandate.py @@ -0,0 +1,62 @@ +from odoo import _, api, fields, models +from odoo.exceptions import UserError + + +class AccountBankingMandate(models.Model): + _inherit = "account.banking.mandate" + + delay_days = fields.Integer( + required=True, + default=10, + help="""Number of days to wait after invoice + date before including an invoice in Payment + Order for processing.""", + ) + + def validate(self): + for mandate in self: + if not mandate.delay_days: + raise UserError( + _("""Delay days must be specified, and greater than 0.""") + ) + return super(AccountBankingMandate, self).validate() + + def set_payment_modes_on_partner(self): + """ + Set the payment modes on the Partner if they don't already exist. + """ + payment_modes = {} + if ( + self.partner_id.customer_rank + and not self.partner_id.customer_payment_mode_id + ): + customer_mode = self.env["account.payment.mode"].search( + [ + ("payment_type", "=", "inbound"), + ("company_id", "=", self.company_id.id), + ], + limit=1, + ) + if customer_mode: + payment_modes["customer_payment_mode_id"] = customer_mode.id + if ( + self.partner_id.supplier_rank + and not self.partner_id.supplier_payment_mode_id + ): + supplier_mode = self.env["account.payment.mode"].search( + [ + ("payment_type", "=", "outbound"), + ("company_id", "=", self.company_id.id), + ], + limit=1, + ) + if supplier_mode: + payment_modes["supplier_payment_mode_id"] = supplier_mode.id + if payment_modes: + self.partner_id.write(payment_modes) + + @api.model + def create(self, vals): + mandate = super(AccountBankingMandate, self).create(vals) + mandate.set_payment_modes_on_partner() + return mandate diff --git a/account_banking_ach_base/models/account_move.py b/account_banking_ach_base/models/account_move.py new file mode 100644 index 00000000..be44eaea --- /dev/null +++ b/account_banking_ach_base/models/account_move.py @@ -0,0 +1,26 @@ +from datetime import date, timedelta + +from odoo import _, fields, models +from odoo.exceptions import UserError + + +class AccountMove(models.Model): + _inherit = "account.move" + + def create_account_payment_line(self): + today = date.today() + for invoice in self: + mandate = invoice.mandate_id + if not mandate: + continue + invoice_date = fields.Date.from_string(invoice.invoice_date) + delay_expired = invoice_date + timedelta(days=mandate.delay_days) + if today < delay_expired: + raise UserError( + _( + "To satisfy payment mandate, cannot add invoice %(name)s to Debit Order until %(delay_expired)s!" + ), + name=invoice.name, + delay_expired=delay_expired.strftime("%Y-%m-%d"), + ) + return super(AccountMove, self).create_account_payment_line() diff --git a/account_banking_ach_base/models/account_payment_method.py b/account_banking_ach_base/models/account_payment_method.py new file mode 100644 index 00000000..d6c13bde --- /dev/null +++ b/account_banking_ach_base/models/account_payment_method.py @@ -0,0 +1,16 @@ +# Copyright 2016-2020 Akretion France (http://www.akretion.com/) +# @author: Alexis de Lattre +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from odoo import api, fields, models + + +class AccountPaymentMethod(models.Model): + _inherit = "account.payment.method" + + @api.model + def _get_payment_method_information(self): + res = super()._get_payment_method_information() + res['ACH-In'] = {'mode': 'multi', 'domain': [('type', '=', 'bank')]} + res['ACH-Out'] = {'mode': 'multi', 'domain': [('type', '=', 'bank')]} + return res diff --git a/account_banking_ach_base/models/account_payment_order.py b/account_banking_ach_base/models/account_payment_order.py new file mode 100644 index 00000000..153b8912 --- /dev/null +++ b/account_banking_ach_base/models/account_payment_order.py @@ -0,0 +1,154 @@ +import re +from string import ascii_uppercase + +from ach.builder import AchFile + +from odoo import _, fields, models +from odoo.exceptions import UserError + +CREDIT_AUTOMATED_RETURN = "21" +CREDIT_AUTOMATED_DEPOSIT = "22" +CREDIT_PRENOTE_DNE_ENR = "23" +CREDIT_ZERO_DOLLAR_ENTRY_WITH_ADDENDA = "24" + +DEBIT_AUTOMATED_RETURN = "26" +DEBIT_AUTOMATED_PAYMENT = "27" +DEBIT_PRENOTE_DNE_ENR = "28" +DEBIT_ZERO_DOLLAR_ENTRY_WITH_ADDENDA = "29" + + +class AccountPaymentOrder(models.Model): + _inherit = "account.payment.order" + + def get_file_id_mod(self): + """ + ACH file_id_mod should be 'A' for the first of the day, + 'B' for the second and so on. + """ + ach_transactions_today = self.env["account.payment.order"].search_count( + [ + ("create_date", ">=", fields.Date.today()), + ("company_partner_bank_id", "=", self.company_partner_bank_id.id), + ("state", "in", ["generated", "uploaded"]), + ("payment_mode_id.payment_method_id.code", "in", ["ACH-In", "ACH-Out"]), + ] + ) + return ascii_uppercase[ach_transactions_today] + + def ach_settings(self): + bank = self.company_partner_bank_id.bank_id + routing_number = bank.routing_number + legal_id_number = self.company_id.legal_id_number + if not legal_id_number: + raise UserError( + _("%s does not have an EIN / SSN / BN assigned!") % self.company_id.name + ) + + if not routing_number: + raise UserError( + _("%s does not have a Routing Number assigned!") % bank.name + ) + return { + "immediate_dest": self.company_partner_bank_id.acc_number, + "immediate_org": routing_number, + "immediate_dest_name": bank.name, + "immediate_org_name": self.company_id.name, + "company_id": legal_id_number, + } + + def validate_banking(self, line): + if not line.partner_bank_id.bank_id: + raise UserError( + _("%s account number has no Bank assigned") + % line.partner_bank_id.acc_number + ) + + if not line.partner_bank_id.bank_id.routing_number: + raise UserError( + _("%s has no routing number specified") + % line.partner_bank_id.bank_id.name + ) + + def validate_mandates(self, line): + """Ensure that mandates are correctly set""" + if not line.mandate_id: + raise UserError( + _( + "Missing ACH Direct Debit mandate on the " + "payment line with partner %(name)s " + "(reference %(line_name)s).", + name=line.partner_id.name, + line_name=line.name, + ) + ) + if line.mandate_id.state != "valid": + raise Warning( + _( + "The ACH Direct Debit mandate with reference %(unique_mandate_reference)s " + "for partner %(name)s has expired." + ), + unique_mandate_reference=line.mandate_id.unique_mandate_reference, + name=line.mandate_id.partner_id.name, + ) + if line.mandate_id.type == "oneoff" and line.mandate_id.last_debit_date: + raise Warning( + _( + "The mandate with reference %(unique_mandate_reference)s for partner " + "%(name)s has type set to 'One-Off' and it has a " + "last debit date set to %(last_debit_date)s, so we can't use " + "it." + ), + unique_mandate_reference=line.mandate_id.unique_mandate_reference, + name=line.mandate_id.partner_id.name, + last_debit_date=line.mandate_id.last_debit_date, + ) + + def get_transaction_type(self, amount): + if not amount: + return ( + DEBIT_ZERO_DOLLAR_ENTRY_WITH_ADDENDA + if self.payment_type == "inbound" + else CREDIT_ZERO_DOLLAR_ENTRY_WITH_ADDENDA + ) + + return ( + DEBIT_AUTOMATED_PAYMENT + if self.payment_type == "inbound" + else CREDIT_AUTOMATED_DEPOSIT + ) + + def generate_ach_file(self): + self.ensure_one() + + inbound_payment = self.payment_type == "inbound" + + file_mod = self.get_file_id_mod() + ach_file = AchFile(file_id_mod=file_mod, settings=self.ach_settings()) + filename = "{today}_{bank}_{file_mod}.txt".format( + today=fields.Date.today(), + bank=self.company_partner_bank_id.id, + file_mod=file_mod, + ) + entries = [] + for line in self.payment_ids: + if inbound_payment: + self.validate_mandates(line) + self.validate_banking(line) + amount = line.amount + name = re.sub("[^A-Za-z0-9]+", "", line.partner_id.name) + note = re.sub("[^A-Za-z0-9]+", "", line.ref) + entries.append( + { + "type": self.get_transaction_type(amount=amount), + "routing_number": line.partner_bank_id.bank_id.routing_number, + "account_number": line.partner_bank_id.acc_number, + "amount": str(amount), + "name": name, + "addenda": [{"payment_related_info": note}], + } + ) + outbound_payment = self.payment_type == "outbound" + ach_file.add_batch( + "PPD", entries, credits=outbound_payment, debits=inbound_payment + ) + return ach_file.render_to_string().encode("utf-8"), filename diff --git a/account_banking_ach_base/models/res_bank.py b/account_banking_ach_base/models/res_bank.py new file mode 100644 index 00000000..76d4aeb2 --- /dev/null +++ b/account_banking_ach_base/models/res_bank.py @@ -0,0 +1,29 @@ +from stdnum.us import rtn + +from odoo import _, api, fields, models +from odoo.exceptions import ValidationError + + +class ResBank(models.Model): + _inherit = "res.bank" + + routing_number = fields.Char() + + @api.constrains("routing_number") + def validate_routing_number(self): + if not self.routing_number or not self.country: + return + country_code = self.country.code + if country_code == "US": + try: + rtn.validate(self.routing_number) + except Exception: + raise ValidationError( + _("%s is not a valid US routing number!") % self.routing_number + ) + elif country_code == "CA": + if len(self.routing_number) != 8 or not self.routing_number.is_digit(): + raise ValidationError( + _("%s is not a valid Canadian routing number!") + % self.routing_number + ) diff --git a/account_banking_ach_base/models/res_company.py b/account_banking_ach_base/models/res_company.py new file mode 100644 index 00000000..11326873 --- /dev/null +++ b/account_banking_ach_base/models/res_company.py @@ -0,0 +1,15 @@ +from odoo import fields, models + + +class ResCompany(models.Model): + _name = "res.company" + _inherit = ["countinghouse.legal_id_number", "res.company"] + + mandate_url = fields.Char( + string="Mandate URL", + required=False, + help="""Full URL to download ACH Mandate / + Authorization form. Useful to include in email + templates for customer to access and + complete the Mandate form.""", + ) diff --git a/account_banking_ach_base/readme/CONTRIBUTORS.rst b/account_banking_ach_base/readme/CONTRIBUTORS.rst new file mode 100644 index 00000000..fdaab636 --- /dev/null +++ b/account_banking_ach_base/readme/CONTRIBUTORS.rst @@ -0,0 +1,4 @@ +* Dave Burkholder +* Maxime Chambreuil +* Serpent Consulting Services Pvt. Ltd. +* Murtaza Mithaiwala diff --git a/account_banking_ach_base/readme/DESCRIPTION.rst b/account_banking_ach_base/readme/DESCRIPTION.rst new file mode 100644 index 00000000..f67cdafa --- /dev/null +++ b/account_banking_ach_base/readme/DESCRIPTION.rst @@ -0,0 +1 @@ +Add fields to Bank, Partner and Company required for ACH transactions in USA. diff --git a/account_banking_ach_base/readme/USAGE.rst b/account_banking_ach_base/readme/USAGE.rst new file mode 100644 index 00000000..381ada16 --- /dev/null +++ b/account_banking_ach_base/readme/USAGE.rst @@ -0,0 +1,6 @@ +Add `routing_number` on Bank records. + +Add Legal ID on Partner and Company records. + +Add Mandate URL field to Company record. Use in email templates to provide customer with an easy +way to access your Mandate Authorization form to streamline ACH authorizations. diff --git a/account_banking_ach_base/static/description/icon.png b/account_banking_ach_base/static/description/icon.png new file mode 100644 index 00000000..3a0328b5 Binary files /dev/null and b/account_banking_ach_base/static/description/icon.png differ diff --git a/account_banking_ach_base/static/description/index.html b/account_banking_ach_base/static/description/index.html new file mode 100644 index 00000000..5136220c --- /dev/null +++ b/account_banking_ach_base/static/description/index.html @@ -0,0 +1,430 @@ + + + + + + +Localizations for North American Banking & Financials + + + +
+

Localizations for North American Banking & Financials

+ + +

Beta License: AGPL-3 OCA/l10n-usa Translate me on Weblate Try me on Runbot

+

Add fields to Bank, Partner and Company required for ACH transactions in USA.

+

Table of contents

+ +
+

Usage

+

Add routing_number on Bank records.

+

Add Legal ID on Partner and Company records.

+

Add Mandate URL field to Company record. Use in email templates to provide customer with an easy +way to access your Mandate Authorization form to streamline ACH authorizations.

+
+
+

Bug Tracker

+

Bugs are tracked on GitHub Issues. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smashing it by providing a detailed and welcomed +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • Thinkwell Designs
  • +
+
+
+

Contributors

+ +
+
+

Maintainers

+

This module is maintained by the OCA.

+Odoo Community Association +

OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use.

+

This module is part of the OCA/l10n-usa project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+ + diff --git a/account_banking_ach_base/views/account_banking_mandate.xml b/account_banking_ach_base/views/account_banking_mandate.xml new file mode 100644 index 00000000..d91bf00b --- /dev/null +++ b/account_banking_ach_base/views/account_banking_mandate.xml @@ -0,0 +1,16 @@ + + + + account.invoice.days.delay + account.banking.mandate + + + + + + + 1 + + + + diff --git a/account_banking_ach_base/views/account_move.xml b/account_banking_ach_base/views/account_move.xml new file mode 100644 index 00000000..994cf91d --- /dev/null +++ b/account_banking_ach_base/views/account_move.xml @@ -0,0 +1,17 @@ + + + + account.invoice.valid.mandate + account.move + + + + + + + + diff --git a/account_banking_ach_base/views/res_bank.xml b/account_banking_ach_base/views/res_bank.xml new file mode 100644 index 00000000..31a9d2eb --- /dev/null +++ b/account_banking_ach_base/views/res_bank.xml @@ -0,0 +1,13 @@ + + + + Bank Routing Transit Number + res.bank + + + + + + + + diff --git a/account_banking_ach_base/views/res_company.xml b/account_banking_ach_base/views/res_company.xml new file mode 100644 index 00000000..2a178765 --- /dev/null +++ b/account_banking_ach_base/views/res_company.xml @@ -0,0 +1,14 @@ + + + + Company Legal ID Number + res.company + + + + + + + + + diff --git a/requirements.txt b/requirements.txt index f8f07db7..5041c4a4 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,3 @@ # generated from manifests external_dependencies +ach python-stdnum