Merge branch 'version-13-hotfix' into item-variant-config-backend-cleanup
This commit is contained in:
@@ -354,7 +354,6 @@ class POSInvoice(SalesInvoice):
|
|||||||
if not for_validate and not self.customer:
|
if not for_validate and not self.customer:
|
||||||
self.customer = profile.customer
|
self.customer = profile.customer
|
||||||
|
|
||||||
self.ignore_pricing_rule = profile.ignore_pricing_rule
|
|
||||||
self.account_for_change_amount = profile.get('account_for_change_amount') or self.account_for_change_amount
|
self.account_for_change_amount = profile.get('account_for_change_amount') or self.account_for_change_amount
|
||||||
self.set_warehouse = profile.get('warehouse') or self.set_warehouse
|
self.set_warehouse = profile.get('warehouse') or self.set_warehouse
|
||||||
|
|
||||||
|
|||||||
@@ -556,6 +556,37 @@ class TestPOSInvoice(unittest.TestCase):
|
|||||||
batch.cancel()
|
batch.cancel()
|
||||||
batch.delete()
|
batch.delete()
|
||||||
|
|
||||||
|
def test_ignore_pricing_rule(self):
|
||||||
|
from erpnext.accounts.doctype.pricing_rule.test_pricing_rule import make_pricing_rule
|
||||||
|
|
||||||
|
item_price = frappe.get_doc({
|
||||||
|
'doctype': 'Item Price',
|
||||||
|
'item_code': '_Test Item',
|
||||||
|
'price_list': '_Test Price List',
|
||||||
|
'price_list_rate': '450',
|
||||||
|
})
|
||||||
|
item_price.insert()
|
||||||
|
pr = make_pricing_rule(selling=1, priority=5, discount_percentage=10)
|
||||||
|
pr.save()
|
||||||
|
pos_inv = create_pos_invoice(qty=1, do_not_submit=1)
|
||||||
|
pos_inv.items[0].rate = 300
|
||||||
|
pos_inv.save()
|
||||||
|
self.assertEquals(pos_inv.items[0].discount_percentage, 10)
|
||||||
|
# rate shouldn't change
|
||||||
|
self.assertEquals(pos_inv.items[0].rate, 405)
|
||||||
|
|
||||||
|
pos_inv.ignore_pricing_rule = 1
|
||||||
|
pos_inv.items[0].rate = 300
|
||||||
|
pos_inv.save()
|
||||||
|
self.assertEquals(pos_inv.ignore_pricing_rule, 1)
|
||||||
|
# rate should change since pricing rules are ignored
|
||||||
|
self.assertEquals(pos_inv.items[0].rate, 300)
|
||||||
|
|
||||||
|
item_price.delete()
|
||||||
|
pos_inv.delete()
|
||||||
|
pr.delete()
|
||||||
|
|
||||||
|
|
||||||
def create_pos_invoice(**args):
|
def create_pos_invoice(**args):
|
||||||
args = frappe._dict(args)
|
args = frappe._dict(args)
|
||||||
pos_profile = None
|
pos_profile = None
|
||||||
|
|||||||
@@ -652,7 +652,7 @@ def make_pricing_rule(**args):
|
|||||||
"rate": args.rate or 0.0,
|
"rate": args.rate or 0.0,
|
||||||
"margin_rate_or_amount": args.margin_rate_or_amount or 0.0,
|
"margin_rate_or_amount": args.margin_rate_or_amount or 0.0,
|
||||||
"condition": args.condition or '',
|
"condition": args.condition or '',
|
||||||
"priority": 1,
|
"priority": args.priority or 1,
|
||||||
"discount_amount": args.discount_amount or 0.0,
|
"discount_amount": args.discount_amount or 0.0,
|
||||||
"apply_multiple_pricing_rules": args.apply_multiple_pricing_rules or 0
|
"apply_multiple_pricing_rules": args.apply_multiple_pricing_rules or 0
|
||||||
})
|
})
|
||||||
@@ -678,6 +678,8 @@ def make_pricing_rule(**args):
|
|||||||
if args.get(applicable_for):
|
if args.get(applicable_for):
|
||||||
doc.db_set(applicable_for, args.get(applicable_for))
|
doc.db_set(applicable_for, args.get(applicable_for))
|
||||||
|
|
||||||
|
return doc
|
||||||
|
|
||||||
def setup_pricing_rule_data():
|
def setup_pricing_rule_data():
|
||||||
if not frappe.db.exists('Campaign', '_Test Campaign'):
|
if not frappe.db.exists('Campaign', '_Test Campaign'):
|
||||||
frappe.get_doc({
|
frappe.get_doc({
|
||||||
|
|||||||
@@ -651,7 +651,7 @@
|
|||||||
"hide_seconds": 1,
|
"hide_seconds": 1,
|
||||||
"label": "Ignore Pricing Rule",
|
"label": "Ignore Pricing Rule",
|
||||||
"no_copy": 1,
|
"no_copy": 1,
|
||||||
"permlevel": 1,
|
"permlevel": 0,
|
||||||
"print_hide": 1
|
"print_hide": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -2038,7 +2038,7 @@
|
|||||||
"link_fieldname": "consolidated_invoice"
|
"link_fieldname": "consolidated_invoice"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"modified": "2021-10-21 20:19:38.667508",
|
"modified": "2021-12-23 20:19:38.667508",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Sales Invoice",
|
"name": "Sales Invoice",
|
||||||
|
|||||||
@@ -167,7 +167,7 @@ frappe.query_reports["General Ledger"] = {
|
|||||||
"fieldname": "include_dimensions",
|
"fieldname": "include_dimensions",
|
||||||
"label": __("Consider Accounting Dimensions"),
|
"label": __("Consider Accounting Dimensions"),
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"default": 0
|
"default": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "show_opening_entries",
|
"fieldname": "show_opening_entries",
|
||||||
|
|||||||
@@ -449,9 +449,11 @@ def get_accountwise_gle(filters, accounting_dimensions, gl_entries, gle_map):
|
|||||||
|
|
||||||
elif group_by_voucher_consolidated:
|
elif group_by_voucher_consolidated:
|
||||||
keylist = [gle.get("voucher_type"), gle.get("voucher_no"), gle.get("account")]
|
keylist = [gle.get("voucher_type"), gle.get("voucher_no"), gle.get("account")]
|
||||||
for dim in accounting_dimensions:
|
if filters.get("include_dimensions"):
|
||||||
keylist.append(gle.get(dim))
|
for dim in accounting_dimensions:
|
||||||
keylist.append(gle.get("cost_center"))
|
keylist.append(gle.get(dim))
|
||||||
|
keylist.append(gle.get("cost_center"))
|
||||||
|
|
||||||
key = tuple(keylist)
|
key = tuple(keylist)
|
||||||
if key not in consolidated_gle:
|
if key not in consolidated_gle:
|
||||||
consolidated_gle.setdefault(key, gle)
|
consolidated_gle.setdefault(key, gle)
|
||||||
@@ -595,14 +597,14 @@ def get_columns(filters):
|
|||||||
"fieldname": dim.fieldname,
|
"fieldname": dim.fieldname,
|
||||||
"width": 100
|
"width": 100
|
||||||
})
|
})
|
||||||
|
columns.append({
|
||||||
columns.extend([
|
|
||||||
{
|
|
||||||
"label": _("Cost Center"),
|
"label": _("Cost Center"),
|
||||||
"options": "Cost Center",
|
"options": "Cost Center",
|
||||||
"fieldname": "cost_center",
|
"fieldname": "cost_center",
|
||||||
"width": 100
|
"width": 100
|
||||||
},
|
})
|
||||||
|
|
||||||
|
columns.extend([
|
||||||
{
|
{
|
||||||
"label": _("Against Voucher Type"),
|
"label": _("Against Voucher Type"),
|
||||||
"fieldname": "against_voucher_type",
|
"fieldname": "against_voucher_type",
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import unittest
|
import unittest
|
||||||
from functools import partial
|
from functools import partial
|
||||||
|
|
||||||
|
import frappe
|
||||||
|
|
||||||
from erpnext.controllers import queries
|
from erpnext.controllers import queries
|
||||||
|
|
||||||
|
|
||||||
@@ -85,3 +87,6 @@ class TestQueries(unittest.TestCase):
|
|||||||
|
|
||||||
wh = query(filters=[["Bin", "item_code", "=", "_Test Item"]])
|
wh = query(filters=[["Bin", "item_code", "=", "_Test Item"]])
|
||||||
self.assertGreaterEqual(len(wh), 1)
|
self.assertGreaterEqual(len(wh), 1)
|
||||||
|
|
||||||
|
def test_default_uoms(self):
|
||||||
|
self.assertGreaterEqual(frappe.db.count("UOM", {"enabled": 1}), 10)
|
||||||
|
|||||||
@@ -197,7 +197,10 @@ class ProductQuery:
|
|||||||
website_item_groups = frappe.db.get_all(
|
website_item_groups = frappe.db.get_all(
|
||||||
"Website Item",
|
"Website Item",
|
||||||
fields=self.fields + ["`tabWebsite Item Group`.parent as wig_parent"],
|
fields=self.fields + ["`tabWebsite Item Group`.parent as wig_parent"],
|
||||||
filters=[["Website Item Group", "item_group", "=", item_group]]
|
filters=[
|
||||||
|
["Website Item Group", "item_group", "=", item_group],
|
||||||
|
["published", "=", 1]
|
||||||
|
]
|
||||||
)
|
)
|
||||||
return website_item_groups
|
return website_item_groups
|
||||||
|
|
||||||
|
|||||||
@@ -531,16 +531,6 @@ class BOM(WebsiteGenerator):
|
|||||||
row.hour_rate = (hour_rate / flt(self.conversion_rate)
|
row.hour_rate = (hour_rate / flt(self.conversion_rate)
|
||||||
if self.conversion_rate and hour_rate else hour_rate)
|
if self.conversion_rate and hour_rate else hour_rate)
|
||||||
|
|
||||||
if self.routing:
|
|
||||||
time_in_mins = flt(frappe.db.get_value("BOM Operation", {
|
|
||||||
"workstation": row.workstation,
|
|
||||||
"operation": row.operation,
|
|
||||||
"parent": self.routing
|
|
||||||
}, ["time_in_mins"]))
|
|
||||||
|
|
||||||
if time_in_mins:
|
|
||||||
row.time_in_mins = time_in_mins
|
|
||||||
|
|
||||||
if row.hour_rate and row.time_in_mins:
|
if row.hour_rate and row.time_in_mins:
|
||||||
row.base_hour_rate = flt(row.hour_rate) * flt(self.conversion_rate)
|
row.base_hour_rate = flt(row.hour_rate) * flt(self.conversion_rate)
|
||||||
row.operating_cost = flt(row.hour_rate) * flt(row.time_in_mins) / 60.0
|
row.operating_cost = flt(row.hour_rate) * flt(row.time_in_mins) / 60.0
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ class TestRouting(ERPNextTestCase):
|
|||||||
wo_doc.delete()
|
wo_doc.delete()
|
||||||
|
|
||||||
def test_update_bom_operation_time(self):
|
def test_update_bom_operation_time(self):
|
||||||
|
"""Update cost shouldn't update routing times."""
|
||||||
operations = [
|
operations = [
|
||||||
{
|
{
|
||||||
"operation": "Test Operation A",
|
"operation": "Test Operation A",
|
||||||
@@ -85,8 +86,8 @@ class TestRouting(ERPNextTestCase):
|
|||||||
routing_doc.save()
|
routing_doc.save()
|
||||||
bom_doc.update_cost()
|
bom_doc.update_cost()
|
||||||
bom_doc.reload()
|
bom_doc.reload()
|
||||||
self.assertEqual(bom_doc.operations[0].time_in_mins, 90)
|
self.assertEqual(bom_doc.operations[0].time_in_mins, 30)
|
||||||
self.assertEqual(bom_doc.operations[1].time_in_mins, 42.2)
|
self.assertEqual(bom_doc.operations[1].time_in_mins, 20)
|
||||||
|
|
||||||
|
|
||||||
def setup_operations(rows):
|
def setup_operations(rows):
|
||||||
|
|||||||
@@ -305,6 +305,7 @@ erpnext.patches.v13_0.shopify_deprecation_warning
|
|||||||
erpnext.patches.v13_0.add_custom_field_for_south_africa #2
|
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.rename_discharge_ordered_date_in_ip_record
|
||||||
erpnext.patches.v13_0.remove_bad_selling_defaults
|
erpnext.patches.v13_0.remove_bad_selling_defaults
|
||||||
|
erpnext.patches.v13_0.trim_whitespace_from_serial_nos
|
||||||
erpnext.patches.v13_0.migrate_stripe_api
|
erpnext.patches.v13_0.migrate_stripe_api
|
||||||
erpnext.patches.v13_0.reset_clearance_date_for_intracompany_payment_entries
|
erpnext.patches.v13_0.reset_clearance_date_for_intracompany_payment_entries
|
||||||
execute:frappe.reload_doc("erpnext_integrations", "doctype", "TaxJar Settings")
|
execute:frappe.reload_doc("erpnext_integrations", "doctype", "TaxJar Settings")
|
||||||
@@ -330,6 +331,7 @@ erpnext.patches.v13_0.enable_scheduler_job_for_item_reposting
|
|||||||
erpnext.patches.v13_0.requeue_failed_reposts
|
erpnext.patches.v13_0.requeue_failed_reposts
|
||||||
erpnext.patches.v13_0.fetch_thumbnail_in_website_items
|
erpnext.patches.v13_0.fetch_thumbnail_in_website_items
|
||||||
erpnext.patches.v13_0.update_job_card_status
|
erpnext.patches.v13_0.update_job_card_status
|
||||||
|
erpnext.patches.v13_0.enable_uoms
|
||||||
erpnext.patches.v12_0.update_production_plan_status
|
erpnext.patches.v12_0.update_production_plan_status
|
||||||
erpnext.patches.v13_0.item_naming_series_not_mandatory
|
erpnext.patches.v13_0.item_naming_series_not_mandatory
|
||||||
erpnext.patches.v13_0.update_category_in_ltds_certificate
|
erpnext.patches.v13_0.update_category_in_ltds_certificate
|
||||||
|
|||||||
13
erpnext/patches/v13_0/enable_uoms.py
Normal file
13
erpnext/patches/v13_0/enable_uoms.py
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import frappe
|
||||||
|
|
||||||
|
|
||||||
|
def execute():
|
||||||
|
frappe.reload_doc('setup', 'doctype', 'uom')
|
||||||
|
|
||||||
|
uom = frappe.qb.DocType("UOM")
|
||||||
|
|
||||||
|
(frappe.qb
|
||||||
|
.update(uom)
|
||||||
|
.set(uom.enabled, 1)
|
||||||
|
.where(uom.creation >= "2021-10-18") # date when this field was released
|
||||||
|
).run()
|
||||||
65
erpnext/patches/v13_0/trim_whitespace_from_serial_nos.py
Normal file
65
erpnext/patches/v13_0/trim_whitespace_from_serial_nos.py
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
import frappe
|
||||||
|
|
||||||
|
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
|
||||||
|
|
||||||
|
|
||||||
|
def execute():
|
||||||
|
broken_sles = frappe.db.sql("""
|
||||||
|
select name, serial_no
|
||||||
|
from `tabStock Ledger Entry`
|
||||||
|
where
|
||||||
|
is_cancelled = 0
|
||||||
|
and (serial_no like %s or serial_no like %s or serial_no like %s or serial_no like %s)
|
||||||
|
""",
|
||||||
|
(
|
||||||
|
" %", # leading whitespace
|
||||||
|
"% ", # trailing whitespace
|
||||||
|
"%\n %", # leading whitespace on newline
|
||||||
|
"% \n%", # trailing whitespace on newline
|
||||||
|
),
|
||||||
|
as_dict=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
frappe.db.MAX_WRITES_PER_TRANSACTION += len(broken_sles)
|
||||||
|
|
||||||
|
if not broken_sles:
|
||||||
|
return
|
||||||
|
|
||||||
|
broken_serial_nos = set()
|
||||||
|
|
||||||
|
# patch SLEs
|
||||||
|
for sle in broken_sles:
|
||||||
|
serial_no_list = get_serial_nos(sle.serial_no)
|
||||||
|
correct_sr_no = "\n".join(serial_no_list)
|
||||||
|
|
||||||
|
if correct_sr_no == sle.serial_no:
|
||||||
|
continue
|
||||||
|
|
||||||
|
frappe.db.set_value("Stock Ledger Entry", sle.name, "serial_no", correct_sr_no, update_modified=False)
|
||||||
|
broken_serial_nos.update(serial_no_list)
|
||||||
|
|
||||||
|
if not broken_serial_nos:
|
||||||
|
return
|
||||||
|
|
||||||
|
# Patch serial No documents if they don't have purchase info
|
||||||
|
# Purchase info is used for fetching incoming rate
|
||||||
|
broken_sr_no_records = frappe.get_list("Serial No",
|
||||||
|
filters={
|
||||||
|
"status":"Active",
|
||||||
|
"name": ("in", broken_serial_nos),
|
||||||
|
"purchase_document_type": ("is", "not set")
|
||||||
|
},
|
||||||
|
pluck="name",
|
||||||
|
)
|
||||||
|
|
||||||
|
frappe.db.MAX_WRITES_PER_TRANSACTION += len(broken_sr_no_records)
|
||||||
|
|
||||||
|
patch_savepoint = "serial_no_patch"
|
||||||
|
for serial_no in broken_sr_no_records:
|
||||||
|
try:
|
||||||
|
frappe.db.savepoint(patch_savepoint)
|
||||||
|
sn = frappe.get_doc("Serial No", serial_no)
|
||||||
|
sn.update_serial_no_reference()
|
||||||
|
sn.db_update()
|
||||||
|
except Exception:
|
||||||
|
frappe.db.rollback(save_point=patch_savepoint)
|
||||||
@@ -350,7 +350,8 @@ def add_uom_data():
|
|||||||
"doctype": "UOM",
|
"doctype": "UOM",
|
||||||
"uom_name": _(d.get("uom_name")),
|
"uom_name": _(d.get("uom_name")),
|
||||||
"name": _(d.get("uom_name")),
|
"name": _(d.get("uom_name")),
|
||||||
"must_be_whole_number": d.get("must_be_whole_number")
|
"must_be_whole_number": d.get("must_be_whole_number"),
|
||||||
|
"enabled": 1,
|
||||||
}).db_insert()
|
}).db_insert()
|
||||||
|
|
||||||
# bootstrap uom conversion factors
|
# bootstrap uom conversion factors
|
||||||
|
|||||||
Reference in New Issue
Block a user