mirror of
https://github.com/frappe/erpnext.git
synced 2026-05-31 10:49:09 +00:00
fix: Add server side methods and other fixes
This commit is contained in:
@@ -442,7 +442,7 @@ class AccountsController(TransactionBase):
|
|||||||
account_currency = get_account_currency(gl_dict.account)
|
account_currency = get_account_currency(gl_dict.account)
|
||||||
|
|
||||||
if gl_dict.account and self.doctype not in ["Journal Entry",
|
if gl_dict.account and self.doctype not in ["Journal Entry",
|
||||||
"Period Closing Voucher", "Payment Entry"]:
|
"Period Closing Voucher", "Payment Entry", "Purchase Receipt", "Purchase Invoice"]:
|
||||||
self.validate_account_currency(gl_dict.account, account_currency)
|
self.validate_account_currency(gl_dict.account, account_currency)
|
||||||
set_balance_in_account_currency(gl_dict, account_currency, self.get("conversion_rate"),
|
set_balance_in_account_currency(gl_dict, account_currency, self.get("conversion_rate"),
|
||||||
self.company_currency)
|
self.company_currency)
|
||||||
|
|||||||
@@ -96,9 +96,9 @@ erpnext.stock.LandedCostVoucher = erpnext.stock.StockController.extend({
|
|||||||
set_total_taxes_and_charges: function() {
|
set_total_taxes_and_charges: function() {
|
||||||
var total_taxes_and_charges = 0.0;
|
var total_taxes_and_charges = 0.0;
|
||||||
$.each(this.frm.doc.taxes || [], function(i, d) {
|
$.each(this.frm.doc.taxes || [], function(i, d) {
|
||||||
total_taxes_and_charges += flt(d.base_amount)
|
total_taxes_and_charges += flt(d.base_amount);
|
||||||
});
|
});
|
||||||
cur_frm.set_value("total_taxes_and_charges", total_taxes_and_charges);
|
this.frm.set_value("total_taxes_and_charges", total_taxes_and_charges);
|
||||||
},
|
},
|
||||||
|
|
||||||
set_applicable_charges_for_item: function() {
|
set_applicable_charges_for_item: function() {
|
||||||
@@ -148,11 +148,16 @@ frappe.ui.form.on('Landed Cost Voucher', {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
onload: function(frm) {
|
||||||
|
let company_currency = frappe.get_doc(":Company", frm.doc.company).default_currency;
|
||||||
|
frm.set_currency_labels(["total_taxes_and_charges"], company_currency);
|
||||||
|
},
|
||||||
|
|
||||||
set_exchange_rate: function(frm, cdt, cdn) {
|
set_exchange_rate: function(frm, cdt, cdn) {
|
||||||
let row = locals[cdt][cdn];
|
let row = locals[cdt][cdn];
|
||||||
let company_currency = frappe.get_doc(":Company", frm.doc.company).default_currency;
|
let company_currency = frappe.get_doc(":Company", frm.doc.company).default_currency;
|
||||||
|
|
||||||
if(row.account_currency == company_currency) {
|
if (row.account_currency == company_currency) {
|
||||||
row.exchange_rate = 1;
|
row.exchange_rate = 1;
|
||||||
} else if (!row.exchange_rate || row.exchange_rate == 1) {
|
} else if (!row.exchange_rate || row.exchange_rate == 1) {
|
||||||
frappe.call({
|
frappe.call({
|
||||||
@@ -164,12 +169,12 @@ frappe.ui.form.on('Landed Cost Voucher', {
|
|||||||
company: frm.doc.company
|
company: frm.doc.company
|
||||||
},
|
},
|
||||||
callback: function(r) {
|
callback: function(r) {
|
||||||
if(r.message) {
|
if (r.message) {
|
||||||
frappe.model.set_value(cdt, cdn, "exchange_rate", r.message);
|
frappe.model.set_value(cdt, cdn, "exchange_rate", r.message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
}
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
set_base_amount: function(frm, cdt, cdn) {
|
set_base_amount: function(frm, cdt, cdn) {
|
||||||
@@ -177,7 +182,7 @@ frappe.ui.form.on('Landed Cost Voucher', {
|
|||||||
frappe.model.set_value(cdt, cdn, "base_amount",
|
frappe.model.set_value(cdt, cdn, "base_amount",
|
||||||
flt(flt(row.amount)*row.exchange_rate, precision("base_amount", row)));
|
flt(flt(row.amount)*row.exchange_rate, precision("base_amount", row)));
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
|
|
||||||
frappe.ui.form.on('Landed Cost Taxes and Charges', {
|
frappe.ui.form.on('Landed Cost Taxes and Charges', {
|
||||||
expense_account: function(frm, cdt, cdn) {
|
expense_account: function(frm, cdt, cdn) {
|
||||||
|
|||||||
@@ -40,14 +40,17 @@ class LandedCostVoucher(Document):
|
|||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
self.check_mandatory()
|
self.check_mandatory()
|
||||||
|
self.validate_purchase_receipts()
|
||||||
|
self.set_account_currency()
|
||||||
self.set_exchange_rate()
|
self.set_exchange_rate()
|
||||||
self.set_amounts_in_company_currency()
|
self.set_amounts_in_company_currency()
|
||||||
|
self.set_total_taxes_and_charges()
|
||||||
if not self.get("items"):
|
if not self.get("items"):
|
||||||
self.get_items_from_purchase_receipts()
|
self.get_items_from_purchase_receipts()
|
||||||
else:
|
|
||||||
self.validate_applicable_charges_for_item()
|
self.set_applicable_charges_on_item()
|
||||||
self.validate_purchase_receipts()
|
self.validate_applicable_charges_for_item()
|
||||||
self.set_total_taxes_and_charges()
|
|
||||||
|
|
||||||
def check_mandatory(self):
|
def check_mandatory(self):
|
||||||
if not self.get("purchase_receipts"):
|
if not self.get("purchase_receipts"):
|
||||||
@@ -78,6 +81,33 @@ class LandedCostVoucher(Document):
|
|||||||
def set_total_taxes_and_charges(self):
|
def set_total_taxes_and_charges(self):
|
||||||
self.total_taxes_and_charges = sum([flt(d.base_amount) for d in self.get("taxes")])
|
self.total_taxes_and_charges = sum([flt(d.base_amount) for d in self.get("taxes")])
|
||||||
|
|
||||||
|
def set_applicable_charges_on_item(self):
|
||||||
|
if self.get('taxes'):
|
||||||
|
total_item_cost = 0.0
|
||||||
|
total_charges = 0.0
|
||||||
|
item_count = 0
|
||||||
|
based_on_field = frappe.scrub(self.distribute_charges_based_on)
|
||||||
|
|
||||||
|
for item in self.get('items'):
|
||||||
|
total_item_cost += item.get(based_on_field)
|
||||||
|
|
||||||
|
for item in self.get('items'):
|
||||||
|
item.applicable_charges = flt(flt(item.get(based_on_field)) * flt(self.total_taxes_and_charges) / flt(total_item_cost),
|
||||||
|
item.precision('applicable_charges'))
|
||||||
|
total_charges += item.applicable_charges
|
||||||
|
item_count += 1
|
||||||
|
|
||||||
|
if total_charges != self.total_taxes_and_charges:
|
||||||
|
diff = self.total_taxes_and_charges - total_charges
|
||||||
|
self.get('items')[item_count - 1].applicable_charges += diff
|
||||||
|
|
||||||
|
def set_account_currency(self):
|
||||||
|
company_currency = erpnext.get_company_currency(self.company)
|
||||||
|
for d in self.get('taxes'):
|
||||||
|
if not d.account_currency:
|
||||||
|
account_currency = frappe.db.get_value('Account', d.expense_account, 'account_currency')
|
||||||
|
d.account_currency = account_currency or company_currency
|
||||||
|
|
||||||
def set_exchange_rate(self):
|
def set_exchange_rate(self):
|
||||||
company_currency = erpnext.get_company_currency(self.company)
|
company_currency = erpnext.get_company_currency(self.company)
|
||||||
for d in self.get('taxes'):
|
for d in self.get('taxes'):
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt \
|
|||||||
import set_perpetual_inventory, get_gl_entries, test_records as pr_test_records, make_purchase_receipt
|
import set_perpetual_inventory, get_gl_entries, test_records as pr_test_records, make_purchase_receipt
|
||||||
from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice
|
from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice
|
||||||
from erpnext.accounts.doctype.account.test_account import get_inventory_account
|
from erpnext.accounts.doctype.account.test_account import get_inventory_account
|
||||||
|
from erpnext.accounts.doctype.account.test_account import create_account
|
||||||
|
|
||||||
class TestLandedCostVoucher(unittest.TestCase):
|
class TestLandedCostVoucher(unittest.TestCase):
|
||||||
def test_landed_cost_voucher(self):
|
def test_landed_cost_voucher(self):
|
||||||
@@ -27,7 +28,7 @@ class TestLandedCostVoucher(unittest.TestCase):
|
|||||||
},
|
},
|
||||||
fieldname=["qty_after_transaction", "stock_value"], as_dict=1)
|
fieldname=["qty_after_transaction", "stock_value"], as_dict=1)
|
||||||
|
|
||||||
submit_landed_cost_voucher("Purchase Receipt", pr.name, pr.company)
|
create_landed_cost_voucher("Purchase Receipt", pr.name, pr.company)
|
||||||
|
|
||||||
pr_lc_value = frappe.db.get_value("Purchase Receipt Item", {"parent": pr.name}, "landed_cost_voucher_amount")
|
pr_lc_value = frappe.db.get_value("Purchase Receipt Item", {"parent": pr.name}, "landed_cost_voucher_amount")
|
||||||
self.assertEqual(pr_lc_value, 25.0)
|
self.assertEqual(pr_lc_value, 25.0)
|
||||||
@@ -89,7 +90,7 @@ class TestLandedCostVoucher(unittest.TestCase):
|
|||||||
},
|
},
|
||||||
fieldname=["qty_after_transaction", "stock_value"], as_dict=1)
|
fieldname=["qty_after_transaction", "stock_value"], as_dict=1)
|
||||||
|
|
||||||
submit_landed_cost_voucher("Purchase Invoice", pi.name, pi.company)
|
create_landed_cost_voucher("Purchase Invoice", pi.name, pi.company)
|
||||||
|
|
||||||
pi_lc_value = frappe.db.get_value("Purchase Invoice Item", {"parent": pi.name},
|
pi_lc_value = frappe.db.get_value("Purchase Invoice Item", {"parent": pi.name},
|
||||||
"landed_cost_voucher_amount")
|
"landed_cost_voucher_amount")
|
||||||
@@ -137,7 +138,7 @@ class TestLandedCostVoucher(unittest.TestCase):
|
|||||||
|
|
||||||
serial_no_rate = frappe.db.get_value("Serial No", "SN001", "purchase_rate")
|
serial_no_rate = frappe.db.get_value("Serial No", "SN001", "purchase_rate")
|
||||||
|
|
||||||
submit_landed_cost_voucher("Purchase Receipt", pr.name, pr.company)
|
create_landed_cost_voucher("Purchase Receipt", pr.name, pr.company)
|
||||||
|
|
||||||
serial_no = frappe.db.get_value("Serial No", "SN001",
|
serial_no = frappe.db.get_value("Serial No", "SN001",
|
||||||
["warehouse", "purchase_rate"], as_dict=1)
|
["warehouse", "purchase_rate"], as_dict=1)
|
||||||
@@ -160,7 +161,7 @@ class TestLandedCostVoucher(unittest.TestCase):
|
|||||||
})
|
})
|
||||||
pr.submit()
|
pr.submit()
|
||||||
|
|
||||||
lcv = submit_landed_cost_voucher("Purchase Receipt", pr.name, pr.company, 123.22)
|
lcv = create_landed_cost_voucher("Purchase Receipt", pr.name, pr.company, 123.22)
|
||||||
|
|
||||||
self.assertEqual(lcv.items[0].applicable_charges, 41.07)
|
self.assertEqual(lcv.items[0].applicable_charges, 41.07)
|
||||||
self.assertEqual(lcv.items[2].applicable_charges, 41.08)
|
self.assertEqual(lcv.items[2].applicable_charges, 41.08)
|
||||||
@@ -206,6 +207,46 @@ class TestLandedCostVoucher(unittest.TestCase):
|
|||||||
self.assertEqual(pr.items[0].landed_cost_voucher_amount, 100)
|
self.assertEqual(pr.items[0].landed_cost_voucher_amount, 100)
|
||||||
self.assertEqual(pr.items[1].landed_cost_voucher_amount, 100)
|
self.assertEqual(pr.items[1].landed_cost_voucher_amount, 100)
|
||||||
|
|
||||||
|
def test_multi_currency_lcv(self):
|
||||||
|
## Create USD Shipping charges_account
|
||||||
|
usd_shipping = create_account(account_name="Shipping Charges USD",
|
||||||
|
parent_account="Duties and Taxes - TCP1", company="_Test Company with perpetual inventory",
|
||||||
|
account_currency="USD")
|
||||||
|
|
||||||
|
pr = make_purchase_receipt(company="_Test Company with perpetual inventory", warehouse = "Stores - TCP1",
|
||||||
|
supplier_warehouse = "Stores - TCP1")
|
||||||
|
pr.submit()
|
||||||
|
|
||||||
|
lcv = make_landed_cost_voucher(company = pr.company, receipt_document_type = "Purchase Receipt",
|
||||||
|
receipt_document=pr.name, charges=100, do_not_save=True)
|
||||||
|
|
||||||
|
lcv.append("taxes", {
|
||||||
|
"description": "Shipping Charges",
|
||||||
|
"expense_account": usd_shipping,
|
||||||
|
"amount": 10
|
||||||
|
})
|
||||||
|
|
||||||
|
lcv.save()
|
||||||
|
lcv.submit()
|
||||||
|
pr.load_from_db()
|
||||||
|
|
||||||
|
# Considering exchange rate from USD to INR as 62.9
|
||||||
|
self.assertEqual(lcv.total_taxes_and_charges, 729)
|
||||||
|
self.assertEqual(pr.items[0].landed_cost_voucher_amount, 729)
|
||||||
|
|
||||||
|
gl_entries = frappe.get_all("GL Entry", fields=["account", "credit", "credit_in_account_currency"],
|
||||||
|
filters={"voucher_no": pr.name, "account": ("in", ["Shipping Charges USD - TCP1", "Expenses Included In Valuation - TCP1"])})
|
||||||
|
|
||||||
|
expected_gl_entries = {
|
||||||
|
"Shipping Charges USD - TCP1": [629, 10],
|
||||||
|
"Expenses Included In Valuation - TCP1": [100, 100]
|
||||||
|
}
|
||||||
|
|
||||||
|
for entry in gl_entries:
|
||||||
|
amounts = expected_gl_entries.get(entry.account)
|
||||||
|
self.assertEqual(entry.credit, amounts[0])
|
||||||
|
self.assertEqual(entry.credit_in_account_currency, amounts[1])
|
||||||
|
|
||||||
def make_landed_cost_voucher(** args):
|
def make_landed_cost_voucher(** args):
|
||||||
args = frappe._dict(args)
|
args = frappe._dict(args)
|
||||||
ref_doc = frappe.get_doc(args.receipt_document_type, args.receipt_document)
|
ref_doc = frappe.get_doc(args.receipt_document_type, args.receipt_document)
|
||||||
@@ -236,7 +277,7 @@ def make_landed_cost_voucher(** args):
|
|||||||
return lcv
|
return lcv
|
||||||
|
|
||||||
|
|
||||||
def submit_landed_cost_voucher(receipt_document_type, receipt_document, company, charges=50):
|
def create_landed_cost_voucher(receipt_document_type, receipt_document, company, charges=50):
|
||||||
ref_doc = frappe.get_doc(receipt_document_type, receipt_document)
|
ref_doc = frappe.get_doc(receipt_document_type, receipt_document)
|
||||||
|
|
||||||
lcv = frappe.new_doc("Landed Cost Voucher")
|
lcv = frappe.new_doc("Landed Cost Voucher")
|
||||||
|
|||||||
@@ -279,12 +279,15 @@ class PurchaseReceipt(BuyingController):
|
|||||||
# Amount added through landed-cost-voucher
|
# Amount added through landed-cost-voucher
|
||||||
if d.landed_cost_voucher_amount and landed_cost_entries:
|
if d.landed_cost_voucher_amount and landed_cost_entries:
|
||||||
for account, amount in iteritems(landed_cost_entries[(d.item_code, d.name)]):
|
for account, amount in iteritems(landed_cost_entries[(d.item_code, d.name)]):
|
||||||
|
account_currency = get_account_currency(account)
|
||||||
gl_entries.append(self.get_gl_dict({
|
gl_entries.append(self.get_gl_dict({
|
||||||
"account": account,
|
"account": account,
|
||||||
|
"account_currency": account_currency,
|
||||||
"against": warehouse_account[d.warehouse]["account"],
|
"against": warehouse_account[d.warehouse]["account"],
|
||||||
"cost_center": d.cost_center,
|
"cost_center": d.cost_center,
|
||||||
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
|
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
|
||||||
"credit": flt(amount),
|
"credit": flt(amount["base_amount"]),
|
||||||
|
"credit_in_account_currency": flt(amount["amount"]),
|
||||||
"project": d.project
|
"project": d.project
|
||||||
}, item=d))
|
}, item=d))
|
||||||
|
|
||||||
@@ -729,9 +732,16 @@ def get_item_account_wise_additional_cost(purchase_document):
|
|||||||
if item.receipt_document == purchase_document:
|
if item.receipt_document == purchase_document:
|
||||||
for account in landed_cost_voucher_doc.taxes:
|
for account in landed_cost_voucher_doc.taxes:
|
||||||
item_account_wise_cost.setdefault((item.item_code, item.purchase_receipt_item), {})
|
item_account_wise_cost.setdefault((item.item_code, item.purchase_receipt_item), {})
|
||||||
item_account_wise_cost[(item.item_code, item.purchase_receipt_item)].setdefault(account.expense_account, 0.0)
|
item_account_wise_cost[(item.item_code, item.purchase_receipt_item)].setdefault(account.expense_account, {
|
||||||
item_account_wise_cost[(item.item_code, item.purchase_receipt_item)][account.expense_account] += \
|
"amount": 0.0,
|
||||||
|
"base_amount": 0.0
|
||||||
|
})
|
||||||
|
|
||||||
|
item_account_wise_cost[(item.item_code, item.purchase_receipt_item)][account.expense_account]["amount"] += \
|
||||||
account.amount * item.get(based_on_field) / total_item_cost
|
account.amount * item.get(based_on_field) / total_item_cost
|
||||||
|
|
||||||
|
item_account_wise_cost[(item.item_code, item.purchase_receipt_item)][account.expense_account]["base_amount"] += \
|
||||||
|
account.base_amount * item.get(based_on_field) / total_item_cost
|
||||||
|
|
||||||
return item_account_wise_cost
|
return item_account_wise_cost
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user