Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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,50 @@
{
"actions": [],
"allow_rename": 1,
"creation": "2024-07-18 14:18:35.943218",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"customs_tariff_number",
"account_head",
"amount"
],
"fields": [
{
"fieldname": "account_head",
"fieldtype": "Link",
"in_list_view": 1,
"label": "Account Head",
"options": "Account",
"read_only": 1
},
{
"fieldname": "amount",
"fieldtype": "Currency",
"in_list_view": 1,
"label": "Amount",
"options": "currency"
},
{
"fieldname": "customs_tariff_number",
"fieldtype": "Link",
"in_list_view": 1,
"label": "Customs Tariff Number",
"options": "Customs Tariff Number",
"read_only": 1
}
],
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2024-08-20 18:22:06.460326",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Customs Tariff Tax",
"owner": "Administrator",
"permissions": [],
"sort_field": "modified",
"sort_order": "DESC",
"states": []
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Copyright (c) 2024, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt

# import frappe
from frappe.model.document import Document

class CustomsTariffTax(Document):
pass
15 changes: 14 additions & 1 deletion erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,8 @@
"shipping_rule",
"section_break_51",
"taxes",
"section_break_idyjv",
"customs_tariff_tax",
"sec_tax_breakup",
"other_charges_calculation",
"tax_exclusive_totals_section",
Expand Down Expand Up @@ -1878,13 +1880,24 @@
"options": "Company:company:default_currency",
"print_hide": 1,
"read_only": 1
},
{
"fieldname": "section_break_idyjv",
"fieldtype": "Section Break"
},
{
"depends_on": "eval:(doc.taxes || []).filter(d => d.charge_type == \"On HS Code\").length",
"fieldname": "customs_tariff_tax",
"fieldtype": "Table",
"label": "Customs Tariff Tax",
"options": "Customs Tariff Tax"
}
],
"icon": "fa fa-file-text",
"idx": 204,
"is_submittable": 1,
"links": [],
"modified": "2024-02-12 16:23:06.891238",
"modified": "2024-08-12 18:36:30.556478",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Invoice",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
"label": "Type",
"oldfieldname": "charge_type",
"oldfieldtype": "Select",
"options": "\nActual\nOn Net Total\nOn Previous Row Amount\nOn Previous Row Total\nOn Item Quantity\nWeighted Distribution\nManual",
"options": "\nActual\nOn Net Total\nOn Previous Row Amount\nOn Previous Row Total\nOn Item Quantity\nOn HS Code\nWeighted Distribution\nManual",
"reqd": 1
},
{
Expand Down Expand Up @@ -265,7 +265,7 @@
"idx": 1,
"istable": 1,
"links": [],
"modified": "2023-08-23 13:59:40.617093",
"modified": "2024-09-05 16:27:52.880423",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Taxes and Charges",
Expand Down
29 changes: 29 additions & 0 deletions erpnext/controllers/taxes_and_totals.py
Original file line number Diff line number Diff line change
Expand Up @@ -586,6 +586,35 @@ def get_current_tax_amount(self, item, tax, item_tax_map, weighted_distrubution_
current_tax_amount = (tax_rate / 100.0) * taxable_amount
elif tax.charge_type == "On Item Quantity":
current_tax_amount = tax_rate * item.qty
elif tax.charge_type == "On HS Code":
items_net_total = []
#totalling of items prices based on their HS codes
if len(self.doc.get("customs_tariff_tax", [])) > 0:
for items in self.doc.get("items", []):
index = -1
for i, sel_item in enumerate(items_net_total):
if sel_item["customs_tariff_number"] == items.customs_tariff_number:
index = i
break

if index != -1:
items_net_total[index]["total"] += items.amount
else:
items_net_total.append({
"customs_tariff_number": items.customs_tariff_number,
"total": items.amount,
})

#tax distribution according to the item qty & HS code
for tariff_tax_table in self.doc.get("customs_tariff_tax", []):
if tariff_tax_table.account_head == tax.account_head and item.customs_tariff_number == tariff_tax_table.customs_tariff_number:
for i, sel_item in enumerate(items_net_total):
if sel_item["customs_tariff_number"] == item.customs_tariff_number:
HS_code_tax_amount = tariff_tax_table.amount
HS_code_net_total = items_net_total[i]["total"]
current_tax_amount = (HS_code_tax_amount / HS_code_net_total) * item.amount
break


self.set_item_wise_tax(item, tax, tax_rate, current_tax_amount)

Expand Down
50 changes: 49 additions & 1 deletion erpnext/public/js/controllers/accounts.js
Original file line number Diff line number Diff line change
Expand Up @@ -168,13 +168,16 @@ cur_frm.cscript.account_head = function(doc, cdt, cdn) {
args: {
account_head: d.account_head
},
callback: function(r) {
callback: (r) => {
if (r.message) {
frappe.model.set_value(cdt, cdn, "description", r.message.account_name);
frappe.model.set_value(cdt, cdn, "exclude_from_item_tax_amount", cint(r.message.exclude_from_item_tax_amount));

if (["Actual", "Manual"].includes(d.charge_type)) {
frappe.model.set_value(cdt, cdn, "rate", flt(r.message.tax_rate) || 0);
} else if (d.charge_type == "On HS Code") {
this.update_customs_tariff_table();
frappe.model.set_value(cdt, cdn, "rate", 0);
} else {
frappe.model.set_value(cdt, cdn, "rate", 0);
}
Expand All @@ -184,6 +187,51 @@ cur_frm.cscript.account_head = function(doc, cdt, cdn) {
}
}

cur_frm.cscript.update_customs_tariff_table = function() {
let account_heads = (this.frm.doc.taxes || []).filter(tax => tax.charge_type === "On HS Code" && tax.account_head).map(tax => tax.account_head);
account_heads = [...new Set(account_heads)];

let customs_tariff_nos = (this.frm.doc.items || []).filter(d => d.customs_tariff_number).map(d => d.customs_tariff_number);
customs_tariff_nos = [...new Set(customs_tariff_nos)];

let item_account_tariff_nos = [];
for (let account_head of account_heads) {
for (let customs_tariff_number of customs_tariff_nos) {
item_account_tariff_nos.push({
account_head: account_head,
customs_tariff_number: customs_tariff_number,
});
}
}

let ui_account_tariff_nos = [];
for (let d of this.frm.doc.customs_tariff_tax || []) {
if (d.customs_tariff_number && d.account_head) {
ui_account_tariff_nos.push({
account_head: d.account_head,
customs_tariff_number: d.customs_tariff_number,
});
}
}

// Add missing
for (let item_data of item_account_tariff_nos) {
if (!ui_account_tariff_nos.find(ui_data => ui_data.account_head == item_data.account_head && ui_data.customs_tariff_number == item_data.customs_tariff_number)) {
let row = this.frm.add_child('customs_tariff_tax');
row.account_head = item_data.account_head;
row.customs_tariff_number = item_data.customs_tariff_number
this.frm.refresh_field('customs_tariff_tax');
}
}

// Remove extra
this.frm.doc.customs_tariff_tax = (this.frm.doc.customs_tariff_tax || []).filter(ui_data => {
return item_account_tariff_nos.find(item_data => ui_data.account_head == item_data.account_head && ui_data.customs_tariff_number == item_data.customs_tariff_number);
});

this.frm.refresh_field("customs_tariff_tax");
}

cur_frm.cscript.validate_taxes_and_charges = function(cdt, cdn) {
var d = locals[cdt][cdn];
var msg = "";
Expand Down
36 changes: 35 additions & 1 deletion erpnext/public/js/controllers/taxes_and_totals.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// License: GNU General Public License v3. See license.txt

erpnext.taxes_and_totals_hooks = [];

erpnext.taxes_and_totals = class TaxesAndTotals extends erpnext.payments {
apply_pricing_rule_on_item(item) {
let effective_item_rate = item.price_list_rate;
Expand Down Expand Up @@ -694,13 +694,46 @@ erpnext.taxes_and_totals = class TaxesAndTotals extends erpnext.payments {
current_tax_amount = (tax_rate / 100.0) * taxable_amount;
} else if (tax.charge_type == "On Item Quantity") {
current_tax_amount = tax_rate * item.qty;
} else if (tax.charge_type == "On HS Code") {
let items_net_total = [];
// totalling of items prices based on their HS codes
if ((this.frm.doc["customs_tariff_tax"] || []).length > 0) {
(this.frm.doc["items"] || []).forEach((item) => {
let index = items_net_total.findIndex(d => d.customs_tariff_number === item.customs_tariff_number);

if (index !== -1) {
items_net_total[index].total += item.amount;
} else {
items_net_total.push({
customs_tariff_number: item.customs_tariff_number,
total: item.amount,
});
}
});
}

// tax distribution according to the item qty & HS code
$.each(this.frm.doc["customs_tariff_tax"] || [], function(j, tariff_tax_table) {
if (tariff_tax_table.account_head == tax.account_head && item.customs_tariff_number == tariff_tax_table.customs_tariff_number) {
let HS_code_tax_amount = tariff_tax_table.amount;
let HS_code_net_total = items_net_total[items_net_total.findIndex(d => d.customs_tariff_number == item.customs_tariff_number)].total
current_tax_amount = (HS_code_tax_amount / HS_code_net_total) * item.amount;
}
});
this.frm.refresh_field("taxes");
this.frm.refresh_field("total_taxes_and_charges");

}

this.set_item_wise_tax(item, tax, tax_rate, current_tax_amount);

return current_tax_amount;
}

amount = function(doc, cdt, cdn) {
this._calculate_taxes_and_totals();
}

set_item_wise_tax(item, tax, tax_rate, current_tax_amount) {
// store tax breakup for each item
if (!item.item_tax_detail.hasOwnProperty(tax.name)) {
Expand Down Expand Up @@ -825,6 +858,7 @@ erpnext.taxes_and_totals = class TaxesAndTotals extends erpnext.payments {
this.frm.doc.total_taxes_and_charges = this.frm.doc.total_after_taxes - this.frm.doc.taxable_total - flt(this.frm.doc.rounding_adjustment);
if (this.should_round_transaction_currency()) {
this.frm.doc.total_taxes_and_charges = flt(this.frm.doc.total_taxes_and_charges, precision("total_taxes_and_charges"));

}

this.set_in_company_currency(this.frm.doc, ["total_taxes_and_charges", "rounding_adjustment"],
Expand Down
9 changes: 6 additions & 3 deletions erpnext/public/js/controllers/transaction.js
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,9 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe

frappe.ui.form.on(this.frm.cscript.tax_table, {
taxes_remove: function(frm, cdt, cdn) {
cur_frm.cscript.set_dynamic_labels();
cur_frm.cscript.calculate_taxes_and_totals();
frm.cscript.set_dynamic_labels();
frm.cscript.update_customs_tariff_table();
frm.cscript.calculate_taxes_and_totals();
}
});

Expand Down Expand Up @@ -201,6 +202,7 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe
},

items_remove: function (frm) {
frm.cscript.update_customs_tariff_table();
frm.cscript.calculate_taxes_and_totals();
},

Expand Down Expand Up @@ -775,7 +777,8 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe
let key = item.name;
me.apply_rule_on_other_items({key: item});
}
}
},
() => me.update_customs_tariff_table(),
]);
}
}
Expand Down
1 change: 1 addition & 0 deletions erpnext/stock/get_item_details.py
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,7 @@ def get_basic_details(args, item, overwrite_warehouse=True):
"has_serial_no": item.has_serial_no,
"has_batch_no": item.has_batch_no,
"is_vehicle": item.is_vehicle,
"customs_tariff_number": item.customs_tariff_number,
"batch_no": args.get("batch_no") if args.get("batch_no") and frappe.db.get_value("Batch", args.get("batch_no"), 'item') == item.name else "",
"stock_uom": item.stock_uom,
"uom": default_uom,
Expand Down