Merge branch 'develop' of https://github.com/frappe/erpnext into develop

This commit is contained in:
Khushal Trivedi 2019-11-20 18:48:21 +05:30
commit 2224fe96c8
18 changed files with 515 additions and 1122 deletions

View File

@ -398,7 +398,7 @@ cur_frm.cscript.voucher_type = function(doc, cdt, cdn) {
method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_default_bank_cash_account", method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_default_bank_cash_account",
args: { args: {
"account_type": (doc.voucher_type=="Bank Entry" ? "account_type": (doc.voucher_type=="Bank Entry" ?
"Bank" : (doc.voucher_type=="Cash" ? "Cash" : null)), "Bank" : (doc.voucher_type=="Cash Entry" ? "Cash" : null)),
"company": doc.company "company": doc.company
}, },
callback: function(r) { callback: function(r) {

View File

@ -181,8 +181,9 @@ def get_serial_no_for_item(args):
item_details.serial_no = get_serial_no(args) item_details.serial_no = get_serial_no(args)
return item_details return item_details
def get_pricing_rule_for_item(args, price_list_rate=0, doc=None): def get_pricing_rule_for_item(args, price_list_rate=0, doc=None, for_validate=False):
from erpnext.accounts.doctype.pricing_rule.utils import get_pricing_rules from erpnext.accounts.doctype.pricing_rule.utils import (get_pricing_rules,
get_applied_pricing_rules, get_pricing_rule_items)
if isinstance(doc, string_types): if isinstance(doc, string_types):
doc = json.loads(doc) doc = json.loads(doc)
@ -209,6 +210,55 @@ def get_pricing_rule_for_item(args, price_list_rate=0, doc=None):
item_details, args.get('item_code')) item_details, args.get('item_code'))
return item_details return item_details
update_args_for_pricing_rule(args)
pricing_rules = (get_applied_pricing_rules(args)
if for_validate and args.get("pricing_rules") else get_pricing_rules(args, doc))
if pricing_rules:
rules = []
for pricing_rule in pricing_rules:
if not pricing_rule: continue
if isinstance(pricing_rule, string_types):
pricing_rule = frappe.get_cached_doc("Pricing Rule", pricing_rule)
pricing_rule.apply_rule_on_other_items = get_pricing_rule_items(pricing_rule)
if pricing_rule.get('suggestion'): continue
item_details.validate_applied_rule = pricing_rule.get("validate_applied_rule", 0)
item_details.price_or_product_discount = pricing_rule.get("price_or_product_discount")
rules.append(get_pricing_rule_details(args, pricing_rule))
if pricing_rule.mixed_conditions or pricing_rule.apply_rule_on_other:
item_details.update({
'apply_rule_on_other_items': json.dumps(pricing_rule.apply_rule_on_other_items),
'apply_rule_on': (frappe.scrub(pricing_rule.apply_rule_on_other)
if pricing_rule.apply_rule_on_other else frappe.scrub(pricing_rule.get('apply_on')))
})
if pricing_rule.coupon_code_based==1 and args.coupon_code==None:
return item_details
if (not pricing_rule.validate_applied_rule and
pricing_rule.price_or_product_discount == "Price"):
apply_price_discount_pricing_rule(pricing_rule, item_details, args)
item_details.has_pricing_rule = 1
item_details.pricing_rules = ','.join([d.pricing_rule for d in rules])
if not doc: return item_details
elif args.get("pricing_rules"):
item_details = remove_pricing_rule_for_item(args.get("pricing_rules"),
item_details, args.get('item_code'))
return item_details
def update_args_for_pricing_rule(args):
if not (args.item_group and args.brand): if not (args.item_group and args.brand):
try: try:
args.item_group, args.brand = frappe.get_cached_value("Item", args.item_code, ["item_group", "brand"]) args.item_group, args.brand = frappe.get_cached_value("Item", args.item_code, ["item_group", "brand"])
@ -235,52 +285,12 @@ def get_pricing_rule_for_item(args, price_list_rate=0, doc=None):
args.supplier_group = frappe.get_cached_value("Supplier", args.supplier, "supplier_group") args.supplier_group = frappe.get_cached_value("Supplier", args.supplier, "supplier_group")
args.customer = args.customer_group = args.territory = None args.customer = args.customer_group = args.territory = None
pricing_rules = get_pricing_rules(args, doc)
if pricing_rules:
rules = []
for pricing_rule in pricing_rules:
if not pricing_rule or pricing_rule.get('suggestion'): continue
item_details.validate_applied_rule = pricing_rule.get("validate_applied_rule", 0)
rules.append(get_pricing_rule_details(args, pricing_rule))
if pricing_rule.mixed_conditions or pricing_rule.apply_rule_on_other:
continue
if pricing_rule.coupon_code_based==1 and args.coupon_code==None:
return item_details
if (not pricing_rule.validate_applied_rule and
pricing_rule.price_or_product_discount == "Price"):
apply_price_discount_pricing_rule(pricing_rule, item_details, args)
item_details.has_pricing_rule = 1
# if discount is applied on the rate and not on price list rate
# if price_list_rate:
# set_discount_amount(price_list_rate, item_details)
item_details.pricing_rules = ','.join([d.pricing_rule for d in rules])
if not doc: return item_details
for rule in rules:
doc.append('pricing_rules', rule)
elif args.get("pricing_rules"):
item_details = remove_pricing_rule_for_item(args.get("pricing_rules"),
item_details, args.get('item_code'))
return item_details
def get_pricing_rule_details(args, pricing_rule): def get_pricing_rule_details(args, pricing_rule):
return frappe._dict({ return frappe._dict({
'pricing_rule': pricing_rule.name, 'pricing_rule': pricing_rule.name,
'rate_or_discount': pricing_rule.rate_or_discount, 'rate_or_discount': pricing_rule.rate_or_discount,
'margin_type': pricing_rule.margin_type, 'margin_type': pricing_rule.margin_type,
'item_code': pricing_rule.item_code or args.get("item_code"), 'item_code': args.get("item_code"),
'child_docname': args.get('child_docname') 'child_docname': args.get('child_docname')
}) })
@ -327,10 +337,10 @@ def set_discount_amount(rate, item_details):
item_details.rate = rate item_details.rate = rate
def remove_pricing_rule_for_item(pricing_rules, item_details, item_code=None): def remove_pricing_rule_for_item(pricing_rules, item_details, item_code=None):
from erpnext.accounts.doctype.pricing_rule.utils import get_apply_on_and_items from erpnext.accounts.doctype.pricing_rule.utils import get_pricing_rule_items
for d in pricing_rules.split(','): for d in pricing_rules.split(','):
if not d or not frappe.db.exists("Pricing Rule", d): continue if not d or not frappe.db.exists("Pricing Rule", d): continue
pricing_rule = frappe.get_doc('Pricing Rule', d) pricing_rule = frappe.get_cached_doc('Pricing Rule', d)
if pricing_rule.price_or_product_discount == 'Price': if pricing_rule.price_or_product_discount == 'Price':
if pricing_rule.rate_or_discount == 'Discount Percentage': if pricing_rule.rate_or_discount == 'Discount Percentage':
@ -348,8 +358,9 @@ def remove_pricing_rule_for_item(pricing_rules, item_details, item_code=None):
else pricing_rule.get('free_item')) else pricing_rule.get('free_item'))
if pricing_rule.get("mixed_conditions") or pricing_rule.get("apply_rule_on_other"): if pricing_rule.get("mixed_conditions") or pricing_rule.get("apply_rule_on_other"):
apply_on, items = get_apply_on_and_items(pricing_rule, item_details) items = get_pricing_rule_items(pricing_rule)
item_details.apply_on = apply_on item_details.apply_on = (frappe.scrub(pricing_rule.apply_rule_on_other)
if pricing_rule.apply_rule_on_other else frappe.scrub(pricing_rule.get('apply_on')))
item_details.applied_on_items = ','.join(items) item_details.applied_on_items = ','.join(items)
item_details.pricing_rules = '' item_details.pricing_rules = ''

View File

