mirror of
https://github.com/frappe/erpnext.git
synced 2026-06-02 19:59:12 +00:00
Merge branch 'version-13-hotfix' into psa_pdf_issue_v13
This commit is contained in:
@@ -712,6 +712,140 @@ class TestPricingRule(unittest.TestCase):
|
|||||||
|
|
||||||
item.delete()
|
item.delete()
|
||||||
|
|
||||||
|
def test_item_group_price_with_blank_uom_pricing_rule(self):
|
||||||
|
group = frappe.get_doc(
|
||||||
|
doctype="Item Group",
|
||||||
|
item_group_name="_Test Pricing Rule Item Group",
|
||||||
|
parent_item_group="All Item Groups",
|
||||||
|
)
|
||||||
|
group.save()
|
||||||
|
properties = {
|
||||||
|
"item_code": "Item with Group Blank UOM",
|
||||||
|
"item_group": "_Test Pricing Rule Item Group",
|
||||||
|
"stock_uom": "Nos",
|
||||||
|
"sales_uom": "Box",
|
||||||
|
"uoms": [dict(uom="Box", conversion_factor=10)],
|
||||||
|
}
|
||||||
|
item = make_item(properties=properties)
|
||||||
|
|
||||||
|
make_item_price("Item with Group Blank UOM", "_Test Price List", 100)
|
||||||
|
|
||||||
|
pricing_rule_record = {
|
||||||
|
"doctype": "Pricing Rule",
|
||||||
|
"title": "_Test Item with Group Blank UOM Rule",
|
||||||
|
"apply_on": "Item Group",
|
||||||
|
"item_groups": [
|
||||||
|
{
|
||||||
|
"item_group": "_Test Pricing Rule Item Group",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"selling": 1,
|
||||||
|
"currency": "INR",
|
||||||
|
"rate_or_discount": "Rate",
|
||||||
|
"rate": 101,
|
||||||
|
"company": "_Test Company",
|
||||||
|
}
|
||||||
|
rule = frappe.get_doc(pricing_rule_record)
|
||||||
|
rule.insert()
|
||||||
|
|
||||||
|
si = create_sales_invoice(
|
||||||
|
do_not_save=True, item_code="Item with Group Blank UOM", uom="Box", conversion_factor=10
|
||||||
|
)
|
||||||
|
si.selling_price_list = "_Test Price List"
|
||||||
|
si.save()
|
||||||
|
|
||||||
|
# If UOM is blank consider it as stock UOM and apply pricing_rule on all UOM.
|
||||||
|
# rate is 101, Selling UOM is Box that have conversion_factor of 10 so 101 * 10 = 1010
|
||||||
|
self.assertEqual(si.items[0].price_list_rate, 1010)
|
||||||
|
self.assertEqual(si.items[0].rate, 1010)
|
||||||
|
|
||||||
|
si.delete()
|
||||||
|
|
||||||
|
si = create_sales_invoice(do_not_save=True, item_code="Item with Group Blank UOM", uom="Nos")
|
||||||
|
si.selling_price_list = "_Test Price List"
|
||||||
|
si.save()
|
||||||
|
|
||||||
|
# UOM is blank so consider it as stock UOM and apply pricing_rule on all UOM.
|
||||||
|
# rate is 101, Selling UOM is Nos that have conversion_factor of 1 so 101 * 1 = 101
|
||||||
|
self.assertEqual(si.items[0].price_list_rate, 101)
|
||||||
|
self.assertEqual(si.items[0].rate, 101)
|
||||||
|
|
||||||
|
si.delete()
|
||||||
|
rule.delete()
|
||||||
|
frappe.get_doc("Item Price", {"item_code": "Item with Group Blank UOM"}).delete()
|
||||||
|
item.delete()
|
||||||
|
group.delete()
|
||||||
|
|
||||||
|
def test_item_group_price_with_selling_uom_pricing_rule(self):
|
||||||
|
group = frappe.get_doc(
|
||||||
|
doctype="Item Group",
|
||||||
|
item_group_name="_Test Pricing Rule Item Group UOM",
|
||||||
|
parent_item_group="All Item Groups",
|
||||||
|
)
|
||||||
|
group.save()
|
||||||
|
properties = {
|
||||||
|
"item_code": "Item with Group UOM other than Stock",
|
||||||
|
"item_group": "_Test Pricing Rule Item Group UOM",
|
||||||
|
"stock_uom": "Nos",
|
||||||
|
"sales_uom": "Box",
|
||||||
|
"uoms": [dict(uom="Box", conversion_factor=10)],
|
||||||
|
}
|
||||||
|
item = make_item(properties=properties)
|
||||||
|
|
||||||
|
make_item_price("Item with Group UOM other than Stock", "_Test Price List", 100)
|
||||||
|
|
||||||
|
pricing_rule_record = {
|
||||||
|
"doctype": "Pricing Rule",
|
||||||
|
"title": "_Test Item with Group UOM other than Stock Rule",
|
||||||
|
"apply_on": "Item Group",
|
||||||
|
"item_groups": [
|
||||||
|
{
|
||||||
|
"item_group": "_Test Pricing Rule Item Group UOM",
|
||||||
|
"uom": "Box",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"selling": 1,
|
||||||
|
"currency": "INR",
|
||||||
|
"rate_or_discount": "Rate",
|
||||||
|
"rate": 101,
|
||||||
|
"company": "_Test Company",
|
||||||
|
}
|
||||||
|
rule = frappe.get_doc(pricing_rule_record)
|
||||||
|
rule.insert()
|
||||||
|
|
||||||
|
si = create_sales_invoice(
|
||||||
|
do_not_save=True,
|
||||||
|
item_code="Item with Group UOM other than Stock",
|
||||||
|
uom="Box",
|
||||||
|
conversion_factor=10,
|
||||||
|
)
|
||||||
|
si.selling_price_list = "_Test Price List"
|
||||||
|
si.save()
|
||||||
|
|
||||||
|
# UOM is Box so apply pricing_rule only on Box UOM.
|
||||||
|
# Selling UOM is Box and as both UOM are same no need to multiply by conversion_factor.
|
||||||
|
self.assertEqual(si.items[0].price_list_rate, 101)
|
||||||
|
self.assertEqual(si.items[0].rate, 101)
|
||||||
|
|
||||||
|
si.delete()
|
||||||
|
|
||||||
|
si = create_sales_invoice(
|
||||||
|
do_not_save=True, item_code="Item with Group UOM other than Stock", uom="Nos"
|
||||||
|
)
|
||||||
|
si.selling_price_list = "_Test Price List"
|
||||||
|
si.save()
|
||||||
|
|
||||||
|
# UOM is Box so pricing_rule won't apply as selling_uom is Nos.
|
||||||
|
# As Pricing Rule is not applied price of 100 will be fetched from Item Price List.
|
||||||
|
self.assertEqual(si.items[0].price_list_rate, 100)
|
||||||
|
self.assertEqual(si.items[0].rate, 100)
|
||||||
|
|
||||||
|
si.delete()
|
||||||
|
rule.delete()
|
||||||
|
frappe.get_doc("Item Price", {"item_code": "Item with Group UOM other than Stock"}).delete()
|
||||||
|
item.delete()
|
||||||
|
group.delete()
|
||||||
|
|
||||||
def test_pricing_rule_for_different_currency(self):
|
def test_pricing_rule_for_different_currency(self):
|
||||||
make_item("Test Sanitizer Item")
|
make_item("Test Sanitizer Item")
|
||||||
|
|
||||||
|
|||||||
@@ -127,7 +127,12 @@ def _get_pricing_rules(apply_on, args, values):
|
|||||||
values["variant_of"] = args.variant_of
|
values["variant_of"] = args.variant_of
|
||||||
elif apply_on_field == "item_group":
|
elif apply_on_field == "item_group":
|
||||||
item_conditions = _get_tree_conditions(args, "Item Group", child_doc, False)
|
item_conditions = _get_tree_conditions(args, "Item Group", child_doc, False)
|
||||||
|
if args.get("uom", None):
|
||||||
|
item_conditions += (
|
||||||
|
" and ({child_doc}.uom='{item_uom}' or IFNULL({child_doc}.uom, '')='')".format(
|
||||||
|
child_doc=child_doc, item_uom=args.get("uom")
|
||||||
|
)
|
||||||
|
)
|
||||||
conditions += get_other_conditions(conditions, values, args)
|
conditions += get_other_conditions(conditions, values, args)
|
||||||
warehouse_conditions = _get_tree_conditions(args, "Warehouse", "`tabPricing Rule`")
|
warehouse_conditions = _get_tree_conditions(args, "Warehouse", "`tabPricing Rule`")
|
||||||
if warehouse_conditions:
|
if warehouse_conditions:
|
||||||
|
|||||||
@@ -50,6 +50,10 @@
|
|||||||
<div class="col-xs-4"><label>Document No</label></div>
|
<div class="col-xs-4"><label>Document No</label></div>
|
||||||
<div class="col-xs-8 value">{{ einvoice.DocDtls.No }}</div>
|
<div class="col-xs-8 value">{{ einvoice.DocDtls.No }}</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row data-field">
|
||||||
|
<div class="col-xs-4"><label>Document Date</label></div>
|
||||||
|
<div class="col-xs-8 value">{{ einvoice.DocDtls.Dt }}</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-xs-4 column-break">
|
<div class="col-xs-4 column-break">
|
||||||
<img src="{{ doc.qrcode_image }}" width="175px" style="float: right;">
|
<img src="{{ doc.qrcode_image }}" width="175px" style="float: right;">
|
||||||
|
|||||||
@@ -43,6 +43,11 @@ frappe.ui.form.on("Purchase Order", {
|
|||||||
erpnext.queries.setup_queries(frm, "Warehouse", function() {
|
erpnext.queries.setup_queries(frm, "Warehouse", function() {
|
||||||
return erpnext.queries.warehouse(frm.doc);
|
return erpnext.queries.warehouse(frm.doc);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// On cancel and amending a purchase order with advance payment, reset advance paid amount
|
||||||
|
if (frm.is_new()) {
|
||||||
|
frm.set_value("advance_paid", 0)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
apply_tds: function(frm) {
|
apply_tds: function(frm) {
|
||||||
|
|||||||
@@ -577,8 +577,8 @@ def regenerate_repayment_schedule(loan, cancel=0):
|
|||||||
loan_doc = frappe.get_doc("Loan", loan)
|
loan_doc = frappe.get_doc("Loan", loan)
|
||||||
next_accrual_date = None
|
next_accrual_date = None
|
||||||
accrued_entries = 0
|
accrued_entries = 0
|
||||||
last_repayment_amount = 0
|
last_repayment_amount = None
|
||||||
last_balance_amount = 0
|
last_balance_amount = None
|
||||||
|
|
||||||
for term in reversed(loan_doc.get("repayment_schedule")):
|
for term in reversed(loan_doc.get("repayment_schedule")):
|
||||||
if not term.is_accrued:
|
if not term.is_accrued:
|
||||||
@@ -586,9 +586,9 @@ def regenerate_repayment_schedule(loan, cancel=0):
|
|||||||
loan_doc.remove(term)
|
loan_doc.remove(term)
|
||||||
else:
|
else:
|
||||||
accrued_entries += 1
|
accrued_entries += 1
|
||||||
if not last_repayment_amount:
|
if last_repayment_amount is None:
|
||||||
last_repayment_amount = term.total_payment
|
last_repayment_amount = term.total_payment
|
||||||
if not last_balance_amount:
|
if last_balance_amount is None:
|
||||||
last_balance_amount = term.balance_loan_amount
|
last_balance_amount = term.balance_loan_amount
|
||||||
|
|
||||||
loan_doc.save()
|
loan_doc.save()
|
||||||
|
|||||||
@@ -54,6 +54,9 @@ class JobCard(Document):
|
|||||||
self.set_onload("job_card_excess_transfer", excess_transfer)
|
self.set_onload("job_card_excess_transfer", excess_transfer)
|
||||||
self.set_onload("work_order_stopped", self.is_work_order_stopped())
|
self.set_onload("work_order_stopped", self.is_work_order_stopped())
|
||||||
|
|
||||||
|
def before_validate(self):
|
||||||
|
self.set_wip_warehouse()
|
||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
self.validate_time_logs()
|
self.validate_time_logs()
|
||||||
self.set_status()
|
self.set_status()
|
||||||
@@ -639,6 +642,12 @@ class JobCard(Document):
|
|||||||
if update_status:
|
if update_status:
|
||||||
self.db_set("status", self.status)
|
self.db_set("status", self.status)
|
||||||
|
|
||||||
|
def set_wip_warehouse(self):
|
||||||
|
if not self.wip_warehouse:
|
||||||
|
self.wip_warehouse = frappe.db.get_single_value(
|
||||||
|
"Manufacturing Settings", "default_wip_warehouse"
|
||||||
|
)
|
||||||
|
|
||||||
def validate_operation_id(self):
|
def validate_operation_id(self):
|
||||||
if (
|
if (
|
||||||
self.get("operation_id")
|
self.get("operation_id")
|
||||||
|
|||||||
@@ -145,7 +145,7 @@ class WorkOrder(Document):
|
|||||||
frappe.throw(_("Sales Order {0} is {1}").format(self.sales_order, status))
|
frappe.throw(_("Sales Order {0} is {1}").format(self.sales_order, status))
|
||||||
|
|
||||||
def set_default_warehouse(self):
|
def set_default_warehouse(self):
|
||||||
if not self.wip_warehouse:
|
if not self.wip_warehouse and not self.skip_transfer:
|
||||||
self.wip_warehouse = frappe.db.get_single_value(
|
self.wip_warehouse = frappe.db.get_single_value(
|
||||||
"Manufacturing Settings", "default_wip_warehouse"
|
"Manufacturing Settings", "default_wip_warehouse"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -95,6 +95,11 @@ frappe.ui.form.on("Sales Order", {
|
|||||||
return query;
|
return query;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// On cancel and amending a sales order with advance payment, reset advance paid amount
|
||||||
|
if (frm.is_new()) {
|
||||||
|
frm.set_value("advance_paid", 0)
|
||||||
|
}
|
||||||
|
|
||||||
frm.ignore_doctypes_on_cancel_all = ['Purchase Order'];
|
frm.ignore_doctypes_on_cancel_all = ['Purchase Order'];
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -315,6 +315,9 @@ def get_basic_details(args, item, overwrite_warehouse=True):
|
|||||||
else:
|
else:
|
||||||
args.uom = item.stock_uom
|
args.uom = item.stock_uom
|
||||||
|
|
||||||
|
# Set stock UOM in args, so that it can be used while fetching item price
|
||||||
|
args.stock_uom = item.stock_uom
|
||||||
|
|
||||||
if args.get("batch_no") and item.name != frappe.get_cached_value(
|
if args.get("batch_no") and item.name != frappe.get_cached_value(
|
||||||
"Batch", args.get("batch_no"), "item"
|
"Batch", args.get("batch_no"), "item"
|
||||||
):
|
):
|
||||||
|
|||||||
Reference in New Issue
Block a user