mirror of
https://github.com/frappe/erpnext.git
synced 2026-05-16 19:49:18 +00:00
Merge branch 'version-12-hotfix' of https://github.com/frappe/erpnext into unpaid_subscription_fix
This commit is contained in:
@@ -246,22 +246,26 @@ class StatusUpdater(Document):
|
|||||||
if not args.get("second_source_extra_cond"):
|
if not args.get("second_source_extra_cond"):
|
||||||
args["second_source_extra_cond"] = ""
|
args["second_source_extra_cond"] = ""
|
||||||
|
|
||||||
args['second_source_condition'] = """ + ifnull((select sum(%(second_source_field)s)
|
args['second_source_condition'] = frappe.db.sql(""" select ifnull((select sum(%(second_source_field)s)
|
||||||
from `tab%(second_source_dt)s`
|
from `tab%(second_source_dt)s`
|
||||||
where `%(second_join_field)s`="%(detail_id)s"
|
where `%(second_join_field)s`="%(detail_id)s"
|
||||||
and (`tab%(second_source_dt)s`.docstatus=1) %(second_source_extra_cond)s FOR UPDATE), 0) """ % args
|
and (`tab%(second_source_dt)s`.docstatus=1)
|
||||||
|
%(second_source_extra_cond)s), 0) """ % args)[0][0]
|
||||||
|
|
||||||
if args['detail_id']:
|
if args['detail_id']:
|
||||||
if not args.get("extra_cond"): args["extra_cond"] = ""
|
if not args.get("extra_cond"): args["extra_cond"] = ""
|
||||||
|
|
||||||
frappe.db.sql("""update `tab%(target_dt)s`
|
args["source_dt_value"] = frappe.db.sql("""
|
||||||
set %(target_field)s = (
|
|
||||||
(select ifnull(sum(%(source_field)s), 0)
|
(select ifnull(sum(%(source_field)s), 0)
|
||||||
from `tab%(source_dt)s` where `%(join_field)s`="%(detail_id)s"
|
from `tab%(source_dt)s` where `%(join_field)s`="%(detail_id)s"
|
||||||
and (docstatus=1 %(cond)s) %(extra_cond)s)
|
and (docstatus=1 %(cond)s) %(extra_cond)s)
|
||||||
%(second_source_condition)s
|
""" % args)[0][0] or 0.0
|
||||||
)
|
|
||||||
%(update_modified)s
|
if args['second_source_condition']:
|
||||||
|
args["source_dt_value"] += flt(args['second_source_condition'])
|
||||||
|
|
||||||
|
frappe.db.sql("""update `tab%(target_dt)s`
|
||||||
|
set %(target_field)s = %(source_dt_value)s %(update_modified)s
|
||||||
where name='%(detail_id)s'""" % args)
|
where name='%(detail_id)s'""" % args)
|
||||||
|
|
||||||
def _update_percent_field_in_targets(self, args, update_modified=True):
|
def _update_percent_field_in_targets(self, args, update_modified=True):
|
||||||
|
|||||||
@@ -227,9 +227,9 @@ class StockController(AccountsController):
|
|||||||
|
|
||||||
def check_expense_account(self, item):
|
def check_expense_account(self, item):
|
||||||
if not item.get("expense_account"):
|
if not item.get("expense_account"):
|
||||||
frappe.throw(_("Row #{0}: Expense Account not set for Item {1}. Please set an Expense \
|
msg = _("Please set an Expense Account in the Items table")
|
||||||
Account in the Items table").format(item.idx, frappe.bold(item.item_code)),
|
frappe.throw(_("Row #{0}: Expense Account not set for the Item {1}. {2}")
|
||||||
title=_("Expense Account Missing"))
|
.format(item.idx, frappe.bold(item.item_code), msg), title=_("Expense Account Missing"))
|
||||||
|
|
||||||
else:
|
else:
|
||||||
is_expense_account = frappe.db.get_value("Account",
|
is_expense_account = frappe.db.get_value("Account",
|
||||||
@@ -242,11 +242,12 @@ class StockController(AccountsController):
|
|||||||
_(self.doctype), self.name, item.get("item_code")))
|
_(self.doctype), self.name, item.get("item_code")))
|
||||||
|
|
||||||
def delete_auto_created_batches(self):
|
def delete_auto_created_batches(self):
|
||||||
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
|
|
||||||
for d in self.items:
|
for d in self.items:
|
||||||
if not d.batch_no: continue
|
if not d.batch_no: continue
|
||||||
|
|
||||||
serial_nos = get_serial_nos(d.serial_no)
|
serial_nos = [sr.name for sr in frappe.get_all("Serial No",
|
||||||
|
{'batch_no': d.batch_no, 'status': 'Inactive'})]
|
||||||
|
|
||||||
if serial_nos:
|
if serial_nos:
|
||||||
frappe.db.set_value("Serial No", { 'name': ['in', serial_nos] }, "batch_no", None)
|
frappe.db.set_value("Serial No", { 'name': ['in', serial_nos] }, "batch_no", None)
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ def get_approvers(doctype, txt, searchfield, start, page_len, filters):
|
|||||||
approvers = []
|
approvers = []
|
||||||
department_details = {}
|
department_details = {}
|
||||||
department_list = []
|
department_list = []
|
||||||
employee = frappe.get_value("Employee", filters.get("employee"), ["department", "leave_approver"], as_dict=True)
|
employee = frappe.get_value("Employee", filters.get("employee"), ["employee_name","department", "leave_approver"], as_dict=True)
|
||||||
|
|
||||||
employee_department = filters.get("department") or employee.department
|
employee_department = filters.get("department") or employee.department
|
||||||
if employee_department:
|
if employee_department:
|
||||||
@@ -36,8 +36,10 @@ def get_approvers(doctype, txt, searchfield, start, page_len, filters):
|
|||||||
|
|
||||||
if filters.get("doctype") == "Leave Application":
|
if filters.get("doctype") == "Leave Application":
|
||||||
parentfield = "leave_approvers"
|
parentfield = "leave_approvers"
|
||||||
else:
|
field_name = "Leave Approver"
|
||||||
|
elif filters.get("doctype") == "Expense Claim":
|
||||||
parentfield = "expense_approvers"
|
parentfield = "expense_approvers"
|
||||||
|
field_name = "Expense Approver"
|
||||||
if department_list:
|
if department_list:
|
||||||
for d in department_list:
|
for d in department_list:
|
||||||
approvers += frappe.db.sql("""select user.name, user.first_name, user.last_name from
|
approvers += frappe.db.sql("""select user.name, user.first_name, user.last_name from
|
||||||
@@ -47,4 +49,10 @@ def get_approvers(doctype, txt, searchfield, start, page_len, filters):
|
|||||||
and approver.parentfield = %s
|
and approver.parentfield = %s
|
||||||
and approver.approver=user.name""",(d, "%" + txt + "%", parentfield), as_list=True)
|
and approver.approver=user.name""",(d, "%" + txt + "%", parentfield), as_list=True)
|
||||||
|
|
||||||
|
if len(approvers) == 0:
|
||||||
|
error_msg = _("Please set {0} for the Employee: {1}").format(field_name, frappe.bold(employee.employee_name))
|
||||||
|
if department_list:
|
||||||
|
error_msg += _(" or for Department: {0}").format(frappe.bold(employee_department))
|
||||||
|
frappe.throw(error_msg, title=_(field_name + " Missing"))
|
||||||
|
|
||||||
return set(tuple(approver) for approver in approvers)
|
return set(tuple(approver) for approver in approvers)
|
||||||
|
|||||||
@@ -224,17 +224,19 @@ def get_operation_details(work_order, operation):
|
|||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_operations(doctype, txt, searchfield, start, page_len, filters):
|
def get_operations(doctype, txt, searchfield, start, page_len, filters):
|
||||||
if filters.get("work_order"):
|
if not filters.get("work_order"):
|
||||||
args = {"parent": filters.get("work_order")}
|
frappe.msgprint(_("Please select a Work Order first."))
|
||||||
if txt:
|
return []
|
||||||
args["operation"] = ("like", "%{0}%".format(txt))
|
args = {"parent": filters.get("work_order")}
|
||||||
|
if txt:
|
||||||
|
args["operation"] = ("like", "%{0}%".format(txt))
|
||||||
|
|
||||||
return frappe.get_all("Work Order Operation",
|
return frappe.get_all("Work Order Operation",
|
||||||
filters = args,
|
filters = args,
|
||||||
fields = ["distinct operation as operation"],
|
fields = ["distinct operation as operation"],
|
||||||
limit_start = start,
|
limit_start = start,
|
||||||
limit_page_length = page_len,
|
limit_page_length = page_len,
|
||||||
order_by="idx asc", as_list=1)
|
order_by="idx asc", as_list=1)
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def make_material_request(source_name, target_doc=None):
|
def make_material_request(source_name, target_doc=None):
|
||||||
|
|||||||
@@ -319,6 +319,29 @@ class TestWorkOrder(unittest.TestCase):
|
|||||||
|
|
||||||
allow_overproduction("overproduction_percentage_for_work_order", 0)
|
allow_overproduction("overproduction_percentage_for_work_order", 0)
|
||||||
|
|
||||||
|
def test_finished_good_valuation_rate(self):
|
||||||
|
allow_overproduction("overproduction_percentage_for_work_order", 0)
|
||||||
|
wo_order = make_wo_order_test_record(planned_start_date=now(), qty=2)
|
||||||
|
test_stock_entry.make_stock_entry(item_code="_Test Item",
|
||||||
|
target="_Test Warehouse - _TC", qty=10, basic_rate=5000.0)
|
||||||
|
test_stock_entry.make_stock_entry(item_code="_Test Item Home Desktop 100",
|
||||||
|
target="_Test Warehouse - _TC", qty=10, basic_rate=1000.0)
|
||||||
|
|
||||||
|
ste_doc = frappe.get_doc(make_stock_entry(wo_order.name, "Material Transfer for Manufacture", 2))
|
||||||
|
ste_doc.submit()
|
||||||
|
|
||||||
|
ste_doc = frappe.get_doc(make_stock_entry(wo_order.name, "Manufacture", 2))
|
||||||
|
ste_doc.save()
|
||||||
|
|
||||||
|
self.assertEquals(ste_doc.total_incoming_value, ste_doc.total_outgoing_value)
|
||||||
|
|
||||||
|
for row in ste_doc.items:
|
||||||
|
if row.t_warehouse and not row.s_warehouse:
|
||||||
|
row.valuation_rate = 120
|
||||||
|
ste_doc.save()
|
||||||
|
|
||||||
|
self.assertEquals(ste_doc.total_incoming_value, ste_doc.total_outgoing_value)
|
||||||
|
|
||||||
def test_over_production_for_sales_order(self):
|
def test_over_production_for_sales_order(self):
|
||||||
so = make_sales_order(item_code="_Test FG Item", qty=2)
|
so = make_sales_order(item_code="_Test FG Item", qty=2)
|
||||||
|
|
||||||
|
|||||||
@@ -25,11 +25,11 @@ frappe.query_reports["BOM Stock Report"] = {
|
|||||||
],
|
],
|
||||||
"formatter": function(value, row, column, data, default_formatter) {
|
"formatter": function(value, row, column, data, default_formatter) {
|
||||||
value = default_formatter(value, row, column, data);
|
value = default_formatter(value, row, column, data);
|
||||||
if (column.id == "Item"){
|
if (column.id == "item") {
|
||||||
if (data["Enough Parts to Build"] > 0){
|
if (data["enough_parts_to_build"] > 0) {
|
||||||
value = `<a style='color:green' href="#Form/Item/${data['Item']}" data-doctype="Item">${data['Item']}</a>`
|
value = `<a style='color:green' href="#Form/Item/${data['item']}" data-doctype="Item">${data['item']}</a>`;
|
||||||
} else {
|
} else {
|
||||||
value = `<a style='color:red' href="#Form/Item/${data['Item']}" data-doctype="Item">${data['Item']}</a>`
|
value = `<a style='color:red' href="#Form/Item/${data['item']}" data-doctype="Item">${data['item']}</a>`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return value
|
return value
|
||||||
|
|||||||
@@ -539,7 +539,8 @@ def make_purchase_invoice(source_name, target_doc=None):
|
|||||||
"doctype": "Purchase Invoice",
|
"doctype": "Purchase Invoice",
|
||||||
"field_map": {
|
"field_map": {
|
||||||
"supplier_warehouse":"supplier_warehouse",
|
"supplier_warehouse":"supplier_warehouse",
|
||||||
"is_return": "is_return"
|
"is_return": "is_return",
|
||||||
|
"bill_date": "bill_date"
|
||||||
},
|
},
|
||||||
"validation": {
|
"validation": {
|
||||||
"docstatus": ["=", 1],
|
"docstatus": ["=", 1],
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ class StockEntry(StockController):
|
|||||||
self.set_incoming_rate()
|
self.set_incoming_rate()
|
||||||
self.validate_serialized_batch()
|
self.validate_serialized_batch()
|
||||||
self.set_actual_qty()
|
self.set_actual_qty()
|
||||||
self.calculate_rate_and_amount(update_finished_item_rate=False)
|
self.calculate_rate_and_amount()
|
||||||
|
|
||||||
def on_submit(self):
|
def on_submit(self):
|
||||||
|
|
||||||
|
|||||||
@@ -164,7 +164,7 @@ def get_stock_ledger_entries(filters, items):
|
|||||||
select
|
select
|
||||||
sle.item_code, warehouse, sle.posting_date, sle.actual_qty, sle.valuation_rate,
|
sle.item_code, warehouse, sle.posting_date, sle.actual_qty, sle.valuation_rate,
|
||||||
sle.company, sle.voucher_type, sle.qty_after_transaction, sle.stock_value_difference,
|
sle.company, sle.voucher_type, sle.qty_after_transaction, sle.stock_value_difference,
|
||||||
sle.item_code as name, sle.voucher_no
|
sle.item_code as name, sle.voucher_no, sle.stock_value
|
||||||
from
|
from
|
||||||
`tabStock Ledger Entry` sle force index (posting_sort_index)
|
`tabStock Ledger Entry` sle force index (posting_sort_index)
|
||||||
where sle.docstatus < 2 %s %s
|
where sle.docstatus < 2 %s %s
|
||||||
@@ -196,7 +196,7 @@ def get_item_warehouse_map(filters, sle):
|
|||||||
else:
|
else:
|
||||||
qty_diff = flt(d.actual_qty)
|
qty_diff = flt(d.actual_qty)
|
||||||
|
|
||||||
value_diff = flt(d.stock_value_difference)
|
value_diff = flt(d.stock_value) - flt(qty_dict.bal_val)
|
||||||
|
|
||||||
if d.posting_date < from_date:
|
if d.posting_date < from_date:
|
||||||
qty_dict.opening_qty += qty_diff
|
qty_dict.opening_qty += qty_diff
|
||||||
|
|||||||
Reference in New Issue
Block a user