Merge branch 'v7.2.0-beta' into develop
This commit is contained in:
commit
0632ee3da9
@ -4,7 +4,7 @@ from __future__ import unicode_literals
|
||||
|
||||
import frappe
|
||||
import unittest, copy
|
||||
from frappe.utils import nowdate, add_days, flt, nowdate
|
||||
from frappe.utils import nowdate, add_days, flt
|
||||
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry, get_qty_after_transaction
|
||||
from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import unlink_payment_on_cancel_of_invoice
|
||||
from erpnext.accounts.doctype.pos_profile.test_pos_profile import make_pos_profile
|
||||
@ -162,11 +162,50 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
self.assertEquals(si.base_grand_total, 1628)
|
||||
self.assertEquals(si.grand_total, 32.56)
|
||||
|
||||
def test_sales_invoice_with_discount_and_inclusive_tax(self):
|
||||
si = create_sales_invoice(qty=100, rate=50, do_not_save=True)
|
||||
si.append("taxes", {
|
||||
"charge_type": "On Net Total",
|
||||
"account_head": "_Test Account Service Tax - _TC",
|
||||
"cost_center": "_Test Cost Center - _TC",
|
||||
"description": "Service Tax",
|
||||
"rate": 14,
|
||||
'included_in_print_rate': 1
|
||||
})
|
||||
si.insert()
|
||||
|
||||
# with inclusive tax
|
||||
self.assertEquals(si.net_total, 4385.96)
|
||||
self.assertEquals(si.grand_total, 5000)
|
||||
|
||||
si.reload()
|
||||
|
||||
# additional discount
|
||||
si.discount_amount = 100
|
||||
si.apply_discount_on = 'Net Total'
|
||||
|
||||
si.save()
|
||||
|
||||
# with inclusive tax and additional discount
|
||||
self.assertEquals(si.net_total, 4285.96)
|
||||
self.assertEquals(si.grand_total, 4885.99)
|
||||
|
||||
si.reload()
|
||||
|
||||
# additional discount on grand total
|
||||
si.discount_amount = 100
|
||||
si.apply_discount_on = 'Grand Total'
|
||||
|
||||
si.save()
|
||||
|
||||
# with inclusive tax and additional discount
|
||||
self.assertEquals(si.net_total, 4298.24)
|
||||
self.assertEquals(si.grand_total, 4900.00)
|
||||
|
||||
def test_sales_invoice_discount_amount(self):
|
||||
si = frappe.copy_doc(test_records[3])
|
||||
si.discount_amount = 104.95
|
||||
si.append("taxes", {
|
||||
"doctype": "Sales Taxes and Charges",
|
||||
"charge_type": "On Previous Row Amount",
|
||||
"account_head": "_Test Account Service Tax - _TC",
|
||||
"cost_center": "_Test Cost Center - _TC",
|
||||
@ -961,7 +1000,7 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
pe.submit()
|
||||
|
||||
self.assertEquals(frappe.db.get_value('Customer', customer.name, 'status'), 'Active')
|
||||
|
||||
|
||||
def test_outstanding_amount_after_advance_jv_cancelation(self):
|
||||
from erpnext.accounts.doctype.journal_entry.test_journal_entry \
|
||||
import test_records as jv_test_records
|
||||
@ -986,15 +1025,15 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
|
||||
#check outstanding after advance allocation
|
||||
self.assertEqual(flt(si.outstanding_amount), flt(si.grand_total - si.total_advance, si.precision("outstanding_amount")))
|
||||
|
||||
|
||||
#added to avoid Document has been modified exception
|
||||
jv = frappe.get_doc("Journal Entry", jv.name)
|
||||
jv.cancel()
|
||||
|
||||
|
||||
si.load_from_db()
|
||||
#check outstanding after advance cancellation
|
||||
self.assertEqual(flt(si.outstanding_amount), flt(si.grand_total + si.total_advance, si.precision("outstanding_amount")))
|
||||
|
||||
|
||||
def test_outstanding_amount_after_advance_payment_entry_cancelation(self):
|
||||
pe = frappe.get_doc({
|
||||
"doctype": "Payment Entry",
|
||||
@ -1015,7 +1054,7 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
})
|
||||
pe.insert()
|
||||
pe.submit()
|
||||
|
||||
|
||||
si = frappe.copy_doc(test_records[0])
|
||||
si.is_pos = 0
|
||||
si.append("advances", {
|
||||
@ -1028,16 +1067,16 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
})
|
||||
si.insert()
|
||||
si.submit()
|
||||
|
||||
|
||||
si.load_from_db()
|
||||
|
||||
#check outstanding after advance allocation
|
||||
self.assertEqual(flt(si.outstanding_amount), flt(si.grand_total - si.total_advance, si.precision("outstanding_amount")))
|
||||
|
||||
|
||||
#added to avoid Document has been modified exception
|
||||
pe = frappe.get_doc("Payment Entry", pe.name)
|
||||
pe.cancel()
|
||||
|
||||
|
||||
si.load_from_db()
|
||||
#check outstanding after advance cancellation
|
||||
self.assertEqual(flt(si.outstanding_amount), flt(si.grand_total + si.total_advance, si.precision("outstanding_amount")))
|
||||
|
@ -366,8 +366,9 @@ class calculate_taxes_and_totals(object):
|
||||
# discount amount rounding loss adjustment if no taxes
|
||||
if (not taxes or self.doc.apply_discount_on == "Net Total") \
|
||||
and i == len(self.doc.get("items")) - 1:
|
||||
discount_amount_loss = flt(self.doc.total - net_total - self.doc.discount_amount,
|
||||
discount_amount_loss = flt(self.doc.net_total - net_total - self.doc.discount_amount,
|
||||
self.doc.precision("net_total"))
|
||||
|
||||
item.net_amount = flt(item.net_amount + discount_amount_loss,
|
||||
item.precision("net_amount"))
|
||||
|
||||
@ -452,7 +453,7 @@ class calculate_taxes_and_totals(object):
|
||||
|
||||
elif self.doc.doctype == "Purchase Invoice":
|
||||
self.doc.outstanding_amount = flt(total_amount_to_pay, self.doc.precision("outstanding_amount"))
|
||||
|
||||
|
||||
def calculate_paid_amount(self):
|
||||
paid_amount = base_paid_amount = 0.0
|
||||
for payment in self.doc.get('payments'):
|
||||
@ -467,7 +468,7 @@ class calculate_taxes_and_totals(object):
|
||||
self.doc.change_amount = 0.0
|
||||
self.doc.base_change_amount = 0.0
|
||||
if self.doc.paid_amount > self.doc.grand_total:
|
||||
self.doc.change_amount = flt(self.doc.paid_amount - self.doc.grand_total +
|
||||
self.doc.change_amount = flt(self.doc.paid_amount - self.doc.grand_total +
|
||||
self.doc.write_off_amount, self.doc.precision("change_amount"))
|
||||
|
||||
self.doc.base_change_amount = flt(self.doc.base_paid_amount - self.doc.base_grand_total +
|
||||
@ -483,7 +484,7 @@ class calculate_taxes_and_totals(object):
|
||||
def calculate_margin(self, item):
|
||||
total_margin = 0.0
|
||||
if item.price_list_rate:
|
||||
if item.pricing_rule and not self.doc.ignore_pricing_rule:
|
||||
if item.pricing_rule and not self.doc.ignore_pricing_rule:
|
||||
pricing_rule = frappe.get_doc('Pricing Rule', item.pricing_rule)
|
||||
item.margin_type = pricing_rule.margin_type
|
||||
item.margin_rate_or_amount = pricing_rule.margin_rate_or_amount
|
||||
@ -492,4 +493,4 @@ class calculate_taxes_and_totals(object):
|
||||
margin_value = item.margin_rate_or_amount if item.margin_type == 'Amount' else flt(item.price_list_rate) * flt(item.margin_rate_or_amount) / 100
|
||||
total_margin = flt(item.price_list_rate) + flt(margin_value)
|
||||
|
||||
return total_margin
|
||||
return total_margin
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -431,22 +431,16 @@ frappe.ui.form.on('Stock Entry Detail', {
|
||||
uom: function(doc, cdt, cdn) {
|
||||
var d = locals[cdt][cdn];
|
||||
if(d.uom && d.item_code){
|
||||
arg = {
|
||||
'item_code':d.item_code,
|
||||
'uom':d.uom,
|
||||
'qty':d.qty
|
||||
};
|
||||
return frappe.call({
|
||||
doc: cur_frm.doc,
|
||||
method: "get_uom_details",
|
||||
args: arg,
|
||||
method: "erpnext.stock.doctype.stock_entry.stock_entry.get_uom_details",
|
||||
args: {
|
||||
item_code: d.item_code,
|
||||
uom: d.uom,
|
||||
qty: d.qty
|
||||
},
|
||||
callback: function(r) {
|
||||
if(r.message) {
|
||||
var d = locals[cdt][cdn];
|
||||
$.each(r.message, function(k, v) {
|
||||
d[k] = v;
|
||||
});
|
||||
refresh_field("items");
|
||||
frappe.model.set_value(cdt, cdn, r.message);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -233,7 +233,7 @@ class StockEntry(StockController):
|
||||
for d in self.get('items'):
|
||||
transferred_serial_no = frappe.db.get_value("Stock Entry Detail",{"parent": previous_se,
|
||||
"item_code": d.item_code}, "serial_no")
|
||||
|
||||
|
||||
if transferred_serial_no:
|
||||
d.serial_no = transferred_serial_no
|
||||
|
||||
@ -496,7 +496,7 @@ class StockEntry(StockController):
|
||||
|
||||
# update uom
|
||||
if args.get("uom") and for_update:
|
||||
ret.update(self.get_uom_details(args))
|
||||
ret.update(get_uom_details(args.get('item_code'), args.get('uom'), args.get('qty')))
|
||||
|
||||
if not ret["expense_account"]:
|
||||
ret["expense_account"] = frappe.db.get_value("Company", self.company, "stock_adjustment_account")
|
||||
@ -509,23 +509,6 @@ class StockEntry(StockController):
|
||||
|
||||
return ret
|
||||
|
||||
def get_uom_details(self, args):
|
||||
"""Returns dict `{"conversion_factor": [value], "transfer_qty": qty * [value]}`
|
||||
|
||||
:param args: dict with `item_code`, `uom` and `qty`"""
|
||||
conversion_factor = get_conversion_factor(args.get("item_code"), args.get("uom")).get("conversion_factor")
|
||||
|
||||
if not conversion_factor:
|
||||
frappe.msgprint(_("UOM coversion factor required for UOM: {0} in Item: {1}")
|
||||
.format(args.get("uom"), args.get("item_code")))
|
||||
ret = {'uom' : ''}
|
||||
else:
|
||||
ret = {
|
||||
'conversion_factor' : flt(conversion_factor),
|
||||
'transfer_qty' : flt(args.get("qty")) * flt(conversion_factor)
|
||||
}
|
||||
return ret
|
||||
|
||||
def get_items(self):
|
||||
self.set('items', [])
|
||||
self.validate_production_order()
|
||||
@ -559,7 +542,7 @@ class StockEntry(StockController):
|
||||
item["from_warehouse"] = self.pro_doc.wip_warehouse
|
||||
|
||||
item["to_warehouse"] = self.to_warehouse if self.purpose=="Subcontract" else ""
|
||||
|
||||
|
||||
self.add_to_stock_entry_detail(item_dict)
|
||||
|
||||
scrap_item_dict = self.get_bom_scrap_material(self.fg_completed_qty)
|
||||
@ -567,7 +550,7 @@ class StockEntry(StockController):
|
||||
if self.pro_doc and self.pro_doc.scrap_warehouse:
|
||||
item["to_warehouse"] = self.pro_doc.scrap_warehouse
|
||||
self.add_to_stock_entry_detail(scrap_item_dict, bom_no=self.bom_no)
|
||||
|
||||
|
||||
# fetch the serial_no of the first stock entry for the second stock entry
|
||||
if self.production_order and self.purpose == "Manufacture":
|
||||
self.set_serial_nos(self.production_order)
|
||||
@ -632,10 +615,10 @@ class StockEntry(StockController):
|
||||
for item in item_dict.values():
|
||||
item.from_warehouse = self.from_warehouse or item.default_warehouse
|
||||
return item_dict
|
||||
|
||||
|
||||
def get_bom_scrap_material(self, qty):
|
||||
from erpnext.manufacturing.doctype.bom.bom import get_bom_items_as_dict
|
||||
|
||||
|
||||
# item dict = { item_code: {qty, description, stock_uom} }
|
||||
item_dict = get_bom_items_as_dict(self.bom_no, self.company, qty=qty,
|
||||
fetch_exploded = 0, fetch_scrap_items = 1)
|
||||
@ -643,7 +626,7 @@ class StockEntry(StockController):
|
||||
for item in item_dict.values():
|
||||
item.from_warehouse = ""
|
||||
return item_dict
|
||||
|
||||
|
||||
def get_transfered_raw_materials(self):
|
||||
transferred_materials = frappe.db.sql("""
|
||||
select
|
||||
@ -849,6 +832,24 @@ def get_operating_cost_per_unit(production_order=None, bom_no=None):
|
||||
|
||||
return operating_cost_per_unit
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_uom_details(item_code, uom, qty):
|
||||
"""Returns dict `{"conversion_factor": [value], "transfer_qty": qty * [value]}`
|
||||
|
||||
:param args: dict with `item_code`, `uom` and `qty`"""
|
||||
conversion_factor = get_conversion_factor(item_code, uom).get("conversion_factor")
|
||||
|
||||
if not conversion_factor:
|
||||
frappe.msgprint(_("UOM coversion factor required for UOM: {0} in Item: {1}")
|
||||
.format(uom, item_code))
|
||||
ret = {'uom' : ''}
|
||||
else:
|
||||
ret = {
|
||||
'conversion_factor' : flt(conversion_factor),
|
||||
'transfer_qty' : flt(qty) * flt(conversion_factor)
|
||||
}
|
||||
return ret
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_warehouse_details(args):
|
||||
if isinstance(args, basestring):
|
||||
|
Loading…
x
Reference in New Issue
Block a user