mirror of
https://github.com/frappe/erpnext.git
synced 2026-04-16 13:25:10 +00:00
Merge branch 'hotfix'
This commit is contained in:
@@ -5,7 +5,7 @@ import frappe
|
|||||||
from erpnext.hooks import regional_overrides
|
from erpnext.hooks import regional_overrides
|
||||||
from frappe.utils import getdate
|
from frappe.utils import getdate
|
||||||
|
|
||||||
__version__ = '10.1.48'
|
__version__ = '10.1.49'
|
||||||
|
|
||||||
def get_default_company(user=None):
|
def get_default_company(user=None):
|
||||||
'''Get default company for user'''
|
'''Get default company for user'''
|
||||||
|
|||||||
@@ -207,10 +207,13 @@ def validate_account_number(name, account_number, company):
|
|||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def update_account_number(name, account_name, account_number=None):
|
def update_account_number(name, account_name, account_number=None):
|
||||||
|
|
||||||
account = frappe.db.get_value("Account", name, ["company"], as_dict=True)
|
account = frappe.db.get_value("Account", name, "company", as_dict=True)
|
||||||
|
if not account: return
|
||||||
validate_account_number(name, account_number, account.company)
|
validate_account_number(name, account_number, account.company)
|
||||||
if account_number:
|
if account_number:
|
||||||
frappe.db.set_value("Account", name, "account_number", account_number.strip())
|
frappe.db.set_value("Account", name, "account_number", account_number.strip())
|
||||||
|
else:
|
||||||
|
frappe.db.set_value("Account", name, "account_number", "")
|
||||||
frappe.db.set_value("Account", name, "account_name", account_name.strip())
|
frappe.db.set_value("Account", name, "account_name", account_name.strip())
|
||||||
|
|
||||||
new_name = get_account_autoname(account_number, account_name, account.company)
|
new_name = get_account_autoname(account_number, account_name, account.company)
|
||||||
|
|||||||
@@ -27,13 +27,21 @@ class Budget(Document):
|
|||||||
def validate_duplicate(self):
|
def validate_duplicate(self):
|
||||||
budget_against_field = frappe.scrub(self.budget_against)
|
budget_against_field = frappe.scrub(self.budget_against)
|
||||||
budget_against = self.get(budget_against_field)
|
budget_against = self.get(budget_against_field)
|
||||||
existing_budget = frappe.db.get_value("Budget", {budget_against_field: budget_against,
|
|
||||||
"fiscal_year": self.fiscal_year, "company": self.company,
|
accounts = [d.account for d in self.accounts] or []
|
||||||
"name": ["!=", self.name], "docstatus": ["!=", 2]})
|
existing_budget = frappe.db.sql("""
|
||||||
if existing_budget:
|
select
|
||||||
frappe.throw(_("Another Budget record '{0}' already exists against {1} '{2}' for fiscal year {3}")
|
b.name, ba.account from `tabBudget` b, `tabBudget Account` ba
|
||||||
.format(existing_budget, self.budget_against, budget_against, self.fiscal_year), DuplicateBudgetError)
|
where
|
||||||
|
ba.parent = b.name and b.company = %s and %s=%s and
|
||||||
|
b.fiscal_year=%s and b.name != %sand ba.account in (%s) """
|
||||||
|
% ('%s', budget_against_field, '%s', '%s', '%s', ','.join(['%s'] * len(accounts))),
|
||||||
|
(self.company, budget_against, self.fiscal_year, self.name) + tuple(accounts), as_dict=1)
|
||||||
|
|
||||||
|
for d in existing_budget:
|
||||||
|
frappe.throw(_("Another Budget record '{0}' already exists against {1} '{2}' and account '{3}' for fiscal year {4}")
|
||||||
|
.format(d.name, self.budget_against, budget_against, d.account, self.fiscal_year), DuplicateBudgetError)
|
||||||
|
|
||||||
def validate_accounts(self):
|
def validate_accounts(self):
|
||||||
account_list = []
|
account_list = []
|
||||||
for d in self.get('accounts'):
|
for d in self.get('accounts'):
|
||||||
|
|||||||
@@ -132,7 +132,7 @@
|
|||||||
"remember_last_selected_value": 0,
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 1,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
@@ -702,7 +702,7 @@
|
|||||||
"remember_last_selected_value": 0,
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 1,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
}
|
}
|
||||||
@@ -718,7 +718,7 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2017-12-20 12:40:09.611951",
|
"modified": "2018-08-10 16:16:53.019380",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "GL Entry",
|
"name": "GL Entry",
|
||||||
@@ -794,4 +794,4 @@
|
|||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
"track_changes": 0,
|
"track_changes": 0,
|
||||||
"track_seen": 0
|
"track_seen": 0
|
||||||
}
|
}
|
||||||
@@ -381,7 +381,7 @@
|
|||||||
"remember_last_selected_value": 0,
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 1,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
@@ -1443,7 +1443,7 @@
|
|||||||
"istable": 0,
|
"istable": 0,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"menu_index": 0,
|
"menu_index": 0,
|
||||||
"modified": "2017-08-31 11:21:09.442695",
|
"modified": "2018-08-10 16:35:31.361030",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Journal Entry",
|
"name": "Journal Entry",
|
||||||
|
|||||||
@@ -199,7 +199,7 @@
|
|||||||
"remember_last_selected_value": 0,
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 1,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
@@ -661,7 +661,7 @@
|
|||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
@@ -795,7 +795,7 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2017-12-07 19:54:19.851534",
|
"modified": "2018-08-10 16:35:42.833549",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Journal Entry Account",
|
"name": "Journal Entry Account",
|
||||||
|
|||||||
@@ -286,7 +286,7 @@
|
|||||||
"remember_last_selected_value": 0,
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 1,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
@@ -1439,7 +1439,7 @@
|
|||||||
"remember_last_selected_value": 0,
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 1,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
@@ -1791,7 +1791,7 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2018-07-27 01:49:24.720317",
|
"modified": "2018-08-10 16:34:46.771275",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Payment Entry",
|
"name": "Payment Entry",
|
||||||
|
|||||||
@@ -585,6 +585,38 @@
|
|||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"depends_on": "discount_percentage",
|
||||||
|
"fieldname": "discount_amount",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Discount Amount",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"options": "currency",
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 1,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
@@ -2156,7 +2188,7 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2017-11-30 14:21:00.962126",
|
"modified": "2018-08-06 05:17:38.205356",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Purchase Invoice Item",
|
"name": "Purchase Invoice Item",
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -123,9 +123,6 @@ class ReceivablePayableReport(object):
|
|||||||
currency_precision = get_currency_precision() or 2
|
currency_precision = get_currency_precision() or 2
|
||||||
dr_or_cr = "debit" if args.get("party_type") == "Customer" else "credit"
|
dr_or_cr = "debit" if args.get("party_type") == "Customer" else "credit"
|
||||||
|
|
||||||
dn_details = get_dn_details(args.get("party_type"))
|
|
||||||
voucher_details = self.get_voucher_details(args.get("party_type"), dn_details)
|
|
||||||
|
|
||||||
future_vouchers = self.get_entries_after(self.filters.report_date, args.get("party_type"))
|
future_vouchers = self.get_entries_after(self.filters.report_date, args.get("party_type"))
|
||||||
|
|
||||||
if not self.filters.get("company"):
|
if not self.filters.get("company"):
|
||||||
@@ -138,7 +135,14 @@ class ReceivablePayableReport(object):
|
|||||||
data = []
|
data = []
|
||||||
pdc_details = get_pdc_details(args.get("party_type"), self.filters.report_date)
|
pdc_details = get_pdc_details(args.get("party_type"), self.filters.report_date)
|
||||||
|
|
||||||
for gle in self.get_entries_till(self.filters.report_date, args.get("party_type")):
|
gl_entries_data = self.get_entries_till(self.filters.report_date, args.get("party_type"))
|
||||||
|
|
||||||
|
if gl_entries_data:
|
||||||
|
voucher_nos = [d.voucher_no for d in gl_entries_data] or []
|
||||||
|
dn_details = get_dn_details(args.get("party_type"), voucher_nos)
|
||||||
|
voucher_details = get_voucher_details(args.get("party_type"), voucher_nos, dn_details)
|
||||||
|
|
||||||
|
for gle in gl_entries_data:
|
||||||
if self.is_receivable_or_payable(gle, dr_or_cr, future_vouchers):
|
if self.is_receivable_or_payable(gle, dr_or_cr, future_vouchers):
|
||||||
outstanding_amount, credit_note_amount = self.get_outstanding_amount(gle,
|
outstanding_amount, credit_note_amount = self.get_outstanding_amount(gle,
|
||||||
self.filters.report_date, dr_or_cr, return_entries, currency_precision)
|
self.filters.report_date, dr_or_cr, return_entries, currency_precision)
|
||||||
@@ -171,7 +175,7 @@ class ReceivablePayableReport(object):
|
|||||||
if self.filters.ageing_based_on == "Due Date":
|
if self.filters.ageing_based_on == "Due Date":
|
||||||
entry_date = due_date
|
entry_date = due_date
|
||||||
elif self.filters.ageing_based_on == "Supplier Invoice Date":
|
elif self.filters.ageing_based_on == "Supplier Invoice Date":
|
||||||
entry_date = bill_date
|
entry_date = bill_date
|
||||||
else:
|
else:
|
||||||
entry_date = gle.posting_date
|
entry_date = gle.posting_date
|
||||||
row += get_ageing_data(cint(self.filters.range1), cint(self.filters.range2),
|
row += get_ageing_data(cint(self.filters.range1), cint(self.filters.range2),
|
||||||
@@ -218,12 +222,11 @@ class ReceivablePayableReport(object):
|
|||||||
|
|
||||||
def get_entries_after(self, report_date, party_type):
|
def get_entries_after(self, report_date, party_type):
|
||||||
# returns a distinct list
|
# returns a distinct list
|
||||||
return list(set([(e.voucher_type, e.voucher_no) for e in self.get_gl_entries(party_type)
|
return list(set([(e.voucher_type, e.voucher_no) for e in self.get_gl_entries(party_type, report_date, for_future=True)]))
|
||||||
if getdate(e.posting_date) > report_date]))
|
|
||||||
|
|
||||||
def get_entries_till(self, report_date, party_type):
|
def get_entries_till(self, report_date, party_type):
|
||||||
# returns a generator
|
# returns a generator
|
||||||
return (e for e in self.get_gl_entries(party_type) if getdate(e.posting_date) <= report_date)
|
return self.get_gl_entries(party_type, report_date)
|
||||||
|
|
||||||
def is_receivable_or_payable(self, gle, dr_or_cr, future_vouchers):
|
def is_receivable_or_payable(self, gle, dr_or_cr, future_vouchers):
|
||||||
return (
|
return (
|
||||||
@@ -286,42 +289,31 @@ class ReceivablePayableReport(object):
|
|||||||
|
|
||||||
return self.party_map
|
return self.party_map
|
||||||
|
|
||||||
def get_voucher_details(self, party_type, dn_details):
|
def get_gl_entries(self, party_type, date=None, for_future=False):
|
||||||
voucher_details = frappe._dict()
|
conditions, values = self.prepare_conditions(party_type)
|
||||||
|
|
||||||
if party_type == "Customer":
|
if self.filters.get(scrub(party_type)):
|
||||||
for si in frappe.db.sql("""select name, due_date, po_no
|
select_fields = "sum(debit_in_account_currency) as debit, sum(credit_in_account_currency) as credit"
|
||||||
from `tabSales Invoice` where docstatus=1""", as_dict=1):
|
else:
|
||||||
si['delivery_note'] = dn_details.get(si.name)
|
select_fields = "sum(debit) as debit, sum(credit) as credit"
|
||||||
voucher_details.setdefault(si.name, si)
|
|
||||||
|
|
||||||
if party_type == "Supplier":
|
if date and not for_future:
|
||||||
for pi in frappe.db.sql("""select name, due_date, bill_no, bill_date
|
conditions += " and posting_date <= '%s'" % date
|
||||||
from `tabPurchase Invoice` where docstatus = 1
|
|
||||||
union
|
|
||||||
select name, due_date, bill_no, bill_date from `tabJournal Entry`
|
|
||||||
where docstatus = 1 and bill_no is not NULL""", as_dict=1):
|
|
||||||
voucher_details.setdefault(pi.name, pi)
|
|
||||||
|
|
||||||
return voucher_details
|
if date and for_future:
|
||||||
|
conditions += " and posting_date > '%s'" % date
|
||||||
|
|
||||||
def get_gl_entries(self, party_type):
|
self.gl_entries = frappe.db.sql("""
|
||||||
if not hasattr(self, "gl_entries"):
|
select
|
||||||
conditions, values = self.prepare_conditions(party_type)
|
name, posting_date, account, party_type, party, voucher_type, voucher_no,
|
||||||
|
against_voucher_type, against_voucher, account_currency, remarks, {0}
|
||||||
if self.filters.get(scrub(party_type)):
|
from
|
||||||
select_fields = "sum(debit_in_account_currency) as debit, sum(credit_in_account_currency) as credit"
|
`tabGL Entry`
|
||||||
else:
|
where
|
||||||
select_fields = "sum(debit) as debit, sum(credit) as credit"
|
docstatus < 2 and party_type=%s and (party is not null and party != '') {1}
|
||||||
|
|
||||||
self.gl_entries = frappe.db.sql("""select name, posting_date, account, party_type, party,
|
|
||||||
voucher_type, voucher_no, against_voucher_type, against_voucher,
|
|
||||||
account_currency, remarks, {0}
|
|
||||||
from `tabGL Entry`
|
|
||||||
where docstatus < 2 and party_type=%s and (party is not null and party != '') {1}
|
|
||||||
group by voucher_type, voucher_no, against_voucher_type, against_voucher, party
|
group by voucher_type, voucher_no, against_voucher_type, against_voucher, party
|
||||||
order by posting_date, party"""
|
order by posting_date, party"""
|
||||||
.format(select_fields, conditions), values, as_dict=True)
|
.format(select_fields, conditions), values, as_dict=True)
|
||||||
|
|
||||||
return self.gl_entries
|
return self.gl_entries
|
||||||
|
|
||||||
@@ -457,18 +449,57 @@ def get_pdc_details(party_type, report_date):
|
|||||||
|
|
||||||
return pdc_details
|
return pdc_details
|
||||||
|
|
||||||
def get_dn_details(party_type):
|
def get_dn_details(party_type, voucher_nos):
|
||||||
dn_details = frappe._dict()
|
dn_details = frappe._dict()
|
||||||
|
|
||||||
if party_type == "Customer":
|
if party_type == "Customer":
|
||||||
for si in frappe.db.sql("""select parent, GROUP_CONCAT(delivery_note SEPARATOR ', ') as dn
|
for si in frappe.db.sql("""
|
||||||
from `tabSales Invoice Item`
|
select
|
||||||
where docstatus=1 and delivery_note is not null and delivery_note != '' group by parent
|
parent, GROUP_CONCAT(delivery_note SEPARATOR ', ') as dn
|
||||||
Union
|
from
|
||||||
select against_sales_invoice as parent, GROUP_CONCAT(parent SEPARATOR ', ') as dn
|
`tabSales Invoice Item`
|
||||||
from `tabDelivery Note Item`
|
where
|
||||||
where docstatus=1 and against_sales_invoice is not null
|
docstatus=1 and delivery_note is not null and delivery_note != ''
|
||||||
and against_sales_invoice != '' group by against_sales_invoice""", as_dict=1):
|
and parent in (%s) group by parent
|
||||||
|
""" %(','.join(['%s'] * len(voucher_nos))), tuple(voucher_nos) , as_dict=1):
|
||||||
|
dn_details.setdefault(si.parent, si.dn)
|
||||||
|
|
||||||
|
for si in frappe.db.sql("""
|
||||||
|
select
|
||||||
|
against_sales_invoice as parent, GROUP_CONCAT(parent SEPARATOR ', ') as dn
|
||||||
|
from
|
||||||
|
`tabDelivery Note Item`
|
||||||
|
where
|
||||||
|
docstatus=1 and against_sales_invoice is not null and against_sales_invoice != ''
|
||||||
|
and against_sales_invoice in (%s)
|
||||||
|
group by against_sales_invoice
|
||||||
|
""" %(','.join(['%s'] * len(voucher_nos))), tuple(voucher_nos) , as_dict=1):
|
||||||
|
if si.parent in dn_details:
|
||||||
|
dn_details[si.parent] += ', %s' %(si.dn)
|
||||||
|
else:
|
||||||
dn_details.setdefault(si.parent, si.dn)
|
dn_details.setdefault(si.parent, si.dn)
|
||||||
|
|
||||||
return dn_details
|
return dn_details
|
||||||
|
|
||||||
|
def get_voucher_details(party_type, voucher_nos, dn_details):
|
||||||
|
voucher_details = frappe._dict()
|
||||||
|
|
||||||
|
if party_type == "Customer":
|
||||||
|
for si in frappe.db.sql("""select name, due_date, po_no
|
||||||
|
from `tabSales Invoice` where docstatus=1 and name in (%s)
|
||||||
|
""" %(','.join(['%s'] *len(voucher_nos))), (tuple(voucher_nos)), as_dict=1):
|
||||||
|
si['delivery_note'] = dn_details.get(si.name)
|
||||||
|
voucher_details.setdefault(si.name, si)
|
||||||
|
|
||||||
|
if party_type == "Supplier":
|
||||||
|
for pi in frappe.db.sql("""select name, due_date, bill_no, bill_date
|
||||||
|
from `tabPurchase Invoice` where docstatus = 1 and name in (%s)
|
||||||
|
""" %(','.join(['%s'] *len(voucher_nos))), (tuple(voucher_nos)), as_dict=1):
|
||||||
|
voucher_details.setdefault(pi.name, pi)
|
||||||
|
|
||||||
|
for pi in frappe.db.sql("""select name, due_date, bill_no, bill_date from
|
||||||
|
`tabJournal Entry` where docstatus = 1 and bill_no is not NULL and name in (%s)
|
||||||
|
""" %(','.join(['%s'] *len(voucher_nos))), (tuple(voucher_nos)), as_dict=1):
|
||||||
|
voucher_details.setdefault(pi.name, pi)
|
||||||
|
|
||||||
|
return voucher_details
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ frappe.ui.form.on('Asset Category', {
|
|||||||
var d = locals[cdt][cdn];
|
var d = locals[cdt][cdn];
|
||||||
return {
|
return {
|
||||||
"filters": {
|
"filters": {
|
||||||
"root_type": "Asset",
|
"account_type": "Accumulated Depreciation",
|
||||||
"is_group": 0,
|
"is_group": 0,
|
||||||
"company": d.company_name
|
"company": d.company_name
|
||||||
}
|
}
|
||||||
@@ -41,4 +41,4 @@ frappe.ui.form.on('Asset Category', {
|
|||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -629,6 +629,38 @@
|
|||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"depends_on": "discount_percentage",
|
||||||
|
"fieldname": "discount_amount",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Discount Amount",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"options": "currency",
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 1,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
@@ -1897,7 +1929,7 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2018-07-18 07:53:54.677844",
|
"modified": "2018-08-06 05:16:58.258276",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Buying",
|
"module": "Buying",
|
||||||
"name": "Purchase Order Item",
|
"name": "Purchase Order Item",
|
||||||
|
|||||||
@@ -470,6 +470,38 @@
|
|||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"depends_on": "discount_percentage",
|
||||||
|
"fieldname": "discount_amount",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Discount Amount",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"options": "currency",
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 1,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
@@ -1645,7 +1677,7 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2018-01-25 15:04:40.171617",
|
"modified": "2018-08-06 05:33:07.404385",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Buying",
|
"module": "Buying",
|
||||||
"name": "Supplier Quotation Item",
|
"name": "Supplier Quotation Item",
|
||||||
|
|||||||
@@ -218,7 +218,8 @@ def bom(doctype, txt, searchfield, start, page_len, filters):
|
|||||||
def get_project_name(doctype, txt, searchfield, start, page_len, filters):
|
def get_project_name(doctype, txt, searchfield, start, page_len, filters):
|
||||||
cond = ''
|
cond = ''
|
||||||
if filters.get('customer'):
|
if filters.get('customer'):
|
||||||
cond = '(`tabProject`.customer = "' + filters['customer'] + '" or ifnull(`tabProject`.customer,"")="") and'
|
cond = """(`tabProject`.customer = '%s' or
|
||||||
|
ifnull(`tabProject`.customer,"")="") and""" %(frappe.db.escape(filters.get("customer")))
|
||||||
|
|
||||||
return frappe.db.sql("""select `tabProject`.name from `tabProject`
|
return frappe.db.sql("""select `tabProject`.name from `tabProject`
|
||||||
where `tabProject`.status not in ("Completed", "Cancelled")
|
where `tabProject`.status not in ("Completed", "Cancelled")
|
||||||
|
|||||||
@@ -151,6 +151,7 @@ def get_ref_item_dict(valid_items, ref_item_row):
|
|||||||
"rejected_qty": 0,
|
"rejected_qty": 0,
|
||||||
"received_qty": 0,
|
"received_qty": 0,
|
||||||
"serial_no": [],
|
"serial_no": [],
|
||||||
|
"conversion_factor": ref_item_row.get("conversion_factor", 1),
|
||||||
"batch_no": []
|
"batch_no": []
|
||||||
}))
|
}))
|
||||||
item_dict = valid_items[ref_item_row.item_code]
|
item_dict = valid_items[ref_item_row.item_code]
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"allow_copy": 0,
|
"allow_copy": 0,
|
||||||
"allow_guest_to_view": 0,
|
"allow_guest_to_view": 0,
|
||||||
"allow_import": 0,
|
"allow_import": 1,
|
||||||
"allow_rename": 0,
|
"allow_rename": 0,
|
||||||
"autoname": "RES.######",
|
"autoname": "RES.######",
|
||||||
"beta": 0,
|
"beta": 0,
|
||||||
@@ -662,7 +662,7 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2018-01-09 14:14:30.090317",
|
"modified": "2018-08-20 11:21:19.248393",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Education",
|
"module": "Education",
|
||||||
"name": "Assessment Result",
|
"name": "Assessment Result",
|
||||||
|
|||||||
@@ -1,873 +0,0 @@
|
|||||||
/* globals Hub, HubList */
|
|
||||||
|
|
||||||
frappe.provide('erpnext.hub');
|
|
||||||
|
|
||||||
frappe.pages['hub'].on_page_load = function(wrapper) {
|
|
||||||
const page = frappe.ui.make_app_page({
|
|
||||||
parent: wrapper,
|
|
||||||
title: 'Hub',
|
|
||||||
single_col: false
|
|
||||||
});
|
|
||||||
|
|
||||||
wrapper.hub_page = new erpnext.hub.Hub({ page });
|
|
||||||
};
|
|
||||||
|
|
||||||
frappe.pages['hub'].on_page_show = function(wrapper) {
|
|
||||||
const hub_page = wrapper.hub_page;
|
|
||||||
const [hub, type, id] = frappe.get_route();
|
|
||||||
|
|
||||||
if (!(hub || type || id)) {
|
|
||||||
hub_page.go_to_home_page();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type === "Products") {
|
|
||||||
hub_page.go_to_item_page(id);
|
|
||||||
} else if (type === "Company") {
|
|
||||||
hub_page.go_to_company_page(id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
erpnext.hub.Hub = class Hub {
|
|
||||||
constructor({ page }) {
|
|
||||||
this.page = page;
|
|
||||||
frappe.require('/assets/erpnext/css/hub.css', () => {
|
|
||||||
this.setup();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
setup() {
|
|
||||||
this.setup_header();
|
|
||||||
this.company_cache = {};
|
|
||||||
this.item_cache = {};
|
|
||||||
this.filters = {};
|
|
||||||
this.order_by = '';
|
|
||||||
|
|
||||||
this.$hub_main_section =
|
|
||||||
$(`<div class='hub-main-section'>`).appendTo(this.page.body);
|
|
||||||
this.bind_events();
|
|
||||||
this.refresh();
|
|
||||||
}
|
|
||||||
|
|
||||||
refresh() {
|
|
||||||
this.$hub_main_section.empty();
|
|
||||||
this.page.page_form.hide();
|
|
||||||
|
|
||||||
const $layout_main = this.page.wrapper.find('.layout-main');
|
|
||||||
const $page_head = this.page.wrapper.find('.page-head');
|
|
||||||
|
|
||||||
frappe.model.with_doc('Hub Settings', 'Hub Settings', () => {
|
|
||||||
this.hub_settings = frappe.get_doc('Hub Settings');
|
|
||||||
|
|
||||||
if(this.hub_settings.enabled == 0) {
|
|
||||||
let $empty_state = this.page.get_empty_state(
|
|
||||||
__("Register for Hub"),
|
|
||||||
__(`Let other ERPNext users discover your products
|
|
||||||
and automate workflow with Supplier from within ERPNext.`),
|
|
||||||
__("Register")
|
|
||||||
);
|
|
||||||
|
|
||||||
$page_head.hide();
|
|
||||||
$layout_main
|
|
||||||
.find('.layout-side-section, .layout-main-section-wrapper')
|
|
||||||
.hide();
|
|
||||||
$layout_main.append($empty_state);
|
|
||||||
|
|
||||||
$empty_state.find('.btn-primary').on('click', () => {
|
|
||||||
this.register_for_hub();
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
$page_head.show();
|
|
||||||
$layout_main.find('.page-card-container').remove();
|
|
||||||
$layout_main.find('.layout-side-section, .layout-main-section-wrapper').show();
|
|
||||||
this.setup_live_state();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
register_for_hub() {
|
|
||||||
if (frappe.session.user.includes('Administrator')) {
|
|
||||||
frappe.throw(__('Please login as another user.'))
|
|
||||||
}
|
|
||||||
frappe.verify_password(() => {
|
|
||||||
frappe.call({
|
|
||||||
method: 'erpnext.hub_node.enable_hub',
|
|
||||||
callback: (r) => {
|
|
||||||
if(r.message.enabled == 1) {
|
|
||||||
Object.assign(this.hub_settings, r.message);
|
|
||||||
this.refresh();
|
|
||||||
this.prompt_for_item_sync();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
prompt_for_item_sync() {
|
|
||||||
frappe.call({
|
|
||||||
method: 'frappe.client.get_list',
|
|
||||||
args: {
|
|
||||||
doctype: 'Data Migration Run',
|
|
||||||
filters: {
|
|
||||||
'data_migration_plan': 'Hub Sync'
|
|
||||||
},
|
|
||||||
limit_page_length: 1
|
|
||||||
},
|
|
||||||
callback: function(r) {
|
|
||||||
if (!r) {
|
|
||||||
frappe.confirm(__('Do you want to publish your Items to Hub ?'), () => {
|
|
||||||
this.sync_items_to_hub();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
setup_header() {
|
|
||||||
this.page.page_title = this.page.wrapper.find('.page-title');
|
|
||||||
this.tag_line = $(`
|
|
||||||
<div class='tag-line-container'>
|
|
||||||
<span class='tag-line text-muted small'>
|
|
||||||
${__('Product listing and discovery for ERPNext users')}
|
|
||||||
</span>
|
|
||||||
</div>`)
|
|
||||||
.appendTo(this.page.page_title);
|
|
||||||
|
|
||||||
this.bind_title();
|
|
||||||
}
|
|
||||||
|
|
||||||
setup_live_state() {
|
|
||||||
if(!this.$search) {
|
|
||||||
this.setup_filters();
|
|
||||||
}
|
|
||||||
this.page.page_form.show();
|
|
||||||
this.setup_menu();
|
|
||||||
this.setup_sidebar();
|
|
||||||
this.render_body();
|
|
||||||
this.setup_lists();
|
|
||||||
}
|
|
||||||
|
|
||||||
setup_filters() {
|
|
||||||
|
|
||||||
// frappe.call({
|
|
||||||
// method: 'erpnext.hub_node.get_categories'
|
|
||||||
// }).then((r) => {
|
|
||||||
// if (r.message) {
|
|
||||||
// const categories = r.message;
|
|
||||||
// console.log("categories", categories);
|
|
||||||
// categories
|
|
||||||
// .map(c => c.hub_category_name)
|
|
||||||
// .map(c => this.sidebar.add_item({
|
|
||||||
// label: c,
|
|
||||||
// on_click: () => {
|
|
||||||
// this.home_item_list &&
|
|
||||||
// this.home_item_list.refresh({
|
|
||||||
// text: '',
|
|
||||||
// start: 0,
|
|
||||||
// limit: 20,
|
|
||||||
// category: c && c !== 'All Categories' ? c : undefined
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
// }, __('Hub Category')));
|
|
||||||
|
|
||||||
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
|
|
||||||
// this.category_select = this.page.add_select(__('Category'),
|
|
||||||
// [
|
|
||||||
// {label: __('Sort by Price ...'), value: '' },
|
|
||||||
// {label: __('High to Low'), value: 'price desc' },
|
|
||||||
// {label: __('Low to High'), value: 'price' },
|
|
||||||
// ]
|
|
||||||
// );
|
|
||||||
|
|
||||||
this.price_sort_select = this.page.add_select(__('Sort by Price'),
|
|
||||||
[
|
|
||||||
{label: __('Sort by Price ...'), value: '' },
|
|
||||||
{label: __('High to Low'), value: 'price desc' },
|
|
||||||
{label: __('Low to High'), value: 'price' },
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
this.criteria_select = this.page.add_select(__('Sort by Criteria'),
|
|
||||||
[
|
|
||||||
{label: __('Most Popular'), value: 'request_count' },
|
|
||||||
{label: __('Newest'), value: 'creation' },
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
this.price_sort_select.on('change', () => {
|
|
||||||
this.refresh_item_only_page();
|
|
||||||
});
|
|
||||||
|
|
||||||
this.criteria_select.on('change', () => {
|
|
||||||
this.refresh_item_only_page();
|
|
||||||
});
|
|
||||||
|
|
||||||
this.setup_hub_category_filter();
|
|
||||||
this.setup_search();
|
|
||||||
}
|
|
||||||
|
|
||||||
bind_events() {
|
|
||||||
const me = this;
|
|
||||||
this.$hub_main_section
|
|
||||||
.on('click', '.company-link a', function(e) {
|
|
||||||
e.preventDefault();
|
|
||||||
const company_name = $(this).attr('data-company-name');
|
|
||||||
frappe.set_route('hub', 'Company', company_name);
|
|
||||||
})
|
|
||||||
.on('click', '.breadcrumb li', function(e) {
|
|
||||||
e.preventDefault();
|
|
||||||
const $li = $(this);
|
|
||||||
if ($li.attr('data-route') === 'Home') {
|
|
||||||
me.go_to_home_page();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
update_filters() {
|
|
||||||
let price_sort = $(this.price_sort_select).val() || '';
|
|
||||||
let criteria = $(this.criteria_select).val() || '';
|
|
||||||
|
|
||||||
let order_by_params = [];
|
|
||||||
let query_string = '';
|
|
||||||
if(criteria) {
|
|
||||||
order_by_params.push(criteria);
|
|
||||||
// query_string += 'sort_by=' + criteria
|
|
||||||
}
|
|
||||||
if(price_sort) order_by_params.push(price_sort);
|
|
||||||
this.order_by = order_by_params.join(",");
|
|
||||||
// return query_string;
|
|
||||||
}
|
|
||||||
|
|
||||||
reset_filters() {
|
|
||||||
this.order_by = '';
|
|
||||||
$(this.category_select).val('');
|
|
||||||
$(this.price_sort_select).val('');
|
|
||||||
$(this.criteria_select).val('Most Popular');
|
|
||||||
}
|
|
||||||
|
|
||||||
refresh_item_only_page() {
|
|
||||||
this.reset_search();
|
|
||||||
this.update_filters();
|
|
||||||
this.go_to_items_only_page(
|
|
||||||
['hub', 'Products'],
|
|
||||||
'', 'product-list'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
bind_title() {
|
|
||||||
this.page.page_title.find('.title-text').on('click', () => {
|
|
||||||
this.go_to_home_page();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
render_body() {
|
|
||||||
this.$home_page = $(`
|
|
||||||
<div class = 'hub-home-page'>
|
|
||||||
<div class='banner'></div>
|
|
||||||
<div class='listing-body row'>
|
|
||||||
<div class='main-list-section'></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
`).appendTo(this.$hub_main_section);
|
|
||||||
|
|
||||||
this.$banner = this.$hub_main_section.find('.banner');
|
|
||||||
this.$listing_body = this.$hub_main_section.find('.listing-body');
|
|
||||||
this.$main_list_section = this.$hub_main_section.find('.main-list-section');
|
|
||||||
this.$side_list_section = this.$hub_main_section.find('.side-list-section');
|
|
||||||
}
|
|
||||||
|
|
||||||
setup_lists() {
|
|
||||||
this.home_item_list = new erpnext.hub.HubList({
|
|
||||||
parent: this.$main_list_section,
|
|
||||||
title: 'New',
|
|
||||||
page_length: 20,
|
|
||||||
list_css_class: 'home-product-list',
|
|
||||||
method: 'erpnext.hub_node.get_items',
|
|
||||||
// order_by: 'request_count',
|
|
||||||
filters: {text: '', country: this.country}, // filters at the time of creation
|
|
||||||
on_item_click: (item_code) => {
|
|
||||||
frappe.set_route('hub', 'Products', item_code);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
this.home_item_list.setup();
|
|
||||||
}
|
|
||||||
|
|
||||||
setup_hub_category_filter() {
|
|
||||||
const me = this;
|
|
||||||
|
|
||||||
this.hub_category_field = this.page.add_field({
|
|
||||||
fieldtype: 'Autocomplete',
|
|
||||||
label: 'Hub Category',
|
|
||||||
change() {
|
|
||||||
let value = this.get_value();
|
|
||||||
let title = value;
|
|
||||||
if (value === 'All Categories') {
|
|
||||||
// show all items
|
|
||||||
value = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
me.home_item_list.title = title;
|
|
||||||
me.home_item_list.refresh({
|
|
||||||
text: '',
|
|
||||||
start: 0,
|
|
||||||
limit: 20,
|
|
||||||
category: value
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
frappe.call('erpnext.hub_node.get_categories')
|
|
||||||
.then((r) => {
|
|
||||||
if (r.message) {
|
|
||||||
const categories = r.message;
|
|
||||||
|
|
||||||
this.hub_category_field.set_data(
|
|
||||||
categories.map(c => c.hub_category_name)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
setup_search() {
|
|
||||||
this.$search = this.page.add_data(__('Search'));
|
|
||||||
this.$search.on('keypress', (e) => {
|
|
||||||
if(e.which === 13) {
|
|
||||||
var search_term = ($(this.$search).val() || '').toLowerCase();
|
|
||||||
this.go_to_items_only_page(
|
|
||||||
['hub', 'search', search_term],
|
|
||||||
'Search results for \'' + search_term + '\'',
|
|
||||||
'search-product-list',
|
|
||||||
{text: search_term}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
go_to_items_only_page(route, title, class_name, filters = {text: ''}, by_item_codes=0) {
|
|
||||||
frappe.set_route(route);
|
|
||||||
this.$hub_main_section.empty();
|
|
||||||
this.filtered_item_list = new erpnext.hub.HubList({
|
|
||||||
parent: this.$hub_main_section,
|
|
||||||
title: title,
|
|
||||||
page_length: 20,
|
|
||||||
list_css_class: class_name,
|
|
||||||
method: 'erpnext.hub_node.get_items',
|
|
||||||
order_by: this.order_by,
|
|
||||||
filters: filters,
|
|
||||||
by_item_codes: by_item_codes
|
|
||||||
});
|
|
||||||
this.filtered_item_list.on_item_click = (item_code) => {
|
|
||||||
frappe.set_route('hub', 'Products', item_code);
|
|
||||||
}
|
|
||||||
this.filtered_item_list.setup();
|
|
||||||
}
|
|
||||||
|
|
||||||
go_to_item_page(item_code) {
|
|
||||||
if(this.item_cache) {
|
|
||||||
let item = this.item_cache[item_code];
|
|
||||||
if(item) {
|
|
||||||
this.render_item_page(item);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.item_cache = {};
|
|
||||||
}
|
|
||||||
frappe.call({
|
|
||||||
args:{
|
|
||||||
hub_sync_id: item_code
|
|
||||||
},
|
|
||||||
method: "erpnext.hub_node.get_item_details",
|
|
||||||
callback: (r) => {
|
|
||||||
if (!r || !r.message) return;
|
|
||||||
let item = r.message;
|
|
||||||
this.item_cache[item_code] = item;
|
|
||||||
this.render_item_page(item);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
render_item_page(item) {
|
|
||||||
this.$hub_main_section.empty();
|
|
||||||
|
|
||||||
|
|
||||||
let $item_page =
|
|
||||||
$(this.get_item_page(item))
|
|
||||||
.appendTo(this.$hub_main_section);
|
|
||||||
|
|
||||||
let $company_items = $item_page.find('.company-items');
|
|
||||||
|
|
||||||
let company_item_list = new erpnext.hub.HubList({
|
|
||||||
parent: $company_items,
|
|
||||||
title: 'More by ' + item.company_name,
|
|
||||||
page_length: 5,
|
|
||||||
list_css_class: 'company-item-list',
|
|
||||||
method: 'erpnext.hub_node.get_items',
|
|
||||||
// order_by: 'request_count',
|
|
||||||
filters: {text: '', company_name: item.company_name, country: this.country},
|
|
||||||
paginated: 0,
|
|
||||||
img_size: 150
|
|
||||||
});
|
|
||||||
|
|
||||||
company_item_list.on_item_click = (item_code) => {
|
|
||||||
frappe.set_route('hub', 'Products', item_code);
|
|
||||||
}
|
|
||||||
company_item_list.setup();
|
|
||||||
|
|
||||||
$item_page.find('.rfq-btn')
|
|
||||||
.click((e) => {
|
|
||||||
const $btn = $(e.target);
|
|
||||||
|
|
||||||
this.show_rfq_modal(item)
|
|
||||||
.then(values => {
|
|
||||||
item.item_code = values.item_code;
|
|
||||||
delete values.item_code;
|
|
||||||
|
|
||||||
const supplier = values;
|
|
||||||
return [item, supplier];
|
|
||||||
})
|
|
||||||
.then(([item, supplier]) => {
|
|
||||||
return this.make_rfq(item, supplier, $btn);
|
|
||||||
})
|
|
||||||
.then(r => {
|
|
||||||
console.log(r);
|
|
||||||
if (r.message && r.message.rfq) {
|
|
||||||
$btn.addClass('disabled').html(`<span><i class='fa fa-check'></i> ${__('Quote Requested')}</span>`);
|
|
||||||
} else {
|
|
||||||
throw r;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((e) => {
|
|
||||||
console.log(e); //eslint-disable-line
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
show_rfq_modal(item) {
|
|
||||||
return new Promise(res => {
|
|
||||||
let fields = [
|
|
||||||
{ label: __('Item Code'), fieldtype: 'Data', fieldname: 'item_code', default: item.item_code },
|
|
||||||
{ fieldtype: 'Column Break' },
|
|
||||||
{ label: __('Item Group'), fieldtype: 'Link', fieldname: 'item_group', default: item.item_group },
|
|
||||||
{ label: __('Supplier Details'), fieldtype: 'Section Break' },
|
|
||||||
{ label: __('Supplier Name'), fieldtype: 'Data', fieldname: 'supplier_name', default: item.company_name },
|
|
||||||
{ label: __('Supplier Email'), fieldtype: 'Data', fieldname: 'supplier_email', default: item.seller },
|
|
||||||
{ fieldtype: 'Column Break' },
|
|
||||||
{ label: __('Supplier Type'), fieldname: 'supplier_type',
|
|
||||||
fieldtype: 'Link', options: 'Supplier Type' }
|
|
||||||
];
|
|
||||||
fields = fields.map(f => { f.reqd = 1; return f; });
|
|
||||||
|
|
||||||
const d = new frappe.ui.Dialog({
|
|
||||||
title: __('Request for Quotation'),
|
|
||||||
fields: fields,
|
|
||||||
primary_action_label: __('Send'),
|
|
||||||
primary_action: (values) => {
|
|
||||||
res(values);
|
|
||||||
d.hide();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
d.show();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
get_company_details(company_id) {
|
|
||||||
this.company_cache = this.company_cache || {};
|
|
||||||
|
|
||||||
return new Promise(resolve => {
|
|
||||||
// get from cache if exists
|
|
||||||
let company_details = this.company_cache[company_id];
|
|
||||||
if(company_details) {
|
|
||||||
resolve(company_details);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
frappe.call({
|
|
||||||
method: 'erpnext.hub_node.get_company_details',
|
|
||||||
args: {hub_sync_id: company_id}
|
|
||||||
}).then((r) => {
|
|
||||||
if (r.message) {
|
|
||||||
const company_details = r.message;
|
|
||||||
this.company_cache[company_id] = company_details;
|
|
||||||
resolve(company_details)
|
|
||||||
}
|
|
||||||
});
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
go_to_company_page(company_id) {
|
|
||||||
this.get_company_details(company_id)
|
|
||||||
.then(this.show_company_page.bind(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
show_company_page(company_details) {
|
|
||||||
this.$hub_main_section.empty();
|
|
||||||
|
|
||||||
let $company_page =
|
|
||||||
$(this.get_company_page(company_details))
|
|
||||||
.appendTo(this.$hub_main_section);
|
|
||||||
|
|
||||||
let $company_items = $company_page.find('.company-items');
|
|
||||||
|
|
||||||
let company_item_list = new erpnext.hub.HubList({
|
|
||||||
parent: $company_items,
|
|
||||||
title: 'More by ' + company_details.company_name,
|
|
||||||
page_length: 5,
|
|
||||||
list_css_class: 'company-item-list',
|
|
||||||
method: 'erpnext.hub_node.get_items',
|
|
||||||
// order_by: 'request_count',
|
|
||||||
filters: {text: '', company: company_details.company_name, country: this.country},
|
|
||||||
paginated: 0,
|
|
||||||
img_size: 150
|
|
||||||
});
|
|
||||||
|
|
||||||
company_item_list.on_item_click = (item_code) => {
|
|
||||||
frappe.set_route('hub', 'Products', item_code);
|
|
||||||
}
|
|
||||||
company_item_list.setup();
|
|
||||||
}
|
|
||||||
|
|
||||||
get_item_page(item) {
|
|
||||||
return `
|
|
||||||
<div class="hub-item-page">
|
|
||||||
<div class="item-header">
|
|
||||||
<div class="item-page-image">
|
|
||||||
${ this.home_item_list.get_item_image(item) }
|
|
||||||
</div>
|
|
||||||
<div class="title-content">
|
|
||||||
<div class="breadcrumbs">
|
|
||||||
${this.get_breadcrumb(item.item_name, "Products") }
|
|
||||||
</div>
|
|
||||||
<div class="title">
|
|
||||||
<h2>${ item.item_name }</h2>
|
|
||||||
</div>
|
|
||||||
<div class="company">
|
|
||||||
<span class="">${ item.company_name }</span>
|
|
||||||
</div>
|
|
||||||
<div class="category">
|
|
||||||
<span class="text-muted">Products</span>
|
|
||||||
</div>
|
|
||||||
<div class="description">
|
|
||||||
<span class="small">${ item.description ? item.description : "" }</span>
|
|
||||||
</div>
|
|
||||||
<div class="price">
|
|
||||||
${ item.formatted_price ? item.formatted_price : '' }
|
|
||||||
</div>
|
|
||||||
<div class="actions">
|
|
||||||
<a class="btn btn-primary rfq-btn">Request A Quote</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<div class="item-more-info"></div>
|
|
||||||
<div class="company-items">
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
get_company_page(company_details) {
|
|
||||||
return `
|
|
||||||
<div class="hub-item-page">
|
|
||||||
<div class="item-header">
|
|
||||||
<div class="title-content">
|
|
||||||
<div class="breadcrumbs">
|
|
||||||
${this.get_breadcrumb(company_details.company_name, "Company") }
|
|
||||||
</div>
|
|
||||||
<div class="title">
|
|
||||||
<h2>${ company_details.company_name }</h2>
|
|
||||||
</div>
|
|
||||||
<div class="company">
|
|
||||||
<span class="">${ company_details.country }</span>
|
|
||||||
</div>
|
|
||||||
<div class="description">
|
|
||||||
<span class="small">${ company_details.site_name }</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<div class="item-more-info"></div>
|
|
||||||
<div class="company-items">
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
get_breadcrumb(name, type) {
|
|
||||||
return `
|
|
||||||
<ul class="breadcrumb">
|
|
||||||
<li data-route="Home">
|
|
||||||
<a href><span>Home</span></a>
|
|
||||||
</li>
|
|
||||||
<li data-route="List">
|
|
||||||
<a href><span>${type}</span></a>
|
|
||||||
</li>
|
|
||||||
<li class="active">
|
|
||||||
<span>${name}</span>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
go_to_home_page() {
|
|
||||||
frappe.set_route('hub');
|
|
||||||
this.reset_filters();
|
|
||||||
this.refresh();
|
|
||||||
}
|
|
||||||
|
|
||||||
setup_menu() {
|
|
||||||
if (this.menu_setup) return;
|
|
||||||
|
|
||||||
this.page.add_menu_item(__('Hub Settings'),
|
|
||||||
() => frappe.set_route('Form', 'Hub Settings'));
|
|
||||||
this.page.add_menu_item(__('Refresh'), () => this.refresh());
|
|
||||||
this.page.add_menu_item(__('Sync'), () => this.sync_items_to_hub());
|
|
||||||
|
|
||||||
this.menu_setup = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
sync_items_to_hub() {
|
|
||||||
frappe.call('erpnext.hub_node.doctype.hub_settings.hub_settings.sync')
|
|
||||||
}
|
|
||||||
|
|
||||||
setup_sidebar() {
|
|
||||||
var me = this;
|
|
||||||
this.sidebar = new frappe.ui.Sidebar({
|
|
||||||
wrapper: this.page.wrapper.find('.layout-side-section'),
|
|
||||||
css_class: 'hub-sidebar'
|
|
||||||
});
|
|
||||||
|
|
||||||
this.add_account_to_sidebar();
|
|
||||||
}
|
|
||||||
|
|
||||||
add_account_to_sidebar() {
|
|
||||||
this.sidebar.add_item({
|
|
||||||
label: this.hub_settings.company,
|
|
||||||
on_click: () => frappe.set_route('Form', 'Company', this.hub_settings.company)
|
|
||||||
}, __("Account"));
|
|
||||||
|
|
||||||
this.sidebar.add_item({
|
|
||||||
label: __("My Orders"),
|
|
||||||
on_click: () => frappe.set_route('List', 'Request for Quotation')
|
|
||||||
}, __("Account"));
|
|
||||||
}
|
|
||||||
|
|
||||||
get_search_term() {
|
|
||||||
return this.$search.val();
|
|
||||||
}
|
|
||||||
|
|
||||||
reset_search() {
|
|
||||||
this.$search.val('');
|
|
||||||
}
|
|
||||||
|
|
||||||
make_rfq(item, supplier, btn) {
|
|
||||||
console.log(supplier);
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
frappe.call({
|
|
||||||
method: 'erpnext.hub_node.make_rfq_and_send_opportunity',
|
|
||||||
args: { item, supplier },
|
|
||||||
callback: resolve,
|
|
||||||
btn,
|
|
||||||
}).fail(reject);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
go_to_seen_items() {
|
|
||||||
this.go_to_items_only_page(
|
|
||||||
['hub', 'Requested Products'],
|
|
||||||
__('Requested Products'),
|
|
||||||
'requested-product-list',
|
|
||||||
{}, 1
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
erpnext.hub.HubList = class HubList {
|
|
||||||
constructor({
|
|
||||||
parent = null,
|
|
||||||
title = 'Products',
|
|
||||||
page_length = 20,
|
|
||||||
list_css_class = '',
|
|
||||||
method = 'erpnext.hub_node.get_items',
|
|
||||||
filters = {text: ''},
|
|
||||||
order_by = '',
|
|
||||||
by_item_codes = 0,
|
|
||||||
paginated = 1,
|
|
||||||
on_item_click = null,
|
|
||||||
img_size = 200
|
|
||||||
}) {
|
|
||||||
this.parent = parent;
|
|
||||||
this.title = title;
|
|
||||||
this.page_length = page_length;
|
|
||||||
this.list_css_class = list_css_class;
|
|
||||||
this.method = method;
|
|
||||||
this.filters = filters;
|
|
||||||
this.order_by = order_by;
|
|
||||||
this.by_item_codes = by_item_codes;
|
|
||||||
this.paginated = paginated;
|
|
||||||
|
|
||||||
this.on_item_click = on_item_click;
|
|
||||||
this.img_size = img_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
// to be called on demand
|
|
||||||
setup() {
|
|
||||||
this.container = $(`
|
|
||||||
<div class='item-list-container ${this.list_css_class}' data-page-length='${this.page_length}'>
|
|
||||||
<div class='item-list-header'>
|
|
||||||
<h3>${this.title}</h3>
|
|
||||||
</div>
|
|
||||||
<div class='item-list'></div>
|
|
||||||
<div class='list-state'>
|
|
||||||
<div class='loading'>
|
|
||||||
<p class='text-muted text-center'>${__('Loading...')}</p>
|
|
||||||
</div>
|
|
||||||
<div class='done hide'>
|
|
||||||
<p class='text-muted text-center'>${__('No more results')}</p>
|
|
||||||
</div>
|
|
||||||
<div class='more text-right'>
|
|
||||||
<button class='btn btn-default btn-sm'>${__('More')}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>`)
|
|
||||||
.appendTo(this.parent);
|
|
||||||
|
|
||||||
this.$item_list_title = this.container.find('.item-list-header h3');
|
|
||||||
this.$list = this.container.find('.item-list');
|
|
||||||
this.$loading = this.container.find('.loading').hide();
|
|
||||||
this.$more = this.container.find('.more').hide();
|
|
||||||
this.$done = this.container.find('.done');
|
|
||||||
|
|
||||||
this.$more.on('click', () => {
|
|
||||||
this.next_page();
|
|
||||||
});
|
|
||||||
|
|
||||||
this.next_page();
|
|
||||||
}
|
|
||||||
|
|
||||||
refresh(filters = this.filters) {
|
|
||||||
this.reset();
|
|
||||||
this.set_filters(filters);
|
|
||||||
this.next_page();
|
|
||||||
}
|
|
||||||
|
|
||||||
reset() {
|
|
||||||
this.$list.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
set_filters(filters) {
|
|
||||||
this.filters = filters;
|
|
||||||
}
|
|
||||||
|
|
||||||
next_page() {
|
|
||||||
this.$item_list_title.html(this.title);
|
|
||||||
const start = this.$list.find('.hub-item-wrapper').length;
|
|
||||||
this.$loading.show();
|
|
||||||
|
|
||||||
// build args
|
|
||||||
let args = {
|
|
||||||
start: start,
|
|
||||||
// query one extra
|
|
||||||
limit: this.page_length + 1
|
|
||||||
};
|
|
||||||
Object.assign(args, this.filters);
|
|
||||||
console.log("filters: ", args);
|
|
||||||
args.order_by = this.order_by;
|
|
||||||
args.by_item_codes = this.by_item_codes;
|
|
||||||
|
|
||||||
frappe.call({
|
|
||||||
method: this.method,
|
|
||||||
args: args,
|
|
||||||
callback: (r) => {
|
|
||||||
let items = r.message;
|
|
||||||
console.log("items: ", items);
|
|
||||||
this.render_items(items);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
render_items(items) {
|
|
||||||
if(items) {
|
|
||||||
// clear any filler divs
|
|
||||||
this.$list.find('.filler').remove();
|
|
||||||
let done = 0;
|
|
||||||
console.log("items length", items.length);
|
|
||||||
if(items.length && items.length > this.page_length) {
|
|
||||||
// remove the extra queried
|
|
||||||
items.pop();
|
|
||||||
} else {
|
|
||||||
done = 1;
|
|
||||||
}
|
|
||||||
items.forEach((item) => {
|
|
||||||
this.make_item_card(item).appendTo(this.$list);
|
|
||||||
});
|
|
||||||
|
|
||||||
const remainder = items.length % 4;
|
|
||||||
if (remainder > 0) {
|
|
||||||
// fill with filler divs to make flexbox happy
|
|
||||||
Array.from(Array(remainder))
|
|
||||||
.map(r => $('<div class="filler">').css('width', '200px').appendTo(this.$list));
|
|
||||||
}
|
|
||||||
this.update_list_state(done);
|
|
||||||
} else {
|
|
||||||
this.update_list_state(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
update_list_state(done=0) {
|
|
||||||
this.$loading.hide();
|
|
||||||
if(done) {
|
|
||||||
this.$done.removeClass('hide');
|
|
||||||
this.$more.hide();
|
|
||||||
} else {
|
|
||||||
this.$more.show();
|
|
||||||
this.$done.addClass('hide');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
make_item_card(item) {
|
|
||||||
let $item_card = $(`
|
|
||||||
<div class="hub-item-wrapper" style="max-width: ${this.img_size}px;">
|
|
||||||
<a class="item-link" href>
|
|
||||||
<div class="hub-item-image">
|
|
||||||
${ this.get_item_image(item) }
|
|
||||||
</div>
|
|
||||||
<div class="hub-item-title">
|
|
||||||
<h5 class="bold">
|
|
||||||
${!item.seen ? item.item_name : `<span class="indicator blue">${item.item_name}</span>`}
|
|
||||||
<h5>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<div class="company-link">
|
|
||||||
<a data-company-name="${ item.company_name }" class="">${ item.company_name }</a>
|
|
||||||
</div>
|
|
||||||
<div>${ item.formatted_price ? item.formatted_price : ''}</div>
|
|
||||||
</div>
|
|
||||||
`);
|
|
||||||
|
|
||||||
$item_card.find(".item-link").click((e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
this.on_item_click && this.on_item_click(item.name);
|
|
||||||
});
|
|
||||||
|
|
||||||
return $item_card;
|
|
||||||
}
|
|
||||||
|
|
||||||
get_item_image(item, size=this.img_size) {
|
|
||||||
const _size = size + 'px';
|
|
||||||
const item_image = item.image ?
|
|
||||||
`<img src="${item.image}"><span class="helper"></span>` :
|
|
||||||
`<div class="standard-image">${item.item_name[0]}</div>`;
|
|
||||||
|
|
||||||
return `
|
|
||||||
<div class="img-wrapper"
|
|
||||||
style="max-width: ${_size}; width: ${_size}; height: ${_size};">
|
|
||||||
${item_image}
|
|
||||||
</div>`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
{
|
|
||||||
"content": null,
|
|
||||||
"creation": "2015-02-18 05:17:17.301735",
|
|
||||||
"docstatus": 0,
|
|
||||||
"doctype": "Page",
|
|
||||||
"modified": "2015-02-18 05:17:17.301735",
|
|
||||||
"modified_by": "Administrator",
|
|
||||||
"module": "Hub Node",
|
|
||||||
"name": "hub",
|
|
||||||
"owner": "Administrator",
|
|
||||||
"page_name": "hub",
|
|
||||||
"roles": [
|
|
||||||
{
|
|
||||||
"role": "All"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"script": null,
|
|
||||||
"standard": "Yes",
|
|
||||||
"style": null,
|
|
||||||
"title": "Hub"
|
|
||||||
}
|
|
||||||
@@ -502,4 +502,6 @@ erpnext.patches.v10_0.taxes_issue_with_pos
|
|||||||
erpnext.patches.v10_0.set_qty_in_transactions_based_on_serial_no_input
|
erpnext.patches.v10_0.set_qty_in_transactions_based_on_serial_no_input
|
||||||
erpnext.patches.v10_0.show_leaves_of_all_department_members_in_calendar
|
erpnext.patches.v10_0.show_leaves_of_all_department_members_in_calendar
|
||||||
erpnext.patches.v10_0.update_status_in_purchase_receipt
|
erpnext.patches.v10_0.update_status_in_purchase_receipt
|
||||||
erpnext.patches.v10_0.update_address_template_for_india
|
erpnext.patches.v10_0.update_address_template_for_india
|
||||||
|
erpnext.patches.v10_0.set_discount_amount
|
||||||
|
erpnext.patches.v10_0.recalculate_gross_margin_for_project
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
# Copyright (c) 2017, Frappe and Contributors
|
||||||
|
# License: GNU General Public License v3. See license.txt
|
||||||
|
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
import frappe
|
||||||
|
|
||||||
|
def execute():
|
||||||
|
frappe.reload_doc('projects', 'doctype', 'project')
|
||||||
|
for d in frappe.db.sql(""" select name from `tabProject` where
|
||||||
|
ifnull(total_consumed_material_cost, 0 ) > 0 and ifnull(total_billed_amount, 0) > 0""", as_dict=1):
|
||||||
|
doc = frappe.get_doc("Project", d.name)
|
||||||
|
doc.calculate_gross_margin()
|
||||||
|
doc.db_set('gross_margin', doc.gross_margin)
|
||||||
|
doc.db_set('per_gross_margin', doc.per_gross_margin)
|
||||||
56
erpnext/patches/v10_0/set_discount_amount.py
Normal file
56
erpnext/patches/v10_0/set_discount_amount.py
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
|
||||||
|
import frappe
|
||||||
|
|
||||||
|
def execute():
|
||||||
|
frappe.reload_doc("accounts", "doctype", "sales_invoice_item")
|
||||||
|
frappe.reload_doc('accounts', 'doctype', 'purchase_invoice_item')
|
||||||
|
frappe.reload_doc('buying', 'doctype', 'purchase_order_item')
|
||||||
|
frappe.reload_doc('buying', 'doctype', 'supplier_quotation_item')
|
||||||
|
frappe.reload_doc('selling', 'doctype', 'sales_order_item')
|
||||||
|
frappe.reload_doc('selling', 'doctype', 'quotation_item')
|
||||||
|
frappe.reload_doc('stock', 'doctype', 'delivery_note_item')
|
||||||
|
frappe.reload_doc('stock', 'doctype', 'purchase_receipt_item')
|
||||||
|
|
||||||
|
selling_doctypes = ["Sales Order Item", "Sales Invoice Item", "Delivery Note Item", "Quotation Item"]
|
||||||
|
buying_doctypes = ["Purchase Order Item", "Purchase Invoice Item", "Purchase Receipt Item", "Supplier Quotation Item"]
|
||||||
|
|
||||||
|
for doctype in selling_doctypes:
|
||||||
|
values = frappe.db.sql('''
|
||||||
|
SELECT
|
||||||
|
discount_percentage, rate_with_margin, price_list_rate, name
|
||||||
|
FROM
|
||||||
|
`tab%s`
|
||||||
|
WHERE
|
||||||
|
ifnull(discount_percentage, 0) > 0
|
||||||
|
''' % (doctype), as_dict=True)
|
||||||
|
calculate_discount(doctype, values)
|
||||||
|
|
||||||
|
for doctype in buying_doctypes:
|
||||||
|
values = frappe.db.sql('''
|
||||||
|
SELECT
|
||||||
|
discount_percentage, price_list_rate, name
|
||||||
|
FROM
|
||||||
|
`tab%s`
|
||||||
|
WHERE
|
||||||
|
discount_percentage > 0
|
||||||
|
''' % (doctype), as_dict=True)
|
||||||
|
calculate_discount(doctype, values)
|
||||||
|
|
||||||
|
def calculate_discount(doctype, values):
|
||||||
|
rate = None
|
||||||
|
if not values: return
|
||||||
|
for d in values:
|
||||||
|
if d.rate_with_margin and d.rate_with_margin > 0:
|
||||||
|
rate = d.rate_with_margin
|
||||||
|
else:
|
||||||
|
rate = d.price_list_rate
|
||||||
|
|
||||||
|
discount_value = rate * d.get('discount_percentage') / 100
|
||||||
|
frappe.db.sql('''
|
||||||
|
UPDATE
|
||||||
|
`tab%s`
|
||||||
|
SET
|
||||||
|
discount_amount = %s
|
||||||
|
WHERE
|
||||||
|
name = '%s'
|
||||||
|
''' % (doctype, discount_value, d.get('name')))
|
||||||
@@ -14,6 +14,7 @@
|
|||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
@@ -41,10 +42,43 @@
|
|||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "column_break_3",
|
||||||
|
"fieldtype": "Column Break",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
@@ -71,10 +105,75 @@
|
|||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "show_availability_status",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Show Availability Status",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "section_break_5",
|
||||||
|
"fieldtype": "Section Break",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
@@ -103,6 +202,7 @@
|
|||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@@ -116,7 +216,7 @@
|
|||||||
"issingle": 1,
|
"issingle": 1,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2017-11-07 19:34:33.055048",
|
"modified": "2018-08-14 17:59:58.473100",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Portal",
|
"module": "Portal",
|
||||||
"name": "Products Settings",
|
"name": "Products Settings",
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ class Project(Document):
|
|||||||
self.tasks = []
|
self.tasks = []
|
||||||
self.load_tasks()
|
self.load_tasks()
|
||||||
self.send_welcome_email()
|
self.send_welcome_email()
|
||||||
|
self.update_percent_complete()
|
||||||
|
|
||||||
def validate_project_name(self):
|
def validate_project_name(self):
|
||||||
if self.get("__islocal") and frappe.db.exists("Project", self.project_name):
|
if self.get("__islocal") and frappe.db.exists("Project", self.project_name):
|
||||||
@@ -236,9 +237,13 @@ class Project(Document):
|
|||||||
self.update_purchase_costing()
|
self.update_purchase_costing()
|
||||||
self.update_sales_amount()
|
self.update_sales_amount()
|
||||||
self.update_billed_amount()
|
self.update_billed_amount()
|
||||||
|
self.calculate_gross_margin()
|
||||||
|
|
||||||
self.gross_margin = flt(self.total_billed_amount) - (flt(self.total_costing_amount) + flt(self.total_expense_claim) + flt(self.total_purchase_cost))
|
def calculate_gross_margin(self):
|
||||||
|
expense_amount = (flt(self.total_costing_amount) + flt(self.total_expense_claim)
|
||||||
|
+ flt(self.total_purchase_cost) + flt(self.get('total_consumed_material_cost', 0)))
|
||||||
|
|
||||||
|
self.gross_margin = flt(self.total_billed_amount) - expense_amount
|
||||||
if self.total_billed_amount:
|
if self.total_billed_amount:
|
||||||
self.per_gross_margin = (self.gross_margin / flt(self.total_billed_amount)) *100
|
self.per_gross_margin = (self.gross_margin / flt(self.total_billed_amount)) *100
|
||||||
|
|
||||||
|
|||||||
@@ -113,8 +113,8 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({
|
|||||||
var item = frappe.get_doc(cdt, cdn);
|
var item = frappe.get_doc(cdt, cdn);
|
||||||
frappe.model.round_floats_in(item, ["price_list_rate", "discount_percentage"]);
|
frappe.model.round_floats_in(item, ["price_list_rate", "discount_percentage"]);
|
||||||
|
|
||||||
item.rate = flt(item.price_list_rate * (1 - item.discount_percentage / 100.0),
|
item.discount_amount = flt(item.price_list_rate) * flt(item.discount_percentage) / 100;
|
||||||
precision("rate", item));
|
item.rate = flt((item.price_list_rate) - (item.discount_amount), precision('rate', item));
|
||||||
|
|
||||||
this.calculate_taxes_and_totals();
|
this.calculate_taxes_and_totals();
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -16,8 +16,8 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
|
|||||||
item.rate = flt(item.rate_with_margin , precision("rate", item));
|
item.rate = flt(item.rate_with_margin , precision("rate", item));
|
||||||
|
|
||||||
if(item.discount_percentage){
|
if(item.discount_percentage){
|
||||||
var discount_value = flt(item.rate_with_margin) * flt(item.discount_percentage) / 100;
|
item.discount_amount = flt(item.rate_with_margin) * flt(item.discount_percentage) / 100;
|
||||||
item.rate = flt((item.rate_with_margin) - (discount_value), precision('rate', item));
|
item.rate = flt((item.rate_with_margin) - (item.discount_amount), precision('rate', item));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -790,6 +790,38 @@
|
|||||||
"unique": 0,
|
"unique": 0,
|
||||||
"width": "100px"
|
"width": "100px"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"depends_on": "discount_percentage",
|
||||||
|
"fieldname": "discount_amount",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Discount Amount",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"options": "currency",
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 1,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
@@ -1766,7 +1798,7 @@
|
|||||||
"istable": 1,
|
"istable": 1,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"menu_index": 0,
|
"menu_index": 0,
|
||||||
"modified": "2017-12-14 09:39:17.180709",
|
"modified": "2018-08-06 05:18:38.135668",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Selling",
|
"module": "Selling",
|
||||||
"name": "Quotation Item",
|
"name": "Quotation Item",
|
||||||
|
|||||||
@@ -820,6 +820,38 @@
|
|||||||
"unique": 0,
|
"unique": 0,
|
||||||
"width": "70px"
|
"width": "70px"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"depends_on": "discount_percentage",
|
||||||
|
"fieldname": "discount_amount",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Discount Amount",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"options": "currency",
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 1,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
@@ -2146,7 +2178,7 @@
|
|||||||
"istable": 1,
|
"istable": 1,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"menu_index": 0,
|
"menu_index": 0,
|
||||||
"modified": "2017-11-30 14:05:39.173834",
|
"modified": "2018-08-06 05:17:51.297862",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Selling",
|
"module": "Selling",
|
||||||
"name": "Sales Order Item",
|
"name": "Sales Order Item",
|
||||||
|
|||||||
@@ -145,6 +145,15 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({
|
|||||||
this.set_gross_profit(item);
|
this.set_gross_profit(item);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
discount_amount: function(doc, cdt, cdn) {
|
||||||
|
var item = frappe.get_doc(cdt, cdn);
|
||||||
|
if(!item.price_list_rate) {
|
||||||
|
item.discount_amount = 0.0;
|
||||||
|
} else {
|
||||||
|
this.price_list_rate(doc, cdt, cdn);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
commission_rate: function() {
|
commission_rate: function() {
|
||||||
this.calculate_commission();
|
this.calculate_commission();
|
||||||
refresh_field("total_commission");
|
refresh_field("total_commission");
|
||||||
|
|||||||
@@ -138,6 +138,9 @@ def get_item_for_list_in_html(context):
|
|||||||
if (context.get("website_image") or "").startswith("files/"):
|
if (context.get("website_image") or "").startswith("files/"):
|
||||||
context["website_image"] = "/" + urllib.quote(context["website_image"])
|
context["website_image"] = "/" + urllib.quote(context["website_image"])
|
||||||
|
|
||||||
|
context["show_availability_status"] = cint(frappe.db.get_single_value('Products Settings',
|
||||||
|
'show_availability_status'))
|
||||||
|
|
||||||
products_template = 'templates/includes/products_as_grid.html'
|
products_template = 'templates/includes/products_as_grid.html'
|
||||||
if cint(frappe.db.get_single_value('Products Settings', 'products_as_list')):
|
if cint(frappe.db.get_single_value('Products Settings', 'products_as_list')):
|
||||||
products_template = 'templates/includes/products_as_list.html'
|
products_template = 'templates/includes/products_as_list.html'
|
||||||
|
|||||||
@@ -819,6 +819,38 @@
|
|||||||
"unique": 0,
|
"unique": 0,
|
||||||
"width": "100px"
|
"width": "100px"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"depends_on": "discount_percentage",
|
||||||
|
"fieldname": "discount_amount",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Discount Amount",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"options": "currency",
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 1,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
@@ -2139,7 +2171,7 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2017-11-30 14:07:12.217563",
|
"modified": "2018-08-06 05:18:26.132899",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Stock",
|
"module": "Stock",
|
||||||
"name": "Delivery Note Item",
|
"name": "Delivery Note Item",
|
||||||
|
|||||||
@@ -759,6 +759,38 @@
|
|||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"depends_on": "discount_percentage",
|
||||||
|
"fieldname": "discount_amount",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Discount Amount",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"options": "currency",
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 1,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
@@ -2290,7 +2322,7 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2017-12-06 13:50:08.201145",
|
"modified": "2018-08-06 05:16:48.590787",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Stock",
|
"module": "Stock",
|
||||||
"name": "Purchase Receipt Item",
|
"name": "Purchase Receipt Item",
|
||||||
|
|||||||
@@ -82,6 +82,7 @@ class StockEntry(StockController):
|
|||||||
if self.purchase_order and self.purpose == "Subcontract":
|
if self.purchase_order and self.purpose == "Subcontract":
|
||||||
self.update_purchase_order_supplied_items()
|
self.update_purchase_order_supplied_items()
|
||||||
self.make_gl_entries_on_cancel()
|
self.make_gl_entries_on_cancel()
|
||||||
|
self.update_cost_in_project()
|
||||||
|
|
||||||
def validate_purpose(self):
|
def validate_purpose(self):
|
||||||
valid_purposes = ["Material Issue", "Material Receipt", "Material Transfer", "Material Transfer for Manufacture",
|
valid_purposes = ["Material Issue", "Material Receipt", "Material Transfer", "Material Transfer for Manufacture",
|
||||||
@@ -107,8 +108,8 @@ class StockEntry(StockController):
|
|||||||
se.docstatus = 1 and se.project = %s and sed.parent = se.name
|
se.docstatus = 1 and se.project = %s and sed.parent = se.name
|
||||||
and (sed.t_warehouse is null or sed.t_warehouse = '')""", self.project, as_list=1)
|
and (sed.t_warehouse is null or sed.t_warehouse = '')""", self.project, as_list=1)
|
||||||
|
|
||||||
if amount:
|
amount = amount[0][0] if amount else 0
|
||||||
frappe.db.set_value('Project', self.project, 'total_consumed_material_cost', amount[0][0])
|
frappe.db.set_value('Project', self.project, 'total_consumed_material_cost', amount)
|
||||||
|
|
||||||
def validate_item(self):
|
def validate_item(self):
|
||||||
stock_items = self.get_stock_items()
|
stock_items = self.get_stock_items()
|
||||||
|
|||||||
@@ -139,7 +139,7 @@ class Warehouse(NestedSet):
|
|||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_children(doctype, parent=None, company=None, is_root=False):
|
def get_children(doctype, parent=None, company=None, is_root=False):
|
||||||
from erpnext.stock.utils import get_stock_value_on
|
from erpnext.stock.utils import get_stock_value_from_bin
|
||||||
|
|
||||||
if is_root:
|
if is_root:
|
||||||
parent = ""
|
parent = ""
|
||||||
@@ -154,7 +154,7 @@ def get_children(doctype, parent=None, company=None, is_root=False):
|
|||||||
|
|
||||||
# return warehouses
|
# return warehouses
|
||||||
for wh in warehouses:
|
for wh in warehouses:
|
||||||
wh["balance"] = get_stock_value_on(warehouse=wh.value)
|
wh["balance"] = get_stock_value_from_bin(warehouse=wh.value)
|
||||||
return warehouses
|
return warehouses
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
@@ -170,4 +170,4 @@ def add_node():
|
|||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def convert_to_group_or_ledger():
|
def convert_to_group_or_ledger():
|
||||||
args = frappe.form_dict
|
args = frappe.form_dict
|
||||||
return frappe.get_doc("Warehouse", args.docname).convert_to_group_or_ledger()
|
return frappe.get_doc("Warehouse", args.docname).convert_to_group_or_ledger()
|
||||||
|
|||||||
@@ -481,8 +481,8 @@ def get_projected_qty(item_code, warehouse):
|
|||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_bin_details(item_code, warehouse):
|
def get_bin_details(item_code, warehouse):
|
||||||
return frappe.db.get_value("Bin", {"item_code": item_code, "warehouse": warehouse},
|
return frappe.db.get_value("Bin", {"item_code": item_code, "warehouse": warehouse},
|
||||||
["projected_qty", "actual_qty"], as_dict=True) \
|
["projected_qty", "actual_qty", "reserved_qty"], as_dict=True) \
|
||||||
or {"projected_qty": 0, "actual_qty": 0}
|
or {"projected_qty": 0, "actual_qty": 0, "reserved_qty": 0}
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_serial_no_details(item_code, warehouse, stock_qty, serial_no):
|
def get_serial_no_details(item_code, warehouse, stock_qty, serial_no):
|
||||||
|
|||||||
@@ -9,21 +9,45 @@ from frappe.utils import flt, cstr, nowdate, nowtime
|
|||||||
|
|
||||||
class InvalidWarehouseCompany(frappe.ValidationError): pass
|
class InvalidWarehouseCompany(frappe.ValidationError): pass
|
||||||
|
|
||||||
|
def get_stock_value_from_bin(warehouse=None, item_code=None):
|
||||||
|
values = {}
|
||||||
|
conditions = ""
|
||||||
|
if warehouse:
|
||||||
|
conditions += """ and warehouse in (
|
||||||
|
select w2.name from `tabWarehouse` w1
|
||||||
|
join `tabWarehouse` w2 on
|
||||||
|
w1.name = %(warehouse)s
|
||||||
|
and w2.lft between w1.lft and w1.rgt
|
||||||
|
) """
|
||||||
|
|
||||||
|
values['warehouse'] = warehouse
|
||||||
|
|
||||||
|
if item_code:
|
||||||
|
conditions += " and item_code = %(item_code)s"
|
||||||
|
|
||||||
|
values['item_code'] = item_code
|
||||||
|
|
||||||
|
query = "select sum(stock_value) from `tabBin` where 1 = 1 %s" % conditions
|
||||||
|
|
||||||
|
stock_value = frappe.db.sql(query, values)
|
||||||
|
|
||||||
|
return stock_value
|
||||||
|
|
||||||
def get_stock_value_on(warehouse=None, posting_date=None, item_code=None):
|
def get_stock_value_on(warehouse=None, posting_date=None, item_code=None):
|
||||||
if not posting_date: posting_date = nowdate()
|
if not posting_date: posting_date = nowdate()
|
||||||
|
|
||||||
values, condition = [posting_date], ""
|
values, condition = [posting_date], ""
|
||||||
|
|
||||||
if warehouse:
|
if warehouse:
|
||||||
|
|
||||||
lft, rgt, is_group = frappe.db.get_value("Warehouse", warehouse, ["lft", "rgt", "is_group"])
|
lft, rgt, is_group = frappe.db.get_value("Warehouse", warehouse, ["lft", "rgt", "is_group"])
|
||||||
|
|
||||||
if is_group:
|
if is_group:
|
||||||
values.extend([lft, rgt])
|
values.extend([lft, rgt])
|
||||||
condition += "and exists (\
|
condition += "and exists (\
|
||||||
select name from `tabWarehouse` wh where wh.name = sle.warehouse\
|
select name from `tabWarehouse` wh where wh.name = sle.warehouse\
|
||||||
and wh.lft >= %s and wh.rgt <= %s)"
|
and wh.lft >= %s and wh.rgt <= %s)"
|
||||||
|
|
||||||
else:
|
else:
|
||||||
values.append(warehouse)
|
values.append(warehouse)
|
||||||
condition += " AND warehouse = %s"
|
condition += " AND warehouse = %s"
|
||||||
@@ -43,7 +67,7 @@ def get_stock_value_on(warehouse=None, posting_date=None, item_code=None):
|
|||||||
for sle in stock_ledger_entries:
|
for sle in stock_ledger_entries:
|
||||||
if not sle_map.has_key((sle.item_code, sle.warehouse)):
|
if not sle_map.has_key((sle.item_code, sle.warehouse)):
|
||||||
sle_map[(sle.item_code, sle.warehouse)] = flt(sle.stock_value)
|
sle_map[(sle.item_code, sle.warehouse)] = flt(sle.stock_value)
|
||||||
|
|
||||||
return sum(sle_map.values())
|
return sum(sle_map.values())
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
@@ -73,17 +97,17 @@ def get_latest_stock_qty(item_code, warehouse=None):
|
|||||||
values, condition = [item_code], ""
|
values, condition = [item_code], ""
|
||||||
if warehouse:
|
if warehouse:
|
||||||
lft, rgt, is_group = frappe.db.get_value("Warehouse", warehouse, ["lft", "rgt", "is_group"])
|
lft, rgt, is_group = frappe.db.get_value("Warehouse", warehouse, ["lft", "rgt", "is_group"])
|
||||||
|
|
||||||
if is_group:
|
if is_group:
|
||||||
values.extend([lft, rgt])
|
values.extend([lft, rgt])
|
||||||
condition += "and exists (\
|
condition += "and exists (\
|
||||||
select name from `tabWarehouse` wh where wh.name = tabBin.warehouse\
|
select name from `tabWarehouse` wh where wh.name = tabBin.warehouse\
|
||||||
and wh.lft >= %s and wh.rgt <= %s)"
|
and wh.lft >= %s and wh.rgt <= %s)"
|
||||||
|
|
||||||
else:
|
else:
|
||||||
values.append(warehouse)
|
values.append(warehouse)
|
||||||
condition += " AND warehouse = %s"
|
condition += " AND warehouse = %s"
|
||||||
|
|
||||||
actual_qty = frappe.db.sql("""select sum(actual_qty) from tabBin
|
actual_qty = frappe.db.sql("""select sum(actual_qty) from tabBin
|
||||||
where item_code=%s {0}""".format(condition), values)[0][0]
|
where item_code=%s {0}""".format(condition), values)[0][0]
|
||||||
|
|
||||||
@@ -219,4 +243,3 @@ def validate_warehouse_company(warehouse, company):
|
|||||||
def is_group_warehouse(warehouse):
|
def is_group_warehouse(warehouse):
|
||||||
if frappe.db.get_value("Warehouse", warehouse, "is_group"):
|
if frappe.db.get_value("Warehouse", warehouse, "is_group"):
|
||||||
frappe.throw(_("Group node warehouse is not allowed to select for transactions"))
|
frappe.throw(_("Group node warehouse is not allowed to select for transactions"))
|
||||||
|
|
||||||
|
|||||||
@@ -5,10 +5,12 @@
|
|||||||
<div class="product-image-img">
|
<div class="product-image-img">
|
||||||
{{ product_image_square(thumbnail or website_image) }}
|
{{ product_image_square(thumbnail or website_image) }}
|
||||||
<div class="product-text" itemprop="name">{{ item_name }}</div>
|
<div class="product-text" itemprop="name">{{ item_name }}</div>
|
||||||
{% if in_stock or not is_stock_item %}
|
{% if show_availability_status %}
|
||||||
<div style='color: green'> <i class='fa fa-check'></i> {{ _("In stock") }}</div>
|
{% if in_stock or not is_stock_item %}
|
||||||
{% else %}
|
<div style='color: green'> <i class='fa fa-check'></i> {{ _("In stock") }}</div>
|
||||||
<div style='color: red'> <i class='fa fa-close'></i> {{ _("Not in stock") }}</div>
|
{% else %}
|
||||||
|
<div style='color: red'> <i class='fa fa-close'></i> {{ _("Not in stock") }}</div>
|
||||||
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user