Merge pull request #1691 from nabinhait/v4-hotfix
build_filter_conditions and pricing rules
This commit is contained in:
commit
852e7cdb41
@ -64,13 +64,3 @@ class CForm(Document):
|
||||
'net_total' : inv.net_total,
|
||||
'grand_total' : inv.grand_total
|
||||
}
|
||||
|
||||
def get_invoice_nos(doctype, txt, searchfield, start, page_len, filters):
|
||||
from erpnext.utilities import build_filter_conditions
|
||||
conditions, filter_values = build_filter_conditions(filters)
|
||||
|
||||
return frappe.db.sql("""select name from `tabSales Invoice` where docstatus = 1
|
||||
and c_form_applicable = 'Yes' and ifnull(c_form_no, '') = '' %s
|
||||
and %s like %s order by name limit %s, %s""" %
|
||||
(conditions, searchfield, "%s", "%s", "%s"),
|
||||
tuple(filter_values + ["%%%s%%" % txt, start, page_len]))
|
||||
|
64
erpnext/accounts/doctype/pricing_rule/pricing_rule.js
Normal file
64
erpnext/accounts/doctype/pricing_rule/pricing_rule.js
Normal file
@ -0,0 +1,64 @@
|
||||
// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
// License: GNU General Public License v3. See license.txt
|
||||
|
||||
frappe.ui.form.on("Pricing Rule", "refresh", function(frm) {
|
||||
var help_content = ['<table class="table table-bordered" style="background-color: #f9f9f9;">',
|
||||
'<tr><td>',
|
||||
'<h4><i class="icon-hand-right"></i> ',
|
||||
__('Notes'),
|
||||
':</h4>',
|
||||
'<ul>',
|
||||
'<li>',
|
||||
__("Pricing Rule is made to overwrite Price List / define discount percentage, based on some criteria."),
|
||||
'</li>',
|
||||
'<li>',
|
||||
__("If selected Pricing Rule is made for 'Price', it will overwrite Price List. Pricing Rule price is the final price, so no further discount should be applied. Hence, in transactions like Sales Order, Purchase Order etc, it will be fetched in 'Rate' field, rather than 'Price List Rate' field."),
|
||||
'</li>',
|
||||
'<li>',
|
||||
__('Discount Percentage can be applied either against a Price List or for all Price List.'),
|
||||
'</li>',
|
||||
'<li>',
|
||||
__('To not apply Pricing Rule in a particular transaction, all applicable Pricing Rules should be disabled.'),
|
||||
'</li>',
|
||||
'</ul>',
|
||||
'</td></tr>',
|
||||
'<tr><td>',
|
||||
'<h4><i class="icon-question-sign"></i> ',
|
||||
__('How Pricing Rule is applied?'),
|
||||
'</h4>',
|
||||
'<ol>',
|
||||
'<li>',
|
||||
__("Pricing Rule is first selected based on 'Apply On' field, which can be Item, Item Group or Brand."),
|
||||
'</li>',
|
||||
'<li>',
|
||||
__("Then Pricing Rules are filtered out based on Customer, Customer Group, Territory, Supplier, Supplier Type, Campaign, Sales Partner etc."),
|
||||
'</li>',
|
||||
'<li>',
|
||||
__('Pricing Rules are further filtered based on quantity.'),
|
||||
'</li>',
|
||||
'<li>',
|
||||
__('If two or more Pricing Rules are found based on the above conditions, Priority is applied. Priority is a number between 0 to 20 while default value is zero (blank). Higher number means it will take precedence if there are multiple Pricing Rules with same conditions.'),
|
||||
'</li>',
|
||||
'<li>',
|
||||
__('Even if there are multiple Pricing Rules with highest priority, then following internal priorities are applied:'),
|
||||
'<ul>',
|
||||
'<li>',
|
||||
__('Item Code > Item Group > Brand'),
|
||||
'</li>',
|
||||
'<li>',
|
||||
__('Customer > Customer Group > Territory'),
|
||||
'</li>',
|
||||
'<li>',
|
||||
__('Supplier > Supplier Type'),
|
||||
'</li>',
|
||||
'</ul>',
|
||||
'</li>',
|
||||
'<li>',
|
||||
__('If multiple Pricing Rules continue to prevail, users are asked to set Priority manually to resolve conflict.'),
|
||||
'</li>',
|
||||
'</ol>',
|
||||
'</td></tr>',
|
||||
'</table>'].join("\n");
|
||||
|
||||
set_field_options("pricing_rule_help", help_content);
|
||||
});
|
@ -131,6 +131,13 @@
|
||||
"fieldtype": "Column Break",
|
||||
"permlevel": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "company",
|
||||
"fieldtype": "Link",
|
||||
"label": "Company",
|
||||
"options": "Company",
|
||||
"permlevel": 0
|
||||
},
|
||||
{
|
||||
"default": "Today",
|
||||
"fieldname": "valid_from",
|
||||
@ -198,12 +205,25 @@
|
||||
"label": "For Price List",
|
||||
"options": "Price List",
|
||||
"permlevel": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "help_section",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "",
|
||||
"options": "Simple",
|
||||
"permlevel": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "pricing_rule_help",
|
||||
"fieldtype": "HTML",
|
||||
"label": "Pricing Rule Help",
|
||||
"permlevel": 0
|
||||
}
|
||||
],
|
||||
"icon": "icon-gift",
|
||||
"idx": 1,
|
||||
"istable": 0,
|
||||
"modified": "2014-05-12 16:24:52.005162",
|
||||
"modified": "2014-05-28 15:36:29.403659",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Pricing Rule",
|
||||
|
@ -15,7 +15,6 @@ class PricingRule(Document):
|
||||
self.validate_min_max_qty()
|
||||
self.cleanup_fields_value()
|
||||
|
||||
|
||||
def validate_mandatory(self):
|
||||
for field in ["apply_on", "applicable_for", "price_or_discount"]:
|
||||
tocheck = frappe.scrub(self.get(field) or "")
|
||||
@ -26,7 +25,6 @@ class PricingRule(Document):
|
||||
if self.min_qty and self.max_qty and flt(self.min_qty) > flt(self.max_qty):
|
||||
throw(_("Min Qty can not be greater than Max Qty"))
|
||||
|
||||
|
||||
def cleanup_fields_value(self):
|
||||
for logic_field in ["apply_on", "applicable_for", "price_or_discount"]:
|
||||
fieldname = frappe.scrub(self.get(logic_field) or "")
|
||||
|
@ -20,6 +20,7 @@ class TestPricingRule(unittest.TestCase):
|
||||
"price_or_discount": "Discount Percentage",
|
||||
"price": 0,
|
||||
"discount_percentage": 10,
|
||||
"company": "_Test Company"
|
||||
}
|
||||
frappe.get_doc(test_record.copy()).insert()
|
||||
|
||||
@ -36,7 +37,6 @@ class TestPricingRule(unittest.TestCase):
|
||||
"transaction_type": "selling",
|
||||
"customer": "_Test Customer",
|
||||
})
|
||||
|
||||
details = get_item_details(args)
|
||||
self.assertEquals(details.get("discount_percentage"), 10)
|
||||
|
||||
@ -72,7 +72,7 @@ class TestPricingRule(unittest.TestCase):
|
||||
|
||||
frappe.db.sql("update `tabPricing Rule` set priority=NULL where campaign='_Test Campaign'")
|
||||
from erpnext.stock.get_item_details import MultiplePricingRuleConflict
|
||||
self.assertRaises (MultiplePricingRuleConflict, get_item_details, args)
|
||||
self.assertRaises(MultiplePricingRuleConflict, get_item_details, args)
|
||||
|
||||
args.item_code = "_Test Item 2"
|
||||
details = get_item_details(args)
|
||||
|
@ -77,16 +77,19 @@ erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({
|
||||
},
|
||||
|
||||
supplier: function() {
|
||||
var me = this;
|
||||
if(this.frm.updating_party_details)
|
||||
return;
|
||||
erpnext.utils.get_party_details(this.frm,
|
||||
"erpnext.accounts.party.get_party_details", {
|
||||
erpnext.utils.get_party_details(this.frm, "erpnext.accounts.party.get_party_details",
|
||||
{
|
||||
posting_date: this.frm.doc.posting_date,
|
||||
party: this.frm.doc.supplier,
|
||||
party_type: "Supplier",
|
||||
account: this.frm.doc.debit_to,
|
||||
price_list: this.frm.doc.buying_price_list,
|
||||
})
|
||||
}, function() {
|
||||
me.apply_pricing_rule();
|
||||
})
|
||||
},
|
||||
|
||||
credit_to: function() {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"autoname": "EVD.######",
|
||||
"creation": "2013-05-22 12:43:10.000000",
|
||||
"creation": "2013-05-22 12:43:10",
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"fields": [
|
||||
@ -193,17 +193,9 @@
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "pricing_rule_for_price",
|
||||
"fieldname": "pricing_rule",
|
||||
"fieldtype": "Link",
|
||||
"label": "Pricing Rule For Price",
|
||||
"options": "Pricing Rule",
|
||||
"permlevel": 0,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "pricing_rule_for_discount",
|
||||
"fieldtype": "Link",
|
||||
"label": "Pricing Rule For Discount",
|
||||
"label": "Pricing Rule",
|
||||
"options": "Pricing Rule",
|
||||
"permlevel": 0,
|
||||
"read_only": 1
|
||||
@ -429,9 +421,12 @@
|
||||
],
|
||||
"idx": 1,
|
||||
"istable": 1,
|
||||
"modified": "2014-02-28 11:27:53.000000",
|
||||
"modified": "2014-05-28 12:43:40.647183",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Purchase Invoice Item",
|
||||
"owner": "Administrator"
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC"
|
||||
}
|
@ -155,8 +155,9 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
|
||||
},
|
||||
|
||||
customer: function() {
|
||||
if(this.frm.updating_party_details)
|
||||
return;
|
||||
var me = this;
|
||||
if(this.frm.updating_party_details) return;
|
||||
|
||||
erpnext.utils.get_party_details(this.frm,
|
||||
"erpnext.accounts.party.get_party_details", {
|
||||
posting_date: this.frm.doc.posting_date,
|
||||
@ -164,7 +165,9 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
|
||||
party_type: "Customer",
|
||||
account: this.frm.doc.debit_to,
|
||||
price_list: this.frm.doc.selling_price_list,
|
||||
})
|
||||
}, function() {
|
||||
me.apply_pricing_rule();
|
||||
})
|
||||
},
|
||||
|
||||
debit_to: function() {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"autoname": "INVD.######",
|
||||
"creation": "2013-06-04 11:02:19.000000",
|
||||
"creation": "2013-06-04 11:02:19",
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"fields": [
|
||||
@ -201,17 +201,9 @@
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "pricing_rule_for_price",
|
||||
"fieldname": "pricing_rule",
|
||||
"fieldtype": "Link",
|
||||
"label": "Pricing Rule For Price",
|
||||
"options": "Pricing Rule",
|
||||
"permlevel": 0,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "pricing_rule_for_discount",
|
||||
"fieldtype": "Link",
|
||||
"label": "Pricing Rule For Discount",
|
||||
"label": "Pricing Rule",
|
||||
"options": "Pricing Rule",
|
||||
"permlevel": 0,
|
||||
"read_only": 1
|
||||
@ -456,9 +448,12 @@
|
||||
],
|
||||
"idx": 1,
|
||||
"istable": 1,
|
||||
"modified": "2014-02-28 11:04:19.000000",
|
||||
"modified": "2014-05-28 12:42:28.209942",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Sales Invoice Item",
|
||||
"owner": "Administrator"
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC"
|
||||
}
|
@ -18,7 +18,7 @@ frappe.query_reports["Accounts Payable"] = {
|
||||
"get_query": function() {
|
||||
var company = frappe.query_report.filters_by_name.company.get_value();
|
||||
return {
|
||||
"query": "erpnext.accounts.utils.get_account_list",
|
||||
"query": "erpnext.controllers.queries.get_account_list",
|
||||
"filters": {
|
||||
"report_type": "Balance Sheet",
|
||||
"company": company,
|
||||
|
@ -18,7 +18,7 @@ frappe.query_reports["Accounts Receivable"] = {
|
||||
"get_query": function() {
|
||||
var company = frappe.query_report.filters_by_name.company.get_value();
|
||||
return {
|
||||
"query": "erpnext.accounts.utils.get_account_list",
|
||||
"query": "erpnext.controllers.queries.get_account_list",
|
||||
"filters": {
|
||||
"report_type": "Balance Sheet",
|
||||
"company": company,
|
||||
|
@ -23,7 +23,7 @@ frappe.query_reports["Bank Clearance Summary"] = {
|
||||
"options": "Account",
|
||||
"get_query": function() {
|
||||
return {
|
||||
"query": "erpnext.accounts.utils.get_account_list",
|
||||
"query": "erpnext.controllers.queries.get_account_list",
|
||||
"filters": [
|
||||
['Account', 'account_type', 'in', 'Bank, Cash'],
|
||||
['Account', 'group_or_ledger', '=', 'Ledger'],
|
||||
|
@ -11,7 +11,7 @@ frappe.query_reports["Bank Reconciliation Statement"] = {
|
||||
"reqd": 1,
|
||||
"get_query": function() {
|
||||
return {
|
||||
"query": "erpnext.accounts.utils.get_account_list",
|
||||
"query": "erpnext.controllers.queries.get_account_list",
|
||||
"filters": [
|
||||
['Account', 'account_type', 'in', 'Bank, Cash'],
|
||||
['Account', 'group_or_ledger', '=', 'Ledger'],
|
||||
@ -27,4 +27,4 @@ frappe.query_reports["Bank Reconciliation Statement"] = {
|
||||
"reqd": 1
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -7,10 +7,13 @@ from frappe.utils import flt
|
||||
|
||||
def execute(filters=None):
|
||||
if not filters: filters = {}
|
||||
|
||||
|
||||
columns = get_columns()
|
||||
|
||||
if not filters.get("account"): return columns, []
|
||||
|
||||
data = get_entries(filters)
|
||||
|
||||
|
||||
from erpnext.accounts.utils import get_balance_on
|
||||
balance_as_per_company = get_balance_on(filters["account"], filters["report_date"])
|
||||
|
||||
@ -20,33 +23,33 @@ def execute(filters=None):
|
||||
total_credit += flt(d[5])
|
||||
|
||||
bank_bal = flt(balance_as_per_company) + flt(total_debit) - flt(total_credit)
|
||||
|
||||
|
||||
data += [
|
||||
get_balance_row("Balance as per company books", balance_as_per_company),
|
||||
["", "", "", "Amounts not reflected in bank", total_debit, total_credit],
|
||||
["", "", "", "Amounts not reflected in bank", total_debit, total_credit],
|
||||
get_balance_row("Balance as per bank", bank_bal)
|
||||
]
|
||||
|
||||
|
||||
return columns, data
|
||||
|
||||
|
||||
def get_columns():
|
||||
return ["Journal Voucher:Link/Journal Voucher:140", "Posting Date:Date:100",
|
||||
"Clearance Date:Date:110", "Against Account:Link/Account:200",
|
||||
return ["Journal Voucher:Link/Journal Voucher:140", "Posting Date:Date:100",
|
||||
"Clearance Date:Date:110", "Against Account:Link/Account:200",
|
||||
"Debit:Currency:120", "Credit:Currency:120"
|
||||
]
|
||||
|
||||
|
||||
def get_entries(filters):
|
||||
entries = frappe.db.sql("""select
|
||||
entries = frappe.db.sql("""select
|
||||
jv.name, jv.posting_date, jv.clearance_date, jvd.against_account, jvd.debit, jvd.credit
|
||||
from
|
||||
`tabJournal Voucher Detail` jvd, `tabJournal Voucher` jv
|
||||
where jvd.parent = jv.name and jv.docstatus=1
|
||||
and jvd.account = %(account)s and jv.posting_date <= %(report_date)s
|
||||
from
|
||||
`tabJournal Voucher Detail` jvd, `tabJournal Voucher` jv
|
||||
where jvd.parent = jv.name and jv.docstatus=1
|
||||
and jvd.account = %(account)s and jv.posting_date <= %(report_date)s
|
||||
and ifnull(jv.clearance_date, '4000-01-01') > %(report_date)s
|
||||
order by jv.name DESC""", filters, as_list=1)
|
||||
|
||||
|
||||
return entries
|
||||
|
||||
|
||||
def get_balance_row(label, amount):
|
||||
if amount > 0:
|
||||
return ["", "", "", label, amount, 0]
|
||||
|
@ -30,7 +30,7 @@ frappe.query_reports["Item-wise Purchase Register"] = {
|
||||
"get_query": function() {
|
||||
var company = frappe.query_report.filters_by_name.company.get_value();
|
||||
return {
|
||||
"query": "erpnext.accounts.utils.get_account_list",
|
||||
"query": "erpnext.controllers.queries.get_account_list",
|
||||
"filters": {
|
||||
"report_type": "Balance Sheet",
|
||||
"company": company,
|
||||
|
@ -24,7 +24,7 @@ frappe.query_reports["Item-wise Sales Register"] = frappe.query_reports["Sales R
|
||||
"get_query": function() {
|
||||
var company = frappe.query_report.filters_by_name.company.get_value();
|
||||
return {
|
||||
"query": "erpnext.accounts.utils.get_account_list",
|
||||
"query": "erpnext.controllers.queries.get_account_list",
|
||||
"filters": {
|
||||
"report_type": "Balance Sheet",
|
||||
"company": company,
|
||||
|
@ -29,7 +29,7 @@ frappe.query_reports["Payment Period Based On Invoice Date"] = {
|
||||
options: "Account",
|
||||
get_query: function() {
|
||||
return {
|
||||
query: "erpnext.accounts.utils.get_account_list",
|
||||
query: "erpnext.controllers.queries.get_account_list",
|
||||
filters: {
|
||||
"report_type": "Balance Sheet",
|
||||
company: frappe.query_report.filters_by_name.company.get_value()
|
||||
|
@ -24,7 +24,7 @@ frappe.query_reports["Purchase Register"] = {
|
||||
"get_query": function() {
|
||||
var company = frappe.query_report.filters_by_name.company.get_value();
|
||||
return {
|
||||
"query": "erpnext.accounts.utils.get_account_list",
|
||||
"query": "erpnext.controllers.queries.get_account_list",
|
||||
"filters": {
|
||||
"report_type": "Balance Sheet",
|
||||
"company": company,
|
||||
|
@ -24,7 +24,7 @@ frappe.query_reports["Sales Register"] = {
|
||||
"get_query": function() {
|
||||
var company = frappe.query_report.filters_by_name.company.get_value();
|
||||
return {
|
||||
"query": "erpnext.accounts.utils.get_account_list",
|
||||
"query": "erpnext.controllers.queries.get_account_list",
|
||||
"filters": {
|
||||
"report_type": "Balance Sheet",
|
||||
"company": company,
|
||||
|
@ -7,8 +7,7 @@ import frappe
|
||||
from frappe.utils import nowdate, cstr, flt, now, getdate, add_months
|
||||
from frappe import throw, _
|
||||
from frappe.utils import formatdate
|
||||
from erpnext.utilities import build_filter_conditions
|
||||
|
||||
import frappe.widgets.reportview
|
||||
|
||||
class FiscalYearError(frappe.ValidationError): pass
|
||||
class BudgetError(frappe.ValidationError): pass
|
||||
@ -196,28 +195,6 @@ def update_against_doc(d, jv_obj):
|
||||
jv_obj.ignore_validate_update_after_submit = True
|
||||
jv_obj.save()
|
||||
|
||||
def get_account_list(doctype, txt, searchfield, start, page_len, filters):
|
||||
if not filters.get("group_or_ledger"):
|
||||
filters["group_or_ledger"] = "Ledger"
|
||||
|
||||
conditions, filter_values = build_filter_conditions(filters)
|
||||
|
||||
return frappe.db.sql("""select name, parent_account from `tabAccount`
|
||||
where docstatus < 2 %s and %s like %s order by name limit %s, %s""" %
|
||||
(conditions, searchfield, "%s", "%s", "%s"),
|
||||
tuple(filter_values + ["%%%s%%" % txt, start, page_len]))
|
||||
|
||||
def get_cost_center_list(doctype, txt, searchfield, start, page_len, filters):
|
||||
if not filters.get("group_or_ledger"):
|
||||
filters["group_or_ledger"] = "Ledger"
|
||||
|
||||
conditions, filter_values = build_filter_conditions(filters)
|
||||
|
||||
return frappe.db.sql("""select name, parent_cost_center from `tabCost Center`
|
||||
where docstatus < 2 %s and %s like %s order by name limit %s, %s""" %
|
||||
(conditions, searchfield, "%s", "%s", "%s"),
|
||||
tuple(filter_values + ["%%%s%%" % txt, start, page_len]))
|
||||
|
||||
def remove_against_link_from_jv(ref_type, ref_no, against_field):
|
||||
linked_jv = frappe.db.sql_list("""select parent from `tabJournal Voucher Detail`
|
||||
where `%s`=%s and docstatus < 2""" % (against_field, "%s"), (ref_no))
|
||||
|
@ -62,7 +62,8 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({
|
||||
},
|
||||
|
||||
supplier: function() {
|
||||
erpnext.utils.get_party_details(this.frm);
|
||||
var me = this;
|
||||
erpnext.utils.get_party_details(this.frm, null, null, function(){me.apply_pricing_rule()});
|
||||
},
|
||||
|
||||
supplier_address: function() {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"autoname": "POD/.#####",
|
||||
"creation": "2013-05-24 19:29:06.000000",
|
||||
"creation": "2013-05-24 19:29:06",
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"fields": [
|
||||
@ -252,17 +252,9 @@
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "pricing_rule_for_price",
|
||||
"fieldname": "pricing_rule",
|
||||
"fieldtype": "Link",
|
||||
"label": "Pricing Rule For Price",
|
||||
"options": "Pricing Rule",
|
||||
"permlevel": 0,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "pricing_rule_for_discount",
|
||||
"fieldtype": "Link",
|
||||
"label": "Pricing Rule For Discount",
|
||||
"label": "Pricing Rule",
|
||||
"options": "Pricing Rule",
|
||||
"permlevel": 0,
|
||||
"read_only": 1
|
||||
@ -474,9 +466,12 @@
|
||||
],
|
||||
"idx": 1,
|
||||
"istable": 1,
|
||||
"modified": "2014-02-28 11:26:25.000000",
|
||||
"modified": "2014-05-28 12:42:53.018610",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Buying",
|
||||
"name": "Purchase Order Item",
|
||||
"owner": "Administrator"
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC"
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"autoname": "SQI-.#####",
|
||||
"creation": "2013-05-22 12:43:10.000000",
|
||||
"creation": "2013-05-22 12:43:10",
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"fields": [
|
||||
@ -195,17 +195,9 @@
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "pricing_rule_for_price",
|
||||
"fieldname": "pricing_rule",
|
||||
"fieldtype": "Link",
|
||||
"label": "Pricing Rule For Price",
|
||||
"options": "Pricing Rule",
|
||||
"permlevel": 0,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "pricing_rule_for_discount",
|
||||
"fieldtype": "Link",
|
||||
"label": "Pricing Rule For Discount",
|
||||
"label": "Pricing Rule",
|
||||
"options": "Pricing Rule",
|
||||
"permlevel": 0,
|
||||
"read_only": 1
|
||||
@ -354,9 +346,12 @@
|
||||
],
|
||||
"idx": 1,
|
||||
"istable": 1,
|
||||
"modified": "2014-02-28 11:25:38.000000",
|
||||
"modified": "2014-05-28 12:44:17.347236",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Buying",
|
||||
"name": "Supplier Quotation Item",
|
||||
"owner": "Administrator"
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC"
|
||||
}
|
@ -1,18 +1,18 @@
|
||||
// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
// License: GNU General Public License v3. See license.txt
|
||||
|
||||
frappe.pages['purchase-analytics'].onload = function(wrapper) {
|
||||
frappe.pages['purchase-analytics'].onload = function(wrapper) {
|
||||
frappe.ui.make_app_page({
|
||||
parent: wrapper,
|
||||
title: __('Purchase Analytics'),
|
||||
single_column: true
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
new erpnext.PurchaseAnalytics(wrapper);
|
||||
|
||||
|
||||
|
||||
wrapper.appframe.add_module_icon("Buying")
|
||||
|
||||
|
||||
}
|
||||
|
||||
erpnext.PurchaseAnalytics = frappe.views.TreeGridReport.extend({
|
||||
@ -22,19 +22,19 @@ erpnext.PurchaseAnalytics = frappe.views.TreeGridReport.extend({
|
||||
page: wrapper,
|
||||
parent: $(wrapper).find('.layout-main'),
|
||||
appframe: wrapper.appframe,
|
||||
doctypes: ["Item", "Item Group", "Supplier", "Supplier Type", "Company", "Fiscal Year",
|
||||
"Purchase Invoice", "Purchase Invoice Item",
|
||||
"Purchase Order", "Purchase Order Item[Purchase Analytics]",
|
||||
doctypes: ["Item", "Item Group", "Supplier", "Supplier Type", "Company", "Fiscal Year",
|
||||
"Purchase Invoice", "Purchase Invoice Item",
|
||||
"Purchase Order", "Purchase Order Item[Purchase Analytics]",
|
||||
"Purchase Receipt", "Purchase Receipt Item[Purchase Analytics]"],
|
||||
tree_grid: { show: true }
|
||||
});
|
||||
|
||||
|
||||
this.tree_grids = {
|
||||
"Supplier Type": {
|
||||
label: __("Supplier Type / Supplier"),
|
||||
show: true,
|
||||
show: true,
|
||||
item_key: "supplier",
|
||||
parent_field: "parent_supplier_type",
|
||||
parent_field: "parent_supplier_type",
|
||||
formatter: function(item) {
|
||||
// return repl('<a href="#Report/stock-invoices/customer=%(enc_value)s">%(value)s</a>', {
|
||||
// value: item.name,
|
||||
@ -45,29 +45,29 @@ erpnext.PurchaseAnalytics = frappe.views.TreeGridReport.extend({
|
||||
},
|
||||
"Supplier": {
|
||||
label: __("Supplier"),
|
||||
show: false,
|
||||
show: false,
|
||||
item_key: "supplier",
|
||||
formatter: function(item) {
|
||||
return item.name;
|
||||
}
|
||||
},
|
||||
},
|
||||
"Item Group": {
|
||||
label: "Item",
|
||||
show: true,
|
||||
parent_field: "parent_item_group",
|
||||
show: true,
|
||||
parent_field: "parent_item_group",
|
||||
item_key: "item_code",
|
||||
formatter: function(item) {
|
||||
return item.name;
|
||||
}
|
||||
},
|
||||
},
|
||||
"Item": {
|
||||
label: "Item",
|
||||
show: false,
|
||||
show: false,
|
||||
item_key: "item_code",
|
||||
formatter: function(item) {
|
||||
return item.name;
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
setup_columns: function() {
|
||||
@ -82,24 +82,24 @@ erpnext.PurchaseAnalytics = frappe.views.TreeGridReport.extend({
|
||||
formatter: this.currency_formatter}
|
||||
];
|
||||
|
||||
this.make_date_range_columns();
|
||||
this.make_date_range_columns();
|
||||
this.columns = std_columns.concat(this.columns);
|
||||
},
|
||||
filters: [
|
||||
{fieldtype:"Select", label: __("Tree Type"), options:["Supplier Type", "Supplier",
|
||||
{fieldtype:"Select", label: __("Tree Type"), options:["Supplier Type", "Supplier",
|
||||
"Item Group", "Item"],
|
||||
filter: function(val, item, opts, me) {
|
||||
return me.apply_zero_filter(val, item, opts, me);
|
||||
}},
|
||||
{fieldtype:"Select", label: __("Based On"), options:["Purchase Invoice",
|
||||
{fieldtype:"Select", label: __("Based On"), options:["Purchase Invoice",
|
||||
"Purchase Order", "Purchase Receipt"]},
|
||||
{fieldtype:"Select", label: __("Value or Qty"), options:["Value", "Quantity"]},
|
||||
{fieldtype:"Select", label: __("Company"), link:"Company",
|
||||
{fieldtype:"Select", label: __("Company"), link:"Company",
|
||||
default_value: "Select Company..."},
|
||||
{fieldtype:"Date", label: __("From Date")},
|
||||
{fieldtype:"Label", label: __("To")},
|
||||
{fieldtype:"Date", label: __("To Date")},
|
||||
{fieldtype:"Select", label: __("Range"),
|
||||
{fieldtype:"Select", label: __("Range"),
|
||||
options:["Daily", "Weekly", "Monthly", "Quarterly", "Yearly"]},
|
||||
{fieldtype:"Button", label: __("Refresh"), icon:"icon-refresh icon-white"},
|
||||
{fieldtype:"Button", label: __("Reset Filters"), icon: "icon-filter"}
|
||||
@ -107,10 +107,10 @@ erpnext.PurchaseAnalytics = frappe.views.TreeGridReport.extend({
|
||||
setup_filters: function() {
|
||||
var me = this;
|
||||
this._super();
|
||||
|
||||
|
||||
this.trigger_refresh_on_change(["value_or_qty", "tree_type", "based_on", "company"]);
|
||||
|
||||
this.show_zero_check()
|
||||
this.show_zero_check()
|
||||
this.setup_plot_check();
|
||||
},
|
||||
init_filter_values: function() {
|
||||
@ -124,34 +124,34 @@ erpnext.PurchaseAnalytics = frappe.views.TreeGridReport.extend({
|
||||
// Add 'All Supplier Types' Supplier Type
|
||||
// (Supplier / Item are not mandatory!!)
|
||||
// Set parent supplier type for tree view
|
||||
|
||||
|
||||
$.each(frappe.report_dump.data["Supplier Type"], function(i, v) {
|
||||
v['parent_supplier_type'] = "All Supplier Types"
|
||||
})
|
||||
|
||||
|
||||
frappe.report_dump.data["Supplier Type"] = [{
|
||||
name: __("All Supplier Types"),
|
||||
name: __("All Supplier Types"),
|
||||
id: "All Supplier Types",
|
||||
}].concat(frappe.report_dump.data["Supplier Type"]);
|
||||
|
||||
|
||||
frappe.report_dump.data["Supplier"].push({
|
||||
name: __("Not Set"),
|
||||
name: __("Not Set"),
|
||||
parent_supplier_type: "All Supplier Types",
|
||||
id: "Not Set",
|
||||
});
|
||||
|
||||
frappe.report_dump.data["Item"].push({
|
||||
name: __("Not Set"),
|
||||
name: __("Not Set"),
|
||||
parent_item_group: "All Item Groups",
|
||||
id: "Not Set",
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
if (!this.tl || !this.tl[this.based_on]) {
|
||||
this.make_transaction_list(this.based_on, this.based_on + " Item");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if(!this.data || me.item_type != me.tree_type) {
|
||||
if(me.tree_type=='Supplier') {
|
||||
var items = frappe.report_dump.data["Supplier"];
|
||||
@ -177,20 +177,20 @@ erpnext.PurchaseAnalytics = frappe.views.TreeGridReport.extend({
|
||||
me.parent_map[d.name] = d[me.tree_grid.parent_field];
|
||||
}
|
||||
me.reset_item_values(d);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
this.set_indent();
|
||||
|
||||
|
||||
} else {
|
||||
// otherwise, only reset values
|
||||
$.each(this.data, function(i, d) {
|
||||
me.reset_item_values(d);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
this.prepare_balances();
|
||||
if(me.tree_grid.show) {
|
||||
this.set_totals(false);
|
||||
this.set_totals(false);
|
||||
this.update_groups();
|
||||
} else {
|
||||
this.set_totals(true);
|
||||
@ -201,14 +201,14 @@ erpnext.PurchaseAnalytics = frappe.views.TreeGridReport.extend({
|
||||
var from_date = dateutil.str_to_obj(this.from_date);
|
||||
var to_date = dateutil.str_to_obj(this.to_date);
|
||||
var is_val = this.value_or_qty == 'Value';
|
||||
|
||||
|
||||
$.each(this.tl[this.based_on], function(i, tl) {
|
||||
if (me.is_default('company') ? true : tl.company === me.company) {
|
||||
if (me.is_default('company') ? true : tl.company === me.company) {
|
||||
var posting_date = dateutil.str_to_obj(tl.posting_date);
|
||||
if (posting_date >= from_date && posting_date <= to_date) {
|
||||
var item = me.item_by_name[tl[me.tree_grid.item_key]] ||
|
||||
var item = me.item_by_name[tl[me.tree_grid.item_key]] ||
|
||||
me.item_by_name['Not Set'];
|
||||
item[me.column_map[tl.posting_date].field] += (is_val ? tl.amount : tl.qty);
|
||||
item[me.column_map[tl.posting_date].field] += (is_val ? tl.base_amount : tl.qty);
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -220,10 +220,10 @@ erpnext.PurchaseAnalytics = frappe.views.TreeGridReport.extend({
|
||||
var parent = me.parent_map[item.name];
|
||||
while(parent) {
|
||||
parent_group = me.item_by_name[parent];
|
||||
|
||||
|
||||
$.each(me.columns, function(c, col) {
|
||||
if (col.formatter == me.currency_formatter) {
|
||||
parent_group[col.field] =
|
||||
parent_group[col.field] =
|
||||
flt(parent_group[col.field])
|
||||
+ flt(item[col.field]);
|
||||
}
|
||||
@ -235,10 +235,10 @@ erpnext.PurchaseAnalytics = frappe.views.TreeGridReport.extend({
|
||||
set_totals: function(sort) {
|
||||
var me = this;
|
||||
var checked = false;
|
||||
$.each(this.data, function(i, d) {
|
||||
$.each(this.data, function(i, d) {
|
||||
d.total = 0.0;
|
||||
$.each(me.columns, function(i, col) {
|
||||
if(col.formatter==me.currency_formatter && !col.hidden && col.field!="total")
|
||||
if(col.formatter==me.currency_formatter && !col.hidden && col.field!="total")
|
||||
d.total += d[col.field];
|
||||
if(d.checked) checked = true;
|
||||
})
|
||||
@ -251,7 +251,7 @@ erpnext.PurchaseAnalytics = frappe.views.TreeGridReport.extend({
|
||||
}
|
||||
},
|
||||
get_plot_points: function(item, col, idx) {
|
||||
return [[dateutil.str_to_obj(col.id).getTime(), item[col.field]],
|
||||
return [[dateutil.str_to_obj(col.id).getTime(), item[col.field]],
|
||||
[dateutil.user_to_obj(col.name).getTime(), item[col.field]]];
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@ -156,6 +156,11 @@ def get_data():
|
||||
"name": "Industry Type",
|
||||
"description": _("Track Leads by Industry Type.")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "SMS Settings",
|
||||
"description": _("Setup SMS gateway settings")
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -83,6 +83,11 @@ def get_data():
|
||||
"name": "Jobs Email Settings",
|
||||
"description": _("Setup incoming server for jobs email id. (e.g. jobs@example.com)")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "SMS Settings",
|
||||
"description": _("Setup SMS gateway settings")
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -97,11 +97,17 @@ class AccountsController(TransactionBase):
|
||||
args = item.as_dict()
|
||||
args.update(parent_dict)
|
||||
ret = get_item_details(args)
|
||||
|
||||
for fieldname, value in ret.items():
|
||||
if item.meta.get_field(fieldname) and \
|
||||
item.get(fieldname) is None and value is not None:
|
||||
item.set(fieldname, value)
|
||||
|
||||
if ret.get("pricing_rule"):
|
||||
for field in ["base_price_list_rate", "price_list_rate",
|
||||
"discount_percentage", "base_rate", "rate"]:
|
||||
item.set(field, ret.get(field))
|
||||
|
||||
def set_taxes(self, tax_parentfield, tax_master_field):
|
||||
if not self.meta.get_field(tax_parentfield):
|
||||
return
|
||||
@ -409,7 +415,7 @@ class AccountsController(TransactionBase):
|
||||
|
||||
if total_billed_amt - max_allowed_amt > 0.01:
|
||||
reduce_by = total_billed_amt - max_allowed_amt
|
||||
frappe.throw(_("Cannot overbill for Item {0} in row {0} more than {1}. To allow overbilling, please set in 'Setup' > 'Global Defaults'").format(item.item_code, item.row, max_allowed_amt))
|
||||
frappe.throw(_("Cannot overbill for Item {0} in row {0} more than {1}. To allow overbilling, please set in Stock Settings").format(item.item_code, item.idx, max_allowed_amt))
|
||||
|
||||
def get_company_default(self, fieldname):
|
||||
from erpnext.accounts.utils import get_company_default
|
||||
|
@ -234,3 +234,15 @@ def get_batch_no(doctype, txt, searchfield, start, page_len, filters):
|
||||
'posting_date': filters['posting_date'], 'txt': "%%%s%%" % txt,
|
||||
'mcond':get_match_cond(doctype),'start': start,
|
||||
'page_len': page_len})
|
||||
|
||||
def get_account_list(doctype, txt, searchfield, start, page_len, filters):
|
||||
if isinstance(filters, dict):
|
||||
if not filters.get("group_or_ledger"):
|
||||
filters["group_or_ledger"] = "Ledger"
|
||||
elif isinstance(filters, list):
|
||||
if "group_or_ledger" not in [d[0] for d in filters]:
|
||||
filters.append(["Account", "group_or_ledger", "=", "Ledger"])
|
||||
|
||||
return frappe.widgets.reportview.execute("Account", filters = filters,
|
||||
fields = ["name", "parent_account"],
|
||||
limit_start=start, limit_page_length=page_len, as_list=True)
|
||||
|
@ -156,8 +156,8 @@ class StatusUpdater(Document):
|
||||
item['max_allowed'] = flt(item[args['target_ref_field']] * (100+tolerance)/100)
|
||||
item['reduce_by'] = item[args['target_field']] - item['max_allowed']
|
||||
|
||||
msgprint(_("Allowance for over-delivery / over-billing crossed for Item {0}").format(item["item_code"]))
|
||||
throw(_("{0} must be less than or equal to {1}").format(_(item["target_ref_field"]), item[args["max_allowed"]]))
|
||||
msgprint(_("Allowance for over-delivery / over-billing crossed for Item {0}.").format(item["item_code"]))
|
||||
throw(_("{0} must be less than or equal to {1}").format(item["target_ref_field"].title(), item["max_allowed"]))
|
||||
|
||||
def update_qty(self, change_modified=True):
|
||||
"""
|
||||
|
@ -4,11 +4,11 @@
|
||||
// On REFRESH
|
||||
cur_frm.cscript.refresh = function(doc,dt,dn){
|
||||
cur_frm.toggle_enable("item", doc.__islocal);
|
||||
|
||||
|
||||
if (!doc.__islocal && doc.docstatus<2) {
|
||||
cur_frm.add_custom_button(__("Update Cost"), cur_frm.cscript.update_cost);
|
||||
}
|
||||
|
||||
|
||||
cur_frm.cscript.with_operations(doc);
|
||||
set_operation_no(doc);
|
||||
}
|
||||
@ -41,14 +41,14 @@ var set_operation_no = function(doc) {
|
||||
var op = op_table[i].operation_no;
|
||||
if (op && !inList(operations, op)) operations.push(op);
|
||||
}
|
||||
|
||||
frappe.meta.get_docfield("BOM Item", "operation_no",
|
||||
|
||||
frappe.meta.get_docfield("BOM Item", "operation_no",
|
||||
cur_frm.docname).options = operations.join("\n");
|
||||
|
||||
|
||||
$.each(doc.bom_materials || [], function(i, v) {
|
||||
if(!inList(operations, cstr(v.operation_no))) v.operation_no = null;
|
||||
});
|
||||
|
||||
|
||||
refresh_field("bom_materials");
|
||||
}
|
||||
|
||||
@ -97,7 +97,7 @@ var get_bom_material_detail= function(doc, cdt, cdn) {
|
||||
doc: cur_frm.doc,
|
||||
method: "get_bom_material_detail",
|
||||
args: {
|
||||
'item_code': d.item_code,
|
||||
'item_code': d.item_code,
|
||||
'bom_no': d.bom_no != null ? d.bom_no: '',
|
||||
'qty': d.qty
|
||||
},
|
||||
@ -131,7 +131,7 @@ cur_frm.cscript.rate = function(doc, cdt, cdn) {
|
||||
}
|
||||
}
|
||||
|
||||
var calculate_op_cost = function(doc) {
|
||||
var calculate_op_cost = function(doc) {
|
||||
var op = doc.bom_operations || [];
|
||||
total_op_cost = 0;
|
||||
for(var i=0;i<op.length;i++) {
|
||||
@ -143,13 +143,13 @@ var calculate_op_cost = function(doc) {
|
||||
refresh_field('operating_cost');
|
||||
}
|
||||
|
||||
var calculate_rm_cost = function(doc) {
|
||||
var calculate_rm_cost = function(doc) {
|
||||
var rm = doc.bom_materials || [];
|
||||
total_rm_cost = 0;
|
||||
for(var i=0;i<rm.length;i++) {
|
||||
amt = flt(rm[i].rate) * flt(rm[i].qty);
|
||||
set_multiple('BOM Item',rm[i].name, {'amount': amt}, 'bom_materials');
|
||||
set_multiple('BOM Item',rm[i].name,
|
||||
set_multiple('BOM Item',rm[i].name,
|
||||
{'qty_consumed_per_unit': flt(rm[i].qty)/flt(doc.quantity)}, 'bom_materials');
|
||||
total_rm_cost += amt;
|
||||
}
|
||||
@ -196,7 +196,7 @@ cur_frm.fields_dict['bom_materials'].grid.get_field('bom_no').get_query = functi
|
||||
'is_active': 1,
|
||||
'docstatus': 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cur_frm.cscript.validate = function(doc, dt, dn) {
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe.utils import cint, cstr, flt, now, nowdate
|
||||
from frappe.utils import cint, cstr, flt
|
||||
|
||||
from frappe import _
|
||||
from frappe.model.document import Document
|
||||
@ -54,7 +54,7 @@ class BOM(Document):
|
||||
def get_item_det(self, item_code):
|
||||
item = frappe.db.sql("""select name, is_asset_item, is_purchase_item,
|
||||
docstatus, description, is_sub_contracted_item, stock_uom, default_bom,
|
||||
last_purchase_rate, standard_rate, is_manufactured_item
|
||||
last_purchase_rate, is_manufactured_item
|
||||
from `tabItem` where name=%s""", item_code, as_dict = 1)
|
||||
|
||||
return item
|
||||
@ -111,8 +111,6 @@ class BOM(Document):
|
||||
frappe.throw(_("Please select Price List"))
|
||||
rate = frappe.db.get_value("Item Price", {"price_list": self.buying_price_list,
|
||||
"item_code": arg["item_code"]}, "price_list_rate") or 0
|
||||
elif self.rm_cost_as_per == 'Standard Rate':
|
||||
rate = arg['standard_rate']
|
||||
|
||||
return rate
|
||||
|
||||
@ -134,26 +132,15 @@ class BOM(Document):
|
||||
return bom and bom[0]['unit_cost'] or 0
|
||||
|
||||
def get_valuation_rate(self, args):
|
||||
""" Get average valuation rate of relevant warehouses
|
||||
as per valuation method (MAR/FIFO)
|
||||
as on costing date
|
||||
"""
|
||||
from erpnext.stock.utils import get_incoming_rate
|
||||
posting_date, posting_time = nowdate(), now().split()[1]
|
||||
warehouse = frappe.db.sql("select warehouse from `tabBin` where item_code = %s", args['item_code'])
|
||||
rate = []
|
||||
for wh in warehouse:
|
||||
r = get_incoming_rate({
|
||||
"item_code": args.get("item_code"),
|
||||
"warehouse": wh[0],
|
||||
"posting_date": posting_date,
|
||||
"posting_time": posting_time,
|
||||
"qty": args.get("qty") or 0
|
||||
})
|
||||
if r:
|
||||
rate.append(r)
|
||||
""" Get weighted average of valuation rate from all warehouses """
|
||||
|
||||
return rate and flt(sum(rate))/len(rate) or 0
|
||||
total_qty, total_value = 0.0, 0.0
|
||||
for d in frappe.db.sql("""select actual_qty, stock_value from `tabBin`
|
||||
where item_code=%s and actual_qty > 0""", args['item_code'], as_dict=1):
|
||||
total_qty += flt(d.actual_qty)
|
||||
total_value += flt(d.stock_value)
|
||||
|
||||
return total_value / total_qty if total_qty else 0.0
|
||||
|
||||
def manage_default_bom(self):
|
||||
""" Uncheck others if current one is selected as default,
|
||||
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"creation": "2013-02-22 01:27:49.000000",
|
||||
"creation": "2013-02-22 01:27:49",
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"fields": [
|
||||
@ -79,7 +79,8 @@
|
||||
"fieldtype": "Float",
|
||||
"in_list_view": 1,
|
||||
"label": "Rate",
|
||||
"permlevel": 0
|
||||
"permlevel": 0,
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "col_break2",
|
||||
@ -133,9 +134,12 @@
|
||||
],
|
||||
"idx": 1,
|
||||
"istable": 1,
|
||||
"modified": "2014-02-03 12:47:39.000000",
|
||||
"modified": "2014-05-29 15:56:31.859868",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Manufacturing",
|
||||
"name": "BOM Item",
|
||||
"owner": "Administrator"
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC"
|
||||
}
|
@ -194,6 +194,7 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({
|
||||
}
|
||||
|
||||
this.frm.script_manager.trigger("currency");
|
||||
this.apply_pricing_rule()
|
||||
}
|
||||
},
|
||||
|
||||
@ -225,7 +226,9 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({
|
||||
this.frm.doc.plc_conversion_rate !== this.frm.doc.conversion_rate) {
|
||||
this.frm.set_value("plc_conversion_rate", this.frm.doc.conversion_rate);
|
||||
}
|
||||
if(flt(this.frm.doc.conversion_rate)>0.0) this.calculate_taxes_and_totals();
|
||||
if(flt(this.frm.doc.conversion_rate)>0.0) {
|
||||
this.apply_pricing_rule();
|
||||
}
|
||||
},
|
||||
|
||||
get_price_list_currency: function(buying_or_selling) {
|
||||
@ -278,12 +281,12 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({
|
||||
}
|
||||
if(this.frm.doc.price_list_currency === this.frm.doc.currency) {
|
||||
this.frm.set_value("conversion_rate", this.frm.doc.plc_conversion_rate);
|
||||
this.calculate_taxes_and_totals();
|
||||
this.apply_pricing_rule();
|
||||
}
|
||||
},
|
||||
|
||||
qty: function(doc, cdt, cdn) {
|
||||
this.calculate_taxes_and_totals();
|
||||
this.apply_pricing_rule(frappe.get_doc(cdt, cdn));
|
||||
},
|
||||
|
||||
// tax rate
|
||||
@ -326,6 +329,53 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({
|
||||
this.calculate_taxes_and_totals();
|
||||
},
|
||||
|
||||
apply_pricing_rule: function(item) {
|
||||
var me = this;
|
||||
|
||||
var _apply_pricing_rule = function(item) {
|
||||
return me.frm.call({
|
||||
method: "erpnext.stock.get_item_details.apply_pricing_rule",
|
||||
child: item,
|
||||
args: {
|
||||
args: {
|
||||
item_code: item.item_code,
|
||||
item_group: item.item_group,
|
||||
brand: item.brand,
|
||||
qty: item.qty,
|
||||
customer: me.frm.doc.customer,
|
||||
customer_group: me.frm.doc.customer_group,
|
||||
territory: me.frm.doc.territory,
|
||||
supplier: me.frm.doc.supplier,
|
||||
supplier_type: me.frm.doc.supplier_type,
|
||||
currency: me.frm.doc.currency,
|
||||
conversion_rate: me.frm.doc.conversion_rate,
|
||||
price_list: me.frm.doc.selling_price_list ||
|
||||
me.frm.doc.buying_price_list,
|
||||
plc_conversion_rate: me.frm.doc.plc_conversion_rate,
|
||||
company: me.frm.doc.company,
|
||||
transaction_date: me.frm.doc.transaction_date || me.frm.doc.posting_date,
|
||||
campaign: me.frm.doc.campaign,
|
||||
sales_partner: me.frm.doc.sales_partner
|
||||
}
|
||||
},
|
||||
callback: function(r) {
|
||||
if(!r.exc) {
|
||||
me.frm.script_manager.trigger("price_list_rate", item.doctype, item.name);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
if(item) {
|
||||
_apply_pricing_rule(item);
|
||||
} else {
|
||||
$.each(this.get_item_doclist(), function(n, item) {
|
||||
_apply_pricing_rule(item);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
included_in_print_rate: function(doc, cdt, cdn) {
|
||||
var tax = frappe.get_doc(cdt, cdn);
|
||||
try {
|
||||
|
@ -2,7 +2,7 @@
|
||||
// License: GNU General Public License v3. See license.txt
|
||||
|
||||
frappe.provide("erpnext.utils");
|
||||
erpnext.utils.get_party_details = function(frm, method, args) {
|
||||
erpnext.utils.get_party_details = function(frm, method, args, callback) {
|
||||
if(!method) {
|
||||
method = "erpnext.accounts.party.get_party_details";
|
||||
}
|
||||
@ -33,6 +33,7 @@ erpnext.utils.get_party_details = function(frm, method, args) {
|
||||
frm.updating_party_details = true;
|
||||
frm.set_value(r.message);
|
||||
frm.updating_party_details = false;
|
||||
if(callback) callback();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"autoname": "QUOD/.#####",
|
||||
"creation": "2013-03-07 11:42:57.000000",
|
||||
"creation": "2013-03-07 11:42:57",
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"fields": [
|
||||
@ -231,17 +231,9 @@
|
||||
"width": "100px"
|
||||
},
|
||||
{
|
||||
"fieldname": "pricing_rule_for_price",
|
||||
"fieldname": "pricing_rule",
|
||||
"fieldtype": "Link",
|
||||
"label": "Pricing Rule For Price",
|
||||
"options": "Pricing Rule",
|
||||
"permlevel": 0,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "pricing_rule_for_discount",
|
||||
"fieldtype": "Link",
|
||||
"label": "Pricing Rule For Discount",
|
||||
"label": "Pricing Rule",
|
||||
"options": "Pricing Rule",
|
||||
"permlevel": 0,
|
||||
"read_only": 1
|
||||
@ -353,9 +345,12 @@
|
||||
],
|
||||
"idx": 1,
|
||||
"istable": 1,
|
||||
"modified": "2014-02-28 11:20:34.000000",
|
||||
"modified": "2014-05-28 12:41:40.811916",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Selling",
|
||||
"name": "Quotation Item",
|
||||
"owner": "Administrator"
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC"
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"autoname": "SOD/.#####",
|
||||
"creation": "2013-03-07 11:42:58.000000",
|
||||
"creation": "2013-03-07 11:42:58",
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"fields": [
|
||||
@ -217,17 +217,9 @@
|
||||
"width": "100px"
|
||||
},
|
||||
{
|
||||
"fieldname": "pricing_rule_for_price",
|
||||
"fieldname": "pricing_rule",
|
||||
"fieldtype": "Link",
|
||||
"label": "Pricing Rule For Price",
|
||||
"options": "Pricing Rule",
|
||||
"permlevel": 0,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "pricing_rule_for_discount",
|
||||
"fieldtype": "Link",
|
||||
"label": "Pricing Rule For Discount",
|
||||
"label": "Pricing Rule",
|
||||
"options": "Pricing Rule",
|
||||
"permlevel": 0,
|
||||
"read_only": 1
|
||||
@ -439,9 +431,12 @@
|
||||
],
|
||||
"idx": 1,
|
||||
"istable": 1,
|
||||
"modified": "2014-02-28 11:20:05.000000",
|
||||
"modified": "2014-05-27 14:41:14.996650",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Selling",
|
||||
"name": "Sales Order Item",
|
||||
"owner": "Administrator"
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC"
|
||||
}
|
@ -1,17 +1,17 @@
|
||||
// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
// License: GNU General Public License v3. See license.txt
|
||||
|
||||
frappe.pages['sales-analytics'].onload = function(wrapper) {
|
||||
frappe.pages['sales-analytics'].onload = function(wrapper) {
|
||||
frappe.ui.make_app_page({
|
||||
parent: wrapper,
|
||||
title: __('Sales Analytics'),
|
||||
single_column: true
|
||||
});
|
||||
new erpnext.SalesAnalytics(wrapper);
|
||||
|
||||
|
||||
|
||||
wrapper.appframe.add_module_icon("Selling")
|
||||
|
||||
|
||||
}
|
||||
|
||||
erpnext.SalesAnalytics = frappe.views.TreeGridReport.extend({
|
||||
@ -21,55 +21,55 @@ erpnext.SalesAnalytics = frappe.views.TreeGridReport.extend({
|
||||
page: wrapper,
|
||||
parent: $(wrapper).find('.layout-main'),
|
||||
appframe: wrapper.appframe,
|
||||
doctypes: ["Item", "Item Group", "Customer", "Customer Group", "Company", "Territory",
|
||||
"Fiscal Year", "Sales Invoice", "Sales Invoice Item",
|
||||
"Sales Order", "Sales Order Item[Sales Analytics]",
|
||||
doctypes: ["Item", "Item Group", "Customer", "Customer Group", "Company", "Territory",
|
||||
"Fiscal Year", "Sales Invoice", "Sales Invoice Item",
|
||||
"Sales Order", "Sales Order Item[Sales Analytics]",
|
||||
"Delivery Note", "Delivery Note Item[Sales Analytics]"],
|
||||
tree_grid: { show: true }
|
||||
});
|
||||
|
||||
|
||||
this.tree_grids = {
|
||||
"Customer Group": {
|
||||
label: __("Customer Group / Customer"),
|
||||
show: true,
|
||||
show: true,
|
||||
item_key: "customer",
|
||||
parent_field: "parent_customer_group",
|
||||
parent_field: "parent_customer_group",
|
||||
formatter: function(item) { return item.name; }
|
||||
},
|
||||
"Customer": {
|
||||
label: __("Customer"),
|
||||
show: false,
|
||||
show: false,
|
||||
item_key: "customer",
|
||||
formatter: function(item) {
|
||||
return item.name;
|
||||
}
|
||||
},
|
||||
},
|
||||
"Item Group": {
|
||||
label: __("Item"),
|
||||
show: true,
|
||||
parent_field: "parent_item_group",
|
||||
show: true,
|
||||
parent_field: "parent_item_group",
|
||||
item_key: "item_code",
|
||||
formatter: function(item) {
|
||||
return item.name;
|
||||
}
|
||||
},
|
||||
},
|
||||
"Item": {
|
||||
label: __("Item"),
|
||||
show: false,
|
||||
show: false,
|
||||
item_key: "item_code",
|
||||
formatter: function(item) {
|
||||
return item.name;
|
||||
}
|
||||
},
|
||||
},
|
||||
"Territory": {
|
||||
label: __("Territory / Customer"),
|
||||
show: true,
|
||||
show: true,
|
||||
item_key: "customer",
|
||||
parent_field: "parent_territory",
|
||||
parent_field: "parent_territory",
|
||||
formatter: function(item) {
|
||||
return item.name;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
setup_columns: function() {
|
||||
@ -84,24 +84,24 @@ erpnext.SalesAnalytics = frappe.views.TreeGridReport.extend({
|
||||
formatter: this.currency_formatter}
|
||||
];
|
||||
|
||||
this.make_date_range_columns();
|
||||
this.make_date_range_columns();
|
||||
this.columns = std_columns.concat(this.columns);
|
||||
},
|
||||
filters: [
|
||||
{fieldtype:"Select", fieldname: "tree_type", label: __("Tree Type"), options:["Customer Group", "Customer",
|
||||
{fieldtype:"Select", fieldname: "tree_type", label: __("Tree Type"), options:["Customer Group", "Customer",
|
||||
"Item Group", "Item", "Territory"],
|
||||
filter: function(val, item, opts, me) {
|
||||
return me.apply_zero_filter(val, item, opts, me);
|
||||
}},
|
||||
{fieldtype:"Select", fieldname: "based_on", label: __("Based On"), options:["Sales Invoice",
|
||||
{fieldtype:"Select", fieldname: "based_on", label: __("Based On"), options:["Sales Invoice",
|
||||
"Sales Order", "Delivery Note"]},
|
||||
{fieldtype:"Select", fieldname: "value_or_qty", label: __("Value or Qty"), options:["Value", "Quantity"]},
|
||||
{fieldtype:"Select", fieldname: "company", label: __("Company"), link:"Company",
|
||||
{fieldtype:"Select", fieldname: "company", label: __("Company"), link:"Company",
|
||||
default_value: "Select Company..."},
|
||||
{fieldtype:"Date", fieldname: "from_date", label: __("From Date")},
|
||||
{fieldtype:"Label", fieldname: "to", label: __("To")},
|
||||
{fieldtype:"Date", fieldname: "to_date", label: __("To Date")},
|
||||
{fieldtype:"Select", fieldname: "range", label: __("Range"),
|
||||
{fieldtype:"Select", fieldname: "range", label: __("Range"),
|
||||
options:["Daily", "Weekly", "Monthly", "Quarterly", "Yearly"]},
|
||||
{fieldtype:"Button", fieldname: "refresh", label: __("Refresh"), icon:"icon-refresh"},
|
||||
{fieldtype:"Button", fieldname: "reset_filters", label: __("Reset Filters"), icon:"icon-filter"}
|
||||
@ -109,10 +109,10 @@ erpnext.SalesAnalytics = frappe.views.TreeGridReport.extend({
|
||||
setup_filters: function() {
|
||||
var me = this;
|
||||
this._super();
|
||||
|
||||
|
||||
this.trigger_refresh_on_change(["value_or_qty", "tree_type", "based_on", "company"]);
|
||||
|
||||
this.show_zero_check()
|
||||
this.show_zero_check()
|
||||
this.setup_plot_check();
|
||||
},
|
||||
init_filter_values: function() {
|
||||
@ -125,14 +125,14 @@ erpnext.SalesAnalytics = frappe.views.TreeGridReport.extend({
|
||||
// add 'Not Set' Customer & Item
|
||||
// (Customer / Item are not mandatory!!)
|
||||
frappe.report_dump.data["Customer"].push({
|
||||
name: "Not Set",
|
||||
name: "Not Set",
|
||||
parent_customer_group: "All Customer Groups",
|
||||
parent_territory: "All Territories",
|
||||
id: "Not Set",
|
||||
});
|
||||
|
||||
frappe.report_dump.data["Item"].push({
|
||||
name: "Not Set",
|
||||
name: "Not Set",
|
||||
parent_item_group: "All Item Groups",
|
||||
id: "Not Set",
|
||||
});
|
||||
@ -141,7 +141,7 @@ erpnext.SalesAnalytics = frappe.views.TreeGridReport.extend({
|
||||
if (!this.tl || !this.tl[this.based_on]) {
|
||||
this.make_transaction_list(this.based_on, this.based_on + " Item");
|
||||
}
|
||||
|
||||
|
||||
if(!this.data || me.item_type != me.tree_type) {
|
||||
if(me.tree_type=='Customer') {
|
||||
var items = frappe.report_dump.data["Customer"];
|
||||
@ -159,7 +159,7 @@ erpnext.SalesAnalytics = frappe.views.TreeGridReport.extend({
|
||||
me.parent_map = {};
|
||||
me.item_by_name = {};
|
||||
me.data = [];
|
||||
|
||||
|
||||
$.each(items, function(i, v) {
|
||||
var d = copy_dict(v);
|
||||
|
||||
@ -169,20 +169,20 @@ erpnext.SalesAnalytics = frappe.views.TreeGridReport.extend({
|
||||
me.parent_map[d.name] = d[me.tree_grid.parent_field];
|
||||
}
|
||||
me.reset_item_values(d);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
this.set_indent();
|
||||
|
||||
|
||||
} else {
|
||||
// otherwise, only reset values
|
||||
$.each(this.data, function(i, d) {
|
||||
me.reset_item_values(d);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
this.prepare_balances();
|
||||
if(me.tree_grid.show) {
|
||||
this.set_totals(false);
|
||||
this.set_totals(false);
|
||||
this.update_groups();
|
||||
} else {
|
||||
this.set_totals(true);
|
||||
@ -194,14 +194,14 @@ erpnext.SalesAnalytics = frappe.views.TreeGridReport.extend({
|
||||
var from_date = dateutil.str_to_obj(this.from_date);
|
||||
var to_date = dateutil.str_to_obj(this.to_date);
|
||||
var is_val = this.value_or_qty == 'Value';
|
||||
|
||||
|
||||
$.each(this.tl[this.based_on], function(i, tl) {
|
||||
if (me.is_default('company') ? true : tl.company === me.company) {
|
||||
if (me.is_default('company') ? true : tl.company === me.company) {
|
||||
var posting_date = dateutil.str_to_obj(tl.posting_date);
|
||||
if (posting_date >= from_date && posting_date <= to_date) {
|
||||
var item = me.item_by_name[tl[me.tree_grid.item_key]] ||
|
||||
var item = me.item_by_name[tl[me.tree_grid.item_key]] ||
|
||||
me.item_by_name['Not Set'];
|
||||
item[me.column_map[tl.posting_date].field] += (is_val ? tl.amount : tl.qty);
|
||||
item[me.column_map[tl.posting_date].field] += (is_val ? tl.base_amount : tl.qty);
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -213,10 +213,10 @@ erpnext.SalesAnalytics = frappe.views.TreeGridReport.extend({
|
||||
var parent = me.parent_map[item.name];
|
||||
while(parent) {
|
||||
parent_group = me.item_by_name[parent];
|
||||
|
||||
|
||||
$.each(me.columns, function(c, col) {
|
||||
if (col.formatter == me.currency_formatter) {
|
||||
parent_group[col.field] =
|
||||
parent_group[col.field] =
|
||||
flt(parent_group[col.field])
|
||||
+ flt(item[col.field]);
|
||||
}
|
||||
@ -228,10 +228,10 @@ erpnext.SalesAnalytics = frappe.views.TreeGridReport.extend({
|
||||
set_totals: function(sort) {
|
||||
var me = this;
|
||||
var checked = false;
|
||||
$.each(this.data, function(i, d) {
|
||||
$.each(this.data, function(i, d) {
|
||||
d.total = 0.0;
|
||||
$.each(me.columns, function(i, col) {
|
||||
if(col.formatter==me.currency_formatter && !col.hidden && col.field!="total")
|
||||
if(col.formatter==me.currency_formatter && !col.hidden && col.field!="total")
|
||||
d.total += d[col.field];
|
||||
if(d.checked) checked = true;
|
||||
})
|
||||
@ -244,7 +244,7 @@ erpnext.SalesAnalytics = frappe.views.TreeGridReport.extend({
|
||||
}
|
||||
},
|
||||
get_plot_points: function(item, col, idx) {
|
||||
return [[dateutil.str_to_obj(col.id).getTime(), item[col.field]],
|
||||
return [[dateutil.str_to_obj(col.id).getTime(), item[col.field]],
|
||||
[dateutil.user_to_obj(col.name).getTime(), item[col.field]]];
|
||||
}
|
||||
});
|
||||
|
@ -104,7 +104,8 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({
|
||||
},
|
||||
|
||||
customer: function() {
|
||||
erpnext.utils.get_party_details(this.frm);
|
||||
var me = this;
|
||||
erpnext.utils.get_party_details(this.frm, null, null, function(){me.apply_pricing_rule()});
|
||||
},
|
||||
|
||||
customer_address: function() {
|
||||
@ -119,6 +120,14 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({
|
||||
erpnext.utils.get_contact_details(this.frm);
|
||||
},
|
||||
|
||||
sales_partner: function() {
|
||||
this.apply_pricing_rule();
|
||||
},
|
||||
|
||||
campaign: function() {
|
||||
this.apply_pricing_rule();
|
||||
},
|
||||
|
||||
barcode: function(doc, cdt, cdn) {
|
||||
this.item_code(doc, cdt, cdn);
|
||||
},
|
||||
|
@ -18,14 +18,14 @@ data_map = {
|
||||
|
||||
# Accounts
|
||||
"Account": {
|
||||
"columns": ["name", "parent_account", "lft", "rgt", "report_type",
|
||||
"columns": ["name", "parent_account", "lft", "rgt", "report_type",
|
||||
"company", "group_or_ledger"],
|
||||
"conditions": ["docstatus < 2"],
|
||||
"order_by": "lft",
|
||||
"links": {
|
||||
"company": ["Company", "name"],
|
||||
}
|
||||
|
||||
|
||||
},
|
||||
"Cost Center": {
|
||||
"columns": ["name", "lft", "rgt"],
|
||||
@ -33,7 +33,7 @@ data_map = {
|
||||
"order_by": "lft"
|
||||
},
|
||||
"GL Entry": {
|
||||
"columns": ["name", "account", "posting_date", "cost_center", "debit", "credit",
|
||||
"columns": ["name", "account", "posting_date", "cost_center", "debit", "credit",
|
||||
"is_opening", "company", "voucher_type", "voucher_no", "remarks"],
|
||||
"order_by": "posting_date, account",
|
||||
"links": {
|
||||
@ -45,8 +45,8 @@ data_map = {
|
||||
|
||||
# Stock
|
||||
"Item": {
|
||||
"columns": ["name", "if(item_name=name, '', item_name) as item_name", "description",
|
||||
"item_group as parent_item_group", "stock_uom", "brand", "valuation_method",
|
||||
"columns": ["name", "if(item_name=name, '', item_name) as item_name", "description",
|
||||
"item_group as parent_item_group", "stock_uom", "brand", "valuation_method",
|
||||
"re_order_level", "re_order_qty"],
|
||||
# "conditions": ["docstatus < 2"],
|
||||
"order_by": "name",
|
||||
@ -76,7 +76,7 @@ data_map = {
|
||||
"order_by": "name"
|
||||
},
|
||||
"Stock Ledger Entry": {
|
||||
"columns": ["name", "posting_date", "posting_time", "item_code", "warehouse",
|
||||
"columns": ["name", "posting_date", "posting_time", "item_code", "warehouse",
|
||||
"actual_qty as qty", "voucher_type", "voucher_no", "project",
|
||||
"ifnull(incoming_rate,0) as incoming_rate", "stock_uom", "serial_no"],
|
||||
"order_by": "posting_date, posting_time, name",
|
||||
@ -98,8 +98,8 @@ data_map = {
|
||||
"order_by": "posting_date, posting_time, name",
|
||||
},
|
||||
"Production Order": {
|
||||
"columns": ["name", "production_item as item_code",
|
||||
"(ifnull(qty, 0) - ifnull(produced_qty, 0)) as qty",
|
||||
"columns": ["name", "production_item as item_code",
|
||||
"(ifnull(qty, 0) - ifnull(produced_qty, 0)) as qty",
|
||||
"fg_warehouse as warehouse"],
|
||||
"conditions": ["docstatus=1", "status != 'Stopped'", "ifnull(fg_warehouse, '')!=''",
|
||||
"ifnull(qty, 0) > ifnull(produced_qty, 0)"],
|
||||
@ -109,7 +109,7 @@ data_map = {
|
||||
},
|
||||
},
|
||||
"Material Request Item": {
|
||||
"columns": ["item.name as name", "item_code", "warehouse",
|
||||
"columns": ["item.name as name", "item_code", "warehouse",
|
||||
"(ifnull(qty, 0) - ifnull(ordered_qty, 0)) as qty"],
|
||||
"from": "`tabMaterial Request Item` item, `tabMaterial Request` main",
|
||||
"conditions": ["item.parent = main.name", "main.docstatus=1", "main.status != 'Stopped'",
|
||||
@ -120,21 +120,21 @@ data_map = {
|
||||
},
|
||||
},
|
||||
"Purchase Order Item": {
|
||||
"columns": ["item.name as name", "item_code", "warehouse",
|
||||
"columns": ["item.name as name", "item_code", "warehouse",
|
||||
"(ifnull(qty, 0) - ifnull(received_qty, 0)) as qty"],
|
||||
"from": "`tabPurchase Order Item` item, `tabPurchase Order` main",
|
||||
"conditions": ["item.parent = main.name", "main.docstatus=1", "main.status != 'Stopped'",
|
||||
"conditions": ["item.parent = main.name", "main.docstatus=1", "main.status != 'Stopped'",
|
||||
"ifnull(warehouse, '')!=''", "ifnull(qty, 0) > ifnull(received_qty, 0)"],
|
||||
"links": {
|
||||
"item_code": ["Item", "name"],
|
||||
"warehouse": ["Warehouse", "name"]
|
||||
},
|
||||
},
|
||||
|
||||
|
||||
"Sales Order Item": {
|
||||
"columns": ["item.name as name", "item_code", "(ifnull(qty, 0) - ifnull(delivered_qty, 0)) as qty", "warehouse"],
|
||||
"from": "`tabSales Order Item` item, `tabSales Order` main",
|
||||
"conditions": ["item.parent = main.name", "main.docstatus=1", "main.status != 'Stopped'",
|
||||
"conditions": ["item.parent = main.name", "main.docstatus=1", "main.status != 'Stopped'",
|
||||
"ifnull(warehouse, '')!=''", "ifnull(qty, 0) > ifnull(delivered_qty, 0)"],
|
||||
"links": {
|
||||
"item_code": ["Item", "name"],
|
||||
@ -144,7 +144,7 @@ data_map = {
|
||||
|
||||
# Sales
|
||||
"Customer": {
|
||||
"columns": ["name", "if(customer_name=name, '', customer_name) as customer_name",
|
||||
"columns": ["name", "if(customer_name=name, '', customer_name) as customer_name",
|
||||
"customer_group as parent_customer_group", "territory as parent_territory"],
|
||||
"conditions": ["docstatus < 2"],
|
||||
"order_by": "name",
|
||||
@ -218,7 +218,7 @@ data_map = {
|
||||
}
|
||||
},
|
||||
"Supplier": {
|
||||
"columns": ["name", "if(supplier_name=name, '', supplier_name) as supplier_name",
|
||||
"columns": ["name", "if(supplier_name=name, '', supplier_name) as supplier_name",
|
||||
"supplier_type as parent_supplier_type"],
|
||||
"conditions": ["docstatus < 2"],
|
||||
"order_by": "name",
|
||||
@ -291,5 +291,5 @@ data_map = {
|
||||
"conditions": ["docstatus < 2"],
|
||||
"order_by": "creation"
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"autoname": "DND/.#######",
|
||||
"creation": "2013-04-22 13:15:44.000000",
|
||||
"creation": "2013-04-22 13:15:44",
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"fields": [
|
||||
@ -225,17 +225,9 @@
|
||||
"width": "100px"
|
||||
},
|
||||
{
|
||||
"fieldname": "pricing_rule_for_price",
|
||||
"fieldname": "pricing_rule",
|
||||
"fieldtype": "Link",
|
||||
"label": "Pricing Rule For Price",
|
||||
"options": "Pricing Rule",
|
||||
"permlevel": 0,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "pricing_rule_for_discount",
|
||||
"fieldtype": "Link",
|
||||
"label": "Pricing Rule For Discount",
|
||||
"label": "Pricing Rule",
|
||||
"options": "Pricing Rule",
|
||||
"permlevel": 0,
|
||||
"read_only": 1
|
||||
@ -437,9 +429,12 @@
|
||||
],
|
||||
"idx": 1,
|
||||
"istable": 1,
|
||||
"modified": "2014-02-28 11:20:58.000000",
|
||||
"modified": "2014-05-28 12:42:05.788579",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Stock",
|
||||
"name": "Delivery Note Item",
|
||||
"owner": "Administrator"
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC"
|
||||
}
|
@ -439,16 +439,6 @@
|
||||
"permlevel": 0,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.is_purchase_item==\"Yes\"",
|
||||
"fieldname": "standard_rate",
|
||||
"fieldtype": "Float",
|
||||
"label": "Standard Rate",
|
||||
"oldfieldname": "standard_rate",
|
||||
"oldfieldtype": "Currency",
|
||||
"permlevel": 0,
|
||||
"read_only": 0
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.is_purchase_item==\"Yes\"",
|
||||
"fieldname": "column_break2",
|
||||
@ -835,7 +825,7 @@
|
||||
"icon": "icon-tag",
|
||||
"idx": 1,
|
||||
"max_attachments": 1,
|
||||
"modified": "2014-05-21 15:37:30.124881",
|
||||
"modified": "2014-05-29 16:05:53.126214",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Stock",
|
||||
"name": "Item",
|
||||
|
@ -137,7 +137,6 @@ class Item(WebsiteGenerator):
|
||||
bom = frappe.db.sql("""select name from `tabBOM` where item = %s
|
||||
and is_active = 1""", (self.name,))
|
||||
if bom and bom[0][0]:
|
||||
print self.name
|
||||
frappe.throw(_("""Allow Bill of Materials should be 'Yes'. Because one or many active BOMs present for this item"""))
|
||||
|
||||
def fill_customer_code(self):
|
||||
|
@ -141,7 +141,7 @@ class PackingSlip(Document):
|
||||
note
|
||||
"""
|
||||
recommended_case_no = frappe.db.sql("""SELECT MAX(to_case_no) FROM `tabPacking Slip`
|
||||
WHERE delivery_note = %(delivery_note)s AND docstatus=1""", self.as_dict())
|
||||
WHERE delivery_note = %s AND docstatus=1""", self.delivery_note)
|
||||
|
||||
return cint(recommended_case_no[0][0]) + 1
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"autoname": "GRND/.#######",
|
||||
"creation": "2013-05-24 19:29:10.000000",
|
||||
"creation": "2013-05-24 19:29:10",
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"fields": [
|
||||
@ -256,17 +256,9 @@
|
||||
"width": "100px"
|
||||
},
|
||||
{
|
||||
"fieldname": "pricing_rule_for_price",
|
||||
"fieldname": "pricing_rule",
|
||||
"fieldtype": "Link",
|
||||
"label": "Pricing Rule For Price",
|
||||
"options": "Pricing Rule",
|
||||
"permlevel": 0,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "pricing_rule_for_discount",
|
||||
"fieldtype": "Link",
|
||||
"label": "Pricing Rule For Discount",
|
||||
"label": "Pricing Rule",
|
||||
"options": "Pricing Rule",
|
||||
"permlevel": 0,
|
||||
"read_only": 1
|
||||
@ -553,9 +545,12 @@
|
||||
],
|
||||
"idx": 1,
|
||||
"istable": 1,
|
||||
"modified": "2014-02-28 11:27:09.000000",
|
||||
"modified": "2014-05-28 12:43:16.669040",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Stock",
|
||||
"name": "Purchase Receipt Item",
|
||||
"owner": "Administrator"
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC"
|
||||
}
|
@ -41,6 +41,7 @@ class StockEntry(StockController):
|
||||
self.validate_return_reference_doc()
|
||||
self.validate_with_material_request()
|
||||
self.validate_fiscal_year()
|
||||
self.validate_valuation_rate()
|
||||
self.set_total_amount()
|
||||
|
||||
def on_submit(self):
|
||||
@ -170,11 +171,26 @@ class StockEntry(StockController):
|
||||
frappe.throw(_("Stock Entries already created for Production Order ")
|
||||
+ self.production_order + ":" + ", ".join(other_ste), DuplicateEntryForProductionOrderError)
|
||||
|
||||
def validate_valuation_rate(self):
|
||||
if self.purpose == "Manufacture/Repack":
|
||||
valuation_at_source, valuation_at_target = 0, 0
|
||||
for d in self.get("mtn_details"):
|
||||
if d.s_warehouse and not d.t_warehouse:
|
||||
valuation_at_source += flt(d.amount)
|
||||
if d.t_warehouse and not d.s_warehouse:
|
||||
valuation_at_target += flt(d.amount)
|
||||
|
||||
if valuation_at_target < valuation_at_source:
|
||||
frappe.throw(_("Total valuation for manufactured or repacked item(s) can not be less than total valuation of raw materials"))
|
||||
|
||||
def set_total_amount(self):
|
||||
self.total_amount = sum([flt(item.amount) for item in self.get("mtn_details")])
|
||||
|
||||
def get_stock_and_rate(self):
|
||||
"""get stock and incoming rate on posting date"""
|
||||
|
||||
raw_material_cost = 0.0
|
||||
|
||||
for d in self.get('mtn_details'):
|
||||
args = frappe._dict({
|
||||
"item_code": d.item_code,
|
||||
@ -182,17 +198,28 @@ class StockEntry(StockController):
|
||||
"posting_date": self.posting_date,
|
||||
"posting_time": self.posting_time,
|
||||
"qty": d.s_warehouse and -1*d.transfer_qty or d.transfer_qty,
|
||||
"serial_no": d.serial_no,
|
||||
"bom_no": d.bom_no,
|
||||
"serial_no": d.serial_no
|
||||
})
|
||||
# get actual stock at source warehouse
|
||||
d.actual_qty = get_previous_sle(args).get("qty_after_transaction") or 0
|
||||
|
||||
# get incoming rate
|
||||
if not flt(d.incoming_rate):
|
||||
d.incoming_rate = self.get_incoming_rate(args)
|
||||
if not d.bom_no:
|
||||
if not flt(d.incoming_rate):
|
||||
d.incoming_rate = self.get_incoming_rate(args)
|
||||
|
||||
d.amount = flt(d.transfer_qty) * flt(d.incoming_rate)
|
||||
d.amount = flt(d.transfer_qty) * flt(d.incoming_rate)
|
||||
raw_material_cost += flt(d.amount)
|
||||
|
||||
# set incoming rate for fg item
|
||||
if self.production_order and self.purpose == "Manufacture/Repack":
|
||||
for d in self.get("mtn_details"):
|
||||
if d.bom_no:
|
||||
if not flt(d.incoming_rate):
|
||||
bom = frappe.db.get_value("BOM", d.bom_no, ["operating_cost", "quantity"], as_dict=1)
|
||||
operation_cost_per_unit = flt(bom.operating_cost) / flt(bom.quantity)
|
||||
d.incoming_rate = operation_cost_per_unit + (raw_material_cost / flt(d.transfer_qty))
|
||||
d.amount = flt(d.transfer_qty) * flt(d.incoming_rate)
|
||||
|
||||
def get_incoming_rate(self, args):
|
||||
incoming_rate = 0
|
||||
@ -365,17 +392,18 @@ class StockEntry(StockController):
|
||||
ret.update(stock_and_rate)
|
||||
return ret
|
||||
|
||||
def get_uom_details(self, arg = ''):
|
||||
arg, ret = eval(arg), {}
|
||||
uom = frappe.db.sql("""select conversion_factor from `tabUOM Conversion Detail`
|
||||
where parent = %s and uom = %s""", (arg['item_code'], arg['uom']), as_dict = 1)
|
||||
if not uom or not flt(uom[0].conversion_factor):
|
||||
frappe.msgprint(_("UOM coversion factor required for UOM {0} in Item {1}").format(arg["uom"], arg["item_code"]))
|
||||
def get_uom_details(self, args):
|
||||
conversion_factor = frappe.db.get_value("UOM Conversion Detail", {"parent": args.get("item_code"),
|
||||
"uom": args.get("uom")}, "conversion_factor")
|
||||
|
||||
if not conversion_factor:
|
||||
frappe.msgprint(_("UOM coversion factor required for UOM: {0} in Item: {1}")
|
||||
.format(args.get("uom"), args.get("item_code")))
|
||||
ret = {'uom' : ''}
|
||||
else:
|
||||
ret = {
|
||||
'conversion_factor' : flt(uom[0]['conversion_factor']),
|
||||
'transfer_qty' : flt(arg['qty']) * flt(uom[0]['conversion_factor']),
|
||||
'conversion_factor' : flt(conversion_factor),
|
||||
'transfer_qty' : flt(args.get("qty")) * flt(conversion_factor)
|
||||
}
|
||||
return ret
|
||||
|
||||
|
@ -11,8 +11,11 @@ from erpnext.stock.stock_ledger import update_entries_after
|
||||
from erpnext.controllers.stock_controller import StockController
|
||||
|
||||
class StockReconciliation(StockController):
|
||||
def validate(self):
|
||||
def __init__(self, arg1, arg2=None):
|
||||
super(StockReconciliation, self).__init__(arg1, arg2)
|
||||
self.head_row = ["Item Code", "Warehouse", "Quantity", "Valuation Rate"]
|
||||
|
||||
def validate(self):
|
||||
self.entries = []
|
||||
|
||||
self.validate_data()
|
||||
@ -300,4 +303,5 @@ class StockReconciliation(StockController):
|
||||
@frappe.whitelist()
|
||||
def upload():
|
||||
from frappe.utils.datautils import read_csv_content_from_uploaded_file
|
||||
return read_csv_content_from_uploaded_file()
|
||||
csv_content = read_csv_content_from_uploaded_file()
|
||||
return filter(lambda x: x and any(x), csv_content)
|
||||
|
@ -68,7 +68,12 @@ def get_item_details(args):
|
||||
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)
|
||||
# update args with out, if key or value not exists
|
||||
for key, value in out.iteritems():
|
||||
if args.get(key) is None:
|
||||
args[key] = value
|
||||
|
||||
out.update(apply_pricing_rule(args))
|
||||
|
||||
if args.get("doctype") in ("Sales Invoice", "Delivery Note"):
|
||||
if item_doc.has_serial_no == "Yes" and not args.serial_no:
|
||||
@ -243,36 +248,51 @@ def get_pos_settings(company):
|
||||
|
||||
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)
|
||||
all_pricing_rules = get_pricing_rules(args_dict)
|
||||
@frappe.whitelist()
|
||||
def apply_pricing_rule(args):
|
||||
if isinstance(args, basestring):
|
||||
args = json.loads(args)
|
||||
|
||||
rule_for_price = False
|
||||
for rule_for in ["price", "discount_percentage"]:
|
||||
pricing_rules = filter(lambda x: x[rule_for] > 0.0, all_pricing_rules)
|
||||
if rule_for_price:
|
||||
pricing_rules = filter(lambda x: not x["for_price_list"], pricing_rules)
|
||||
args = frappe._dict(args)
|
||||
out = frappe._dict()
|
||||
|
||||
pricing_rule = filter_pricing_rules(args_dict, pricing_rules)
|
||||
if not args.get("item_group") or not args.get("brand"):
|
||||
args.item_group, args.brand = frappe.db.get_value("Item",
|
||||
args.item_code, ["item_group", "brand"])
|
||||
|
||||
if pricing_rule:
|
||||
if rule_for == "discount_percentage":
|
||||
out["discount_percentage"] = pricing_rule["discount_percentage"]
|
||||
out["pricing_rule_for_discount"] = pricing_rule["name"]
|
||||
else:
|
||||
out["base_price_list_rate"] = pricing_rule["price"]
|
||||
out["price_list_rate"] = pricing_rule["price"] * \
|
||||
flt(args_dict.plc_conversion_rate) / flt(args_dict.conversion_rate)
|
||||
out["pricing_rule_for_price"] = pricing_rule["name"]
|
||||
rule_for_price = True
|
||||
if args.get("customer") and (not args.get("customer_group") or not args.get("territory")):
|
||||
args.customer_group, args.territory = frappe.db.get_value("Customer",
|
||||
args.customer, ["customer_group", "territory"])
|
||||
|
||||
def get_pricing_rules(args_dict):
|
||||
if args.get("supplier") and not args.get("supplier_type"):
|
||||
args.supplier_type = frappe.db.get_value("Supplier", args.supplier, "supplier_type")
|
||||
|
||||
pricing_rules = get_pricing_rules(args)
|
||||
|
||||
pricing_rule = filter_pricing_rules(args, pricing_rules)
|
||||
|
||||
if pricing_rule:
|
||||
out.pricing_rule = pricing_rule.name
|
||||
if pricing_rule.price_or_discount == "Price":
|
||||
out.base_price_list_rate = pricing_rule.price
|
||||
out.price_list_rate = pricing_rule.price*flt(args.plc_conversion_rate)/flt(args.conversion_rate)
|
||||
out.base_rate = out.base_price_list_rate
|
||||
out.rate = out.price_list_rate
|
||||
out.discount_percentage = 0.0
|
||||
else:
|
||||
out.discount_percentage = pricing_rule.discount_percentage
|
||||
else:
|
||||
out.pricing_rule = None
|
||||
|
||||
return out
|
||||
|
||||
|
||||
def get_pricing_rules(args):
|
||||
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"])
|
||||
if args.get(field):
|
||||
lft, rgt = frappe.db.get_value(doctype, args[field], ["lft", "rgt"])
|
||||
parent_groups = frappe.db.sql_list("""select name from `tab%s`
|
||||
where lft<=%s and rgt>=%s""" % (doctype, '%s', '%s'), (lft, rgt))
|
||||
|
||||
@ -284,8 +304,8 @@ def get_pricing_rules(args_dict):
|
||||
|
||||
|
||||
conditions = ""
|
||||
for field in ["customer", "supplier", "supplier_type", "campaign", "sales_partner"]:
|
||||
if args_dict.get(field):
|
||||
for field in ["company", "customer", "supplier", "supplier_type", "campaign", "sales_partner"]:
|
||||
if args.get(field):
|
||||
conditions += " and ifnull("+field+", '') in (%("+field+")s, '')"
|
||||
else:
|
||||
conditions += " and ifnull("+field+", '') = ''"
|
||||
@ -297,8 +317,7 @@ def get_pricing_rules(args_dict):
|
||||
|
||||
conditions += " and ifnull(for_price_list, '') in (%(price_list)s, '')"
|
||||
|
||||
|
||||
if args_dict.get("transaction_date"):
|
||||
if args.get("transaction_date"):
|
||||
conditions += """ and %(transaction_date)s between ifnull(valid_from, '2000-01-01')
|
||||
and ifnull(valid_upto, '2500-12-31')"""
|
||||
|
||||
@ -307,13 +326,13 @@ def get_pricing_rules(args_dict):
|
||||
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),
|
||||
args_dict, as_dict=1)
|
||||
args, as_dict=1)
|
||||
|
||||
def filter_pricing_rules(args_dict, pricing_rules):
|
||||
def filter_pricing_rules(args, pricing_rules):
|
||||
# filter for qty
|
||||
if pricing_rules and args_dict.get("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)
|
||||
if pricing_rules and args.get("qty"):
|
||||
pricing_rules = filter(lambda x: (args.qty>=flt(x.min_qty)
|
||||
and (args.qty<=x.max_qty if x.max_qty else True)), pricing_rules)
|
||||
|
||||
# find pricing rule with highest priority
|
||||
if pricing_rules:
|
||||
@ -323,16 +342,22 @@ def filter_pricing_rules(args_dict, pricing_rules):
|
||||
|
||||
# apply internal priority
|
||||
all_fields = ["item_code", "item_group", "brand", "customer", "customer_group", "territory",
|
||||
"supplier", "supplier_type", "campaign", "for_price_list", "sales_partner"]
|
||||
"supplier", "supplier_type", "campaign", "sales_partner"]
|
||||
|
||||
if len(pricing_rules) > 1:
|
||||
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):
|
||||
pricing_rules = apply_internal_priority(pricing_rules, field_set, args_dict)
|
||||
pricing_rules = apply_internal_priority(pricing_rules, field_set, args)
|
||||
break
|
||||
|
||||
if len(pricing_rules) > 1:
|
||||
price_or_discount = list(set([d.price_or_discount for d in pricing_rules]))
|
||||
if len(price_or_discount) == 1 and price_or_discount[0] == "Discount Percentage":
|
||||
pricing_rules = filter(lambda x: x.for_price_list==args.price_list, pricing_rules) \
|
||||
or pricing_rules
|
||||
|
||||
if len(pricing_rules) > 1:
|
||||
frappe.throw(_("Multiple Price Rule exists with same criteria, please resolve \
|
||||
conflict by assigning priority. Price Rules: {0}")
|
||||
@ -350,11 +375,11 @@ def if_all_rules_same(pricing_rules, fields):
|
||||
|
||||
return all_rules_same
|
||||
|
||||
def apply_internal_priority(pricing_rules, field_set, args_dict):
|
||||
def apply_internal_priority(pricing_rules, field_set, args):
|
||||
filtered_rules = []
|
||||
for field in field_set:
|
||||
if args_dict.get(field):
|
||||
filtered_rules = filter(lambda x: x[field]==args_dict[field], pricing_rules)
|
||||
if args.get(field):
|
||||
filtered_rules = filter(lambda x: x[field]==args[field], pricing_rules)
|
||||
if filtered_rules: break
|
||||
|
||||
return filtered_rules or pricing_rules
|
||||
|
@ -3,18 +3,18 @@
|
||||
|
||||
frappe.require("assets/erpnext/js/stock_analytics.js");
|
||||
|
||||
frappe.pages['stock-balance'].onload = function(wrapper) {
|
||||
frappe.pages['stock-balance'].onload = function(wrapper) {
|
||||
frappe.ui.make_app_page({
|
||||
parent: wrapper,
|
||||
title: __('Stock Balance'),
|
||||
single_column: true
|
||||
});
|
||||
|
||||
|
||||
new erpnext.StockBalance(wrapper);
|
||||
|
||||
|
||||
|
||||
wrapper.appframe.add_module_icon("Stock")
|
||||
|
||||
|
||||
}
|
||||
|
||||
erpnext.StockBalance = erpnext.StockAnalytics.extend({
|
||||
@ -30,40 +30,42 @@ erpnext.StockBalance = erpnext.StockAnalytics.extend({
|
||||
{id: "name", name: __("Item"), field: "name", width: 300,
|
||||
formatter: this.tree_formatter},
|
||||
{id: "item_name", name: __("Item Name"), field: "item_name", width: 100},
|
||||
{id: "description", name: __("Description"), field: "description", width: 200,
|
||||
{id: "description", name: __("Description"), field: "description", width: 200,
|
||||
formatter: this.text_formatter},
|
||||
{id: "brand", name: __("Brand"), field: "brand", width: 100},
|
||||
{id: "stock_uom", name: __("UOM"), field: "stock_uom", width: 100},
|
||||
{id: "opening_qty", name: __("Opening Qty"), field: "opening_qty", width: 100,
|
||||
{id: "opening_qty", name: __("Opening Qty"), field: "opening_qty", width: 100,
|
||||
formatter: this.currency_formatter},
|
||||
{id: "inflow_qty", name: __("In Qty"), field: "inflow_qty", width: 100,
|
||||
{id: "inflow_qty", name: __("In Qty"), field: "inflow_qty", width: 100,
|
||||
formatter: this.currency_formatter},
|
||||
{id: "outflow_qty", name: __("Out Qty"), field: "outflow_qty", width: 100,
|
||||
{id: "outflow_qty", name: __("Out Qty"), field: "outflow_qty", width: 100,
|
||||
formatter: this.currency_formatter},
|
||||
{id: "closing_qty", name: __("Closing Qty"), field: "closing_qty", width: 100,
|
||||
{id: "closing_qty", name: __("Closing Qty"), field: "closing_qty", width: 100,
|
||||
formatter: this.currency_formatter},
|
||||
|
||||
{id: "opening_value", name: __("Opening Value"), field: "opening_value", width: 100,
|
||||
|
||||
{id: "opening_value", name: __("Opening Value"), field: "opening_value", width: 100,
|
||||
formatter: this.currency_formatter},
|
||||
{id: "inflow_value", name: __("In Value"), field: "inflow_value", width: 100,
|
||||
{id: "inflow_value", name: __("In Value"), field: "inflow_value", width: 100,
|
||||
formatter: this.currency_formatter},
|
||||
{id: "outflow_value", name: __("Out Value"), field: "outflow_value", width: 100,
|
||||
{id: "outflow_value", name: __("Out Value"), field: "outflow_value", width: 100,
|
||||
formatter: this.currency_formatter},
|
||||
{id: "closing_value", name: __("Closing Value"), field: "closing_value", width: 100,
|
||||
{id: "closing_value", name: __("Closing Value"), field: "closing_value", width: 100,
|
||||
formatter: this.currency_formatter},
|
||||
{id: "valuation_rate", name: __("Valuation Rate"), field: "valuation_rate", width: 100,
|
||||
formatter: this.currency_formatter},
|
||||
];
|
||||
},
|
||||
|
||||
|
||||
filters: [
|
||||
{fieldtype:"Select", label: __("Brand"), link:"Brand",
|
||||
{fieldtype:"Select", label: __("Brand"), link:"Brand",
|
||||
default_value: "Select Brand...", filter: function(val, item, opts) {
|
||||
return val == opts.default_value || item.brand == val || item._show;
|
||||
}, link_formatter: {filter_input: "brand"}},
|
||||
{fieldtype:"Select", label: __("Warehouse"), link:"Warehouse",
|
||||
{fieldtype:"Select", label: __("Warehouse"), link:"Warehouse",
|
||||
default_value: "Select Warehouse...", filter: function(val, item, opts, me) {
|
||||
return me.apply_zero_filter(val, item, opts, me);
|
||||
}},
|
||||
{fieldtype:"Select", label: __("Project"), link:"Project",
|
||||
{fieldtype:"Select", label: __("Project"), link:"Project",
|
||||
default_value: "Select Project...", filter: function(val, item, opts, me) {
|
||||
return me.apply_zero_filter(val, item, opts, me);
|
||||
}, link_formatter: {filter_input: "project"}},
|
||||
@ -73,16 +75,16 @@ erpnext.StockBalance = erpnext.StockAnalytics.extend({
|
||||
{fieldtype:"Button", label: __("Refresh"), icon:"icon-refresh icon-white"},
|
||||
{fieldtype:"Button", label: __("Reset Filters"), icon: "icon-filter"}
|
||||
],
|
||||
|
||||
|
||||
setup_plot_check: function() {
|
||||
return;
|
||||
},
|
||||
|
||||
|
||||
prepare_data: function() {
|
||||
this.stock_entry_map = this.make_name_map(frappe.report_dump.data["Stock Entry"], "name");
|
||||
this._super();
|
||||
},
|
||||
|
||||
|
||||
prepare_balances: function() {
|
||||
var me = this;
|
||||
var from_date = dateutil.str_to_obj(this.from_date);
|
||||
@ -95,26 +97,26 @@ erpnext.StockBalance = erpnext.StockAnalytics.extend({
|
||||
for(var i=0, j=data.length; i<j; i++) {
|
||||
var sl = data[i];
|
||||
var sl_posting_date = dateutil.str_to_obj(sl.posting_date);
|
||||
|
||||
|
||||
if((me.is_default("warehouse") ? true : me.warehouse == sl.warehouse) &&
|
||||
(me.is_default("project") ? true : me.project == sl.project)) {
|
||||
var item = me.item_by_name[sl.item_code];
|
||||
var wh = me.get_item_warehouse(sl.warehouse, sl.item_code);
|
||||
var valuation_method = item.valuation_method ?
|
||||
var valuation_method = item.valuation_method ?
|
||||
item.valuation_method : sys_defaults.valuation_method;
|
||||
var is_fifo = valuation_method == "FIFO";
|
||||
|
||||
var qty_diff = sl.qty;
|
||||
var value_diff = me.get_value_diff(wh, sl, is_fifo);
|
||||
|
||||
|
||||
if(sl_posting_date < from_date) {
|
||||
item.opening_qty += qty_diff;
|
||||
item.opening_value += value_diff;
|
||||
} else if(sl_posting_date <= to_date) {
|
||||
var ignore_inflow_outflow = this.is_default("warehouse")
|
||||
&& sl.voucher_type=="Stock Entry"
|
||||
&& sl.voucher_type=="Stock Entry"
|
||||
&& this.stock_entry_map[sl.voucher_no].purpose=="Material Transfer";
|
||||
|
||||
|
||||
if(!ignore_inflow_outflow) {
|
||||
if(qty_diff < 0) {
|
||||
item.outflow_qty += Math.abs(qty_diff);
|
||||
@ -126,7 +128,7 @@ erpnext.StockBalance = erpnext.StockAnalytics.extend({
|
||||
} else {
|
||||
item.inflow_value += value_diff;
|
||||
}
|
||||
|
||||
|
||||
item.closing_qty += qty_diff;
|
||||
item.closing_value += value_diff;
|
||||
}
|
||||
@ -138,13 +140,18 @@ erpnext.StockBalance = erpnext.StockAnalytics.extend({
|
||||
}
|
||||
|
||||
// opening + diff = closing
|
||||
// adding opening, since diff already added to closing
|
||||
// adding opening, since diff already added to closing
|
||||
$.each(me.item_by_name, function(key, item) {
|
||||
item.closing_qty += item.opening_qty;
|
||||
item.closing_value += item.opening_value;
|
||||
|
||||
// valuation rate
|
||||
if(!item.is_group && flt(item.closing_qty) > 0)
|
||||
item.valuation_rate = flt(item.closing_value) / flt(item.closing_qty);
|
||||
else item.valuation_rate = 0.0
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
update_groups: function() {
|
||||
var me = this;
|
||||
|
||||
@ -155,24 +162,22 @@ erpnext.StockBalance = erpnext.StockAnalytics.extend({
|
||||
while(parent) {
|
||||
parent_group = me.item_by_name[parent];
|
||||
$.each(me.columns, function(c, col) {
|
||||
if (col.formatter == me.currency_formatter) {
|
||||
parent_group[col.field] =
|
||||
flt(parent_group[col.field])
|
||||
+ flt(item[col.field]);
|
||||
if (col.formatter == me.currency_formatter && col.field != "valuation_rate") {
|
||||
parent_group[col.field] = flt(parent_group[col.field]) + flt(item[col.field]);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// show parent if filtered by brand
|
||||
if(item.brand == me.brand)
|
||||
parent_group._show = true;
|
||||
|
||||
|
||||
parent = me.parent_map[parent];
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
get_plot_data: function() {
|
||||
return;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@ -1,13 +1,13 @@
|
||||
// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
// License: GNU General Public License v3. See license.txt
|
||||
|
||||
frappe.pages['stock-ledger'].onload = function(wrapper) {
|
||||
frappe.pages['stock-ledger'].onload = function(wrapper) {
|
||||
frappe.ui.make_app_page({
|
||||
parent: wrapper,
|
||||
title: __('Stock Ledger'),
|
||||
single_column: true
|
||||
});
|
||||
|
||||
|
||||
new erpnext.StockLedger(wrapper);
|
||||
wrapper.appframe.add_module_icon("Stock")
|
||||
}
|
||||
@ -30,7 +30,7 @@ erpnext.StockLedger = erpnext.StockGridReport.extend({
|
||||
this.columns = [
|
||||
{id: "posting_datetime", name: __("Posting Date"), field: "posting_datetime", width: 120,
|
||||
formatter: this.date_formatter},
|
||||
{id: "item_code", name: __("Item Code"), field: "item_code", width: 160,
|
||||
{id: "item_code", name: __("Item Code"), field: "item_code", width: 160,
|
||||
link_formatter: {
|
||||
filter_input: "item_code",
|
||||
open_btn: true,
|
||||
@ -57,10 +57,10 @@ erpnext.StockLedger = erpnext.StockGridReport.extend({
|
||||
doctype: "dataContext.voucher_type"
|
||||
}},
|
||||
];
|
||||
|
||||
|
||||
},
|
||||
filters: [
|
||||
{fieldtype:"Select", label: __("Warehouse"), link:"Warehouse",
|
||||
{fieldtype:"Select", label: __("Warehouse"), link:"Warehouse",
|
||||
default_value: "Select Warehouse...", filter: function(val, item, opts) {
|
||||
return item.warehouse == val || val == opts.default_value;
|
||||
}},
|
||||
@ -68,7 +68,7 @@ erpnext.StockLedger = erpnext.StockGridReport.extend({
|
||||
filter: function(val, item, opts) {
|
||||
return item.item_code == val || !val;
|
||||
}},
|
||||
{fieldtype:"Select", label: "Brand", link:"Brand",
|
||||
{fieldtype:"Select", label: "Brand", link:"Brand",
|
||||
default_value: "Select Brand...", filter: function(val, item, opts) {
|
||||
return val == opts.default_value || item.brand == val || item._show;
|
||||
}, link_formatter: {filter_input: "brand"}},
|
||||
@ -87,17 +87,17 @@ erpnext.StockLedger = erpnext.StockGridReport.extend({
|
||||
{fieldtype:"Button", label: __("Refresh"), icon:"icon-refresh icon-white"},
|
||||
{fieldtype:"Button", label: __("Reset Filters"), icon: "icon-filter"}
|
||||
],
|
||||
|
||||
|
||||
setup_filters: function() {
|
||||
var me = this;
|
||||
this._super();
|
||||
|
||||
|
||||
this.wrapper.bind("apply_filters_from_route", function() { me.toggle_enable_brand(); });
|
||||
this.filter_inputs.item_code.change(function() { me.toggle_enable_brand(); });
|
||||
|
||||
|
||||
this.trigger_refresh_on_change(["item_code", "warehouse", "brand"]);
|
||||
},
|
||||
|
||||
|
||||
toggle_enable_brand: function() {
|
||||
if(!this.filter_inputs.item_code.val()) {
|
||||
this.filter_inputs.brand.prop("disabled", false);
|
||||
@ -107,7 +107,7 @@ erpnext.StockLedger = erpnext.StockGridReport.extend({
|
||||
.prop("disabled", true);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
init_filter_values: function() {
|
||||
this._super();
|
||||
this.filter_inputs.warehouse.get(0).selectedIndex = 0;
|
||||
@ -131,19 +131,19 @@ erpnext.StockLedger = erpnext.StockGridReport.extend({
|
||||
item_code: "Total Out", qty: 0.0, balance: 0.0, balance_value: 0.0,
|
||||
id:"_total_out", _show: true, _style: "font-weight: bold"
|
||||
}
|
||||
|
||||
|
||||
// clear balance
|
||||
$.each(frappe.report_dump.data["Item"], function(i, item) {
|
||||
item.balance = item.balance_value = 0.0;
|
||||
item.balance = item.balance_value = 0.0;
|
||||
});
|
||||
|
||||
|
||||
// initialize warehouse-item map
|
||||
this.item_warehouse = {};
|
||||
this.serialized_buying_rates = this.get_serialized_buying_rates();
|
||||
var from_datetime = dateutil.str_to_obj(me.from_date + " 00:00:00");
|
||||
var to_datetime = dateutil.str_to_obj(me.to_date + " 23:59:59");
|
||||
|
||||
//
|
||||
|
||||
//
|
||||
for(var i=0, j=data.length; i<j; i++) {
|
||||
var sl = data[i];
|
||||
var item = me.item_by_name[sl.item_code]
|
||||
@ -152,8 +152,8 @@ erpnext.StockLedger = erpnext.StockGridReport.extend({
|
||||
sl.posting_datetime = sl.posting_date + " " + (sl.posting_time || "00:00:00");
|
||||
sl.brand = item.brand;
|
||||
var posting_datetime = dateutil.str_to_obj(sl.posting_datetime);
|
||||
|
||||
var is_fifo = item.valuation_method ? item.valuation_method=="FIFO"
|
||||
|
||||
var is_fifo = item.valuation_method ? item.valuation_method=="FIFO"
|
||||
: sys_defaults.valuation_method=="FIFO";
|
||||
var value_diff = me.get_value_diff(wh, sl, is_fifo);
|
||||
|
||||
@ -175,27 +175,27 @@ erpnext.StockLedger = erpnext.StockGridReport.extend({
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(!before_end) break;
|
||||
|
||||
// apply filters
|
||||
if(me.apply_filters(sl)) {
|
||||
out.push(sl);
|
||||
}
|
||||
|
||||
|
||||
// update balance
|
||||
if((!me.is_default("warehouse") ? me.apply_filter(sl, "warehouse") : true)) {
|
||||
sl.balance = me.item_by_name[sl.item_code].balance + sl.qty;
|
||||
me.item_by_name[sl.item_code].balance = sl.balance;
|
||||
|
||||
|
||||
sl.balance_value = me.item_by_name[sl.item_code].balance_value + value_diff;
|
||||
me.item_by_name[sl.item_code].balance_value = sl.balance_value;
|
||||
me.item_by_name[sl.item_code].balance_value = sl.balance_value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(me.item_code && !me.voucher_no) {
|
||||
var closing = {
|
||||
item_code: "On " + dateutil.str_to_user(this.to_date),
|
||||
item_code: "On " + dateutil.str_to_user(this.to_date),
|
||||
balance: (out.length ? out[out.length-1].balance : 0), qty: 0,
|
||||
balance_value: (out.length ? out[out.length-1].balance_value : 0),
|
||||
id:"_closing", _show: true, _style: "font-weight: bold"
|
||||
@ -203,7 +203,7 @@ erpnext.StockLedger = erpnext.StockGridReport.extend({
|
||||
total_out.balance_value = -total_out.balance_value;
|
||||
var out = [opening].concat(out).concat([total_in, total_out, closing]);
|
||||
}
|
||||
|
||||
|
||||
this.data = out;
|
||||
},
|
||||
get_plot_data: function() {
|
||||
@ -231,7 +231,7 @@ erpnext.StockLedger = erpnext.StockGridReport.extend({
|
||||
get_plot_options: function() {
|
||||
return {
|
||||
grid: { hoverable: true, clickable: true },
|
||||
xaxis: { mode: "time",
|
||||
xaxis: { mode: "time",
|
||||
min: dateutil.str_to_obj(this.from_date).getTime(),
|
||||
max: dateutil.str_to_obj(this.to_date).getTime(),
|
||||
},
|
||||
@ -244,4 +244,4 @@ erpnext.StockLedger = erpnext.StockGridReport.extend({
|
||||
var value = format_number(y);
|
||||
return value.bold() + " on " + date;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@ -1,13 +0,0 @@
|
||||
{
|
||||
"creation": "2011-08-23 16:49:40",
|
||||
"docstatus": 0,
|
||||
"doctype": "Print Format",
|
||||
"html": "<html>\n<head>\n\n<script>\nfunction replaceAll(s,s1,s2){ return s.split(s1).join(s2);}\n\nfunction get_letter_head() {\n\t// add letter head\n\tvar cp = locals['Control Panel']['Control Panel'];\n\tif(doc.letter_head)\n\t\tvar lh= cstr(_p.letter_heads[doc.letter_head]);\n\telse if(cp.letter_head)\n\t\tvar lh= cp.letter_head;\n\telse \n\t\tvar lh= '';\n\t\t\n\treturn lh;\n}\n\n</script>\n<style>\n.cust_tbl { border-collapse:collapse; }\n.cust_tbl td { border:1px solid #848484; font-size: 13px}\n.large_font td {font-size: 13px}\n</style>\n</head>\n\n<body>\n<script>\nreplaceAll(doc.print_packing_slip,'[HEADER GOES HERE]',get_letter_head());\n</script>\n</body>\n</html>",
|
||||
"idx": 1,
|
||||
"modified": "2014-05-13 16:07:19.133031",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Stock",
|
||||
"name": "Delivery Note Packing List Wise",
|
||||
"owner": "Administrator",
|
||||
"standard": "Yes"
|
||||
}
|
@ -7,7 +7,7 @@ from frappe.utils import flt
|
||||
|
||||
def execute(filters=None):
|
||||
if not filters: filters = {}
|
||||
|
||||
|
||||
columns = get_columns(filters)
|
||||
item_map = get_item_details()
|
||||
pl = get_price_list()
|
||||
@ -19,34 +19,33 @@ def execute(filters=None):
|
||||
precision = get_currency_precision() or 2
|
||||
data = []
|
||||
for item in sorted(item_map):
|
||||
data.append([item, item_map[item]["item_name"],
|
||||
item_map[item]["description"], item_map[item]["stock_uom"],
|
||||
flt(last_purchase_rate.get(item, 0), precision),
|
||||
flt(val_rate_map.get(item, 0), precision),
|
||||
pl.get(item, {}).get("Selling"),
|
||||
pl.get(item, {}).get("Buying"),
|
||||
flt(bom_rate.get(item, 0), precision),
|
||||
flt(item_map[item]["standard_rate"], precision)
|
||||
data.append([item, item_map[item]["item_name"],
|
||||
item_map[item]["description"], item_map[item]["stock_uom"],
|
||||
flt(last_purchase_rate.get(item, 0), precision),
|
||||
flt(val_rate_map.get(item, 0), precision),
|
||||
pl.get(item, {}).get("Selling"),
|
||||
pl.get(item, {}).get("Buying"),
|
||||
flt(bom_rate.get(item, 0), precision)
|
||||
])
|
||||
|
||||
|
||||
return columns, data
|
||||
|
||||
def get_columns(filters):
|
||||
"""return columns based on filters"""
|
||||
|
||||
columns = ["Item:Link/Item:100", "Item Name::150", "Description::150", "UOM:Link/UOM:80",
|
||||
"Last Purchase Rate:Currency:90", "Valuation Rate:Currency:80", "Sales Price List::80",
|
||||
"Purchase Price List::80", "BOM Rate:Currency:90", "Standard Rate:Currency:100"]
|
||||
|
||||
columns = ["Item:Link/Item:100", "Item Name::150", "Description::150", "UOM:Link/UOM:80",
|
||||
"Last Purchase Rate:Currency:90", "Valuation Rate:Currency:80", "Sales Price List::80",
|
||||
"Purchase Price List::80", "BOM Rate:Currency:90"]
|
||||
|
||||
return columns
|
||||
|
||||
def get_item_details():
|
||||
"""returns all items details"""
|
||||
|
||||
|
||||
item_map = {}
|
||||
|
||||
|
||||
for i in frappe.db.sql("select name, item_name, description, \
|
||||
stock_uom, standard_rate from tabItem \
|
||||
stock_uom from tabItem \
|
||||
order by item_code", as_dict=1):
|
||||
item_map.setdefault(i.name, i)
|
||||
|
||||
@ -57,42 +56,42 @@ def get_price_list():
|
||||
|
||||
rate = {}
|
||||
|
||||
price_list = frappe.db.sql("""select ip.item_code, ip.buying, ip.selling,
|
||||
concat(ip.price_list, " - ", ip.currency, " ", ip.price_list_rate) as price
|
||||
from `tabItem Price` ip, `tabPrice List` pl
|
||||
price_list = frappe.db.sql("""select ip.item_code, ip.buying, ip.selling,
|
||||
concat(ip.price_list, " - ", ip.currency, " ", ip.price_list_rate) as price
|
||||
from `tabItem Price` ip, `tabPrice List` pl
|
||||
where ip.price_list=pl.name and pl.enabled=1""", as_dict=1)
|
||||
|
||||
for j in price_list:
|
||||
if j.price:
|
||||
rate.setdefault(j.item_code, {}).setdefault("Buying" if j.buying else "Selling", []).append(j.price)
|
||||
item_rate_map = {}
|
||||
|
||||
|
||||
for item in rate:
|
||||
for buying_or_selling in rate[item]:
|
||||
item_rate_map.setdefault(item, {}).setdefault(buying_or_selling,
|
||||
item_rate_map.setdefault(item, {}).setdefault(buying_or_selling,
|
||||
", ".join(rate[item].get(buying_or_selling, [])))
|
||||
|
||||
|
||||
return item_rate_map
|
||||
|
||||
def get_last_purchase_rate():
|
||||
|
||||
item_last_purchase_rate_map = {}
|
||||
|
||||
query = """select * from (select
|
||||
query = """select * from (select
|
||||
result.item_code,
|
||||
result.base_rate
|
||||
from (
|
||||
(select
|
||||
(select
|
||||
po_item.item_code,
|
||||
po_item.item_name,
|
||||
po.transaction_date as posting_date,
|
||||
po_item.base_price_list_rate,
|
||||
po_item.discount_percentage,
|
||||
po_item.base_price_list_rate,
|
||||
po_item.discount_percentage,
|
||||
po_item.base_rate
|
||||
from `tabPurchase Order` po, `tabPurchase Order Item` po_item
|
||||
where po.name = po_item.parent and po.docstatus = 1)
|
||||
union
|
||||
(select
|
||||
(select
|
||||
pr_item.item_code,
|
||||
pr_item.item_name,
|
||||
pr.posting_date,
|
||||
@ -114,8 +113,8 @@ def get_item_bom_rate():
|
||||
"""Get BOM rate of an item from BOM"""
|
||||
|
||||
item_bom_map = {}
|
||||
|
||||
for b in frappe.db.sql("""select item, (total_cost/quantity) as bom_rate
|
||||
|
||||
for b in frappe.db.sql("""select item, (total_cost/quantity) as bom_rate
|
||||
from `tabBOM` where is_active=1 and is_default=1""", as_dict=1):
|
||||
item_bom_map.setdefault(b.item, flt(b.bom_rate))
|
||||
|
||||
@ -125,8 +124,8 @@ def get_valuation_rate():
|
||||
"""Get an average valuation rate of an item from all warehouses"""
|
||||
|
||||
item_val_rate_map = {}
|
||||
|
||||
for d in frappe.db.sql("""select item_code,
|
||||
|
||||
for d in frappe.db.sql("""select item_code,
|
||||
sum(actual_qty*valuation_rate)/sum(actual_qty) as val_rate
|
||||
from tabBin where actual_qty > 0 group by item_code""", as_dict=1):
|
||||
item_val_rate_map.setdefault(d.item_code, d.val_rate)
|
||||
|
@ -17,23 +17,25 @@ def execute(filters=None):
|
||||
% ("/".join(["#Form", sle.voucher_type, sle.voucher_no]),)
|
||||
|
||||
data.append([sle.date, sle.item_code, item_detail.item_name, item_detail.item_group,
|
||||
item_detail.brand, item_detail.description, sle.warehouse, item_detail.stock_uom,
|
||||
sle.actual_qty, sle.qty_after_transaction, sle.valuation_rate, sle.stock_value,
|
||||
sle.voucher_type, sle.voucher_no, voucher_link_icon, sle.batch_no, sle.serial_no, sle.company])
|
||||
item_detail.brand, item_detail.description, sle.warehouse,
|
||||
item_detail.stock_uom, sle.actual_qty, sle.qty_after_transaction,
|
||||
(sle.incoming_rate if sle.actual_qty > 0 else 0.0),
|
||||
sle.valuation_rate, sle.stock_value, sle.voucher_type, sle.voucher_no,
|
||||
voucher_link_icon, sle.batch_no, sle.serial_no, sle.company])
|
||||
|
||||
return columns, data
|
||||
|
||||
def get_columns():
|
||||
return ["Date:Datetime:95", "Item:Link/Item:130", "Item Name::100",
|
||||
"Item Group:Link/Item Group:100", "Brand:Link/Brand:100",
|
||||
"Description::200", "Warehouse:Link/Warehouse:100",
|
||||
"Stock UOM:Link/UOM:100", "Qty:Float:50", "Balance Qty:Float:100", "Valuation Rate:Currency:110",
|
||||
"Balance Value:Currency:110", "Voucher Type::110", "Voucher #::100", "Link::30",
|
||||
"Batch:Link/Batch:100", "Serial #:Link/Serial No:100", "Company:Link/Company:100"]
|
||||
return ["Date:Datetime:95", "Item:Link/Item:130", "Item Name::100", "Item Group:Link/Item Group:100",
|
||||
"Brand:Link/Brand:100", "Description::200", "Warehouse:Link/Warehouse:100",
|
||||
"Stock UOM:Link/UOM:100", "Qty:Float:50", "Balance Qty:Float:100",
|
||||
"Incoming Rate:Currency:110", "Valuation Rate:Currency:110", "Balance Value:Currency:110",
|
||||
"Voucher Type::110", "Voucher #::100", "Link::30", "Batch:Link/Batch:100",
|
||||
"Serial #:Link/Serial No:100", "Company:Link/Company:100"]
|
||||
|
||||
def get_stock_ledger_entries(filters):
|
||||
return frappe.db.sql("""select concat_ws(" ", posting_date, posting_time) as date,
|
||||
item_code, warehouse, actual_qty, qty_after_transaction, valuation_rate,
|
||||
item_code, warehouse, actual_qty, qty_after_transaction, incoming_rate, valuation_rate,
|
||||
stock_value, voucher_type, voucher_no, batch_no, serial_no, company
|
||||
from `tabStock Ledger Entry`
|
||||
where company = %(company)s and
|
||||
|
@ -68,10 +68,6 @@ def get_incoming_rate(args):
|
||||
in_rate = 0
|
||||
if args.get("serial_no"):
|
||||
in_rate = get_avg_purchase_rate(args.get("serial_no"))
|
||||
elif args.get("bom_no"):
|
||||
result = frappe.db.sql("""select ifnull(total_cost, 0) / ifnull(quantity, 1)
|
||||
from `tabBOM` where name = %s and docstatus=1 and is_active=1""", args.get("bom_no"))
|
||||
in_rate = result and flt(result[0][0]) or 0
|
||||
else:
|
||||
valuation_method = get_valuation_method(args.get("item_code"))
|
||||
previous_sle = get_previous_sle(args)
|
||||
|
@ -22,12 +22,3 @@ from frappe.utils import cint, comma_or
|
||||
def validate_status(status, options):
|
||||
if status not in options:
|
||||
frappe.throw(_("Status must be one of {0}").format(comma_or(options)))
|
||||
|
||||
def build_filter_conditions(filters):
|
||||
conditions, filter_values = [], []
|
||||
for key in filters:
|
||||
conditions.append('`' + key + '` = %s')
|
||||
filter_values.append(filters[key])
|
||||
|
||||
conditions = conditions and " and " + " and ".join(conditions) or ""
|
||||
return conditions, filter_values
|
||||
|
Loading…
Reference in New Issue
Block a user