Merge branch 'develop' of https://github.com/frappe/erpnext into project-link-for-all-accounts

This commit is contained in:
Deepesh Garg
2020-06-19 11:41:21 +05:30
176 changed files with 4541 additions and 2499 deletions

View File

@@ -1137,8 +1137,8 @@ def set_sales_order_defaults(parent_doctype, parent_doctype_name, child_docname,
child_item.item_name = item.item_name
child_item.description = item.description
child_item.delivery_date = trans_item.get('delivery_date') or p_doc.delivery_date
child_item.conversion_factor = flt(trans_item.get('conversion_factor')) or get_conversion_factor(item.item_code, item.stock_uom).get("conversion_factor") or 1.0
child_item.uom = item.stock_uom
child_item.conversion_factor = get_conversion_factor(item.item_code, item.stock_uom).get("conversion_factor") or 1.0
child_item.warehouse = get_item_warehouse(item, p_doc, overwrite_warehouse=True)
if not child_item.warehouse:
frappe.throw(_("Cannot find {} for item {}. Please set the same in Item Master or Stock Settings.")
@@ -1157,8 +1157,8 @@ def set_purchase_order_defaults(parent_doctype, parent_doctype_name, child_docna
child_item.item_name = item.item_name
child_item.description = item.description
child_item.schedule_date = trans_item.get('schedule_date') or p_doc.schedule_date
child_item.conversion_factor = flt(trans_item.get('conversion_factor')) or get_conversion_factor(item.item_code, item.stock_uom).get("conversion_factor") or 1.0
child_item.uom = item.stock_uom
child_item.conversion_factor = get_conversion_factor(item.item_code, item.stock_uom).get("conversion_factor") or 1.0
child_item.base_rate = 1 # Initiallize value will update in parent validation
child_item.base_amount = 1 # Initiallize value will update in parent validation
return child_item
@@ -1190,6 +1190,26 @@ def check_and_delete_children(parent, data):
@frappe.whitelist()
def update_child_qty_rate(parent_doctype, trans_items, parent_doctype_name, child_docname="items"):
def check_permissions(doc, perm_type='create'):
try:
doc.check_permission(perm_type)
except:
action = "add" if perm_type == 'create' else "update"
frappe.throw(_("You do not have permissions to {} items in a Sales Order.").format(action), title=_("Insufficient Permissions"))
def get_new_child_item(item_row):
if parent_doctype == "Sales Order":
return set_sales_order_defaults(parent_doctype, parent_doctype_name, child_docname, item_row)
if parent_doctype == "Purchase Order":
return set_purchase_order_defaults(parent_doctype, parent_doctype_name, child_docname, item_row)
def validate_quantity(child_item, d):
if parent_doctype == "Sales Order" and flt(d.get("qty")) < flt(child_item.delivered_qty):
frappe.throw(_("Cannot set quantity less than delivered quantity"))
if parent_doctype == "Purchase Order" and flt(d.get("qty")) < flt(child_item.received_qty):
frappe.throw(_("Cannot set quantity less than received quantity"))
data = json.loads(trans_items)
sales_doctypes = ['Sales Order', 'Sales Invoice', 'Delivery Note', 'Quotation']
@@ -1201,20 +1221,29 @@ def update_child_qty_rate(parent_doctype, trans_items, parent_doctype_name, chil
new_child_flag = False
if not d.get("docname"):
new_child_flag = True
if parent_doctype == "Sales Order":
child_item = set_sales_order_defaults(parent_doctype, parent_doctype_name, child_docname, d)
if parent_doctype == "Purchase Order":
child_item = set_purchase_order_defaults(parent_doctype, parent_doctype_name, child_docname, d)
check_permissions(parent, 'create')
child_item = get_new_child_item(d)
else:
check_permissions(parent, 'write')
child_item = frappe.get_doc(parent_doctype + ' Item', d.get("docname"))
if flt(child_item.get("rate")) == flt(d.get("rate")) and flt(child_item.get("qty")) == flt(d.get("qty")):
prev_rate, new_rate = flt(child_item.get("rate")), flt(d.get("rate"))
prev_qty, new_qty = flt(child_item.get("qty")), flt(d.get("qty"))
prev_con_fac, new_con_fac = flt(child_item.get("conversion_factor")), flt(d.get("conversion_factor"))
if parent_doctype == 'Sales Order':
prev_date, new_date = child_item.get("delivery_date"), d.get("delivery_date")
elif parent_doctype == 'Purchase Order':
prev_date, new_date = child_item.get("schedule_date"), d.get("schedule_date")
rate_unchanged = prev_rate == new_rate
qty_unchanged = prev_qty == new_qty
conversion_factor_unchanged = prev_con_fac == new_con_fac
date_unchanged = prev_date == new_date if prev_date and new_date else False # in case of delivery note etc
if rate_unchanged and qty_unchanged and conversion_factor_unchanged and date_unchanged:
continue
if parent_doctype == "Sales Order" and flt(d.get("qty")) < flt(child_item.delivered_qty):
frappe.throw(_("Cannot set quantity less than delivered quantity"))
if parent_doctype == "Purchase Order" and flt(d.get("qty")) < flt(child_item.received_qty):
frappe.throw(_("Cannot set quantity less than received quantity"))
validate_quantity(child_item, d)
child_item.qty = flt(d.get("qty"))
precision = child_item.precision("rate") or 2
@@ -1225,6 +1254,18 @@ def update_child_qty_rate(parent_doctype, trans_items, parent_doctype_name, chil
else:
child_item.rate = flt(d.get("rate"))
if d.get("conversion_factor"):
if child_item.stock_uom == child_item.uom:
child_item.conversion_factor = 1
else:
child_item.conversion_factor = flt(d.get('conversion_factor'))
if d.get("delivery_date") and parent_doctype == 'Sales Order':
child_item.delivery_date = d.get('delivery_date')
if d.get("schedule_date") and parent_doctype == 'Purchase Order':
child_item.schedule_date = d.get('schedule_date')
if flt(child_item.price_list_rate):
if flt(child_item.rate) > flt(child_item.price_list_rate):
# if rate is greater than price_list_rate, set margin

View File

@@ -349,7 +349,7 @@ class BuyingController(StockController):
})
if not rm.rate:
rm.rate = get_valuation_rate(raw_material_data.item_code, self.supplier_warehouse,
rm.rate = get_valuation_rate(raw_material_data.rm_item_code, self.supplier_warehouse,
self.doctype, self.name, currency=self.company_currency, company=self.company)
rm.amount = qty * flt(rm.rate)

View File

@@ -70,7 +70,7 @@ def validate_item_variant_attributes(item, args=None):
else:
attributes_list = attribute_values.get(attribute.lower(), [])
validate_item_attribute_value(attributes_list, attribute, value, item.name)
validate_item_attribute_value(attributes_list, attribute, value, item.name, from_variant=True)
def validate_is_incremental(numeric_attribute, attribute, value, item):
from_range = numeric_attribute.from_range
@@ -93,13 +93,20 @@ def validate_is_incremental(numeric_attribute, attribute, value, item):
.format(attribute, from_range, to_range, increment, item),
InvalidItemAttributeValueError, title=_('Invalid Attribute'))
def validate_item_attribute_value(attributes_list, attribute, attribute_value, item):
def validate_item_attribute_value(attributes_list, attribute, attribute_value, item, from_variant=True):
allow_rename_attribute_value = frappe.db.get_single_value('Item Variant Settings', 'allow_rename_attribute_value')
if allow_rename_attribute_value:
pass
elif attribute_value not in attributes_list:
frappe.throw(_("The value {0} is already assigned to an exisiting Item {2}.").format(
attribute_value, attribute, item), InvalidItemAttributeValueError, title=_('Rename Not Allowed'))
if from_variant:
frappe.throw(_("{0} is not a valid Value for Attribute {1} of Item {2}.").format(
frappe.bold(attribute_value), frappe.bold(attribute), frappe.bold(item)), InvalidItemAttributeValueError, title=_("Invalid Value"))
else:
msg = _("The value {0} is already assigned to an existing Item {1}.").format(
frappe.bold(attribute_value), frappe.bold(item))
msg += "<br>" + _("To still proceed with editing this Attribute Value, enable {0} in Item Variant Settings.").format(frappe.bold("Allow Rename Attribute Value"))
frappe.throw(msg, InvalidItemAttributeValueError, title=_('Edit Not Allowed'))
def get_attribute_values(item):
if not frappe.flags.attribute_values:

View File

@@ -19,7 +19,8 @@ class QualityInspectionNotSubmittedError(frappe.ValidationError): pass
class StockController(AccountsController):
def validate(self):
super(StockController, self).validate()
self.validate_inspection()
if not self.get('is_return'):
self.validate_inspection()
self.validate_serialized_batch()
self.validate_customer_provided_item()
@@ -228,7 +229,9 @@ class StockController(AccountsController):
def check_expense_account(self, item):
if not item.get("expense_account"):
frappe.throw(_("Expense Account not set for Item {0}. Please set an Expense Account for the item in the Items table").format(item.item_code))
frappe.throw(_("Row #{0}: Expense Account not set for Item {1}. Please set an Expense \
Account in the Items table").format(item.idx, frappe.bold(item.item_code)),
title=_("Expense Account Missing"))
else:
is_expense_account = frappe.db.get_value("Account",