mirror of
https://github.com/frappe/erpnext.git
synced 2026-05-18 12:39:18 +00:00
Merge branch 'v12-pre-release' into version-12
This commit is contained in:
@@ -63,6 +63,7 @@ install:
|
|||||||
- tar -xf /tmp/wkhtmltox.tar.xz -C /tmp
|
- tar -xf /tmp/wkhtmltox.tar.xz -C /tmp
|
||||||
- sudo mv /tmp/wkhtmltox/bin/wkhtmltopdf /usr/local/bin/wkhtmltopdf
|
- sudo mv /tmp/wkhtmltox/bin/wkhtmltopdf /usr/local/bin/wkhtmltopdf
|
||||||
- sudo chmod o+x /usr/local/bin/wkhtmltopdf
|
- sudo chmod o+x /usr/local/bin/wkhtmltopdf
|
||||||
|
- sudo apt-get install libcups2-dev
|
||||||
|
|
||||||
- cd ~/frappe-bench
|
- cd ~/frappe-bench
|
||||||
|
|
||||||
|
|||||||
@@ -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__ = '12.4.3'
|
__version__ = '12.5.0'
|
||||||
|
|
||||||
def get_default_company(user=None):
|
def get_default_company(user=None):
|
||||||
'''Get default company for user'''
|
'''Get default company for user'''
|
||||||
|
|||||||
@@ -95,29 +95,29 @@ class Account(NestedSet):
|
|||||||
# ignore validation while creating new compnay or while syncing to child companies
|
# ignore validation while creating new compnay or while syncing to child companies
|
||||||
if frappe.local.flags.ignore_root_company_validation or self.flags.ignore_root_company_validation:
|
if frappe.local.flags.ignore_root_company_validation or self.flags.ignore_root_company_validation:
|
||||||
return
|
return
|
||||||
|
|
||||||
ancestors = get_root_company(self.company)
|
ancestors = get_root_company(self.company)
|
||||||
if ancestors:
|
if ancestors:
|
||||||
if frappe.get_value("Company", self.company, "allow_account_creation_against_child_company"):
|
if frappe.get_value("Company", self.company, "allow_account_creation_against_child_company"):
|
||||||
return
|
return
|
||||||
|
|
||||||
if not frappe.db.get_value("Account",
|
if not frappe.db.get_value("Account",
|
||||||
{'account_name': self.account_name, 'company': ancestors[0]}, 'name'):
|
{'account_name': self.account_name, 'company': ancestors[0]}, 'name'):
|
||||||
frappe.throw(_("Please add the account to root level Company - %s" % ancestors[0]))
|
frappe.throw(_("Please add the account to root level Company - %s" % ancestors[0]))
|
||||||
else:
|
else:
|
||||||
descendants = get_descendants_of('Company', self.company)
|
descendants = get_descendants_of('Company', self.company)
|
||||||
if not descendants: return
|
if not descendants: return
|
||||||
|
|
||||||
parent_acc_name_map = {}
|
parent_acc_name_map = {}
|
||||||
parent_acc_name, parent_acc_number = frappe.db.get_value('Account', self.parent_account, \
|
parent_acc_name, parent_acc_number = frappe.db.get_value('Account', self.parent_account, \
|
||||||
["account_name", "account_number"])
|
["account_name", "account_number"])
|
||||||
for d in frappe.db.get_values('Account',
|
filters = {
|
||||||
{ "company": ["in", descendants], "account_name": parent_acc_name,
|
"company": ["in", descendants],
|
||||||
"account_number": parent_acc_number },
|
"account_name": parent_acc_name,
|
||||||
["company", "name"], as_dict=True):
|
}
|
||||||
|
if parent_acc_number:
|
||||||
|
filters["account_number"] = parent_acc_number
|
||||||
|
|
||||||
|
for d in frappe.db.get_values('Account', filters=filters, fieldname=["company", "name"], as_dict=True):
|
||||||
parent_acc_name_map[d["company"]] = d["name"]
|
parent_acc_name_map[d["company"]] = d["name"]
|
||||||
if not parent_acc_name_map: return
|
if not parent_acc_name_map: return
|
||||||
|
|
||||||
self.create_account_for_child_company(parent_acc_name_map, descendants, parent_acc_name)
|
self.create_account_for_child_company(parent_acc_name_map, descendants, parent_acc_name)
|
||||||
|
|
||||||
def validate_group_or_ledger(self):
|
def validate_group_or_ledger(self):
|
||||||
@@ -175,7 +175,6 @@ class Account(NestedSet):
|
|||||||
filters["account_number"] = self.account_number
|
filters["account_number"] = self.account_number
|
||||||
|
|
||||||
child_account = frappe.db.get_value("Account", filters, 'name')
|
child_account = frappe.db.get_value("Account", filters, 'name')
|
||||||
|
|
||||||
if not child_account:
|
if not child_account:
|
||||||
doc = frappe.copy_doc(self)
|
doc = frappe.copy_doc(self)
|
||||||
doc.flags.ignore_root_company_validation = True
|
doc.flags.ignore_root_company_validation = True
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
|
"actions": [],
|
||||||
"allow_import": 1,
|
"allow_import": 1,
|
||||||
"allow_rename": 1,
|
"allow_rename": 1,
|
||||||
"creation": "2017-05-29 21:35:13.136357",
|
"creation": "2017-05-29 21:35:13.136357",
|
||||||
@@ -82,7 +83,7 @@
|
|||||||
"default": "0",
|
"default": "0",
|
||||||
"fieldname": "is_default",
|
"fieldname": "is_default",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"label": "Is the Default Account"
|
"label": "Is Default Account"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"default": "0",
|
"default": "0",
|
||||||
@@ -211,7 +212,8 @@
|
|||||||
"read_only": 1
|
"read_only": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"modified": "2019-10-02 01:34:12.417601",
|
"links": [],
|
||||||
|
"modified": "2020-01-29 20:42:26.458316",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Bank Account",
|
"name": "Bank Account",
|
||||||
|
|||||||
@@ -3,16 +3,16 @@
|
|||||||
|
|
||||||
frappe.ui.form.on("Bank Reconciliation", {
|
frappe.ui.form.on("Bank Reconciliation", {
|
||||||
setup: function(frm) {
|
setup: function(frm) {
|
||||||
frm.add_fetch("bank_account", "account_currency", "account_currency");
|
frm.add_fetch("account", "account_currency", "account_currency");
|
||||||
},
|
},
|
||||||
|
|
||||||
onload: function(frm) {
|
onload: function(frm) {
|
||||||
|
|
||||||
let default_bank_account = frappe.defaults.get_user_default("Company")?
|
let default_bank_account = frappe.defaults.get_user_default("Company")?
|
||||||
locals[":Company"][frappe.defaults.get_user_default("Company")]["default_bank_account"]: "";
|
locals[":Company"][frappe.defaults.get_user_default("Company")]["default_bank_account"]: "";
|
||||||
frm.set_value("bank_account", default_bank_account);
|
frm.set_value("account", default_bank_account);
|
||||||
|
|
||||||
frm.set_query("bank_account", function() {
|
frm.set_query("account", function() {
|
||||||
return {
|
return {
|
||||||
"filters": {
|
"filters": {
|
||||||
"account_type": ["in",["Bank","Cash"]],
|
"account_type": ["in",["Bank","Cash"]],
|
||||||
|
|||||||
@@ -19,10 +19,9 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
"description": "Select account head of the bank where cheque was deposited.",
|
"fetch_from": "bank_account.account",
|
||||||
"fetch_from": "bank_account_no.account",
|
|
||||||
"fetch_if_empty": 1,
|
"fetch_if_empty": 1,
|
||||||
"fieldname": "bank_account",
|
"fieldname": "account",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
@@ -31,7 +30,7 @@
|
|||||||
"in_global_search": 0,
|
"in_global_search": 0,
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"in_standard_filter": 0,
|
"in_standard_filter": 0,
|
||||||
"label": "Bank Account",
|
"label": "Account",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"options": "Account",
|
"options": "Account",
|
||||||
@@ -164,7 +163,6 @@
|
|||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
"print_hide": 0,
|
||||||
"print_hide_if_no_value": 0,
|
"print_hide_if_no_value": 0,
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
@@ -183,8 +181,9 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"description": "Select the Bank Account to reconcile.",
|
||||||
"fetch_if_empty": 0,
|
"fetch_if_empty": 0,
|
||||||
"fieldname": "bank_account_no",
|
"fieldname": "bank_account",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
@@ -193,12 +192,11 @@
|
|||||||
"in_global_search": 0,
|
"in_global_search": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
"in_standard_filter": 0,
|
"in_standard_filter": 0,
|
||||||
"label": "Bank Account No",
|
"label": "Bank Account",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"options": "Bank Account",
|
"options": "Bank Account",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
"print_hide": 0,
|
||||||
"print_hide_if_no_value": 0,
|
"print_hide_if_no_value": 0,
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
@@ -450,7 +448,7 @@
|
|||||||
"istable": 0,
|
"istable": 0,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"menu_index": 0,
|
"menu_index": 0,
|
||||||
"modified": "2019-04-09 18:41:06.110453",
|
"modified": "2020-01-22 00:00:00.000000",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Bank Reconciliation",
|
"name": "Bank Reconciliation",
|
||||||
@@ -483,4 +481,4 @@
|
|||||||
"track_changes": 0,
|
"track_changes": 0,
|
||||||
"track_seen": 0,
|
"track_seen": 0,
|
||||||
"track_views": 0
|
"track_views": 0
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,10 +21,6 @@ class BankReconciliation(Document):
|
|||||||
if not self.include_reconciled_entries:
|
if not self.include_reconciled_entries:
|
||||||
condition = " and (clearance_date is null or clearance_date='0000-00-00')"
|
condition = " and (clearance_date is null or clearance_date='0000-00-00')"
|
||||||
|
|
||||||
account_cond = ""
|
|
||||||
if self.bank_account_no:
|
|
||||||
account_cond = " and t2.bank_account_no = {0}".format(frappe.db.escape(self.bank_account_no))
|
|
||||||
|
|
||||||
journal_entries = frappe.db.sql("""
|
journal_entries = frappe.db.sql("""
|
||||||
select
|
select
|
||||||
"Journal Entry" as payment_document, t1.name as payment_entry,
|
"Journal Entry" as payment_document, t1.name as payment_entry,
|
||||||
@@ -34,15 +30,12 @@ class BankReconciliation(Document):
|
|||||||
from
|
from
|
||||||
`tabJournal Entry` t1, `tabJournal Entry Account` t2
|
`tabJournal Entry` t1, `tabJournal Entry Account` t2
|
||||||
where
|
where
|
||||||
t2.parent = t1.name and t2.account = %s and t1.docstatus=1
|
t2.parent = t1.name and t2.account = %(account)s and t1.docstatus=1
|
||||||
and t1.posting_date >= %s and t1.posting_date <= %s
|
and t1.posting_date >= %(from)s and t1.posting_date <= %(to)s
|
||||||
and ifnull(t1.is_opening, 'No') = 'No' {0} {1}
|
and ifnull(t1.is_opening, 'No') = 'No' %(condition)s
|
||||||
group by t2.account, t1.name
|
group by t2.account, t1.name
|
||||||
order by t1.posting_date ASC, t1.name DESC
|
order by t1.posting_date ASC, t1.name DESC
|
||||||
""".format(condition, account_cond), (self.bank_account, self.from_date, self.to_date), as_dict=1)
|
""", {"condition":condition, "account": self.account, "from": self.from_date, "to": self.to_date}, as_dict=1)
|
||||||
|
|
||||||
if self.bank_account_no:
|
|
||||||
condition = " and bank_account = %(bank_account_no)s"
|
|
||||||
|
|
||||||
payment_entries = frappe.db.sql("""
|
payment_entries = frappe.db.sql("""
|
||||||
select
|
select
|
||||||
@@ -55,12 +48,12 @@ class BankReconciliation(Document):
|
|||||||
from `tabPayment Entry`
|
from `tabPayment Entry`
|
||||||
where
|
where
|
||||||
(paid_from=%(account)s or paid_to=%(account)s) and docstatus=1
|
(paid_from=%(account)s or paid_to=%(account)s) and docstatus=1
|
||||||
and posting_date >= %(from)s and posting_date <= %(to)s {0}
|
and posting_date >= %(from)s and posting_date <= %(to)s
|
||||||
|
and bank_account = %(bank_account)s
|
||||||
order by
|
order by
|
||||||
posting_date ASC, name DESC
|
posting_date ASC, name DESC
|
||||||
""".format(condition),
|
""", {"account": self.account, "from":self.from_date,
|
||||||
{"account":self.bank_account, "from":self.from_date,
|
"to": self.to_date, "bank_account": self.bank_account}, as_dict=1)
|
||||||
"to":self.to_date, "bank_account_no": self.bank_account_no}, as_dict=1)
|
|
||||||
|
|
||||||
pos_entries = []
|
pos_entries = []
|
||||||
if self.include_pos_transactions:
|
if self.include_pos_transactions:
|
||||||
@@ -72,11 +65,10 @@ class BankReconciliation(Document):
|
|||||||
from `tabSales Invoice Payment` sip, `tabSales Invoice` si, `tabAccount` account
|
from `tabSales Invoice Payment` sip, `tabSales Invoice` si, `tabAccount` account
|
||||||
where
|
where
|
||||||
sip.account=%(account)s and si.docstatus=1 and sip.parent = si.name
|
sip.account=%(account)s and si.docstatus=1 and sip.parent = si.name
|
||||||
and account.name = sip.account and si.posting_date >= %(from)s and si.posting_date <= %(to)s {0}
|
and account.name = sip.account and si.posting_date >= %(from)s and si.posting_date <= %(to)s
|
||||||
order by
|
order by
|
||||||
si.posting_date ASC, si.name DESC
|
si.posting_date ASC, si.name DESC
|
||||||
""".format(condition),
|
""", {"account":self.account, "from":self.from_date, "to":self.to_date}, as_dict=1)
|
||||||
{"account":self.bank_account, "from":self.from_date, "to":self.to_date}, as_dict=1)
|
|
||||||
|
|
||||||
entries = sorted(list(payment_entries)+list(journal_entries+list(pos_entries)),
|
entries = sorted(list(payment_entries)+list(journal_entries+list(pos_entries)),
|
||||||
key=lambda k: k['posting_date'] or getdate(nowdate()))
|
key=lambda k: k['posting_date'] or getdate(nowdate()))
|
||||||
|
|||||||
@@ -110,6 +110,15 @@
|
|||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"translatable": 0,
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"depends_on": "eval:doc.docstatus==1",
|
||||||
|
"fieldname": "clearance_date",
|
||||||
|
"fieldtype": "Date",
|
||||||
|
"label": "Clearance Date",
|
||||||
|
"no_copy": 1,
|
||||||
|
"print_hide": 1,
|
||||||
|
"read_only": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"has_web_view": 0,
|
"has_web_view": 0,
|
||||||
@@ -122,7 +131,7 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2018-12-06 10:57:02.635141",
|
"modified": "2020-01-22 00:00:00.000000",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Bank Transaction Payments",
|
"name": "Bank Transaction Payments",
|
||||||
@@ -138,4 +147,4 @@
|
|||||||
"track_changes": 1,
|
"track_changes": 1,
|
||||||
"track_seen": 0,
|
"track_seen": 0,
|
||||||
"track_views": 0
|
"track_views": 0
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -210,10 +210,10 @@ def get_requested_amount(args, budget):
|
|||||||
item_code = args.get('item_code')
|
item_code = args.get('item_code')
|
||||||
condition = get_other_condition(args, budget, 'Material Request')
|
condition = get_other_condition(args, budget, 'Material Request')
|
||||||
|
|
||||||
data = frappe.db.sql(""" select ifnull((sum(mri.stock_qty - mri.ordered_qty) * rate), 0) as amount
|
data = frappe.db.sql(""" select ifnull((sum(child.stock_qty - child.ordered_qty) * rate), 0) as amount
|
||||||
from `tabMaterial Request Item` mri, `tabMaterial Request` mr where mr.name = mri.parent and
|
from `tabMaterial Request Item` child, `tabMaterial Request` parent where parent.name = child.parent and
|
||||||
mri.item_code = %s and mr.docstatus = 1 and mri.stock_qty > mri.ordered_qty and {0} and
|
child.item_code = %s and parent.docstatus = 1 and child.stock_qty > child.ordered_qty and {0} and
|
||||||
mr.material_request_type = 'Purchase' and mr.status != 'Stopped'""".format(condition), item_code, as_list=1)
|
parent.material_request_type = 'Purchase' and parent.status != 'Stopped'""".format(condition), item_code, as_list=1)
|
||||||
|
|
||||||
return data[0][0] if data else 0
|
return data[0][0] if data else 0
|
||||||
|
|
||||||
@@ -221,10 +221,10 @@ def get_ordered_amount(args, budget):
|
|||||||
item_code = args.get('item_code')
|
item_code = args.get('item_code')
|
||||||
condition = get_other_condition(args, budget, 'Purchase Order')
|
condition = get_other_condition(args, budget, 'Purchase Order')
|
||||||
|
|
||||||
data = frappe.db.sql(""" select ifnull(sum(poi.amount - poi.billed_amt), 0) as amount
|
data = frappe.db.sql(""" select ifnull(sum(child.amount - child.billed_amt), 0) as amount
|
||||||
from `tabPurchase Order Item` poi, `tabPurchase Order` po where
|
from `tabPurchase Order Item` child, `tabPurchase Order` parent where
|
||||||
po.name = poi.parent and poi.item_code = %s and po.docstatus = 1 and poi.amount > poi.billed_amt
|
parent.name = child.parent and child.item_code = %s and parent.docstatus = 1 and child.amount > child.billed_amt
|
||||||
and po.status != 'Closed' and {0}""".format(condition), item_code, as_list=1)
|
and parent.status != 'Closed' and {0}""".format(condition), item_code, as_list=1)
|
||||||
|
|
||||||
return data[0][0] if data else 0
|
return data[0][0] if data else 0
|
||||||
|
|
||||||
@@ -233,16 +233,15 @@ def get_other_condition(args, budget, for_doc):
|
|||||||
budget_against_field = frappe.scrub(args.get("budget_against_field"))
|
budget_against_field = frappe.scrub(args.get("budget_against_field"))
|
||||||
|
|
||||||
if budget_against_field and args.get(budget_against_field):
|
if budget_against_field and args.get(budget_against_field):
|
||||||
condition += " and %s = '%s'" %(budget_against_field, args.get(budget_against_field))
|
condition += " and child.%s = '%s'" %(budget_against_field, args.get(budget_against_field))
|
||||||
|
|
||||||
if args.get('fiscal_year'):
|
if args.get('fiscal_year'):
|
||||||
date_field = 'schedule_date' if for_doc == 'Material Request' else 'transaction_date'
|
date_field = 'schedule_date' if for_doc == 'Material Request' else 'transaction_date'
|
||||||
start_date, end_date = frappe.db.get_value('Fiscal Year', args.get('fiscal_year'),
|
start_date, end_date = frappe.db.get_value('Fiscal Year', args.get('fiscal_year'),
|
||||||
['year_start_date', 'year_end_date'])
|
['year_start_date', 'year_end_date'])
|
||||||
|
|
||||||
alias = 'mr' if for_doc == 'Material Request' else 'po'
|
condition += """ and parent.%s
|
||||||
condition += """ and %s.%s
|
between '%s' and '%s' """ %(date_field, start_date, end_date)
|
||||||
between '%s' and '%s' """ %(alias, date_field, start_date, end_date)
|
|
||||||
|
|
||||||
return condition
|
return condition
|
||||||
|
|
||||||
|
|||||||
@@ -96,7 +96,11 @@ def build_forest(data):
|
|||||||
if parent_account == account_name == child:
|
if parent_account == account_name == child:
|
||||||
return [parent_account]
|
return [parent_account]
|
||||||
elif account_name == child:
|
elif account_name == child:
|
||||||
return [child] + return_parent(data, parent_account)
|
parent_account_list = return_parent(data, parent_account)
|
||||||
|
if not parent_account_list:
|
||||||
|
frappe.throw(_("The parent account {0} does not exists")
|
||||||
|
.format(parent_account))
|
||||||
|
return [child] + parent_account_list
|
||||||
|
|
||||||
charts_map, paths = {}, []
|
charts_map, paths = {}, []
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
|
"actions": [],
|
||||||
"allow_copy": 1,
|
"allow_copy": 1,
|
||||||
"allow_import": 1,
|
"allow_import": 1,
|
||||||
"allow_rename": 1,
|
"allow_rename": 1,
|
||||||
@@ -123,7 +124,8 @@
|
|||||||
],
|
],
|
||||||
"icon": "fa fa-money",
|
"icon": "fa fa-money",
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
"modified": "2019-09-16 14:44:17.103548",
|
"links": [],
|
||||||
|
"modified": "2020-01-28 13:50:23.430434",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Cost Center",
|
"name": "Cost Center",
|
||||||
@@ -162,7 +164,6 @@
|
|||||||
"role": "Purchase User"
|
"role": "Purchase User"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"quick_entry": 1,
|
|
||||||
"search_fields": "parent_cost_center, is_group",
|
"search_fields": "parent_cost_center, is_group",
|
||||||
"show_name_in_global_search": 1,
|
"show_name_in_global_search": 1,
|
||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -11,6 +11,7 @@ class ModeofPayment(Document):
|
|||||||
def validate(self):
|
def validate(self):
|
||||||
self.validate_accounts()
|
self.validate_accounts()
|
||||||
self.validate_repeating_companies()
|
self.validate_repeating_companies()
|
||||||
|
self.validate_pos_mode_of_payment()
|
||||||
|
|
||||||
def validate_repeating_companies(self):
|
def validate_repeating_companies(self):
|
||||||
"""Error when Same Company is entered multiple times in accounts"""
|
"""Error when Same Company is entered multiple times in accounts"""
|
||||||
@@ -27,3 +28,15 @@ class ModeofPayment(Document):
|
|||||||
if frappe.db.get_value("Account", entry.default_account, "company") != entry.company:
|
if frappe.db.get_value("Account", entry.default_account, "company") != entry.company:
|
||||||
frappe.throw(_("Account {0} does not match with Company {1} in Mode of Account: {2}")
|
frappe.throw(_("Account {0} does not match with Company {1} in Mode of Account: {2}")
|
||||||
.format(entry.default_account, entry.company, self.name))
|
.format(entry.default_account, entry.company, self.name))
|
||||||
|
|
||||||
|
def validate_pos_mode_of_payment(self):
|
||||||
|
if not self.enabled:
|
||||||
|
pos_profiles = frappe.db.sql("""SELECT sip.parent FROM `tabSales Invoice Payment` sip
|
||||||
|
WHERE sip.parenttype = 'POS Profile' and sip.mode_of_payment = %s""", (self.name))
|
||||||
|
pos_profiles = list(map(lambda x: x[0], pos_profiles))
|
||||||
|
|
||||||
|
if pos_profiles:
|
||||||
|
message = "POS Profile " + frappe.bold(", ".join(pos_profiles)) + " contains \
|
||||||
|
Mode of Payment " + frappe.bold(str(self.name)) + ". Please remove them to disable this mode."
|
||||||
|
frappe.throw(_(message), title="Not Allowed")
|
||||||
|
|
||||||
|
|||||||
@@ -102,7 +102,9 @@ class PaymentEntry(AccountsController):
|
|||||||
|
|
||||||
self.bank = bank_data.bank
|
self.bank = bank_data.bank
|
||||||
self.bank_account_no = bank_data.bank_account_no
|
self.bank_account_no = bank_data.bank_account_no
|
||||||
self.set(field, bank_data.account)
|
|
||||||
|
if not self.get(field):
|
||||||
|
self.set(field, bank_data.account)
|
||||||
|
|
||||||
def validate_allocated_amount(self):
|
def validate_allocated_amount(self):
|
||||||
for d in self.get("references"):
|
for d in self.get("references"):
|
||||||
|
|||||||
@@ -373,6 +373,7 @@ def get_existing_payment_request_amount(ref_dt, ref_dn):
|
|||||||
reference_doctype = %s
|
reference_doctype = %s
|
||||||
and reference_name = %s
|
and reference_name = %s
|
||||||
and docstatus = 1
|
and docstatus = 1
|
||||||
|
and status != 'Paid'
|
||||||
""", (ref_dt, ref_dn))
|
""", (ref_dt, ref_dn))
|
||||||
return flt(existing_payment_request_amount[0][0]) if existing_payment_request_amount else 0
|
return flt(existing_payment_request_amount[0][0]) if existing_payment_request_amount else 0
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
"autoname": "Prompt",
|
"autoname": "Prompt",
|
||||||
"creation": "2013-05-24 12:15:51",
|
"creation": "2013-05-24 12:15:51",
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
|
"engine": "InnoDB",
|
||||||
"field_order": [
|
"field_order": [
|
||||||
"disabled",
|
"disabled",
|
||||||
"section_break_2",
|
"section_break_2",
|
||||||
@@ -50,6 +51,7 @@
|
|||||||
"income_account",
|
"income_account",
|
||||||
"expense_account",
|
"expense_account",
|
||||||
"taxes_and_charges",
|
"taxes_and_charges",
|
||||||
|
"tax_category",
|
||||||
"apply_discount_on",
|
"apply_discount_on",
|
||||||
"accounting_dimensions_section",
|
"accounting_dimensions_section",
|
||||||
"cost_center",
|
"cost_center",
|
||||||
@@ -381,11 +383,17 @@
|
|||||||
{
|
{
|
||||||
"fieldname": "dimension_col_break",
|
"fieldname": "dimension_col_break",
|
||||||
"fieldtype": "Column Break"
|
"fieldtype": "Column Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "tax_category",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": "Tax Category",
|
||||||
|
"options": "Tax Category"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"icon": "icon-cog",
|
"icon": "icon-cog",
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
"modified": "2019-05-25 22:56:30.352693",
|
"modified": "2020-01-24 15:52:03.797701",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "POS Profile",
|
"name": "POS Profile",
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_orde
|
|||||||
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
|
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
|
||||||
from erpnext.stock.get_item_details import get_item_details
|
from erpnext.stock.get_item_details import get_item_details
|
||||||
from frappe import MandatoryError
|
from frappe import MandatoryError
|
||||||
|
from erpnext.stock.doctype.item.test_item import make_item
|
||||||
|
from erpnext.healthcare.doctype.lab_test_template.lab_test_template import make_item_price
|
||||||
|
|
||||||
class TestPricingRule(unittest.TestCase):
|
class TestPricingRule(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
@@ -145,6 +147,52 @@ class TestPricingRule(unittest.TestCase):
|
|||||||
self.assertEquals(details.get("margin_type"), "Percentage")
|
self.assertEquals(details.get("margin_type"), "Percentage")
|
||||||
self.assertEquals(details.get("margin_rate_or_amount"), 10)
|
self.assertEquals(details.get("margin_rate_or_amount"), 10)
|
||||||
|
|
||||||
|
def test_mixed_conditions_for_item_group(self):
|
||||||
|
for item in ["Mixed Cond Item 1", "Mixed Cond Item 2"]:
|
||||||
|
make_item(item, {"item_group": "Products"})
|
||||||
|
make_item_price(item, "_Test Price List", 100)
|
||||||
|
|
||||||
|
test_record = {
|
||||||
|
"doctype": "Pricing Rule",
|
||||||
|
"title": "_Test Pricing Rule for Item Group",
|
||||||
|
"apply_on": "Item Group",
|
||||||
|
"item_groups": [
|
||||||
|
{
|
||||||
|
"item_group": "Products",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"item_group": "Seed",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"selling": 1,
|
||||||
|
"mixed_conditions": 1,
|
||||||
|
"currency": "USD",
|
||||||
|
"rate_or_discount": "Discount Percentage",
|
||||||
|
"discount_percentage": 10,
|
||||||
|
"applicable_for": "Customer Group",
|
||||||
|
"customer_group": "All Customer Groups",
|
||||||
|
"company": "_Test Company"
|
||||||
|
}
|
||||||
|
frappe.get_doc(test_record.copy()).insert()
|
||||||
|
|
||||||
|
args = frappe._dict({
|
||||||
|
"item_code": "Mixed Cond Item 1",
|
||||||
|
"item_group": "Products",
|
||||||
|
"company": "_Test Company",
|
||||||
|
"price_list": "_Test Price List",
|
||||||
|
"currency": "_Test Currency",
|
||||||
|
"doctype": "Sales Order",
|
||||||
|
"conversion_rate": 1,
|
||||||
|
"price_list_currency": "_Test Currency",
|
||||||
|
"plc_conversion_rate": 1,
|
||||||
|
"order_type": "Sales",
|
||||||
|
"customer": "_Test Customer",
|
||||||
|
"customer_group": "_Test Customer Group",
|
||||||
|
"name": None
|
||||||
|
})
|
||||||
|
details = get_item_details(args)
|
||||||
|
self.assertEquals(details.get("discount_percentage"), 10)
|
||||||
|
|
||||||
def test_pricing_rule_for_variants(self):
|
def test_pricing_rule_for_variants(self):
|
||||||
from erpnext.stock.get_item_details import get_item_details
|
from erpnext.stock.get_item_details import get_item_details
|
||||||
from frappe import MandatoryError
|
from frappe import MandatoryError
|
||||||
|
|||||||
@@ -489,7 +489,7 @@ def get_pricing_rule_items(pr_doc):
|
|||||||
|
|
||||||
for d in pr_doc.get(pricing_rule_apply_on):
|
for d in pr_doc.get(pricing_rule_apply_on):
|
||||||
if apply_on == 'item_group':
|
if apply_on == 'item_group':
|
||||||
get_child_item_groups(d.get(apply_on))
|
apply_on_data.extend(get_child_item_groups(d.get(apply_on)))
|
||||||
else:
|
else:
|
||||||
apply_on_data.append(d.get(apply_on))
|
apply_on_data.append(d.get(apply_on))
|
||||||
|
|
||||||
|
|||||||
@@ -167,8 +167,15 @@ erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({
|
|||||||
make_comment_dialog_and_block_invoice: function(){
|
make_comment_dialog_and_block_invoice: function(){
|
||||||
const me = this;
|
const me = this;
|
||||||
|
|
||||||
const title = __('Add Comment');
|
const title = __('Block Invoice');
|
||||||
const fields = [
|
const fields = [
|
||||||
|
{
|
||||||
|
fieldname: 'release_date',
|
||||||
|
read_only: 0,
|
||||||
|
fieldtype:'Date',
|
||||||
|
label: __('Release Date'),
|
||||||
|
default: me.frm.doc.release_date
|
||||||
|
},
|
||||||
{
|
{
|
||||||
fieldname: 'hold_comment',
|
fieldname: 'hold_comment',
|
||||||
read_only: 0,
|
read_only: 0,
|
||||||
@@ -187,7 +194,11 @@ erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({
|
|||||||
const dialog_data = me.dialog.get_values();
|
const dialog_data = me.dialog.get_values();
|
||||||
frappe.call({
|
frappe.call({
|
||||||
'method': 'erpnext.accounts.doctype.purchase_invoice.purchase_invoice.block_invoice',
|
'method': 'erpnext.accounts.doctype.purchase_invoice.purchase_invoice.block_invoice',
|
||||||
'args': {'name': me.frm.doc.name, 'hold_comment': dialog_data.hold_comment},
|
'args': {
|
||||||
|
'name': me.frm.doc.name,
|
||||||
|
'hold_comment': dialog_data.hold_comment,
|
||||||
|
'release_date': dialog_data.release_date
|
||||||
|
},
|
||||||
'callback': (r) => me.frm.reload_doc()
|
'callback': (r) => me.frm.reload_doc()
|
||||||
});
|
});
|
||||||
me.dialog.hide();
|
me.dialog.hide();
|
||||||
|
|||||||
@@ -866,6 +866,7 @@ class PurchaseInvoice(BuyingController):
|
|||||||
# because updating ordered qty in bin depends upon updated ordered qty in PO
|
# because updating ordered qty in bin depends upon updated ordered qty in PO
|
||||||
if self.update_stock == 1:
|
if self.update_stock == 1:
|
||||||
self.update_stock_ledger()
|
self.update_stock_ledger()
|
||||||
|
self.delete_auto_created_batches()
|
||||||
|
|
||||||
self.make_gl_entries_on_cancel()
|
self.make_gl_entries_on_cancel()
|
||||||
self.update_project()
|
self.update_project()
|
||||||
@@ -927,9 +928,10 @@ class PurchaseInvoice(BuyingController):
|
|||||||
def on_recurring(self, reference_doc, auto_repeat_doc):
|
def on_recurring(self, reference_doc, auto_repeat_doc):
|
||||||
self.due_date = None
|
self.due_date = None
|
||||||
|
|
||||||
def block_invoice(self, hold_comment=None):
|
def block_invoice(self, hold_comment=None, release_date=None):
|
||||||
self.db_set('on_hold', 1)
|
self.db_set('on_hold', 1)
|
||||||
self.db_set('hold_comment', cstr(hold_comment))
|
self.db_set('hold_comment', cstr(hold_comment))
|
||||||
|
self.db_set('release_date', release_date)
|
||||||
|
|
||||||
def unblock_invoice(self):
|
def unblock_invoice(self):
|
||||||
self.db_set('on_hold', 0)
|
self.db_set('on_hold', 0)
|
||||||
@@ -1013,10 +1015,10 @@ def unblock_invoice(name):
|
|||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def block_invoice(name, hold_comment):
|
def block_invoice(name, release_date, hold_comment=None):
|
||||||
if frappe.db.exists('Purchase Invoice', name):
|
if frappe.db.exists('Purchase Invoice', name):
|
||||||
pi = frappe.get_doc('Purchase Invoice', name)
|
pi = frappe.get_doc('Purchase Invoice', name)
|
||||||
pi.block_invoice(hold_comment)
|
pi.block_invoice(hold_comment, release_date)
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def make_inter_company_sales_invoice(source_name, target_doc=None):
|
def make_inter_company_sales_invoice(source_name, target_doc=None):
|
||||||
|
|||||||
@@ -152,8 +152,11 @@ def update_multi_mode_option(doc, pos_profile):
|
|||||||
|
|
||||||
|
|
||||||
def get_mode_of_payment(doc):
|
def get_mode_of_payment(doc):
|
||||||
return frappe.db.sql(""" select mpa.default_account, mpa.parent, mp.type as type from `tabMode of Payment Account` mpa, \
|
return frappe.db.sql("""
|
||||||
`tabMode of Payment` mp where mpa.parent = mp.name and mpa.company = %(company)s""", {'company': doc.company}, as_dict=1)
|
select mpa.default_account, mpa.parent, mp.type as type
|
||||||
|
from `tabMode of Payment Account` mpa,`tabMode of Payment` mp
|
||||||
|
where mpa.parent = mp.name and mpa.company = %(company)s and mp.enabled = 1""",
|
||||||
|
{'company': doc.company}, as_dict=1)
|
||||||
|
|
||||||
|
|
||||||
def update_tax_table(doc):
|
def update_tax_table(doc):
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
{
|
{
|
||||||
"actions": [],
|
|
||||||
"allow_import": 1,
|
"allow_import": 1,
|
||||||
"autoname": "naming_series:",
|
"autoname": "naming_series:",
|
||||||
"creation": "2013-05-24 19:29:05",
|
"creation": "2013-05-24 19:29:05",
|
||||||
@@ -373,7 +372,8 @@
|
|||||||
"no_copy": 1,
|
"no_copy": 1,
|
||||||
"options": "Sales Invoice",
|
"options": "Sales Invoice",
|
||||||
"print_hide": 1,
|
"print_hide": 1,
|
||||||
"read_only": 1
|
"read_only": 1,
|
||||||
|
"search_index": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "column_break_21",
|
"fieldname": "column_break_21",
|
||||||
@@ -1568,8 +1568,7 @@
|
|||||||
"icon": "fa fa-file-text",
|
"icon": "fa fa-file-text",
|
||||||
"idx": 181,
|
"idx": 181,
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"links": [],
|
"modified": "2020-02-10 04:57:11.221180",
|
||||||
"modified": "2019-12-30 19:15:59.580414",
|
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Sales Invoice",
|
"name": "Sales Invoice",
|
||||||
|
|||||||
@@ -412,6 +412,9 @@ class SalesInvoice(SellingController):
|
|||||||
|
|
||||||
if pos:
|
if pos:
|
||||||
self.allow_print_before_pay = pos.allow_print_before_pay
|
self.allow_print_before_pay = pos.allow_print_before_pay
|
||||||
|
|
||||||
|
if not for_validate:
|
||||||
|
self.tax_category = pos.get("tax_category")
|
||||||
|
|
||||||
if not for_validate and not self.customer:
|
if not for_validate and not self.customer:
|
||||||
self.customer = pos.customer
|
self.customer = pos.customer
|
||||||
@@ -1232,24 +1235,27 @@ class SalesInvoice(SellingController):
|
|||||||
self.status = 'Draft'
|
self.status = 'Draft'
|
||||||
return
|
return
|
||||||
|
|
||||||
|
precision = self.precision("outstanding_amount")
|
||||||
|
outstanding_amount = flt(self.outstanding_amount, precision)
|
||||||
|
|
||||||
if not status:
|
if not status:
|
||||||
if self.docstatus == 2:
|
if self.docstatus == 2:
|
||||||
status = "Cancelled"
|
status = "Cancelled"
|
||||||
elif self.docstatus == 1:
|
elif self.docstatus == 1:
|
||||||
if flt(self.outstanding_amount) > 0 and getdate(self.due_date) < getdate(nowdate()) and self.is_discounted and self.get_discounting_status()=='Disbursed':
|
if outstanding_amount > 0 and getdate(self.due_date) < getdate(nowdate()) and self.is_discounted and self.get_discounting_status()=='Disbursed':
|
||||||
self.status = "Overdue and Discounted"
|
self.status = "Overdue and Discounted"
|
||||||
elif flt(self.outstanding_amount) > 0 and getdate(self.due_date) < getdate(nowdate()):
|
elif outstanding_amount > 0 and getdate(self.due_date) < getdate(nowdate()):
|
||||||
self.status = "Overdue"
|
self.status = "Overdue"
|
||||||
elif flt(self.outstanding_amount) > 0 and getdate(self.due_date) >= getdate(nowdate()) and self.is_discounted and self.get_discounting_status()=='Disbursed':
|
elif outstanding_amount > 0 and getdate(self.due_date) >= getdate(nowdate()) and self.is_discounted and self.get_discounting_status()=='Disbursed':
|
||||||
self.status = "Unpaid and Discounted"
|
self.status = "Unpaid and Discounted"
|
||||||
elif flt(self.outstanding_amount) > 0 and getdate(self.due_date) >= getdate(nowdate()):
|
elif outstanding_amount > 0 and getdate(self.due_date) >= getdate(nowdate()):
|
||||||
self.status = "Unpaid"
|
self.status = "Unpaid"
|
||||||
#Check if outstanding amount is 0 due to credit note issued against invoice
|
#Check if outstanding amount is 0 due to credit note issued against invoice
|
||||||
elif flt(self.outstanding_amount) <= 0 and self.is_return == 0 and frappe.db.get_value('Sales Invoice', {'is_return': 1, 'return_against': self.name, 'docstatus': 1}):
|
elif outstanding_amount <= 0 and self.is_return == 0 and frappe.db.get_value('Sales Invoice', {'is_return': 1, 'return_against': self.name, 'docstatus': 1}):
|
||||||
self.status = "Credit Note Issued"
|
self.status = "Credit Note Issued"
|
||||||
elif self.is_return == 1:
|
elif self.is_return == 1:
|
||||||
self.status = "Return"
|
self.status = "Return"
|
||||||
elif flt(self.outstanding_amount)<=0:
|
elif outstanding_amount <=0:
|
||||||
self.status = "Paid"
|
self.status = "Paid"
|
||||||
else:
|
else:
|
||||||
self.status = "Submitted"
|
self.status = "Submitted"
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
|
"actions": [],
|
||||||
"autoname": "ACC-SUB-.YYYY.-.#####",
|
"autoname": "ACC-SUB-.YYYY.-.#####",
|
||||||
"creation": "2017-07-18 17:50:43.967266",
|
"creation": "2017-07-18 17:50:43.967266",
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
@@ -155,7 +156,7 @@
|
|||||||
"fieldname": "apply_additional_discount",
|
"fieldname": "apply_additional_discount",
|
||||||
"fieldtype": "Select",
|
"fieldtype": "Select",
|
||||||
"label": "Apply Additional Discount On",
|
"label": "Apply Additional Discount On",
|
||||||
"options": "\nGrand Total\nNet total"
|
"options": "\nGrand Total\nNet Total"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "cb_2",
|
"fieldname": "cb_2",
|
||||||
@@ -196,7 +197,8 @@
|
|||||||
"fieldtype": "Column Break"
|
"fieldtype": "Column Break"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"modified": "2019-07-25 18:45:38.579579",
|
"links": [],
|
||||||
|
"modified": "2020-01-27 14:37:32.845173",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Subscription",
|
"name": "Subscription",
|
||||||
|
|||||||
@@ -280,7 +280,7 @@ class Subscription(Document):
|
|||||||
|
|
||||||
if self.additional_discount_percentage or self.additional_discount_amount:
|
if self.additional_discount_percentage or self.additional_discount_amount:
|
||||||
discount_on = self.apply_additional_discount
|
discount_on = self.apply_additional_discount
|
||||||
invoice.apply_additional_discount = discount_on if discount_on else 'Grand Total'
|
invoice.apply_discount_on = discount_on if discount_on else 'Grand Total'
|
||||||
|
|
||||||
# Subscription period
|
# Subscription period
|
||||||
invoice.from_date = self.current_invoice_start
|
invoice.from_date = self.current_invoice_start
|
||||||
|
|||||||
@@ -57,7 +57,7 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2020-01-15 17:14:28.951793",
|
"modified": "2020-01-15 17:14:28.951793",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Tax Category",
|
"name": "Tax Category",
|
||||||
|
|||||||
@@ -100,6 +100,11 @@ frappe.query_reports["Accounts Payable"] = {
|
|||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"options": "Supplier Group"
|
"options": "Supplier Group"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "group_by_party",
|
||||||
|
"label": __("Group By Supplier"),
|
||||||
|
"fieldtype": "Check"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"fieldname":"based_on_payment_terms",
|
"fieldname":"based_on_payment_terms",
|
||||||
"label": __("Based On Payment Terms"),
|
"label": __("Based On Payment Terms"),
|
||||||
@@ -112,6 +117,16 @@ frappe.query_reports["Accounts Payable"] = {
|
|||||||
"hidden": 1
|
"hidden": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
||||||
|
"formatter": function(value, row, column, data, default_formatter) {
|
||||||
|
value = default_formatter(value, row, column, data);
|
||||||
|
if (data && data.bold) {
|
||||||
|
value = value.bold();
|
||||||
|
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
},
|
||||||
|
|
||||||
onload: function(report) {
|
onload: function(report) {
|
||||||
report.page.add_inner_button(__("Accounts Payable Summary"), function() {
|
report.page.add_inner_button(__("Accounts Payable Summary"), function() {
|
||||||
var filters = report.get_values();
|
var filters = report.get_values();
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ frappe.query_reports["Accounts Receivable"] = {
|
|||||||
frappe.query_report.set_filter_value('payment_terms', value["payment_terms"]);
|
frappe.query_report.set_filter_value('payment_terms', value["payment_terms"]);
|
||||||
});
|
});
|
||||||
|
|
||||||
frappe.db.get_value('Customer Credit Limit', {'parent': customer, 'company': company},
|
frappe.db.get_value('Customer Credit Limit', {'parent': customer, 'company': company},
|
||||||
["credit_limit"], function(value) {
|
["credit_limit"], function(value) {
|
||||||
if (value) {
|
if (value) {
|
||||||
frappe.query_report.set_filter_value('credit_limit', value["credit_limit"]);
|
frappe.query_report.set_filter_value('credit_limit', value["credit_limit"]);
|
||||||
@@ -131,6 +131,11 @@ frappe.query_reports["Accounts Receivable"] = {
|
|||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"options": "Sales Person"
|
"options": "Sales Person"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "group_by_party",
|
||||||
|
"label": __("Group By Customer"),
|
||||||
|
"fieldtype": "Check"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"fieldname":"based_on_payment_terms",
|
"fieldname":"based_on_payment_terms",
|
||||||
"label": __("Based On Payment Terms"),
|
"label": __("Based On Payment Terms"),
|
||||||
@@ -177,6 +182,15 @@ frappe.query_reports["Accounts Receivable"] = {
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
||||||
|
"formatter": function(value, row, column, data, default_formatter) {
|
||||||
|
value = default_formatter(value, row, column, data);
|
||||||
|
if (data && data.bold) {
|
||||||
|
value = value.bold();
|
||||||
|
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
},
|
||||||
|
|
||||||
onload: function(report) {
|
onload: function(report) {
|
||||||
report.page.add_inner_button(__("Accounts Receivable Summary"), function() {
|
report.page.add_inner_button(__("Accounts Receivable Summary"), function() {
|
||||||
var filters = report.get_values();
|
var filters = report.get_values();
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ class ReceivablePayableReport(object):
|
|||||||
self.get_columns()
|
self.get_columns()
|
||||||
self.get_data()
|
self.get_data()
|
||||||
self.get_chart_data()
|
self.get_chart_data()
|
||||||
return self.columns, self.data, None, self.chart
|
return self.columns, self.data, None, self.chart, None, self.skip_total_row
|
||||||
|
|
||||||
def set_defaults(self):
|
def set_defaults(self):
|
||||||
if not self.filters.get("company"):
|
if not self.filters.get("company"):
|
||||||
@@ -57,6 +57,12 @@ class ReceivablePayableReport(object):
|
|||||||
self.party_type = self.filters.party_type
|
self.party_type = self.filters.party_type
|
||||||
self.party_details = {}
|
self.party_details = {}
|
||||||
self.invoices = set()
|
self.invoices = set()
|
||||||
|
self.skip_total_row = 0
|
||||||
|
|
||||||
|
if self.filters.get('group_by_party'):
|
||||||
|
self.previous_party=''
|
||||||
|
self.total_row_map = {}
|
||||||
|
self.skip_total_row = 1
|
||||||
|
|
||||||
def get_data(self):
|
def get_data(self):
|
||||||
self.get_gl_entries()
|
self.get_gl_entries()
|
||||||
@@ -102,6 +108,12 @@ class ReceivablePayableReport(object):
|
|||||||
)
|
)
|
||||||
self.get_invoices(gle)
|
self.get_invoices(gle)
|
||||||
|
|
||||||
|
if self.filters.get('group_by_party'):
|
||||||
|
self.init_subtotal_row(gle.party)
|
||||||
|
|
||||||
|
if self.filters.get('group_by_party'):
|
||||||
|
self.init_subtotal_row('Total')
|
||||||
|
|
||||||
def get_invoices(self, gle):
|
def get_invoices(self, gle):
|
||||||
if gle.voucher_type in ('Sales Invoice', 'Purchase Invoice'):
|
if gle.voucher_type in ('Sales Invoice', 'Purchase Invoice'):
|
||||||
if self.filters.get("sales_person"):
|
if self.filters.get("sales_person"):
|
||||||
@@ -111,6 +123,20 @@ class ReceivablePayableReport(object):
|
|||||||
else:
|
else:
|
||||||
self.invoices.add(gle.voucher_no)
|
self.invoices.add(gle.voucher_no)
|
||||||
|
|
||||||
|
def init_subtotal_row(self, party):
|
||||||
|
if not self.total_row_map.get(party):
|
||||||
|
self.total_row_map.setdefault(party, {
|
||||||
|
'party': party,
|
||||||
|
'bold': 1
|
||||||
|
})
|
||||||
|
|
||||||
|
for field in self.get_currency_fields():
|
||||||
|
self.total_row_map[party][field] = 0.0
|
||||||
|
|
||||||
|
def get_currency_fields(self):
|
||||||
|
return ['invoiced', 'paid', 'credit_note', 'outstanding', 'range1',
|
||||||
|
'range2', 'range3', 'range4', 'range5']
|
||||||
|
|
||||||
def update_voucher_balance(self, gle):
|
def update_voucher_balance(self, gle):
|
||||||
# get the row where this balance needs to be updated
|
# get the row where this balance needs to be updated
|
||||||
# if its a payment, it will return the linked invoice or will be considered as advance
|
# if its a payment, it will return the linked invoice or will be considered as advance
|
||||||
@@ -135,6 +161,18 @@ class ReceivablePayableReport(object):
|
|||||||
# advance / unlinked payment or other adjustment
|
# advance / unlinked payment or other adjustment
|
||||||
row.paid -= gle_balance
|
row.paid -= gle_balance
|
||||||
|
|
||||||
|
def update_sub_total_row(self, row, party):
|
||||||
|
total_row = self.total_row_map.get(party)
|
||||||
|
|
||||||
|
for field in self.get_currency_fields():
|
||||||
|
total_row[field] += row.get(field, 0.0)
|
||||||
|
|
||||||
|
def append_subtotal_row(self, party):
|
||||||
|
sub_total_row = self.total_row_map.get(party)
|
||||||
|
self.data.append(sub_total_row)
|
||||||
|
self.data.append({})
|
||||||
|
self.update_sub_total_row(sub_total_row, 'Total')
|
||||||
|
|
||||||
def get_voucher_balance(self, gle):
|
def get_voucher_balance(self, gle):
|
||||||
if self.filters.get("sales_person"):
|
if self.filters.get("sales_person"):
|
||||||
against_voucher = gle.against_voucher or gle.voucher_no
|
against_voucher = gle.against_voucher or gle.voucher_no
|
||||||
@@ -192,11 +230,22 @@ class ReceivablePayableReport(object):
|
|||||||
else:
|
else:
|
||||||
self.append_row(row)
|
self.append_row(row)
|
||||||
|
|
||||||
|
if self.filters.get('group_by_party'):
|
||||||
|
self.append_subtotal_row(self.previous_party)
|
||||||
|
self.data.append(self.total_row_map.get('Total'))
|
||||||
|
|
||||||
def append_row(self, row):
|
def append_row(self, row):
|
||||||
self.allocate_future_payments(row)
|
self.allocate_future_payments(row)
|
||||||
self.set_invoice_details(row)
|
self.set_invoice_details(row)
|
||||||
self.set_party_details(row)
|
self.set_party_details(row)
|
||||||
self.set_ageing(row)
|
self.set_ageing(row)
|
||||||
|
|
||||||
|
if self.filters.get('group_by_party'):
|
||||||
|
self.update_sub_total_row(row, row.party)
|
||||||
|
if self.previous_party and (self.previous_party != row.party):
|
||||||
|
self.append_subtotal_row(self.previous_party)
|
||||||
|
self.previous_party = row.party
|
||||||
|
|
||||||
self.data.append(row)
|
self.data.append(row)
|
||||||
|
|
||||||
def set_invoice_details(self, row):
|
def set_invoice_details(self, row):
|
||||||
@@ -503,6 +552,7 @@ class ReceivablePayableReport(object):
|
|||||||
# get all the GL entries filtered by the given filters
|
# get all the GL entries filtered by the given filters
|
||||||
|
|
||||||
conditions, values = self.prepare_conditions()
|
conditions, values = self.prepare_conditions()
|
||||||
|
order_by = self.get_order_by_condition()
|
||||||
|
|
||||||
if self.filters.get(scrub(self.party_type)):
|
if self.filters.get(scrub(self.party_type)):
|
||||||
select_fields = "debit_in_account_currency as debit, credit_in_account_currency as credit"
|
select_fields = "debit_in_account_currency as debit, credit_in_account_currency as credit"
|
||||||
@@ -520,9 +570,8 @@ class ReceivablePayableReport(object):
|
|||||||
and party_type=%s
|
and party_type=%s
|
||||||
and (party is not null and party != '')
|
and (party is not null and party != '')
|
||||||
and posting_date <= %s
|
and posting_date <= %s
|
||||||
{1}
|
{1} {2}"""
|
||||||
order by posting_date, party"""
|
.format(select_fields, conditions, order_by), values, as_dict=True)
|
||||||
.format(select_fields, conditions), values, as_dict=True)
|
|
||||||
|
|
||||||
def get_sales_invoices_or_customers_based_on_sales_person(self):
|
def get_sales_invoices_or_customers_based_on_sales_person(self):
|
||||||
if self.filters.get("sales_person"):
|
if self.filters.get("sales_person"):
|
||||||
@@ -557,6 +606,12 @@ class ReceivablePayableReport(object):
|
|||||||
|
|
||||||
return " and ".join(conditions), values
|
return " and ".join(conditions), values
|
||||||
|
|
||||||
|
def get_order_by_condition(self):
|
||||||
|
if self.filters.get('group_by_party'):
|
||||||
|
return "order by party, posting_date"
|
||||||
|
else:
|
||||||
|
return "order by posting_date, party"
|
||||||
|
|
||||||
def add_common_filters(self, conditions, values, party_type_field):
|
def add_common_filters(self, conditions, values, party_type_field):
|
||||||
if self.filters.company:
|
if self.filters.company:
|
||||||
conditions.append("company=%s")
|
conditions.append("company=%s")
|
||||||
@@ -736,11 +791,13 @@ class ReceivablePayableReport(object):
|
|||||||
def get_chart_data(self):
|
def get_chart_data(self):
|
||||||
rows = []
|
rows = []
|
||||||
for row in self.data:
|
for row in self.data:
|
||||||
values = [row.range1, row.range2, row.range3, row.range4, row.range5]
|
row = frappe._dict(row)
|
||||||
precision = cint(frappe.db.get_default("float_precision")) or 2
|
if not cint(row.bold):
|
||||||
rows.append({
|
values = [row.range1, row.range2, row.range3, row.range4, row.range5]
|
||||||
'values': [flt(val, precision) for val in values]
|
precision = cint(frappe.db.get_default("float_precision")) or 2
|
||||||
})
|
rows.append({
|
||||||
|
'values': [flt(val, precision) for val in values]
|
||||||
|
})
|
||||||
|
|
||||||
self.chart = {
|
self.chart = {
|
||||||
"data": {
|
"data": {
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ frappe.require("assets/erpnext/js/financial_statements.js", function() {
|
|||||||
frappe.query_reports["Balance Sheet"]["filters"].push({
|
frappe.query_reports["Balance Sheet"]["filters"].push({
|
||||||
"fieldname": "include_default_book_entries",
|
"fieldname": "include_default_book_entries",
|
||||||
"label": __("Include Default Book Entries"),
|
"label": __("Include Default Book Entries"),
|
||||||
"fieldtype": "Check"
|
"fieldtype": "Check",
|
||||||
|
"default": 1
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -20,7 +20,8 @@ frappe.require("assets/erpnext/js/financial_statements.js", function() {
|
|||||||
{
|
{
|
||||||
"fieldname": "include_default_book_entries",
|
"fieldname": "include_default_book_entries",
|
||||||
"label": __("Include Default Book Entries"),
|
"label": __("Include Default Book Entries"),
|
||||||
"fieldtype": "Check"
|
"fieldtype": "Check",
|
||||||
|
"default": 1
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import frappe
|
import frappe
|
||||||
from frappe import _
|
from frappe import _
|
||||||
from frappe.utils import cint
|
from frappe.utils import cint, cstr
|
||||||
from erpnext.accounts.report.financial_statements import (get_period_list, get_columns, get_data)
|
from erpnext.accounts.report.financial_statements import (get_period_list, get_columns, get_data)
|
||||||
from erpnext.accounts.report.profit_and_loss_statement.profit_and_loss_statement import get_net_profit_loss
|
from erpnext.accounts.report.profit_and_loss_statement.profit_and_loss_statement import get_net_profit_loss
|
||||||
from erpnext.accounts.utils import get_fiscal_year
|
from erpnext.accounts.utils import get_fiscal_year
|
||||||
@@ -129,13 +129,13 @@ def get_account_type_based_gl_data(company, start_date, end_date, account_type,
|
|||||||
cond = ""
|
cond = ""
|
||||||
filters = frappe._dict(filters)
|
filters = frappe._dict(filters)
|
||||||
|
|
||||||
if filters.finance_book:
|
if filters.include_default_book_entries:
|
||||||
cond = " and finance_book = %s" %(frappe.db.escape(filters.finance_book))
|
company_fb = frappe.db.get_value("Company", company, 'default_finance_book')
|
||||||
if filters.include_default_book_entries:
|
cond = """ AND (finance_book in (%s, %s, '') OR finance_book IS NULL)
|
||||||
company_fb = frappe.db.get_value("Company", company, 'default_finance_book')
|
""" %(frappe.db.escape(filters.finance_book), frappe.db.escape(company_fb))
|
||||||
|
else:
|
||||||
|
cond = " AND (finance_book in (%s, '') OR finance_book IS NULL)" %(frappe.db.escape(cstr(filters.finance_book)))
|
||||||
|
|
||||||
cond = """ and finance_book in (%s, %s)
|
|
||||||
""" %(frappe.db.escape(filters.finance_book), frappe.db.escape(company_fb))
|
|
||||||
|
|
||||||
gl_sum = frappe.db.sql_list("""
|
gl_sum = frappe.db.sql_list("""
|
||||||
select sum(credit) - sum(debit)
|
select sum(credit) - sum(debit)
|
||||||
|
|||||||
@@ -58,7 +58,8 @@ frappe.query_reports["Consolidated Financial Statement"] = {
|
|||||||
{
|
{
|
||||||
"fieldname": "include_default_book_entries",
|
"fieldname": "include_default_book_entries",
|
||||||
"label": __("Include Default Book Entries"),
|
"label": __("Include Default Book Entries"),
|
||||||
"fieldtype": "Check"
|
"fieldtype": "Check",
|
||||||
|
"default": 1
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -387,11 +387,10 @@ def get_additional_conditions(from_date, ignore_closing_entries, filters):
|
|||||||
if from_date:
|
if from_date:
|
||||||
additional_conditions.append("gl.posting_date >= %(from_date)s")
|
additional_conditions.append("gl.posting_date >= %(from_date)s")
|
||||||
|
|
||||||
if filters.get("finance_book"):
|
if filters.get("include_default_book_entries"):
|
||||||
if filters.get("include_default_book_entries"):
|
additional_conditions.append("(finance_book in (%(finance_book)s, %(company_fb)s, '') OR finance_book IS NULL)")
|
||||||
additional_conditions.append("finance_book in (%(finance_book)s, %(company_fb)s)")
|
else:
|
||||||
else:
|
additional_conditions.append("(finance_book in (%(finance_book)s, '') OR finance_book IS NULL)")
|
||||||
additional_conditions.append("finance_book in (%(finance_book)s)")
|
|
||||||
|
|
||||||
return " and {}".format(" and ".join(additional_conditions)) if additional_conditions else ""
|
return " and {}".format(" and ".join(additional_conditions)) if additional_conditions else ""
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import frappe, erpnext
|
|||||||
from erpnext.accounts.report.utils import get_currency, convert_to_presentation_currency
|
from erpnext.accounts.report.utils import get_currency, convert_to_presentation_currency
|
||||||
from erpnext.accounts.utils import get_fiscal_year
|
from erpnext.accounts.utils import get_fiscal_year
|
||||||
from frappe import _
|
from frappe import _
|
||||||
from frappe.utils import (flt, getdate, get_first_day, add_months, add_days, formatdate)
|
from frappe.utils import (flt, getdate, get_first_day, add_months, add_days, formatdate, cstr)
|
||||||
|
|
||||||
from six import itervalues
|
from six import itervalues
|
||||||
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions
|
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions
|
||||||
@@ -348,40 +348,42 @@ def set_gl_entries_by_account(
|
|||||||
additional_conditions = get_additional_conditions(from_date, ignore_closing_entries, filters)
|
additional_conditions = get_additional_conditions(from_date, ignore_closing_entries, filters)
|
||||||
|
|
||||||
accounts = frappe.db.sql_list("""select name from `tabAccount`
|
accounts = frappe.db.sql_list("""select name from `tabAccount`
|
||||||
where lft >= %s and rgt <= %s""", (root_lft, root_rgt))
|
where lft >= %s and rgt <= %s and company = %s""", (root_lft, root_rgt, company))
|
||||||
additional_conditions += " and account in ({})"\
|
|
||||||
.format(", ".join([frappe.db.escape(d) for d in accounts]))
|
|
||||||
|
|
||||||
gl_filters = {
|
if accounts:
|
||||||
"company": company,
|
additional_conditions += " and account in ({})"\
|
||||||
"from_date": from_date,
|
.format(", ".join([frappe.db.escape(d) for d in accounts]))
|
||||||
"to_date": to_date,
|
|
||||||
"finance_book": filters.get("finance_book")
|
|
||||||
}
|
|
||||||
|
|
||||||
if filters.get("include_default_book_entries"):
|
gl_filters = {
|
||||||
gl_filters["company_fb"] = frappe.db.get_value("Company",
|
"company": company,
|
||||||
company, 'default_finance_book')
|
"from_date": from_date,
|
||||||
|
"to_date": to_date,
|
||||||
|
"finance_book": cstr(filters.get("finance_book"))
|
||||||
|
}
|
||||||
|
|
||||||
for key, value in filters.items():
|
if filters.get("include_default_book_entries"):
|
||||||
if value:
|
gl_filters["company_fb"] = frappe.db.get_value("Company",
|
||||||
gl_filters.update({
|
company, 'default_finance_book')
|
||||||
key: value
|
|
||||||
})
|
|
||||||
|
|
||||||
gl_entries = frappe.db.sql("""select posting_date, account, debit, credit, is_opening, fiscal_year, debit_in_account_currency, credit_in_account_currency, account_currency from `tabGL Entry`
|
for key, value in filters.items():
|
||||||
where company=%(company)s
|
if value:
|
||||||
{additional_conditions}
|
gl_filters.update({
|
||||||
and posting_date <= %(to_date)s
|
key: value
|
||||||
order by account, posting_date""".format(additional_conditions=additional_conditions), gl_filters, as_dict=True) #nosec
|
})
|
||||||
|
|
||||||
if filters and filters.get('presentation_currency'):
|
gl_entries = frappe.db.sql("""select posting_date, account, debit, credit, is_opening, fiscal_year, debit_in_account_currency, credit_in_account_currency, account_currency from `tabGL Entry`
|
||||||
convert_to_presentation_currency(gl_entries, get_currency(filters))
|
where company=%(company)s
|
||||||
|
{additional_conditions}
|
||||||
|
and posting_date <= %(to_date)s
|
||||||
|
order by account, posting_date""".format(additional_conditions=additional_conditions), gl_filters, as_dict=True) #nosec
|
||||||
|
|
||||||
for entry in gl_entries:
|
if filters and filters.get('presentation_currency'):
|
||||||
gl_entries_by_account.setdefault(entry.account, []).append(entry)
|
convert_to_presentation_currency(gl_entries, get_currency(filters))
|
||||||
|
|
||||||
return gl_entries_by_account
|
for entry in gl_entries:
|
||||||
|
gl_entries_by_account.setdefault(entry.account, []).append(entry)
|
||||||
|
|
||||||
|
return gl_entries_by_account
|
||||||
|
|
||||||
|
|
||||||
def get_additional_conditions(from_date, ignore_closing_entries, filters):
|
def get_additional_conditions(from_date, ignore_closing_entries, filters):
|
||||||
@@ -406,12 +408,11 @@ def get_additional_conditions(from_date, ignore_closing_entries, filters):
|
|||||||
filters.cost_center = get_cost_centers_with_children(filters.cost_center)
|
filters.cost_center = get_cost_centers_with_children(filters.cost_center)
|
||||||
additional_conditions.append("cost_center in %(cost_center)s")
|
additional_conditions.append("cost_center in %(cost_center)s")
|
||||||
|
|
||||||
if filters.get("finance_book"):
|
if filters.get("include_default_book_entries"):
|
||||||
if filters.get("include_default_book_entries"):
|
additional_conditions.append("(finance_book in (%(finance_book)s, %(company_fb)s, '') OR finance_book IS NULL)")
|
||||||
additional_conditions.append("finance_book in (%(finance_book)s, %(company_fb)s)")
|
else:
|
||||||
else:
|
additional_conditions.append("(finance_book in (%(finance_book)s, '') OR finance_book IS NULL)")
|
||||||
additional_conditions.append("finance_book in (%(finance_book)s)")
|
|
||||||
|
|
||||||
if accounting_dimensions:
|
if accounting_dimensions:
|
||||||
for dimension in accounting_dimensions:
|
for dimension in accounting_dimensions:
|
||||||
if filters.get(dimension):
|
if filters.get(dimension):
|
||||||
|
|||||||
@@ -154,7 +154,8 @@ frappe.query_reports["General Ledger"] = {
|
|||||||
{
|
{
|
||||||
"fieldname": "include_default_book_entries",
|
"fieldname": "include_default_book_entries",
|
||||||
"label": __("Include Default Book Entries"),
|
"label": __("Include Default Book Entries"),
|
||||||
"fieldtype": "Check"
|
"fieldtype": "Check",
|
||||||
|
"default": 1
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -119,7 +119,7 @@ def get_gl_entries(filters):
|
|||||||
select_fields = """, debit, credit, debit_in_account_currency,
|
select_fields = """, debit, credit, debit_in_account_currency,
|
||||||
credit_in_account_currency """
|
credit_in_account_currency """
|
||||||
|
|
||||||
order_by_statement = "order by posting_date, account"
|
order_by_statement = "order by posting_date, account, creation"
|
||||||
|
|
||||||
if filters.get("group_by") == _("Group by Voucher"):
|
if filters.get("group_by") == _("Group by Voucher"):
|
||||||
order_by_statement = "order by posting_date, voucher_type, voucher_no"
|
order_by_statement = "order by posting_date, voucher_type, voucher_no"
|
||||||
@@ -184,7 +184,7 @@ def get_conditions(filters):
|
|||||||
|
|
||||||
if filters.get("finance_book"):
|
if filters.get("finance_book"):
|
||||||
if filters.get("include_default_book_entries"):
|
if filters.get("include_default_book_entries"):
|
||||||
conditions.append("finance_book in (%(finance_book)s, %(company_fb)s)")
|
conditions.append("(finance_book in (%(finance_book)s, %(company_fb)s, '') OR finance_book IS NULL)")
|
||||||
else:
|
else:
|
||||||
conditions.append("finance_book in (%(finance_book)s)")
|
conditions.append("finance_book in (%(finance_book)s)")
|
||||||
|
|
||||||
|
|||||||
@@ -34,6 +34,20 @@ frappe.query_reports["Item-wise Purchase Register"] = {
|
|||||||
"label": __("Mode of Payment"),
|
"label": __("Mode of Payment"),
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"options": "Mode of Payment"
|
"options": "Mode of Payment"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": __("Group By"),
|
||||||
|
"fieldname": "group_by",
|
||||||
|
"fieldtype": "Select",
|
||||||
|
"options": ["Supplier", "Item Group", "Item", "Invoice"]
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"formatter": function(value, row, column, data, default_formatter) {
|
||||||
|
value = default_formatter(value, row, column, data);
|
||||||
|
if (data && data.bold) {
|
||||||
|
value = value.bold();
|
||||||
|
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,9 @@ from __future__ import unicode_literals
|
|||||||
import frappe, erpnext
|
import frappe, erpnext
|
||||||
from frappe import _
|
from frappe import _
|
||||||
from frappe.utils import flt
|
from frappe.utils import flt
|
||||||
from erpnext.accounts.report.item_wise_sales_register.item_wise_sales_register import get_tax_accounts
|
from erpnext.accounts.report.item_wise_sales_register.item_wise_sales_register import (get_tax_accounts,
|
||||||
|
get_grand_total, add_total_row, get_display_value, get_group_by_and_display_fields, add_sub_total_row,
|
||||||
|
get_group_by_conditions)
|
||||||
|
|
||||||
def execute(filters=None):
|
def execute(filters=None):
|
||||||
return _execute(filters)
|
return _execute(filters)
|
||||||
@@ -13,7 +15,7 @@ def execute(filters=None):
|
|||||||
def _execute(filters=None, additional_table_columns=None, additional_query_columns=None):
|
def _execute(filters=None, additional_table_columns=None, additional_query_columns=None):
|
||||||
if not filters: filters = {}
|
if not filters: filters = {}
|
||||||
filters.update({"from_date": filters.get("date_range")[0], "to_date": filters.get("date_range")[1]})
|
filters.update({"from_date": filters.get("date_range")[0], "to_date": filters.get("date_range")[1]})
|
||||||
columns = get_columns(additional_table_columns)
|
columns = get_columns(additional_table_columns, filters)
|
||||||
|
|
||||||
company_currency = erpnext.get_company_currency(filters.company)
|
company_currency = erpnext.get_company_currency(filters.company)
|
||||||
|
|
||||||
@@ -23,16 +25,16 @@ def _execute(filters=None, additional_table_columns=None, additional_query_colum
|
|||||||
itemised_tax, tax_columns = get_tax_accounts(item_list, columns, company_currency,
|
itemised_tax, tax_columns = get_tax_accounts(item_list, columns, company_currency,
|
||||||
doctype="Purchase Invoice", tax_doctype="Purchase Taxes and Charges")
|
doctype="Purchase Invoice", tax_doctype="Purchase Taxes and Charges")
|
||||||
|
|
||||||
columns.append({
|
|
||||||
"fieldname": "currency",
|
|
||||||
"label": _("Currency"),
|
|
||||||
"fieldtype": "Data",
|
|
||||||
"width": 80
|
|
||||||
})
|
|
||||||
|
|
||||||
po_pr_map = get_purchase_receipts_against_purchase_order(item_list)
|
po_pr_map = get_purchase_receipts_against_purchase_order(item_list)
|
||||||
|
|
||||||
data = []
|
data = []
|
||||||
|
total_row_map = {}
|
||||||
|
skip_total_row = 0
|
||||||
|
prev_group_by_value = ''
|
||||||
|
|
||||||
|
if filters.get('group_by'):
|
||||||
|
grand_total = get_grand_total(filters, 'Purchase Invoice')
|
||||||
|
|
||||||
for d in item_list:
|
for d in item_list:
|
||||||
if not d.stock_qty:
|
if not d.stock_qty:
|
||||||
continue
|
continue
|
||||||
@@ -44,51 +46,243 @@ def _execute(filters=None, additional_table_columns=None, additional_query_colum
|
|||||||
purchase_receipt = ", ".join(po_pr_map.get(d.po_detail, []))
|
purchase_receipt = ", ".join(po_pr_map.get(d.po_detail, []))
|
||||||
|
|
||||||
expense_account = d.expense_account or aii_account_map.get(d.company)
|
expense_account = d.expense_account or aii_account_map.get(d.company)
|
||||||
row = [d.item_code, d.item_name, d.item_group, d.description, d.parent, d.posting_date, d.supplier,
|
|
||||||
d.supplier_name]
|
row = {
|
||||||
|
'item_code': d.item_code,
|
||||||
|
'item_name': d.item_name,
|
||||||
|
'item_group': d.item_group,
|
||||||
|
'description': d.description,
|
||||||
|
'invoice': d.parent,
|
||||||
|
'posting_date': d.posting_date,
|
||||||
|
'customer': d.supplier,
|
||||||
|
'customer_name': d.supplier_name
|
||||||
|
}
|
||||||
|
|
||||||
if additional_query_columns:
|
if additional_query_columns:
|
||||||
for col in additional_query_columns:
|
for col in additional_query_columns:
|
||||||
row.append(d.get(col))
|
row.update({
|
||||||
|
col: d.get(col)
|
||||||
|
})
|
||||||
|
|
||||||
row += [
|
row.update({
|
||||||
d.credit_to, d.mode_of_payment, d.project, d.company, d.purchase_order,
|
'credit_to': d.credit_to,
|
||||||
purchase_receipt, expense_account, d.stock_qty, d.stock_uom, d.base_net_amount / d.stock_qty, d.base_net_amount
|
'mode_of_payment': d.mode_of_payment,
|
||||||
]
|
'project': d.project,
|
||||||
|
'company': d.company,
|
||||||
|
'purchase_order': d.purchase_order,
|
||||||
|
'purchase_receipt': d.purchase_receipt,
|
||||||
|
'expense_account': expense_account,
|
||||||
|
'stock_qty': d.stock_qty,
|
||||||
|
'stock_uom': d.stock_uom,
|
||||||
|
'rate': d.base_net_amount / d.stock_qty,
|
||||||
|
'amount': d.base_net_amount
|
||||||
|
})
|
||||||
|
|
||||||
total_tax = 0
|
total_tax = 0
|
||||||
for tax in tax_columns:
|
for tax in tax_columns:
|
||||||
item_tax = itemised_tax.get(d.name, {}).get(tax, {})
|
item_tax = itemised_tax.get(d.name, {}).get(tax, {})
|
||||||
row += [item_tax.get("tax_rate", 0), item_tax.get("tax_amount", 0)]
|
row.update({
|
||||||
|
frappe.scrub(tax + ' Rate'): item_tax.get("tax_rate", 0),
|
||||||
|
frappe.scrub(tax + ' Amount'): item_tax.get("tax_amount", 0),
|
||||||
|
})
|
||||||
total_tax += flt(item_tax.get("tax_amount"))
|
total_tax += flt(item_tax.get("tax_amount"))
|
||||||
|
|
||||||
row += [total_tax, d.base_net_amount + total_tax, company_currency]
|
row.update({
|
||||||
|
'total_tax': total_tax,
|
||||||
|
'total': d.base_net_amount + total_tax,
|
||||||
|
'currency': company_currency
|
||||||
|
})
|
||||||
|
|
||||||
|
if filters.get('group_by'):
|
||||||
|
row.update({'percent_gt': flt(row['total']/grand_total) * 100})
|
||||||
|
group_by_field, subtotal_display_field = get_group_by_and_display_fields(filters)
|
||||||
|
data, prev_group_by_value = add_total_row(data, filters, prev_group_by_value, d, total_row_map,
|
||||||
|
group_by_field, subtotal_display_field, grand_total, tax_columns)
|
||||||
|
add_sub_total_row(row, total_row_map, d.get(group_by_field, ''), tax_columns)
|
||||||
|
|
||||||
data.append(row)
|
data.append(row)
|
||||||
|
|
||||||
return columns, data
|
if filters.get('group_by'):
|
||||||
|
total_row = total_row_map.get(prev_group_by_value or d.get('item_name'))
|
||||||
|
total_row['percent_gt'] = flt(total_row['total']/grand_total * 100)
|
||||||
|
data.append(total_row)
|
||||||
|
data.append({})
|
||||||
|
add_sub_total_row(total_row, total_row_map, 'total_row', tax_columns)
|
||||||
|
data.append(total_row_map.get('total_row'))
|
||||||
|
skip_total_row = 1
|
||||||
|
|
||||||
|
return columns, data, None, None, None, skip_total_row
|
||||||
|
|
||||||
|
|
||||||
def get_columns(additional_table_columns):
|
def get_columns(additional_table_columns, filters):
|
||||||
columns = [
|
|
||||||
_("Item Code") + ":Link/Item:120", _("Item Name") + "::120",
|
columns = []
|
||||||
_("Item Group") + ":Link/Item Group:100", "Description::150", _("Invoice") + ":Link/Purchase Invoice:120",
|
|
||||||
_("Posting Date") + ":Date:80", _("Supplier") + ":Link/Supplier:120",
|
if filters.get('group_by') != ('Item'):
|
||||||
"Supplier Name::120"
|
columns.extend(
|
||||||
]
|
[
|
||||||
|
{
|
||||||
|
'label': _('Item Code'),
|
||||||
|
'fieldname': 'item_code',
|
||||||
|
'fieldtype': 'Link',
|
||||||
|
'options': 'Item',
|
||||||
|
'width': 120
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': _('Item Name'),
|
||||||
|
'fieldname': 'item_name',
|
||||||
|
'fieldtype': 'Data',
|
||||||
|
'width': 120
|
||||||
|
}
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
if filters.get('group_by') not in ('Item', 'Item Group'):
|
||||||
|
columns.extend([
|
||||||
|
{
|
||||||
|
'label': _('Item Group'),
|
||||||
|
'fieldname': 'item_group',
|
||||||
|
'fieldtype': 'Link',
|
||||||
|
'options': 'Item Group',
|
||||||
|
'width': 120
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
columns.extend([
|
||||||
|
{
|
||||||
|
'label': _('Description'),
|
||||||
|
'fieldname': 'description',
|
||||||
|
'fieldtype': 'Data',
|
||||||
|
'width': 150
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': _('Invoice'),
|
||||||
|
'fieldname': 'invoice',
|
||||||
|
'fieldtype': 'Link',
|
||||||
|
'options': 'Purchase Invoice',
|
||||||
|
'width': 120
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': _('Posting Date'),
|
||||||
|
'fieldname': 'posting_date',
|
||||||
|
'fieldtype': 'Date',
|
||||||
|
'width': 120
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
if filters.get('group_by') != 'Supplier':
|
||||||
|
columns.extend([
|
||||||
|
{
|
||||||
|
'label': _('Supplier'),
|
||||||
|
'fieldname': 'supplier',
|
||||||
|
'fieldtype': 'Link',
|
||||||
|
'options': 'Supplier',
|
||||||
|
'width': 120
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': _('Supplier Name'),
|
||||||
|
'fieldname': 'supplier_name',
|
||||||
|
'fieldtype': 'Data',
|
||||||
|
'width': 120
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
if additional_table_columns:
|
if additional_table_columns:
|
||||||
columns += additional_table_columns
|
columns += additional_table_columns
|
||||||
|
|
||||||
columns += [
|
columns += [
|
||||||
"Payable Account:Link/Account:120",
|
{
|
||||||
_("Mode of Payment") + ":Link/Mode of Payment:80", _("Project") + ":Link/Project:80",
|
'label': _('Payable Account'),
|
||||||
_("Company") + ":Link/Company:100", _("Purchase Order") + ":Link/Purchase Order:100",
|
'fieldname': 'credit_to',
|
||||||
_("Purchase Receipt") + ":Link/Purchase Receipt:100", _("Expense Account") + ":Link/Account:140",
|
'fieldtype': 'Link',
|
||||||
_("Stock Qty") + ":Float:120", _("Stock UOM") + "::100",
|
'options': 'Account',
|
||||||
_("Rate") + ":Currency/currency:120", _("Amount") + ":Currency/currency:120"
|
'width': 80
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': _('Mode Of Payment'),
|
||||||
|
'fieldname': 'mode_of_payment',
|
||||||
|
'fieldtype': 'Data',
|
||||||
|
'width': 120
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': _('Project'),
|
||||||
|
'fieldname': 'project',
|
||||||
|
'fieldtype': 'Link',
|
||||||
|
'options': 'Project',
|
||||||
|
'width': 80
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': _('Company'),
|
||||||
|
'fieldname': 'company',
|
||||||
|
'fieldtype': 'Link',
|
||||||
|
'options': 'Company',
|
||||||
|
'width': 80
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': _('Purchase Order'),
|
||||||
|
'fieldname': 'purchase_order',
|
||||||
|
'fieldtype': 'Link',
|
||||||
|
'options': 'Purchase Order',
|
||||||
|
'width': 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': _("Purchase Receipt"),
|
||||||
|
'fieldname': 'Purchase Receipt',
|
||||||
|
'fieldtype': 'Link',
|
||||||
|
'options': 'Purchase Receipt',
|
||||||
|
'width': 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': _('Expense Account'),
|
||||||
|
'fieldname': 'expense_account',
|
||||||
|
'fieldtype': 'Link',
|
||||||
|
'options': 'Account',
|
||||||
|
'width': 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': _('Stock Qty'),
|
||||||
|
'fieldname': 'stock_qty',
|
||||||
|
'fieldtype': 'Float',
|
||||||
|
'width': 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': _('Stock UOM'),
|
||||||
|
'fieldname': 'stock_uom',
|
||||||
|
'fieldtype': 'Link',
|
||||||
|
'options': 'UOM',
|
||||||
|
'width': 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': _('Rate'),
|
||||||
|
'fieldname': 'rate',
|
||||||
|
'fieldtype': 'Float',
|
||||||
|
'options': 'currency',
|
||||||
|
'width': 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': _('Amount'),
|
||||||
|
'fieldname': 'amount',
|
||||||
|
'fieldtype': 'Currency',
|
||||||
|
'options': 'currency',
|
||||||
|
'width': 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'fieldname': 'currency',
|
||||||
|
'label': _('Currency'),
|
||||||
|
'fieldtype': 'Currency',
|
||||||
|
'width': 80,
|
||||||
|
'hidden': 1
|
||||||
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
if filters.get('group_by'):
|
||||||
|
columns.append({
|
||||||
|
'label': _('% Of Grand Total'),
|
||||||
|
'fieldname': 'percent_gt',
|
||||||
|
'fieldtype': 'Float',
|
||||||
|
'width': 80
|
||||||
|
})
|
||||||
|
|
||||||
return columns
|
return columns
|
||||||
|
|
||||||
def get_conditions(filters):
|
def get_conditions(filters):
|
||||||
@@ -103,6 +297,11 @@ def get_conditions(filters):
|
|||||||
if filters.get(opts[0]):
|
if filters.get(opts[0]):
|
||||||
conditions += opts[1]
|
conditions += opts[1]
|
||||||
|
|
||||||
|
if not filters.get("group_by"):
|
||||||
|
conditions += "ORDER BY `tabPurchase Invoice`.posting_date desc, `tabPurchase Invoice Item`.item_code desc"
|
||||||
|
else:
|
||||||
|
conditions += get_group_by_conditions(filters, 'Purchase Invoice')
|
||||||
|
|
||||||
return conditions
|
return conditions
|
||||||
|
|
||||||
def get_items(filters, additional_query_columns):
|
def get_items(filters, additional_query_columns):
|
||||||
@@ -129,7 +328,6 @@ def get_items(filters, additional_query_columns):
|
|||||||
from `tabPurchase Invoice`, `tabPurchase Invoice Item`
|
from `tabPurchase Invoice`, `tabPurchase Invoice Item`
|
||||||
where `tabPurchase Invoice`.name = `tabPurchase Invoice Item`.`parent` and
|
where `tabPurchase Invoice`.name = `tabPurchase Invoice Item`.`parent` and
|
||||||
`tabPurchase Invoice`.docstatus = 1 %s %s
|
`tabPurchase Invoice`.docstatus = 1 %s %s
|
||||||
order by `tabPurchase Invoice`.posting_date desc, `tabPurchase Invoice Item`.item_code desc
|
|
||||||
""".format(additional_query_columns) % (conditions, match_conditions), filters, as_dict=1)
|
""".format(additional_query_columns) % (conditions, match_conditions), filters, as_dict=1)
|
||||||
|
|
||||||
def get_aii_accounts():
|
def get_aii_accounts():
|
||||||
|
|||||||
@@ -4,48 +4,62 @@
|
|||||||
frappe.query_reports["Item-wise Sales Register"] = {
|
frappe.query_reports["Item-wise Sales Register"] = {
|
||||||
"filters": [
|
"filters": [
|
||||||
{
|
{
|
||||||
"fieldname":"date_range",
|
"fieldname": "date_range",
|
||||||
"label": __("Date Range"),
|
"label": __("Date Range"),
|
||||||
"fieldtype": "DateRange",
|
"fieldtype": "DateRange",
|
||||||
"default": [frappe.datetime.add_months(frappe.datetime.get_today(),-1), frappe.datetime.get_today()],
|
"default": [frappe.datetime.add_months(frappe.datetime.get_today(),-1), frappe.datetime.get_today()],
|
||||||
"reqd": 1
|
"reqd": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname":"customer",
|
"fieldname": "customer",
|
||||||
"label": __("Customer"),
|
"label": __("Customer"),
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"options": "Customer"
|
"options": "Customer"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname":"company",
|
"fieldname": "company",
|
||||||
"label": __("Company"),
|
"label": __("Company"),
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"options": "Company",
|
"options": "Company",
|
||||||
"default": frappe.defaults.get_user_default("Company")
|
"default": frappe.defaults.get_user_default("Company")
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname":"mode_of_payment",
|
"fieldname": "mode_of_payment",
|
||||||
"label": __("Mode of Payment"),
|
"label": __("Mode of Payment"),
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"options": "Mode of Payment"
|
"options": "Mode of Payment"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname":"warehouse",
|
"fieldname": "warehouse",
|
||||||
"label": __("Warehouse"),
|
"label": __("Warehouse"),
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"options": "Warehouse"
|
"options": "Warehouse"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname":"brand",
|
"fieldname": "brand",
|
||||||
"label": __("Brand"),
|
"label": __("Brand"),
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"options": "Brand"
|
"options": "Brand"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname":"item_group",
|
"fieldname": "item_group",
|
||||||
"label": __("Item Group"),
|
"label": __("Item Group"),
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"options": "Item Group"
|
"options": "Item Group"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": __("Group By"),
|
||||||
|
"fieldname": "group_by",
|
||||||
|
"fieldtype": "Select",
|
||||||
|
"options": ["Customer Group", "Customer", "Item Group", "Item", "Territory", "Invoice"]
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"formatter": function(value, row, column, data, default_formatter) {
|
||||||
|
value = default_formatter(value, row, column, data);
|
||||||
|
if (data && data.bold) {
|
||||||
|
value = value.bold();
|
||||||
|
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import frappe, erpnext
|
import frappe, erpnext
|
||||||
from frappe import _
|
from frappe import _
|
||||||
from frappe.utils import flt
|
from frappe.utils import flt, cstr
|
||||||
from frappe.model.meta import get_field_precision
|
from frappe.model.meta import get_field_precision
|
||||||
from frappe.utils.xlsxutils import handle_html
|
from frappe.utils.xlsxutils import handle_html
|
||||||
from erpnext.accounts.report.sales_register.sales_register import get_mode_of_payments
|
from erpnext.accounts.report.sales_register.sales_register import get_mode_of_payments
|
||||||
@@ -15,23 +15,25 @@ def execute(filters=None):
|
|||||||
def _execute(filters=None, additional_table_columns=None, additional_query_columns=None):
|
def _execute(filters=None, additional_table_columns=None, additional_query_columns=None):
|
||||||
if not filters: filters = {}
|
if not filters: filters = {}
|
||||||
filters.update({"from_date": filters.get("date_range") and filters.get("date_range")[0], "to_date": filters.get("date_range") and filters.get("date_range")[1]})
|
filters.update({"from_date": filters.get("date_range") and filters.get("date_range")[0], "to_date": filters.get("date_range") and filters.get("date_range")[1]})
|
||||||
columns = get_columns(additional_table_columns)
|
columns = get_columns(additional_table_columns, filters)
|
||||||
|
|
||||||
company_currency = frappe.get_cached_value('Company', filters.get("company"), "default_currency")
|
company_currency = frappe.get_cached_value('Company', filters.get("company"), "default_currency")
|
||||||
|
|
||||||
item_list = get_items(filters, additional_query_columns)
|
item_list = get_items(filters, additional_query_columns)
|
||||||
if item_list:
|
if item_list:
|
||||||
itemised_tax, tax_columns = get_tax_accounts(item_list, columns, company_currency)
|
itemised_tax, tax_columns = get_tax_accounts(item_list, columns, company_currency)
|
||||||
columns.append({
|
|
||||||
"fieldname": "currency",
|
|
||||||
"label": _("Currency"),
|
|
||||||
"fieldtype": "Data",
|
|
||||||
"width": 80
|
|
||||||
})
|
|
||||||
mode_of_payments = get_mode_of_payments(set([d.parent for d in item_list]))
|
mode_of_payments = get_mode_of_payments(set([d.parent for d in item_list]))
|
||||||
so_dn_map = get_delivery_notes_against_sales_order(item_list)
|
so_dn_map = get_delivery_notes_against_sales_order(item_list)
|
||||||
|
|
||||||
data = []
|
data = []
|
||||||
|
total_row_map = {}
|
||||||
|
skip_total_row = 0
|
||||||
|
prev_group_by_value = ''
|
||||||
|
|
||||||
|
if filters.get('group_by'):
|
||||||
|
grand_total = get_grand_total(filters, 'Sales Invoice')
|
||||||
|
|
||||||
for d in item_list:
|
for d in item_list:
|
||||||
delivery_note = None
|
delivery_note = None
|
||||||
if d.delivery_note:
|
if d.delivery_note:
|
||||||
@@ -42,57 +44,285 @@ def _execute(filters=None, additional_table_columns=None, additional_query_colum
|
|||||||
if not delivery_note and d.update_stock:
|
if not delivery_note and d.update_stock:
|
||||||
delivery_note = d.parent
|
delivery_note = d.parent
|
||||||
|
|
||||||
row = [d.item_code, d.item_name, d.item_group, d.description, d.parent, d.posting_date, d.customer, d.customer_name]
|
row = {
|
||||||
|
'item_code': d.item_code,
|
||||||
|
'item_name': d.item_name,
|
||||||
|
'item_group': d.item_group,
|
||||||
|
'description': d.description,
|
||||||
|
'invoice': d.parent,
|
||||||
|
'posting_date': d.posting_date,
|
||||||
|
'customer': d.customer,
|
||||||
|
'customer_name': d.customer_name,
|
||||||
|
'customer_group': d.customer_group,
|
||||||
|
}
|
||||||
|
|
||||||
if additional_query_columns:
|
if additional_query_columns:
|
||||||
for col in additional_query_columns:
|
for col in additional_query_columns:
|
||||||
row.append(d.get(col))
|
row.update({
|
||||||
|
col: d.get(col)
|
||||||
|
})
|
||||||
|
|
||||||
row += [
|
row.update({
|
||||||
d.customer_group, d.debit_to, ", ".join(mode_of_payments.get(d.parent, [])),
|
'debit_to': d.debit_to,
|
||||||
d.territory, d.project, d.company, d.sales_order,
|
'mode_of_payment': ", ".join(mode_of_payments.get(d.parent, [])),
|
||||||
delivery_note, d.income_account, d.cost_center, d.stock_qty, d.stock_uom
|
'territory': d.territory,
|
||||||
]
|
'project': d.project,
|
||||||
|
'company': d.company,
|
||||||
|
'sales_order': d.sales_order,
|
||||||
|
'delivery_note': d.delivery_note,
|
||||||
|
'income_account': d.income_account,
|
||||||
|
'cost_center': d.cost_center,
|
||||||
|
'stock_qty': d.stock_qty,
|
||||||
|
'stock_uom': d.stock_uom
|
||||||
|
})
|
||||||
|
|
||||||
if d.stock_uom != d.uom and d.stock_qty:
|
if d.stock_uom != d.uom and d.stock_qty:
|
||||||
row += [(d.base_net_rate * d.qty)/d.stock_qty, d.base_net_amount]
|
row.update({
|
||||||
|
'rate': (d.base_net_rate * d.qty)/d.stock_qty,
|
||||||
|
'amount': d.base_net_amount
|
||||||
|
})
|
||||||
else:
|
else:
|
||||||
row += [d.base_net_rate, d.base_net_amount]
|
row.update({
|
||||||
|
'rate': d.base_net_rate,
|
||||||
|
'amount': d.base_net_amount
|
||||||
|
})
|
||||||
|
|
||||||
total_tax = 0
|
total_tax = 0
|
||||||
for tax in tax_columns:
|
for tax in tax_columns:
|
||||||
item_tax = itemised_tax.get(d.name, {}).get(tax, {})
|
item_tax = itemised_tax.get(d.name, {}).get(tax, {})
|
||||||
row += [item_tax.get("tax_rate", 0), item_tax.get("tax_amount", 0)]
|
row.update({
|
||||||
|
frappe.scrub(tax + ' Rate'): item_tax.get("tax_rate", 0),
|
||||||
|
frappe.scrub(tax + ' Amount'): item_tax.get("tax_amount", 0),
|
||||||
|
})
|
||||||
total_tax += flt(item_tax.get("tax_amount"))
|
total_tax += flt(item_tax.get("tax_amount"))
|
||||||
|
|
||||||
row += [total_tax, d.base_net_amount + total_tax, company_currency]
|
row.update({
|
||||||
|
'total_tax': total_tax,
|
||||||
|
'total': d.base_net_amount + total_tax,
|
||||||
|
'currency': company_currency
|
||||||
|
})
|
||||||
|
|
||||||
|
if filters.get('group_by'):
|
||||||
|
row.update({'percent_gt': flt(row['total']/grand_total) * 100})
|
||||||
|
group_by_field, subtotal_display_field = get_group_by_and_display_fields(filters)
|
||||||
|
data, prev_group_by_value = add_total_row(data, filters, prev_group_by_value, d, total_row_map,
|
||||||
|
group_by_field, subtotal_display_field, grand_total, tax_columns)
|
||||||
|
add_sub_total_row(row, total_row_map, d.get(group_by_field, ''), tax_columns)
|
||||||
|
|
||||||
data.append(row)
|
data.append(row)
|
||||||
|
|
||||||
return columns, data
|
if filters.get('group_by'):
|
||||||
|
total_row = total_row_map.get(prev_group_by_value or d.get('item_name'))
|
||||||
|
total_row['percent_gt'] = flt(total_row['total']/grand_total * 100)
|
||||||
|
data.append(total_row)
|
||||||
|
data.append({})
|
||||||
|
add_sub_total_row(total_row, total_row_map, 'total_row', tax_columns)
|
||||||
|
data.append(total_row_map.get('total_row'))
|
||||||
|
skip_total_row = 1
|
||||||
|
|
||||||
|
return columns, data, None, None, None, skip_total_row
|
||||||
|
|
||||||
def get_columns(additional_table_columns):
|
def get_columns(additional_table_columns, filters):
|
||||||
columns = [
|
columns = []
|
||||||
_("Item Code") + ":Link/Item:120", _("Item Name") + "::120",
|
|
||||||
_("Item Group") + ":Link/Item Group:100", "Description::150", _("Invoice") + ":Link/Sales Invoice:120",
|
if filters.get('group_by') != ('Item'):
|
||||||
_("Posting Date") + ":Date:80", _("Customer") + ":Link/Customer:120",
|
columns.extend(
|
||||||
_("Customer Name") + "::120"]
|
[
|
||||||
|
{
|
||||||
|
'label': _('Item Code'),
|
||||||
|
'fieldname': 'item_code',
|
||||||
|
'fieldtype': 'Link',
|
||||||
|
'options': 'Item',
|
||||||
|
'width': 120
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': _('Item Name'),
|
||||||
|
'fieldname': 'item_name',
|
||||||
|
'fieldtype': 'Data',
|
||||||
|
'width': 120
|
||||||
|
}
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
if filters.get('group_by') not in ('Item', 'Item Group'):
|
||||||
|
columns.extend([
|
||||||
|
{
|
||||||
|
'label': _('Item Group'),
|
||||||
|
'fieldname': 'item_group',
|
||||||
|
'fieldtype': 'Link',
|
||||||
|
'options': 'Item Group',
|
||||||
|
'width': 120
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
columns.extend([
|
||||||
|
{
|
||||||
|
'label': _('Description'),
|
||||||
|
'fieldname': 'description',
|
||||||
|
'fieldtype': 'Data',
|
||||||
|
'width': 150
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': _('Invoice'),
|
||||||
|
'fieldname': 'invoice',
|
||||||
|
'fieldtype': 'Link',
|
||||||
|
'options': 'Sales Invoice',
|
||||||
|
'width': 120
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': _('Posting Date'),
|
||||||
|
'fieldname': 'posting_date',
|
||||||
|
'fieldtype': 'Date',
|
||||||
|
'width': 120
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
if filters.get('group_by') != 'Customer':
|
||||||
|
columns.extend([
|
||||||
|
{
|
||||||
|
'label': _('Customer Group'),
|
||||||
|
'fieldname': 'customer_group',
|
||||||
|
'fieldtype': 'Link',
|
||||||
|
'options': 'Customer Group',
|
||||||
|
'width': 120
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
if filters.get('group_by') not in ('Customer', 'Customer Group'):
|
||||||
|
columns.extend([
|
||||||
|
{
|
||||||
|
'label': _('Customer'),
|
||||||
|
'fieldname': 'customer',
|
||||||
|
'fieldtype': 'Link',
|
||||||
|
'options': 'Customer',
|
||||||
|
'width': 120
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': _('Customer Name'),
|
||||||
|
'fieldname': 'customer_name',
|
||||||
|
'fieldtype': 'Data',
|
||||||
|
'width': 120
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
if additional_table_columns:
|
if additional_table_columns:
|
||||||
columns += additional_table_columns
|
columns += additional_table_columns
|
||||||
|
|
||||||
columns += [
|
columns += [
|
||||||
_("Customer Group") + ":Link/Customer Group:120",
|
{
|
||||||
_("Receivable Account") + ":Link/Account:120",
|
'label': _('Receivable Account'),
|
||||||
_("Mode of Payment") + "::120", _("Territory") + ":Link/Territory:80",
|
'fieldname': 'debit_to',
|
||||||
_("Project") + ":Link/Project:80", _("Company") + ":Link/Company:100",
|
'fieldtype': 'Link',
|
||||||
_("Sales Order") + ":Link/Sales Order:100", _("Delivery Note") + ":Link/Delivery Note:100",
|
'options': 'Account',
|
||||||
_("Income Account") + ":Link/Account:140", _("Cost Center") + ":Link/Cost Center:140",
|
'width': 80
|
||||||
_("Stock Qty") + ":Float:120", _("Stock UOM") + "::100",
|
},
|
||||||
_("Rate") + ":Currency/currency:120",
|
{
|
||||||
_("Amount") + ":Currency/currency:120"
|
'label': _('Mode Of Payment'),
|
||||||
|
'fieldname': 'mode_of_payment',
|
||||||
|
'fieldtype': 'Data',
|
||||||
|
'width': 120
|
||||||
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
if filters.get('group_by') != 'Terriotory':
|
||||||
|
columns.extend([
|
||||||
|
{
|
||||||
|
'label': _("Territory"),
|
||||||
|
'fieldname': 'territory',
|
||||||
|
'fieldtype': 'Link',
|
||||||
|
'options': 'Territory',
|
||||||
|
'width': 80
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
|
columns += [
|
||||||
|
{
|
||||||
|
'label': _('Project'),
|
||||||
|
'fieldname': 'project',
|
||||||
|
'fieldtype': 'Link',
|
||||||
|
'options': 'Project',
|
||||||
|
'width': 80
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': _('Company'),
|
||||||
|
'fieldname': 'company',
|
||||||
|
'fieldtype': 'Link',
|
||||||
|
'options': 'Company',
|
||||||
|
'width': 80
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': _('Sales Order'),
|
||||||
|
'fieldname': 'sales_order',
|
||||||
|
'fieldtype': 'Link',
|
||||||
|
'options': 'Sales Order',
|
||||||
|
'width': 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': _("Delivery Note"),
|
||||||
|
'fieldname': 'delivery_note',
|
||||||
|
'fieldtype': 'Link',
|
||||||
|
'options': 'Delivery Note',
|
||||||
|
'width': 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': _('Income Account'),
|
||||||
|
'fieldname': 'income_account',
|
||||||
|
'fieldtype': 'Link',
|
||||||
|
'options': 'Account',
|
||||||
|
'width': 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': _("Cost Center"),
|
||||||
|
'fieldname': 'cost_center',
|
||||||
|
'fieldtype': 'Link',
|
||||||
|
'options': 'Cost Center',
|
||||||
|
'width': 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': _('Stock Qty'),
|
||||||
|
'fieldname': 'stock_qty',
|
||||||
|
'fieldtype': 'Float',
|
||||||
|
'width': 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': _('Stock UOM'),
|
||||||
|
'fieldname': 'stock_uom',
|
||||||
|
'fieldtype': 'Link',
|
||||||
|
'options': 'UOM',
|
||||||
|
'width': 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': _('Rate'),
|
||||||
|
'fieldname': 'rate',
|
||||||
|
'fieldtype': 'Float',
|
||||||
|
'options': 'currency',
|
||||||
|
'width': 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': _('Amount'),
|
||||||
|
'fieldname': 'amount',
|
||||||
|
'fieldtype': 'Currency',
|
||||||
|
'options': 'currency',
|
||||||
|
'width': 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'fieldname': 'currency',
|
||||||
|
'label': _('Currency'),
|
||||||
|
'fieldtype': 'Currency',
|
||||||
|
'width': 80,
|
||||||
|
'hidden': 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
if filters.get('group_by'):
|
||||||
|
columns.append({
|
||||||
|
'label': _('% Of Grand Total'),
|
||||||
|
'fieldname': 'percent_gt',
|
||||||
|
'fieldtype': 'Float',
|
||||||
|
'width': 80
|
||||||
|
})
|
||||||
|
|
||||||
return columns
|
return columns
|
||||||
|
|
||||||
def get_conditions(filters):
|
def get_conditions(filters):
|
||||||
@@ -112,24 +342,32 @@ def get_conditions(filters):
|
|||||||
and ifnull(`tabSales Invoice Payment`.mode_of_payment, '') = %(mode_of_payment)s)"""
|
and ifnull(`tabSales Invoice Payment`.mode_of_payment, '') = %(mode_of_payment)s)"""
|
||||||
|
|
||||||
if filters.get("warehouse"):
|
if filters.get("warehouse"):
|
||||||
conditions += """ and exists(select name from `tabSales Invoice Item`
|
conditions += """and ifnull(`tabSales Invoice Item`.warehouse, '') = %(warehouse)s"""
|
||||||
where parent=`tabSales Invoice`.name
|
|
||||||
and ifnull(`tabSales Invoice Item`.warehouse, '') = %(warehouse)s)"""
|
|
||||||
|
|
||||||
|
|
||||||
if filters.get("brand"):
|
if filters.get("brand"):
|
||||||
conditions += """ and exists(select name from `tabSales Invoice Item`
|
conditions += """and ifnull(`tabSales Invoice Item`.brand, '') = %(brand)s"""
|
||||||
where parent=`tabSales Invoice`.name
|
|
||||||
and ifnull(`tabSales Invoice Item`.brand, '') = %(brand)s)"""
|
|
||||||
|
|
||||||
if filters.get("item_group"):
|
if filters.get("item_group"):
|
||||||
conditions += """ and exists(select name from `tabSales Invoice Item`
|
conditions += """and ifnull(`tabSales Invoice Item`.item_group, '') = %(item_group)s"""
|
||||||
where parent=`tabSales Invoice`.name
|
|
||||||
and ifnull(`tabSales Invoice Item`.item_group, '') = %(item_group)s)"""
|
|
||||||
|
|
||||||
|
if not filters.get("group_by"):
|
||||||
|
conditions += "ORDER BY `tabSales Invoice`.posting_date desc, `tabSales Invoice Item`.item_group desc"
|
||||||
|
else:
|
||||||
|
conditions += get_group_by_conditions(filters, 'Sales Invoice')
|
||||||
|
|
||||||
return conditions
|
return conditions
|
||||||
|
|
||||||
|
def get_group_by_conditions(filters, doctype):
|
||||||
|
if filters.get("group_by") == 'Invoice':
|
||||||
|
return "ORDER BY `tab{0} Item`.parent desc".format(doctype)
|
||||||
|
elif filters.get("group_by") == 'Item':
|
||||||
|
return "ORDER BY `tab{0} Item`.`item_code`".format(doctype)
|
||||||
|
elif filters.get("group_by") == 'Item Group':
|
||||||
|
return "ORDER BY `tab{0} Item`.{1}".format(doctype, frappe.scrub(filters.get('group_by')))
|
||||||
|
elif filters.get("group_by") in ('Customer', 'Customer Group', 'Territory', 'Supplier'):
|
||||||
|
return "ORDER BY `tab{0}`.{1}".format(doctype, frappe.scrub(filters.get('group_by')))
|
||||||
|
|
||||||
def get_items(filters, additional_query_columns):
|
def get_items(filters, additional_query_columns):
|
||||||
conditions = get_conditions(filters)
|
conditions = get_conditions(filters)
|
||||||
match_conditions = frappe.build_match_conditions("Sales Invoice")
|
match_conditions = frappe.build_match_conditions("Sales Invoice")
|
||||||
@@ -156,9 +394,8 @@ def get_items(filters, additional_query_columns):
|
|||||||
`tabSales Invoice`.update_stock, `tabSales Invoice Item`.uom, `tabSales Invoice Item`.qty {0}
|
`tabSales Invoice`.update_stock, `tabSales Invoice Item`.uom, `tabSales Invoice Item`.qty {0}
|
||||||
from `tabSales Invoice`, `tabSales Invoice Item`
|
from `tabSales Invoice`, `tabSales Invoice Item`
|
||||||
where `tabSales Invoice`.name = `tabSales Invoice Item`.parent
|
where `tabSales Invoice`.name = `tabSales Invoice Item`.parent
|
||||||
and `tabSales Invoice`.docstatus = 1 %s %s
|
and `tabSales Invoice`.docstatus = 1 {1} {2}
|
||||||
order by `tabSales Invoice`.posting_date desc, `tabSales Invoice Item`.item_code desc
|
""".format(additional_query_columns or '', conditions, match_conditions), filters, as_dict=1) #nosec
|
||||||
""".format(additional_query_columns or '') % (conditions, match_conditions), filters, as_dict=1)
|
|
||||||
|
|
||||||
def get_delivery_notes_against_sales_order(item_list):
|
def get_delivery_notes_against_sales_order(item_list):
|
||||||
so_dn_map = frappe._dict()
|
so_dn_map = frappe._dict()
|
||||||
@@ -177,6 +414,15 @@ def get_delivery_notes_against_sales_order(item_list):
|
|||||||
|
|
||||||
return so_dn_map
|
return so_dn_map
|
||||||
|
|
||||||
|
def get_grand_total(filters, doctype):
|
||||||
|
|
||||||
|
return frappe.db.sql(""" SELECT
|
||||||
|
SUM(`tab{0}`.base_grand_total)
|
||||||
|
FROM `tab{0}`
|
||||||
|
WHERE `tab{0}`.docstatus = 1
|
||||||
|
and posting_date between %s and %s
|
||||||
|
""".format(doctype), (filters.get('from_date'), filters.get('to_date')))[0][0] #nosec
|
||||||
|
|
||||||
def get_deducted_taxes():
|
def get_deducted_taxes():
|
||||||
return frappe.db.sql_list("select name from `tabPurchase Taxes and Charges` where add_deduct_tax = 'Deduct'")
|
return frappe.db.sql_list("select name from `tabPurchase Taxes and Charges` where add_deduct_tax = 'Deduct'")
|
||||||
|
|
||||||
@@ -264,9 +510,117 @@ def get_tax_accounts(item_list, columns, company_currency,
|
|||||||
|
|
||||||
tax_columns.sort()
|
tax_columns.sort()
|
||||||
for desc in tax_columns:
|
for desc in tax_columns:
|
||||||
columns.append(desc + " Rate:Data:80")
|
columns.append({
|
||||||
columns.append(desc + " Amount:Currency/currency:100")
|
'label': _(desc + ' Rate'),
|
||||||
|
'fieldname': frappe.scrub(desc + ' Rate'),
|
||||||
|
'fieldtype': 'Float',
|
||||||
|
'width': 100
|
||||||
|
})
|
||||||
|
|
||||||
columns += ["Total Tax:Currency/currency:80", "Total:Currency/currency:100"]
|
columns.append({
|
||||||
|
'label': _(desc + ' Amount'),
|
||||||
|
'fieldname': frappe.scrub(desc + ' Amount'),
|
||||||
|
'fieldtype': 'Currency',
|
||||||
|
'options': 'currency',
|
||||||
|
'width': 100
|
||||||
|
})
|
||||||
|
|
||||||
|
columns += [
|
||||||
|
{
|
||||||
|
'label': _('Total Tax'),
|
||||||
|
'fieldname': 'total_tax',
|
||||||
|
'fieldtype': 'Currency',
|
||||||
|
'options': 'currency',
|
||||||
|
'width': 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': _('Total'),
|
||||||
|
'fieldname': 'total',
|
||||||
|
'fieldtype': 'Currency',
|
||||||
|
'options': 'currency',
|
||||||
|
'width': 100
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
return itemised_tax, tax_columns
|
return itemised_tax, tax_columns
|
||||||
|
|
||||||
|
def add_total_row(data, filters, prev_group_by_value, item, total_row_map,
|
||||||
|
group_by_field, subtotal_display_field, grand_total, tax_columns):
|
||||||
|
if prev_group_by_value != item.get(group_by_field, ''):
|
||||||
|
if prev_group_by_value:
|
||||||
|
total_row = total_row_map.get(prev_group_by_value)
|
||||||
|
data.append(total_row)
|
||||||
|
data.append({})
|
||||||
|
add_sub_total_row(total_row, total_row_map, 'total_row', tax_columns)
|
||||||
|
|
||||||
|
prev_group_by_value = item.get(group_by_field, '')
|
||||||
|
|
||||||
|
total_row_map.setdefault(item.get(group_by_field, ''), {
|
||||||
|
subtotal_display_field: get_display_value(filters, group_by_field, item),
|
||||||
|
'stock_qty': 0.0,
|
||||||
|
'amount': 0.0,
|
||||||
|
'bold': 1,
|
||||||
|
'total_tax': 0.0,
|
||||||
|
'total': 0.0,
|
||||||
|
'percent_gt': 0.0
|
||||||
|
})
|
||||||
|
|
||||||
|
total_row_map.setdefault('total_row', {
|
||||||
|
subtotal_display_field: "Total",
|
||||||
|
'stock_qty': 0.0,
|
||||||
|
'amount': 0.0,
|
||||||
|
'bold': 1,
|
||||||
|
'total_tax': 0.0,
|
||||||
|
'total': 0.0,
|
||||||
|
'percent_gt': 0.0
|
||||||
|
})
|
||||||
|
|
||||||
|
return data, prev_group_by_value
|
||||||
|
|
||||||
|
def get_display_value(filters, group_by_field, item):
|
||||||
|
if filters.get('group_by') == 'Item':
|
||||||
|
if item.get('item_code') != item.get('item_name'):
|
||||||
|
value = cstr(item.get('item_code')) + "<br><br>" + \
|
||||||
|
"<span style='font-weight: normal'>" + cstr(item.get('item_name')) + "</span>"
|
||||||
|
else:
|
||||||
|
value = item.get('item_code', '')
|
||||||
|
elif filters.get('group_by') in ('Customer', 'Supplier'):
|
||||||
|
party = frappe.scrub(filters.get('group_by'))
|
||||||
|
if item.get(party) != item.get(party+'_name'):
|
||||||
|
value = item.get(party) + "<br><br>" + \
|
||||||
|
"<span style='font-weight: normal'>" + item.get(party+'_name') + "</span>"
|
||||||
|
else:
|
||||||
|
value = item.get(party)
|
||||||
|
else:
|
||||||
|
value = item.get(group_by_field)
|
||||||
|
|
||||||
|
return value
|
||||||
|
|
||||||
|
def get_group_by_and_display_fields(filters):
|
||||||
|
if filters.get('group_by') == 'Item':
|
||||||
|
group_by_field = 'item_code'
|
||||||
|
subtotal_display_field = 'invoice'
|
||||||
|
elif filters.get('group_by') == 'Invoice':
|
||||||
|
group_by_field = 'parent'
|
||||||
|
subtotal_display_field = 'item_code'
|
||||||
|
else:
|
||||||
|
group_by_field = frappe.scrub(filters.get('group_by'))
|
||||||
|
subtotal_display_field = 'item_code'
|
||||||
|
|
||||||
|
return group_by_field, subtotal_display_field
|
||||||
|
|
||||||
|
def add_sub_total_row(item, total_row_map, group_by_value, tax_columns):
|
||||||
|
total_row = total_row_map.get(group_by_value)
|
||||||
|
total_row['stock_qty'] += item['stock_qty']
|
||||||
|
total_row['amount'] += item['amount']
|
||||||
|
total_row['total_tax'] += item['total_tax']
|
||||||
|
total_row['total'] += item['total']
|
||||||
|
total_row['percent_gt'] += item['percent_gt']
|
||||||
|
|
||||||
|
for tax in tax_columns:
|
||||||
|
total_row.setdefault(frappe.scrub(tax + ' Amount'), 0.0)
|
||||||
|
total_row[frappe.scrub(tax + ' Amount')] += flt(item[frappe.scrub(tax + ' Amount')])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,8 @@ frappe.require("assets/erpnext/js/financial_statements.js", function() {
|
|||||||
{
|
{
|
||||||
"fieldname": "include_default_book_entries",
|
"fieldname": "include_default_book_entries",
|
||||||
"label": __("Include Default Book Entries"),
|
"label": __("Include Default Book Entries"),
|
||||||
"fieldtype": "Check"
|
"fieldtype": "Check",
|
||||||
|
"default": 1
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -139,7 +139,7 @@ def get_columns(invoice_list, additional_table_columns):
|
|||||||
|
|
||||||
columns +=[
|
columns +=[
|
||||||
{
|
{
|
||||||
'label': _("Custmer Group"),
|
'label': _("Customer Group"),
|
||||||
'fieldname': 'customer_group',
|
'fieldname': 'customer_group',
|
||||||
'fieldtype': 'Link',
|
'fieldtype': 'Link',
|
||||||
'options': 'Customer Group',
|
'options': 'Customer Group',
|
||||||
@@ -175,7 +175,7 @@ def get_columns(invoice_list, additional_table_columns):
|
|||||||
'label': _("Project"),
|
'label': _("Project"),
|
||||||
'fieldname': 'project',
|
'fieldname': 'project',
|
||||||
'fieldtype': 'Link',
|
'fieldtype': 'Link',
|
||||||
'options': 'project',
|
'options': 'Project',
|
||||||
'width': 80
|
'width': 80
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -85,7 +85,8 @@ frappe.require("assets/erpnext/js/financial_statements.js", function() {
|
|||||||
{
|
{
|
||||||
"fieldname": "include_default_book_entries",
|
"fieldname": "include_default_book_entries",
|
||||||
"label": __("Include Default Book Entries"),
|
"label": __("Include Default Book Entries"),
|
||||||
"fieldtype": "Check"
|
"fieldtype": "Check",
|
||||||
|
"default": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"formatter": erpnext.financial_statements.formatter,
|
"formatter": erpnext.financial_statements.formatter,
|
||||||
|
|||||||
@@ -103,9 +103,9 @@ def get_rootwise_opening_balances(filters, report_type):
|
|||||||
where lft >= %s and rgt <= %s)""" % (lft, rgt)
|
where lft >= %s and rgt <= %s)""" % (lft, rgt)
|
||||||
|
|
||||||
if filters.finance_book:
|
if filters.finance_book:
|
||||||
fb_conditions = " and finance_book = %(finance_book)s"
|
fb_conditions = " AND finance_book = %(finance_book)s"
|
||||||
if filters.include_default_book_entries:
|
if filters.include_default_book_entries:
|
||||||
fb_conditions = " and (finance_book in (%(finance_book)s, %(company_fb)s))"
|
fb_conditions = " AND (finance_book in (%(finance_book)s, %(company_fb)s, '') OR finance_book IS NULL)"
|
||||||
|
|
||||||
additional_conditions += fb_conditions
|
additional_conditions += fb_conditions
|
||||||
|
|
||||||
|
|||||||
@@ -640,8 +640,9 @@ def get_outstanding_invoices(party_type, party, account, condition=None, filters
|
|||||||
precision = frappe.get_precision("Sales Invoice", "outstanding_amount") or 2
|
precision = frappe.get_precision("Sales Invoice", "outstanding_amount") or 2
|
||||||
|
|
||||||
if account:
|
if account:
|
||||||
root_type = frappe.get_cached_value("Account", account, "root_type")
|
root_type, account_type = frappe.get_cached_value("Account", account, ["root_type", "account_type"])
|
||||||
party_account_type = "Receivable" if root_type == "Asset" else "Payable"
|
party_account_type = "Receivable" if root_type == "Asset" else "Payable"
|
||||||
|
party_account_type = account_type or party_account_type
|
||||||
else:
|
else:
|
||||||
party_account_type = erpnext.get_party_account_type(party_type)
|
party_account_type = erpnext.get_party_account_type(party_type)
|
||||||
|
|
||||||
|
|||||||
@@ -620,7 +620,7 @@ def get_asset_account(account_name, asset=None, asset_category=None, company=Non
|
|||||||
|
|
||||||
if not account:
|
if not account:
|
||||||
if not asset_category:
|
if not asset_category:
|
||||||
frappe.throw(_("Set {0} in company {2}").format(account_name.replace('_', ' ').title(), company))
|
frappe.throw(_("Set {0} in company {1}").format(account_name.replace('_', ' ').title(), company))
|
||||||
else:
|
else:
|
||||||
frappe.throw(_("Set {0} in asset category {1} or company {2}")
|
frappe.throw(_("Set {0} in asset category {1} or company {2}")
|
||||||
.format(account_name.replace('_', ' ').title(), asset_category, company))
|
.format(account_name.replace('_', ' ').title(), asset_category, company))
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ def post_depreciation_entries(date=None):
|
|||||||
def get_depreciable_assets(date):
|
def get_depreciable_assets(date):
|
||||||
return frappe.db.sql_list("""select a.name
|
return frappe.db.sql_list("""select a.name
|
||||||
from tabAsset a, `tabDepreciation Schedule` ds
|
from tabAsset a, `tabDepreciation Schedule` ds
|
||||||
where a.name = ds.parent and a.docstatus=1 and ds.schedule_date<=%s
|
where a.name = ds.parent and a.docstatus=1 and ds.schedule_date<=%s and a.calculate_depreciation = 1
|
||||||
and a.status in ('Submitted', 'Partially Depreciated')
|
and a.status in ('Submitted', 'Partially Depreciated')
|
||||||
and ifnull(ds.journal_entry, '')=''""", date)
|
and ifnull(ds.journal_entry, '')=''""", date)
|
||||||
|
|
||||||
|
|||||||
@@ -1,580 +1,146 @@
|
|||||||
{
|
{
|
||||||
"allow_copy": 0,
|
"actions": [],
|
||||||
"allow_guest_to_view": 0,
|
|
||||||
"allow_import": 1,
|
"allow_import": 1,
|
||||||
"allow_rename": 1,
|
"allow_rename": 1,
|
||||||
"autoname": "field:location_name",
|
"autoname": "field:location_name",
|
||||||
"beta": 0,
|
|
||||||
"creation": "2018-05-07 12:49:22.595974",
|
"creation": "2018-05-07 12:49:22.595974",
|
||||||
"custom": 0,
|
|
||||||
"docstatus": 0,
|
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
"document_type": "",
|
|
||||||
"editable_grid": 1,
|
"editable_grid": 1,
|
||||||
"engine": "InnoDB",
|
"engine": "InnoDB",
|
||||||
|
"field_order": [
|
||||||
|
"location_name",
|
||||||
|
"parent_location",
|
||||||
|
"cb_details",
|
||||||
|
"is_container",
|
||||||
|
"is_group",
|
||||||
|
"sb_location_details",
|
||||||
|
"latitude",
|
||||||
|
"longitude",
|
||||||
|
"cb_latlong",
|
||||||
|
"area",
|
||||||
|
"area_uom",
|
||||||
|
"sb_geolocation",
|
||||||
|
"location",
|
||||||
|
"tree_details",
|
||||||
|
"lft",
|
||||||
|
"rgt",
|
||||||
|
"old_parent"
|
||||||
|
],
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "location_name",
|
"fieldname": "location_name",
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Location Name",
|
"label": "Location Name",
|
||||||
"length": 0,
|
|
||||||
"no_copy": 1,
|
"no_copy": 1,
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 1,
|
"reqd": 1,
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 1
|
"unique": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "parent_location",
|
"fieldname": "parent_location",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"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": "Parent Location",
|
"label": "Parent Location",
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "Location",
|
"options": "Location",
|
||||||
"permlevel": 0,
|
"search_index": 1
|
||||||
"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": 1,
|
|
||||||
"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": "cb_details",
|
"fieldname": "cb_details",
|
||||||
"fieldtype": "Column Break",
|
"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,
|
"default": "0",
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"description": "Check if it is a hydroponic unit",
|
"description": "Check if it is a hydroponic unit",
|
||||||
"fieldname": "is_container",
|
"fieldname": "is_container",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"hidden": 0,
|
"label": "Is Container"
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Is Container",
|
|
||||||
"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": 1,
|
"bold": 1,
|
||||||
"collapsible": 0,
|
"default": "0",
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "is_group",
|
"fieldname": "is_group",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"in_standard_filter": 0,
|
"label": "Is Group"
|
||||||
"label": "Is Group",
|
|
||||||
"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": "sb_location_details",
|
"fieldname": "sb_location_details",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"hidden": 0,
|
"label": "Location Details"
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Location Details",
|
|
||||||
"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,
|
|
||||||
"fetch_from": "parent_location.latitude",
|
"fetch_from": "parent_location.latitude",
|
||||||
"fieldname": "latitude",
|
"fieldname": "latitude",
|
||||||
"fieldtype": "Float",
|
"fieldtype": "Float",
|
||||||
"hidden": 0,
|
"label": "Latitude"
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Latitude",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "",
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fetch_from": "parent_location.longitude",
|
"fetch_from": "parent_location.longitude",
|
||||||
"fieldname": "longitude",
|
"fieldname": "longitude",
|
||||||
"fieldtype": "Float",
|
"fieldtype": "Float",
|
||||||
"hidden": 0,
|
"label": "Longitude"
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Longitude",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "",
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "cb_latlong",
|
"fieldname": "cb_latlong",
|
||||||
"fieldtype": "Column Break",
|
"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,
|
|
||||||
"label": "",
|
|
||||||
"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": "area",
|
"fieldname": "area",
|
||||||
"fieldtype": "Float",
|
"fieldtype": "Float",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Area",
|
"label": "Area",
|
||||||
"length": 0,
|
"read_only": 1
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 1,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"depends_on": "eval:doc.area",
|
"depends_on": "eval:doc.area",
|
||||||
"fieldname": "area_uom",
|
"fieldname": "area_uom",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"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": "Area UOM",
|
"label": "Area UOM",
|
||||||
"length": 0,
|
"options": "UOM"
|
||||||
"no_copy": 0,
|
|
||||||
"options": "UOM",
|
|
||||||
"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": "sb_geolocation",
|
"fieldname": "sb_geolocation",
|
||||||
"fieldtype": "Section Break",
|
"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,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "location",
|
"fieldname": "location",
|
||||||
"fieldtype": "Geolocation",
|
"fieldtype": "Geolocation",
|
||||||
"hidden": 0,
|
"label": "Location"
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Location",
|
|
||||||
"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": "tree_details",
|
"fieldname": "tree_details",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"hidden": 1,
|
"hidden": 1,
|
||||||
"ignore_user_permissions": 0,
|
"label": "Tree Details"
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Tree Details",
|
|
||||||
"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": "lft",
|
"fieldname": "lft",
|
||||||
"fieldtype": "Int",
|
"fieldtype": "Int",
|
||||||
"hidden": 1,
|
"hidden": 1,
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "lft",
|
"label": "lft",
|
||||||
"length": 0,
|
|
||||||
"no_copy": 1,
|
"no_copy": 1,
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 1,
|
"print_hide": 1,
|
||||||
"print_hide_if_no_value": 0,
|
"read_only": 1
|
||||||
"read_only": 1,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "rgt",
|
"fieldname": "rgt",
|
||||||
"fieldtype": "Int",
|
"fieldtype": "Int",
|
||||||
"hidden": 1,
|
"hidden": 1,
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "rgt",
|
"label": "rgt",
|
||||||
"length": 0,
|
|
||||||
"no_copy": 1,
|
"no_copy": 1,
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 1,
|
"print_hide": 1,
|
||||||
"print_hide_if_no_value": 0,
|
"read_only": 1
|
||||||
"read_only": 1,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "old_parent",
|
"fieldname": "old_parent",
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
"hidden": 1,
|
"hidden": 1,
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Old Parent",
|
"label": "Old Parent",
|
||||||
"length": 0,
|
|
||||||
"no_copy": 1,
|
"no_copy": 1,
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 1,
|
"print_hide": 1,
|
||||||
"print_hide_if_no_value": 0,
|
"read_only": 1
|
||||||
"read_only": 1,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"has_web_view": 0,
|
"links": [],
|
||||||
"hide_heading": 0,
|
"modified": "2020-01-28 13:52:22.513425",
|
||||||
"hide_toolbar": 0,
|
|
||||||
"idx": 0,
|
|
||||||
"image_view": 0,
|
|
||||||
"in_create": 0,
|
|
||||||
"is_submittable": 0,
|
|
||||||
"issingle": 0,
|
|
||||||
"istable": 0,
|
|
||||||
"max_attachments": 0,
|
|
||||||
"modified": "2018-07-11 13:36:30.999405",
|
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Assets",
|
"module": "Assets",
|
||||||
"name": "Location",
|
"name": "Location",
|
||||||
@@ -582,127 +148,78 @@
|
|||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
{
|
{
|
||||||
"amend": 0,
|
|
||||||
"cancel": 0,
|
|
||||||
"create": 1,
|
"create": 1,
|
||||||
"delete": 1,
|
"delete": 1,
|
||||||
"email": 1,
|
"email": 1,
|
||||||
"export": 1,
|
"export": 1,
|
||||||
"if_owner": 0,
|
|
||||||
"import": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print": 1,
|
"print": 1,
|
||||||
"read": 1,
|
"read": 1,
|
||||||
"report": 1,
|
"report": 1,
|
||||||
"role": "System Manager",
|
"role": "System Manager",
|
||||||
"set_user_permissions": 0,
|
|
||||||
"share": 1,
|
"share": 1,
|
||||||
"submit": 0,
|
|
||||||
"write": 1
|
"write": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"amend": 0,
|
|
||||||
"cancel": 0,
|
|
||||||
"create": 1,
|
"create": 1,
|
||||||
"delete": 1,
|
"delete": 1,
|
||||||
"email": 1,
|
"email": 1,
|
||||||
"export": 1,
|
"export": 1,
|
||||||
"if_owner": 0,
|
|
||||||
"import": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print": 1,
|
"print": 1,
|
||||||
"read": 1,
|
"read": 1,
|
||||||
"report": 1,
|
"report": 1,
|
||||||
"role": "Stock User",
|
"role": "Stock User",
|
||||||
"set_user_permissions": 0,
|
|
||||||
"share": 1,
|
"share": 1,
|
||||||
"submit": 0,
|
|
||||||
"write": 1
|
"write": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"amend": 0,
|
|
||||||
"cancel": 0,
|
|
||||||
"create": 1,
|
"create": 1,
|
||||||
"delete": 1,
|
"delete": 1,
|
||||||
"email": 1,
|
"email": 1,
|
||||||
"export": 1,
|
"export": 1,
|
||||||
"if_owner": 0,
|
|
||||||
"import": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print": 1,
|
"print": 1,
|
||||||
"read": 1,
|
"read": 1,
|
||||||
"report": 1,
|
"report": 1,
|
||||||
"role": "Accounts User",
|
"role": "Accounts User",
|
||||||
"set_user_permissions": 0,
|
|
||||||
"share": 1,
|
"share": 1,
|
||||||
"submit": 0,
|
|
||||||
"write": 1
|
"write": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"amend": 0,
|
|
||||||
"cancel": 0,
|
|
||||||
"create": 1,
|
"create": 1,
|
||||||
"delete": 1,
|
"delete": 1,
|
||||||
"email": 1,
|
"email": 1,
|
||||||
"export": 1,
|
"export": 1,
|
||||||
"if_owner": 0,
|
|
||||||
"import": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print": 1,
|
"print": 1,
|
||||||
"read": 1,
|
"read": 1,
|
||||||
"report": 1,
|
"report": 1,
|
||||||
"role": "Stock Manager",
|
"role": "Stock Manager",
|
||||||
"set_user_permissions": 0,
|
|
||||||
"share": 1,
|
"share": 1,
|
||||||
"submit": 0,
|
|
||||||
"write": 1
|
"write": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"amend": 0,
|
|
||||||
"cancel": 0,
|
|
||||||
"create": 1,
|
"create": 1,
|
||||||
"delete": 1,
|
"delete": 1,
|
||||||
"email": 1,
|
"email": 1,
|
||||||
"export": 1,
|
"export": 1,
|
||||||
"if_owner": 0,
|
|
||||||
"import": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print": 1,
|
"print": 1,
|
||||||
"read": 1,
|
"read": 1,
|
||||||
"report": 1,
|
"report": 1,
|
||||||
"role": "Agriculture Manager",
|
"role": "Agriculture Manager",
|
||||||
"set_user_permissions": 0,
|
|
||||||
"share": 1,
|
"share": 1,
|
||||||
"submit": 0,
|
|
||||||
"write": 1
|
"write": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"amend": 0,
|
|
||||||
"cancel": 0,
|
|
||||||
"create": 0,
|
|
||||||
"delete": 0,
|
|
||||||
"email": 1,
|
"email": 1,
|
||||||
"export": 1,
|
"export": 1,
|
||||||
"if_owner": 0,
|
|
||||||
"import": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print": 1,
|
"print": 1,
|
||||||
"read": 1,
|
"read": 1,
|
||||||
"report": 1,
|
"report": 1,
|
||||||
"role": "Agriculture User",
|
"role": "Agriculture User",
|
||||||
"set_user_permissions": 0,
|
|
||||||
"share": 1,
|
"share": 1,
|
||||||
"submit": 0,
|
|
||||||
"write": 1
|
"write": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"quick_entry": 1,
|
|
||||||
"read_only": 0,
|
|
||||||
"read_only_onload": 0,
|
|
||||||
"show_name_in_global_search": 1,
|
"show_name_in_global_search": 1,
|
||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
"track_changes": 1,
|
"track_changes": 1
|
||||||
"track_seen": 0,
|
|
||||||
"track_views": 0
|
|
||||||
}
|
}
|
||||||
@@ -20,6 +20,16 @@ frappe.query_reports["Fixed Asset Register"] = {
|
|||||||
default: 'In Location',
|
default: 'In Location',
|
||||||
reqd: 1
|
reqd: 1
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
fieldname:"purchase_date",
|
||||||
|
label: __("Purchase Date"),
|
||||||
|
fieldtype: "Date"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldname:"available_for_use_date",
|
||||||
|
label: __("Available For Use Date"),
|
||||||
|
fieldtype: "Date"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
fieldname:"finance_book",
|
fieldname:"finance_book",
|
||||||
label: __("Finance Book"),
|
label: __("Finance Book"),
|
||||||
@@ -27,10 +37,15 @@ frappe.query_reports["Fixed Asset Register"] = {
|
|||||||
options: "Finance Book"
|
options: "Finance Book"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
fieldname:"date",
|
fieldname:"asset_category",
|
||||||
label: __("Date"),
|
label: __("Asset Category"),
|
||||||
fieldtype: "Date",
|
fieldtype: "Link",
|
||||||
default: frappe.datetime.get_today()
|
options: "Asset Category"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldname:"is_existing_asset",
|
||||||
|
label: __("Is Existing Asset"),
|
||||||
|
fieldtype: "Check"
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -40,6 +40,42 @@ def get_columns(filters):
|
|||||||
"fieldname": "status",
|
"fieldname": "status",
|
||||||
"width": 90
|
"width": 90
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"label": _("Purchase Date"),
|
||||||
|
"fieldtype": "Date",
|
||||||
|
"fieldname": "purchase_date",
|
||||||
|
"width": 90
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": _("Available For Use Date"),
|
||||||
|
"fieldtype": "Date",
|
||||||
|
"fieldname": "available_for_use_date",
|
||||||
|
"width": 90
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": _("Gross Purchase Amount"),
|
||||||
|
"fieldname": "gross_purchase_amount",
|
||||||
|
"options": "Currency",
|
||||||
|
"width": 90
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": _("Asset Value"),
|
||||||
|
"fieldname": "asset_value",
|
||||||
|
"options": "Currency",
|
||||||
|
"width": 90
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": _("Opening Accumulated Depreciation"),
|
||||||
|
"fieldname": "opening_accumulated_depreciation",
|
||||||
|
"options": "Currency",
|
||||||
|
"width": 90
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": _("Depreciated Amount"),
|
||||||
|
"fieldname": "depreciated_amount",
|
||||||
|
"options": "Currency",
|
||||||
|
"width": 90
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"label": _("Cost Center"),
|
"label": _("Cost Center"),
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
@@ -54,25 +90,6 @@ def get_columns(filters):
|
|||||||
"options": "Department",
|
"options": "Department",
|
||||||
"width": 100
|
"width": 100
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"label": _("Location"),
|
|
||||||
"fieldtype": "Link",
|
|
||||||
"fieldname": "location",
|
|
||||||
"options": "Location",
|
|
||||||
"width": 100
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": _("Purchase Date"),
|
|
||||||
"fieldtype": "Date",
|
|
||||||
"fieldname": "purchase_date",
|
|
||||||
"width": 90
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": _("Gross Purchase Amount"),
|
|
||||||
"fieldname": "gross_purchase_amount",
|
|
||||||
"options": "Currency",
|
|
||||||
"width": 90
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"label": _("Vendor Name"),
|
"label": _("Vendor Name"),
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
@@ -80,25 +97,29 @@ def get_columns(filters):
|
|||||||
"width": 100
|
"width": 100
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": _("Available For Use Date"),
|
"label": _("Location"),
|
||||||
"fieldtype": "Date",
|
"fieldtype": "Link",
|
||||||
"fieldname": "available_for_use_date",
|
"fieldname": "location",
|
||||||
"width": 90
|
"options": "Location",
|
||||||
},
|
"width": 100
|
||||||
{
|
|
||||||
"label": _("Asset Value"),
|
|
||||||
"fieldname": "asset_value",
|
|
||||||
"options": "Currency",
|
|
||||||
"width": 90
|
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
def get_conditions(filters):
|
def get_conditions(filters):
|
||||||
conditions = {'docstatus': 1}
|
conditions = { 'docstatus': 1 }
|
||||||
status = filters.status
|
status = filters.status
|
||||||
|
date = filters.date
|
||||||
|
|
||||||
if filters.company:
|
if filters.get('company'):
|
||||||
conditions["company"] = filters.company
|
conditions["company"] = filters.company
|
||||||
|
if filters.get('purchase_date'):
|
||||||
|
conditions["purchase_date"] = ('<=', filters.get('purchase_date'))
|
||||||
|
if filters.get('available_for_use_date'):
|
||||||
|
conditions["available_for_use_date"] = ('<=', filters.get('available_for_use_date'))
|
||||||
|
if filters.get('is_existing_asset'):
|
||||||
|
conditions["is_existing_asset"] = filters.get('is_existing_asset')
|
||||||
|
if filters.get('asset_category'):
|
||||||
|
conditions["asset_category"] = filters.get('asset_category')
|
||||||
|
|
||||||
# In Store assets are those that are not sold or scrapped
|
# In Store assets are those that are not sold or scrapped
|
||||||
operand = 'not in'
|
operand = 'not in'
|
||||||
@@ -114,7 +135,7 @@ def get_data(filters):
|
|||||||
data = []
|
data = []
|
||||||
|
|
||||||
conditions = get_conditions(filters)
|
conditions = get_conditions(filters)
|
||||||
depreciation_amount_map = get_finance_book_value_map(filters.date, filters.finance_book)
|
depreciation_amount_map = get_finance_book_value_map(filters)
|
||||||
pr_supplier_map = get_purchase_receipt_supplier_map()
|
pr_supplier_map = get_purchase_receipt_supplier_map()
|
||||||
pi_supplier_map = get_purchase_invoice_supplier_map()
|
pi_supplier_map = get_purchase_invoice_supplier_map()
|
||||||
|
|
||||||
@@ -136,6 +157,8 @@ def get_data(filters):
|
|||||||
"cost_center": asset.cost_center,
|
"cost_center": asset.cost_center,
|
||||||
"vendor_name": pr_supplier_map.get(asset.purchase_receipt) or pi_supplier_map.get(asset.purchase_invoice),
|
"vendor_name": pr_supplier_map.get(asset.purchase_receipt) or pi_supplier_map.get(asset.purchase_invoice),
|
||||||
"gross_purchase_amount": asset.gross_purchase_amount,
|
"gross_purchase_amount": asset.gross_purchase_amount,
|
||||||
|
"opening_accumulated_depreciation": asset.opening_accumulated_depreciation,
|
||||||
|
"depreciated_amount": depreciation_amount_map.get(asset.name) or 0.0,
|
||||||
"available_for_use_date": asset.available_for_use_date,
|
"available_for_use_date": asset.available_for_use_date,
|
||||||
"location": asset.location,
|
"location": asset.location,
|
||||||
"asset_category": asset.asset_category,
|
"asset_category": asset.asset_category,
|
||||||
@@ -146,9 +169,9 @@ def get_data(filters):
|
|||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
def get_finance_book_value_map(date, finance_book=''):
|
def get_finance_book_value_map(filters):
|
||||||
if not date:
|
date = filters.get('purchase_date') or filters.get('available_for_use_date') or today()
|
||||||
date = today()
|
|
||||||
return frappe._dict(frappe.db.sql(''' Select
|
return frappe._dict(frappe.db.sql(''' Select
|
||||||
parent, SUM(depreciation_amount)
|
parent, SUM(depreciation_amount)
|
||||||
FROM `tabDepreciation Schedule`
|
FROM `tabDepreciation Schedule`
|
||||||
@@ -157,7 +180,7 @@ def get_finance_book_value_map(date, finance_book=''):
|
|||||||
AND schedule_date<=%s
|
AND schedule_date<=%s
|
||||||
AND journal_entry IS NOT NULL
|
AND journal_entry IS NOT NULL
|
||||||
AND ifnull(finance_book, '')=%s
|
AND ifnull(finance_book, '')=%s
|
||||||
GROUP BY parent''', (date, cstr(finance_book))))
|
GROUP BY parent''', (date, cstr(filters.finance_book or ''))))
|
||||||
|
|
||||||
def get_purchase_receipt_supplier_map():
|
def get_purchase_receipt_supplier_map():
|
||||||
return frappe._dict(frappe.db.sql(''' Select
|
return frappe._dict(frappe.db.sql(''' Select
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ cur_frm.add_fetch('contact', 'email_id', 'email_id')
|
|||||||
frappe.ui.form.on("Request for Quotation",{
|
frappe.ui.form.on("Request for Quotation",{
|
||||||
setup: function(frm) {
|
setup: function(frm) {
|
||||||
frm.custom_make_buttons = {
|
frm.custom_make_buttons = {
|
||||||
'Supplier Quotation': 'Supplier Quotation'
|
'Supplier Quotation': 'Create'
|
||||||
}
|
}
|
||||||
|
|
||||||
frm.fields_dict["suppliers"].grid.get_field("contact").get_query = function(doc, cdt, cdn) {
|
frm.fields_dict["suppliers"].grid.get_field("contact").get_query = function(doc, cdt, cdn) {
|
||||||
|
|||||||
@@ -141,13 +141,13 @@ def get_conditions(filters):
|
|||||||
conditions = ""
|
conditions = ""
|
||||||
|
|
||||||
if filters.get("company"):
|
if filters.get("company"):
|
||||||
conditions += " AND company='%s'"% filters.get('company')
|
conditions += " AND company=%s"% frappe.db.escape(filters.get('company'))
|
||||||
|
|
||||||
if filters.get("cost_center") or filters.get("project"):
|
if filters.get("cost_center") or filters.get("project"):
|
||||||
conditions += """
|
conditions += """
|
||||||
AND (cost_center='%s'
|
AND (cost_center=%s
|
||||||
OR project='%s')
|
OR project=%s)
|
||||||
"""% (filters.get('cost_center'), filters.get('project'))
|
"""% (frappe.db.escape(filters.get('cost_center')), frappe.db.escape(filters.get('project')))
|
||||||
|
|
||||||
if filters.get("from_date"):
|
if filters.get("from_date"):
|
||||||
conditions += " AND transaction_date>=%s"% filters.get('from_date')
|
conditions += " AND transaction_date>=%s"% filters.get('from_date')
|
||||||
|
|||||||
53
erpnext/change_log/v12/v12_5_0.md
Normal file
53
erpnext/change_log/v12/v12_5_0.md
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
## Version 12.5.0 Release Note
|
||||||
|
|
||||||
|
### New Features:
|
||||||
|
- **Group by Customer / Customer Group / Item / Item Group / Territory / Invoice** option in Itemised Sales Register report [#20251](https://github.com/frappe/erpnext/pull/20251)
|
||||||
|
|
||||||
|
- **Group by Supplier / Item / Item Group / Invoice** option in Itemised Purchase Register report
|
||||||
|
|
||||||
|
- **Group by Customer / Supplier** option in Accounts Receivable / Payable report
|
||||||
|
|
||||||
|
- Enhanced Fixed Asset Register report [#20332](https://github.com/frappe/erpnext/pull/20332)
|
||||||
|
|
||||||
|
- Added tax category in pos profile [#20413](https://github.com/frappe/erpnext/pull/20413)
|
||||||
|
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
- GL Entries were not creating on manual asset creation [#20265](https://github.com/frappe/erpnext/pull/20265)
|
||||||
|
|
||||||
|
- Payment Entry should not be allowed against blocked Purchase Invoice until release date [#20270](https://github.com/frappe/erpnext/pull/20270)
|
||||||
|
|
||||||
|
- Incorrect number of GL Entries error in stock entry due to precision issue [#20297](https://github.com/frappe/erpnext/pull/20297)
|
||||||
|
|
||||||
|
- Wrong outstanding invoices fetched against employee [#20373](https://github.com/frappe/erpnext/pull/20373)
|
||||||
|
|
||||||
|
- Finance book filtering logic in financial statements and other accounting reports [#20411](https://github.com/frappe/erpnext/pull/20410)
|
||||||
|
|
||||||
|
- Additional discount was not appling on sales invoice created by subscription [#20432](https://github.com/frappe/erpnext/pull/20432)
|
||||||
|
|
||||||
|
- Deprecated fetching item price based on minimum qty [#20346](https://github.com/frappe/erpnext/pull/20346)
|
||||||
|
|
||||||
|
- Calculation of carry forwarded leaves [#20341](https://github.com/frappe/erpnext/pull/20341)
|
||||||
|
|
||||||
|
- Quotation status will be expired based on validity only if it is not Ordered or Lost [#20365](https://github.com/frappe/erpnext/pull/20354)
|
||||||
|
|
||||||
|
- Delete auto created batch on cancellation of Purchase Receipt / Stock Entry [#20392](https://github.com/frappe/erpnext/pull/20392)
|
||||||
|
|
||||||
|
- Show product bundle item's availability on website based on availability of all bundled items [#20384](https://github.com/frappe/erpnext/pull/20384)
|
||||||
|
|
||||||
|
- Show relevant suppliers on "Create Purchase Order" popup in Material Request [#20232](https://github.com/frappe/erpnext/pull/20232)
|
||||||
|
|
||||||
|
- Cannot complete task if dependent task are not completed / cancelled [#20434](https://github.com/frappe/erpnext/pull/20434)
|
||||||
|
|
||||||
|
- Show numeric values in item configurator [#20430](https://github.com/frappe/erpnext/pull/20430)
|
||||||
|
|
||||||
|
- Filter serial no based on batch no [#20566](https://github.com/frappe/erpnext/pull/20566)
|
||||||
|
|
||||||
|
- Pricing rule was not working on item groups [#20546](https://github.com/frappe/erpnext/pull/20546)
|
||||||
|
|
||||||
|
- Disabled quick entry for doctypes with tree view [#20453](https://github.com/frappe/erpnext/pull/20453)
|
||||||
|
|
||||||
|
### Optimisation
|
||||||
|
- Handling of large number of serial no creation via Purchase Receipt / Stock Entry (10 times faster than before!) [#20540](https://github.com/frappe/erpnext/pull/20540)
|
||||||
|
|
||||||
|
- Update outstanding amount on Sales Invoice on submission of invoice / payment [#20557](https://github.com/frappe/erpnext/pull/20557)
|
||||||
@@ -1135,6 +1135,7 @@ def set_sales_order_defaults(parent_doctype, parent_doctype_name, child_docname,
|
|||||||
child_item.reqd_by_date = p_doctype.delivery_date
|
child_item.reqd_by_date = p_doctype.delivery_date
|
||||||
child_item.uom = item.stock_uom
|
child_item.uom = item.stock_uom
|
||||||
child_item.conversion_factor = get_conversion_factor(item_code, item.stock_uom).get("conversion_factor") or 1.0
|
child_item.conversion_factor = get_conversion_factor(item_code, item.stock_uom).get("conversion_factor") or 1.0
|
||||||
|
child_item.warehouse = p_doctype.set_warehouse or p_doctype.items[0].warehouse
|
||||||
return child_item
|
return child_item
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -182,7 +182,7 @@ class StatusUpdater(Document):
|
|||||||
if args.get('no_allowance'):
|
if args.get('no_allowance'):
|
||||||
item['reduce_by'] = item[args['target_field']] - item[args['target_ref_field']]
|
item['reduce_by'] = item[args['target_field']] - item[args['target_ref_field']]
|
||||||
if item['reduce_by'] > .01:
|
if item['reduce_by'] > .01:
|
||||||
self.limits_crossed_error(args, item)
|
self.limits_crossed_error(args, item, "qty")
|
||||||
|
|
||||||
elif item[args['target_ref_field']]:
|
elif item[args['target_ref_field']]:
|
||||||
self.check_overflow_with_allowance(item, args)
|
self.check_overflow_with_allowance(item, args)
|
||||||
|
|||||||
@@ -235,6 +235,17 @@ class StockController(AccountsController):
|
|||||||
frappe.throw(_("{0} {1}: Cost Center is mandatory for Item {2}").format(
|
frappe.throw(_("{0} {1}: Cost Center is mandatory for Item {2}").format(
|
||||||
_(self.doctype), self.name, item.get("item_code")))
|
_(self.doctype), self.name, item.get("item_code")))
|
||||||
|
|
||||||
|
def delete_auto_created_batches(self):
|
||||||
|
for d in self.items:
|
||||||
|
if not d.batch_no: continue
|
||||||
|
|
||||||
|
d.batch_no = None
|
||||||
|
d.db_set("batch_no", None)
|
||||||
|
|
||||||
|
for data in frappe.get_all("Batch",
|
||||||
|
{'reference_name': self.name, 'reference_doctype': self.doctype}):
|
||||||
|
frappe.delete_doc("Batch", data.name)
|
||||||
|
|
||||||
def get_sl_entries(self, d, args):
|
def get_sl_entries(self, d, args):
|
||||||
sl_dict = frappe._dict({
|
sl_dict = frappe._dict({
|
||||||
"item_code": d.get("item_code", None),
|
"item_code": d.get("item_code", None),
|
||||||
|
|||||||
@@ -53,8 +53,8 @@ class Lead(SellingController):
|
|||||||
if self.contact_date and getdate(self.contact_date) < getdate(nowdate()):
|
if self.contact_date and getdate(self.contact_date) < getdate(nowdate()):
|
||||||
frappe.throw(_("Next Contact Date cannot be in the past"))
|
frappe.throw(_("Next Contact Date cannot be in the past"))
|
||||||
|
|
||||||
if self.ends_on and self.contact_date and\
|
if (self.ends_on and self.contact_date and
|
||||||
(self.ends_on < self.contact_date):
|
(getdate(self.ends_on) < getdate(self.contact_date))):
|
||||||
frappe.throw(_("Ends On date cannot be before Next Contact Date."))
|
frappe.throw(_("Ends On date cannot be before Next Contact Date."))
|
||||||
|
|
||||||
def on_update(self):
|
def on_update(self):
|
||||||
|
|||||||
@@ -308,7 +308,7 @@ def set_multiple_status(names, status):
|
|||||||
|
|
||||||
def auto_close_opportunity():
|
def auto_close_opportunity():
|
||||||
""" auto close the `Replied` Opportunities after 7 days """
|
""" auto close the `Replied` Opportunities after 7 days """
|
||||||
auto_close_after_days = frappe.db.get_value("Support Settings", "Support Settings", "close_opportunity_after_days") or 15
|
auto_close_after_days = frappe.db.get_single_value("Selling Settings", "close_opportunity_after_days") or 15
|
||||||
|
|
||||||
opportunities = frappe.db.sql(""" select name from tabOpportunity where status='Replied' and
|
opportunities = frappe.db.sql(""" select name from tabOpportunity where status='Replied' and
|
||||||
modified<DATE_SUB(CURDATE(), INTERVAL %s DAY) """, (auto_close_after_days), as_dict=True)
|
modified<DATE_SUB(CURDATE(), INTERVAL %s DAY) """, (auto_close_after_days), as_dict=True)
|
||||||
|
|||||||
@@ -1,28 +1,29 @@
|
|||||||
{
|
{
|
||||||
"add_total_row": 0,
|
"add_total_row": 0,
|
||||||
"creation": "2013-10-22 11:58:16",
|
"creation": "2013-10-22 11:58:16",
|
||||||
"disabled": 0,
|
"disable_prepared_report": 0,
|
||||||
"docstatus": 0,
|
"disabled": 0,
|
||||||
"doctype": "Report",
|
"docstatus": 0,
|
||||||
"idx": 3,
|
"doctype": "Report",
|
||||||
"is_standard": "Yes",
|
"idx": 3,
|
||||||
"modified": "2018-09-26 18:59:46.520731",
|
"is_standard": "Yes",
|
||||||
"modified_by": "Administrator",
|
"modified": "2020-01-22 16:51:56.591110",
|
||||||
"module": "CRM",
|
"modified_by": "Administrator",
|
||||||
"name": "Lead Details",
|
"module": "CRM",
|
||||||
"owner": "Administrator",
|
"name": "Lead Details",
|
||||||
"prepared_report": 0,
|
"owner": "Administrator",
|
||||||
"query": "SELECT\n `tabLead`.name as \"Lead Id:Link/Lead:120\",\n `tabLead`.lead_name as \"Lead Name::120\",\n\t`tabLead`.company_name as \"Company Name::120\",\n\t`tabLead`.status as \"Status::120\",\n\tconcat_ws(', ', \n\t\ttrim(',' from `tabAddress`.address_line1), \n\t\ttrim(',' from tabAddress.address_line2)\n\t) as 'Address::180',\n\t`tabAddress`.state as \"State::100\",\n\t`tabAddress`.pincode as \"Pincode::70\",\n\t`tabAddress`.country as \"Country::100\",\n\t`tabLead`.phone as \"Phone::100\",\n\t`tabLead`.mobile_no as \"Mobile No::100\",\n\t`tabLead`.email_id as \"Email Id::120\",\n\t`tabLead`.lead_owner as \"Lead Owner::120\",\n\t`tabLead`.source as \"Source::120\",\n\t`tabLead`.territory as \"Territory::120\",\n\t`tabLead`.notes as \"Notes::360\",\n `tabLead`.owner as \"Owner:Link/User:120\"\nFROM\n\t`tabLead`\n\tleft join `tabDynamic Link` on (\n\t\t`tabDynamic Link`.link_name=`tabLead`.name\n\t)\n\tleft join `tabAddress` on (\n\t\t`tabAddress`.name=`tabDynamic Link`.parent\n\t)\nWHERE\n\t`tabLead`.docstatus<2\nORDER BY\n\t`tabLead`.name asc",
|
"prepared_report": 0,
|
||||||
"ref_doctype": "Lead",
|
"query": "SELECT\n `tabLead`.name as \"Lead Id:Link/Lead:120\",\n `tabLead`.lead_name as \"Lead Name::120\",\n\t`tabLead`.company_name as \"Company Name::120\",\n\t`tabLead`.status as \"Status::120\",\n\tconcat_ws(', ', \n\t\ttrim(',' from `tabAddress`.address_line1), \n\t\ttrim(',' from tabAddress.address_line2)\n\t) as 'Address::180',\n\t`tabAddress`.state as \"State::100\",\n\t`tabAddress`.pincode as \"Pincode::70\",\n\t`tabAddress`.country as \"Country::100\",\n\t`tabLead`.phone as \"Phone::100\",\n\t`tabLead`.mobile_no as \"Mobile No::100\",\n\t`tabLead`.email_id as \"Email Id::120\",\n\t`tabLead`.lead_owner as \"Lead Owner::120\",\n\t`tabLead`.source as \"Source::120\",\n\t`tabLead`.territory as \"Territory::120\",\n\t`tabLead`.notes as \"Notes::360\",\n `tabLead`.owner as \"Owner:Link/User:120\"\nFROM\n\t`tabLead`\n\tleft join `tabDynamic Link` on (\n\t\t`tabDynamic Link`.link_name=`tabLead`.name \n\t\tand `tabDynamic Link`.parenttype = 'Address'\n\t)\n\tleft join `tabAddress` on (\n\t\t`tabAddress`.name=`tabDynamic Link`.parent\n\t)\nWHERE\n\t`tabLead`.docstatus<2\nORDER BY\n\t`tabLead`.name asc",
|
||||||
"report_name": "Lead Details",
|
"ref_doctype": "Lead",
|
||||||
"report_type": "Query Report",
|
"report_name": "Lead Details",
|
||||||
|
"report_type": "Query Report",
|
||||||
"roles": [
|
"roles": [
|
||||||
{
|
{
|
||||||
"role": "Sales User"
|
"role": "Sales User"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"role": "Sales Manager"
|
"role": "Sales Manager"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"role": "System Manager"
|
"role": "System Manager"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -123,9 +123,11 @@ def get_students(student_group, academic_year, academic_term=None, student_categ
|
|||||||
|
|
||||||
students = frappe.db.sql("""
|
students = frappe.db.sql("""
|
||||||
select pe.student, pe.student_name, pe.program, pe.student_batch_name
|
select pe.student, pe.student_name, pe.program, pe.student_batch_name
|
||||||
from `tabStudent Group Student` sgs, `tabProgram Enrollment` pe
|
from `tabStudent Group Student` sgs, `tabProgram Enrollment` pe, `tabStudent Group` sg
|
||||||
where
|
where
|
||||||
pe.student = sgs.student and pe.academic_year = %s
|
pe.student = sgs.student and pe.academic_year = %s
|
||||||
|
and sg.program = pe.program
|
||||||
|
and sg.name = sgs.parent
|
||||||
and sgs.parent = %s and sgs.active = 1
|
and sgs.parent = %s and sgs.active = 1
|
||||||
{conditions}
|
{conditions}
|
||||||
""".format(conditions=conditions), (academic_year, student_group), as_dict=1)
|
""".format(conditions=conditions), (academic_year, student_group), as_dict=1)
|
||||||
|
|||||||
@@ -49,9 +49,10 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "plaid_env",
|
"fieldname": "plaid_env",
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Select",
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"label": "Plaid Environment"
|
"label": "Plaid Environment",
|
||||||
|
"options": "sandbox\ndevelopment\nproduction"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "column_break_2",
|
"fieldname": "column_break_2",
|
||||||
@@ -69,7 +70,7 @@
|
|||||||
],
|
],
|
||||||
"issingle": 1,
|
"issingle": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2020-01-05 10:00:22.137832",
|
"modified": "2020-02-07 15:21:11.616231",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "ERPNext Integrations",
|
"module": "ERPNext Integrations",
|
||||||
"name": "Plaid Settings",
|
"name": "Plaid Settings",
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ from frappe.model.document import Document
|
|||||||
from erpnext.accounts.doctype.journal_entry.journal_entry import get_default_bank_cash_account
|
from erpnext.accounts.doctype.journal_entry.journal_entry import get_default_bank_cash_account
|
||||||
from erpnext.erpnext_integrations.doctype.plaid_settings.plaid_connector import PlaidConnector
|
from erpnext.erpnext_integrations.doctype.plaid_settings.plaid_connector import PlaidConnector
|
||||||
from frappe.utils import getdate, formatdate, today, add_months
|
from frappe.utils import getdate, formatdate, today, add_months
|
||||||
|
from frappe.desk.doctype.tag.tag import add_tag
|
||||||
|
|
||||||
class PlaidSettings(Document):
|
class PlaidSettings(Document):
|
||||||
pass
|
pass
|
||||||
@@ -53,7 +54,11 @@ def add_institution(token, response):
|
|||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def add_bank_accounts(response, bank, company):
|
def add_bank_accounts(response, bank, company):
|
||||||
response = json.loads(response) if not "accounts" in response else response
|
try:
|
||||||
|
response = json.loads(response)
|
||||||
|
except TypeError:
|
||||||
|
pass
|
||||||
|
|
||||||
bank = json.loads(bank)
|
bank = json.loads(bank)
|
||||||
result = []
|
result = []
|
||||||
|
|
||||||
@@ -129,10 +134,13 @@ def sync_transactions(bank, bank_account):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
transactions = get_transactions(bank=bank, bank_account=bank_account, start_date=start_date, end_date=end_date)
|
transactions = get_transactions(bank=bank, bank_account=bank_account, start_date=start_date, end_date=end_date)
|
||||||
|
|
||||||
result = []
|
result = []
|
||||||
if transactions:
|
for transaction in reversed(transactions):
|
||||||
for transaction in transactions:
|
result += new_bank_transaction(transaction)
|
||||||
result.append(new_bank_transaction(transaction))
|
|
||||||
|
frappe.logger().info("Plaid added {} new Bank Transactions from '{}' between {} and {}".format(
|
||||||
|
len(result), bank_account, start_date, end_date))
|
||||||
|
|
||||||
frappe.db.set_value("Bank Account", bank_account, "last_integration_date", getdate(end_date))
|
frappe.db.set_value("Bank Account", bank_account, "last_integration_date", getdate(end_date))
|
||||||
|
|
||||||
@@ -171,6 +179,13 @@ def new_bank_transaction(transaction):
|
|||||||
|
|
||||||
status = "Pending" if transaction["pending"] == "True" else "Settled"
|
status = "Pending" if transaction["pending"] == "True" else "Settled"
|
||||||
|
|
||||||
|
try:
|
||||||
|
tags = []
|
||||||
|
tags += transaction["category"]
|
||||||
|
tags += ["Plaid Cat. {}".format(transaction["category_id"])]
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
if not frappe.db.exists("Bank Transaction", dict(transaction_id=transaction["transaction_id"])):
|
if not frappe.db.exists("Bank Transaction", dict(transaction_id=transaction["transaction_id"])):
|
||||||
try:
|
try:
|
||||||
new_transaction = frappe.get_doc({
|
new_transaction = frappe.get_doc({
|
||||||
@@ -181,11 +196,16 @@ def new_bank_transaction(transaction):
|
|||||||
"debit": debit,
|
"debit": debit,
|
||||||
"credit": credit,
|
"credit": credit,
|
||||||
"currency": transaction["iso_currency_code"],
|
"currency": transaction["iso_currency_code"],
|
||||||
|
"transaction_id": transaction["transaction_id"],
|
||||||
|
"reference_number": transaction["payment_meta"]["reference_number"],
|
||||||
"description": transaction["name"]
|
"description": transaction["name"]
|
||||||
})
|
})
|
||||||
new_transaction.insert()
|
new_transaction.insert()
|
||||||
new_transaction.submit()
|
new_transaction.submit()
|
||||||
|
|
||||||
|
for tag in tags:
|
||||||
|
add_tag(tag, "Bank Transaction", new_transaction.name)
|
||||||
|
|
||||||
result.append(new_transaction.name)
|
result.append(new_transaction.name)
|
||||||
|
|
||||||
except Exception:
|
except Exception:
|
||||||
@@ -197,7 +217,7 @@ def automatic_synchronization():
|
|||||||
settings = frappe.get_doc("Plaid Settings", "Plaid Settings")
|
settings = frappe.get_doc("Plaid Settings", "Plaid Settings")
|
||||||
|
|
||||||
if settings.enabled == 1 and settings.automatic_sync == 1:
|
if settings.enabled == 1 and settings.automatic_sync == 1:
|
||||||
plaid_accounts = frappe.get_all("Bank Account", filter={"integration_id": ["!=", ""]}, fields=["name", "bank"])
|
plaid_accounts = frappe.get_all("Bank Account", filters={"integration_id": ["!=", ""]}, fields=["name", "bank"])
|
||||||
|
|
||||||
for plaid_account in plaid_accounts:
|
for plaid_account in plaid_accounts:
|
||||||
frappe.enqueue("erpnext.erpnext_integrations.doctype.plaid_settings.plaid_settings.sync_transactions", bank=plaid_account.bank, bank_account=plaid_account.name)
|
frappe.enqueue("erpnext.erpnext_integrations.doctype.plaid_settings.plaid_settings.sync_transactions", bank=plaid_account.bank, bank_account=plaid_account.name)
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -3,17 +3,17 @@
|
|||||||
|
|
||||||
frappe.ui.form.on("Lab Test Template",{
|
frappe.ui.form.on("Lab Test Template",{
|
||||||
lab_test_name: function(frm) {
|
lab_test_name: function(frm) {
|
||||||
if(!frm.doc.lab_test_code)
|
if (!frm.doc.lab_test_code)
|
||||||
frm.set_value("lab_test_code", frm.doc.lab_test_name);
|
frm.set_value("lab_test_code", frm.doc.lab_test_name);
|
||||||
if(!frm.doc.lab_test_description)
|
if (!frm.doc.lab_test_description)
|
||||||
frm.set_value("lab_test_description", frm.doc.lab_test_name);
|
frm.set_value("lab_test_description", frm.doc.lab_test_name);
|
||||||
},
|
},
|
||||||
refresh : function(frm){
|
refresh : function(frm) {
|
||||||
// Restrict Special, Grouped type templates in Child TestGroups
|
// Restrict Special, Grouped type templates in Child TestGroups
|
||||||
frm.set_query("lab_test_template", "lab_test_groups", function() {
|
frm.set_query("lab_test_template", "lab_test_groups", function() {
|
||||||
return {
|
return {
|
||||||
filters: {
|
filters: {
|
||||||
lab_test_template_type:['in',['Single','Compound']]
|
lab_test_template_type: ['in',['Single','Compound']]
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
@@ -23,83 +23,44 @@ frappe.ui.form.on("Lab Test Template",{
|
|||||||
cur_frm.cscript.custom_refresh = function(doc) {
|
cur_frm.cscript.custom_refresh = function(doc) {
|
||||||
cur_frm.set_df_property("lab_test_code", "read_only", doc.__islocal ? 0 : 1);
|
cur_frm.set_df_property("lab_test_code", "read_only", doc.__islocal ? 0 : 1);
|
||||||
|
|
||||||
if(!doc.__islocal) {
|
if (!doc.__islocal) {
|
||||||
cur_frm.add_custom_button(__('Change Template Code'), function() {
|
cur_frm.add_custom_button(__("Change Template Code"), function() {
|
||||||
change_template_code(cur_frm,doc);
|
change_template_code(doc);
|
||||||
} );
|
});
|
||||||
if(doc.disabled == 1){
|
|
||||||
cur_frm.add_custom_button(__('Enable Template'), function() {
|
|
||||||
enable_template(cur_frm);
|
|
||||||
} );
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
cur_frm.add_custom_button(__('Disable Template'), function() {
|
|
||||||
disable_template(cur_frm);
|
|
||||||
} );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var disable_template = function(frm){
|
let change_template_code = function(doc) {
|
||||||
var doc = frm.doc;
|
let d = new frappe.ui.Dialog({
|
||||||
frappe.call({
|
|
||||||
method: "erpnext.healthcare.doctype.lab_test_template.lab_test_template.disable_enable_test_template",
|
|
||||||
args: {status: 1, name: doc.name, is_billable: doc.is_billable},
|
|
||||||
callback: function(){
|
|
||||||
cur_frm.reload_doc();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
var enable_template = function(frm){
|
|
||||||
var doc = frm.doc;
|
|
||||||
frappe.call({
|
|
||||||
method: "erpnext.healthcare.doctype.lab_test_template.lab_test_template.disable_enable_test_template",
|
|
||||||
args: {status: 0, name: doc.name, is_billable: doc.is_billable},
|
|
||||||
callback: function(){
|
|
||||||
cur_frm.reload_doc();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
var change_template_code = function(frm,doc){
|
|
||||||
var d = new frappe.ui.Dialog({
|
|
||||||
title:__("Change Template Code"),
|
title:__("Change Template Code"),
|
||||||
fields:[
|
fields:[
|
||||||
{
|
{
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
"label": "Test Template Code",
|
"label": "Lab Test Template Code",
|
||||||
"fieldname": "Test Code",
|
"fieldname": "lab_test_code",
|
||||||
reqd:1
|
reqd: 1
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldtype": "Button",
|
|
||||||
"label": __("Change Code"),
|
|
||||||
click: function() {
|
|
||||||
var values = d.get_values();
|
|
||||||
if(!values)
|
|
||||||
return;
|
|
||||||
change_test_code_from_template(values["Test Code"],doc);
|
|
||||||
d.hide();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
primary_action: function() {
|
||||||
|
let values = d.get_values();
|
||||||
|
if (values) {
|
||||||
|
frappe.call({
|
||||||
|
"method": "erpnext.healthcare.doctype.lab_test_template.lab_test_template.change_test_code_from_template",
|
||||||
|
"args": {lab_test_code: values.lab_test_code, doc: doc},
|
||||||
|
callback: function (data) {
|
||||||
|
frappe.set_route("Form", "Lab Test Template", data.message);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
d.hide();
|
||||||
|
},
|
||||||
|
primary_action_label: __("Change Template Code")
|
||||||
});
|
});
|
||||||
d.show();
|
d.show();
|
||||||
d.set_values({
|
|
||||||
'Test Code': doc.lab_test_code
|
|
||||||
});
|
|
||||||
|
|
||||||
var change_test_code_from_template = function(lab_test_code,doc){
|
d.set_values({
|
||||||
frappe.call({
|
"lab_test_code": doc.lab_test_code
|
||||||
"method": "erpnext.healthcare.doctype.lab_test_template.lab_test_template.change_test_code_from_template",
|
});
|
||||||
"args": {lab_test_code: lab_test_code, doc: doc},
|
|
||||||
callback: function (data) {
|
|
||||||
frappe.set_route("Form", "Lab Test Template", data.message);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
frappe.ui.form.on("Lab Test Template", "lab_test_name", function(frm){
|
frappe.ui.form.on("Lab Test Template", "lab_test_name", function(frm){
|
||||||
@@ -124,8 +85,8 @@ frappe.ui.form.on("Lab Test Template", "lab_test_description", function(frm){
|
|||||||
});
|
});
|
||||||
|
|
||||||
frappe.ui.form.on("Lab Test Groups", "template_or_new_line", function (frm, cdt, cdn) {
|
frappe.ui.form.on("Lab Test Groups", "template_or_new_line", function (frm, cdt, cdn) {
|
||||||
var child = locals[cdt][cdn];
|
let child = locals[cdt][cdn];
|
||||||
if(child.template_or_new_line =="Add new line"){
|
if (child.template_or_new_line == "Add new line") {
|
||||||
frappe.model.set_value(cdt, cdn, 'lab_test_template', "");
|
frappe.model.set_value(cdt, cdn, 'lab_test_template', "");
|
||||||
frappe.model.set_value(cdt, cdn, 'lab_test_description', "");
|
frappe.model.set_value(cdt, cdn, 'lab_test_description', "");
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -8,59 +8,76 @@ from frappe.model.document import Document
|
|||||||
from frappe import _
|
from frappe import _
|
||||||
|
|
||||||
class LabTestTemplate(Document):
|
class LabTestTemplate(Document):
|
||||||
|
def after_insert(self):
|
||||||
|
if not self.item:
|
||||||
|
create_item_from_template(self)
|
||||||
|
|
||||||
|
def validate(self):
|
||||||
|
self.enable_disable_item()
|
||||||
|
|
||||||
def on_update(self):
|
def on_update(self):
|
||||||
#Item and Price List update --> if (change_in_item)
|
# if change_in_item update Item and Price List
|
||||||
if(self.change_in_item and self.is_billable == 1 and self.item):
|
if self.change_in_item and self.is_billable and self.item:
|
||||||
updating_item(self)
|
self.update_item()
|
||||||
item_price = item_price_exist(self)
|
item_price = self.item_price_exists()
|
||||||
if not item_price:
|
if not item_price:
|
||||||
if(self.lab_test_rate != 0.0):
|
if self.lab_test_rate != 0.0:
|
||||||
price_list_name = frappe.db.get_value("Price List", {"selling": 1})
|
price_list_name = frappe.db.get_value("Price List", {"selling": 1})
|
||||||
if(self.lab_test_rate):
|
if self.lab_test_rate:
|
||||||
make_item_price(self.lab_test_code, price_list_name, self.lab_test_rate)
|
make_item_price(self.lab_test_code, price_list_name, self.lab_test_rate)
|
||||||
else:
|
else:
|
||||||
make_item_price(self.lab_test_code, price_list_name, 0.0)
|
make_item_price(self.lab_test_code, price_list_name, 0.0)
|
||||||
else:
|
else:
|
||||||
frappe.db.set_value("Item Price", item_price, "price_list_rate", self.lab_test_rate)
|
frappe.db.set_value("Item Price", item_price, "price_list_rate", self.lab_test_rate)
|
||||||
|
|
||||||
frappe.db.set_value(self.doctype,self.name,"change_in_item",0)
|
frappe.db.set_value(self.doctype, self.name, "change_in_item", 0)
|
||||||
elif(self.is_billable == 0 and self.item):
|
|
||||||
frappe.db.set_value("Item",self.item,"disabled",1)
|
elif not self.is_billable and self.item:
|
||||||
|
frappe.db.set_value("Item", self.item, "disabled", 1)
|
||||||
|
|
||||||
self.reload()
|
self.reload()
|
||||||
|
|
||||||
def after_insert(self):
|
|
||||||
if not self.item:
|
|
||||||
create_item_from_template(self)
|
|
||||||
|
|
||||||
#Call before delete the template
|
|
||||||
def on_trash(self):
|
def on_trash(self):
|
||||||
# remove template refernce from item and disable item
|
# remove template reference from item and disable item
|
||||||
if(self.item):
|
if self.item:
|
||||||
try:
|
try:
|
||||||
frappe.delete_doc("Item",self.item, force=True)
|
frappe.delete_doc("Item", self.item)
|
||||||
except Exception:
|
except Exception:
|
||||||
frappe.throw(_("""Not permitted. Please disable the Test Template"""))
|
frappe.throw(_("Not permitted. Please disable the Lab Test Template"))
|
||||||
|
|
||||||
def item_price_exist(doc):
|
def enable_disable_item(self):
|
||||||
item_price = frappe.db.exists({
|
if self.is_billable:
|
||||||
"doctype": "Item Price",
|
if self.disabled:
|
||||||
"item_code": doc.lab_test_code})
|
frappe.db.set_value('Item', self.item, 'disabled', 1)
|
||||||
if(item_price):
|
else:
|
||||||
return item_price[0][0]
|
frappe.db.set_value('Item', self.item, 'disabled', 0)
|
||||||
else:
|
|
||||||
return False
|
def update_item(self):
|
||||||
|
item = frappe.get_doc("Item", self.item)
|
||||||
|
if item:
|
||||||
|
item.update({
|
||||||
|
"item_name": self.lab_test_name,
|
||||||
|
"item_group": self.lab_test_group,
|
||||||
|
"disabled": 0,
|
||||||
|
"standard_rate": self.lab_test_rate,
|
||||||
|
"description": self.lab_test_description
|
||||||
|
})
|
||||||
|
item.save()
|
||||||
|
|
||||||
|
def item_price_exists(self):
|
||||||
|
item_price = frappe.db.exists({"doctype": "Item Price", "item_code": self.lab_test_code})
|
||||||
|
if item_price:
|
||||||
|
return item_price[0][0]
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
def updating_item(self):
|
|
||||||
frappe.db.sql("""update `tabItem` set item_name=%s, item_group=%s, disabled=0, standard_rate=%s,
|
|
||||||
description=%s, modified=NOW() where item_code=%s""",
|
|
||||||
(self.lab_test_name, self.lab_test_group , self.lab_test_rate, self.lab_test_description, self.item))
|
|
||||||
|
|
||||||
def create_item_from_template(doc):
|
def create_item_from_template(doc):
|
||||||
if(doc.is_billable == 1):
|
if doc.is_billable:
|
||||||
disabled = 0
|
disabled = 0
|
||||||
else:
|
else:
|
||||||
disabled = 1
|
disabled = 1
|
||||||
#insert item
|
# insert item
|
||||||
item = frappe.get_doc({
|
item = frappe.get_doc({
|
||||||
"doctype": "Item",
|
"doctype": "Item",
|
||||||
"item_code": doc.lab_test_code,
|
"item_code": doc.lab_test_code,
|
||||||
@@ -77,9 +94,9 @@ def create_item_from_template(doc):
|
|||||||
"stock_uom": "Unit"
|
"stock_uom": "Unit"
|
||||||
}).insert(ignore_permissions=True)
|
}).insert(ignore_permissions=True)
|
||||||
|
|
||||||
#insert item price
|
# insert item price
|
||||||
#get item price list to insert item price
|
# get item price list to insert item price
|
||||||
if(doc.lab_test_rate != 0.0):
|
if doc.lab_test_rate != 0.0:
|
||||||
price_list_name = frappe.db.get_value("Price List", {"selling": 1})
|
price_list_name = frappe.db.get_value("Price List", {"selling": 1})
|
||||||
if(doc.lab_test_rate):
|
if(doc.lab_test_rate):
|
||||||
make_item_price(item.name, price_list_name, doc.lab_test_rate)
|
make_item_price(item.name, price_list_name, doc.lab_test_rate)
|
||||||
@@ -88,10 +105,10 @@ def create_item_from_template(doc):
|
|||||||
make_item_price(item.name, price_list_name, 0.0)
|
make_item_price(item.name, price_list_name, 0.0)
|
||||||
item.standard_rate = 0.0
|
item.standard_rate = 0.0
|
||||||
item.save(ignore_permissions = True)
|
item.save(ignore_permissions = True)
|
||||||
#Set item to the template
|
# Set item in the template
|
||||||
frappe.db.set_value("Lab Test Template", doc.name, "item", item.name)
|
frappe.db.set_value("Lab Test Template", doc.name, "item", item.name)
|
||||||
|
|
||||||
doc.reload() #refresh the doc after insert.
|
doc.reload()
|
||||||
|
|
||||||
def make_item_price(item, price_list_name, item_price):
|
def make_item_price(item, price_list_name, item_price):
|
||||||
frappe.get_doc({
|
frappe.get_doc({
|
||||||
@@ -103,22 +120,13 @@ def make_item_price(item, price_list_name, item_price):
|
|||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def change_test_code_from_template(lab_test_code, doc):
|
def change_test_code_from_template(lab_test_code, doc):
|
||||||
args = json.loads(doc)
|
doc = frappe._dict(json.loads(doc))
|
||||||
doc = frappe._dict(args)
|
|
||||||
|
|
||||||
item_exist = frappe.db.exists({
|
if frappe.db.exists({ "doctype": "Item", "item_code": lab_test_code}):
|
||||||
"doctype": "Item",
|
frappe.throw(_("Lab Test Item {0} already exist").format(lab_test_code))
|
||||||
"item_code": lab_test_code})
|
|
||||||
if(item_exist):
|
|
||||||
frappe.throw(_("Code {0} already exist").format(lab_test_code))
|
|
||||||
else:
|
else:
|
||||||
frappe.rename_doc("Item", doc.name, lab_test_code, ignore_permissions = True)
|
rename_doc("Item", doc.name, lab_test_code, ignore_permissions=True)
|
||||||
frappe.db.set_value("Lab Test Template",doc.name,"lab_test_code",lab_test_code)
|
frappe.db.set_value("Lab Test Template", doc.name, "lab_test_code", lab_test_code)
|
||||||
frappe.rename_doc("Lab Test Template", doc.name, lab_test_code, ignore_permissions = True)
|
frappe.db.set_value("Lab Test Template", doc.name, "lab_test_name", lab_test_code)
|
||||||
|
rename_doc("Lab Test Template", doc.name, lab_test_code, ignore_permissions=True)
|
||||||
return lab_test_code
|
return lab_test_code
|
||||||
|
|
||||||
@frappe.whitelist()
|
|
||||||
def disable_enable_test_template(status, name, is_billable):
|
|
||||||
frappe.db.set_value("Lab Test Template",name,"disabled",status)
|
|
||||||
if(is_billable == 1):
|
|
||||||
frappe.db.set_value("Item",name,"disabled",status)
|
|
||||||
|
|||||||
@@ -3,13 +3,5 @@
|
|||||||
*/
|
*/
|
||||||
frappe.listview_settings['Lab Test Template'] = {
|
frappe.listview_settings['Lab Test Template'] = {
|
||||||
add_fields: ["lab_test_name", "lab_test_code", "lab_test_rate"],
|
add_fields: ["lab_test_name", "lab_test_code", "lab_test_rate"],
|
||||||
filters:[["disabled","=",0]],
|
filters: [["disabled", "=", 0]]
|
||||||
/* get_indicator: function(doc) {
|
|
||||||
if(doc.disabled==1){
|
|
||||||
return [__("Disabled"), "red", "disabled,=,Disabled"];
|
|
||||||
}
|
|
||||||
if(doc.disabled==0){
|
|
||||||
return [__("Enabled"), "green", "disabled,=,0"];
|
|
||||||
}
|
|
||||||
} */
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ class Attendance(Document):
|
|||||||
def validate_duplicate_record(self):
|
def validate_duplicate_record(self):
|
||||||
res = frappe.db.sql("""select name from `tabAttendance` where employee = %s and attendance_date = %s
|
res = frappe.db.sql("""select name from `tabAttendance` where employee = %s and attendance_date = %s
|
||||||
and name != %s and docstatus != 2""",
|
and name != %s and docstatus != 2""",
|
||||||
(self.employee, self.attendance_date, self.name))
|
(self.employee, getdate(self.attendance_date), self.name))
|
||||||
if res:
|
if res:
|
||||||
frappe.throw(_("Attendance for employee {0} is already marked").format(self.employee))
|
frappe.throw(_("Attendance for employee {0} is already marked").format(self.employee))
|
||||||
|
|
||||||
|
|||||||
@@ -265,7 +265,7 @@
|
|||||||
"bold": 1,
|
"bold": 1,
|
||||||
"fieldname": "person_to_be_contacted",
|
"fieldname": "person_to_be_contacted",
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
"label": "Emergency Contact"
|
"label": "Emergency Contact Name"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "relation",
|
"fieldname": "relation",
|
||||||
@@ -782,7 +782,7 @@
|
|||||||
"icon": "fa fa-user",
|
"icon": "fa fa-user",
|
||||||
"idx": 24,
|
"idx": 24,
|
||||||
"image_field": "image",
|
"image_field": "image",
|
||||||
"modified": "2019-09-12 14:21:12.711280",
|
"modified": "2020-01-09 04:23:55.611366",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "HR",
|
"module": "HR",
|
||||||
"name": "Employee",
|
"name": "Employee",
|
||||||
|
|||||||
@@ -2,7 +2,9 @@
|
|||||||
// For license information, please see license.txt
|
// For license information, please see license.txt
|
||||||
|
|
||||||
frappe.ui.form.on('Employee Checkin', {
|
frappe.ui.form.on('Employee Checkin', {
|
||||||
// refresh: function(frm) {
|
setup: (frm) => {
|
||||||
|
if(!frm.doc.time) {
|
||||||
// }
|
frm.set_value("time", frappe.datetime.now_datetime());
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
|
"actions": [],
|
||||||
"allow_import": 1,
|
"allow_import": 1,
|
||||||
"autoname": "EMP-CKIN-.MM.-.YYYY.-.######",
|
"autoname": "EMP-CKIN-.MM.-.YYYY.-.######",
|
||||||
"creation": "2019-06-10 11:56:34.536413",
|
"creation": "2019-06-10 11:56:34.536413",
|
||||||
@@ -23,7 +24,6 @@
|
|||||||
{
|
{
|
||||||
"fieldname": "employee",
|
"fieldname": "employee",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"in_list_view": 1,
|
|
||||||
"label": "Employee",
|
"label": "Employee",
|
||||||
"options": "Employee",
|
"options": "Employee",
|
||||||
"reqd": 1
|
"reqd": 1
|
||||||
@@ -32,14 +32,17 @@
|
|||||||
"fetch_from": "employee.employee_name",
|
"fetch_from": "employee.employee_name",
|
||||||
"fieldname": "employee_name",
|
"fieldname": "employee_name",
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
|
"in_list_view": 1,
|
||||||
"label": "Employee Name",
|
"label": "Employee Name",
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "log_type",
|
"fieldname": "log_type",
|
||||||
"fieldtype": "Select",
|
"fieldtype": "Select",
|
||||||
|
"in_list_view": 1,
|
||||||
"label": "Log Type",
|
"label": "Log Type",
|
||||||
"options": "\nIN\nOUT"
|
"options": "\nIN\nOUT",
|
||||||
|
"reqd": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "shift",
|
"fieldname": "shift",
|
||||||
@@ -58,6 +61,7 @@
|
|||||||
"fieldtype": "Datetime",
|
"fieldtype": "Datetime",
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"label": "Time",
|
"label": "Time",
|
||||||
|
"permlevel": 1,
|
||||||
"reqd": 1
|
"reqd": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -103,7 +107,8 @@
|
|||||||
"label": "Shift Actual End"
|
"label": "Shift Actual End"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"modified": "2019-07-23 23:47:33.975263",
|
"links": [],
|
||||||
|
"modified": "2020-01-23 04:57:42.551355",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "HR",
|
"module": "HR",
|
||||||
"name": "Employee Checkin",
|
"name": "Employee Checkin",
|
||||||
@@ -147,9 +152,58 @@
|
|||||||
"role": "HR User",
|
"role": "HR User",
|
||||||
"share": 1,
|
"share": 1,
|
||||||
"write": 1
|
"write": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"create": 1,
|
||||||
|
"delete": 1,
|
||||||
|
"read": 1,
|
||||||
|
"role": "Employee",
|
||||||
|
"write": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"delete": 1,
|
||||||
|
"email": 1,
|
||||||
|
"export": 1,
|
||||||
|
"permlevel": 1,
|
||||||
|
"print": 1,
|
||||||
|
"read": 1,
|
||||||
|
"report": 1,
|
||||||
|
"role": "System Manager",
|
||||||
|
"share": 1,
|
||||||
|
"write": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"delete": 1,
|
||||||
|
"email": 1,
|
||||||
|
"export": 1,
|
||||||
|
"permlevel": 1,
|
||||||
|
"print": 1,
|
||||||
|
"read": 1,
|
||||||
|
"report": 1,
|
||||||
|
"role": "HR Manager",
|
||||||
|
"share": 1,
|
||||||
|
"write": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"delete": 1,
|
||||||
|
"email": 1,
|
||||||
|
"export": 1,
|
||||||
|
"permlevel": 1,
|
||||||
|
"print": 1,
|
||||||
|
"read": 1,
|
||||||
|
"report": 1,
|
||||||
|
"role": "HR User",
|
||||||
|
"share": 1,
|
||||||
|
"write": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"permlevel": 1,
|
||||||
|
"read": 1,
|
||||||
|
"role": "Employee"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "ASC",
|
"sort_order": "ASC",
|
||||||
|
"title_field": "employee_name",
|
||||||
"track_changes": 1
|
"track_changes": 1
|
||||||
}
|
}
|
||||||
@@ -104,11 +104,16 @@ frappe.ui.form.on("Leave Application", {
|
|||||||
},
|
},
|
||||||
|
|
||||||
half_day: function(frm) {
|
half_day: function(frm) {
|
||||||
if (frm.doc.from_date == frm.doc.to_date) {
|
if (frm.doc.half_day) {
|
||||||
frm.set_value("half_day_date", frm.doc.from_date);
|
if (frm.doc.from_date == frm.doc.to_date) {
|
||||||
|
frm.set_value("half_day_date", frm.doc.from_date);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
frm.trigger("half_day_datepicker");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
frm.trigger("half_day_datepicker");
|
frm.set_value("half_day_date", "");
|
||||||
}
|
}
|
||||||
frm.trigger("calculate_total_days");
|
frm.trigger("calculate_total_days");
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -520,8 +520,7 @@ def get_pending_leaves_for_period(employee, leave_type, from_date, to_date):
|
|||||||
|
|
||||||
def get_remaining_leaves(allocation, leaves_taken, date, expiry):
|
def get_remaining_leaves(allocation, leaves_taken, date, expiry):
|
||||||
''' Returns minimum leaves remaining after comparing with remaining days for allocation expiry '''
|
''' Returns minimum leaves remaining after comparing with remaining days for allocation expiry '''
|
||||||
def _get_remaining_leaves(allocated_leaves, end_date):
|
def _get_remaining_leaves(remaining_leaves, end_date):
|
||||||
remaining_leaves = flt(allocated_leaves) + flt(leaves_taken)
|
|
||||||
|
|
||||||
if remaining_leaves > 0:
|
if remaining_leaves > 0:
|
||||||
remaining_days = date_diff(end_date, date) + 1
|
remaining_days = date_diff(end_date, date) + 1
|
||||||
@@ -529,10 +528,11 @@ def get_remaining_leaves(allocation, leaves_taken, date, expiry):
|
|||||||
|
|
||||||
return remaining_leaves
|
return remaining_leaves
|
||||||
|
|
||||||
total_leaves = allocation.total_leaves_allocated
|
total_leaves = flt(allocation.total_leaves_allocated) + flt(leaves_taken)
|
||||||
|
|
||||||
if expiry and allocation.unused_leaves:
|
if expiry and allocation.unused_leaves:
|
||||||
remaining_leaves = _get_remaining_leaves(allocation.unused_leaves, expiry)
|
remaining_leaves = flt(allocation.unused_leaves) + flt(leaves_taken)
|
||||||
|
remaining_leaves = _get_remaining_leaves(remaining_leaves, expiry)
|
||||||
|
|
||||||
total_leaves = flt(allocation.new_leaves_allocated) + flt(remaining_leaves)
|
total_leaves = flt(allocation.new_leaves_allocated) + flt(remaining_leaves)
|
||||||
|
|
||||||
|
|||||||
@@ -409,7 +409,7 @@ class TestLeaveApplication(unittest.TestCase):
|
|||||||
|
|
||||||
self.assertEqual(get_leave_balance_on(employee.name, leave_type.name, nowdate(), add_days(nowdate(), 8)), 21)
|
self.assertEqual(get_leave_balance_on(employee.name, leave_type.name, nowdate(), add_days(nowdate(), 8)), 21)
|
||||||
|
|
||||||
def test_earned_leave(self):
|
def test_earned_leaves_creation(self):
|
||||||
leave_period = get_leave_period()
|
leave_period = get_leave_period()
|
||||||
employee = get_employee()
|
employee = get_employee()
|
||||||
leave_type = 'Test Earned Leave Type'
|
leave_type = 'Test Earned Leave Type'
|
||||||
@@ -437,6 +437,14 @@ class TestLeaveApplication(unittest.TestCase):
|
|||||||
i += 1
|
i += 1
|
||||||
self.assertEqual(get_leave_balance_on(employee.name, leave_type, nowdate()), 6)
|
self.assertEqual(get_leave_balance_on(employee.name, leave_type, nowdate()), 6)
|
||||||
|
|
||||||
|
# validate earned leaves creation without maximum leaves
|
||||||
|
frappe.db.set_value('Leave Type', leave_type, 'max_leaves_allowed', 0)
|
||||||
|
i = 0
|
||||||
|
while(i<6):
|
||||||
|
allocate_earned_leaves()
|
||||||
|
i += 1
|
||||||
|
self.assertEqual(get_leave_balance_on(employee.name, leave_type, nowdate()), 9)
|
||||||
|
|
||||||
# test to not consider current leave in leave balance while submitting
|
# test to not consider current leave in leave balance while submitting
|
||||||
def test_current_leave_on_submit(self):
|
def test_current_leave_on_submit(self):
|
||||||
employee = get_employee()
|
employee = get_employee()
|
||||||
@@ -616,4 +624,4 @@ def allocate_leaves(employee, leave_period, leave_type, new_leaves_allocated, el
|
|||||||
"docstatus": 1
|
"docstatus": 1
|
||||||
}).insert()
|
}).insert()
|
||||||
|
|
||||||
allocate_leave.submit()
|
allocate_leave.submit()
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ frappe.ui.form.on('Salary Structure', {
|
|||||||
frm.trigger("toggle_fields");
|
frm.trigger("toggle_fields");
|
||||||
frm.fields_dict['earnings'].grid.set_column_disp("default_amount", false);
|
frm.fields_dict['earnings'].grid.set_column_disp("default_amount", false);
|
||||||
frm.fields_dict['deductions'].grid.set_column_disp("default_amount", false);
|
frm.fields_dict['deductions'].grid.set_column_disp("default_amount", false);
|
||||||
|
|
||||||
if(frm.doc.docstatus === 1) {
|
if(frm.doc.docstatus === 1) {
|
||||||
frm.add_custom_button(__("Preview Salary Slip"), function() {
|
frm.add_custom_button(__("Preview Salary Slip"), function() {
|
||||||
frm.trigger('preview_salary_slip');
|
frm.trigger('preview_salary_slip');
|
||||||
@@ -75,6 +75,7 @@ frappe.ui.form.on('Salary Structure', {
|
|||||||
title: __("Assign to Employees"),
|
title: __("Assign to Employees"),
|
||||||
fields: [
|
fields: [
|
||||||
{fieldname: "sec_break", fieldtype: "Section Break", label: __("Filter Employees By (Optional)")},
|
{fieldname: "sec_break", fieldtype: "Section Break", label: __("Filter Employees By (Optional)")},
|
||||||
|
{fieldname: "company", fieldtype: "Link", options: "Company", label: __("Company"), default: frm.doc.company, read_only:1},
|
||||||
{fieldname: "grade", fieldtype: "Link", options: "Employee Grade", label: __("Employee Grade")},
|
{fieldname: "grade", fieldtype: "Link", options: "Employee Grade", label: __("Employee Grade")},
|
||||||
{fieldname:'department', fieldtype:'Link', options: 'Department', label: __('Department')},
|
{fieldname:'department', fieldtype:'Link', options: 'Department', label: __('Department')},
|
||||||
{fieldname:'designation', fieldtype:'Link', options: 'Designation', label: __('Designation')},
|
{fieldname:'designation', fieldtype:'Link', options: 'Designation', label: __('Designation')},
|
||||||
@@ -87,7 +88,6 @@ frappe.ui.form.on('Salary Structure', {
|
|||||||
],
|
],
|
||||||
primary_action: function() {
|
primary_action: function() {
|
||||||
var data = d.get_values();
|
var data = d.get_values();
|
||||||
|
|
||||||
frappe.call({
|
frappe.call({
|
||||||
doc: frm.doc,
|
doc: frm.doc,
|
||||||
method: "assign_salary_structure",
|
method: "assign_salary_structure",
|
||||||
|
|||||||
@@ -81,24 +81,24 @@ class SalaryStructure(Document):
|
|||||||
return employees
|
return employees
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def assign_salary_structure(self, grade=None, department=None, designation=None,employee=None,
|
def assign_salary_structure(self, company=None, grade=None, department=None, designation=None,employee=None,
|
||||||
from_date=None, base=None,variable=None):
|
from_date=None, base=None,variable=None):
|
||||||
employees = self.get_employees(grade= grade,department= department,designation= designation,name=employee)
|
employees = self.get_employees(company= company, grade= grade,department= department,designation= designation,name=employee)
|
||||||
|
|
||||||
if employees:
|
if employees:
|
||||||
if len(employees) > 20:
|
if len(employees) > 20:
|
||||||
frappe.enqueue(assign_salary_structure_for_employees, timeout=600,
|
frappe.enqueue(assign_salary_structure_for_employees, timeout=600,
|
||||||
employees=employees, salary_structure=self,from_date=from_date, base=base,variable=variable)
|
employees=employees, salary_structure=self,from_date=from_date, base=base,variable=variable)
|
||||||
else:
|
else:
|
||||||
assign_salary_structure_for_employees(employees, self,from_date=from_date, base=base,variable=variable)
|
assign_salary_structure_for_employees(employees, self, from_date=from_date, base=base,variable=variable)
|
||||||
else:
|
else:
|
||||||
frappe.msgprint(_("No Employee Found"))
|
frappe.msgprint(_("No Employee Found"))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def assign_salary_structure_for_employees(employees, salary_structure,from_date=None, base=None,variable=None):
|
def assign_salary_structure_for_employees(employees, salary_structure, from_date=None, base=None,variable=None):
|
||||||
salary_structures_assignments = []
|
salary_structures_assignments = []
|
||||||
existing_assignments_for = get_existing_assignments(employees, salary_structure.name,from_date)
|
existing_assignments_for = get_existing_assignments(employees, salary_structure, from_date)
|
||||||
count=0
|
count=0
|
||||||
for employee in employees:
|
for employee in employees:
|
||||||
if employee in existing_assignments_for:
|
if employee in existing_assignments_for:
|
||||||
@@ -117,6 +117,7 @@ def create_salary_structures_assignment(employee, salary_structure, from_date, b
|
|||||||
assignment = frappe.new_doc("Salary Structure Assignment")
|
assignment = frappe.new_doc("Salary Structure Assignment")
|
||||||
assignment.employee = employee
|
assignment.employee = employee
|
||||||
assignment.salary_structure = salary_structure.name
|
assignment.salary_structure = salary_structure.name
|
||||||
|
assignment.company = salary_structure.company
|
||||||
assignment.from_date = from_date
|
assignment.from_date = from_date
|
||||||
assignment.base = base
|
assignment.base = base
|
||||||
assignment.variable = variable
|
assignment.variable = variable
|
||||||
@@ -125,12 +126,12 @@ def create_salary_structures_assignment(employee, salary_structure, from_date, b
|
|||||||
return assignment.name
|
return assignment.name
|
||||||
|
|
||||||
|
|
||||||
def get_existing_assignments(employees, salary_structure,from_date):
|
def get_existing_assignments(employees, salary_structure, from_date):
|
||||||
salary_structures_assignments = frappe.db.sql_list("""
|
salary_structures_assignments = frappe.db.sql_list("""
|
||||||
select distinct employee from `tabSalary Structure Assignment`
|
select distinct employee from `tabSalary Structure Assignment`
|
||||||
where salary_structure=%s and employee in (%s)
|
where salary_structure=%s and employee in (%s)
|
||||||
and from_date=%s and docstatus=1
|
and from_date=%s and company= %s and docstatus=1
|
||||||
""" % ('%s', ', '.join(['%s']*len(employees)),'%s'), [salary_structure] + employees+[from_date])
|
""" % ('%s', ', '.join(['%s']*len(employees)),'%s', '%s'), [salary_structure.name] + employees+[from_date]+[salary_structure.company])
|
||||||
if salary_structures_assignments:
|
if salary_structures_assignments:
|
||||||
frappe.msgprint(_("Skipping Salary Structure Assignment for the following employees, as Salary Structure Assignment records already exists against them. {0}")
|
frappe.msgprint(_("Skipping Salary Structure Assignment for the following employees, as Salary Structure Assignment records already exists against them. {0}")
|
||||||
.format("\n".join(salary_structures_assignments)))
|
.format("\n".join(salary_structures_assignments)))
|
||||||
@@ -170,7 +171,7 @@ def make_salary_slip(source_name, target_doc = None, employee = None, as_print =
|
|||||||
def get_employees(salary_structure):
|
def get_employees(salary_structure):
|
||||||
employees = frappe.get_list('Salary Structure Assignment',
|
employees = frappe.get_list('Salary Structure Assignment',
|
||||||
filters={'salary_structure': salary_structure, 'docstatus': 1}, fields=['employee'])
|
filters={'salary_structure': salary_structure, 'docstatus': 1}, fields=['employee'])
|
||||||
|
|
||||||
if not employees:
|
if not employees:
|
||||||
frappe.throw(_("There's no Employee with Salary Structure: {0}. \
|
frappe.throw(_("There's no Employee with Salary Structure: {0}. \
|
||||||
Assign {1} to an Employee to preview Salary Slip").format(salary_structure, salary_structure))
|
Assign {1} to an Employee to preview Salary Slip").format(salary_structure, salary_structure))
|
||||||
|
|||||||
@@ -316,7 +316,9 @@ def allocate_earned_leaves():
|
|||||||
|
|
||||||
allocation = frappe.get_doc('Leave Allocation', allocation.name)
|
allocation = frappe.get_doc('Leave Allocation', allocation.name)
|
||||||
new_allocation = flt(allocation.total_leaves_allocated) + flt(earned_leaves)
|
new_allocation = flt(allocation.total_leaves_allocated) + flt(earned_leaves)
|
||||||
new_allocation = new_allocation if new_allocation <= e_leave_type.max_leaves_allowed else e_leave_type.max_leaves_allowed
|
|
||||||
|
if new_allocation > e_leave_type.max_leaves_allowed and e_leave_type.max_leaves_allowed > 0:
|
||||||
|
new_allocation = e_leave_type.max_leaves_allowed
|
||||||
|
|
||||||
if new_allocation == allocation.total_leaves_allocated:
|
if new_allocation == allocation.total_leaves_allocated:
|
||||||
continue
|
continue
|
||||||
|
|||||||
@@ -193,7 +193,7 @@ class MaintenanceSchedule(TransactionBase):
|
|||||||
|
|
||||||
if sr_details.amc_expiry_date and getdate(sr_details.amc_expiry_date) >= getdate(amc_start_date):
|
if sr_details.amc_expiry_date and getdate(sr_details.amc_expiry_date) >= getdate(amc_start_date):
|
||||||
throw(_("Serial No {0} is under maintenance contract upto {1}")
|
throw(_("Serial No {0} is under maintenance contract upto {1}")
|
||||||
.format(serial_no, sr_details.amc_start_date))
|
.format(serial_no, sr_details.amc_expiry_date))
|
||||||
|
|
||||||
if not sr_details.warehouse and sr_details.delivery_date and \
|
if not sr_details.warehouse and sr_details.delivery_date and \
|
||||||
getdate(sr_details.delivery_date) >= getdate(amc_start_date):
|
getdate(sr_details.delivery_date) >= getdate(amc_start_date):
|
||||||
|
|||||||
@@ -588,7 +588,7 @@ class BOM(WebsiteGenerator):
|
|||||||
for d in self.operations:
|
for d in self.operations:
|
||||||
if not d.description:
|
if not d.description:
|
||||||
d.description = frappe.db.get_value('Operation', d.operation, 'description')
|
d.description = frappe.db.get_value('Operation', d.operation, 'description')
|
||||||
if not d.batch_size > 0:
|
if not d.batch_size or d.batch_size <= 0:
|
||||||
d.batch_size = 1
|
d.batch_size = 1
|
||||||
|
|
||||||
def get_list_context(context):
|
def get_list_context(context):
|
||||||
|
|||||||
@@ -625,7 +625,6 @@ def get_items_for_material_requests(doc, ignore_existing_ordered_qty=None):
|
|||||||
for data in po_items:
|
for data in po_items:
|
||||||
planned_qty = data.get('required_qty') or data.get('planned_qty')
|
planned_qty = data.get('required_qty') or data.get('planned_qty')
|
||||||
ignore_existing_ordered_qty = data.get('ignore_existing_ordered_qty') or ignore_existing_ordered_qty
|
ignore_existing_ordered_qty = data.get('ignore_existing_ordered_qty') or ignore_existing_ordered_qty
|
||||||
warehouse = data.get("warehouse") or warehouse
|
|
||||||
|
|
||||||
item_details = {}
|
item_details = {}
|
||||||
if data.get("bom") or data.get("bom_no"):
|
if data.get("bom") or data.get("bom_no"):
|
||||||
@@ -729,6 +728,6 @@ def get_sub_assembly_items(bom_no, bom_data):
|
|||||||
})
|
})
|
||||||
|
|
||||||
bom_item = bom_data.get(key)
|
bom_item = bom_data.get(key)
|
||||||
bom_item["stock_qty"] += d.stock_qty
|
bom_item["stock_qty"] += d.stock_qty / d.parent_bom_qty
|
||||||
|
|
||||||
get_sub_assembly_items(bom_item.get("bom_no"), bom_data)
|
get_sub_assembly_items(bom_item.get("bom_no"), bom_data)
|
||||||
|
|||||||
@@ -648,3 +648,5 @@ erpnext.patches.v12_0.update_owner_fields_in_acc_dimension_custom_fields
|
|||||||
erpnext.patches.v12_0.remove_denied_leaves_from_leave_ledger
|
erpnext.patches.v12_0.remove_denied_leaves_from_leave_ledger
|
||||||
erpnext.patches.v12_0.update_price_or_product_discount
|
erpnext.patches.v12_0.update_price_or_product_discount
|
||||||
erpnext.patches.v12_0.add_export_type_field_in_party_master
|
erpnext.patches.v12_0.add_export_type_field_in_party_master
|
||||||
|
erpnext.patches.v12_0.rename_bank_reconciliation_fields # 2020-01-22
|
||||||
|
erpnext.patches.v12_0.create_irs_1099_field_united_states
|
||||||
|
|||||||
10
erpnext/patches/v12_0/create_irs_1099_field_united_states.py
Normal file
10
erpnext/patches/v12_0/create_irs_1099_field_united_states.py
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
from __future__ import unicode_literals
|
||||||
|
import frappe
|
||||||
|
from erpnext.regional.united_states.setup import make_custom_fields
|
||||||
|
|
||||||
|
def execute():
|
||||||
|
company = frappe.get_all('Company', filters = {'country': 'United States'})
|
||||||
|
if not company:
|
||||||
|
return
|
||||||
|
|
||||||
|
make_custom_fields()
|
||||||
14
erpnext/patches/v12_0/rename_bank_reconciliation_fields.py
Normal file
14
erpnext/patches/v12_0/rename_bank_reconciliation_fields.py
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
# Copyright (c) 2020, Frappe and Contributors
|
||||||
|
# License: GNU General Public License v3. See license.txt
|
||||||
|
|
||||||
|
import frappe
|
||||||
|
|
||||||
|
def _rename_single_field(**kwargs):
|
||||||
|
count = frappe.db.sql("SELECT COUNT(*) FROM tabSingles WHERE doctype='{doctype}' AND field='{new_name}';".format(**kwargs))[0][0] #nosec
|
||||||
|
if count == 0:
|
||||||
|
frappe.db.sql("UPDATE tabSingles SET field='{new_name}' WHERE doctype='{doctype}' AND field='{old_name}';".format(**kwargs)) #nosec
|
||||||
|
|
||||||
|
def execute():
|
||||||
|
_rename_single_field(doctype = "Bank Reconciliation", old_name = "bank_account" , new_name = "account")
|
||||||
|
_rename_single_field(doctype = "Bank Reconciliation", old_name = "bank_account_no", new_name = "bank_account")
|
||||||
|
frappe.reload_doc("Accounts", "doctype", "Bank Reconciliation")
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import frappe
|
import frappe
|
||||||
|
import numpy as np
|
||||||
from erpnext.portal.product_configurator.item_variants_cache import ItemVariantsCacheManager
|
from erpnext.portal.product_configurator.item_variants_cache import ItemVariantsCacheManager
|
||||||
|
|
||||||
def get_field_filter_data():
|
def get_field_filter_data():
|
||||||
@@ -172,6 +173,7 @@ def get_attributes_and_values(item_code):
|
|||||||
|
|
||||||
item_attribute_values = frappe.db.get_all('Item Attribute Value',
|
item_attribute_values = frappe.db.get_all('Item Attribute Value',
|
||||||
['parent', 'attribute_value', 'idx'], order_by='parent asc, idx asc')
|
['parent', 'attribute_value', 'idx'], order_by='parent asc, idx asc')
|
||||||
|
item_attribute_values += get_numeric_values()
|
||||||
ordered_attribute_value_map = frappe._dict()
|
ordered_attribute_value_map = frappe._dict()
|
||||||
for iv in item_attribute_values:
|
for iv in item_attribute_values:
|
||||||
ordered_attribute_value_map.setdefault(iv.parent, []).append(iv.attribute_value)
|
ordered_attribute_value_map.setdefault(iv.parent, []).append(iv.attribute_value)
|
||||||
@@ -184,6 +186,23 @@ def get_attributes_and_values(item_code):
|
|||||||
|
|
||||||
return attributes
|
return attributes
|
||||||
|
|
||||||
|
def get_numeric_values():
|
||||||
|
attribute_values_list = []
|
||||||
|
numeric_attributes = frappe.get_list("Item Attribute", fields=['name', 'from_range', 'to_range', 'increment'], filters={"numeric_values": 1})
|
||||||
|
for attribute in numeric_attributes:
|
||||||
|
from_range = attribute["from_range"]
|
||||||
|
to_range = attribute['to_range'] + attribute['increment']
|
||||||
|
increment = attribute['increment']
|
||||||
|
values = list(np.arange(from_range, to_range, increment))
|
||||||
|
|
||||||
|
for idx, val in enumerate(values):
|
||||||
|
attribute_values_list.append(frappe._dict({
|
||||||
|
"parent": attribute.get("name"),
|
||||||
|
"attribute_value": str(int(val)) if val.is_integer() else str(val),
|
||||||
|
"idx": idx
|
||||||
|
}))
|
||||||
|
return attribute_values_list
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist(allow_guest=True)
|
@frappe.whitelist(allow_guest=True)
|
||||||
def get_next_attribute_and_values(item_code, selected_attributes):
|
def get_next_attribute_and_values(item_code, selected_attributes):
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
|
"actions": [],
|
||||||
"creation": "2016-03-25 02:52:19.283003",
|
"creation": "2016-03-25 02:52:19.283003",
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
"editable_grid": 1,
|
"editable_grid": 1,
|
||||||
@@ -46,6 +47,7 @@
|
|||||||
"fetch_from": "user.full_name",
|
"fetch_from": "user.full_name",
|
||||||
"fieldname": "full_name",
|
"fieldname": "full_name",
|
||||||
"fieldtype": "Read Only",
|
"fieldtype": "Read Only",
|
||||||
|
"in_list_view": 1,
|
||||||
"label": "Full Name"
|
"label": "Full Name"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -55,7 +57,7 @@
|
|||||||
"label": "Welcome email sent"
|
"label": "Welcome email sent"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"columns": 1,
|
"columns": 2,
|
||||||
"default": "0",
|
"default": "0",
|
||||||
"fieldname": "view_attachments",
|
"fieldname": "view_attachments",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
@@ -74,7 +76,8 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"modified": "2019-07-15 19:37:26.942294",
|
"links": [],
|
||||||
|
"modified": "2020-02-09 23:26:50.321417",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Projects",
|
"module": "Projects",
|
||||||
"name": "Project User",
|
"name": "Project User",
|
||||||
|
|||||||
@@ -56,8 +56,8 @@ class Task(NestedSet):
|
|||||||
def validate_status(self):
|
def validate_status(self):
|
||||||
if self.status!=self.get_db_value("status") and self.status == "Completed":
|
if self.status!=self.get_db_value("status") and self.status == "Completed":
|
||||||
for d in self.depends_on:
|
for d in self.depends_on:
|
||||||
if frappe.db.get_value("Task", d.task, "status") != "Completed":
|
if frappe.db.get_value("Task", d.task, "status") not in ("Completed", "Cancelled"):
|
||||||
frappe.throw(_("Cannot close task {0} as its dependant task {1} is not closed.").format(frappe.bold(self.name), frappe.bold(d.task)))
|
frappe.throw(_("Cannot complete task {0} as its dependant tasks {1} are not completed / cancelled.").format(frappe.bold(self.name), frappe.bold(d.task)))
|
||||||
|
|
||||||
close_all_assignments(self.doctype, self.name)
|
close_all_assignments(self.doctype, self.name)
|
||||||
|
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ $.extend(frappe.breadcrumbs.preferred, {
|
|||||||
"Territory": "Selling",
|
"Territory": "Selling",
|
||||||
"Sales Person": "Selling",
|
"Sales Person": "Selling",
|
||||||
"Sales Partner": "Selling",
|
"Sales Partner": "Selling",
|
||||||
"Brand": "Selling"
|
"Brand": "Stock"
|
||||||
});
|
});
|
||||||
|
|
||||||
$.extend(frappe.breadcrumbs.module_map, {
|
$.extend(frappe.breadcrumbs.module_map, {
|
||||||
|
|||||||
@@ -941,15 +941,19 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
conversion_factor: function(doc, cdt, cdn, dont_fetch_price_list_rate) {
|
conversion_factor: function(doc, cdt, cdn, dont_fetch_price_list_rate) {
|
||||||
if(doc.doctype != 'Material Request' && frappe.meta.get_docfield(cdt, "stock_qty", cdn)) {
|
if(frappe.meta.get_docfield(cdt, "stock_qty", cdn)) {
|
||||||
var item = frappe.get_doc(cdt, cdn);
|
var item = frappe.get_doc(cdt, cdn);
|
||||||
frappe.model.round_floats_in(item, ["qty", "conversion_factor"]);
|
frappe.model.round_floats_in(item, ["qty", "conversion_factor"]);
|
||||||
item.stock_qty = flt(item.qty * item.conversion_factor, precision("stock_qty", item));
|
item.stock_qty = flt(item.qty * item.conversion_factor, precision("stock_qty", item));
|
||||||
item.total_weight = flt(item.stock_qty * item.weight_per_unit);
|
|
||||||
refresh_field("stock_qty", item.name, item.parentfield);
|
refresh_field("stock_qty", item.name, item.parentfield);
|
||||||
refresh_field("total_weight", item.name, item.parentfield);
|
|
||||||
this.toggle_conversion_factor(item);
|
this.toggle_conversion_factor(item);
|
||||||
this.calculate_net_weight();
|
|
||||||
|
if(doc.doctype != "Material Request") {
|
||||||
|
item.total_weight = flt(item.stock_qty * item.weight_per_unit);
|
||||||
|
refresh_field("total_weight", item.name, item.parentfield);
|
||||||
|
this.calculate_net_weight();
|
||||||
|
}
|
||||||
|
|
||||||
if (!dont_fetch_price_list_rate &&
|
if (!dont_fetch_price_list_rate &&
|
||||||
frappe.meta.has_field(doc.doctype, "price_list_currency")) {
|
frappe.meta.has_field(doc.doctype, "price_list_currency")) {
|
||||||
this.apply_price_list(item, true);
|
this.apply_price_list(item, true);
|
||||||
|
|||||||
@@ -90,7 +90,8 @@ erpnext.SerialNoBatchSelector = Class.extend({
|
|||||||
args: {
|
args: {
|
||||||
qty: qty,
|
qty: qty,
|
||||||
item_code: me.item_code,
|
item_code: me.item_code,
|
||||||
warehouse: me.warehouse_details.name
|
warehouse: me.warehouse_details.name,
|
||||||
|
batch_no: me.item.batch_no || null
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -316,7 +317,7 @@ erpnext.SerialNoBatchSelector = Class.extend({
|
|||||||
frappe.call({
|
frappe.call({
|
||||||
method: 'erpnext.stock.doctype.batch.batch.get_batch_qty',
|
method: 'erpnext.stock.doctype.batch.batch.get_batch_qty',
|
||||||
args: {
|
args: {
|
||||||
batch_no: this.doc.batch_no,
|
batch_no: me.item.batch_no,
|
||||||
warehouse: me.warehouse_details.name,
|
warehouse: me.warehouse_details.name,
|
||||||
item_code: me.item_code
|
item_code: me.item_code
|
||||||
},
|
},
|
||||||
@@ -392,6 +393,10 @@ erpnext.SerialNoBatchSelector = Class.extend({
|
|||||||
delivery_document_no: ""
|
delivery_document_no: ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.item.batch_no) {
|
||||||
|
serial_no_filters["batch_no"] = this.item.batch_no;
|
||||||
|
}
|
||||||
|
|
||||||
if (me.warehouse_details.name) {
|
if (me.warehouse_details.name) {
|
||||||
serial_no_filters['warehouse'] = me.warehouse_details.name;
|
serial_no_filters['warehouse'] = me.warehouse_details.name;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ frappe.treeview_settings["Quality Procedure"] = {
|
|||||||
add_tree_node: 'erpnext.quality_management.doctype.quality_procedure.quality_procedure.add_node',
|
add_tree_node: 'erpnext.quality_management.doctype.quality_procedure.quality_procedure.add_node',
|
||||||
filters: [
|
filters: [
|
||||||
{
|
{
|
||||||
fieldname: "quality_procedure",
|
fieldname: "parent_quality_procedure",
|
||||||
fieldtype: "Link",
|
fieldtype: "Link",
|
||||||
options: "Quality Procedure",
|
options: "Quality Procedure",
|
||||||
label: __("Quality Procedure"),
|
label: __("Quality Procedure"),
|
||||||
|
|||||||
@@ -73,7 +73,7 @@
|
|||||||
"reqd": 1
|
"reqd": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"modified": "2019-05-26 23:12:47.302189",
|
"modified": "2020-02-01 10:57:27.119312",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Quality Management",
|
"module": "Quality Management",
|
||||||
"name": "Quality Review",
|
"name": "Quality Review",
|
||||||
@@ -102,6 +102,18 @@
|
|||||||
"role": "All",
|
"role": "All",
|
||||||
"share": 1,
|
"share": 1,
|
||||||
"write": 1
|
"write": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"create": 1,
|
||||||
|
"delete": 1,
|
||||||
|
"email": 1,
|
||||||
|
"export": 1,
|
||||||
|
"print": 1,
|
||||||
|
"read": 1,
|
||||||
|
"report": 1,
|
||||||
|
"role": "Quality Manager",
|
||||||
|
"share": 1,
|
||||||
|
"write": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
|
|||||||
@@ -1,24 +1,28 @@
|
|||||||
{
|
{
|
||||||
"add_total_row": 0,
|
"add_total_row": 0,
|
||||||
"creation": "2018-10-16 12:28:43.651915",
|
"creation": "2018-10-16 12:28:43.651915",
|
||||||
"disabled": 0,
|
"disable_prepared_report": 0,
|
||||||
"docstatus": 0,
|
"disabled": 0,
|
||||||
"doctype": "Report",
|
"docstatus": 0,
|
||||||
"idx": 0,
|
"doctype": "Report",
|
||||||
"is_standard": "Yes",
|
"idx": 0,
|
||||||
"modified": "2018-10-16 15:23:25.667237",
|
"is_standard": "Yes",
|
||||||
"modified_by": "Administrator",
|
"modified": "2020-02-01 11:04:47.299453",
|
||||||
"module": "Quality Management",
|
"modified_by": "Administrator",
|
||||||
"name": "Review",
|
"module": "Quality Management",
|
||||||
"owner": "Administrator",
|
"name": "Review",
|
||||||
"prepared_report": 0,
|
"owner": "Administrator",
|
||||||
"query": "SELECT\n `tabQuality Action`.name as \"Name:Data:200\",\n `tabQuality Action`.action as \"Action:Select/[corrective,Preventive]:200\",\n `tabQuality Action`.review as \"Review:Link/Quality Review:200\",\n `tabQuality Action`.date as \"Date:Date:120\",\n `tabQuality Action`.status as \"Status:Select/Planned:150\"\nFROM\n `tabQuality Action`\nWHERE\n `tabQuality Action`.type='Quality Review'\n \n ",
|
"prepared_report": 0,
|
||||||
"ref_doctype": "Quality Action",
|
"query": "SELECT\n `tabQuality Action`.name as \"Name:Data:200\",\n `tabQuality Action`.corrective_preventive as \"Action:Select/[Corrective,Preventive]:200\",\n `tabQuality Action`.document_type as \"Document Type:Select/[Quality Review, Quality Feedback]:200\",\n `tabQuality Action`.date as \"Date:Date:120\",\n `tabQuality Action`.status as \"Status:Select/Planned:150\"\nFROM\n `tabQuality Action`\nWHERE\n `tabQuality Action`.document_type='Quality Review'\n \n ",
|
||||||
"report_name": "Review",
|
"ref_doctype": "Quality Action",
|
||||||
"report_type": "Query Report",
|
"report_name": "Review",
|
||||||
|
"report_type": "Query Report",
|
||||||
"roles": [
|
"roles": [
|
||||||
{
|
{
|
||||||
"role": "System Manager"
|
"role": "System Manager"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"role": "Quality Manager"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -79,9 +79,10 @@ def add_custom_roles_for_reports():
|
|||||||
def add_permissions():
|
def add_permissions():
|
||||||
for doctype in ('GST HSN Code', 'GST Settings'):
|
for doctype in ('GST HSN Code', 'GST Settings'):
|
||||||
add_permission(doctype, 'All', 0)
|
add_permission(doctype, 'All', 0)
|
||||||
add_permission(doctype, 'Accounts Manager', 0)
|
for role in ('Accounts Manager', 'System Manager', 'Item Manager', 'Stock Manager'):
|
||||||
update_permission_property(doctype, 'Accounts Manager', 0, 'write', 1)
|
add_permission(doctype, role, 0)
|
||||||
update_permission_property(doctype, 'Accounts Manager', 0, 'create', 1)
|
update_permission_property(doctype, role, 0, 'write', 1)
|
||||||
|
update_permission_property(doctype, role, 0, 'create', 1)
|
||||||
|
|
||||||
def add_print_formats():
|
def add_print_formats():
|
||||||
frappe.reload_doc("regional", "print_format", "gst_tax_invoice")
|
frappe.reload_doc("regional", "print_format", "gst_tax_invoice")
|
||||||
@@ -718,4 +719,4 @@ def get_tds_details(accounts, fiscal_year):
|
|||||||
doctype="Tax Withholding Category", accounts=accounts,
|
doctype="Tax Withholding Category", accounts=accounts,
|
||||||
rates=[{"fiscal_year": fiscal_year, "tax_withholding_rate": 20,
|
rates=[{"fiscal_year": fiscal_year, "tax_withholding_rate": 20,
|
||||||
"single_threshold": 2500, "cumulative_threshold": 0}])
|
"single_threshold": 2500, "cumulative_threshold": 0}])
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -160,7 +160,7 @@ def get_gl_entries(filters, as_dict):
|
|||||||
where gl.company = %(company)s
|
where gl.company = %(company)s
|
||||||
and DATE(gl.posting_date) >= %(from_date)s
|
and DATE(gl.posting_date) >= %(from_date)s
|
||||||
and DATE(gl.posting_date) <= %(to_date)s
|
and DATE(gl.posting_date) <= %(to_date)s
|
||||||
order by 'Belegdatum', gl.voucher_no""", filters, as_dict=as_dict, as_utf8=1)
|
order by 'Belegdatum', gl.voucher_no""", filters, as_dict=as_dict)
|
||||||
|
|
||||||
return gl_entries
|
return gl_entries
|
||||||
|
|
||||||
|
|||||||
@@ -55,6 +55,14 @@ frappe.ui.form.on("Customer", {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
frm.set_query('default_bank_account', function() {
|
||||||
|
return {
|
||||||
|
filters: {
|
||||||
|
'is_company_account': 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
},
|
},
|
||||||
customer_primary_address: function(frm){
|
customer_primary_address: function(frm){
|
||||||
if(frm.doc.customer_primary_address){
|
if(frm.doc.customer_primary_address){
|
||||||
@@ -103,7 +111,7 @@ frappe.ui.form.on("Customer", {
|
|||||||
}
|
}
|
||||||
|
|
||||||
frappe.dynamic_link = {doc: frm.doc, fieldname: 'name', doctype: 'Customer'}
|
frappe.dynamic_link = {doc: frm.doc, fieldname: 'name', doctype: 'Customer'}
|
||||||
frm.toggle_display(['address_html','contact_html','primary_address_and_contact_detail'], !frm.doc.__islocal);
|
frm.toggle_display(['address_html','contact_html'], !frm.doc.__islocal);
|
||||||
|
|
||||||
if(!frm.doc.__islocal) {
|
if(!frm.doc.__islocal) {
|
||||||
frappe.contacts.render_address_and_contact(frm);
|
frappe.contacts.render_address_and_contact(frm);
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
|
"actions": [],
|
||||||
"allow_events_in_timeline": 1,
|
"allow_events_in_timeline": 1,
|
||||||
"allow_import": 1,
|
"allow_import": 1,
|
||||||
"allow_rename": 1,
|
"allow_rename": 1,
|
||||||
@@ -122,7 +123,7 @@
|
|||||||
{
|
{
|
||||||
"fieldname": "default_bank_account",
|
"fieldname": "default_bank_account",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"label": "Default Bank Account",
|
"label": "Default Company Bank Account",
|
||||||
"options": "Bank Account"
|
"options": "Bank Account"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -322,8 +323,9 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "primary_address",
|
"fieldname": "primary_address",
|
||||||
"fieldtype": "Read Only",
|
"fieldtype": "Text",
|
||||||
"label": "Primary Address"
|
"label": "Primary Address",
|
||||||
|
"read_only": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"collapsible": 1,
|
"collapsible": 1,
|
||||||
@@ -469,7 +471,8 @@
|
|||||||
"icon": "fa fa-user",
|
"icon": "fa fa-user",
|
||||||
"idx": 363,
|
"idx": 363,
|
||||||
"image_field": "image",
|
"image_field": "image",
|
||||||
"modified": "2019-09-06 12:40:31.801424",
|
"links": [],
|
||||||
|
"modified": "2020-01-29 20:36:37.879581",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Selling",
|
"module": "Selling",
|
||||||
"name": "Customer",
|
"name": "Customer",
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ class Customer(TransactionBase):
|
|||||||
self.validate_credit_limit_on_change()
|
self.validate_credit_limit_on_change()
|
||||||
self.set_loyalty_program()
|
self.set_loyalty_program()
|
||||||
self.check_customer_group_change()
|
self.check_customer_group_change()
|
||||||
|
self.validate_default_bank_account()
|
||||||
|
|
||||||
# set loyalty program tier
|
# set loyalty program tier
|
||||||
if frappe.db.exists('Customer', self.name):
|
if frappe.db.exists('Customer', self.name):
|
||||||
@@ -72,6 +73,11 @@ class Customer(TransactionBase):
|
|||||||
if self.customer_group != frappe.db.get_value('Customer', self.name, 'customer_group'):
|
if self.customer_group != frappe.db.get_value('Customer', self.name, 'customer_group'):
|
||||||
frappe.flags.customer_group_changed = True
|
frappe.flags.customer_group_changed = True
|
||||||
|
|
||||||
|
def validate_default_bank_account(self):
|
||||||
|
if self.default_bank_account:
|
||||||
|
is_company_account = frappe.db.get_value('Bank Account', self.default_bank_account, 'is_company_account')
|
||||||
|
frappe.throw(_("{0} is not a company bank account").format(frappe.bold(self.default_bank_account)))
|
||||||
|
|
||||||
def on_update(self):
|
def on_update(self):
|
||||||
self.validate_name_with_customer_group()
|
self.validate_name_with_customer_group()
|
||||||
self.create_primary_contact()
|
self.create_primary_contact()
|
||||||
|
|||||||
@@ -185,8 +185,12 @@ def _make_sales_order(source_name, target_doc=None, ignore_permissions=False):
|
|||||||
return doclist
|
return doclist
|
||||||
|
|
||||||
def set_expired_status():
|
def set_expired_status():
|
||||||
frappe.db.sql("""UPDATE `tabQuotation` SET `status` = 'Expired'
|
frappe.db.sql("""
|
||||||
WHERE `status` != "Expired" AND `valid_till` < %s""", (nowdate()))
|
UPDATE
|
||||||
|
`tabQuotation` SET `status` = 'Expired'
|
||||||
|
WHERE
|
||||||
|
`status` not in ('Ordered', 'Expired', 'Lost', 'Cancelled') AND `valid_till` < %s
|
||||||
|
""", (nowdate()))
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def make_sales_invoice(source_name, target_doc=None):
|
def make_sales_invoice(source_name, target_doc=None):
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user