@ -8,6 +8,7 @@ import frappe, copy, json
from frappe import throw, _ from frappe import throw, _
from six import string_types from six import string_types
from frappe.utils import flt, cint, get_datetime from frappe.utils import flt, cint, get_datetime
from erpnext.setup.doctype.item_group.item_group import get_child_item_groups
from erpnext.stock.doctype.warehouse.warehouse import get_child_warehouses from erpnext.stock.doctype.warehouse.warehouse import get_child_warehouses
from erpnext.stock.get_item_details import get_conversion_factor from erpnext.stock.get_item_details import get_conversion_factor
@ -173,10 +174,11 @@ def filter_pricing_rules(args, pricing_rules, doc=None):
if (field and pricing_rules[0].get('other_' + field) != args.get(field)): return if (field and pricing_rules[0].get('other_' + field) != args.get(field)): return
pr_doc = frappe.get_doc('Pricing Rule', pricing_rules[0].name) pr_doc = frappe.get_cached_doc('Pricing Rule', pricing_rules[0].name)
if pricing_rules[0].mixed_conditions and doc: if pricing_rules[0].mixed_conditions and doc:
stock_qty, amount = get_qty_and_rate_for_mixed_conditions(doc, pr_doc, args) stock_qty, amount, items = get_qty_and_rate_for_mixed_conditions(doc, pr_doc, args)
pricing_rules[0].apply_rule_on_other_items = items
elif pricing_rules[0].is_cumulative: elif pricing_rules[0].is_cumulative:
items = [args.get(frappe.scrub(pr_doc.get('apply_on')))] items = [args.get(frappe.scrub(pr_doc.get('apply_on')))]
@ -339,17 +341,19 @@ def get_qty_and_rate_for_mixed_conditions(doc, pr_doc, args):
sum_qty += data[0] sum_qty += data[0]
sum_amt += data[1] sum_amt += data[1]
return sum_qty, sum_amt return sum_qty, sum_amt, items
def get_qty_and_rate_for_other_item(doc, pr_doc, pricing_rules): def get_qty_and_rate_for_other_item(doc, pr_doc, pricing_rules):
for d in get_pricing_rule_items(pr_doc): items = get_pricing_rule_items(pr_doc)
for row in doc.items:
if d == row.get(frappe.scrub(pr_doc.apply_on)):
pricing_rules = filter_pricing_rules_for_qty_amount(row.get("stock_qty"),
row.get("amount"), pricing_rules, row)
if pricing_rules and pricing_rules[0]: for row in doc.items:
return pricing_rules if row.get(frappe.scrub(pr_doc.apply_rule_on_other)) in items:
pricing_rules = filter_pricing_rules_for_qty_amount(row.get("stock_qty"),
row.get("amount"), pricing_rules, row)
if pricing_rules and pricing_rules[0]:
pricing_rules[0].apply_rule_on_other_items = items
return pricing_rules
def get_qty_amount_data_for_cumulative(pr_doc, doc, items=[]): def get_qty_amount_data_for_cumulative(pr_doc, doc, items=[]):
sum_qty, sum_amt = [0, 0] sum_qty, sum_amt = [0, 0]
@ -397,31 +401,7 @@ def get_qty_amount_data_for_cumulative(pr_doc, doc, items=[]):
return [sum_qty, sum_amt] return [sum_qty, sum_amt]
def validate_pricing_rules(doc): def apply_pricing_rule_on_transaction(doc):
validate_pricing_rule_on_transactions(doc)
for d in doc.items:
validate_pricing_rule_on_items(doc, d)
doc.calculate_taxes_and_totals()
def validate_pricing_rule_on_items(doc, item_row, do_not_validate = False):
value = 0
for pricing_rule in get_applied_pricing_rules(doc, item_row):
pr_doc = frappe.get_doc('Pricing Rule', pricing_rule)
if pr_doc.get('apply_on') == 'Transaction': continue
if pr_doc.get('price_or_product_discount') == 'Product':
apply_pricing_rule_for_free_items(doc, pr_doc)
else:
for field in ['discount_percentage', 'discount_amount', 'rate']:
if not pr_doc.get(field): continue
value += pr_doc.get(field)
apply_pricing_rule(doc, pr_doc, item_row, value, do_not_validate)
def validate_pricing_rule_on_transactions(doc):
conditions = "apply_on = 'Transaction'" conditions = "apply_on = 'Transaction'"
values = {} values = {}
@ -453,7 +433,7 @@ def validate_pricing_rule_on_transactions(doc):
elif d.price_or_product_discount == 'Product': elif d.price_or_product_discount == 'Product':
apply_pricing_rule_for_free_items(doc, d) apply_pricing_rule_for_free_items(doc, d)
def get_applied_pricing_rules(doc, item_row): def get_applied_pricing_rules(item_row):
return (item_row.get("pricing_rules").split(',') return (item_row.get("pricing_rules").split(',')
if item_row.get("pricing_rules") else []) if item_row.get("pricing_rules") else [])
@ -468,70 +448,29 @@ def apply_pricing_rule_for_free_items(doc, pricing_rule):
'item_code': pricing_rule.get('free_item'), 'item_code': pricing_rule.get('free_item'),
'qty': pricing_rule.get('free_qty'), 'qty': pricing_rule.get('free_qty'),
'uom': pricing_rule.get('free_item_uom'), 'uom': pricing_rule.get('free_item_uom'),
'rate': pricing_rule.get('free_item_rate'), 'rate': pricing_rule.get('free_item_rate') or 0,
'is_free_item': 1 'is_free_item': 1
}) })
doc.set_missing_values() doc.set_missing_values()
def apply_pricing_rule(doc, pr_doc, item_row, value, do_not_validate=False):
apply_on, items = get_apply_on_and_items(pr_doc, item_row)
rule_applied = {}
for item in doc.get("items"):
if item.get(apply_on) in items:
if not item.pricing_rules:
item.pricing_rules = item_row.pricing_rules
for field in ['discount_percentage', 'discount_amount', 'rate']:
if not pr_doc.get(field): continue
key = (item.name, item.pricing_rules)
if not pr_doc.validate_applied_rule:
rule_applied[key] = 1
item.set(field, value)
elif item.get(field) < value:
if not do_not_validate and item.idx == item_row.idx:
rule_applied[key] = 0
frappe.msgprint(_("Row {0}: user has not applied rule <b>{1}</b> on the item <b>{2}</b>")
.format(item.idx, pr_doc.title, item.item_code))
if rule_applied and doc.get("pricing_rules"):
for d in doc.get("pricing_rules"):
key = (d.child_docname, d.pricing_rule)
if key in rule_applied:
d.rule_applied = 1
def get_apply_on_and_items(pr_doc, item_row):
# for mixed or other items conditions
apply_on = frappe.scrub(pr_doc.get('apply_on'))
items = (get_pricing_rule_items(pr_doc)
if pr_doc.mixed_conditions else [item_row.get(apply_on)])
if pr_doc.apply_rule_on_other:
apply_on = frappe.scrub(pr_doc.apply_rule_on_other)
items = [pr_doc.get(apply_on)]
return apply_on, items
def get_pricing_rule_items(pr_doc): def get_pricing_rule_items(pr_doc):
apply_on_data = []
apply_on = frappe.scrub(pr_doc.get('apply_on')) apply_on = frappe.scrub(pr_doc.get('apply_on'))
pricing_rule_apply_on = apply_on_table.get(pr_doc.get('apply_on')) pricing_rule_apply_on = apply_on_table.get(pr_doc.get('apply_on'))
return [item.get(apply_on) for item in pr_doc.get(pricing_rule_apply_on)] or [] for d in pr_doc.get(pricing_rule_apply_on):
if apply_on == 'item_group':
get_child_item_groups(d.get(apply_on))
else:
apply_on_data.append(d.get(apply_on))
@frappe.whitelist() if pr_doc.apply_rule_on_other:
def validate_pricing_rule_for_different_cond(doc): apply_on = frappe.scrub(pr_doc.apply_rule_on_other)
if isinstance(doc, string_types): apply_on_data.append(pr_doc.get(apply_on))
doc = json.loads(doc)
doc = frappe.get_doc(doc) return list(set(apply_on_data))
for d in doc.get("items"):
validate_pricing_rule_on_items(doc, d, True)
return doc
def validate_coupon_code(coupon_name): def validate_coupon_code(coupon_name):
from frappe.utils import today,getdate from frappe.utils import today,getdate

