Compare commits
180 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fda7cbeca4 | ||
|
|
2fc58b3327 | ||
|
|
0cee807dfb | ||
|
|
a51c56c4b3 | ||
|
|
d2f26e57d2 | ||
|
|
b7790c0394 | ||
|
|
2a1e9b542e | ||
|
|
8f458feafc | ||
|
|
e116d8f819 | ||
|
|
f3674ccc6c | ||
|
|
6f35a63f2d | ||
|
|
b26fd04843 | ||
|
|
1b78d20d3c | ||
|
|
b203406d4c | ||
|
|
8903258362 | ||
|
|
2d2aa7d664 | ||
|
|
cd6b60df70 | ||
|
|
b18790f5c2 | ||
|
|
f6d7090f07 | ||
|
|
017d280877 | ||
|
|
0119d15adb | ||
|
|
df6cb3c43b | ||
|
|
1ed737cf64 | ||
|
|
c64e46fe67 | ||
|
|
f579b0e3de | ||
|
|
b63c041aa4 | ||
|
|
22f9a5f09f | ||
|
|
e47875340e | ||
|
|
6f28383531 | ||
|
|
95050702f1 | ||
|
|
ae8f717fe5 | ||
|
|
f95ac99baa | ||
|
|
660b4d1e2f | ||
|
|
5bfebaf1c0 | ||
|
|
980e54c5f4 | ||
|
|
efbfeb2d89 | ||
|
|
0676ed08b1 | ||
|
|
e9946672e0 | ||
|
|
6124f83e6e | ||
|
|
2b83debc72 | ||
|
|
fc4cc9ab42 | ||
|
|
cd19974d7a | ||
|
|
cde48a44cf | ||
|
|
57d33f9ce6 | ||
|
|
90a46acc0d | ||
|
|
60634cc829 | ||
|
|
a7c27596bb | ||
|
|
b4e3146665 | ||
|
|
495ab6c7f2 | ||
|
|
0e396a62b1 | ||
|
|
1343a4b755 | ||
|
|
ec45c096a0 | ||
|
|
c7e523cee4 | ||
|
|
9e436336e2 | ||
|
|
a9205adfbd | ||
|
|
f5bff5f15d | ||
|
|
bbeacb9acf | ||
|
|
7027584391 | ||
|
|
372d4e2e05 | ||
|
|
bdfa2ff33a | ||
|
|
787b31674a | ||
|
|
0eb9f7408e | ||
|
|
5c96415eb5 | ||
|
|
d9f8347fc8 | ||
|
|
2a48fe6ce6 | ||
|
|
3ed574532d | ||
|
|
9f58e59a2c | ||
|
|
23c6d6cf16 | ||
|
|
8e0a9e8748 | ||
|
|
67dbeee7b2 | ||
|
|
b4a0c773ae | ||
|
|
694f57fbb4 | ||
|
|
0f90b870fb | ||
|
|
bd5b37dbb7 | ||
|
|
7e93e87244 | ||
|
|
02f4aa6db6 | ||
|
|
ade2c36123 | ||
|
|
3ef80f2d2e | ||
|
|
85c6480b41 | ||
|
|
f3c94315c3 | ||
|
|
a4219f1cfe | ||
|
|
831a7ddd6f | ||
|
|
43886ca016 | ||
|
|
61b4244837 | ||
|
|
6871979acc | ||
|
|
bb7cf81d52 | ||
|
|
9826291c52 | ||
|
|
08661250d2 | ||
|
|
814001a90f | ||
|
|
eef73a0d92 | ||
|
|
a1e3202054 | ||
|
|
bee017e17c | ||
|
|
a054508211 | ||
|
|
feaa82a8ea | ||
|
|
a175e06149 | ||
|
|
ba4d9469ff | ||
|
|
54c6f91dde | ||
|
|
e552e958de | ||
|
|
7524ecbc59 | ||
|
|
be2ca5f8cc | ||
|
|
d4d641a07e | ||
|
|
8e5b812a97 | ||
|
|
df94f0565e | ||
|
|
f2838c4a13 | ||
|
|
fe56c7ce39 | ||
|
|
29ecbde445 | ||
|
|
611f212aa4 | ||
|
|
6fbafa1924 | ||
|
|
875bac8bb9 | ||
|
|
b4b410f1d2 | ||
|
|
eec0ee83e2 | ||
|
|
148951e6f3 | ||
|
|
612e3b77fd | ||
|
|
a60849f6ab | ||
|
|
6f27e97980 | ||
|
|
8d9145aaac | ||
|
|
25a7330db0 | ||
|
|
92c999afcb | ||
|
|
9e3dc25b1c | ||
|
|
2a3cd7d601 | ||
|
|
3ca67ceebb | ||
|
|
245fc49089 | ||
|
|
78199dbf0a | ||
|
|
2ac33c9ce9 | ||
|
|
34cd035d8c | ||
|
|
ba4f565ca3 | ||
|
|
5860427bc5 | ||
|
|
89f42eef49 | ||
|
|
eacbfa15c0 | ||
|
|
5d45c2c184 | ||
|
|
b24b0378ea | ||
|
|
144012a5de | ||
|
|
5fb4027375 | ||
|
|
3fa65f1363 | ||
|
|
79f630661a | ||
|
|
61b9fe6a81 | ||
|
|
f38d9d8f0d | ||
|
|
3a67daa1fd | ||
|
|
813726b415 | ||
|
|
87fe2143be | ||
|
|
c759b06f16 | ||
|
|
c32249a72f | ||
|
|
05f4be69f4 | ||
|
|
541881162a | ||
|
|
19c5e031a9 | ||
|
|
45be9fe416 | ||
|
|
1596352585 | ||
|
|
4b893b1d51 | ||
|
|
d85e144944 | ||
|
|
4dfff5a271 | ||
|
|
c2b9598966 | ||
|
|
d16e7c096b | ||
|
|
5511912251 | ||
|
|
514d3c37b9 | ||
|
|
7721954bbb | ||
|
|
0a50088a0e | ||
|
|
6ba6ba27bd | ||
|
|
611e23c149 | ||
|
|
89affd8d09 | ||
|
|
8dfd5535f1 | ||
|
|
8c45ae73b3 | ||
|
|
fed9e2861c | ||
|
|
6e115638a1 | ||
|
|
437be1162e | ||
|
|
e3b6a14ab1 | ||
|
|
eb7893768b | ||
|
|
6e1ef4f5c2 | ||
|
|
7d7027f47c | ||
|
|
7086ecb3b0 | ||
|
|
8508ace50e | ||
|
|
c52ef56875 | ||
|
|
4dfe8ab483 | ||
|
|
ea5e0a9d5b | ||
|
|
30111e6403 | ||
|
|
e5a572a4a8 | ||
|
|
83ed7df8cd | ||
|
|
97e93c6257 | ||
|
|
73089470b1 | ||
|
|
3798f8bd25 | ||
|
|
f805a76e79 |
@@ -63,6 +63,7 @@ install:
|
||||
- tar -xf /tmp/wkhtmltox.tar.xz -C /tmp
|
||||
- sudo mv /tmp/wkhtmltox/bin/wkhtmltopdf /usr/local/bin/wkhtmltopdf
|
||||
- sudo chmod o+x /usr/local/bin/wkhtmltopdf
|
||||
- sudo apt-get install libcups2-dev
|
||||
|
||||
- cd ~/frappe-bench
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import frappe
|
||||
from erpnext.hooks import regional_overrides
|
||||
from frappe.utils import getdate
|
||||
|
||||
__version__ = '12.4.2'
|
||||
__version__ = '12.5.2'
|
||||
|
||||
def get_default_company(user=None):
|
||||
'''Get default company for user'''
|
||||
|
||||
@@ -95,29 +95,29 @@ class Account(NestedSet):
|
||||
# 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:
|
||||
return
|
||||
|
||||
ancestors = get_root_company(self.company)
|
||||
if ancestors:
|
||||
if frappe.get_value("Company", self.company, "allow_account_creation_against_child_company"):
|
||||
return
|
||||
|
||||
if not frappe.db.get_value("Account",
|
||||
{'account_name': self.account_name, 'company': ancestors[0]}, 'name'):
|
||||
frappe.throw(_("Please add the account to root level Company - %s" % ancestors[0]))
|
||||
else:
|
||||
descendants = get_descendants_of('Company', self.company)
|
||||
if not descendants: return
|
||||
|
||||
parent_acc_name_map = {}
|
||||
parent_acc_name, parent_acc_number = frappe.db.get_value('Account', self.parent_account, \
|
||||
["account_name", "account_number"])
|
||||
for d in frappe.db.get_values('Account',
|
||||
{ "company": ["in", descendants], "account_name": parent_acc_name,
|
||||
"account_number": parent_acc_number },
|
||||
["company", "name"], as_dict=True):
|
||||
filters = {
|
||||
"company": ["in", descendants],
|
||||
"account_name": parent_acc_name,
|
||||
}
|
||||
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"]
|
||||
if not parent_acc_name_map: return
|
||||
|
||||
self.create_account_for_child_company(parent_acc_name_map, descendants, parent_acc_name)
|
||||
|
||||
def validate_group_or_ledger(self):
|
||||
@@ -175,7 +175,6 @@ class Account(NestedSet):
|
||||
filters["account_number"] = self.account_number
|
||||
|
||||
child_account = frappe.db.get_value("Account", filters, 'name')
|
||||
|
||||
if not child_account:
|
||||
doc = frappe.copy_doc(self)
|
||||
doc.flags.ignore_root_company_validation = True
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
{
|
||||
"actions": [],
|
||||
"allow_import": 1,
|
||||
"allow_rename": 1,
|
||||
"creation": "2017-05-29 21:35:13.136357",
|
||||
@@ -82,7 +83,7 @@
|
||||
"default": "0",
|
||||
"fieldname": "is_default",
|
||||
"fieldtype": "Check",
|
||||
"label": "Is the Default Account"
|
||||
"label": "Is Default Account"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
@@ -211,7 +212,8 @@
|
||||
"read_only": 1
|
||||
}
|
||||
],
|
||||
"modified": "2019-10-02 01:34:12.417601",
|
||||
"links": [],
|
||||
"modified": "2020-01-29 20:42:26.458316",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Bank Account",
|
||||
|
||||
@@ -3,16 +3,16 @@
|
||||
|
||||
frappe.ui.form.on("Bank Reconciliation", {
|
||||
setup: function(frm) {
|
||||
frm.add_fetch("bank_account", "account_currency", "account_currency");
|
||||
frm.add_fetch("account", "account_currency", "account_currency");
|
||||
},
|
||||
|
||||
onload: function(frm) {
|
||||
|
||||
let default_bank_account = frappe.defaults.get_user_default("Company")?
|
||||
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 {
|
||||
"filters": {
|
||||
"account_type": ["in",["Bank","Cash"]],
|
||||
|
||||
@@ -19,10 +19,9 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "Select account head of the bank where cheque was deposited.",
|
||||
"fetch_from": "bank_account_no.account",
|
||||
"fetch_from": "bank_account.account",
|
||||
"fetch_if_empty": 1,
|
||||
"fieldname": "bank_account",
|
||||
"fieldname": "account",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
@@ -31,7 +30,7 @@
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Bank Account",
|
||||
"label": "Account",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Account",
|
||||
@@ -164,7 +163,6 @@
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
@@ -183,8 +181,9 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "Select the Bank Account to reconcile.",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "bank_account_no",
|
||||
"fieldname": "bank_account",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
@@ -193,12 +192,11 @@
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Bank Account No",
|
||||
"label": "Bank Account",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Bank Account",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
@@ -450,7 +448,7 @@
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"menu_index": 0,
|
||||
"modified": "2019-04-09 18:41:06.110453",
|
||||
"modified": "2020-01-22 00:00:00.000000",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Bank Reconciliation",
|
||||
@@ -483,4 +481,4 @@
|
||||
"track_changes": 0,
|
||||
"track_seen": 0,
|
||||
"track_views": 0
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,17 +13,15 @@ form_grid_templates = {
|
||||
|
||||
class BankReconciliation(Document):
|
||||
def get_payment_entries(self):
|
||||
if not (self.bank_account and self.from_date and self.to_date):
|
||||
msgprint(_("Bank Account, From Date and To Date are Mandatory"))
|
||||
return
|
||||
if not (self.from_date and self.to_date):
|
||||
frappe.throw(_("From Date and To Date are Mandatory"))
|
||||
|
||||
if not self.account:
|
||||
frappe.throw(_("Account is mandatory to get payment entries"))
|
||||
|
||||
condition = ""
|
||||
if not self.include_reconciled_entries:
|
||||
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))
|
||||
condition = "and (clearance_date IS NULL or clearance_date='0000-00-00')"
|
||||
|
||||
journal_entries = frappe.db.sql("""
|
||||
select
|
||||
@@ -34,15 +32,16 @@ class BankReconciliation(Document):
|
||||
from
|
||||
`tabJournal Entry` t1, `tabJournal Entry Account` t2
|
||||
where
|
||||
t2.parent = t1.name and t2.account = %s and t1.docstatus=1
|
||||
and t1.posting_date >= %s and t1.posting_date <= %s
|
||||
and ifnull(t1.is_opening, 'No') = 'No' {0} {1}
|
||||
t2.parent = t1.name and t2.account = %(account)s and t1.docstatus=1
|
||||
and t1.posting_date >= %(from)s and t1.posting_date <= %(to)s
|
||||
and ifnull(t1.is_opening, 'No') = 'No' {condition}
|
||||
group by t2.account, t1.name
|
||||
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)
|
||||
""".format(condition=condition), {"account": self.account, "from": self.from_date, "to": self.to_date}, as_dict=1)
|
||||
condition = ''
|
||||
|
||||
if self.bank_account_no:
|
||||
condition = " and bank_account = %(bank_account_no)s"
|
||||
if self.bank_account:
|
||||
condition += 'and bank_account = %(bank_account)s'
|
||||
|
||||
payment_entries = frappe.db.sql("""
|
||||
select
|
||||
@@ -55,12 +54,12 @@ class BankReconciliation(Document):
|
||||
from `tabPayment Entry`
|
||||
where
|
||||
(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
|
||||
{condition}
|
||||
order by
|
||||
posting_date ASC, name DESC
|
||||
""".format(condition),
|
||||
{"account":self.bank_account, "from":self.from_date,
|
||||
"to":self.to_date, "bank_account_no": self.bank_account_no}, as_dict=1)
|
||||
""".format(condition=condition), {"account": self.account, "from":self.from_date,
|
||||
"to": self.to_date, "bank_account": self.bank_account}, as_dict=1)
|
||||
|
||||
pos_entries = []
|
||||
if self.include_pos_transactions:
|
||||
@@ -72,11 +71,10 @@ class BankReconciliation(Document):
|
||||
from `tabSales Invoice Payment` sip, `tabSales Invoice` si, `tabAccount` account
|
||||
where
|
||||
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
|
||||
si.posting_date ASC, si.name DESC
|
||||
""".format(condition),
|
||||
{"account":self.bank_account, "from":self.from_date, "to":self.to_date}, as_dict=1)
|
||||
""", {"account":self.account, "from":self.from_date, "to":self.to_date}, as_dict=1)
|
||||
|
||||
entries = sorted(list(payment_entries)+list(journal_entries+list(pos_entries)),
|
||||
key=lambda k: k['posting_date'] or getdate(nowdate()))
|
||||
|
||||
@@ -110,6 +110,15 @@
|
||||
"set_only_once": 0,
|
||||
"translatable": 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,
|
||||
@@ -122,7 +131,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-12-06 10:57:02.635141",
|
||||
"modified": "2020-01-22 00:00:00.000000",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Bank Transaction Payments",
|
||||
@@ -138,4 +147,4 @@
|
||||
"track_changes": 1,
|
||||
"track_seen": 0,
|
||||
"track_views": 0
|
||||
}
|
||||
}
|
||||
|
||||
@@ -210,10 +210,10 @@ def get_requested_amount(args, budget):
|
||||
item_code = args.get('item_code')
|
||||
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
|
||||
from `tabMaterial Request Item` mri, `tabMaterial Request` mr where mr.name = mri.parent and
|
||||
mri.item_code = %s and mr.docstatus = 1 and mri.stock_qty > mri.ordered_qty and {0} and
|
||||
mr.material_request_type = 'Purchase' and mr.status != 'Stopped'""".format(condition), item_code, as_list=1)
|
||||
data = frappe.db.sql(""" select ifnull((sum(child.stock_qty - child.ordered_qty) * rate), 0) as amount
|
||||
from `tabMaterial Request Item` child, `tabMaterial Request` parent where parent.name = child.parent and
|
||||
child.item_code = %s and parent.docstatus = 1 and child.stock_qty > child.ordered_qty and {0} and
|
||||
parent.material_request_type = 'Purchase' and parent.status != 'Stopped'""".format(condition), item_code, as_list=1)
|
||||
|
||||
return data[0][0] if data else 0
|
||||
|
||||
@@ -221,10 +221,10 @@ def get_ordered_amount(args, budget):
|
||||
item_code = args.get('item_code')
|
||||
condition = get_other_condition(args, budget, 'Purchase Order')
|
||||
|
||||
data = frappe.db.sql(""" select ifnull(sum(poi.amount - poi.billed_amt), 0) as amount
|
||||
from `tabPurchase Order Item` poi, `tabPurchase Order` po where
|
||||
po.name = poi.parent and poi.item_code = %s and po.docstatus = 1 and poi.amount > poi.billed_amt
|
||||
and po.status != 'Closed' and {0}""".format(condition), item_code, as_list=1)
|
||||
data = frappe.db.sql(""" select ifnull(sum(child.amount - child.billed_amt), 0) as amount
|
||||
from `tabPurchase Order Item` child, `tabPurchase Order` parent where
|
||||
parent.name = child.parent and child.item_code = %s and parent.docstatus = 1 and child.amount > child.billed_amt
|
||||
and parent.status != 'Closed' and {0}""".format(condition), item_code, as_list=1)
|
||||
|
||||
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"))
|
||||
|
||||
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'):
|
||||
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'),
|
||||
['year_start_date', 'year_end_date'])
|
||||
|
||||
alias = 'mr' if for_doc == 'Material Request' else 'po'
|
||||
condition += """ and %s.%s
|
||||
between '%s' and '%s' """ %(alias, date_field, start_date, end_date)
|
||||
condition += """ and parent.%s
|
||||
between '%s' and '%s' """ %(date_field, start_date, end_date)
|
||||
|
||||
return condition
|
||||
|
||||
|
||||
@@ -96,7 +96,11 @@ def build_forest(data):
|
||||
if parent_account == account_name == child:
|
||||
return [parent_account]
|
||||
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 = {}, []
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
{
|
||||
"actions": [],
|
||||
"allow_copy": 1,
|
||||
"allow_import": 1,
|
||||
"allow_rename": 1,
|
||||
@@ -123,7 +124,8 @@
|
||||
],
|
||||
"icon": "fa fa-money",
|
||||
"idx": 1,
|
||||
"modified": "2019-09-16 14:44:17.103548",
|
||||
"links": [],
|
||||
"modified": "2020-01-28 13:50:23.430434",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Cost Center",
|
||||
@@ -162,7 +164,6 @@
|
||||
"role": "Purchase User"
|
||||
}
|
||||
],
|
||||
"quick_entry": 1,
|
||||
"search_fields": "parent_cost_center, is_group",
|
||||
"show_name_in_global_search": 1,
|
||||
"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):
|
||||
self.validate_accounts()
|
||||
self.validate_repeating_companies()
|
||||
self.validate_pos_mode_of_payment()
|
||||
|
||||
def validate_repeating_companies(self):
|
||||
"""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:
|
||||
frappe.throw(_("Account {0} does not match with Company {1} in Mode of Account: {2}")
|
||||
.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_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):
|
||||
for d in self.get("references"):
|
||||
|
||||
@@ -373,6 +373,7 @@ def get_existing_payment_request_amount(ref_dt, ref_dn):
|
||||
reference_doctype = %s
|
||||
and reference_name = %s
|
||||
and docstatus = 1
|
||||
and status != 'Paid'
|
||||
""", (ref_dt, ref_dn))
|
||||
return flt(existing_payment_request_amount[0][0]) if existing_payment_request_amount else 0
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
"autoname": "Prompt",
|
||||
"creation": "2013-05-24 12:15:51",
|
||||
"doctype": "DocType",
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"disabled",
|
||||
"section_break_2",
|
||||
@@ -50,6 +51,7 @@
|
||||
"income_account",
|
||||
"expense_account",
|
||||
"taxes_and_charges",
|
||||
"tax_category",
|
||||
"apply_discount_on",
|
||||
"accounting_dimensions_section",
|
||||
"cost_center",
|
||||
@@ -381,11 +383,17 @@
|
||||
{
|
||||
"fieldname": "dimension_col_break",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "tax_category",
|
||||
"fieldtype": "Link",
|
||||
"label": "Tax Category",
|
||||
"options": "Tax Category"
|
||||
}
|
||||
],
|
||||
"icon": "icon-cog",
|
||||
"idx": 1,
|
||||
"modified": "2019-05-25 22:56:30.352693",
|
||||
"modified": "2020-01-24 15:52:03.797701",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"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.stock.get_item_details import get_item_details
|
||||
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):
|
||||
def setUp(self):
|
||||
@@ -145,6 +147,52 @@ class TestPricingRule(unittest.TestCase):
|
||||
self.assertEquals(details.get("margin_type"), "Percentage")
|
||||
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):
|
||||
from erpnext.stock.get_item_details import get_item_details
|
||||
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):
|
||||
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:
|
||||
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(){
|
||||
const me = this;
|
||||
|
||||
const title = __('Add Comment');
|
||||
const title = __('Block Invoice');
|
||||
const fields = [
|
||||
{
|
||||
fieldname: 'release_date',
|
||||
read_only: 0,
|
||||
fieldtype:'Date',
|
||||
label: __('Release Date'),
|
||||
default: me.frm.doc.release_date
|
||||
},
|
||||
{
|
||||
fieldname: 'hold_comment',
|
||||
read_only: 0,
|
||||
@@ -187,7 +194,11 @@ erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({
|
||||
const dialog_data = me.dialog.get_values();
|
||||
frappe.call({
|
||||
'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()
|
||||
});
|
||||
me.dialog.hide();
|
||||
|
||||
@@ -866,6 +866,7 @@ class PurchaseInvoice(BuyingController):
|
||||
# because updating ordered qty in bin depends upon updated ordered qty in PO
|
||||
if self.update_stock == 1:
|
||||
self.update_stock_ledger()
|
||||
self.delete_auto_created_batches()
|
||||
|
||||
self.make_gl_entries_on_cancel()
|
||||
self.update_project()
|
||||
@@ -927,9 +928,10 @@ class PurchaseInvoice(BuyingController):
|
||||
def on_recurring(self, reference_doc, auto_repeat_doc):
|
||||
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('hold_comment', cstr(hold_comment))
|
||||
self.db_set('release_date', release_date)
|
||||
|
||||
def unblock_invoice(self):
|
||||
self.db_set('on_hold', 0)
|
||||
@@ -1013,10 +1015,10 @@ def unblock_invoice(name):
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def block_invoice(name, hold_comment):
|
||||
def block_invoice(name, release_date, hold_comment=None):
|
||||
if frappe.db.exists('Purchase Invoice', name):
|
||||
pi = frappe.get_doc('Purchase Invoice', name)
|
||||
pi.block_invoice(hold_comment)
|
||||
pi.block_invoice(hold_comment, release_date)
|
||||
|
||||
@frappe.whitelist()
|
||||
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):
|
||||
return frappe.db.sql(""" 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""", {'company': doc.company}, as_dict=1)
|
||||
return frappe.db.sql("""
|
||||
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):
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
{
|
||||
"actions": [],
|
||||
"allow_import": 1,
|
||||
"autoname": "naming_series:",
|
||||
"creation": "2013-05-24 19:29:05",
|
||||
@@ -373,7 +372,8 @@
|
||||
"no_copy": 1,
|
||||
"options": "Sales Invoice",
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
"read_only": 1,
|
||||
"search_index": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_21",
|
||||
@@ -1568,8 +1568,7 @@
|
||||
"icon": "fa fa-file-text",
|
||||
"idx": 181,
|
||||
"is_submittable": 1,
|
||||
"links": [],
|
||||
"modified": "2019-12-30 19:15:59.580414",
|
||||
"modified": "2020-02-10 04:57:11.221180",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Sales Invoice",
|
||||
|
||||
@@ -412,6 +412,9 @@ class SalesInvoice(SellingController):
|
||||
|
||||
if pos:
|
||||
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:
|
||||
self.customer = pos.customer
|
||||
@@ -1232,24 +1235,27 @@ class SalesInvoice(SellingController):
|
||||
self.status = 'Draft'
|
||||
return
|
||||
|
||||
precision = self.precision("outstanding_amount")
|
||||
outstanding_amount = flt(self.outstanding_amount, precision)
|
||||
|
||||
if not status:
|
||||
if self.docstatus == 2:
|
||||
status = "Cancelled"
|
||||
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"
|
||||
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"
|
||||
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"
|
||||
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"
|
||||
#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"
|
||||
elif self.is_return == 1:
|
||||
self.status = "Return"
|
||||
elif flt(self.outstanding_amount)<=0:
|
||||
elif outstanding_amount <=0:
|
||||
self.status = "Paid"
|
||||
else:
|
||||
self.status = "Submitted"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
{
|
||||
"actions": [],
|
||||
"autoname": "ACC-SUB-.YYYY.-.#####",
|
||||
"creation": "2017-07-18 17:50:43.967266",
|
||||
"doctype": "DocType",
|
||||
@@ -155,7 +156,7 @@
|
||||
"fieldname": "apply_additional_discount",
|
||||
"fieldtype": "Select",
|
||||
"label": "Apply Additional Discount On",
|
||||
"options": "\nGrand Total\nNet total"
|
||||
"options": "\nGrand Total\nNet Total"
|
||||
},
|
||||
{
|
||||
"fieldname": "cb_2",
|
||||
@@ -196,7 +197,8 @@
|
||||
"fieldtype": "Column Break"
|
||||
}
|
||||
],
|
||||
"modified": "2019-07-25 18:45:38.579579",
|
||||
"links": [],
|
||||
"modified": "2020-01-27 14:37:32.845173",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Subscription",
|
||||
|
||||
@@ -280,7 +280,7 @@ class Subscription(Document):
|
||||
|
||||
if self.additional_discount_percentage or self.additional_discount_amount:
|
||||
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
|
||||
invoice.from_date = self.current_invoice_start
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2020-01-15 17:14:28.951793",
|
||||
"modified": "2020-01-15 17:14:28.951793",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Tax Category",
|
||||
|
||||
@@ -100,6 +100,11 @@ frappe.query_reports["Accounts Payable"] = {
|
||||
"fieldtype": "Link",
|
||||
"options": "Supplier Group"
|
||||
},
|
||||
{
|
||||
"fieldname": "group_by_party",
|
||||
"label": __("Group By Supplier"),
|
||||
"fieldtype": "Check"
|
||||
},
|
||||
{
|
||||
"fieldname":"based_on_payment_terms",
|
||||
"label": __("Based On Payment Terms"),
|
||||
@@ -112,6 +117,16 @@ frappe.query_reports["Accounts Payable"] = {
|
||||
"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) {
|
||||
report.page.add_inner_button(__("Accounts Payable Summary"), function() {
|
||||
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.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) {
|
||||
if (value) {
|
||||
frappe.query_report.set_filter_value('credit_limit', value["credit_limit"]);
|
||||
@@ -131,6 +131,11 @@ frappe.query_reports["Accounts Receivable"] = {
|
||||
"fieldtype": "Link",
|
||||
"options": "Sales Person"
|
||||
},
|
||||
{
|
||||
"fieldname": "group_by_party",
|
||||
"label": __("Group By Customer"),
|
||||
"fieldtype": "Check"
|
||||
},
|
||||
{
|
||||
"fieldname":"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) {
|
||||
report.page.add_inner_button(__("Accounts Receivable Summary"), function() {
|
||||
var filters = report.get_values();
|
||||
|
||||
@@ -46,7 +46,7 @@ class ReceivablePayableReport(object):
|
||||
self.get_columns()
|
||||
self.get_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):
|
||||
if not self.filters.get("company"):
|
||||
@@ -57,6 +57,12 @@ class ReceivablePayableReport(object):
|
||||
self.party_type = self.filters.party_type
|
||||
self.party_details = {}
|
||||
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):
|
||||
self.get_gl_entries()
|
||||
@@ -102,6 +108,12 @@ class ReceivablePayableReport(object):
|
||||
)
|
||||
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):
|
||||
if gle.voucher_type in ('Sales Invoice', 'Purchase Invoice'):
|
||||
if self.filters.get("sales_person"):
|
||||
@@ -111,6 +123,20 @@ class ReceivablePayableReport(object):
|
||||
else:
|
||||
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):
|
||||
# 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
|
||||
@@ -135,6 +161,18 @@ class ReceivablePayableReport(object):
|
||||
# advance / unlinked payment or other adjustment
|
||||
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):
|
||||
if self.filters.get("sales_person"):
|
||||
against_voucher = gle.against_voucher or gle.voucher_no
|
||||
@@ -192,11 +230,22 @@ class ReceivablePayableReport(object):
|
||||
else:
|
||||
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):
|
||||
self.allocate_future_payments(row)
|
||||
self.set_invoice_details(row)
|
||||
self.set_party_details(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)
|
||||
|
||||
def set_invoice_details(self, row):
|
||||
@@ -503,6 +552,7 @@ class ReceivablePayableReport(object):
|
||||
# get all the GL entries filtered by the given filters
|
||||
|
||||
conditions, values = self.prepare_conditions()
|
||||
order_by = self.get_order_by_condition()
|
||||
|
||||
if self.filters.get(scrub(self.party_type)):
|
||||
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 is not null and party != '')
|
||||
and posting_date <= %s
|
||||
{1}
|
||||
order by posting_date, party"""
|
||||
.format(select_fields, conditions), values, as_dict=True)
|
||||
{1} {2}"""
|
||||
.format(select_fields, conditions, order_by), values, as_dict=True)
|
||||
|
||||
def get_sales_invoices_or_customers_based_on_sales_person(self):
|
||||
if self.filters.get("sales_person"):
|
||||
@@ -557,6 +606,12 @@ class ReceivablePayableReport(object):
|
||||
|
||||
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):
|
||||
if self.filters.company:
|
||||
conditions.append("company=%s")
|
||||
@@ -736,11 +791,13 @@ class ReceivablePayableReport(object):
|
||||
def get_chart_data(self):
|
||||
rows = []
|
||||
for row in self.data:
|
||||
values = [row.range1, row.range2, row.range3, row.range4, row.range5]
|
||||
precision = cint(frappe.db.get_default("float_precision")) or 2
|
||||
rows.append({
|
||||
'values': [flt(val, precision) for val in values]
|
||||
})
|
||||
row = frappe._dict(row)
|
||||
if not cint(row.bold):
|
||||
values = [row.range1, row.range2, row.range3, row.range4, row.range5]
|
||||
precision = cint(frappe.db.get_default("float_precision")) or 2
|
||||
rows.append({
|
||||
'values': [flt(val, precision) for val in values]
|
||||
})
|
||||
|
||||
self.chart = {
|
||||
"data": {
|
||||
|
||||
@@ -14,6 +14,7 @@ frappe.require("assets/erpnext/js/financial_statements.js", function() {
|
||||
frappe.query_reports["Balance Sheet"]["filters"].push({
|
||||
"fieldname": "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",
|
||||
"label": __("Include Default Book Entries"),
|
||||
"fieldtype": "Check"
|
||||
"fieldtype": "Check",
|
||||
"default": 1
|
||||
}
|
||||
);
|
||||
});
|
||||
@@ -4,7 +4,7 @@
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
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.profit_and_loss_statement.profit_and_loss_statement import get_net_profit_loss
|
||||
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 = ""
|
||||
filters = frappe._dict(filters)
|
||||
|
||||
if filters.finance_book:
|
||||
cond = " and finance_book = %s" %(frappe.db.escape(filters.finance_book))
|
||||
if filters.include_default_book_entries:
|
||||
company_fb = frappe.db.get_value("Company", company, 'default_finance_book')
|
||||
if filters.include_default_book_entries:
|
||||
company_fb = frappe.db.get_value("Company", company, 'default_finance_book')
|
||||
cond = """ AND (finance_book in (%s, %s, '') OR finance_book IS NULL)
|
||||
""" %(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("""
|
||||
select sum(credit) - sum(debit)
|
||||
|
||||
@@ -58,7 +58,8 @@ frappe.query_reports["Consolidated Financial Statement"] = {
|
||||
{
|
||||
"fieldname": "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:
|
||||
additional_conditions.append("gl.posting_date >= %(from_date)s")
|
||||
|
||||
if filters.get("finance_book"):
|
||||
if filters.get("include_default_book_entries"):
|
||||
additional_conditions.append("finance_book in (%(finance_book)s, %(company_fb)s)")
|
||||
else:
|
||||
additional_conditions.append("finance_book in (%(finance_book)s)")
|
||||
if filters.get("include_default_book_entries"):
|
||||
additional_conditions.append("(finance_book in (%(finance_book)s, %(company_fb)s, '') OR finance_book IS NULL)")
|
||||
else:
|
||||
additional_conditions.append("(finance_book in (%(finance_book)s, '') OR finance_book IS NULL)")
|
||||
|
||||
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.utils import get_fiscal_year
|
||||
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 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)
|
||||
|
||||
accounts = frappe.db.sql_list("""select name from `tabAccount`
|
||||
where lft >= %s and rgt <= %s""", (root_lft, root_rgt))
|
||||
additional_conditions += " and account in ({})"\
|
||||
.format(", ".join([frappe.db.escape(d) for d in accounts]))
|
||||
where lft >= %s and rgt <= %s and company = %s""", (root_lft, root_rgt, company))
|
||||
|
||||
gl_filters = {
|
||||
"company": company,
|
||||
"from_date": from_date,
|
||||
"to_date": to_date,
|
||||
"finance_book": filters.get("finance_book")
|
||||
}
|
||||
if accounts:
|
||||
additional_conditions += " and account in ({})"\
|
||||
.format(", ".join([frappe.db.escape(d) for d in accounts]))
|
||||
|
||||
if filters.get("include_default_book_entries"):
|
||||
gl_filters["company_fb"] = frappe.db.get_value("Company",
|
||||
company, 'default_finance_book')
|
||||
gl_filters = {
|
||||
"company": company,
|
||||
"from_date": from_date,
|
||||
"to_date": to_date,
|
||||
"finance_book": cstr(filters.get("finance_book"))
|
||||
}
|
||||
|
||||
for key, value in filters.items():
|
||||
if value:
|
||||
gl_filters.update({
|
||||
key: value
|
||||
})
|
||||
if filters.get("include_default_book_entries"):
|
||||
gl_filters["company_fb"] = frappe.db.get_value("Company",
|
||||
company, 'default_finance_book')
|
||||
|
||||
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`
|
||||
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 key, value in filters.items():
|
||||
if value:
|
||||
gl_filters.update({
|
||||
key: value
|
||||
})
|
||||
|
||||
if filters and filters.get('presentation_currency'):
|
||||
convert_to_presentation_currency(gl_entries, get_currency(filters))
|
||||
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`
|
||||
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:
|
||||
gl_entries_by_account.setdefault(entry.account, []).append(entry)
|
||||
if filters and filters.get('presentation_currency'):
|
||||
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):
|
||||
@@ -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)
|
||||
additional_conditions.append("cost_center in %(cost_center)s")
|
||||
|
||||
if filters.get("finance_book"):
|
||||
if filters.get("include_default_book_entries"):
|
||||
additional_conditions.append("finance_book in (%(finance_book)s, %(company_fb)s)")
|
||||
else:
|
||||
additional_conditions.append("finance_book in (%(finance_book)s)")
|
||||
|
||||
if filters.get("include_default_book_entries"):
|
||||
additional_conditions.append("(finance_book in (%(finance_book)s, %(company_fb)s, '') OR finance_book IS NULL)")
|
||||
else:
|
||||
additional_conditions.append("(finance_book in (%(finance_book)s, '') OR finance_book IS NULL)")
|
||||
|
||||
if accounting_dimensions:
|
||||
for dimension in accounting_dimensions:
|
||||
if filters.get(dimension):
|
||||
|
||||
@@ -154,7 +154,8 @@ frappe.query_reports["General Ledger"] = {
|
||||
{
|
||||
"fieldname": "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,
|
||||
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"):
|
||||
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("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:
|
||||
conditions.append("finance_book in (%(finance_book)s)")
|
||||
|
||||
|
||||
@@ -34,6 +34,20 @@ frappe.query_reports["Item-wise Purchase Register"] = {
|
||||
"label": __("Mode of Payment"),
|
||||
"fieldtype": "Link",
|
||||
"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
|
||||
from frappe import _
|
||||
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):
|
||||
return _execute(filters)
|
||||
@@ -13,7 +15,7 @@ def execute(filters=None):
|
||||
def _execute(filters=None, additional_table_columns=None, additional_query_columns=None):
|
||||
if not filters: filters = {}
|
||||
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)
|
||||
|
||||
@@ -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,
|
||||
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)
|
||||
|
||||
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:
|
||||
if not d.stock_qty:
|
||||
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, []))
|
||||
|
||||
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:
|
||||
for col in additional_query_columns:
|
||||
row.append(d.get(col))
|
||||
row.update({
|
||||
col: d.get(col)
|
||||
})
|
||||
|
||||
row += [
|
||||
d.credit_to, d.mode_of_payment, d.project, d.company, d.purchase_order,
|
||||
purchase_receipt, expense_account, d.stock_qty, d.stock_uom, d.base_net_amount / d.stock_qty, d.base_net_amount
|
||||
]
|
||||
row.update({
|
||||
'credit_to': d.credit_to,
|
||||
'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
|
||||
for tax in tax_columns:
|
||||
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"))
|
||||
|
||||
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)
|
||||
|
||||
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):
|
||||
columns = [
|
||||
_("Item Code") + ":Link/Item:120", _("Item Name") + "::120",
|
||||
_("Item Group") + ":Link/Item Group:100", "Description::150", _("Invoice") + ":Link/Purchase Invoice:120",
|
||||
_("Posting Date") + ":Date:80", _("Supplier") + ":Link/Supplier:120",
|
||||
"Supplier Name::120"
|
||||
]
|
||||
def get_columns(additional_table_columns, filters):
|
||||
|
||||
columns = []
|
||||
|
||||
if filters.get('group_by') != ('Item'):
|
||||
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:
|
||||
columns += additional_table_columns
|
||||
|
||||
columns += [
|
||||
"Payable Account:Link/Account:120",
|
||||
_("Mode of Payment") + ":Link/Mode of Payment:80", _("Project") + ":Link/Project:80",
|
||||
_("Company") + ":Link/Company:100", _("Purchase Order") + ":Link/Purchase Order:100",
|
||||
_("Purchase Receipt") + ":Link/Purchase Receipt:100", _("Expense Account") + ":Link/Account:140",
|
||||
_("Stock Qty") + ":Float:120", _("Stock UOM") + "::100",
|
||||
_("Rate") + ":Currency/currency:120", _("Amount") + ":Currency/currency:120"
|
||||
{
|
||||
'label': _('Payable Account'),
|
||||
'fieldname': 'credit_to',
|
||||
'fieldtype': 'Link',
|
||||
'options': 'Account',
|
||||
'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
|
||||
|
||||
def get_conditions(filters):
|
||||
@@ -103,14 +297,15 @@ def get_conditions(filters):
|
||||
if filters.get(opts[0]):
|
||||
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
|
||||
|
||||
def get_items(filters, additional_query_columns):
|
||||
conditions = get_conditions(filters)
|
||||
match_conditions = frappe.build_match_conditions("Purchase Invoice")
|
||||
|
||||
if match_conditions:
|
||||
match_conditions = " and {0} ".format(match_conditions)
|
||||
|
||||
if additional_query_columns:
|
||||
additional_query_columns = ', ' + ', '.join(additional_query_columns)
|
||||
@@ -128,9 +323,8 @@ def get_items(filters, additional_query_columns):
|
||||
`tabPurchase Invoice`.supplier_name, `tabPurchase Invoice`.mode_of_payment {0}
|
||||
from `tabPurchase Invoice`, `tabPurchase Invoice Item`
|
||||
where `tabPurchase Invoice`.name = `tabPurchase Invoice Item`.`parent` and
|
||||
`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)
|
||||
`tabPurchase Invoice`.docstatus = 1 %s
|
||||
""".format(additional_query_columns) % (conditions), filters, as_dict=1)
|
||||
|
||||
def get_aii_accounts():
|
||||
return dict(frappe.db.sql("select name, stock_received_but_not_billed from tabCompany"))
|
||||
|
||||
@@ -4,48 +4,62 @@
|
||||
frappe.query_reports["Item-wise Sales Register"] = {
|
||||
"filters": [
|
||||
{
|
||||
"fieldname":"date_range",
|
||||
"fieldname": "date_range",
|
||||
"label": __("Date Range"),
|
||||
"fieldtype": "DateRange",
|
||||
"default": [frappe.datetime.add_months(frappe.datetime.get_today(),-1), frappe.datetime.get_today()],
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname":"customer",
|
||||
"fieldname": "customer",
|
||||
"label": __("Customer"),
|
||||
"fieldtype": "Link",
|
||||
"options": "Customer"
|
||||
},
|
||||
{
|
||||
"fieldname":"company",
|
||||
"fieldname": "company",
|
||||
"label": __("Company"),
|
||||
"fieldtype": "Link",
|
||||
"options": "Company",
|
||||
"default": frappe.defaults.get_user_default("Company")
|
||||
},
|
||||
{
|
||||
"fieldname":"mode_of_payment",
|
||||
"fieldname": "mode_of_payment",
|
||||
"label": __("Mode of Payment"),
|
||||
"fieldtype": "Link",
|
||||
"options": "Mode of Payment"
|
||||
},
|
||||
{
|
||||
"fieldname":"warehouse",
|
||||
"fieldname": "warehouse",
|
||||
"label": __("Warehouse"),
|
||||
"fieldtype": "Link",
|
||||
"options": "Warehouse"
|
||||
},
|
||||
{
|
||||
"fieldname":"brand",
|
||||
"fieldname": "brand",
|
||||
"label": __("Brand"),
|
||||
"fieldtype": "Link",
|
||||
"options": "Brand"
|
||||
},
|
||||
{
|
||||
"fieldname":"item_group",
|
||||
"fieldname": "item_group",
|
||||
"label": __("Item Group"),
|
||||
"fieldtype": "Link",
|
||||
"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
|
||||
import frappe, erpnext
|
||||
from frappe import _
|
||||
from frappe.utils import flt
|
||||
from frappe.utils import flt, cstr
|
||||
from frappe.model.meta import get_field_precision
|
||||
from frappe.utils.xlsxutils import handle_html
|
||||
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):
|
||||
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]})
|
||||
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")
|
||||
|
||||
item_list = get_items(filters, additional_query_columns)
|
||||
if item_list:
|
||||
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]))
|
||||
so_dn_map = get_delivery_notes_against_sales_order(item_list)
|
||||
|
||||
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:
|
||||
delivery_note = None
|
||||
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:
|
||||
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:
|
||||
for col in additional_query_columns:
|
||||
row.append(d.get(col))
|
||||
row.update({
|
||||
col: d.get(col)
|
||||
})
|
||||
|
||||
row += [
|
||||
d.customer_group, d.debit_to, ", ".join(mode_of_payments.get(d.parent, [])),
|
||||
d.territory, d.project, d.company, d.sales_order,
|
||||
delivery_note, d.income_account, d.cost_center, d.stock_qty, d.stock_uom
|
||||
]
|
||||
row.update({
|
||||
'debit_to': d.debit_to,
|
||||
'mode_of_payment': ", ".join(mode_of_payments.get(d.parent, [])),
|
||||
'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:
|
||||
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:
|
||||
row += [d.base_net_rate, d.base_net_amount]
|
||||
row.update({
|
||||
'rate': d.base_net_rate,
|
||||
'amount': d.base_net_amount
|
||||
})
|
||||
|
||||
total_tax = 0
|
||||
for tax in tax_columns:
|
||||
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"))
|
||||
|
||||
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)
|
||||
|
||||
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
|
||||
|
||||
def get_columns(additional_table_columns):
|
||||
columns = [
|
||||
_("Item Code") + ":Link/Item:120", _("Item Name") + "::120",
|
||||
_("Item Group") + ":Link/Item Group:100", "Description::150", _("Invoice") + ":Link/Sales Invoice:120",
|
||||
_("Posting Date") + ":Date:80", _("Customer") + ":Link/Customer:120",
|
||||
_("Customer Name") + "::120"]
|
||||
return columns, data, None, None, None, skip_total_row
|
||||
|
||||
def get_columns(additional_table_columns, filters):
|
||||
columns = []
|
||||
|
||||
if filters.get('group_by') != ('Item'):
|
||||
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': '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:
|
||||
columns += additional_table_columns
|
||||
|
||||
columns += [
|
||||
_("Customer Group") + ":Link/Customer Group:120",
|
||||
_("Receivable Account") + ":Link/Account:120",
|
||||
_("Mode of Payment") + "::120", _("Territory") + ":Link/Territory:80",
|
||||
_("Project") + ":Link/Project:80", _("Company") + ":Link/Company:100",
|
||||
_("Sales Order") + ":Link/Sales Order:100", _("Delivery Note") + ":Link/Delivery Note:100",
|
||||
_("Income Account") + ":Link/Account:140", _("Cost Center") + ":Link/Cost Center:140",
|
||||
_("Stock Qty") + ":Float:120", _("Stock UOM") + "::100",
|
||||
_("Rate") + ":Currency/currency:120",
|
||||
_("Amount") + ":Currency/currency:120"
|
||||
{
|
||||
'label': _('Receivable Account'),
|
||||
'fieldname': 'debit_to',
|
||||
'fieldtype': 'Link',
|
||||
'options': 'Account',
|
||||
'width': 80
|
||||
},
|
||||
{
|
||||
'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
|
||||
|
||||
def get_conditions(filters):
|
||||
@@ -112,30 +342,34 @@ def get_conditions(filters):
|
||||
and ifnull(`tabSales Invoice Payment`.mode_of_payment, '') = %(mode_of_payment)s)"""
|
||||
|
||||
if filters.get("warehouse"):
|
||||
conditions += """ and exists(select name from `tabSales Invoice Item`
|
||||
where parent=`tabSales Invoice`.name
|
||||
and ifnull(`tabSales Invoice Item`.warehouse, '') = %(warehouse)s)"""
|
||||
conditions += """and ifnull(`tabSales Invoice Item`.warehouse, '') = %(warehouse)s"""
|
||||
|
||||
|
||||
if filters.get("brand"):
|
||||
conditions += """ and exists(select name from `tabSales Invoice Item`
|
||||
where parent=`tabSales Invoice`.name
|
||||
and ifnull(`tabSales Invoice Item`.brand, '') = %(brand)s)"""
|
||||
conditions += """and ifnull(`tabSales Invoice Item`.brand, '') = %(brand)s"""
|
||||
|
||||
if filters.get("item_group"):
|
||||
conditions += """ and exists(select name from `tabSales Invoice Item`
|
||||
where parent=`tabSales Invoice`.name
|
||||
and ifnull(`tabSales Invoice Item`.item_group, '') = %(item_group)s)"""
|
||||
conditions += """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
|
||||
|
||||
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):
|
||||
conditions = get_conditions(filters)
|
||||
match_conditions = frappe.build_match_conditions("Sales Invoice")
|
||||
|
||||
if match_conditions:
|
||||
match_conditions = " and {0} ".format(match_conditions)
|
||||
|
||||
if additional_query_columns:
|
||||
additional_query_columns = ', ' + ', '.join(additional_query_columns)
|
||||
@@ -156,9 +390,8 @@ def get_items(filters, additional_query_columns):
|
||||
`tabSales Invoice`.update_stock, `tabSales Invoice Item`.uom, `tabSales Invoice Item`.qty {0}
|
||||
from `tabSales Invoice`, `tabSales Invoice Item`
|
||||
where `tabSales Invoice`.name = `tabSales Invoice Item`.parent
|
||||
and `tabSales Invoice`.docstatus = 1 %s %s
|
||||
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)
|
||||
and `tabSales Invoice`.docstatus = 1 {1}
|
||||
""".format(additional_query_columns or '', conditions), filters, as_dict=1) #nosec
|
||||
|
||||
def get_delivery_notes_against_sales_order(item_list):
|
||||
so_dn_map = frappe._dict()
|
||||
@@ -177,6 +410,15 @@ def get_delivery_notes_against_sales_order(item_list):
|
||||
|
||||
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():
|
||||
return frappe.db.sql_list("select name from `tabPurchase Taxes and Charges` where add_deduct_tax = 'Deduct'")
|
||||
|
||||
@@ -264,9 +506,117 @@ def get_tax_accounts(item_list, columns, company_currency,
|
||||
|
||||
tax_columns.sort()
|
||||
for desc in tax_columns:
|
||||
columns.append(desc + " Rate:Data:80")
|
||||
columns.append(desc + " Amount:Currency/currency:100")
|
||||
columns.append({
|
||||
'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
|
||||
|
||||
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",
|
||||
"label": __("Include Default Book Entries"),
|
||||
"fieldtype": "Check"
|
||||
"fieldtype": "Check",
|
||||
"default": 1
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
@@ -139,7 +139,7 @@ def get_columns(invoice_list, additional_table_columns):
|
||||
|
||||
columns +=[
|
||||
{
|
||||
'label': _("Custmer Group"),
|
||||
'label': _("Customer Group"),
|
||||
'fieldname': 'customer_group',
|
||||
'fieldtype': 'Link',
|
||||
'options': 'Customer Group',
|
||||
@@ -175,7 +175,7 @@ def get_columns(invoice_list, additional_table_columns):
|
||||
'label': _("Project"),
|
||||
'fieldname': 'project',
|
||||
'fieldtype': 'Link',
|
||||
'options': 'project',
|
||||
'options': 'Project',
|
||||
'width': 80
|
||||
},
|
||||
{
|
||||
|
||||
@@ -85,7 +85,8 @@ frappe.require("assets/erpnext/js/financial_statements.js", function() {
|
||||
{
|
||||
"fieldname": "include_default_book_entries",
|
||||
"label": __("Include Default Book Entries"),
|
||||
"fieldtype": "Check"
|
||||
"fieldtype": "Check",
|
||||
"default": 1
|
||||
}
|
||||
],
|
||||
"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)
|
||||
|
||||
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:
|
||||
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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
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 = account_type or party_account_type
|
||||
else:
|
||||
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 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:
|
||||
frappe.throw(_("Set {0} in asset category {1} or company {2}")
|
||||
.format(account_name.replace('_', ' ').title(), asset_category, company))
|
||||
|
||||
@@ -22,7 +22,7 @@ def post_depreciation_entries(date=None):
|
||||
def get_depreciable_assets(date):
|
||||
return frappe.db.sql_list("""select a.name
|
||||
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 ifnull(ds.journal_entry, '')=''""", date)
|
||||
|
||||
|
||||
@@ -1,580 +1,146 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"actions": [],
|
||||
"allow_import": 1,
|
||||
"allow_rename": 1,
|
||||
"autoname": "field:location_name",
|
||||
"beta": 0,
|
||||
"creation": "2018-05-07 12:49:22.595974",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "",
|
||||
"editable_grid": 1,
|
||||
"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": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "location_name",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Location Name",
|
||||
"length": 0,
|
||||
"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,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "parent_location",
|
||||
"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",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Location",
|
||||
"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": 1,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
"search_index": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "cb_details",
|
||||
"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
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "0",
|
||||
"description": "Check if it is a hydroponic unit",
|
||||
"fieldname": "is_container",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "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
|
||||
"label": "Is Container"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 1,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "0",
|
||||
"fieldname": "is_group",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "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
|
||||
"label": "Is Group"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "sb_location_details",
|
||||
"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,
|
||||
"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
|
||||
"label": "Location Details"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_from": "parent_location.latitude",
|
||||
"fieldname": "latitude",
|
||||
"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": "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
|
||||
"label": "Latitude"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_from": "parent_location.longitude",
|
||||
"fieldname": "longitude",
|
||||
"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": "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
|
||||
"label": "Longitude"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "cb_latlong",
|
||||
"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
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "area",
|
||||
"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",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "eval:doc.area",
|
||||
"fieldname": "area_uom",
|
||||
"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",
|
||||
"length": 0,
|
||||
"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
|
||||
"options": "UOM"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "sb_geolocation",
|
||||
"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
|
||||
"fieldtype": "Section Break"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "location",
|
||||
"fieldtype": "Geolocation",
|
||||
"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": "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
|
||||
"label": "Location"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "tree_details",
|
||||
"fieldtype": "Section Break",
|
||||
"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": "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
|
||||
"label": "Tree Details"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "lft",
|
||||
"fieldtype": "Int",
|
||||
"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",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 1,
|
||||
"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
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "rgt",
|
||||
"fieldtype": "Int",
|
||||
"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",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 1,
|
||||
"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
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "old_parent",
|
||||
"fieldtype": "Data",
|
||||
"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",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 1,
|
||||
"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
|
||||
"read_only": 1
|
||||
}
|
||||
],
|
||||
"has_web_view": 0,
|
||||
"hide_heading": 0,
|
||||
"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",
|
||||
"links": [],
|
||||
"modified": "2020-01-28 13:52:22.513425",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Assets",
|
||||
"name": "Location",
|
||||
@@ -582,127 +148,78 @@
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"amend": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "System Manager",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 0,
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Stock User",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 0,
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Accounts User",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 0,
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Stock Manager",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 0,
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Agriculture Manager",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 0,
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"cancel": 0,
|
||||
"create": 0,
|
||||
"delete": 0,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Agriculture User",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 0,
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"quick_entry": 1,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"show_name_in_global_search": 1,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1,
|
||||
"track_seen": 0,
|
||||
"track_views": 0
|
||||
"track_changes": 1
|
||||
}
|
||||
@@ -20,6 +20,16 @@ frappe.query_reports["Fixed Asset Register"] = {
|
||||
default: 'In Location',
|
||||
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",
|
||||
label: __("Finance Book"),
|
||||
@@ -27,10 +37,15 @@ frappe.query_reports["Fixed Asset Register"] = {
|
||||
options: "Finance Book"
|
||||
},
|
||||
{
|
||||
fieldname:"date",
|
||||
label: __("Date"),
|
||||
fieldtype: "Date",
|
||||
default: frappe.datetime.get_today()
|
||||
fieldname:"asset_category",
|
||||
label: __("Asset Category"),
|
||||
fieldtype: "Link",
|
||||
options: "Asset Category"
|
||||
},
|
||||
{
|
||||
fieldname:"is_existing_asset",
|
||||
label: __("Is Existing Asset"),
|
||||
fieldtype: "Check"
|
||||
},
|
||||
]
|
||||
};
|
||||
|
||||
@@ -40,6 +40,42 @@ def get_columns(filters):
|
||||
"fieldname": "status",
|
||||
"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"),
|
||||
"fieldtype": "Link",
|
||||
@@ -54,25 +90,6 @@ def get_columns(filters):
|
||||
"options": "Department",
|
||||
"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"),
|
||||
"fieldtype": "Data",
|
||||
@@ -80,25 +97,29 @@ def get_columns(filters):
|
||||
"width": 100
|
||||
},
|
||||
{
|
||||
"label": _("Available For Use Date"),
|
||||
"fieldtype": "Date",
|
||||
"fieldname": "available_for_use_date",
|
||||
"width": 90
|
||||
},
|
||||
{
|
||||
"label": _("Asset Value"),
|
||||
"fieldname": "asset_value",
|
||||
"options": "Currency",
|
||||
"width": 90
|
||||
"label": _("Location"),
|
||||
"fieldtype": "Link",
|
||||
"fieldname": "location",
|
||||
"options": "Location",
|
||||
"width": 100
|
||||
},
|
||||
]
|
||||
|
||||
def get_conditions(filters):
|
||||
conditions = {'docstatus': 1}
|
||||
conditions = { 'docstatus': 1 }
|
||||
status = filters.status
|
||||
date = filters.date
|
||||
|
||||
if filters.company:
|
||||
if filters.get('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
|
||||
operand = 'not in'
|
||||
@@ -114,7 +135,7 @@ def get_data(filters):
|
||||
data = []
|
||||
|
||||
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()
|
||||
pi_supplier_map = get_purchase_invoice_supplier_map()
|
||||
|
||||
@@ -136,6 +157,8 @@ def get_data(filters):
|
||||
"cost_center": asset.cost_center,
|
||||
"vendor_name": pr_supplier_map.get(asset.purchase_receipt) or pi_supplier_map.get(asset.purchase_invoice),
|
||||
"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,
|
||||
"location": asset.location,
|
||||
"asset_category": asset.asset_category,
|
||||
@@ -146,9 +169,9 @@ def get_data(filters):
|
||||
|
||||
return data
|
||||
|
||||
def get_finance_book_value_map(date, finance_book=''):
|
||||
if not date:
|
||||
date = today()
|
||||
def get_finance_book_value_map(filters):
|
||||
date = filters.get('purchase_date') or filters.get('available_for_use_date') or today()
|
||||
|
||||
return frappe._dict(frappe.db.sql(''' Select
|
||||
parent, SUM(depreciation_amount)
|
||||
FROM `tabDepreciation Schedule`
|
||||
@@ -157,7 +180,7 @@ def get_finance_book_value_map(date, finance_book=''):
|
||||
AND schedule_date<=%s
|
||||
AND journal_entry IS NOT NULL
|
||||
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():
|
||||
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",{
|
||||
setup: function(frm) {
|
||||
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) {
|
||||
|
||||
@@ -141,13 +141,13 @@ def get_conditions(filters):
|
||||
conditions = ""
|
||||
|
||||
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"):
|
||||
conditions += """
|
||||
AND (cost_center='%s'
|
||||
OR project='%s')
|
||||
"""% (filters.get('cost_center'), filters.get('project'))
|
||||
AND (cost_center=%s
|
||||
OR project=%s)
|
||||
"""% (frappe.db.escape(filters.get('cost_center')), frappe.db.escape(filters.get('project')))
|
||||
|
||||
if 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.uom = item.stock_uom
|
||||
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
|
||||
|
||||
|
||||
|
||||
@@ -182,7 +182,7 @@ class StatusUpdater(Document):
|
||||
if args.get('no_allowance'):
|
||||
item['reduce_by'] = item[args['target_field']] - item[args['target_ref_field']]
|
||||
if item['reduce_by'] > .01:
|
||||
self.limits_crossed_error(args, item)
|
||||
self.limits_crossed_error(args, item, "qty")
|
||||
|
||||
elif item[args['target_ref_field']]:
|
||||
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(
|
||||
_(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):
|
||||
sl_dict = frappe._dict({
|
||||
"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()):
|
||||
frappe.throw(_("Next Contact Date cannot be in the past"))
|
||||
|
||||
if self.ends_on and self.contact_date and\
|
||||
(self.ends_on < self.contact_date):
|
||||
if (self.ends_on and self.contact_date and
|
||||
(getdate(self.ends_on) < getdate(self.contact_date))):
|
||||
frappe.throw(_("Ends On date cannot be before Next Contact Date."))
|
||||
|
||||
def on_update(self):
|
||||
|
||||
@@ -308,7 +308,7 @@ def set_multiple_status(names, status):
|
||||
|
||||
def auto_close_opportunity():
|
||||
""" 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
|
||||
modified<DATE_SUB(CURDATE(), INTERVAL %s DAY) """, (auto_close_after_days), as_dict=True)
|
||||
|
||||
@@ -1,28 +1,29 @@
|
||||
{
|
||||
"add_total_row": 0,
|
||||
"creation": "2013-10-22 11:58:16",
|
||||
"disabled": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "Report",
|
||||
"idx": 3,
|
||||
"is_standard": "Yes",
|
||||
"modified": "2018-09-26 18:59:46.520731",
|
||||
"modified_by": "Administrator",
|
||||
"module": "CRM",
|
||||
"name": "Lead Details",
|
||||
"owner": "Administrator",
|
||||
"prepared_report": 0,
|
||||
"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",
|
||||
"ref_doctype": "Lead",
|
||||
"report_name": "Lead Details",
|
||||
"report_type": "Query Report",
|
||||
"add_total_row": 0,
|
||||
"creation": "2013-10-22 11:58:16",
|
||||
"disable_prepared_report": 0,
|
||||
"disabled": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "Report",
|
||||
"idx": 3,
|
||||
"is_standard": "Yes",
|
||||
"modified": "2020-01-22 16:51:56.591110",
|
||||
"modified_by": "Administrator",
|
||||
"module": "CRM",
|
||||
"name": "Lead Details",
|
||||
"owner": "Administrator",
|
||||
"prepared_report": 0,
|
||||
"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",
|
||||
"ref_doctype": "Lead",
|
||||
"report_name": "Lead Details",
|
||||
"report_type": "Query Report",
|
||||
"roles": [
|
||||
{
|
||||
"role": "Sales User"
|
||||
},
|
||||
},
|
||||
{
|
||||
"role": "Sales Manager"
|
||||
},
|
||||
},
|
||||
{
|
||||
"role": "System Manager"
|
||||
}
|
||||
|
||||
@@ -123,9 +123,11 @@ def get_students(student_group, academic_year, academic_term=None, student_categ
|
||||
|
||||
students = frappe.db.sql("""
|
||||
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
|
||||
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
|
||||
{conditions}
|
||||
""".format(conditions=conditions), (academic_year, student_group), as_dict=1)
|
||||
|
||||
@@ -49,9 +49,10 @@
|
||||
},
|
||||
{
|
||||
"fieldname": "plaid_env",
|
||||
"fieldtype": "Data",
|
||||
"fieldtype": "Select",
|
||||
"in_list_view": 1,
|
||||
"label": "Plaid Environment"
|
||||
"label": "Plaid Environment",
|
||||
"options": "sandbox\ndevelopment\nproduction"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_2",
|
||||
@@ -69,7 +70,7 @@
|
||||
],
|
||||
"issingle": 1,
|
||||
"links": [],
|
||||
"modified": "2020-01-05 10:00:22.137832",
|
||||
"modified": "2020-02-07 15:21:11.616231",
|
||||
"modified_by": "Administrator",
|
||||
"module": "ERPNext Integrations",
|
||||
"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.erpnext_integrations.doctype.plaid_settings.plaid_connector import PlaidConnector
|
||||
from frappe.utils import getdate, formatdate, today, add_months
|
||||
from frappe.desk.doctype.tag.tag import add_tag
|
||||
|
||||
class PlaidSettings(Document):
|
||||
pass
|
||||
@@ -53,7 +54,11 @@ def add_institution(token, response):
|
||||
|
||||
@frappe.whitelist()
|
||||
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)
|
||||
result = []
|
||||
|
||||
@@ -129,10 +134,13 @@ def sync_transactions(bank, bank_account):
|
||||
|
||||
try:
|
||||
transactions = get_transactions(bank=bank, bank_account=bank_account, start_date=start_date, end_date=end_date)
|
||||
|
||||
result = []
|
||||
if transactions:
|
||||
for transaction in transactions:
|
||||
result.append(new_bank_transaction(transaction))
|
||||
for transaction in reversed(transactions):
|
||||
result += 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))
|
||||
|
||||
@@ -171,6 +179,13 @@ def new_bank_transaction(transaction):
|
||||
|
||||
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"])):
|
||||
try:
|
||||
new_transaction = frappe.get_doc({
|
||||
@@ -181,11 +196,16 @@ def new_bank_transaction(transaction):
|
||||
"debit": debit,
|
||||
"credit": credit,
|
||||
"currency": transaction["iso_currency_code"],
|
||||
"transaction_id": transaction["transaction_id"],
|
||||
"reference_number": transaction["payment_meta"]["reference_number"],
|
||||
"description": transaction["name"]
|
||||
})
|
||||
new_transaction.insert()
|
||||
new_transaction.submit()
|
||||
|
||||
for tag in tags:
|
||||
add_tag(tag, "Bank Transaction", new_transaction.name)
|
||||
|
||||
result.append(new_transaction.name)
|
||||
|
||||
except Exception:
|
||||
@@ -197,7 +217,7 @@ def automatic_synchronization():
|
||||
settings = frappe.get_doc("Plaid Settings", "Plaid Settings")
|
||||
|
||||
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:
|
||||
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",{
|
||||
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);
|
||||
if(!frm.doc.lab_test_description)
|
||||
if (!frm.doc.lab_test_description)
|
||||
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
|
||||
frm.set_query("lab_test_template", "lab_test_groups", function() {
|
||||
return {
|
||||
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.set_df_property("lab_test_code", "read_only", doc.__islocal ? 0 : 1);
|
||||
|
||||
if(!doc.__islocal) {
|
||||
cur_frm.add_custom_button(__('Change Template Code'), function() {
|
||||
change_template_code(cur_frm,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);
|
||||
} );
|
||||
}
|
||||
if (!doc.__islocal) {
|
||||
cur_frm.add_custom_button(__("Change Template Code"), function() {
|
||||
change_template_code(doc);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
var disable_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: 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({
|
||||
let change_template_code = function(doc) {
|
||||
let d = new frappe.ui.Dialog({
|
||||
title:__("Change Template Code"),
|
||||
fields:[
|
||||
{
|
||||
"fieldtype": "Data",
|
||||
"label": "Test Template Code",
|
||||
"fieldname": "Test Code",
|
||||
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();
|
||||
}
|
||||
"label": "Lab Test Template Code",
|
||||
"fieldname": "lab_test_code",
|
||||
reqd: 1
|
||||
}
|
||||
]
|
||||
],
|
||||
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.set_values({
|
||||
'Test Code': doc.lab_test_code
|
||||
});
|
||||
|
||||
var change_test_code_from_template = function(lab_test_code,doc){
|
||||
frappe.call({
|
||||
"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);
|
||||
}
|
||||
});
|
||||
};
|
||||
d.set_values({
|
||||
"lab_test_code": doc.lab_test_code
|
||||
});
|
||||
};
|
||||
|
||||
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) {
|
||||
var child = locals[cdt][cdn];
|
||||
if(child.template_or_new_line =="Add new line"){
|
||||
let child = locals[cdt][cdn];
|
||||
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_description', "");
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -8,59 +8,76 @@ from frappe.model.document import Document
|
||||
from frappe import _
|
||||
|
||||
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):
|
||||
#Item and Price List update --> if (change_in_item)
|
||||
if(self.change_in_item and self.is_billable == 1 and self.item):
|
||||
updating_item(self)
|
||||
item_price = item_price_exist(self)
|
||||
# if change_in_item update Item and Price List
|
||||
if self.change_in_item and self.is_billable and self.item:
|
||||
self.update_item()
|
||||
item_price = self.item_price_exists()
|
||||
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})
|
||||
if(self.lab_test_rate):
|
||||
if self.lab_test_rate:
|
||||
make_item_price(self.lab_test_code, price_list_name, self.lab_test_rate)
|
||||
else:
|
||||
make_item_price(self.lab_test_code, price_list_name, 0.0)
|
||||
else:
|
||||
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)
|
||||
elif(self.is_billable == 0 and self.item):
|
||||
frappe.db.set_value("Item",self.item,"disabled",1)
|
||||
frappe.db.set_value(self.doctype, self.name, "change_in_item", 0)
|
||||
|
||||
elif not self.is_billable and self.item:
|
||||
frappe.db.set_value("Item", self.item, "disabled", 1)
|
||||
|
||||
self.reload()
|
||||
|
||||
def after_insert(self):
|
||||
if not self.item:
|
||||
create_item_from_template(self)
|
||||
|
||||
#Call before delete the template
|
||||
def on_trash(self):
|
||||
# remove template refernce from item and disable item
|
||||
if(self.item):
|
||||
# remove template reference from item and disable item
|
||||
if self.item:
|
||||
try:
|
||||
frappe.delete_doc("Item",self.item, force=True)
|
||||
frappe.delete_doc("Item", self.item)
|
||||
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):
|
||||
item_price = frappe.db.exists({
|
||||
"doctype": "Item Price",
|
||||
"item_code": doc.lab_test_code})
|
||||
if(item_price):
|
||||
return item_price[0][0]
|
||||
else:
|
||||
return False
|
||||
def enable_disable_item(self):
|
||||
if self.is_billable:
|
||||
if self.disabled:
|
||||
frappe.db.set_value('Item', self.item, 'disabled', 1)
|
||||
else:
|
||||
frappe.db.set_value('Item', self.item, 'disabled', 0)
|
||||
|
||||
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):
|
||||
if(doc.is_billable == 1):
|
||||
if doc.is_billable:
|
||||
disabled = 0
|
||||
else:
|
||||
disabled = 1
|
||||
#insert item
|
||||
# insert item
|
||||
item = frappe.get_doc({
|
||||
"doctype": "Item",
|
||||
"item_code": doc.lab_test_code,
|
||||
@@ -77,9 +94,9 @@ def create_item_from_template(doc):
|
||||
"stock_uom": "Unit"
|
||||
}).insert(ignore_permissions=True)
|
||||
|
||||
#insert item price
|
||||
#get item price list to insert item price
|
||||
if(doc.lab_test_rate != 0.0):
|
||||
# insert item price
|
||||
# get item price list to insert item price
|
||||
if doc.lab_test_rate != 0.0:
|
||||
price_list_name = frappe.db.get_value("Price List", {"selling": 1})
|
||||
if(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)
|
||||
item.standard_rate = 0.0
|
||||
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)
|
||||
|
||||
doc.reload() #refresh the doc after insert.
|
||||
doc.reload()
|
||||
|
||||
def make_item_price(item, price_list_name, item_price):
|
||||
frappe.get_doc({
|
||||
@@ -103,22 +120,13 @@ def make_item_price(item, price_list_name, item_price):
|
||||
|
||||
@frappe.whitelist()
|
||||
def change_test_code_from_template(lab_test_code, doc):
|
||||
args = json.loads(doc)
|
||||
doc = frappe._dict(args)
|
||||
doc = frappe._dict(json.loads(doc))
|
||||
|
||||
item_exist = frappe.db.exists({
|
||||
"doctype": "Item",
|
||||
"item_code": lab_test_code})
|
||||
if(item_exist):
|
||||
frappe.throw(_("Code {0} already exist").format(lab_test_code))
|
||||
if frappe.db.exists({ "doctype": "Item", "item_code": lab_test_code}):
|
||||
frappe.throw(_("Lab Test Item {0} already exist").format(lab_test_code))
|
||||
else:
|
||||
frappe.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.rename_doc("Lab Test Template", 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_name", lab_test_code)
|
||||
rename_doc("Lab Test Template", doc.name, lab_test_code, ignore_permissions=True)
|
||||
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'] = {
|
||||
add_fields: ["lab_test_name", "lab_test_code", "lab_test_rate"],
|
||||
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"];
|
||||
}
|
||||
} */
|
||||
filters: [["disabled", "=", 0]]
|
||||
};
|
||||
|
||||
@@ -13,7 +13,7 @@ class Attendance(Document):
|
||||
def validate_duplicate_record(self):
|
||||
res = frappe.db.sql("""select name from `tabAttendance` where employee = %s and attendance_date = %s
|
||||
and name != %s and docstatus != 2""",
|
||||
(self.employee, self.attendance_date, self.name))
|
||||
(self.employee, getdate(self.attendance_date), self.name))
|
||||
if res:
|
||||
frappe.throw(_("Attendance for employee {0} is already marked").format(self.employee))
|
||||
|
||||
|
||||
@@ -265,7 +265,7 @@
|
||||
"bold": 1,
|
||||
"fieldname": "person_to_be_contacted",
|
||||
"fieldtype": "Data",
|
||||
"label": "Emergency Contact"
|
||||
"label": "Emergency Contact Name"
|
||||
},
|
||||
{
|
||||
"fieldname": "relation",
|
||||
@@ -782,7 +782,7 @@
|
||||
"icon": "fa fa-user",
|
||||
"idx": 24,
|
||||
"image_field": "image",
|
||||
"modified": "2019-09-12 14:21:12.711280",
|
||||
"modified": "2020-01-09 04:23:55.611366",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "Employee",
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
// For license information, please see license.txt
|
||||
|
||||
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,
|
||||
"autoname": "EMP-CKIN-.MM.-.YYYY.-.######",
|
||||
"creation": "2019-06-10 11:56:34.536413",
|
||||
@@ -23,7 +24,6 @@
|
||||
{
|
||||
"fieldname": "employee",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Employee",
|
||||
"options": "Employee",
|
||||
"reqd": 1
|
||||
@@ -32,14 +32,17 @@
|
||||
"fetch_from": "employee.employee_name",
|
||||
"fieldname": "employee_name",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "Employee Name",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "log_type",
|
||||
"fieldtype": "Select",
|
||||
"in_list_view": 1,
|
||||
"label": "Log Type",
|
||||
"options": "\nIN\nOUT"
|
||||
"options": "\nIN\nOUT",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "shift",
|
||||
@@ -58,6 +61,7 @@
|
||||
"fieldtype": "Datetime",
|
||||
"in_list_view": 1,
|
||||
"label": "Time",
|
||||
"permlevel": 1,
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
@@ -103,7 +107,8 @@
|
||||
"label": "Shift Actual End"
|
||||
}
|
||||
],
|
||||
"modified": "2019-07-23 23:47:33.975263",
|
||||
"links": [],
|
||||
"modified": "2020-01-23 04:57:42.551355",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "Employee Checkin",
|
||||
@@ -147,9 +152,58 @@
|
||||
"role": "HR User",
|
||||
"share": 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_order": "ASC",
|
||||
"title_field": "employee_name",
|
||||
"track_changes": 1
|
||||
}
|
||||
@@ -104,11 +104,16 @@ frappe.ui.form.on("Leave Application", {
|
||||
},
|
||||
|
||||
half_day: function(frm) {
|
||||
if (frm.doc.from_date == frm.doc.to_date) {
|
||||
frm.set_value("half_day_date", frm.doc.from_date);
|
||||
if (frm.doc.half_day) {
|
||||
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 {
|
||||
frm.trigger("half_day_datepicker");
|
||||
frm.set_value("half_day_date", "");
|
||||
}
|
||||
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):
|
||||
''' Returns minimum leaves remaining after comparing with remaining days for allocation expiry '''
|
||||
def _get_remaining_leaves(allocated_leaves, end_date):
|
||||
remaining_leaves = flt(allocated_leaves) + flt(leaves_taken)
|
||||
def _get_remaining_leaves(remaining_leaves, end_date):
|
||||
|
||||
if remaining_leaves > 0:
|
||||
remaining_days = date_diff(end_date, date) + 1
|
||||
@@ -529,10 +528,11 @@ def get_remaining_leaves(allocation, leaves_taken, date, expiry):
|
||||
|
||||
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:
|
||||
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)
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
def test_earned_leave(self):
|
||||
def test_earned_leaves_creation(self):
|
||||
leave_period = get_leave_period()
|
||||
employee = get_employee()
|
||||
leave_type = 'Test Earned Leave Type'
|
||||
@@ -437,6 +437,14 @@ class TestLeaveApplication(unittest.TestCase):
|
||||
i += 1
|
||||
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
|
||||
def test_current_leave_on_submit(self):
|
||||
employee = get_employee()
|
||||
@@ -616,4 +624,4 @@ def allocate_leaves(employee, leave_period, leave_type, new_leaves_allocated, el
|
||||
"docstatus": 1
|
||||
}).insert()
|
||||
|
||||
allocate_leave.submit()
|
||||
allocate_leave.submit()
|
||||
|
||||
@@ -46,7 +46,7 @@ frappe.ui.form.on('Salary Structure', {
|
||||
frm.trigger("toggle_fields");
|
||||
frm.fields_dict['earnings'].grid.set_column_disp("default_amount", false);
|
||||
frm.fields_dict['deductions'].grid.set_column_disp("default_amount", false);
|
||||
|
||||
|
||||
if(frm.doc.docstatus === 1) {
|
||||
frm.add_custom_button(__("Preview Salary Slip"), function() {
|
||||
frm.trigger('preview_salary_slip');
|
||||
@@ -75,6 +75,7 @@ frappe.ui.form.on('Salary Structure', {
|
||||
title: __("Assign to Employees"),
|
||||
fields: [
|
||||
{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:'department', fieldtype:'Link', options: 'Department', label: __('Department')},
|
||||
{fieldname:'designation', fieldtype:'Link', options: 'Designation', label: __('Designation')},
|
||||
@@ -87,7 +88,6 @@ frappe.ui.form.on('Salary Structure', {
|
||||
],
|
||||
primary_action: function() {
|
||||
var data = d.get_values();
|
||||
|
||||
frappe.call({
|
||||
doc: frm.doc,
|
||||
method: "assign_salary_structure",
|
||||
|
||||
@@ -81,24 +81,24 @@ class SalaryStructure(Document):
|
||||
return employees
|
||||
|
||||
@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):
|
||||
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 len(employees) > 20:
|
||||
frappe.enqueue(assign_salary_structure_for_employees, timeout=600,
|
||||
employees=employees, salary_structure=self,from_date=from_date, base=base,variable=variable)
|
||||
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:
|
||||
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 = []
|
||||
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
|
||||
for employee in employees:
|
||||
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.employee = employee
|
||||
assignment.salary_structure = salary_structure.name
|
||||
assignment.company = salary_structure.company
|
||||
assignment.from_date = from_date
|
||||
assignment.base = base
|
||||
assignment.variable = variable
|
||||
@@ -125,12 +126,12 @@ def create_salary_structures_assignment(employee, salary_structure, from_date, b
|
||||
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("""
|
||||
select distinct employee from `tabSalary Structure Assignment`
|
||||
where salary_structure=%s and employee in (%s)
|
||||
and from_date=%s and docstatus=1
|
||||
""" % ('%s', ', '.join(['%s']*len(employees)),'%s'), [salary_structure] + employees+[from_date])
|
||||
and from_date=%s and company= %s and docstatus=1
|
||||
""" % ('%s', ', '.join(['%s']*len(employees)),'%s', '%s'), [salary_structure.name] + employees+[from_date]+[salary_structure.company])
|
||||
if salary_structures_assignments:
|
||||
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)))
|
||||
@@ -170,7 +171,7 @@ def make_salary_slip(source_name, target_doc = None, employee = None, as_print =
|
||||
def get_employees(salary_structure):
|
||||
employees = frappe.get_list('Salary Structure Assignment',
|
||||
filters={'salary_structure': salary_structure, 'docstatus': 1}, fields=['employee'])
|
||||
|
||||
|
||||
if not employees:
|
||||
frappe.throw(_("There's no Employee with Salary Structure: {0}. \
|
||||
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)
|
||||
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:
|
||||
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):
|
||||
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 \
|
||||
getdate(sr_details.delivery_date) >= getdate(amc_start_date):
|
||||
|
||||
@@ -588,7 +588,7 @@ class BOM(WebsiteGenerator):
|
||||
for d in self.operations:
|
||||
if not d.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
|
||||
|
||||
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:
|
||||
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
|
||||
warehouse = data.get("warehouse") or warehouse
|
||||
|
||||
item_details = {}
|
||||
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["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)
|
||||
|
||||
@@ -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.update_price_or_product_discount
|
||||
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 numpy as np
|
||||
from erpnext.portal.product_configurator.item_variants_cache import ItemVariantsCacheManager
|
||||
|
||||
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',
|
||||
['parent', 'attribute_value', 'idx'], order_by='parent asc, idx asc')
|
||||
item_attribute_values += get_numeric_values()
|
||||
ordered_attribute_value_map = frappe._dict()
|
||||
for iv in item_attribute_values:
|
||||
ordered_attribute_value_map.setdefault(iv.parent, []).append(iv.attribute_value)
|
||||
@@ -184,6 +186,23 @@ def get_attributes_and_values(item_code):
|
||||
|
||||
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)
|
||||
def get_next_attribute_and_values(item_code, selected_attributes):
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
{
|
||||
"actions": [],
|
||||
"creation": "2016-03-25 02:52:19.283003",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
@@ -46,6 +47,7 @@
|
||||
"fetch_from": "user.full_name",
|
||||
"fieldname": "full_name",
|
||||
"fieldtype": "Read Only",
|
||||
"in_list_view": 1,
|
||||
"label": "Full Name"
|
||||
},
|
||||
{
|
||||
@@ -55,7 +57,7 @@
|
||||
"label": "Welcome email sent"
|
||||
},
|
||||
{
|
||||
"columns": 1,
|
||||
"columns": 2,
|
||||
"default": "0",
|
||||
"fieldname": "view_attachments",
|
||||
"fieldtype": "Check",
|
||||
@@ -74,7 +76,8 @@
|
||||
}
|
||||
],
|
||||
"istable": 1,
|
||||
"modified": "2019-07-15 19:37:26.942294",
|
||||
"links": [],
|
||||
"modified": "2020-02-09 23:26:50.321417",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Projects",
|
||||
"name": "Project User",
|
||||
|
||||
@@ -56,8 +56,8 @@ class Task(NestedSet):
|
||||
def validate_status(self):
|
||||
if self.status!=self.get_db_value("status") and self.status == "Completed":
|
||||
for d in self.depends_on:
|
||||
if frappe.db.get_value("Task", d.task, "status") != "Completed":
|
||||
frappe.throw(_("Cannot close task {0} as its dependant task {1} is not closed.").format(frappe.bold(self.name), frappe.bold(d.task)))
|
||||
if frappe.db.get_value("Task", d.task, "status") not in ("Completed", "Cancelled"):
|
||||
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)
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ $.extend(frappe.breadcrumbs.preferred, {
|
||||
"Territory": "Selling",
|
||||
"Sales Person": "Selling",
|
||||
"Sales Partner": "Selling",
|
||||
"Brand": "Selling"
|
||||
"Brand": "Stock"
|
||||
});
|
||||
|
||||
$.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) {
|
||||
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);
|
||||
frappe.model.round_floats_in(item, ["qty", "conversion_factor"]);
|
||||
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("total_weight", item.name, item.parentfield);
|
||||
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 &&
|
||||
frappe.meta.has_field(doc.doctype, "price_list_currency")) {
|
||||
this.apply_price_list(item, true);
|
||||
|
||||
@@ -90,7 +90,8 @@ erpnext.SerialNoBatchSelector = Class.extend({
|
||||
args: {
|
||||
qty: qty,
|
||||
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({
|
||||
method: 'erpnext.stock.doctype.batch.batch.get_batch_qty',
|
||||
args: {
|
||||
batch_no: this.doc.batch_no,
|
||||
batch_no: me.item.batch_no,
|
||||
warehouse: me.warehouse_details.name,
|
||||
item_code: me.item_code
|
||||
},
|
||||
@@ -392,6 +393,10 @@ erpnext.SerialNoBatchSelector = Class.extend({
|
||||
delivery_document_no: ""
|
||||
}
|
||||
|
||||
if (this.item.batch_no) {
|
||||
serial_no_filters["batch_no"] = this.item.batch_no;
|
||||
}
|
||||
|
||||
if (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',
|
||||
filters: [
|
||||
{
|
||||
fieldname: "quality_procedure",
|
||||
fieldname: "parent_quality_procedure",
|
||||
fieldtype: "Link",
|
||||
options: "Quality Procedure",
|
||||
label: __("Quality Procedure"),
|
||||
|
||||
@@ -73,7 +73,7 @@
|
||||
"reqd": 1
|
||||
}
|
||||
],
|
||||
"modified": "2019-05-26 23:12:47.302189",
|
||||
"modified": "2020-02-01 10:57:27.119312",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Quality Management",
|
||||
"name": "Quality Review",
|
||||
@@ -102,6 +102,18 @@
|
||||
"role": "All",
|
||||
"share": 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",
|
||||
|
||||
@@ -1,24 +1,28 @@
|
||||
{
|
||||
"add_total_row": 0,
|
||||
"creation": "2018-10-16 12:28:43.651915",
|
||||
"disabled": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "Report",
|
||||
"idx": 0,
|
||||
"is_standard": "Yes",
|
||||
"modified": "2018-10-16 15:23:25.667237",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Quality Management",
|
||||
"name": "Review",
|
||||
"owner": "Administrator",
|
||||
"prepared_report": 0,
|
||||
"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 ",
|
||||
"ref_doctype": "Quality Action",
|
||||
"report_name": "Review",
|
||||
"report_type": "Query Report",
|
||||
"add_total_row": 0,
|
||||
"creation": "2018-10-16 12:28:43.651915",
|
||||
"disable_prepared_report": 0,
|
||||
"disabled": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "Report",
|
||||
"idx": 0,
|
||||
"is_standard": "Yes",
|
||||
"modified": "2020-02-01 11:04:47.299453",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Quality Management",
|
||||
"name": "Review",
|
||||
"owner": "Administrator",
|
||||
"prepared_report": 0,
|
||||
"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 ",
|
||||
"ref_doctype": "Quality Action",
|
||||
"report_name": "Review",
|
||||
"report_type": "Query Report",
|
||||
"roles": [
|
||||
{
|
||||
"role": "System Manager"
|
||||
},
|
||||
{
|
||||
"role": "Quality Manager"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -79,9 +79,10 @@ def add_custom_roles_for_reports():
|
||||
def add_permissions():
|
||||
for doctype in ('GST HSN Code', 'GST Settings'):
|
||||
add_permission(doctype, 'All', 0)
|
||||
add_permission(doctype, 'Accounts Manager', 0)
|
||||
update_permission_property(doctype, 'Accounts Manager', 0, 'write', 1)
|
||||
update_permission_property(doctype, 'Accounts Manager', 0, 'create', 1)
|
||||
for role in ('Accounts Manager', 'System Manager', 'Item Manager', 'Stock Manager'):
|
||||
add_permission(doctype, role, 0)
|
||||
update_permission_property(doctype, role, 0, 'write', 1)
|
||||
update_permission_property(doctype, role, 0, 'create', 1)
|
||||
|
||||
def add_print_formats():
|
||||
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,
|
||||
rates=[{"fiscal_year": fiscal_year, "tax_withholding_rate": 20,
|
||||
"single_threshold": 2500, "cumulative_threshold": 0}])
|
||||
]
|
||||
]
|
||||
|
||||
@@ -160,7 +160,7 @@ def get_gl_entries(filters, as_dict):
|
||||
where gl.company = %(company)s
|
||||
and DATE(gl.posting_date) >= %(from_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
|
||||
|
||||
|
||||
@@ -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){
|
||||
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'}
|
||||
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) {
|
||||
frappe.contacts.render_address_and_contact(frm);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
{
|
||||
"actions": [],
|
||||
"allow_events_in_timeline": 1,
|
||||
"allow_import": 1,
|
||||
"allow_rename": 1,
|
||||
@@ -122,7 +123,7 @@
|
||||
{
|
||||
"fieldname": "default_bank_account",
|
||||
"fieldtype": "Link",
|
||||
"label": "Default Bank Account",
|
||||
"label": "Default Company Bank Account",
|
||||
"options": "Bank Account"
|
||||
},
|
||||
{
|
||||
@@ -322,8 +323,9 @@
|
||||
},
|
||||
{
|
||||
"fieldname": "primary_address",
|
||||
"fieldtype": "Read Only",
|
||||
"label": "Primary Address"
|
||||
"fieldtype": "Text",
|
||||
"label": "Primary Address",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"collapsible": 1,
|
||||
@@ -469,7 +471,8 @@
|
||||
"icon": "fa fa-user",
|
||||
"idx": 363,
|
||||
"image_field": "image",
|
||||
"modified": "2019-09-06 12:40:31.801424",
|
||||
"links": [],
|
||||
"modified": "2020-01-29 20:36:37.879581",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Selling",
|
||||
"name": "Customer",
|
||||
|
||||
@@ -54,6 +54,7 @@ class Customer(TransactionBase):
|
||||
self.validate_credit_limit_on_change()
|
||||
self.set_loyalty_program()
|
||||
self.check_customer_group_change()
|
||||
self.validate_default_bank_account()
|
||||
|
||||
# set loyalty program tier
|
||||
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'):
|
||||
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):
|
||||
self.validate_name_with_customer_group()
|
||||
self.create_primary_contact()
|
||||
|
||||
@@ -185,8 +185,12 @@ def _make_sales_order(source_name, target_doc=None, ignore_permissions=False):
|
||||
return doclist
|
||||
|
||||
def set_expired_status():
|
||||
frappe.db.sql("""UPDATE `tabQuotation` SET `status` = 'Expired'
|
||||
WHERE `status` != "Expired" AND `valid_till` < %s""", (nowdate()))
|
||||
frappe.db.sql("""
|
||||
UPDATE
|
||||
`tabQuotation` SET `status` = 'Expired'
|
||||
WHERE
|
||||
`status` not in ('Ordered', 'Expired', 'Lost', 'Cancelled') AND `valid_till` < %s
|
||||
""", (nowdate()))
|
||||
|
||||
@frappe.whitelist()
|
||||
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