Merge branch 'new/12.0/account_us_ca_salestax' into '12.0'

new/12.0/account_us_ca_salestax into 12.0

See merge request hibou-io/hibou-odoo/suite!198
This commit is contained in:
Jared Kipe
2019-12-17 19:27:25 +00:00
7 changed files with 375 additions and 0 deletions

View File

@@ -0,0 +1 @@
from . import models

View File

@@ -0,0 +1,13 @@
{'name': 'US CA California State SalesTax API',
'version': '12.0.1.0.0',
'category': 'Tools',
'depends': ['account',
],
'author': 'Hibou Corp.',
'license': 'AGPL-3',
'website': 'https://hibou.io/',
'data': ['views/account_fiscal_position_view.xml',
],
'installable': True,
'application': False,
}

View File

@@ -0,0 +1 @@
from . import account_fiscal_position

View File

@@ -0,0 +1,76 @@
from odoo import api, fields, models
from .ca_tax_request import CATaxRequest
class AccountFiscalPosition(models.Model):
_inherit = 'account.fiscal.position'
is_us_ca = fields.Boolean(string='Use CA State API')
ca_base_tax_id = fields.Many2one('account.tax', string='CA Base/Error Tax', company_dependent=True)
@api.multi
def map_tax(self, taxes, product=None, partner=None):
if not taxes or not self.is_us_ca or partner is None:
return super(AccountFiscalPosition, self).map_tax(taxes)
AccountTax = self.env['account.tax'].sudo()
result = AccountTax.browse()
for tax in taxes:
ca_tax = None
request = CATaxRequest()
try:
res = request.get_rate(partner)
ca_tax = AccountTax.search([
('company_id', '=', self.ca_base_tax_id.company_id.id),
('ca_county', '=', res['county']),
('amount', '=', res['rate']),
('amount_type', '=', 'percent'),
('type_tax_use', '=', 'sale')], limit=1)
if not ca_tax:
ca_tax = AccountTax.create({
'name': '%s - Tax %0.2f%%' % (res['county'], res['rate']),
'ca_county': res['county'],
'amount': res['rate'],
'amount_type': 'percent',
'type_tax_use': 'sale',
'account_id': self.ca_base_tax_id.account_id.id,
'refund_account_id': self.ca_base_tax_id.refund_account_id.id,
'company_id': self.ca_base_tax_id.company_id.id,
'ca_location_zips': partner.zip,
})
except:
ca_tax = AccountTax.search([
('ca_location_zips', 'like', '%' + partner.zip + '%'),
('amount_type', '=', 'percent'),
('type_tax_use', '=', 'sale')], limit=1)
if not ca_tax:
result |= self.ca_base_tax_id
continue
if not ca_tax.ca_location_zips:
ca_tax.write({'ca_location_zips': partner.zip})
elif not ca_tax.ca_location_zips.find(str(partner.zip)) >= 0:
zips = ca_tax.ca_location_zips.split(',')
zips.append(str(partner.zip))
ca_tax.write({'ca_location_zips': ','.join(zips)})
# step 3: Find or create mapping
tax_line = self.tax_ids.filtered(lambda x: x.tax_src_id.id == tax.id and x.tax_dest_id.id == ca_tax.id)
if not tax_line:
tax_line = self.env['account.fiscal.position.tax'].sudo().create({
'position_id': self.id,
'tax_src_id': tax.id,
'tax_dest_id': ca_tax.id,
})
result |= tax_line.tax_dest_id
return result
class AccountTax(models.Model):
_inherit = 'account.tax'
ca_county = fields.Char('CA County')
ca_location_zips = fields.Char('CA Location ZIPs', default='')

View File