View File

@ -357,14 +357,11 @@ def get_customer_wise_price_list():
def get_bin_data(pos_profile): def get_bin_data(pos_profile):
itemwise_bin_data = {} itemwise_bin_data = {}
cond = "1=1" filters = { 'actual_qty': ['>', 0] }
if pos_profile.get('warehouse'): if pos_profile.get('warehouse'):
cond = "warehouse = %(warehouse)s" filters.update({ 'warehouse': pos_profile.get('warehouse') })
bin_data = frappe.db.sql(""" select item_code, warehouse, actual_qty from `tabBin` bin_data = frappe.db.get_all('Bin', fields = ['item_code', 'warehouse', 'actual_qty'], filters=filters)
where actual_qty > 0 and {cond}""".format(cond=cond), {
'warehouse': frappe.db.escape(pos_profile.get('warehouse'))
}, as_dict=1)
for bins in bin_data: for bins in bin_data:
if bins.item_code not in itemwise_bin_data: if bins.item_code not in itemwise_bin_data:
@ -550,11 +547,15 @@ def make_address(args, customer):
def make_email_queue(email_queue): def make_email_queue(email_queue):
name_list = [] name_list = []
for key, data in iteritems(email_queue): for key, data in iteritems(email_queue):
name = frappe.db.get_value('Sales Invoice', {'offline_pos_name': key}, 'name') name = frappe.db.get_value('Sales Invoice', {'offline_pos_name': key}, 'name')
if not name: continue
data = json.loads(data) data = json.loads(data)
sender = frappe.session.user sender = frappe.session.user
print_format = "POS Invoice" if not cint(frappe.db.get_value('Print Format', 'POS Invoice', 'disabled')) else None print_format = "POS Invoice" if not cint(frappe.db.get_value('Print Format', 'POS Invoice', 'disabled')) else None
attachments = [frappe.attach_print('Sales Invoice', name, print_format=print_format)] attachments = [frappe.attach_print('Sales Invoice', name, print_format=print_format)]
make(subject=data.get('subject'), content=data.get('content'), recipients=data.get('recipients'), make(subject=data.get('subject'), content=data.get('content'), recipients=data.get('recipients'),

View File

@ -5,15 +5,17 @@ from __future__ import unicode_literals
import frappe, erpnext import frappe, erpnext
import json import json
from frappe import _, throw from frappe import _, throw
from frappe.utils import today, flt, cint, fmt_money, formatdate, getdate, add_days, add_months, get_last_day, nowdate from frappe.utils import (today, flt, cint, fmt_money, formatdate,
from erpnext.stock.get_item_details import get_conversion_factor getdate, add_days, add_months, get_last_day, nowdate, get_link_to_form)
from erpnext.stock.get_item_details import get_conversion_factor, get_item_details
from erpnext.setup.utils import get_exchange_rate from erpnext.setup.utils import get_exchange_rate
from erpnext.accounts.utils import get_fiscal_years, validate_fiscal_year, get_account_currency from erpnext.accounts.utils import get_fiscal_years, validate_fiscal_year, get_account_currency
from erpnext.utilities.transaction_base import TransactionBase from erpnext.utilities.transaction_base import TransactionBase
from erpnext.buying.utils import update_last_purchase_rate from erpnext.buying.utils import update_last_purchase_rate
from erpnext.controllers.sales_and_purchase_return import validate_return from erpnext.controllers.sales_and_purchase_return import validate_return
from erpnext.accounts.party import get_party_account_currency, validate_party_frozen_disabled from erpnext.accounts.party import get_party_account_currency, validate_party_frozen_disabled
from erpnext.accounts.doctype.pricing_rule.utils import validate_pricing_rules from erpnext.accounts.doctype.pricing_rule.utils import (apply_pricing_rule_on_transaction,
apply_pricing_rule_for_free_items, get_applied_pricing_rules)
from erpnext.exceptions import InvalidCurrency from erpnext.exceptions import InvalidCurrency
from six import text_type from six import text_type
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions
@ -101,7 +103,7 @@ class AccountsController(TransactionBase):
validate_regional(self) validate_regional(self)
if self.doctype != 'Material Request': if self.doctype != 'Material Request':
validate_pricing_rules(self) apply_pricing_rule_on_transaction(self)
def validate_invoice_documents_schedule(self): def validate_invoice_documents_schedule(self):
self.validate_payment_schedule_dates() self.validate_payment_schedule_dates()
@ -232,7 +234,6 @@ class AccountsController(TransactionBase):
def set_missing_item_details(self, for_validate=False): def set_missing_item_details(self, for_validate=False):
"""set missing item values""" """set missing item values"""
from erpnext.stock.get_item_details import get_item_details
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
if hasattr(self, "items"): if hasattr(self, "items"):
@ -244,7 +245,6 @@ class AccountsController(TransactionBase):
document_type = "{} Item".format(self.doctype) document_type = "{} Item".format(self.doctype)
parent_dict.update({"document_type": document_type}) parent_dict.update({"document_type": document_type})
self.set('pricing_rules', [])
# party_name field used for customer in quotation # party_name field used for customer in quotation
if self.doctype == "Quotation" and self.quotation_to == "Customer" and parent_dict.get("party_name"): if self.doctype == "Quotation" and self.quotation_to == "Customer" and parent_dict.get("party_name"):
parent_dict.update({"customer": parent_dict.get("party_name")}) parent_dict.update({"customer": parent_dict.get("party_name")})
@ -264,7 +264,7 @@ class AccountsController(TransactionBase):
if self.get("is_subcontracted"): if self.get("is_subcontracted"):
args["is_subcontracted"] = self.is_subcontracted args["is_subcontracted"] = self.is_subcontracted
ret = get_item_details(args, self, overwrite_warehouse=False) ret = get_item_details(args, self, for_validate=True, overwrite_warehouse=False)
for fieldname, value in ret.items(): for fieldname, value in ret.items():
if item.meta.get_field(fieldname) and value is not None: if item.meta.get_field(fieldname) and value is not None:
@ -285,24 +285,42 @@ class AccountsController(TransactionBase):
if self.doctype in ["Purchase Invoice", "Sales Invoice"] and item.meta.get_field('is_fixed_asset'): if self.doctype in ["Purchase Invoice", "Sales Invoice"] and item.meta.get_field('is_fixed_asset'):
item.set('is_fixed_asset', ret.get('is_fixed_asset', 0)) item.set('is_fixed_asset', ret.get('is_fixed_asset', 0))
if ret.get("pricing_rules") and not ret.get("validate_applied_rule", 0): if ret.get("pricing_rules"):
# if user changed the discount percentage then set user's discount percentage ? self.apply_pricing_rule_on_items(item, ret)
item.set("pricing_rules", ret.get("pricing_rules"))
item.set("discount_percentage", ret.get("discount_percentage"))
item.set("discount_amount", ret.get("discount_amount"))
if ret.get("pricing_rule_for") == "Rate":
item.set("price_list_rate", ret.get("price_list_rate"))
if item.get("price_list_rate"):
item.rate = flt(item.price_list_rate *
(1.0 - (flt(item.discount_percentage) / 100.0)), item.precision("rate"))
if item.get('discount_amount'):
item.rate = item.price_list_rate - item.discount_amount
if self.doctype == "Purchase Invoice": if self.doctype == "Purchase Invoice":
self.set_expense_account(for_validate) self.set_expense_account(for_validate)
def apply_pricing_rule_on_items(self, item, pricing_rule_args):
if not pricing_rule_args.get("validate_applied_rule", 0):
# if user changed the discount percentage then set user's discount percentage ?
if pricing_rule_args.get("price_or_product_discount") == 'Price':
item.set("pricing_rules", pricing_rule_args.get("pricing_rules"))
item.set("discount_percentage", pricing_rule_args.get("discount_percentage"))
item.set("discount_amount", pricing_rule_args.get("discount_amount"))
if pricing_rule_args.get("pricing_rule_for") == "Rate":
item.set("price_list_rate", pricing_rule_args.get("price_list_rate"))
if item.get("price_list_rate"):
item.rate = flt(item.price_list_rate *
(1.0 - (flt(item.discount_percentage) / 100.0)), item.precision("rate"))
if item.get('discount_amount'):
item.rate = item.price_list_rate - item.discount_amount
elif pricing_rule_args.get('free_item'):
apply_pricing_rule_for_free_items(self, pricing_rule_args)
elif pricing_rule_args.get("validate_applied_rule"):
for pricing_rule in get_applied_pricing_rules(item):
pricing_rule_doc = frappe.get_cached_doc("Pricing Rule", pricing_rule)
for field in ['discount_percentage', 'discount_amount', 'rate']:
if item.get(field) < pricing_rule_doc.get(field):
title = get_link_to_form("Pricing Rule", pricing_rule)
frappe.msgprint(_("Row {0}: user has not applied the rule {1} on the item {2}")
.format(item.idx, frappe.bold(title), frappe.bold(item.item_code)))
def set_taxes(self): def set_taxes(self):
if not self.meta.get_field("taxes"): if not self.meta.get_field("taxes"):
return return

View File

@ -159,8 +159,12 @@ def item_query(doctype, txt, searchfield, start, page_len, filters, as_dict=Fals
if "description" in searchfields: if "description" in searchfields:
searchfields.remove("description") searchfields.remove("description")
columns = [field for field in searchfields if not field in ["name", "item_group", "description"]] columns = ''
columns = ", ".join(columns) extra_searchfields = [field for field in searchfields
if not field in ["name", "item_group", "description"]]
if extra_searchfields:
columns = ", " + ", ".join(extra_searchfields)
searchfields = searchfields + [field for field in[searchfield or "name", "item_code", "item_group", "item_name"] searchfields = searchfields + [field for field in[searchfield or "name", "item_code", "item_group", "item_name"]
if not field in searchfields] if not field in searchfields]
@ -176,7 +180,7 @@ def item_query(doctype, txt, searchfield, start, page_len, filters, as_dict=Fals
concat(substr(tabItem.item_name, 1, 40), "..."), item_name) as item_name, concat(substr(tabItem.item_name, 1, 40), "..."), item_name) as item_name,
tabItem.item_group, tabItem.item_group,
if(length(tabItem.description) > 40, \ if(length(tabItem.description) > 40, \
concat(substr(tabItem.description, 1, 40), "..."), description) as description, concat(substr(tabItem.description, 1, 40), "..."), description) as description
{columns} {columns}
from tabItem from tabItem
where tabItem.docstatus < 2 where tabItem.docstatus < 2

View File

@ -72,7 +72,7 @@ def validate_returned_items(doc):
items_returned = False items_returned = False
for d in doc.get("items"): for d in doc.get("items"):
if d.item_code and (flt(d.qty) < 0 or d.get('received_qty') < 0): if d.item_code and (flt(d.qty) < 0 or flt(d.get('received_qty')) < 0):
if d.item_code not in valid_items: if d.item_code not in valid_items:
frappe.throw(_("Row # {0}: Returned Item {1} does not exists in {2} {3}") frappe.throw(_("Row # {0}: Returned Item {1} does not exists in {2} {3}")
.format(d.idx, d.item_code, doc.doctype, doc.return_against)) .format(d.idx, d.item_code, doc.doctype, doc.return_against))

View File

@ -552,7 +552,7 @@ class calculate_taxes_and_totals(object):
if item.price_list_rate: if item.price_list_rate:
if item.pricing_rules and not self.doc.ignore_pricing_rule: if item.pricing_rules and not self.doc.ignore_pricing_rule:
for d in item.pricing_rules.split(','): for d in item.pricing_rules.split(','):
pricing_rule = frappe.get_doc('Pricing Rule', d) pricing_rule = frappe.get_cached_doc('Pricing Rule', d)
if (pricing_rule.margin_type == 'Amount' and pricing_rule.currency == self.doc.currency)\ if (pricing_rule.margin_type == 'Amount' and pricing_rule.currency == self.doc.currency)\
or (pricing_rule.margin_type == 'Percentage'): or (pricing_rule.margin_type == 'Percentage'):

View File

@ -20,10 +20,6 @@ def get_approvers(doctype, txt, searchfield, start, page_len, filters):
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"), ["department", "leave_approver"], as_dict=True)
if employee.leave_approver:
approver = frappe.db.get_value("User", employee.leave_approver, ['name', 'first_name', 'last_name'])
approvers.append(approver)
return approvers
employee_department = filters.get("department") or employee.department employee_department = filters.get("department") or employee.department
if employee_department: if employee_department:
@ -34,6 +30,9 @@ def get_approvers(doctype, txt, searchfield, start, page_len, filters):
and disabled=0 and disabled=0
order by lft desc""", (department_details.lft, department_details.rgt), as_list=True) order by lft desc""", (department_details.lft, department_details.rgt), as_list=True)
if filters.get("doctype") == "Leave Application" and employee.leave_approver:
approvers.append(frappe.db.get_value("User", employee.leave_approver, ['name', 'first_name', 'last_name']))
if filters.get("doctype") == "Leave Application": if filters.get("doctype") == "Leave Application":
parentfield = "leave_approvers" parentfield = "leave_approvers"
else: else:
@ -47,4 +46,4 @@ 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)
return approvers return set(tuple(approver) for approver in approvers)

