mirror of
https://gitlab.com/hibou-io/hibou-odoo/suite.git
synced 2025-01-20 12:37:31 +02:00
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:
1
account_us_ca_salestax/__init__.py
Normal file
1
account_us_ca_salestax/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from . import models
|
||||
13
account_us_ca_salestax/__manifest__.py
Normal file
13
account_us_ca_salestax/__manifest__.py
Normal 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,
|
||||
}
|
||||
1
account_us_ca_salestax/models/__init__.py
Normal file
1
account_us_ca_salestax/models/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from . import account_fiscal_position
|
||||
76
account_us_ca_salestax/models/account_fiscal_position.py
Normal file
76
account_us_ca_salestax/models/account_fiscal_position.py
Normal 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='')
|
||||
227
account_us_ca_salestax/models/ca_rates.wsdl
Normal file
227
account_us_ca_salestax/models/ca_rates.wsdl
Normal 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>
|
||||
29
account_us_ca_salestax/models/ca_tax_request.py
Normal file
29
account_us_ca_salestax/models/ca_tax_request.py
Normal 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,
|
||||
}
|
||||
@@ -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>
|
||||
Reference in New Issue
Block a user