[ADD] l10n_ec_website_sale: adapt eCommerce to allow EDI invoice

Currently the eCommerce workflow in Ecuador lacks some information
needed to issue EDI invoices.

The main adaptions needed are:
  * Identification type and number in the checkout process (in the billing address)
  * SRI Payment Method in the eCommerce Payment Method

SRI Payment Method
  * The SRI Payment Method value is required for the EDI
  * In the payment method form view the SRI Payment Method field is hidden
    if the list of fiscal countries of the selected companies does not include Ecuador.
  * Payment methods which do not have an associated SRI Payment Method
    cannot be used in the eCommerce checkout of an Ecuadorian company.
  * A (default) SRI Payment Method has been addeded to some payment methods to simplify the setup.
  * When creating an invoice from a sales order we try to compute the SRI Payment Method as follows:
    We consider all the SRI Payment Methods of the payment methods of the payment transactions associated with the sales order.
    If there is exactly 1 such SRI Payment Method we use this on the invoice.
    This should ensures that we can always set the SRI Payment Method on invoices created through the eCommerce flow.

task-3585823

Part-of: odoo/odoo#142730
This commit is contained in:
Sven Fuehr
2024-02-03 02:06:43 +00:00
parent ecbf5bdddb
commit a513523ed6
14 changed files with 368 additions and 0 deletions
+4
View File
@@ -0,0 +1,4 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import controllers
from . import models
@@ -0,0 +1,24 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
{
'name': 'Ecuadorian Website',
'countries': ['ec'],
'version': '1.0',
'category': 'Accounting/Localizations/Website',
'description': """Make ecommerce work for Ecuador.""",
'depends': [
'website_sale',
'l10n_ec',
],
'data': [
'data/ir_model_fields.xml',
'data/payment_method_data.xml',
'views/website_sales_templates.xml',
'views/payment_method_views.xml',
],
'demo': [
'demo/website_demo.xml',
],
'installable': True,
'auto_install': True,
'license': 'LGPL-3',
}
@@ -0,0 +1,3 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import main
@@ -0,0 +1,44 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo.addons.website_sale.controllers.main import WebsiteSale
from odoo.http import request
class L10nECWebsiteSale(WebsiteSale):
def _get_mandatory_fields_billing(self, country_id=False):
"""Extend mandatory fields to add new identification and responsibility fields when company is Ecuador"""
res = super()._get_mandatory_fields_billing(country_id)
if request.website.sudo().company_id.country_id.code == "EC":
res += ["l10n_latam_identification_type_id", "vat"]
return res
def _get_country_related_render_values(self, kw, render_values):
res = super()._get_country_related_render_values(kw, render_values)
if request.website.sudo().company_id.country_id.code == "EC":
res.update({
'identification': kw.get('l10n_latam_identification_type_id'),
'identification_types': request.env['l10n_latam.identification.type'].search(
['|', ('country_id', '=', False), ('country_id.code', '=', 'EC')]),
})
return res
def _get_vat_validation_fields(self, data):
res = super()._get_vat_validation_fields(data)
latam_id_type_data = data.get("l10n_latam_identification_type_id")
if request.website.sudo().company_id.country_id.code == "EC":
res.update({
'l10n_latam_identification_type_id': int(latam_id_type_data) if latam_id_type_data else False,
'name': data.get('name', False),
})
return res
def _get_shop_payment_values(self, order, **kwargs):
payment_values = super()._get_shop_payment_values(order, **kwargs)
company = order.company_id
# Do not show payment methods without l10n_ec_sri_payment_id.
# Payment methods without this fields could cause issues since we require a l10n_ec_sri_payment_id to post a move.
if company.account_fiscal_country_id.code == 'EC':
payment_methods = payment_values['payment_methods_sudo'].filtered(lambda pm: bool(pm.l10n_ec_sri_payment_id))
payment_values['payment_methods_sudo'] = payment_methods
return payment_values
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<function model="ir.model.fields" name="formbuilder_whitelist">
<value>res.partner</value>
<value eval="[
'l10n_latam_identification_type_id', 'l10n_latam_identification_type_id',
]"/>
</function>
</odoo>
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="payment.payment_method_card" model="payment.method">
<field name="l10n_ec_sri_payment_id" eval="ref('l10n_ec.P19')"/>
</record>
<record id="payment.payment_method_bank_transfer" model="payment.method">
<field name="l10n_ec_sri_payment_id" eval="ref('l10n_ec.P20')"/>
</record>
<record id="payment.payment_method_bank_account" model="payment.method">
<field name="l10n_ec_sri_payment_id" eval="ref('l10n_ec.P20')"/>
</record>
</odoo>
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo noupdate="1">
<record id="default_website_ec" model="website">
<field name="name">EC Company Website</field>
<field name="company_id" ref="l10n_ec.demo_company_ec"/>
</record>
<function model="product.pricelist" name="write">
<value model="product.pricelist" eval="obj().sudo().search([
('currency_id', '=', ref('base.USD')),
('company_id', '=', ref('l10n_ec.demo_company_ec'))
]).id"/>
<value model="website" eval="{'sequence': 1, 'website_id': ref('l10n_ec_website_sale.default_website_ec')}"/>
</function>
</odoo>
+68
View File
@@ -0,0 +1,68 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * l10n_ec_website_sale
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 17.1alpha1+e\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-11-17 13:55+0000\n"
"PO-Revision-Date: 2023-11-17 13:55+0000\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: l10n_ec_website_sale
#: model:website,contact_us_button_url:l10n_ec_website_sale.default_website_ec
msgid "/contactus"
msgstr "/contactus"
#. module: l10n_ec_website_sale
#: model_terms:ir.ui.view,arch_db:l10n_ec_website_sale.partner_info
msgid "<option value=\"\">Identification Type...</option>"
msgstr "<option value=\"\">Tipo de Identificación...</option>"
#. module: l10n_ec_website_sale
#: model_terms:ir.ui.view,arch_db:l10n_ec_website_sale.partner_info
msgid ""
"Changing Identification type is not allowed once document(s) have been "
"issued for your account. Please contact us directly for this operation."
msgstr "Cambiar el Tipo de Identificación no esta permitido una vez que hayan factura(s) emitadas a tu cuenta. Por favor contactenos directamente para esta operación."
#. module: l10n_ec_website_sale
#: model:ir.model.fields,field_description:l10n_ec_website_sale.field_payment_method__fiscal_country_codes
msgid "Fiscal Country Codes"
msgstr "Códigos Fiscales de País"
#. module: l10n_ec_website_sale
#: model_terms:ir.ui.view,arch_db:l10n_ec_website_sale.address
msgid "Identification Number"
msgstr "Número de Identificación"
#. module: l10n_ec_website_sale
#: model_terms:ir.ui.view,arch_db:l10n_ec_website_sale.partner_info
msgid "Identification Type"
msgstr "Tipo de Identificación"
#. module: l10n_ec_website_sale
#: model:website,prevent_zero_price_sale_text:l10n_ec_website_sale.default_website_ec
msgid "Not Available For Sale"
msgstr "No disponible para la venta"
#. module: l10n_ec_website_sale
#: model:ir.model,name:l10n_ec_website_sale.model_payment_method
msgid "Payment Method"
msgstr "Método de pago"
#. module: l10n_ec_website_sale
#: model:ir.model.fields,field_description:l10n_ec_website_sale.field_payment_method__l10n_ec_sri_payment_id
msgid "SRI Payment Method"
msgstr "SRI Forma de pago"
#. module: l10n_ec_website_sale
#: model:ir.model,name:l10n_ec_website_sale.model_sale_order
msgid "Sales Order"
msgstr "Pedido de venta"
@@ -0,0 +1,68 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * l10n_ec_website_sale
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 17.1alpha1+e\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-11-17 14:58+0000\n"
"PO-Revision-Date: 2023-11-17 14:58+0000\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: l10n_ec_website_sale
#: model:website,contact_us_button_url:l10n_ec_website_sale.default_website_ec
msgid "/contactus"
msgstr ""
#. module: l10n_ec_website_sale
#: model_terms:ir.ui.view,arch_db:l10n_ec_website_sale.partner_info
msgid "<option value=\"\">Identification Type...</option>"
msgstr ""
#. module: l10n_ec_website_sale
#: model_terms:ir.ui.view,arch_db:l10n_ec_website_sale.partner_info
msgid ""
"Changing Identification type is not allowed once document(s) have been "
"issued for your account. Please contact us directly for this operation."
msgstr ""
#. module: l10n_ec_website_sale
#: model:ir.model.fields,field_description:l10n_ec_website_sale.field_payment_method__fiscal_country_codes
msgid "Fiscal Country Codes"
msgstr ""
#. module: l10n_ec_website_sale
#: model_terms:ir.ui.view,arch_db:l10n_ec_website_sale.address
msgid "Identification Number"
msgstr ""
#. module: l10n_ec_website_sale
#: model_terms:ir.ui.view,arch_db:l10n_ec_website_sale.partner_info
msgid "Identification Type"
msgstr ""
#. module: l10n_ec_website_sale
#: model:website,prevent_zero_price_sale_text:l10n_ec_website_sale.default_website_ec
msgid "Not Available For Sale"
msgstr ""
#. module: l10n_ec_website_sale
#: model:ir.model,name:l10n_ec_website_sale.model_payment_method
msgid "Payment Method"
msgstr ""
#. module: l10n_ec_website_sale
#: model:ir.model.fields,field_description:l10n_ec_website_sale.field_payment_method__l10n_ec_sri_payment_id
msgid "SRI Payment Method"
msgstr ""
#. module: l10n_ec_website_sale
#: model:ir.model,name:l10n_ec_website_sale.model_sale_order
msgid "Sales Order"
msgstr ""
@@ -0,0 +1,4 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import payment_method
from . import sale_order
@@ -0,0 +1,18 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import api, fields, models
class PaymentMethod(models.Model):
_inherit = 'payment.method'
l10n_ec_sri_payment_id = fields.Many2one(
comodel_name="l10n_ec.sri.payment",
string="SRI Payment Method",
)
fiscal_country_codes = fields.Char(compute="_compute_fiscal_country_codes")
@api.depends_context('allowed_company_ids')
def _compute_fiscal_country_codes(self):
for record in self:
record.fiscal_country_codes = ",".join(self.env.companies.mapped('account_fiscal_country_id.code'))
@@ -0,0 +1,25 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import models
class SaleOrder(models.Model):
_inherit = 'sale.order'
def _create_invoices(self, grouped=False, final=False, date=None):
""" Create invoice(s) for the given Sales Order(s).
:param bool grouped: if True, invoices are grouped by SO id.
If False, invoices are grouped by keys returned by :meth:`_get_invoice_grouping_keys`
:param bool final: if True, refunds will be generated if necessary
:param date: unused parameter
:returns: created invoices
:rtype: `account.move` recordset
:raises: UserError if one of the orders has no invoiceable lines.
"""
moves = super()._create_invoices(grouped, final, date)
for move in moves:
if move.transaction_ids:
sri_payment_methods = move.transaction_ids.mapped('payment_method_id.l10n_ec_sri_payment_id')
if len(sri_payment_methods) == 1:
move.l10n_ec_sri_payment_id = sri_payment_methods
return moves
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="payment_method_form" model="ir.ui.view">
<field name="name">l10n_ec_website_sale.payment.method.form</field>
<field name="model">payment.method</field>
<field name="inherit_id" ref="payment.payment_method_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='supported_currency_ids']/.." position="after">
<field name="fiscal_country_codes" invisible="True"/>
<label for="l10n_ec_sri_payment_id"
invisible="'EC' not in fiscal_country_codes"/>
<div invisible="'EC' not in fiscal_country_codes">
<field name="l10n_ec_sri_payment_id"/>
</div>
</xpath>
</field>
</record>
</odoo>
@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<template id="partner_info" name="Ecuadorian partner">
<!-- show identification type -->
<div t-attf-class="mb-3 #{error.get('l10n_latam_identification_type_id') and 'o_has_error' or ''} col-xl-6">
<label class="col-form-label" for="l10n_latam_identification_type_id">Identification Type</label>
<t t-if="partner.can_edit_vat()">
<select name="l10n_latam_identification_type_id" t-attf-class="form-select #{error.get('l10n_latam_identification_type_id') and 'is-invalid' or ''}">
<option value="">Identification Type...</option>
<t t-foreach="identification_types or []" t-as="id_type">
<option t-att-value="id_type.id" t-att-selected="id_type.id == int(identification) if identification else id_type.id == partner.l10n_latam_identification_type_id.id">
<t t-esc="id_type.name"/>
</option>
</t>
</select>
</t>
<t t-else="">
<p class="form-control" t-esc="partner.l10n_latam_identification_type_id.name" readonly="1" title="Changing Identification type is not allowed once document(s) have been issued for your account. Please contact us directly for this operation."/>
<input name="l10n_latam_identification_type_id" class="form-control" t-att-value="partner.l10n_latam_identification_type_id.id" type='hidden'/>
</t>
</div>
</template>
<template id="address" inherit_id="website_sale.address">
<xpath expr="//input[@name='vat']/.." position="before">
<t t-if="mode[1] == 'billing'">
<t t-if="res_company.country_id.code == 'EC'">
<div class="clearfix"/> <!-- Break the line to put Identifaction Type and Identifaction Number (vat) on the same line -->
<t t-set="partner" t-value="website_sale_order.partner_id"/>
<t t-call="l10n_ec_website_sale.partner_info"/>
</t>
</t>
</xpath>
<label for="vat" position="replace">
<t t-if="res_company.country_id.code != 'EC'">$0</t>
<t t-else="">
<label class="col-form-label label-optional" for="vat">
Identification Number
</label>
</t>
</label>
</template>
</odoo>