summaryrefslogtreecommitdiff
path: root/addons
diff options
context:
space:
mode:
authorMahendra barad <mba@openerp.com>2015-11-20 14:26:12 +0530
committerYannick Tivisse <yti@odoo.com>2016-06-28 12:12:30 +0200
commit6ba6213fa965d8935e6e8d62b2f481308167106f (patch)
tree547b0930f0df35a0dc3c17a08dd21f47c671f36c /addons
parent84b0fb5bbc392788f14184a893e1bdeabb51f92c (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.py4
-rw-r--r--addons/account/models/partner.py4
-rw-r--r--addons/account/views/partner_view.xml10
-rw-r--r--addons/delivery/models/sale_order.py2
-rw-r--r--addons/l10n_us/__init__.py2
-rw-r--r--addons/l10n_us/__openerp__.py1
-rw-r--r--addons/l10n_us/models/__init__.py4
-rw-r--r--addons/l10n_us/models/res_config.py11
-rw-r--r--addons/l10n_us/views/res_config_view.xml18
-rw-r--r--addons/point_of_sale/models/pos_order.py8
-rw-r--r--addons/sale/sale.py2
-rw-r--r--addons/sale/sale_analytic.py3
-rw-r--r--addons/website_sale/models/sale_order.py8
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