Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: TaxJar update - added nexus list, making api call only for nexus (backport #27497) #27940

Merged
merged 25 commits into from
Oct 19, 2021
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
4abcedd
fix: TaxJar update - nexus, selective api call
nemesis189 Sep 14, 2021
52df24c
fix: sales_tax attribute in api call before submit
nemesis189 Sep 14, 2021
0481678
Update erpnext/erpnext_integrations/taxjar_integration.py
nemesis189 Sep 16, 2021
78c5b87
Update erpnext/erpnext_integrations/doctype/taxjar_settings/taxjar_se…
nemesis189 Sep 16, 2021
50216a9
Update erpnext/erpnext_integrations/doctype/taxjar_settings/taxjar_se…
nemesis189 Sep 16, 2021
91b11f6
Update erpnext/erpnext_integrations/taxjar_integration.py
nemesis189 Sep 16, 2021
d5c32be
fix: Renamed child table doctype, delete taxes for non nexus state
nemesis189 Sep 16, 2021
71e6ffd
fix: updated patch, add fields only if fields are checked
nemesis189 Sep 27, 2021
c7c07f0
fix: patch fix, fields disabling
nemesis189 Sep 28, 2021
81e5ab5
fix: using db.exists and get_value instead of get_doc
nemesis189 Sep 29, 2021
7b846ce
fix: dt instead of document in set_value query
nemesis189 Sep 29, 2021
1c36329
minor fixes
nemesis189 Sep 29, 2021
6198687
fix: improved on_update method, added validation for tax calculation,…
nemesis189 Oct 6, 2021
35d56c4
fix: linters fix
nemesis189 Oct 6, 2021
d8a38e6
fix: patch fix added reload_doctype
nemesis189 Oct 7, 2021
ebd5a00
fix: patch fixes- force reload doc, check for company
nemesis189 Oct 11, 2021
036b653
fix: 'Taxjar' type fix
nemesis189 Oct 11, 2021
557dc5e
fix: Update pacthes.txt
deepeshgarg007 Oct 12, 2021
7af724b
fix: Patch
deepeshgarg007 Oct 13, 2021
67adfb8
fix: Move product tax category folder to taxjar settings
deepeshgarg007 Oct 13, 2021
c578406
Update custom_fields_for_taxjar_integration.py
nemesis189 Oct 14, 2021
da6eb5d
Merge branch 'version-13-hotfix' into mergify/bp/version-13-hotfix/pr…
AfshanKhan Oct 19, 2021
4d27dba
fix: conflicts
AfshanKhan Oct 19, 2021
c4663e9
fix: linter issues
nemesis189 Oct 19, 2021
2274778
fix: patch fix
nemesis189 Oct 19, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
{
"actions": [],
"allow_rename": 1,
"creation": "2021-09-11 05:09:53.773838",
"doctype": "DocType",
"engine": "InnoDB",
"field_order": [
"region",
"region_code",
"country",
"country_code"
],
"fields": [
{
"fieldname": "region",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Region"
},
{
"fieldname": "region_code",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Region Code"
},
{
"fieldname": "country",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Country"
},
{
"fieldname": "country_code",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Country Code"
}
],
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2021-09-14 05:33:06.444710",
"modified_by": "Administrator",
"module": "ERPNext Integrations",
"name": "TaxJar Nexus",
"owner": "Administrator",
"permissions": [],
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt

# import frappe
from frappe.model.document import Document


class TaxJarNexus(Document):
pass
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,16 @@ frappe.ui.form.on('TaxJar Settings', {
is_sandbox: (frm) => {
frm.toggle_reqd("api_key", !frm.doc.is_sandbox);
frm.toggle_reqd("sandbox_api_key", frm.doc.is_sandbox);
}
},

refresh: (frm) => {
frm.add_custom_button(__('Update Nexus List'), function() {
frm.call({
doc: frm.doc,
method: 'update_nexus_list'
});
});
},


});
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"is_sandbox",
"taxjar_calculate_tax",
"is_sandbox",
"taxjar_create_transactions",
"credentials",
"api_key",
Expand All @@ -16,7 +16,10 @@
"configuration",
"tax_account_head",
"configuration_cb",
"shipping_account_head"
"shipping_account_head",
"section_break_12",
"nexus_address",
"nexus"
],
"fields": [
{
Expand Down Expand Up @@ -54,6 +57,7 @@
},
{
"default": "0",
"depends_on": "taxjar_calculate_tax",
"fieldname": "is_sandbox",
"fieldtype": "Check",
"label": "Sandbox Mode"
Expand All @@ -69,6 +73,7 @@
},
{
"default": "0",
"depends_on": "taxjar_calculate_tax",
"fieldname": "taxjar_create_transactions",
"fieldtype": "Check",
"label": "Create TaxJar Transaction"
Expand All @@ -82,11 +87,28 @@
{
"fieldname": "cb_keys",
"fieldtype": "Column Break"
},
{
"fieldname": "section_break_12",
"fieldtype": "Section Break",
"label": "Nexus List"
},
{
"fieldname": "nexus_address",
"fieldtype": "HTML",
"label": "Nexus Address"
},
{
"fieldname": "nexus",
"fieldtype": "Table",
"label": "Nexus",
"options": "TaxJar Nexus",
"read_only": 1
}
],
"issingle": 1,
"links": [],
"modified": "2020-04-30 04:38:03.311089",
"modified": "2021-10-06 10:59:13.475442",
"modified_by": "Administrator",
"module": "ERPNext Integrations",
"name": "TaxJar Settings",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,98 @@

from __future__ import unicode_literals

# import frappe
import json
import os

import frappe
from frappe.custom.doctype.custom_field.custom_field import create_custom_fields
from frappe.model.document import Document
from frappe.permissions import add_permission, update_permission_property

from erpnext.erpnext_integrations.taxjar_integration import get_client


class TaxJarSettings(Document):
pass

def on_update(self):
TAXJAR_CREATE_TRANSACTIONS = frappe.db.get_single_value("TaxJar Settings", "taxjar_create_transactions")
TAXJAR_CALCULATE_TAX = frappe.db.get_single_value("TaxJar Settings", "taxjar_calculate_tax")
TAXJAR_SANDBOX_MODE = frappe.db.get_single_value("TaxJar Settings", "is_sandbox")

fields_already_exist = frappe.db.exists('Custom Field', {'dt': ('in', ['Item','Sales Invoice Item']), 'fieldname':'product_tax_category'})
fields_hidden = frappe.get_value('Custom Field', {'dt': ('in', ['Sales Invoice Item'])}, 'hidden')

if (TAXJAR_CREATE_TRANSACTIONS or TAXJAR_CALCULATE_TAX or TAXJAR_SANDBOX_MODE):
if not fields_already_exist:
add_product_tax_categories()
make_custom_fields()
add_permissions()
frappe.enqueue('erpnext.regional.united_states.setup.add_product_tax_categories', now=False)

elif fields_already_exist and fields_hidden:
toggle_tax_category_fields(hidden='0')

elif fields_already_exist:
toggle_tax_category_fields(hidden='1')

def validate(self):
self.calculate_taxes_validation_for_create_transactions()

@frappe.whitelist()
def update_nexus_list(self):
client = get_client()
nexus = client.nexus_regions()

new_nexus_list = [frappe._dict(address) for address in nexus]

self.set('nexus', [])
self.set('nexus', new_nexus_list)
self.save()

def calculate_taxes_validation_for_create_transactions(self):
if not self.taxjar_calculate_tax and (self.taxjar_create_transactions or self.is_sandbox):
frappe.throw(frappe._('Before enabling <b>Create Transaction</b> or <b>Sandbox Mode</b>, you need to check the <b>Enable Tax Calculation</b> box'))


def toggle_tax_category_fields(hidden):
frappe.set_value('Custom Field', {'dt':'Sales Invoice Item', 'fieldname':'product_tax_category'}, 'hidden', hidden)
frappe.set_value('Custom Field', {'dt':'Item', 'fieldname':'product_tax_category'}, 'hidden', hidden)


def add_product_tax_categories():
with open(os.path.join(os.path.dirname(__file__), 'product_tax_category_data.json'), 'r') as f:
tax_categories = json.loads(f.read())
create_tax_categories(tax_categories['categories'])

def create_tax_categories(data):
for d in data:
if not frappe.db.exists('Product Tax Category',{'product_tax_code':d.get('product_tax_code')}):
tax_category = frappe.new_doc('Product Tax Category')
tax_category.description = d.get("description")
tax_category.product_tax_code = d.get("product_tax_code")
tax_category.category_name = d.get("name")
tax_category.db_insert()

def make_custom_fields(update=True):
custom_fields = {
'Sales Invoice Item': [
dict(fieldname='product_tax_category', fieldtype='Link', insert_after='description', options='Product Tax Category',
label='Product Tax Category', fetch_from='item_code.product_tax_category'),
dict(fieldname='tax_collectable', fieldtype='Currency', insert_after='net_amount',
label='Tax Collectable', read_only=1),
dict(fieldname='taxable_amount', fieldtype='Currency', insert_after='tax_collectable',
label='Taxable Amount', read_only=1)
],
'Item': [
dict(fieldname='product_tax_category', fieldtype='Link', insert_after='item_group', options='Product Tax Category',
label='Product Tax Category')
]
}
create_custom_fields(custom_fields, update=update)

def add_permissions():
doctype = "Product Tax Category"
for role in ('Accounts Manager', 'Accounts User', 'System Manager','Item Manager', 'Stock Manager'):
add_permission(doctype, role, 0)
update_permission_property(doctype, role, 0, 'write', 1)
update_permission_property(doctype, role, 0, 'create', 1)
29 changes: 25 additions & 4 deletions erpnext/erpnext_integrations/taxjar_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import taxjar
from frappe import _
from frappe.contacts.doctype.address.address import get_company_address
from frappe.utils import cint
from frappe.utils import cint, flt

from erpnext import get_default_company

Expand Down Expand Up @@ -103,7 +103,7 @@ def get_tax_data(doc):

shipping = sum([tax.tax_amount for tax in doc.taxes if tax.account_head == SHIP_ACCOUNT_HEAD])

line_items = [get_line_item_dict(item) for item in doc.items]
line_items = [get_line_item_dict(item, doc.docstatus) for item in doc.items]

if from_shipping_state not in SUPPORTED_STATE_CODES:
from_shipping_state = get_state_code(from_address, 'Company')
Expand Down Expand Up @@ -139,14 +139,21 @@ def get_state_code(address, location):

return state_code

def get_line_item_dict(item):
return dict(
def get_line_item_dict(item, docstatus):
tax_dict = dict(
id = item.get('idx'),
quantity = item.get('qty'),
unit_price = item.get('rate'),
product_tax_code = item.get('product_tax_category')
)

if docstatus == 1:
tax_dict.update({
'sales_tax':item.get('tax_collectable')
})

return tax_dict

def set_sales_tax(doc, method):
if not TAXJAR_CALCULATE_TAX:
return
Expand All @@ -164,6 +171,9 @@ def set_sales_tax(doc, method):
setattr(doc, "taxes", [tax for tax in doc.taxes if tax.account_head != TAX_ACCOUNT_HEAD])
return

# check if delivering within a nexus
check_for_nexus(doc, tax_dict)

tax_data = validate_tax_request(tax_dict)
if tax_data is not None:
if not tax_data.amount_to_collect:
Expand Down Expand Up @@ -191,6 +201,17 @@ def set_sales_tax(doc, method):

doc.run_method("calculate_taxes_and_totals")

def check_for_nexus(doc, tax_dict):
if not frappe.db.get_value('TaxJar Nexus', {'region_code': tax_dict["to_state"]}):
for item in doc.get("items"):
item.tax_collectable = flt(0)
item.taxable_amount = flt(0)

for tax in doc.taxes:
if tax.account_head == TAX_ACCOUNT_HEAD:
doc.taxes.remove(tax)
return

def check_sales_tax_exemption(doc):
# if the party is exempt from sales tax, then set all tax account heads to zero
sales_tax_exempted = hasattr(doc, "exempt_from_sales_tax") and doc.exempt_from_sales_tax \
Expand Down
6 changes: 6 additions & 0 deletions erpnext/patches.txt
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,12 @@ erpnext.patches.v13_0.add_custom_field_for_south_africa #2
erpnext.patches.v13_0.rename_discharge_ordered_date_in_ip_record
erpnext.patches.v13_0.migrate_stripe_api
erpnext.patches.v13_0.reset_clearance_date_for_intracompany_payment_entries
<<<<<<< HEAD
=======
erpnext.patches.v13_0.einvoicing_deprecation_warning
execute:frappe.reload_doc("erpnext_integrations", "doctype", "TaxJar Settings")
execute:frappe.reload_doc("erpnext_integrations", "doctype", "Product Tax Category")
>>>>>>> 2d19e2d54b (fix: Patch)
erpnext.patches.v13_0.custom_fields_for_taxjar_integration
erpnext.patches.v13_0.set_operation_time_based_on_operating_cost
erpnext.patches.v13_0.validate_options_for_data_field
Expand Down
12 changes: 9 additions & 3 deletions erpnext/patches/v13_0/custom_fields_for_taxjar_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,20 @@
import frappe
from frappe.custom.doctype.custom_field.custom_field import create_custom_fields

from erpnext.regional.united_states.setup import add_permissions
from erpnext.erpnext_integrations.doctype.taxjar_settings.taxjar_settings import add_permissions


def execute():
company = frappe.get_all('Company', filters = {'country': 'United States'}, fields=['name'])
if not company:
return

frappe.reload_doc("regional", "doctype", "product_tax_category")
TAXJAR_CREATE_TRANSACTIONS = frappe.db.get_single_value("TaxJar Settings", "taxjar_create_transactions")
TAXJAR_CALCULATE_TAX = frappe.db.get_single_value("TaxJar Settings", "taxjar_calculate_tax")
TAXJAR_SANDBOX_MODE = frappe.db.get_single_value("TaxJar Settings", "is_sandbox")

if (not TAXJAR_CREATE_TRANSACTIONS and not TAXJAR_CALCULATE_TAX and not TAXJAR_SANDBOX_MODE):
return

custom_fields = {
'Sales Invoice Item': [
Expand All @@ -29,4 +34,5 @@ def execute():
}
create_custom_fields(custom_fields, update=True)
add_permissions()
frappe.enqueue('erpnext.regional.united_states.setup.add_product_tax_categories', now=True)

frappe.enqueue('erpnext.erpnext_integrations.doctype.taxjar_settings.taxjar_settings.add_product_tax_categories', now=True)
Loading