diff options
| author | Mahendra barad <mba@openerp.com> | 2015-11-20 14:26:12 +0530 |
|---|---|---|
| committer | Yannick Tivisse <yti@odoo.com> | 2016-06-28 12:12:30 +0200 |
| commit | 6ba6213fa965d8935e6e8d62b2f481308167106f (patch) | |
| tree | 547b0930f0df35a0dc3c17a08dd21f47c671f36c /addons | |
| parent | 84b0fb5bbc392788f14184a893e1bdeabb51f92c (diff) | |
[ADD] account_taxcloud: Integrate TaxCloud API to get Sales Tax
- add a new checkbox on fiscal position: TaxCloud API
- when computing this fiscal position, it will:
- return an existing tax if one exists for the same tax
percentage, state, zip and TIC Category
- or create and return this tax if it does not exists yet
- Create a data fiscal position: country U.S., tax cloud API
- In l10n_us, add a settings in accounting: compute tax automatically using tax cloud.
NB:
- The signature of map_tax has been modified to optionally specify the product
and the partner on which the tax is applied
- The avoid the validationerrors that may occur while evaluation the tax with Taxcloud
when a public user is on the frontend shop (website_sale), we have to execute the
error silently by logging it.
Diffstat (limited to 'addons')
| -rw-r--r-- | addons/account/models/account_invoice.py | 4 | ||||
| -rw-r--r-- | addons/account/models/partner.py | 4 | ||||
| -rw-r--r-- | addons/account/views/partner_view.xml | 10 | ||||
| -rw-r--r-- | addons/delivery/models/sale_order.py | 2 | ||||
| -rw-r--r-- | addons/l10n_us/__init__.py | 2 | ||||
| -rw-r--r-- | addons/l10n_us/__openerp__.py | 1 | ||||
| -rw-r--r-- | addons/l10n_us/models/__init__.py | 4 | ||||
| -rw-r--r-- | addons/l10n_us/models/res_config.py | 11 | ||||
| -rw-r--r-- | addons/l10n_us/views/res_config_view.xml | 18 | ||||
| -rw-r--r-- | addons/point_of_sale/models/pos_order.py | 8 | ||||
| -rw-r--r-- | addons/sale/sale.py | 2 | ||||
| -rw-r--r-- | addons/sale/sale_analytic.py | 3 | ||||
| -rw-r--r-- | addons/website_sale/models/sale_order.py | 8 |
13 files changed, 60 insertions, 17 deletions
diff --git a/addons/account/models/account_invoice.py b/addons/account/models/account_invoice.py index f51575e1d8d..b1b71994115 100644 --- a/addons/account/models/account_invoice.py +++ b/addons/account/models/account_invoice.py @@ -1179,7 +1179,7 @@ class AccountInvoiceLine(models.Model): company_id = self.company_id or self.env.user.company_id taxes = taxes.filtered(lambda r: r.company_id == company_id) - self.invoice_line_tax_ids = fp_taxes = self.invoice_id.fiscal_position_id.map_tax(taxes) + self.invoice_line_tax_ids = fp_taxes = self.invoice_id.fiscal_position_id.map_tax(taxes, self.product_id, self.invoice_id.partner_id) fix_price = self.env['account.tax']._fix_tax_included_price if self.invoice_id.type in ('in_invoice', 'in_refund'): @@ -1250,7 +1250,7 @@ class AccountInvoiceLine(models.Model): return if not self.product_id: fpos = self.invoice_id.fiscal_position_id - self.invoice_line_tax_ids = fpos.map_tax(self.account_id.tax_ids).ids + self.invoice_line_tax_ids = fpos.map_tax(self.account_id.tax_ids, partner=self.partner_id).ids elif not self.price_unit: self._set_taxes() diff --git a/addons/account/models/partner.py b/addons/account/models/partner.py index 5e5986ed316..799173a60cc 100644 --- a/addons/account/models/partner.py +++ b/addons/account/models/partner.py @@ -45,7 +45,7 @@ class AccountFiscalPosition(models.Model): return True @api.v7 - def map_tax(self, cr, uid, fposition_id, taxes, context=None): + def map_tax(self, cr, uid, fposition_id, taxes, product=None, partner=None, context=None): if not taxes: return [] if not fposition_id: @@ -63,7 +63,7 @@ class AccountFiscalPosition(models.Model): return list(result) @api.v8 # noqa - def map_tax(self, taxes): + def map_tax(self, taxes, product=None, partner=None): result = self.env['account.tax'].browse() for tax in taxes: tax_count = 0 diff --git a/addons/account/views/partner_view.xml b/addons/account/views/partner_view.xml index c7bec407b85..973e593e2dd 100644 --- a/addons/account/views/partner_view.xml +++ b/addons/account/views/partner_view.xml @@ -37,13 +37,15 @@ <page name="tax_mapping" string="Tax Mapping"> <group> <field name="tax_ids" widget="one2many_list" nolabel="1"> - <tree string="Tax Mapping" editable="bottom"> + <tree name="tax_map_tree" string="Tax Mapping" editable="bottom"> <field name="tax_src_id" domain="[('type_tax_use', '!=', None)]"/> <field name="tax_dest_id" domain="[('type_tax_use', '!=', None), ('price_include', '=', False)]"/> </tree> - <form string="Tax Mapping"> - <field name="tax_src_id" domain="[('type_tax_use', '!=', None)]"/> - <field name="tax_dest_id" domain="[('type_tax_use', '!=', None), ('price_include', '=', False)]"/> + <form name="tax_map_form" string="Tax Mapping"> + <group> + <field name="tax_src_id" domain="[('type_tax_use', '!=', None)]"/> + <field name="tax_dest_id" domain="[('type_tax_use', '!=', None), ('price_include', '=', False)]"/> + </group> </form> </field> </group> diff --git a/addons/delivery/models/sale_order.py b/addons/delivery/models/sale_order.py index fe12c65dfa5..2aed9c76c87 100644 --- a/addons/delivery/models/sale_order.py +++ b/addons/delivery/models/sale_order.py @@ -80,7 +80,7 @@ class SaleOrder(models.Model): taxes = carrier.product_id.taxes_id.filtered(lambda t: t.company_id.id == self.company_id.id) taxes_ids = taxes.ids if self.partner_id and self.fiscal_position_id: - taxes_ids = self.fiscal_position_id.map_tax(taxes).ids + taxes_ids = self.fiscal_position_id.map_tax(taxes, carrier.product_id, self.partner_id).ids # Create the sale order line values = { diff --git a/addons/l10n_us/__init__.py b/addons/l10n_us/__init__.py index 67dee8c60db..81fc81d29c9 100644 --- a/addons/l10n_us/__init__.py +++ b/addons/l10n_us/__init__.py @@ -1,2 +1,4 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. + +import models diff --git a/addons/l10n_us/__openerp__.py b/addons/l10n_us/__openerp__.py index 7d7daffaaf6..7b1c0929bca 100644 --- a/addons/l10n_us/__openerp__.py +++ b/addons/l10n_us/__openerp__.py @@ -11,6 +11,7 @@ United States - Chart of accounts. 'depends': ['l10n_generic_coa', 'report'], 'data': [ 'data/res_company.xml', + 'views/res_config_view.xml' ], 'demo': [], 'test': [], diff --git a/addons/l10n_us/models/__init__.py b/addons/l10n_us/models/__init__.py new file mode 100644 index 00000000000..d330642bb78 --- /dev/null +++ b/addons/l10n_us/models/__init__.py @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +import res_config diff --git a/addons/l10n_us/models/res_config.py b/addons/l10n_us/models/res_config.py new file mode 100644 index 00000000000..156061c7def --- /dev/null +++ b/addons/l10n_us/models/res_config.py @@ -0,0 +1,11 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo import fields, models + +class AccountConfigSettings(models.TransientModel): + _inherit = 'account.config.settings' + + module_account_taxcloud = fields.Boolean("Compute sales tax automatically in the United States using TaxCloud.", + help='TaxCloud is an online provider that is committed to making it easy for retailers to collect sales tax online' + 'in the United States.') diff --git a/addons/l10n_us/views/res_config_view.xml b/addons/l10n_us/views/res_config_view.xml new file mode 100644 index 00000000000..491a9b64583 --- /dev/null +++ b/addons/l10n_us/views/res_config_view.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8"?> +<odoo> + + <record id="account_config_settings_inherit_form_view" model="ir.ui.view"> + <field name="name">account settings</field> + <field name="model">account.config.settings</field> + <field name="inherit_id" ref="account.view_account_config_settings"/> + <field name="arch" type="xml"> + <xpath expr="//div[@name='invoice_taxes']" position="inside"> + <div name="taxcloud_tax" class="o_row"> + <field name="module_account_taxcloud"/> + <label for="module_account_taxcloud"/> + </div> + </xpath> + </field> + </record> + +</odoo> diff --git a/addons/point_of_sale/models/pos_order.py b/addons/point_of_sale/models/pos_order.py index 0d0d69d3479..a2fe565291e 100644 --- a/addons/point_of_sale/models/pos_order.py +++ b/addons/point_of_sale/models/pos_order.py @@ -22,7 +22,7 @@ class PosOrder(models.Model): def _amount_line_tax(self, cr, uid, line, fiscal_position_id, context=None): taxes = line.tax_ids.filtered(lambda t: t.company_id.id == line.order_id.company_id.id) if fiscal_position_id: - taxes = fiscal_position_id.map_tax(taxes) + taxes = fiscal_position_id.map_tax(taxes, line.product_id, line.order_id.partner_id) price = line.price_unit * (1 - (line.discount or 0.0) / 100.0) taxes = taxes.compute_all(price, line.order_id.pricelist_id.currency_id, line.qty, product=line.product_id, partner=line.order_id.partner_id or False)['taxes'] return sum(tax.get('amount', 0.0) for tax in taxes) @@ -184,7 +184,7 @@ class PosOrder(models.Model): invoice_line.invoice_line_tax_ids = invoice_line.invoice_line_tax_ids.filtered(lambda t: t.company_id.id == line.order_id.company_id.id).ids fiscal_position_id = line.order_id.fiscal_position_id if fiscal_position_id: - invoice_line.invoice_line_tax_ids = fiscal_position_id.map_tax(invoice_line.invoice_line_tax_ids) + invoice_line.invoice_line_tax_ids = fiscal_position_id.map_tax(invoice_line.invoice_line_tax_ids, line.product_id, line.order_id.partner_id) invoice_line.invoice_line_tax_ids = invoice_line.invoice_line_tax_ids.ids # We convert a new id object back to a dictionary to write to # bridge between old and new api @@ -739,7 +739,7 @@ class PosOrderLine(models.Model): taxes = line.tax_ids.filtered(lambda tax: tax.company_id.id == line.order_id.company_id.id) fiscal_position_id = line.order_id.fiscal_position_id if fiscal_position_id: - taxes = fiscal_position_id.map_tax(taxes) + taxes = fiscal_position_id.map_tax(taxes, line.product_id, line.order_id.partner_id) price = line.price_unit * (1 - (line.discount or 0.0) / 100.0) line.price_subtotal = line.price_subtotal_incl = price * line.qty if taxes: @@ -778,7 +778,7 @@ class PosOrderLine(models.Model): @api.multi def _get_tax_ids_after_fiscal_position(self): for line in self: - line.tax_ids_after_fiscal_position = line.order_id.fiscal_position_id.map_tax(line.tax_ids) + line.tax_ids_after_fiscal_position = line.order_id.fiscal_position_id.map_tax(line.tax_ids, line.product_id, line.order_id.partner_id) class PosOrderLineLot(models.Model): diff --git a/addons/sale/sale.py b/addons/sale/sale.py index 02430a99aa8..752b82771ea 100644 --- a/addons/sale/sale.py +++ b/addons/sale/sale.py @@ -639,7 +639,7 @@ class SaleOrderLine(models.Model): fpos = line.order_id.fiscal_position_id or line.order_id.partner_id.property_account_position_id # If company_id is set, always filter taxes by the company taxes = line.product_id.taxes_id.filtered(lambda r: not line.company_id or r.company_id == line.company_id) - line.tax_id = fpos.map_tax(taxes) if fpos else taxes + line.tax_id = fpos.map_tax(taxes, line.product_id, line.order_id.partner_id) if fpos else taxes @api.multi def _prepare_order_line_procurement(self, group_id=False): diff --git a/addons/sale/sale_analytic.py b/addons/sale/sale_analytic.py index 0eed9f4cf71..555f49fecbc 100644 --- a/addons/sale/sale_analytic.py +++ b/addons/sale/sale_analytic.py @@ -59,7 +59,8 @@ class AccountAnalyticLine(models.Model): last_sequence = last_so_line.sequence + 1 if last_so_line else 100 fpos = order.fiscal_position_id or order.partner_id.property_account_position_id - taxes = fpos.map_tax(self.product_id.taxes_id) + taxes = fpos.map_tax(self.product_id.taxes_id, self.product_id, order.partner_id) + return { 'order_id': order.id, 'name': self.name, diff --git a/addons/website_sale/models/sale_order.py b/addons/website_sale/models/sale_order.py index 43466aad160..66d490d23e4 100644 --- a/addons/website_sale/models/sale_order.py +++ b/addons/website_sale/models/sale_order.py @@ -5,7 +5,7 @@ import random from odoo import api, models, fields, tools, _ from odoo.http import request -from odoo.exceptions import UserError +from odoo.exceptions import UserError, ValidationError _logger = logging.getLogger(__name__) @@ -92,7 +92,11 @@ class SaleOrder(models.Model): if not order_line: values = self._website_product_id_change(self.id, product_id, qty=1) order_line = SaleOrderLineSudo.create(values) - order_line._compute_tax_id() + try: + order_line._compute_tax_id() + except ValidationError as e: + # The validation may occur in backend (eg: taxcloud) but should fail silently in frontend + _logger.debug("ValidationError occurs during tax compute. %s" % (e)) if add_qty: add_qty -= 1 |