View File

@ -89,7 +89,8 @@
"fieldtype": "Link", "fieldtype": "Link",
"label": "Company", "label": "Company",
"options": "Company", "options": "Company",
"reqd": 1 "reqd": 1,
"search_index": 1
}, },
{ {
"fieldname": "section_break_12", "fieldname": "section_break_12",
@ -129,7 +130,7 @@
} }
], ],
"is_submittable": 1, "is_submittable": 1,
"modified": "2019-10-16 13:38:32.302316", "modified": "2019-11-18 19:37:37.151686",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Manufacturing", "module": "Manufacturing",
"name": "Blanket Order", "name": "Blanket Order",

View File

@ -1,298 +1,78 @@
{ {
"allow_copy": 0, "creation": "2018-05-24 07:20:04.255236",
"allow_guest_to_view": 0, "doctype": "DocType",
"allow_import": 0, "editable_grid": 1,
"allow_rename": 0, "engine": "InnoDB",
"beta": 0, "field_order": [
"creation": "2018-05-24 07:20:04.255236", "item_code",
"custom": 0, "item_name",
"docstatus": 0, "column_break_3",
"doctype": "DocType", "qty",
"document_type": "", "rate",
"editable_grid": 1, "ordered_qty",
"engine": "InnoDB", "section_break_7",
"terms_and_conditions"
],
"fields": [ "fields": [
{ {
"allow_bulk_edit": 0, "fieldname": "item_code",
"allow_in_quick_entry": 0, "fieldtype": "Link",
"allow_on_submit": 0, "in_list_view": 1,
"bold": 0, "label": "Item Code",
"collapsible": 0, "options": "Item",
"columns": 0, "reqd": 1,
"fieldname": "item_code", "search_index": 1
"fieldtype": "Link", },
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Item Code",
"length": 0,
"no_copy": 0,
"options": "Item",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{ {
"allow_bulk_edit": 0, "fetch_from": "item_code.item_name",
"allow_in_quick_entry": 0, "fieldname": "item_name",
"allow_on_submit": 0, "fieldtype": "Data",
"bold": 0, "label": "Item Name"
"collapsible": 0, },
"columns": 0,
"fetch_from": "item_code.item_name",
"fieldname": "item_name",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Item Name",
"length": 0,
"no_copy": 0,
"options": "",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{ {
"allow_bulk_edit": 0, "fieldname": "column_break_3",
"allow_in_quick_entry": 0, "fieldtype": "Column Break"
"allow_on_submit": 0, },
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break_3",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{ {
"allow_bulk_edit": 0, "fieldname": "qty",
"allow_in_quick_entry": 0, "fieldtype": "Float",
"allow_on_submit": 0, "in_list_view": 1,
"bold": 0, "label": "Quantity"
"collapsible": 0, },
"columns": 0,
"fieldname": "qty",
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Quantity",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{ {
"allow_bulk_edit": 0, "fieldname": "rate",
"allow_in_quick_entry": 0, "fieldtype": "Currency",
"allow_on_submit": 0, "in_list_view": 1,
"bold": 0, "label": "Rate",
"collapsible": 0, "reqd": 1
"columns": 0, },
"fieldname": "rate",
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Rate",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{ {
"allow_bulk_edit": 0, "fieldname": "ordered_qty",
"allow_in_quick_entry": 0, "fieldtype": "Float",
"allow_on_submit": 0, "in_list_view": 1,
"bold": 0, "label": "Ordered Quantity",
"collapsible": 0, "no_copy": 1,
"columns": 0, "read_only": 1
"fieldname": "ordered_qty", },
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Ordered Quantity",
"length": 0,
"no_copy": 1,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{ {
"allow_bulk_edit": 0, "fieldname": "section_break_7",
"allow_in_quick_entry": 0, "fieldtype": "Section Break"
"allow_on_submit": 0, },
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "section_break_7",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{ {
"allow_bulk_edit": 0, "fieldname": "terms_and_conditions",
"allow_in_quick_entry": 0, "fieldtype": "Text",
"allow_on_submit": 0, "label": "Terms and Conditions"
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "terms_and_conditions",
"fieldtype": "Text",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Terms and Conditions",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
} }
], ],
"has_web_view": 0, "istable": 1,
"hide_heading": 0, "modified": "2019-11-18 19:37:46.245878",
"hide_toolbar": 0, "modified_by": "Administrator",
"idx": 0, "module": "Manufacturing",
"image_view": 0, "name": "Blanket Order Item",
"in_create": 0, "owner": "Administrator",
"is_submittable": 0, "permissions": [],
"issingle": 0, "quick_entry": 1,
"istable": 1, "sort_field": "modified",
"max_attachments": 0, "sort_order": "DESC",
"modified": "2018-06-14 07:04:14.050836", "track_changes": 1
"modified_by": "Administrator",
"module": "Manufacturing",
"name": "Blanket Order Item",
"name_case": "",
"owner": "Administrator",
"permissions": [],
"quick_entry": 1,
"read_only": 0,
"read_only_onload": 0,
"show_name_in_global_search": 0,
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1,
"track_seen": 0
} }

View File

@ -516,7 +516,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
} }
}, },
() => me.conversion_factor(doc, cdt, cdn, true), () => me.conversion_factor(doc, cdt, cdn, true),
() => me.validate_pricing_rule(item) () => me.remove_pricing_rule(item)
]); ]);
} }
} }
@ -1174,7 +1174,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
callback: function(r) { callback: function(r) {
if (!r.exc && r.message) { if (!r.exc && r.message) {
r.message.forEach(row_item => { r.message.forEach(row_item => {
me.validate_pricing_rule(row_item); me.remove_pricing_rule(row_item);
}); });
me._set_values_for_item_list(r.message); me._set_values_for_item_list(r.message);
me.calculate_taxes_and_totals(); me.calculate_taxes_and_totals();
@ -1283,6 +1283,8 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
_set_values_for_item_list: function(children) { _set_values_for_item_list: function(children) {
var me = this; var me = this;
var price_list_rate_changed = false; var price_list_rate_changed = false;
var items_rule_dict = {};
for(var i=0, l=children.length; i<l; i++) { for(var i=0, l=children.length; i<l; i++) {
var d = children[i]; var d = children[i];
var existing_pricing_rule = frappe.model.get_value(d.doctype, d.name, "pricing_rules"); var existing_pricing_rule = frappe.model.get_value(d.doctype, d.name, "pricing_rules");
@ -1299,14 +1301,39 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
// if pricing rule set as blank from an existing value, apply price_list // if pricing rule set as blank from an existing value, apply price_list
if(!me.frm.doc.ignore_pricing_rule && existing_pricing_rule && !d.pricing_rules) { if(!me.frm.doc.ignore_pricing_rule && existing_pricing_rule && !d.pricing_rules) {
me.apply_price_list(frappe.get_doc(d.doctype, d.name)); me.apply_price_list(frappe.get_doc(d.doctype, d.name));
} else { } else if(!d.pricing_rules) {
me.validate_pricing_rule(frappe.get_doc(d.doctype, d.name)); me.remove_pricing_rule(frappe.get_doc(d.doctype, d.name));
}
if (d.apply_rule_on_other_items) {
items_rule_dict[d.name] = d;
} }
} }
me.apply_rule_on_other_items(items_rule_dict);
if(!price_list_rate_changed) me.calculate_taxes_and_totals(); if(!price_list_rate_changed) me.calculate_taxes_and_totals();
}, },
apply_rule_on_other_items: function(args) {
const me = this;
const fields = ["discount_percentage", "discount_amount", "rate"];
for(var k in args) {
let data = args[k];
me.frm.doc.items.forEach(d => {
if (in_list(data.apply_rule_on_other_items, d[data.apply_rule_on])) {
for(var k in data) {
if (in_list(fields, k)) {
frappe.model.set_value(d.doctype, d.name, k, data[k]);
}
}
}
});
}
},
apply_price_list: function(item, reset_plc_conversion) { apply_price_list: function(item, reset_plc_conversion) {
// We need to reset plc_conversion_rate sometimes because the call to // We need to reset plc_conversion_rate sometimes because the call to
// `erpnext.stock.get_item_details.apply_price_list` is sensitive to its value // `erpnext.stock.get_item_details.apply_price_list` is sensitive to its value
@ -1348,33 +1375,11 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
}); });
}, },
validate_pricing_rule: function(item) { remove_pricing_rule: function(item) {
let me = this; let me = this;
const fields = ["discount_percentage", "discount_amount", "pricing_rules"]; const fields = ["discount_percentage", "discount_amount", "pricing_rules"];
if (item.pricing_rules) { if(item.remove_free_item) {
frappe.call({
method: "erpnext.accounts.doctype.pricing_rule.utils.validate_pricing_rule_for_different_cond",
args: {
doc: me.frm.doc
},
callback: function(r) {
if (r.message) {
r.message.items.forEach(d => {
me.frm.doc.items.forEach(row => {
if(d.name == row.name) {
fields.forEach(f => {
row[f] = d[f];
});
}
});
});
me.trigger_price_list_rate();
}
}
});
} else if(item.remove_free_item) {
var items = []; var items = [];
me.frm.doc.items.forEach(d => { me.frm.doc.items.forEach(d => {

View File

@ -451,7 +451,7 @@ erpnext.pos.PointOfSale = class PointOfSale {
change_pos_profile() { change_pos_profile() {
return new Promise((resolve) => { return new Promise((resolve) => {
const on_submit = ({ pos_profile, set_as_default }) => { const on_submit = ({ company, pos_profile, set_as_default }) => {
if (pos_profile) { if (pos_profile) {
this.pos_profile = pos_profile; this.pos_profile = pos_profile;
} }
@ -461,7 +461,7 @@ erpnext.pos.PointOfSale = class PointOfSale {
method: "erpnext.accounts.doctype.pos_profile.pos_profile.set_default_profile", method: "erpnext.accounts.doctype.pos_profile.pos_profile.set_default_profile",
args: { args: {
'pos_profile': pos_profile, 'pos_profile': pos_profile,
'company': this.frm.doc.company 'company': company
} }
}).then(() => { }).then(() => {
this.on_change_pos_profile(); this.on_change_pos_profile();
@ -471,7 +471,42 @@ erpnext.pos.PointOfSale = class PointOfSale {
} }
} }
frappe.prompt(this.get_prompt_fields(),
let me = this;
var dialog = frappe.prompt([{
fieldtype: 'Link',
label: __('Company'),
options: 'Company',
fieldname: 'company',
default: me.frm.doc.company,
reqd: 1,
onchange: function(e) {
me.get_default_pos_profile(this.value).then((r) => {
dialog.set_value('pos_profile', (r && r.name)? r.name : '');
});
}
},
{
fieldtype: 'Link',
label: __('POS Profile'),
options: 'POS Profile',
fieldname: 'pos_profile',
default: me.frm.doc.pos_profile,
reqd: 1,
get_query: () => {
return {
query: 'erpnext.accounts.doctype.pos_profile.pos_profile.pos_profile_query',
filters: {
company: dialog.get_value('company')
}
};
}
}, {
fieldtype: 'Check',
label: __('Set as default'),
fieldname: 'set_as_default'
}],
on_submit, on_submit,
__('Select POS Profile') __('Select POS Profile')
); );
@ -494,26 +529,9 @@ erpnext.pos.PointOfSale = class PointOfSale {
]); ]);
} }
get_prompt_fields() { get_default_pos_profile(company) {
return [{ return frappe.xcall("erpnext.stock.get_item_details.get_pos_profile",
fieldtype: 'Link', {'company': company})
label: __('POS Profile'),
options: 'POS Profile',
fieldname: 'pos_profile',
reqd: 1,
get_query: () => {
return {
query: 'erpnext.accounts.doctype.pos_profile.pos_profile.pos_profile_query',
filters: {
company: this.frm.doc.company
}
};
}
}, {
fieldtype: 'Check',
label: __('Set as default'),
fieldname: 'set_as_default'
}];
} }
setup_company() { setup_company() {

View File

@ -29,7 +29,8 @@ frappe.ui.form.on("Company", {
company_name: function(frm) { company_name: function(frm) {
if(frm.doc.__islocal) { if(frm.doc.__islocal) {
let parts = frm.doc.company_name.split(); # add missing " " arg in split method
let parts = frm.doc.company_name.split(" ");
let abbr = $.map(parts, function (p) { let abbr = $.map(parts, function (p) {
return p? p.substr(0, 1) : null; return p? p.substr(0, 1) : null;
}).join(""); }).join("");

View File

@ -39,6 +39,7 @@ class ItemGroup(NestedSet, WebsiteGenerator):
invalidate_cache_for(self) invalidate_cache_for(self)
self.validate_name_with_item() self.validate_name_with_item()
self.validate_one_root() self.validate_one_root()
self.delete_child_item_groups_key()
def make_route(self): def make_route(self):
'''Make website route''' '''Make website route'''
@ -58,6 +59,7 @@ class ItemGroup(NestedSet, WebsiteGenerator):
def on_trash(self): def on_trash(self):
NestedSet.on_trash(self) NestedSet.on_trash(self)
WebsiteGenerator.on_trash(self) WebsiteGenerator.on_trash(self)
self.delete_child_item_groups_key()
def validate_name_with_item(self): def validate_name_with_item(self):
if frappe.db.exists("Item", self.name): if frappe.db.exists("Item", self.name):
@ -83,6 +85,9 @@ class ItemGroup(NestedSet, WebsiteGenerator):
return context return context
def delete_child_item_groups_key(self):
frappe.cache().hdel("child_item_groups", self.name)
@frappe.whitelist(allow_guest=True) @frappe.whitelist(allow_guest=True)
def get_product_list_for_group(product_group=None, start=0, limit=10, search=None): def get_product_list_for_group(product_group=None, start=0, limit=10, search=None):
if product_group: if product_group:
@ -136,6 +141,7 @@ def get_child_groups_for_list_in_html(item_group, start, limit, search):
fields = ['name', 'route', 'description', 'image'], fields = ['name', 'route', 'description', 'image'],
filters = dict( filters = dict(
show_in_website = 1, show_in_website = 1,
parent_item_group = item_group.name,
lft = ('>', item_group.lft), lft = ('>', item_group.lft),
rgt = ('<', item_group.rgt), rgt = ('<', item_group.rgt),
), ),
@ -167,6 +173,19 @@ def get_child_groups(item_group_name):
from `tabItem Group` where lft>=%(lft)s and rgt<=%(rgt)s from `tabItem Group` where lft>=%(lft)s and rgt<=%(rgt)s
and show_in_website = 1""", {"lft": item_group.lft, "rgt": item_group.rgt}) and show_in_website = 1""", {"lft": item_group.lft, "rgt": item_group.rgt})
def get_child_item_groups(item_group_name):
child_item_groups = frappe.cache().hget("child_item_groups", item_group_name)
if not child_item_groups:
item_group = frappe.get_cached_doc("Item Group", item_group_name)
child_item_groups = [d.name for d in frappe.get_all('Item Group',
filters= {'lft': ('>=', item_group.lft),'rgt': ('>=', item_group.rgt)})]
frappe.cache().hset("child_item_groups", item_group_name, child_item_groups)
return child_item_groups or {}
def get_item_for_list_in_html(context): def get_item_for_list_in_html(context):
# add missing absolute link in files # add missing absolute link in files
# user may forget it during upload # user may forget it during upload

View File

@ -1,599 +1,200 @@
{ {
"allow_copy": 0, "autoname": "MAT-BIN-.YYYY.-.#####",
"allow_guest_to_view": 0, "creation": "2013-01-10 16:34:25",
"allow_import": 0, "doctype": "DocType",
"allow_rename": 0, "engine": "InnoDB",
"autoname": "MAT-BIN-.YYYY.-.#####", "field_order": [
"beta": 0, "warehouse",
"creation": "2013-01-10 16:34:25", "item_code",
"custom": 0, "reserved_qty",
"docstatus": 0, "actual_qty",
"doctype": "DocType", "ordered_qty",
"editable_grid": 0, "indented_qty",
"engine": "InnoDB", "planned_qty",
"projected_qty",
"reserved_qty_for_production",
"reserved_qty_for_sub_contract",
"ma_rate",
"stock_uom",
"fcfs_rate",
"valuation_rate",
"stock_value"
],
"fields": [ "fields": [
{ {
"allow_bulk_edit": 0, "fieldname": "warehouse",
"allow_in_quick_entry": 0, "fieldtype": "Link",
"allow_on_submit": 0, "in_filter": 1,
"bold": 0, "in_list_view": 1,
"collapsible": 0, "in_standard_filter": 1,
"columns": 0, "label": "Warehouse",
"fieldname": "warehouse", "oldfieldname": "warehouse",
"fieldtype": "Link", "oldfieldtype": "Link",
"hidden": 0, "options": "Warehouse",
"ignore_user_permissions": 0, "read_only": 1,
"ignore_xss_filter": 0, "search_index": 1
"in_filter": 1, },
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Warehouse",
"length": 0,
"no_copy": 0,
"oldfieldname": "warehouse",
"oldfieldtype": "Link",
"options": "Warehouse",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{ {
"allow_bulk_edit": 0, "fieldname": "item_code",
"allow_in_quick_entry": 0, "fieldtype": "Link",
"allow_on_submit": 0, "in_filter": 1,
"bold": 0, "in_list_view": 1,
"collapsible": 0, "in_standard_filter": 1,
"columns": 0, "label": "Item Code",
"fieldname": "item_code", "oldfieldname": "item_code",
"fieldtype": "Link", "oldfieldtype": "Link",
"hidden": 0, "options": "Item",
"ignore_user_permissions": 0, "read_only": 1,
"ignore_xss_filter": 0, "search_index": 1
"in_filter": 1, },
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Item Code",
"length": 0,
"no_copy": 0,
"oldfieldname": "item_code",
"oldfieldtype": "Link",
"options": "Item",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{ {
"allow_bulk_edit": 0, "default": "0.00",
"allow_in_quick_entry": 0, "fieldname": "reserved_qty",
"allow_on_submit": 0, "fieldtype": "Float",
"bold": 0, "in_list_view": 1,
"collapsible": 0, "label": "Reserved Quantity",
"columns": 0, "oldfieldname": "reserved_qty",
"default": "0.00", "oldfieldtype": "Currency",
"fieldname": "reserved_qty", "read_only": 1
"fieldtype": "Float", },
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Reserved Quantity",
"length": 0,
"no_copy": 0,
"oldfieldname": "reserved_qty",
"oldfieldtype": "Currency",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{ {
"allow_bulk_edit": 0, "default": "0.00",
"allow_in_quick_entry": 0, "fieldname": "actual_qty",
"allow_on_submit": 0, "fieldtype": "Float",
"bold": 0, "in_filter": 1,
"collapsible": 0, "in_list_view": 1,
"columns": 0, "label": "Actual Quantity",
"default": "0.00", "oldfieldname": "actual_qty",
"fieldname": "actual_qty", "oldfieldtype": "Currency",
"fieldtype": "Float", "read_only": 1
"hidden": 0, },
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 1,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Actual Quantity",
"length": 0,
"no_copy": 0,
"oldfieldname": "actual_qty",
"oldfieldtype": "Currency",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{ {
"allow_bulk_edit": 0, "default": "0.00",
"allow_in_quick_entry": 0, "fieldname": "ordered_qty",
"allow_on_submit": 0, "fieldtype": "Float",
"bold": 0, "in_list_view": 1,
"collapsible": 0, "label": "Ordered Quantity",
"columns": 0, "oldfieldname": "ordered_qty",
"default": "0.00", "oldfieldtype": "Currency",
"fieldname": "ordered_qty", "read_only": 1
"fieldtype": "Float", },
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Ordered Quantity",
"length": 0,
"no_copy": 0,
"oldfieldname": "ordered_qty",
"oldfieldtype": "Currency",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{ {
"allow_bulk_edit": 0, "default": "0.00",
"allow_in_quick_entry": 0, "fieldname": "indented_qty",
"allow_on_submit": 0, "fieldtype": "Float",
"bold": 0, "label": "Requested Quantity",
"collapsible": 0, "oldfieldname": "indented_qty",
"columns": 0, "oldfieldtype": "Currency",
"default": "0.00", "read_only": 1
"fieldname": "indented_qty", },
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Requested Quantity",
"length": 0,
"no_copy": 0,
"oldfieldname": "indented_qty",
"oldfieldtype": "Currency",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{ {
"allow_bulk_edit": 0, "fieldname": "planned_qty",
"allow_in_quick_entry": 0, "fieldtype": "Float",
"allow_on_submit": 0, "label": "Planned Qty",
"bold": 0, "oldfieldname": "planned_qty",
"collapsible": 0, "oldfieldtype": "Currency",
"columns": 0, "read_only": 1
"fieldname": "planned_qty", },
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Planned Qty",
"length": 0,
"no_copy": 0,
"oldfieldname": "planned_qty",
"oldfieldtype": "Currency",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{ {
"allow_bulk_edit": 0, "fieldname": "projected_qty",
"allow_in_quick_entry": 0, "fieldtype": "Float",
"allow_on_submit": 0, "label": "Projected Qty",
"bold": 0, "oldfieldname": "projected_qty",
"collapsible": 0, "oldfieldtype": "Currency",
"columns": 0, "read_only": 1
"fieldname": "projected_qty", },
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Projected Qty",
"length": 0,
"no_copy": 0,
"oldfieldname": "projected_qty",
"oldfieldtype": "Currency",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{ {
"allow_bulk_edit": 0, "fieldname": "reserved_qty_for_production",
"allow_in_quick_entry": 0, "fieldtype": "Float",
"allow_on_submit": 0, "label": "Reserved Qty for Production",
"bold": 0, "read_only": 1
"collapsible": 0, },
"columns": 0,
"fieldname": "reserved_qty_for_production",
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Reserved Qty for Production",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{ {
"allow_bulk_edit": 0, "fieldname": "reserved_qty_for_sub_contract",
"allow_in_quick_entry": 0, "fieldtype": "Float",
"allow_on_submit": 0, "label": "Reserved Qty for sub contract"
"bold": 0, },
"collapsible": 0,
"columns": 0,
"fieldname": "reserved_qty_for_sub_contract",
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Reserved Qty for sub contract",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{ {
"allow_bulk_edit": 0, "fieldname": "ma_rate",
"allow_in_quick_entry": 0, "fieldtype": "Float",
"allow_on_submit": 0, "hidden": 1,
"bold": 0, "label": "Moving Average Rate",
"collapsible": 0, "oldfieldname": "ma_rate",
"columns": 0, "oldfieldtype": "Currency",
"fieldname": "ma_rate", "print_hide": 1,
"fieldtype": "Float", "read_only": 1,
"hidden": 1, "report_hide": 1
"ignore_user_permissions": 0, },
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Moving Average Rate",
"length": 0,
"no_copy": 0,
"oldfieldname": "ma_rate",
"oldfieldtype": "Currency",
"permlevel": 0,
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 1,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{ {
"allow_bulk_edit": 0, "fieldname": "stock_uom",
"allow_in_quick_entry": 0, "fieldtype": "Link",
"allow_on_submit": 0, "in_filter": 1,
"bold": 0, "label": "UOM",
"collapsible": 0, "oldfieldname": "stock_uom",
"columns": 0, "oldfieldtype": "Data",
"fieldname": "stock_uom", "options": "UOM",
"fieldtype": "Link", "read_only": 1
"hidden": 0, },
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 1,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "UOM",
"length": 0,
"no_copy": 0,
"oldfieldname": "stock_uom",
"oldfieldtype": "Data",
"options": "UOM",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{ {
"allow_bulk_edit": 0, "fieldname": "fcfs_rate",
"allow_in_quick_entry": 0, "fieldtype": "Float",
"allow_on_submit": 0, "hidden": 1,
"bold": 0, "label": "FCFS Rate",
"collapsible": 0, "oldfieldname": "fcfs_rate",
"columns": 0, "oldfieldtype": "Currency",
"fieldname": "fcfs_rate", "print_hide": 1,
"fieldtype": "Float", "read_only": 1,
"hidden": 1, "report_hide": 1
"ignore_user_permissions": 0, },
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "FCFS Rate",
"length": 0,
"no_copy": 0,
"oldfieldname": "fcfs_rate",
"oldfieldtype": "Currency",
"permlevel": 0,
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 1,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{ {
"allow_bulk_edit": 0, "fieldname": "valuation_rate",
"allow_in_quick_entry": 0, "fieldtype": "Float",
"allow_on_submit": 0, "label": "Valuation Rate",
"bold": 0, "oldfieldname": "valuation_rate",
"collapsible": 0, "oldfieldtype": "Currency",
"columns": 0, "read_only": 1
"fieldname": "valuation_rate", },
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Valuation Rate",
"length": 0,
"no_copy": 0,
"oldfieldname": "valuation_rate",
"oldfieldtype": "Currency",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{ {
"allow_bulk_edit": 0, "fieldname": "stock_value",
"allow_in_quick_entry": 0, "fieldtype": "Float",
"allow_on_submit": 0, "label": "Stock Value",
"bold": 0, "oldfieldname": "stock_value",
"collapsible": 0, "oldfieldtype": "Currency",
"columns": 0, "read_only": 1
"fieldname": "stock_value",
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Stock Value",
"length": 0,
"no_copy": 0,
"oldfieldname": "stock_value",
"oldfieldtype": "Currency",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
} }
], ],
"has_web_view": 0, "hide_toolbar": 1,
"hide_heading": 0, "idx": 1,
"hide_toolbar": 1, "in_create": 1,
"idx": 1, "modified": "2019-11-18 18:34:59.456882",
"image_view": 0, "modified_by": "Administrator",
"in_create": 1, "module": "Stock",
"is_submittable": 0, "name": "Bin",
"issingle": 0, "owner": "Administrator",
"istable": 0,
"max_attachments": 0,
"modified": "2018-08-21 16:15:39.356230",
"modified_by": "Administrator",
"module": "Stock",
"name": "Bin",
"owner": "Administrator",
"permissions": [ "permissions": [
{ {
"amend": 0, "email": 1,
"cancel": 0, "print": 1,
"create": 0, "read": 1,
"delete": 0, "report": 1,
"email": 1, "role": "Sales User"
"export": 0, },
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Sales User",
"set_user_permissions": 0,
"share": 0,
"submit": 0,
"write": 0
},
{ {
"amend": 0, "email": 1,
"cancel": 0, "print": 1,
"create": 0, "read": 1,
"delete": 0, "report": 1,
"email": 1, "role": "Purchase User"
"export": 0, },
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Purchase User",
"set_user_permissions": 0,
"share": 0,
"submit": 0,
"write": 0
},
{ {
"amend": 0, "email": 1,
"cancel": 0, "print": 1,
"create": 0, "read": 1,
"delete": 0, "report": 1,
"email": 1, "role": "Stock User"
"export": 0,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Stock User",
"set_user_permissions": 0,
"share": 0,
"submit": 0,
"write": 0
} }
], ],
"quick_entry": 1, "quick_entry": 1,
"read_only": 0, "search_fields": "item_code,warehouse",
"read_only_onload": 0, "sort_order": "ASC"
"search_fields": "item_code,warehouse",
"show_name_in_global_search": 0,
"sort_order": "ASC",
"track_changes": 0,
"track_seen": 0,
"track_views": 0
} }

View File

@ -16,6 +16,7 @@ class PriceList(Document):
def on_update(self): def on_update(self):
self.set_default_if_missing() self.set_default_if_missing()
self.update_item_price() self.update_item_price()
self.delete_price_list_details_key()
def set_default_if_missing(self): def set_default_if_missing(self):
if cint(self.selling): if cint(self.selling):
@ -32,6 +33,8 @@ class PriceList(Document):
(self.currency, cint(self.buying), cint(self.selling), self.name)) (self.currency, cint(self.buying), cint(self.selling), self.name))
def on_trash(self): def on_trash(self):
self.delete_price_list_details_key()
def _update_default_price_list(module): def _update_default_price_list(module):
b = frappe.get_doc(module + " Settings") b = frappe.get_doc(module + " Settings")
price_list_fieldname = module.lower() + "_price_list" price_list_fieldname = module.lower() + "_price_list"
@ -43,3 +46,20 @@ class PriceList(Document):
for module in ["Selling", "Buying"]: for module in ["Selling", "Buying"]:
_update_default_price_list(module) _update_default_price_list(module)
def delete_price_list_details_key(self):
frappe.cache().hdel("price_list_details", self.name)
def get_price_list_details(price_list):
price_list_details = frappe.cache().hget("price_list_details", price_list)
if not price_list_details:
price_list_details = frappe.get_cached_value("Price List", price_list,
["currency", "price_not_uom_dependent", "enabled"], as_dict=1)
if not price_list_details or not price_list_details.get("enabled"):
throw(_("Price List {0} is disabled or does not exist").format(price_list))
frappe.cache().hset("price_list_details", price_list, price_list_details)
return price_list_details or {}

View File

@ -12,6 +12,7 @@ from frappe.model.meta import get_field_precision
from erpnext.stock.doctype.batch.batch import get_batch_no from erpnext.stock.doctype.batch.batch import get_batch_no
from erpnext import get_company_currency from erpnext import get_company_currency
from erpnext.stock.doctype.item.item import get_item_defaults, get_uom_conv_factor from erpnext.stock.doctype.item.item import get_item_defaults, get_uom_conv_factor
from erpnext.stock.doctype.price_list.price_list import get_price_list_details
from erpnext.setup.doctype.item_group.item_group import get_item_group_defaults from erpnext.setup.doctype.item_group.item_group import get_item_group_defaults
from erpnext.setup.doctype.brand.brand import get_brand_defaults from erpnext.setup.doctype.brand.brand import get_brand_defaults
from erpnext.stock.doctype.item_manufacturer.item_manufacturer import get_item_manufacturer_part_no from erpnext.stock.doctype.item_manufacturer.item_manufacturer import get_item_manufacturer_part_no
@ -22,7 +23,7 @@ sales_doctypes = ['Quotation', 'Sales Order', 'Delivery Note', 'Sales Invoice']
purchase_doctypes = ['Material Request', 'Supplier Quotation', 'Purchase Order', 'Purchase Receipt', 'Purchase Invoice'] purchase_doctypes = ['Material Request', 'Supplier Quotation', 'Purchase Order', 'Purchase Receipt', 'Purchase Invoice']
@frappe.whitelist() @frappe.whitelist()
def get_item_details(args, doc=None, overwrite_warehouse=True): def get_item_details(args, doc=None, for_validate=False, overwrite_warehouse=True):
""" """
args = { args = {
"item_code": "", "item_code": "",
@ -74,7 +75,9 @@ def get_item_details(args, doc=None, overwrite_warehouse=True):
if args.get(key) is None: if args.get(key) is None:
args[key] = value args[key] = value
data = get_pricing_rule_for_item(args, out.price_list_rate, doc) data = get_pricing_rule_for_item(args, out.price_list_rate,
doc, for_validate=for_validate)
out.update(data) out.update(data)
update_stock(args, out) update_stock(args, out)
@ -479,7 +482,6 @@ def get_price_list_rate(args, item_doc, out):
if meta.get_field("currency") or args.get('currency'): if meta.get_field("currency") or args.get('currency'):
pl_details = get_price_list_currency_and_exchange_rate(args) pl_details = get_price_list_currency_and_exchange_rate(args)
args.update(pl_details) args.update(pl_details)
validate_price_list(args)
if meta.get_field("currency"): if meta.get_field("currency"):
validate_conversion_rate(args, meta) validate_conversion_rate(args, meta)
@ -634,14 +636,6 @@ def check_packing_list(price_list_rate_name, desired_qty, item_code):
return flag return flag
def validate_price_list(args):
if args.get("price_list"):
if not frappe.db.get_value("Price List",
{"name": args.price_list, args.transaction_type: 1, "enabled": 1}):
throw(_("Price List {0} is disabled or does not exist").format(args.price_list))
elif args.get("customer"):
throw(_("Price List not selected"))
def validate_conversion_rate(args, meta): def validate_conversion_rate(args, meta):
from erpnext.controllers.accounts_controller import validate_conversion_rate from erpnext.controllers.accounts_controller import validate_conversion_rate
@ -905,27 +899,6 @@ def apply_price_list_on_item(args):
return item_details return item_details
def get_price_list_currency(price_list):
if price_list:
result = frappe.db.get_value("Price List", {"name": price_list,
"enabled": 1}, ["name", "currency"], as_dict=True)
if not result:
throw(_("Price List {0} is disabled or does not exist").format(price_list))
return result.currency
def get_price_list_uom_dependant(price_list):
if price_list:
result = frappe.db.get_value("Price List", {"name": price_list,
"enabled": 1}, ["name", "price_not_uom_dependent"], as_dict=True)
if not result:
throw(_("Price List {0} is disabled or does not exist").format(price_list))
return not result.price_not_uom_dependent
def get_price_list_currency_and_exchange_rate(args): def get_price_list_currency_and_exchange_rate(args):
if not args.price_list: if not args.price_list:
return {} return {}
@ -935,8 +908,11 @@ def get_price_list_currency_and_exchange_rate(args):
elif args.doctype in ['Purchase Order', 'Purchase Receipt', 'Purchase Invoice']: elif args.doctype in ['Purchase Order', 'Purchase Receipt', 'Purchase Invoice']:
args.update({"exchange_rate": "for_buying"}) args.update({"exchange_rate": "for_buying"})
price_list_currency = get_price_list_currency(args.price_list) price_list_details = get_price_list_details(args.price_list)
price_list_uom_dependant = get_price_list_uom_dependant(args.price_list)
price_list_currency = price_list_details.get("currency")
price_list_uom_dependant = price_list_details.get("price_list_uom_dependant")
plc_conversion_rate = args.plc_conversion_rate plc_conversion_rate = args.plc_conversion_rate
company_currency = get_company_currency(args.company) company_currency = get_company_currency(args.company)