Fixes saving of Sales Order and fetching Prices frappe/frappe#478
This commit is contained in:
parent
13ae548ff6
commit
bd67e87921
@ -260,8 +260,7 @@ class SalesInvoice(SellingController):
|
||||
"""Validate Fixed Asset and whether Income Account Entered Exists"""
|
||||
for d in self.get('entries'):
|
||||
item = frappe.db.sql("""select name,is_asset_item,is_sales_item from `tabItem`
|
||||
where name = %s and (ifnull(end_of_life,'')='' or end_of_life = '0000-00-00'
|
||||
or end_of_life > now())""", d.item_code)
|
||||
where name = %s and (ifnull(end_of_life,'')='' or end_of_life > now())""", d.item_code)
|
||||
acc = frappe.db.sql("""select account_type from `tabAccount`
|
||||
where name = %s and docstatus != 2""", d.income_account)
|
||||
if not acc:
|
||||
|
@ -87,7 +87,7 @@ class AccountsController(TransactionBase):
|
||||
"""set missing item values"""
|
||||
from erpnext.stock.get_item_details import get_item_details
|
||||
if hasattr(self, "fname"):
|
||||
parent_dict = {}
|
||||
parent_dict = {"doctype": self.doctype}
|
||||
for fieldname in self.meta.get_valid_columns():
|
||||
parent_dict[fieldname] = self.get(fieldname)
|
||||
|
||||
|
@ -16,47 +16,47 @@ def get_filters_cond(doctype, filters, conditions):
|
||||
flt.append([doctype, f[0], '!=', f[1][1:]])
|
||||
else:
|
||||
flt.append([doctype, f[0], '=', f[1]])
|
||||
|
||||
|
||||
query = DatabaseQuery(doctype)
|
||||
query.filters = flt
|
||||
query.conditions = conditions
|
||||
query.build_filter_conditions()
|
||||
|
||||
cond = ' and ' + ' and '.join(query.conditions)
|
||||
|
||||
cond = ' and ' + ' and '.join(query.conditions)
|
||||
else:
|
||||
cond = ''
|
||||
return cond
|
||||
|
||||
# searches for active employees
|
||||
def employee_query(doctype, txt, searchfield, start, page_len, filters):
|
||||
return frappe.db.sql("""select name, employee_name from `tabEmployee`
|
||||
where status = 'Active'
|
||||
and docstatus < 2
|
||||
and (%(key)s like "%(txt)s"
|
||||
or employee_name like "%(txt)s")
|
||||
return frappe.db.sql("""select name, employee_name from `tabEmployee`
|
||||
where status = 'Active'
|
||||
and docstatus < 2
|
||||
and (%(key)s like "%(txt)s"
|
||||
or employee_name like "%(txt)s")
|
||||
%(mcond)s
|
||||
order by
|
||||
case when name like "%(txt)s" then 0 else 1 end,
|
||||
case when employee_name like "%(txt)s" then 0 else 1 end,
|
||||
name
|
||||
limit %(start)s, %(page_len)s""" % {'key': searchfield, 'txt': "%%%s%%" % txt,
|
||||
order by
|
||||
case when name like "%(txt)s" then 0 else 1 end,
|
||||
case when employee_name like "%(txt)s" then 0 else 1 end,
|
||||
name
|
||||
limit %(start)s, %(page_len)s""" % {'key': searchfield, 'txt': "%%%s%%" % txt,
|
||||
'mcond':get_match_cond(doctype), 'start': start, 'page_len': page_len})
|
||||
|
||||
# searches for leads which are not converted
|
||||
def lead_query(doctype, txt, searchfield, start, page_len, filters):
|
||||
def lead_query(doctype, txt, searchfield, start, page_len, filters):
|
||||
return frappe.db.sql("""select name, lead_name, company_name from `tabLead`
|
||||
where docstatus < 2
|
||||
and ifnull(status, '') != 'Converted'
|
||||
and (%(key)s like "%(txt)s"
|
||||
or lead_name like "%(txt)s"
|
||||
or company_name like "%(txt)s")
|
||||
where docstatus < 2
|
||||
and ifnull(status, '') != 'Converted'
|
||||
and (%(key)s like "%(txt)s"
|
||||
or lead_name like "%(txt)s"
|
||||
or company_name like "%(txt)s")
|
||||
%(mcond)s
|
||||
order by
|
||||
case when name like "%(txt)s" then 0 else 1 end,
|
||||
case when lead_name like "%(txt)s" then 0 else 1 end,
|
||||
case when company_name like "%(txt)s" then 0 else 1 end,
|
||||
lead_name asc
|
||||
limit %(start)s, %(page_len)s""" % {'key': searchfield, 'txt': "%%%s%%" % txt,
|
||||
order by
|
||||
case when name like "%(txt)s" then 0 else 1 end,
|
||||
case when lead_name like "%(txt)s" then 0 else 1 end,
|
||||
case when company_name like "%(txt)s" then 0 else 1 end,
|
||||
lead_name asc
|
||||
limit %(start)s, %(page_len)s""" % {'key': searchfield, 'txt': "%%%s%%" % txt,
|
||||
'mcond':get_match_cond(doctype), 'start': start, 'page_len': page_len})
|
||||
|
||||
# searches for customer
|
||||
@ -68,82 +68,82 @@ def customer_query(doctype, txt, searchfield, start, page_len, filters):
|
||||
else:
|
||||
fields = ["name", "customer_name", "customer_group", "territory"]
|
||||
|
||||
fields = ", ".join(fields)
|
||||
fields = ", ".join(fields)
|
||||
|
||||
return frappe.db.sql("""select %(field)s from `tabCustomer`
|
||||
where docstatus < 2
|
||||
and (%(key)s like "%(txt)s"
|
||||
or customer_name like "%(txt)s")
|
||||
return frappe.db.sql("""select %(field)s from `tabCustomer`
|
||||
where docstatus < 2
|
||||
and (%(key)s like "%(txt)s"
|
||||
or customer_name like "%(txt)s")
|
||||
%(mcond)s
|
||||
order by
|
||||
case when name like "%(txt)s" then 0 else 1 end,
|
||||
case when customer_name like "%(txt)s" then 0 else 1 end,
|
||||
name, customer_name
|
||||
limit %(start)s, %(page_len)s""" % {'field': fields,'key': searchfield,
|
||||
'txt': "%%%s%%" % txt, 'mcond':get_match_cond(doctype),
|
||||
order by
|
||||
case when name like "%(txt)s" then 0 else 1 end,
|
||||
case when customer_name like "%(txt)s" then 0 else 1 end,
|
||||
name, customer_name
|
||||
limit %(start)s, %(page_len)s""" % {'field': fields,'key': searchfield,
|
||||
'txt': "%%%s%%" % txt, 'mcond':get_match_cond(doctype),
|
||||
'start': start, 'page_len': page_len})
|
||||
|
||||
# searches for supplier
|
||||
def supplier_query(doctype, txt, searchfield, start, page_len, filters):
|
||||
supp_master_name = frappe.defaults.get_user_default("supp_master_name")
|
||||
if supp_master_name == "Supplier Name":
|
||||
if supp_master_name == "Supplier Name":
|
||||
fields = ["name", "supplier_type"]
|
||||
else:
|
||||
else:
|
||||
fields = ["name", "supplier_name", "supplier_type"]
|
||||
fields = ", ".join(fields)
|
||||
fields = ", ".join(fields)
|
||||
|
||||
return frappe.db.sql("""select %(field)s from `tabSupplier`
|
||||
where docstatus < 2
|
||||
and (%(key)s like "%(txt)s"
|
||||
or supplier_name like "%(txt)s")
|
||||
return frappe.db.sql("""select %(field)s from `tabSupplier`
|
||||
where docstatus < 2
|
||||
and (%(key)s like "%(txt)s"
|
||||
or supplier_name like "%(txt)s")
|
||||
%(mcond)s
|
||||
order by
|
||||
case when name like "%(txt)s" then 0 else 1 end,
|
||||
case when supplier_name like "%(txt)s" then 0 else 1 end,
|
||||
name, supplier_name
|
||||
limit %(start)s, %(page_len)s """ % {'field': fields,'key': searchfield,
|
||||
'txt': "%%%s%%" % txt, 'mcond':get_match_cond(doctype), 'start': start,
|
||||
order by
|
||||
case when name like "%(txt)s" then 0 else 1 end,
|
||||
case when supplier_name like "%(txt)s" then 0 else 1 end,
|
||||
name, supplier_name
|
||||
limit %(start)s, %(page_len)s """ % {'field': fields,'key': searchfield,
|
||||
'txt': "%%%s%%" % txt, 'mcond':get_match_cond(doctype), 'start': start,
|
||||
'page_len': page_len})
|
||||
|
||||
|
||||
def tax_account_query(doctype, txt, searchfield, start, page_len, filters):
|
||||
tax_accounts = frappe.db.sql("""select name, parent_account from tabAccount
|
||||
where tabAccount.docstatus!=2
|
||||
tax_accounts = frappe.db.sql("""select name, parent_account from tabAccount
|
||||
where tabAccount.docstatus!=2
|
||||
and account_type in (%s)
|
||||
and group_or_ledger = 'Ledger'
|
||||
and company = %s
|
||||
and `%s` LIKE %s
|
||||
limit %s, %s""" %
|
||||
(", ".join(['%s']*len(filters.get("account_type"))), "%s", searchfield, "%s", "%s", "%s"),
|
||||
tuple(filters.get("account_type") + [filters.get("company"), "%%%s%%" % txt,
|
||||
limit %s, %s""" %
|
||||
(", ".join(['%s']*len(filters.get("account_type"))), "%s", searchfield, "%s", "%s", "%s"),
|
||||
tuple(filters.get("account_type") + [filters.get("company"), "%%%s%%" % txt,
|
||||
start, page_len]))
|
||||
if not tax_accounts:
|
||||
tax_accounts = frappe.db.sql("""select name, parent_account from tabAccount
|
||||
where tabAccount.docstatus!=2 and group_or_ledger = 'Ledger'
|
||||
and company = %s and `%s` LIKE %s limit %s, %s"""
|
||||
% ("%s", searchfield, "%s", "%s", "%s"),
|
||||
tax_accounts = frappe.db.sql("""select name, parent_account from tabAccount
|
||||
where tabAccount.docstatus!=2 and group_or_ledger = 'Ledger'
|
||||
and company = %s and `%s` LIKE %s limit %s, %s"""
|
||||
% ("%s", searchfield, "%s", "%s", "%s"),
|
||||
(filters.get("company"), "%%%s%%" % txt, start, page_len))
|
||||
|
||||
|
||||
return tax_accounts
|
||||
|
||||
def item_query(doctype, txt, searchfield, start, page_len, filters):
|
||||
from frappe.utils import nowdate
|
||||
|
||||
|
||||
conditions = []
|
||||
|
||||
return frappe.db.sql("""select tabItem.name,
|
||||
if(length(tabItem.item_name) > 40,
|
||||
concat(substr(tabItem.item_name, 1, 40), "..."), item_name) as item_name,
|
||||
return frappe.db.sql("""select tabItem.name,
|
||||
if(length(tabItem.item_name) > 40,
|
||||
concat(substr(tabItem.item_name, 1, 40), "..."), item_name) as item_name,
|
||||
if(length(tabItem.description) > 40, \
|
||||
concat(substr(tabItem.description, 1, 40), "..."), description) as decription
|
||||
from tabItem
|
||||
from tabItem
|
||||
where tabItem.docstatus < 2
|
||||
and (ifnull(tabItem.end_of_life, '') = '' or tabItem.end_of_life > %(today)s)
|
||||
and (tabItem.`{key}` LIKE %(txt)s
|
||||
or tabItem.item_name LIKE %(txt)s)
|
||||
or tabItem.item_name LIKE %(txt)s)
|
||||
{fcond} {mcond}
|
||||
limit %(start)s, %(page_len)s """.format(key=searchfield,
|
||||
fcond=get_filters_cond(doctype, filters, conditions),
|
||||
mcond=get_match_cond(doctype)),
|
||||
mcond=get_match_cond(doctype)),
|
||||
{
|
||||
"today": nowdate(),
|
||||
"txt": "%%%s%%" % txt,
|
||||
@ -152,38 +152,38 @@ def item_query(doctype, txt, searchfield, start, page_len, filters):
|
||||
})
|
||||
|
||||
def bom(doctype, txt, searchfield, start, page_len, filters):
|
||||
conditions = []
|
||||
conditions = []
|
||||
|
||||
return frappe.db.sql("""select tabBOM.name, tabBOM.item
|
||||
from tabBOM
|
||||
where tabBOM.docstatus=1
|
||||
and tabBOM.is_active=1
|
||||
and tabBOM.%(key)s like "%(txt)s"
|
||||
%(fcond)s %(mcond)s
|
||||
limit %(start)s, %(page_len)s """ % {'key': searchfield, 'txt': "%%%s%%" % txt,
|
||||
'fcond': get_filters_cond(doctype, filters, conditions),
|
||||
return frappe.db.sql("""select tabBOM.name, tabBOM.item
|
||||
from tabBOM
|
||||
where tabBOM.docstatus=1
|
||||
and tabBOM.is_active=1
|
||||
and tabBOM.%(key)s like "%(txt)s"
|
||||
%(fcond)s %(mcond)s
|
||||
limit %(start)s, %(page_len)s """ % {'key': searchfield, 'txt': "%%%s%%" % txt,
|
||||
'fcond': get_filters_cond(doctype, filters, conditions),
|
||||
'mcond':get_match_cond(doctype), 'start': start, 'page_len': page_len})
|
||||
|
||||
def get_project_name(doctype, txt, searchfield, start, page_len, filters):
|
||||
cond = ''
|
||||
if filters['customer']:
|
||||
cond = '(`tabProject`.customer = "' + filters['customer'] + '" or ifnull(`tabProject`.customer,"")="") and'
|
||||
|
||||
return frappe.db.sql("""select `tabProject`.name from `tabProject`
|
||||
where `tabProject`.status not in ("Completed", "Cancelled")
|
||||
and %(cond)s `tabProject`.name like "%(txt)s" %(mcond)s
|
||||
order by `tabProject`.name asc
|
||||
limit %(start)s, %(page_len)s """ % {'cond': cond,'txt': "%%%s%%" % txt,
|
||||
|
||||
return frappe.db.sql("""select `tabProject`.name from `tabProject`
|
||||
where `tabProject`.status not in ("Completed", "Cancelled")
|
||||
and %(cond)s `tabProject`.name like "%(txt)s" %(mcond)s
|
||||
order by `tabProject`.name asc
|
||||
limit %(start)s, %(page_len)s """ % {'cond': cond,'txt': "%%%s%%" % txt,
|
||||
'mcond':get_match_cond(doctype),'start': start, 'page_len': page_len})
|
||||
|
||||
|
||||
def get_delivery_notes_to_be_billed(doctype, txt, searchfield, start, page_len, filters):
|
||||
return frappe.db.sql("""select `tabDelivery Note`.name, `tabDelivery Note`.customer_name
|
||||
from `tabDelivery Note`
|
||||
where `tabDelivery Note`.`%(key)s` like %(txt)s and
|
||||
from `tabDelivery Note`
|
||||
where `tabDelivery Note`.`%(key)s` like %(txt)s and
|
||||
`tabDelivery Note`.docstatus = 1 %(fcond)s and
|
||||
(ifnull((select sum(qty) from `tabDelivery Note Item` where
|
||||
(ifnull((select sum(qty) from `tabDelivery Note Item` where
|
||||
`tabDelivery Note Item`.parent=`tabDelivery Note`.name), 0) >
|
||||
ifnull((select sum(qty) from `tabSales Invoice Item` where
|
||||
ifnull((select sum(qty) from `tabSales Invoice Item` where
|
||||
`tabSales Invoice Item`.docstatus = 1 and
|
||||
`tabSales Invoice Item`.delivery_note=`tabDelivery Note`.name), 0))
|
||||
%(mcond)s order by `tabDelivery Note`.`%(key)s` asc
|
||||
@ -198,30 +198,30 @@ def get_batch_no(doctype, txt, searchfield, start, page_len, filters):
|
||||
from erpnext.controllers.queries import get_match_cond
|
||||
|
||||
if filters.has_key('warehouse'):
|
||||
return frappe.db.sql("""select batch_no from `tabStock Ledger Entry` sle
|
||||
where item_code = '%(item_code)s'
|
||||
and warehouse = '%(warehouse)s'
|
||||
and batch_no like '%(txt)s'
|
||||
and exists(select * from `tabBatch`
|
||||
where name = sle.batch_no
|
||||
and (ifnull(expiry_date, '')='' or expiry_date >= '%(posting_date)s')
|
||||
and docstatus != 2)
|
||||
return frappe.db.sql("""select batch_no from `tabStock Ledger Entry` sle
|
||||
where item_code = '%(item_code)s'
|
||||
and warehouse = '%(warehouse)s'
|
||||
and batch_no like '%(txt)s'
|
||||
and exists(select * from `tabBatch`
|
||||
where name = sle.batch_no
|
||||
and (ifnull(expiry_date, '')='' or expiry_date >= '%(posting_date)s')
|
||||
and docstatus != 2)
|
||||
%(mcond)s
|
||||
group by batch_no having sum(actual_qty) > 0
|
||||
order by batch_no desc
|
||||
limit %(start)s, %(page_len)s """ % {'item_code': filters['item_code'],
|
||||
'warehouse': filters['warehouse'], 'posting_date': filters['posting_date'],
|
||||
'txt': "%%%s%%" % txt, 'mcond':get_match_cond(doctype),
|
||||
group by batch_no having sum(actual_qty) > 0
|
||||
order by batch_no desc
|
||||
limit %(start)s, %(page_len)s """ % {'item_code': filters['item_code'],
|
||||
'warehouse': filters['warehouse'], 'posting_date': filters['posting_date'],
|
||||
'txt': "%%%s%%" % txt, 'mcond':get_match_cond(doctype),
|
||||
'start': start, 'page_len': page_len})
|
||||
else:
|
||||
return frappe.db.sql("""select name from tabBatch
|
||||
where docstatus != 2
|
||||
and item = '%(item_code)s'
|
||||
return frappe.db.sql("""select name from tabBatch
|
||||
where docstatus != 2
|
||||
and item = '%(item_code)s'
|
||||
and (ifnull(expiry_date, '')='' or expiry_date >= '%(posting_date)s')
|
||||
and name like '%(txt)s'
|
||||
%(mcond)s
|
||||
order by name desc
|
||||
limit %(start)s, %(page_len)s""" % {'item_code': filters['item_code'],
|
||||
'posting_date': filters['posting_date'], 'txt': "%%%s%%" % txt,
|
||||
'mcond':get_match_cond(doctype),'start': start,
|
||||
and name like '%(txt)s'
|
||||
%(mcond)s
|
||||
order by name desc
|
||||
limit %(start)s, %(page_len)s""" % {'item_code': filters['item_code'],
|
||||
'posting_date': filters['posting_date'], 'txt': "%%%s%%" % txt,
|
||||
'mcond':get_match_cond(doctype),'start': start,
|
||||
'page_len': page_len})
|
||||
|
@ -329,7 +329,7 @@ def make_sales_invoice(source_name, target_doc=None):
|
||||
def update_item(source, target, source_parent):
|
||||
target.amount = flt(source.amount) - flt(source.billed_amt)
|
||||
target.base_amount = target.amount * flt(source_parent.conversion_rate)
|
||||
target.qty = source.rate and target.amount / flt(source.rate) or obj.qty
|
||||
target.qty = source.rate and target.amount / flt(source.rate) or source.qty
|
||||
|
||||
doclist = get_mapped_doc("Sales Order", source_name, {
|
||||
"Sales Order": {
|
||||
|
@ -20,22 +20,22 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({
|
||||
this.setup_queries();
|
||||
this.toggle_editable_price_list_rate();
|
||||
},
|
||||
|
||||
|
||||
setup_queries: function() {
|
||||
var me = this;
|
||||
|
||||
|
||||
this.frm.add_fetch("sales_partner", "commission_rate", "commission_rate");
|
||||
|
||||
$.each([["customer_address", "customer_filter"],
|
||||
|
||||
$.each([["customer_address", "customer_filter"],
|
||||
["shipping_address_name", "customer_filter"],
|
||||
["contact_person", "customer_filter"],
|
||||
["customer", "customer"],
|
||||
["lead", "lead"]],
|
||||
["contact_person", "customer_filter"],
|
||||
["customer", "customer"],
|
||||
["lead", "lead"]],
|
||||
function(i, opts) {
|
||||
if(me.frm.fields_dict[opts[0]])
|
||||
if(me.frm.fields_dict[opts[0]])
|
||||
me.frm.set_query(opts[0], erpnext.queries[opts[1]]);
|
||||
});
|
||||
|
||||
|
||||
if(this.frm.fields_dict.taxes_and_charges) {
|
||||
this.frm.set_query("taxes_and_charges", function() {
|
||||
return {
|
||||
@ -52,11 +52,11 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({
|
||||
return { filters: { selling: 1 } };
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
if(!this.fname) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if(this.frm.fields_dict[this.fname].grid.get_field('item_code')) {
|
||||
this.frm.set_query("item_code", this.fname, function() {
|
||||
return {
|
||||
@ -67,7 +67,7 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
if(this.frm.fields_dict[this.fname].grid.get_field('batch_no')) {
|
||||
this.frm.set_query("batch_no", this.fname, function(doc, cdt, cdn) {
|
||||
var item = frappe.get_doc(cdt, cdn);
|
||||
@ -79,7 +79,7 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({
|
||||
'posting_date': me.frm.doc.posting_date,
|
||||
}
|
||||
if(item.warehouse) filters["warehouse"] = item.warehouse
|
||||
|
||||
|
||||
return {
|
||||
query : "erpnext.controllers.queries.get_batch_no",
|
||||
filters: filters
|
||||
@ -87,56 +87,56 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
if(this.frm.fields_dict.sales_team && this.frm.fields_dict.sales_team.grid.get_field("sales_person")) {
|
||||
this.frm.set_query("sales_person", "sales_team", erpnext.queries.not_a_group_filter);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
refresh: function() {
|
||||
this._super();
|
||||
this.frm.toggle_display("customer_name",
|
||||
this.frm.toggle_display("customer_name",
|
||||
(this.frm.doc.customer_name && this.frm.doc.customer_name!==this.frm.doc.customer));
|
||||
if(this.frm.fields_dict.packing_details) {
|
||||
var packing_list_exists = (this.frm.doc.packing_details || []).length;
|
||||
this.frm.toggle_display("packing_list", packing_list_exists ? true : false);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
customer: function() {
|
||||
erpnext.utils.get_party_details(this.frm);
|
||||
},
|
||||
|
||||
|
||||
customer_address: function() {
|
||||
erpnext.utils.get_address_display(this.frm, "customer_address");
|
||||
},
|
||||
|
||||
|
||||
shipping_address_name: function() {
|
||||
erpnext.utils.get_address_display(this.frm, "shipping_address_name", "shipping_address");
|
||||
},
|
||||
|
||||
|
||||
contact_person: function() {
|
||||
erpnext.utils.get_contact_details(this.frm);
|
||||
},
|
||||
|
||||
|
||||
barcode: function(doc, cdt, cdn) {
|
||||
this.item_code(doc, cdt, cdn);
|
||||
},
|
||||
|
||||
|
||||
selling_price_list: function() {
|
||||
this.get_price_list_currency("Selling");
|
||||
},
|
||||
|
||||
|
||||
price_list_rate: function(doc, cdt, cdn) {
|
||||
var item = frappe.get_doc(cdt, cdn);
|
||||
frappe.model.round_floats_in(item, ["price_list_rate", "discount_percentage"]);
|
||||
|
||||
|
||||
item.rate = flt(item.price_list_rate * (1 - item.discount_percentage / 100.0),
|
||||
precision("rate", item));
|
||||
|
||||
|
||||
this.calculate_taxes_and_totals();
|
||||
},
|
||||
|
||||
|
||||
discount_percentage: function(doc, cdt, cdn) {
|
||||
var item = frappe.get_doc(cdt, cdn);
|
||||
if(!item.price_list_rate) {
|
||||
@ -145,63 +145,63 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({
|
||||
this.price_list_rate(doc, cdt, cdn);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
rate: function(doc, cdt, cdn) {
|
||||
var item = frappe.get_doc(cdt, cdn);
|
||||
frappe.model.round_floats_in(item, ["rate", "price_list_rate"]);
|
||||
|
||||
|
||||
if(item.price_list_rate) {
|
||||
item.discount_percentage = flt((1 - item.rate / item.price_list_rate) * 100.0,
|
||||
precision("discount_percentage", item));
|
||||
} else {
|
||||
item.discount_percentage = 0.0;
|
||||
}
|
||||
|
||||
|
||||
this.calculate_taxes_and_totals();
|
||||
},
|
||||
|
||||
discount_amount: function() {
|
||||
this.calculate_taxes_and_totals();
|
||||
},
|
||||
|
||||
|
||||
commission_rate: function() {
|
||||
this.calculate_commission();
|
||||
refresh_field("total_commission");
|
||||
},
|
||||
|
||||
|
||||
total_commission: function() {
|
||||
if(this.frm.doc.net_total) {
|
||||
frappe.model.round_floats_in(this.frm.doc, ["net_total", "total_commission"]);
|
||||
|
||||
|
||||
if(this.frm.doc.net_total < this.frm.doc.total_commission) {
|
||||
var msg = (frappe._("[Error]") + " " +
|
||||
frappe._(frappe.meta.get_label(this.frm.doc.doctype, "total_commission",
|
||||
this.frm.doc.name)) + " > " +
|
||||
var msg = (frappe._("[Error]") + " " +
|
||||
frappe._(frappe.meta.get_label(this.frm.doc.doctype, "total_commission",
|
||||
this.frm.doc.name)) + " > " +
|
||||
frappe._(frappe.meta.get_label(this.frm.doc.doctype, "net_total", this.frm.doc.name)));
|
||||
msgprint(msg);
|
||||
throw msg;
|
||||
}
|
||||
|
||||
this.frm.set_value("commission_rate",
|
||||
|
||||
this.frm.set_value("commission_rate",
|
||||
flt(this.frm.doc.total_commission * 100.0 / this.frm.doc.net_total));
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
allocated_percentage: function(doc, cdt, cdn) {
|
||||
var sales_person = frappe.get_doc(cdt, cdn);
|
||||
|
||||
|
||||
if(sales_person.allocated_percentage) {
|
||||
sales_person.allocated_percentage = flt(sales_person.allocated_percentage,
|
||||
precision("allocated_percentage", sales_person));
|
||||
sales_person.allocated_amount = flt(this.frm.doc.net_total *
|
||||
sales_person.allocated_percentage / 100.0,
|
||||
sales_person.allocated_percentage / 100.0,
|
||||
precision("allocated_amount", sales_person));
|
||||
|
||||
refresh_field(["allocated_percentage", "allocated_amount"], sales_person.name,
|
||||
sales_person.parentfield);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
warehouse: function(doc, cdt, cdn) {
|
||||
var item = frappe.get_doc(cdt, cdn);
|
||||
if(item.item_code && item.warehouse) {
|
||||
@ -215,7 +215,7 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
toggle_rounded_total: function() {
|
||||
var me = this;
|
||||
if(cint(frappe.defaults.get_global_default("disable_rounded_total"))) {
|
||||
@ -225,16 +225,16 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
toggle_editable_price_list_rate: function() {
|
||||
var df = frappe.meta.get_docfield(this.tname, "price_list_rate", this.frm.doc.name);
|
||||
var editable_price_list_rate = cint(frappe.defaults.get_default("editable_price_list_rate"));
|
||||
|
||||
|
||||
if(df && editable_price_list_rate) {
|
||||
df.read_only = 0;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
calculate_taxes_and_totals: function() {
|
||||
this._super();
|
||||
this.calculate_total_advance("Sales Invoice", "advance_adjustment_details");
|
||||
@ -242,13 +242,13 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({
|
||||
this.calculate_contribution();
|
||||
|
||||
// TODO check for custom_recalc in custom scripts of server
|
||||
|
||||
|
||||
this.frm.refresh_fields();
|
||||
},
|
||||
|
||||
|
||||
calculate_item_values: function() {
|
||||
var me = this;
|
||||
|
||||
|
||||
if (!this.discount_amount_applied) {
|
||||
$.each(this.frm.item_doclist, function(i, item) {
|
||||
frappe.model.round_floats_in(item);
|
||||
@ -260,34 +260,34 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
determine_exclusive_rate: function() {
|
||||
var me = this;
|
||||
$.each(me.frm.item_doclist, function(n, item) {
|
||||
var item_tax_map = me._load_item_tax_rate(item.item_tax_rate);
|
||||
var cumulated_tax_fraction = 0.0;
|
||||
|
||||
|
||||
$.each(me.frm.tax_doclist, function(i, tax) {
|
||||
tax.tax_fraction_for_current_item = me.get_current_tax_fraction(tax, item_tax_map);
|
||||
|
||||
|
||||
if(i==0) {
|
||||
tax.grand_total_fraction_for_current_item = 1 + tax.tax_fraction_for_current_item;
|
||||
} else {
|
||||
tax.grand_total_fraction_for_current_item =
|
||||
tax.grand_total_fraction_for_current_item =
|
||||
me.frm.tax_doclist[i-1].grand_total_fraction_for_current_item +
|
||||
tax.tax_fraction_for_current_item;
|
||||
}
|
||||
|
||||
|
||||
cumulated_tax_fraction += tax.tax_fraction_for_current_item;
|
||||
});
|
||||
|
||||
|
||||
if(cumulated_tax_fraction && !me.discount_amount_applied) {
|
||||
item.base_amount = flt(
|
||||
(item.amount * me.frm.doc.conversion_rate) / (1 + cumulated_tax_fraction),
|
||||
precision("base_amount", item));
|
||||
|
||||
item.base_rate = flt(item.base_amount / item.qty, precision("base_rate", item));
|
||||
|
||||
|
||||
if(item.discount_percentage == 100) {
|
||||
item.base_price_list_rate = item.base_rate;
|
||||
item.base_rate = 0.0;
|
||||
@ -298,31 +298,31 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
get_current_tax_fraction: function(tax, item_tax_map) {
|
||||
// Get tax fraction for calculating tax exclusive amount
|
||||
// from tax inclusive amount
|
||||
var current_tax_fraction = 0.0;
|
||||
|
||||
|
||||
if(cint(tax.included_in_print_rate)) {
|
||||
var tax_rate = this._get_tax_rate(tax, item_tax_map);
|
||||
|
||||
|
||||
if(tax.charge_type == "On Net Total") {
|
||||
current_tax_fraction = (tax_rate / 100.0);
|
||||
|
||||
|
||||
} else if(tax.charge_type == "On Previous Row Amount") {
|
||||
current_tax_fraction = (tax_rate / 100.0) *
|
||||
this.frm.tax_doclist[cint(tax.row_id) - 1].tax_fraction_for_current_item;
|
||||
|
||||
|
||||
} else if(tax.charge_type == "On Previous Row Total") {
|
||||
current_tax_fraction = (tax_rate / 100.0) *
|
||||
this.frm.tax_doclist[cint(tax.row_id) - 1].grand_total_fraction_for_current_item;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return current_tax_fraction;
|
||||
},
|
||||
|
||||
|
||||
calculate_net_total: function() {
|
||||
var me = this;
|
||||
this.frm.doc.net_total = this.frm.doc.net_total_export = 0.0;
|
||||
@ -334,7 +334,7 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({
|
||||
|
||||
frappe.model.round_floats_in(this.frm.doc, ["net_total", "net_total_export"]);
|
||||
},
|
||||
|
||||
|
||||
calculate_totals: function() {
|
||||
var me = this;
|
||||
var tax_count = this.frm.tax_doclist.length;
|
||||
@ -344,13 +344,13 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({
|
||||
precision("grand_total"));
|
||||
this.frm.doc.grand_total_export = flt(this.frm.doc.grand_total / this.frm.doc.conversion_rate,
|
||||
precision("grand_total_export"));
|
||||
|
||||
|
||||
this.frm.doc.other_charges_total = flt(this.frm.doc.grand_total - this.frm.doc.net_total,
|
||||
precision("other_charges_total"));
|
||||
this.frm.doc.other_charges_total_export = flt(this.frm.doc.grand_total_export -
|
||||
this.frm.doc.other_charges_total_export = flt(this.frm.doc.grand_total_export -
|
||||
this.frm.doc.net_total_export + flt(this.frm.doc.discount_amount),
|
||||
precision("other_charges_total_export"));
|
||||
|
||||
|
||||
this.frm.doc.rounded_total = Math.round(this.frm.doc.grand_total);
|
||||
this.frm.doc.rounded_total_export = Math.round(this.frm.doc.grand_total_export);
|
||||
},
|
||||
@ -393,19 +393,19 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({
|
||||
total_actual_tax += value;
|
||||
});
|
||||
|
||||
grand_total_for_discount_amount = flt(this.frm.doc.grand_total - total_actual_tax,
|
||||
grand_total_for_discount_amount = flt(this.frm.doc.grand_total - total_actual_tax,
|
||||
precision("grand_total"));
|
||||
return grand_total_for_discount_amount;
|
||||
},
|
||||
|
||||
|
||||
calculate_outstanding_amount: function() {
|
||||
// NOTE:
|
||||
// NOTE:
|
||||
// paid_amount and write_off_amount is only for POS Invoice
|
||||
// total_advance is only for non POS Invoice
|
||||
if(this.frm.doc.doctype == "Sales Invoice" && this.frm.doc.docstatus==0) {
|
||||
frappe.model.round_floats_in(this.frm.doc, ["grand_total", "total_advance", "write_off_amount",
|
||||
"paid_amount"]);
|
||||
var total_amount_to_pay = this.frm.doc.grand_total - this.frm.doc.write_off_amount
|
||||
var total_amount_to_pay = this.frm.doc.grand_total - this.frm.doc.write_off_amount
|
||||
- this.frm.doc.total_advance;
|
||||
if(this.frm.doc.is_pos) {
|
||||
if(!this.frm.doc.paid_amount) this.frm.doc.paid_amount = flt(total_amount_to_pay);
|
||||
@ -413,11 +413,11 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({
|
||||
this.frm.doc.paid_amount = 0
|
||||
}
|
||||
|
||||
this.frm.set_value("outstanding_amount", flt(total_amount_to_pay
|
||||
this.frm.set_value("outstanding_amount", flt(total_amount_to_pay
|
||||
- this.frm.doc.paid_amount, precision("outstanding_amount")));
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
calculate_commission: function() {
|
||||
if(this.frm.fields_dict.commission_rate) {
|
||||
if(this.frm.doc.commission_rate > 100) {
|
||||
@ -426,12 +426,12 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({
|
||||
msgprint(msg);
|
||||
throw msg;
|
||||
}
|
||||
|
||||
|
||||
this.frm.doc.total_commission = flt(this.frm.doc.net_total * this.frm.doc.commission_rate / 100.0,
|
||||
precision("total_commission"));
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
calculate_contribution: function() {
|
||||
var me = this;
|
||||
$.each(this.frm.doc.doctype.sales_team || [], function(i, sales_person) {
|
||||
@ -443,7 +443,7 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
_cleanup: function() {
|
||||
this._super();
|
||||
this.frm.doc.in_words = this.frm.doc.in_words_export = "";
|
||||
@ -463,16 +463,16 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
set_dynamic_labels: function() {
|
||||
this._super();
|
||||
set_sales_bom_help(this.frm.doc);
|
||||
},
|
||||
|
||||
|
||||
change_form_labels: function(company_currency) {
|
||||
var me = this;
|
||||
var field_label_map = {};
|
||||
|
||||
|
||||
var setup_field_label_map = function(fields_list, currency) {
|
||||
$.each(fields_list, function(i, fname) {
|
||||
var docfield = frappe.meta.docfield_map[me.frm.doc.doctype][fname];
|
||||
@ -482,76 +482,76 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({
|
||||
}
|
||||
});
|
||||
};
|
||||
setup_field_label_map(["net_total", "other_charges_total", "grand_total",
|
||||
setup_field_label_map(["net_total", "other_charges_total", "grand_total",
|
||||
"rounded_total", "in_words",
|
||||
"outstanding_amount", "total_advance", "paid_amount", "write_off_amount"],
|
||||
company_currency);
|
||||
|
||||
setup_field_label_map(["net_total_export", "other_charges_total_export", "grand_total_export",
|
||||
|
||||
setup_field_label_map(["net_total_export", "other_charges_total_export", "grand_total_export",
|
||||
"rounded_total_export", "in_words_export"], this.frm.doc.currency);
|
||||
|
||||
cur_frm.set_df_property("conversion_rate", "description", "1 " + this.frm.doc.currency
|
||||
|
||||
cur_frm.set_df_property("conversion_rate", "description", "1 " + this.frm.doc.currency
|
||||
+ " = [?] " + company_currency)
|
||||
|
||||
|
||||
if(this.frm.doc.price_list_currency && this.frm.doc.price_list_currency!=company_currency) {
|
||||
cur_frm.set_df_property("plc_conversion_rate", "description", "1 " + this.frm.doc.price_list_currency
|
||||
cur_frm.set_df_property("plc_conversion_rate", "description", "1 " + this.frm.doc.price_list_currency
|
||||
+ " = [?] " + company_currency)
|
||||
}
|
||||
|
||||
|
||||
// toggle fields
|
||||
this.frm.toggle_display(["conversion_rate", "net_total", "other_charges_total",
|
||||
this.frm.toggle_display(["conversion_rate", "net_total", "other_charges_total",
|
||||
"grand_total", "rounded_total", "in_words"],
|
||||
this.frm.doc.currency != company_currency);
|
||||
|
||||
this.frm.toggle_display(["plc_conversion_rate", "price_list_currency"],
|
||||
|
||||
this.frm.toggle_display(["plc_conversion_rate", "price_list_currency"],
|
||||
this.frm.doc.price_list_currency != company_currency);
|
||||
|
||||
|
||||
// set labels
|
||||
$.each(field_label_map, function(fname, label) {
|
||||
me.frm.fields_dict[fname].set_label(label);
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
change_grid_labels: function(company_currency) {
|
||||
var me = this;
|
||||
var field_label_map = {};
|
||||
|
||||
|
||||
var setup_field_label_map = function(fields_list, currency, parentfield) {
|
||||
var grid_doctype = me.frm.fields_dict[parentfield].grid.doctype;
|
||||
$.each(fields_list, function(i, fname) {
|
||||
var docfield = frappe.meta.docfield_map[grid_doctype][fname];
|
||||
if(docfield) {
|
||||
var label = frappe._(docfield.label || "").replace(/\([^\)]*\)/g, "");
|
||||
field_label_map[grid_doctype + "-" + fname] =
|
||||
field_label_map[grid_doctype + "-" + fname] =
|
||||
label.trim() + " (" + currency + ")";
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
setup_field_label_map(["base_rate", "base_price_list_rate", "base_amount"],
|
||||
company_currency, this.fname);
|
||||
|
||||
|
||||
setup_field_label_map(["rate", "price_list_rate", "amount"],
|
||||
this.frm.doc.currency, this.fname);
|
||||
|
||||
|
||||
setup_field_label_map(["tax_amount", "total"], company_currency, "other_charges");
|
||||
|
||||
|
||||
if(this.frm.fields_dict["advance_allocation_details"]) {
|
||||
setup_field_label_map(["advance_amount", "allocated_amount"], company_currency,
|
||||
"advance_allocation_details");
|
||||
}
|
||||
|
||||
|
||||
// toggle columns
|
||||
var item_grid = this.frm.fields_dict[this.fname].grid;
|
||||
var show = (this.frm.doc.currency != company_currency) ||
|
||||
(cur_frm.doc.other_charges.filter(
|
||||
var show = (this.frm.doc.currency != company_currency) ||
|
||||
((cur_frm.doc.other_charges || []).filter(
|
||||
function(d) { return d.included_in_print_rate===1}).length);
|
||||
|
||||
|
||||
$.each(["base_rate", "base_price_list_rate", "base_amount"], function(i, fname) {
|
||||
if(frappe.meta.get_docfield(item_grid.doctype, fname))
|
||||
item_grid.set_column_disp(fname, show);
|
||||
});
|
||||
|
||||
|
||||
// set labels
|
||||
var $wrapper = $(this.frm.wrapper);
|
||||
$.each(field_label_map, function(fname, label) {
|
||||
@ -567,7 +567,7 @@ var set_sales_bom_help = function(doc) {
|
||||
if(!cur_frm.fields_dict.packing_list) return;
|
||||
if ((doc.packing_details || []).length) {
|
||||
$(cur_frm.fields_dict.packing_list.row.wrapper).toggle(true);
|
||||
|
||||
|
||||
if (inList(['Delivery Note', 'Sales Invoice'], doc.doctype)) {
|
||||
help_msg = "<div class='alert alert-warning'>" +
|
||||
frappe._("For 'Sales BOM' items, warehouse, serial no and batch no \
|
||||
@ -576,7 +576,7 @@ var set_sales_bom_help = function(doc) {
|
||||
those values can be entered in the main item table, values will be copied to 'Packing List' table.")+
|
||||
"</div>";
|
||||
frappe.meta.get_docfield(doc.doctype, 'sales_bom_help', doc.name).options = help_msg;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$(cur_frm.fields_dict.packing_list.row.wrapper).toggle(false);
|
||||
if (inList(['Delivery Note', 'Sales Invoice'], doc.doctype)) {
|
||||
|
@ -1,13 +1,15 @@
|
||||
// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
// License: GNU General Public License v3. See license.txt
|
||||
|
||||
frappe.provide("erpnext.item");
|
||||
|
||||
cur_frm.cscript.refresh = function(doc) {
|
||||
// make sensitive fields(has_serial_no, is_stock_item, valuation_method)
|
||||
// read only if any stock ledger entry exists
|
||||
|
||||
cur_frm.cscript.make_dashboard()
|
||||
erpnext.hide_naming_series();
|
||||
|
||||
|
||||
if(!doc.__islocal && doc.show_in_website) {
|
||||
cur_frm.appframe.add_button("View In Website", function() {
|
||||
window.open(doc.page_name);
|
||||
@ -19,8 +21,19 @@ cur_frm.cscript.refresh = function(doc) {
|
||||
cur_frm.toggle_enable(['has_serial_no', 'is_stock_item', 'valuation_method'],
|
||||
doc.__sle_exists=="exists" ? false : true);
|
||||
}
|
||||
|
||||
erpnext.item.toggle_reqd(cur_frm);
|
||||
}
|
||||
|
||||
erpnext.item.toggle_reqd = function(frm) {
|
||||
frm.toggle_reqd("default_warehouse", frm.doc.is_stock_item==="Yes");
|
||||
};
|
||||
|
||||
frappe.ui.form.on("Item", "is_stock_item", function(frm) {
|
||||
erpnext.item.toggle_reqd(frm);
|
||||
});
|
||||
|
||||
|
||||
cur_frm.cscript.make_dashboard = function() {
|
||||
cur_frm.dashboard.reset();
|
||||
if(cur_frm.doc.__islocal)
|
||||
@ -152,7 +165,7 @@ cur_frm.fields_dict.item_supplier_details.grid.get_field("supplier").get_query =
|
||||
cur_frm.cscript.copy_from_item_group = function(doc) {
|
||||
frappe.model.with_doc("Item Group", doc.item_group, function() {
|
||||
$.each((doc.item_website_specifications || []), function(i, d) {
|
||||
var n = frappe.model.add_child(doc, "Item Website Specification",
|
||||
var n = frappe.model.add_child(doc, "Item Website Specification",
|
||||
"item_website_specifications");
|
||||
n.label = d.label;
|
||||
n.description = d.description;
|
||||
@ -164,11 +177,11 @@ cur_frm.cscript.copy_from_item_group = function(doc) {
|
||||
|
||||
cur_frm.cscript.image = function() {
|
||||
refresh_field("image_view");
|
||||
|
||||
|
||||
if(!cur_frm.doc.description_html)
|
||||
cur_frm.cscript.add_image(cur_frm.doc);
|
||||
else {
|
||||
msgprint(frappe._("You may need to update: ") +
|
||||
msgprint(frappe._("You may need to update: ") +
|
||||
frappe.meta.get_docfield(cur_frm.doc.doctype, "description_html").label);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ from frappe import msgprint, _
|
||||
from frappe.utils import cstr, flt, getdate, now_datetime, formatdate
|
||||
from frappe.website.website_generator import WebsiteGenerator
|
||||
|
||||
class WarehouseNotSet(Exception): pass
|
||||
class WarehouseNotSet(frappe.ValidationError): pass
|
||||
|
||||
class Item(WebsiteGenerator):
|
||||
def onload(self):
|
||||
|
@ -369,8 +369,8 @@ class StockEntry(StockController):
|
||||
arg = json.loads(arg)
|
||||
item = frappe.db.sql("""select stock_uom, description, item_name,
|
||||
expense_account, buying_cost_center from `tabItem`
|
||||
where name = %s and (ifnull(end_of_life,'')='' or end_of_life ='0000-00-00'
|
||||
or end_of_life > now())""", (arg.get('item_code')), as_dict = 1)
|
||||
where name = %s and (ifnull(end_of_life,'')='' or end_of_life > now())""",
|
||||
(arg.get('item_code')), as_dict = 1)
|
||||
if not item:
|
||||
msgprint("Item is not active", raise_exception=1)
|
||||
|
||||
|
@ -31,49 +31,49 @@ def get_item_details(args):
|
||||
|
||||
if isinstance(args, basestring):
|
||||
args = json.loads(args)
|
||||
|
||||
|
||||
args = frappe._dict(args)
|
||||
|
||||
if not args.get("transaction_type"):
|
||||
args.transaction_type = "buying" if frappe.get_meta(args.get("doctype")).get_field("supplier") \
|
||||
else "selling"
|
||||
|
||||
|
||||
if not args.get("price_list"):
|
||||
args.price_list = args.get("selling_price_list") or args.get("buying_price_list")
|
||||
|
||||
|
||||
if args.barcode:
|
||||
args.item_code = get_item_code(barcode=args.barcode)
|
||||
elif not args.item_code and args.serial_no:
|
||||
args.item_code = get_item_code(serial_no=args.serial_no)
|
||||
|
||||
|
||||
item_doc = frappe.get_doc("Item", args.item_code)
|
||||
item = item_doc
|
||||
|
||||
validate_item_details(args, item)
|
||||
|
||||
|
||||
out = get_basic_details(args, item_doc)
|
||||
|
||||
|
||||
get_party_item_code(args, item_doc, out)
|
||||
|
||||
if out.get("warehouse"):
|
||||
out.update(get_available_qty(args.item_code, out.warehouse))
|
||||
out.update(get_projected_qty(item.name, out.warehouse))
|
||||
|
||||
|
||||
get_price_list_rate(args, item_doc, out)
|
||||
|
||||
if args.transaction_type == "selling" and cint(args.is_pos):
|
||||
out.update(get_pos_settings_item_details(args.company, args))
|
||||
|
||||
|
||||
apply_pricing_rule(out, args)
|
||||
|
||||
|
||||
if args.get("doctype") in ("Sales Invoice", "Delivery Note"):
|
||||
if item_doc.has_serial_no == "Yes" and not args.serial_no:
|
||||
out.serial_no = get_serial_nos_by_fifo(args, item_doc)
|
||||
|
||||
|
||||
if args.transaction_date and item.lead_time_days:
|
||||
out.schedule_date = out.lead_time_date = add_days(args.transaction_date,
|
||||
item.lead_time_days)
|
||||
|
||||
|
||||
return out
|
||||
|
||||
def get_item_code(barcode=None, serial_no=None):
|
||||
@ -83,26 +83,26 @@ def get_item_code(barcode=None, serial_no=None):
|
||||
item_code = frappe.db.get_value("Serial No", serial_no, "item_code")
|
||||
|
||||
if not item_code:
|
||||
throw(_("No Item found with ") + _("Barcode") if barcode else _("Serial No") +
|
||||
throw(_("No Item found with ") + _("Barcode") if barcode else _("Serial No") +
|
||||
": %s" % (barcode or serial_no))
|
||||
|
||||
|
||||
return item_code
|
||||
|
||||
|
||||
def validate_item_details(args, item):
|
||||
if not args.company:
|
||||
throw(_("Please specify Company"))
|
||||
|
||||
|
||||
from erpnext.stock.doctype.item.item import validate_end_of_life
|
||||
validate_end_of_life(item.name, item.end_of_life)
|
||||
|
||||
|
||||
if args.transaction_type == "selling":
|
||||
# validate if sales item or service item
|
||||
if args.get("order_type") == "Maintenance":
|
||||
if item.is_service_item != "Yes":
|
||||
throw(_("Item") + (" %s: " % item.name) +
|
||||
throw(_("Item") + (" %s: " % item.name) +
|
||||
_("is not a service item.") +
|
||||
_("Please select a service item or change the order type to Sales."))
|
||||
|
||||
|
||||
elif item.is_sales_item != "Yes":
|
||||
throw(_("Item") + (" %s: " % item.name) + _("is not a sales item"))
|
||||
|
||||
@ -110,15 +110,15 @@ def validate_item_details(args, item):
|
||||
# validate if purchase item or subcontracted item
|
||||
if item.is_purchase_item != "Yes":
|
||||
throw(_("Item") + (" %s: " % item.name) + _("is not a purchase item"))
|
||||
|
||||
|
||||
if args.get("is_subcontracted") == "Yes" and item.is_sub_contracted_item != "Yes":
|
||||
throw(_("Item") + (" %s: " % item.name) +
|
||||
throw(_("Item") + (" %s: " % item.name) +
|
||||
_("not a sub-contracted item.") +
|
||||
_("Please select a sub-contracted item or do not sub-contract the transaction."))
|
||||
|
||||
|
||||
def get_basic_details(args, item_doc):
|
||||
item = item_doc
|
||||
|
||||
|
||||
from frappe.defaults import get_user_default_as_list
|
||||
user_default_warehouse_list = get_user_default_as_list('warehouse')
|
||||
user_default_warehouse = user_default_warehouse_list[0] \
|
||||
@ -136,7 +136,7 @@ def get_basic_details(args, item_doc):
|
||||
"cost_center": item.selling_cost_center \
|
||||
if args.transaction_type == "selling" else item.buying_cost_center,
|
||||
"batch_no": None,
|
||||
"item_tax_rate": json.dumps(dict(([d.tax_type, d.tax_rate] for d in
|
||||
"item_tax_rate": json.dumps(dict(([d.tax_type, d.tax_rate] for d in
|
||||
item_doc.get("item_tax")))),
|
||||
"uom": item.stock_uom,
|
||||
"min_order_qty": flt(item.min_order_qty) if args.doctype == "Material Request" else "",
|
||||
@ -150,12 +150,12 @@ def get_basic_details(args, item_doc):
|
||||
"base_amount": 0.0,
|
||||
"discount_percentage": 0.0
|
||||
})
|
||||
|
||||
|
||||
for fieldname in ("item_name", "item_group", "barcode", "brand", "stock_uom"):
|
||||
out[fieldname] = item.get(fieldname)
|
||||
|
||||
|
||||
return out
|
||||
|
||||
|
||||
def get_price_list_rate(args, item_doc, out):
|
||||
meta = frappe.get_meta(args.doctype)
|
||||
|
||||
@ -163,50 +163,50 @@ def get_price_list_rate(args, item_doc, out):
|
||||
validate_price_list(args)
|
||||
validate_conversion_rate(args, meta)
|
||||
|
||||
price_list_rate = frappe.db.get_value("Item Price",
|
||||
price_list_rate = frappe.db.get_value("Item Price",
|
||||
{"price_list": args.price_list, "item_code": args.item_code}, "price_list_rate")
|
||||
|
||||
|
||||
if not price_list_rate: return {}
|
||||
|
||||
|
||||
out.price_list_rate = flt(price_list_rate) * flt(args.plc_conversion_rate) \
|
||||
/ flt(args.conversion_rate)
|
||||
|
||||
|
||||
if not out.price_list_rate and args.transaction_type == "buying":
|
||||
from erpnext.stock.doctype.item.item import get_last_purchase_details
|
||||
out.update(get_last_purchase_details(item_doc.name,
|
||||
out.update(get_last_purchase_details(item_doc.name,
|
||||
args.docname, args.conversion_rate))
|
||||
|
||||
|
||||
def validate_price_list(args):
|
||||
if args.get("price_list"):
|
||||
if not frappe.db.get_value("Price List",
|
||||
if not frappe.db.get_value("Price List",
|
||||
{"name": args.price_list, args.transaction_type: 1, "enabled": 1}):
|
||||
throw(_("Price List is either disabled or for not ") + _(args.transaction_type))
|
||||
else:
|
||||
throw(_("Price List not selected"))
|
||||
|
||||
|
||||
def validate_conversion_rate(args, meta):
|
||||
from erpnext.setup.doctype.currency.currency import validate_conversion_rate
|
||||
from frappe.model.meta import get_field_precision
|
||||
|
||||
|
||||
# validate currency conversion rate
|
||||
validate_conversion_rate(args.currency, args.conversion_rate,
|
||||
validate_conversion_rate(args.currency, args.conversion_rate,
|
||||
meta.get_label("conversion_rate"), args.company)
|
||||
|
||||
args.conversion_rate = flt(args.conversion_rate,
|
||||
get_field_precision(meta.get_field("conversion_rate"),
|
||||
|
||||
args.conversion_rate = flt(args.conversion_rate,
|
||||
get_field_precision(meta.get_field("conversion_rate"),
|
||||
frappe._dict({"fields": args})))
|
||||
|
||||
|
||||
# validate price list currency conversion rate
|
||||
if not args.get("price_list_currency"):
|
||||
throw(_("Price List Currency not selected"))
|
||||
else:
|
||||
validate_conversion_rate(args.price_list_currency, args.plc_conversion_rate,
|
||||
validate_conversion_rate(args.price_list_currency, args.plc_conversion_rate,
|
||||
meta.get_label("plc_conversion_rate"), args.company)
|
||||
|
||||
args.plc_conversion_rate = flt(args.plc_conversion_rate,
|
||||
get_field_precision(meta.get_field("plc_conversion_rate"),
|
||||
|
||||
args.plc_conversion_rate = flt(args.plc_conversion_rate,
|
||||
get_field_precision(meta.get_field("plc_conversion_rate"),
|
||||
frappe._dict({"fields": args})))
|
||||
|
||||
|
||||
def get_party_item_code(args, item_doc, out):
|
||||
if args.transaction_type == "selling":
|
||||
customer_item_code = item_doc.get("item_customer_details", {"customer_name": args.customer})
|
||||
@ -214,35 +214,35 @@ def get_party_item_code(args, item_doc, out):
|
||||
else:
|
||||
item_supplier = item_doc.get("item_supplier_details", {"supplier": args.supplier})
|
||||
out.supplier_part_no = item_supplier[0].supplier_part_no if item_supplier else None
|
||||
|
||||
|
||||
|
||||
def get_pos_settings_item_details(company, args, pos_settings=None):
|
||||
res = frappe._dict()
|
||||
|
||||
|
||||
if not pos_settings:
|
||||
pos_settings = get_pos_settings(company)
|
||||
|
||||
|
||||
if pos_settings:
|
||||
for fieldname in ("income_account", "cost_center", "warehouse", "expense_account"):
|
||||
if not args.get(fieldname):
|
||||
res[fieldname] = pos_settings.get(fieldname)
|
||||
|
||||
|
||||
if res.get("warehouse"):
|
||||
res.actual_qty = get_available_qty(args.item_code,
|
||||
res.actual_qty = get_available_qty(args.item_code,
|
||||
res.warehouse).get("actual_qty")
|
||||
|
||||
|
||||
return res
|
||||
|
||||
def get_pos_settings(company):
|
||||
pos_settings = frappe.db.sql("""select * from `tabPOS Setting` where user = %s
|
||||
pos_settings = frappe.db.sql("""select * from `tabPOS Setting` where user = %s
|
||||
and company = %s""", (frappe.session['user'], company), as_dict=1)
|
||||
|
||||
|
||||
if not pos_settings:
|
||||
pos_settings = frappe.db.sql("""select * from `tabPOS Setting`
|
||||
pos_settings = frappe.db.sql("""select * from `tabPOS Setting`
|
||||
where ifnull(user,'') = '' and company = %s""", company, as_dict=1)
|
||||
|
||||
|
||||
return pos_settings and pos_settings[0] or None
|
||||
|
||||
|
||||
def apply_pricing_rule(out, args):
|
||||
args_dict = frappe._dict().update(args)
|
||||
args_dict.update(out)
|
||||
@ -260,67 +260,67 @@ def apply_pricing_rule(out, args):
|
||||
out["price_list_rate"] = pricing_rules[0]["price"] * \
|
||||
flt(args_dict.plc_conversion_rate) / flt(args_dict.conversion_rate)
|
||||
out["pricing_rule_for_price"] = pricing_rules[-1]["name"]
|
||||
|
||||
|
||||
def get_pricing_rules(args_dict):
|
||||
def _get_tree_conditions(doctype, allow_blank=True):
|
||||
field = frappe.scrub(doctype)
|
||||
condition = ""
|
||||
if args_dict.get(field):
|
||||
lft, rgt = frappe.db.get_value(doctype, args_dict[field], ["lft", "rgt"])
|
||||
parent_groups = frappe.db.sql_list("""select name from `tab%s`
|
||||
parent_groups = frappe.db.sql_list("""select name from `tab%s`
|
||||
where lft<=%s and rgt>=%s""" % (doctype, '%s', '%s'), (lft, rgt))
|
||||
|
||||
|
||||
if parent_groups:
|
||||
if allow_blank: parent_groups.append('')
|
||||
condition = " ifnull("+field+", '') in ('" + "', '".join(parent_groups)+"')"
|
||||
|
||||
return condition
|
||||
|
||||
|
||||
|
||||
|
||||
conditions = ""
|
||||
for field in ["customer", "supplier", "supplier_type", "campaign", "sales_partner"]:
|
||||
if args_dict.get(field):
|
||||
conditions += " and ifnull("+field+", '') in (%("+field+")s, '')"
|
||||
else:
|
||||
conditions += " and ifnull("+field+", '') = ''"
|
||||
|
||||
|
||||
for doctype in ["Customer Group", "Territory"]:
|
||||
group_condition = _get_tree_conditions(doctype)
|
||||
if group_condition:
|
||||
conditions += " and " + group_condition
|
||||
|
||||
|
||||
conditions += " and ifnull(for_price_list, '') in (%(price_list)s, '')"
|
||||
|
||||
|
||||
|
||||
if args_dict.get("transaction_date"):
|
||||
conditions += """ and %(transaction_date)s between ifnull(valid_from, '2000-01-01')
|
||||
conditions += """ and %(transaction_date)s between ifnull(valid_from, '2000-01-01')
|
||||
and ifnull(valid_upto, '2500-12-31')"""
|
||||
|
||||
return frappe.db.sql("""select * from `tabPricing Rule`
|
||||
where (item_code=%(item_code)s or {item_group_condition} or brand=%(brand)s)
|
||||
|
||||
return frappe.db.sql("""select * from `tabPricing Rule`
|
||||
where (item_code=%(item_code)s or {item_group_condition} or brand=%(brand)s)
|
||||
and docstatus < 2 and ifnull(disable, 0) = 0 {conditions}
|
||||
order by priority desc, name desc""".format(
|
||||
item_group_condition=_get_tree_conditions("Item Group", False), conditions=conditions),
|
||||
item_group_condition=_get_tree_conditions("Item Group", False), conditions=conditions),
|
||||
args_dict, as_dict=1)
|
||||
|
||||
def filter_pricing_rules(args_dict, pricing_rules, price_or_discount):
|
||||
# filter for qty
|
||||
if pricing_rules and args_dict.get("qty"):
|
||||
pricing_rules = filter(lambda x: (args_dict.qty>=flt(x.min_qty)
|
||||
pricing_rules = filter(lambda x: (args_dict.qty>=flt(x.min_qty)
|
||||
and (args_dict.qty<=x.max_qty if x.max_qty else True)), pricing_rules)
|
||||
|
||||
|
||||
# find pricing rule with highest priority
|
||||
if pricing_rules:
|
||||
max_priority = max([cint(p.priority) for p in pricing_rules])
|
||||
if max_priority:
|
||||
pricing_rules = filter(lambda x: cint(x.priority)==max_priority, pricing_rules)
|
||||
|
||||
|
||||
# apply internal priority
|
||||
all_fields = ["item_code", "item_group", "brand", "customer", "customer_group", "territory",
|
||||
all_fields = ["item_code", "item_group", "brand", "customer", "customer_group", "territory",
|
||||
"supplier", "supplier_type", "campaign", "for_price_list", "sales_partner"]
|
||||
|
||||
|
||||
if len(pricing_rules) > 1:
|
||||
for field_set in [["item_code", "item_group", "brand"],
|
||||
for field_set in [["item_code", "item_group", "brand"],
|
||||
["customer", "customer_group", "territory"], ["supplier", "supplier_type"]]:
|
||||
remaining_fields = list(set(all_fields) - set(field_set))
|
||||
if if_all_rules_same(pricing_rules, remaining_fields):
|
||||
@ -329,7 +329,7 @@ def filter_pricing_rules(args_dict, pricing_rules, price_or_discount):
|
||||
|
||||
if len(pricing_rules) > 1:
|
||||
pricing_rules = sorted(pricing_rules, key=lambda x: x[price_or_discount])
|
||||
|
||||
|
||||
return pricing_rules
|
||||
|
||||
def if_all_rules_same(pricing_rules, fields):
|
||||
@ -339,7 +339,7 @@ def if_all_rules_same(pricing_rules, fields):
|
||||
if val != [p[k] for k in fields]:
|
||||
all_rules_same = False
|
||||
break
|
||||
|
||||
|
||||
return all_rules_same
|
||||
|
||||
def apply_internal_priority(pricing_rules, field_set, args_dict):
|
||||
@ -352,8 +352,8 @@ def apply_internal_priority(pricing_rules, field_set, args_dict):
|
||||
return filtered_rules or pricing_rules
|
||||
|
||||
def get_serial_nos_by_fifo(args, item_doc):
|
||||
return "\n".join(frappe.db.sql_list("""select name from `tabSerial No`
|
||||
where item_code=%(item_code)s and warehouse=%(warehouse)s and status='Available'
|
||||
return "\n".join(frappe.db.sql_list("""select name from `tabSerial No`
|
||||
where item_code=%(item_code)s and warehouse=%(warehouse)s and status='Available'
|
||||
order by timestamp(purchase_date, purchase_time) asc limit %(qty)s""", {
|
||||
"item_code": args.item_code,
|
||||
"warehouse": args.warehouse,
|
||||
@ -367,10 +367,10 @@ def get_conversion_factor(item_code, uom):
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_projected_qty(item_code, warehouse):
|
||||
return {"projected_qty": frappe.db.get_value("Bin",
|
||||
return {"projected_qty": frappe.db.get_value("Bin",
|
||||
{"item_code": item_code, "warehouse": warehouse}, "projected_qty")}
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_available_qty(item_code, warehouse):
|
||||
return frappe.db.get_value("Bin", {"item_code": item_code, "warehouse": warehouse},
|
||||
["projected_qty", "actual_qty"], as_dict=True) or {}
|
||||
return frappe.db.get_value("Bin", {"item_code": item_code, "warehouse": warehouse},
|
||||
["projected_qty", "actual_qty"], as_dict=True) or {}
|
||||
|
Loading…
x
Reference in New Issue
Block a user