@@ -0,0 +1,227 @@
<?xml version="1.0" encoding="utf-8"?>
<wsdl:definitions name="CATaxRateAPI" targetNamespace="http://services.gis.boe.ca.gov/api/taxrates"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata"
xmlns:wsx="http://schemas.xmlsoap.org/ws/2004/09/mex"
xmlns:wsap="http://schemas.xmlsoap.org/ws/2004/08/addressing/policy"
xmlns:msc="http://schemas.microsoft.com/ws/2005/12/wsdl/contract"
xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:tns="http://services.gis.boe.ca.gov/api/taxrates"
xmlns:wsa10="http://www.w3.org/2005/08/addressing"
xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl"
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing">
<wsdl:types>
<xs:schema elementFormDefault="qualified" targetNamespace="http://services.gis.boe.ca.gov/api/taxrates"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="Hello">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" name="value" type="xs:int"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="HelloResponse">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" name="HelloResult" nillable="true" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="GetRate">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" name="request" nillable="true" type="tns:CARateRequest"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="CARateRequest">
<xs:sequence>
<xs:element minOccurs="0" name="City" nillable="true" type="xs:string"/>
<xs:element minOccurs="0" name="Latitude" nillable="true" type="xs:double"/>
<xs:element minOccurs="0" name="Longitude" nillable="true" type="xs:double"/>
<xs:element minOccurs="0" name="State" nillable="true" type="xs:string"/>
<xs:element minOccurs="0" name="StreetAddress" nillable="true" type="xs:string"/>
<xs:element minOccurs="0" name="Token" nillable="true" type="xs:string"/>
<xs:element minOccurs="0" name="ZipCode" nillable="true" type="xs:int"/>
<xs:element minOccurs="0" name="ZipCodePlusFour" nillable="true" type="xs:int"/>
</xs:sequence>
</xs:complexType>
<xs:element name="CARateRequest" nillable="true" type="tns:CARateRequest"/>
<xs:element name="GetRateResponse">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" name="GetRateResult" nillable="true"
type="tns:CARateResponseCollection"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="CARateResponseCollection">
<xs:sequence>
<xs:element minOccurs="0" name="AppVersion" nillable="true" type="xs:string"/>
<xs:element minOccurs="0" name="CARateResponses" nillable="true" type="tns:ArrayOfCARateResponse"/>
<xs:element minOccurs="0" name="Disclaimer" nillable="true" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:element name="CARateResponseCollection" nillable="true" type="tns:CARateResponseCollection"/>
<xs:complexType name="ArrayOfCARateResponse">
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="unbounded" name="CARateResponse" nillable="true"
type="tns:CARateResponse"/>
</xs:sequence>
</xs:complexType>
<xs:element name="ArrayOfCARateResponse" nillable="true" type="tns:ArrayOfCARateResponse"/>
<xs:complexType name="CARateResponse">
<xs:sequence>
<xs:element minOccurs="0" name="BufferSize" type="xs:int"/>
<xs:element minOccurs="0" name="CARateRequest" nillable="true" type="tns:CARateRequest"/>
<xs:element minOccurs="0" name="Errors" nillable="true" type="tns:ArrayOfError"/>
<xs:element minOccurs="0" name="ResponseDate" type="xs:dateTime"/>
<xs:element minOccurs="0" name="Responses" nillable="true" type="tns:ArrayOfRateInformation"/>
<xs:element minOccurs="0" name="TermsOfUse" nillable="true" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:element name="CARateResponse" nillable="true" type="tns:CARateResponse"/>
<xs:complexType name="ArrayOfError">
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="unbounded" name="Error" nillable="true" type="tns:Error"/>
</xs:sequence>
</xs:complexType>
<xs:element name="ArrayOfError" nillable="true" type="tns:ArrayOfError"/>
<xs:complexType name="Error">
<xs:sequence>
<xs:element minOccurs="0" name="Code" nillable="true" type="xs:string"/>
<xs:element minOccurs="0" name="Message" nillable="true" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:element name="Error" nillable="true" type="tns:Error"/>
<xs:complexType name="ArrayOfRateInformation">
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="unbounded" name="RateInformation" nillable="true"
type="tns:RateInformation"/>
</xs:sequence>
</xs:complexType>
<xs:element name="ArrayOfRateInformation" nillable="true" type="tns:ArrayOfRateInformation"/>
<xs:complexType name="RateInformation">
<xs:sequence>
<xs:element minOccurs="0" name="Details" nillable="true" type="tns:RateDetails"/>
<xs:element minOccurs="0" name="Rate" nillable="true" type="xs:double"/>
</xs:sequence>
</xs:complexType>
<xs:element name="RateInformation" nillable="true" type="tns:RateInformation"/>
<xs:complexType name="RateDetails">
<xs:sequence>
<xs:element minOccurs="0" name="CalcMethod" nillable="true" type="xs:string"/>
<xs:element minOccurs="0" name="City" nillable="true" type="xs:anyType"/>
<xs:element minOccurs="0" name="Comments" nillable="true" type="xs:string"/>
<xs:element minOccurs="0" name="Confidence" nillable="true" type="xs:string"/>
<xs:element minOccurs="0" name="County" nillable="true" type="xs:string"/>
<xs:element minOccurs="0" name="Jurisdiction" nillable="true" type="xs:string"/>
<xs:element minOccurs="0" name="TAC" nillable="true" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:element name="RateDetails" nillable="true" type="tns:RateDetails"/>
</xs:schema>
<xs:schema attributeFormDefault="qualified" elementFormDefault="qualified"
targetNamespace="http://schemas.microsoft.com/2003/10/Serialization/"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:tns="http://schemas.microsoft.com/2003/10/Serialization/">
<xs:element name="anyType" nillable="true" type="xs:anyType"/>
<xs:element name="anyURI" nillable="true" type="xs:anyURI"/>
<xs:element name="base64Binary" nillable="true" type="xs:base64Binary"/>
<xs:element name="boolean" nillable="true" type="xs:boolean"/>
<xs:element name="byte" nillable="true" type="xs:byte"/>
<xs:element name="dateTime" nillable="true" type="xs:dateTime"/>
<xs:element name="decimal" nillable="true" type="xs:decimal"/>
<xs:element name="double" nillable="true" type="xs:double"/>
<xs:element name="float" nillable="true" type="xs:float"/>
<xs:element name="int" nillable="true" type="xs:int"/>
<xs:element name="long" nillable="true" type="xs:long"/>
<xs:element name="QName" nillable="true" type="xs:QName"/>
<xs:element name="short" nillable="true" type="xs:short"/>
<xs:element name="string" nillable="true" type="xs:string"/>
<xs:element name="unsignedByte" nillable="true" type="xs:unsignedByte"/>
<xs:element name="unsignedInt" nillable="true" type="xs:unsignedInt"/>
<xs:element name="unsignedLong" nillable="true" type="xs:unsignedLong"/>
<xs:element name="unsignedShort" nillable="true" type="xs:unsignedShort"/>
<xs:element name="char" nillable="true" type="tns:char"/>
<xs:simpleType name="char">
<xs:restriction base="xs:int"/>
</xs:simpleType>
<xs:element name="duration" nillable="true" type="tns:duration"/>
<xs:simpleType name="duration">
<xs:restriction base="xs:duration">
<xs:pattern value="\-?P(\d*D)?(T(\d*H)?(\d*M)?(\d*(\.\d*)?S)?)?"/>
<xs:minInclusive value="-P10675199DT2H48M5.4775808S"/>
<xs:maxInclusive value="P10675199DT2H48M5.4775807S"/>
</xs:restriction>
</xs:simpleType>
<xs:element name="guid" nillable="true" type="tns:guid"/>
<xs:simpleType name="guid">
<xs:restriction base="xs:string">
<xs:pattern value="[\da-fA-F]{8}-[\da-fA-F]{4}-[\da-fA-F]{4}-[\da-fA-F]{4}-[\da-fA-F]{12}"/>
</xs:restriction>
</xs:simpleType>
<xs:attribute name="FactoryType" type="xs:QName"/>
<xs:attribute name="Id" type="xs:ID"/>
<xs:attribute name="Ref" type="xs:IDREF"/>
</xs:schema>
</wsdl:types>
<wsdl:message name="CATaxRateAPI_Hello_InputMessage">
<wsdl:part name="parameters" element="tns:Hello"/>
</wsdl:message>
<wsdl:message name="CATaxRateAPI_Hello_OutputMessage">
<wsdl:part name="parameters" element="tns:HelloResponse"/>
</wsdl:message>
<wsdl:message name="CATaxRateAPI_GetRate_InputMessage">
<wsdl:part name="parameters" element="tns:GetRate"/>
</wsdl:message>
<wsdl:message name="CATaxRateAPI_GetRate_OutputMessage">
<wsdl:part name="parameters" element="tns:GetRateResponse"/>
</wsdl:message>
<wsdl:portType name="CATaxRateAPI">
<wsdl:operation name="Hello">
<wsdl:input wsaw:Action="http://services.gis.boe.ca.gov/api/taxrates/CATaxRateAPI/Hello"
message="tns:CATaxRateAPI_Hello_InputMessage"/>
<wsdl:output wsaw:Action="http://services.gis.boe.ca.gov/api/taxrates/CATaxRateAPI/HelloResponse"
message="tns:CATaxRateAPI_Hello_OutputMessage"/>
</wsdl:operation>
<wsdl:operation name="GetRate">
<wsdl:input wsaw:Action="http://services.gis.boe.ca.gov/api/taxrates/CATaxRateAPI/GetRate"
message="tns:CATaxRateAPI_GetRate_InputMessage"/>
<wsdl:output wsaw:Action="http://services.gis.boe.ca.gov/api/taxrates/CATaxRateAPI/GetRateResponse"
message="tns:CATaxRateAPI_GetRate_OutputMessage"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="BasicHttpBinding_CATaxRateAPI" type="tns:CATaxRateAPI">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="Hello">
<soap:operation soapAction="http://services.gis.boe.ca.gov/api/taxrates/CATaxRateAPI/Hello"
style="document"/>
<wsdl:input>
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output>
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="GetRate">
<soap:operation soapAction="http://services.gis.boe.ca.gov/api/taxrates/CATaxRateAPI/GetRate"
style="document"/>
<wsdl:input>
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output>
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="CATaxRateAPI">
<wsdl:port name="BasicHttpBinding_CATaxRateAPI" binding="tns:BasicHttpBinding_CATaxRateAPI">
<soap:address location="http://services.gis.boe.ca.gov/api/taxrates/Rates.svc"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>

View File

@@ -0,0 +1,29 @@
import os
import logging
from suds.client import Client
_logger = logging.getLogger(__name__)
class CATaxRequest:
def __init__(self):
wsdl_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), './ca_rates.wsdl')
self.client = Client('file:///%s' % wsdl_path.lstrip('/'))
def get_rate(self, partner):
request = self.client.factory.create('CARateRequest')
request.StreetAddress = partner.street
request.State = partner.state_id.code
request.City = partner.city
zip_ = partner.zip
if zip_ and len(zip_) > 5:
zip_ = zip_[:5]
request.ZipCode = zip_
_logger.debug('CA Request: ' + str(request))
response = self.client.service.GetRate(request)
_logger.debug('CA Response: ' + str(response))
return {
'rate': response.CARateResponses[0][0].Responses[0][0].Rate * 100.0,
'county': response.CARateResponses[0][0].Responses[0][0].Details.County,
}

View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="account_position_us_ca_inherit_from_view" model="ir.ui.view">
<field name="name">account.fiscal.position.form.inherit</field>
<field name="model">account.fiscal.position</field>
<field name="inherit_id" ref="account.view_account_position_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='name']" position="after">
<field name="is_us_ca"/>
<field name="ca_base_tax_id" attrs="{'invisible': [('is_us_ca', '=', False)]}" />
</xpath>
</field>
</record>
<record id="view_tax_form" model="ir.ui.view">
<field name="name">account.tax.form.inherit</field>
<field name="model">account.tax</field>
<field name="inherit_id" ref="account.view_tax_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='description']" position="after">
<field name="ca_county" />
<field name="ca_location_zips" />
</xpath>
</field>
</record>
</odoo>