Compare commits
54 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c8da7b7d32 | ||
|
|
9679d31397 | ||
|
|
38bebe1b83 | ||
|
|
ffbc11e8de | ||
|
|
818d9674d9 | ||
|
|
086f8942eb | ||
|
|
c3b492b237 | ||
|
|
9d0dd5066a | ||
|
|
e7f479b26a | ||
|
|
7ee45b4af2 | ||
|
|
5cce1e0929 | ||
|
|
be496bc91c | ||
|
|
59f063e5c3 | ||
|
|
af5820874c | ||
|
|
495db99719 | ||
|
|
123beb5a07 | ||
|
|
7ed4e080a2 | ||
|
|
e91025c0aa | ||
|
|
1ac9f2f50d | ||
|
|
bd9aa13db3 | ||
|
|
ed9d5cfdaf | ||
|
|
bf4547ca5f | ||
|
|
b45a6bcb88 | ||
|
|
ac59c2b300 | ||
|
|
6a8d7a1b91 | ||
|
|
5d71a28e97 | ||
|
|
7d100a1ee7 | ||
|
|
81dca110eb | ||
|
|
9c852108d0 | ||
|
|
e3ac032696 | ||
|
|
64cacfb077 | ||
|
|
ae4cc078ea | ||
|
|
0ee543e932 | ||
|
|
a123638d37 | ||
|
|
58996985ed | ||
|
|
5d0ce7939f | ||
|
|
4abf552d7b | ||
|
|
7c5ba957ac | ||
|
|
77f04e293a | ||
|
|
d1d3237784 | ||
|
|
76f0d26f1e | ||
|
|
65922d3079 | ||
|
|
810041cbe3 | ||
|
|
b9626659ea | ||
|
|
e3d13bee36 | ||
|
|
13bd538aca | ||
|
|
d72a24965b | ||
|
|
dc633fe360 | ||
|
|
39046d663d | ||
|
|
6b01abe9ad | ||
|
|
63e4d31aa6 | ||
|
|
f2a0161709 | ||
|
|
3c1a4a0b9b | ||
|
|
82cc2921d1 |
@@ -1,2 +1,2 @@
|
||||
from __future__ import unicode_literals
|
||||
__version__ = '5.0.22'
|
||||
__version__ = '5.0.27'
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
"permlevel": 0,
|
||||
"read_only": 1,
|
||||
"reqd": 1,
|
||||
"search_index": 1
|
||||
"search_index": 0
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
@@ -44,7 +44,7 @@
|
||||
"label": "Is Group",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"search_index": 1
|
||||
"search_index": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "company",
|
||||
@@ -57,7 +57,7 @@
|
||||
"permlevel": 0,
|
||||
"read_only": 1,
|
||||
"reqd": 1,
|
||||
"search_index": 1
|
||||
"search_index": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "root_type",
|
||||
@@ -147,7 +147,8 @@
|
||||
"label": "Lft",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
"read_only": 1,
|
||||
"search_index": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "rgt",
|
||||
@@ -156,7 +157,8 @@
|
||||
"label": "Rgt",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
"read_only": 1,
|
||||
"search_index": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "old_parent",
|
||||
@@ -171,7 +173,7 @@
|
||||
"icon": "icon-money",
|
||||
"idx": 1,
|
||||
"in_create": 0,
|
||||
"modified": "2015-05-28 14:10:40.606010",
|
||||
"modified": "2015-06-14 20:57:55.471334",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Account",
|
||||
|
||||
@@ -48,7 +48,8 @@
|
||||
"fieldtype": "Dynamic Link",
|
||||
"label": "Party",
|
||||
"options": "party_type",
|
||||
"permlevel": 0
|
||||
"permlevel": 0,
|
||||
"search_index": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "cost_center",
|
||||
@@ -192,7 +193,7 @@
|
||||
"icon": "icon-list",
|
||||
"idx": 1,
|
||||
"in_create": 1,
|
||||
"modified": "2015-04-27 20:32:48.246818",
|
||||
"modified": "2015-06-14 20:57:19.800276",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "GL Entry",
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
|
||||
from frappe.utils import flt, fmt_money, getdate, formatdate
|
||||
from frappe.utils import flt, fmt_money, getdate, formatdate, cstr
|
||||
from frappe import _
|
||||
|
||||
from frappe.model.document import Document
|
||||
@@ -118,7 +118,7 @@ def update_outstanding_amt(account, party_type, party, against_voucher_type, aga
|
||||
bal = flt(frappe.db.sql("""select sum(ifnull(debit, 0)) - sum(ifnull(credit, 0))
|
||||
from `tabGL Entry`
|
||||
where against_voucher_type=%s and against_voucher=%s
|
||||
and account = %s and party_type=%s and party=%s""",
|
||||
and account = %s and ifnull(party_type, '')=%s and ifnull(party, '')=%s""",
|
||||
(against_voucher_type, against_voucher, account, party_type, party))[0][0] or 0.0)
|
||||
|
||||
if against_voucher_type == 'Purchase Invoice':
|
||||
@@ -127,8 +127,9 @@ def update_outstanding_amt(account, party_type, party, against_voucher_type, aga
|
||||
against_voucher_amount = flt(frappe.db.sql("""
|
||||
select sum(ifnull(debit, 0)) - sum(ifnull(credit, 0))
|
||||
from `tabGL Entry` where voucher_type = 'Journal Entry' and voucher_no = %s
|
||||
and account = %s and party_type=%s and party=%s and ifnull(against_voucher, '') = ''""",
|
||||
(against_voucher, account, party_type, party))[0][0])
|
||||
and account = %s and ifnull(party_type, '')=%s and ifnull(party, '')=%s
|
||||
and ifnull(against_voucher, '') = ''""",
|
||||
(against_voucher, account, cstr(party_type), cstr(party)))[0][0])
|
||||
|
||||
if not against_voucher_amount:
|
||||
frappe.throw(_("Against Journal Entry {0} is already adjusted against some other voucher")
|
||||
|
||||
@@ -274,30 +274,28 @@ class JournalEntry(AccountsController):
|
||||
r.append(_('Reference #{0} dated {1}').format(self.cheque_no, formatdate(self.cheque_date)))
|
||||
else:
|
||||
msgprint(_("Please enter Reference date"), raise_exception=frappe.MandatoryError)
|
||||
|
||||
|
||||
company_currency = get_company_currency(self.company)
|
||||
|
||||
for d in self.get('accounts'):
|
||||
if d.against_invoice and d.credit:
|
||||
currency = frappe.db.get_value("Sales Invoice", d.against_invoice, "currency")
|
||||
|
||||
r.append(_("{0} against Sales Invoice {1}").format(fmt_money(flt(d.credit), currency = currency), \
|
||||
r.append(_("{0} against Sales Invoice {1}").format(fmt_money(flt(d.credit), currency = company_currency), \
|
||||
d.against_invoice))
|
||||
|
||||
if d.against_sales_order and d.credit:
|
||||
currency = frappe.db.get_value("Sales Order", d.against_sales_order, "currency")
|
||||
r.append(_("{0} against Sales Order {1}").format(fmt_money(flt(d.credit), currency = currency), \
|
||||
r.append(_("{0} against Sales Order {1}").format(fmt_money(flt(d.credit), currency = company_currency), \
|
||||
d.against_sales_order))
|
||||
|
||||
if d.against_voucher and d.debit:
|
||||
bill_no = frappe.db.sql("""select bill_no, bill_date, currency
|
||||
bill_no = frappe.db.sql("""select bill_no, bill_date
|
||||
from `tabPurchase Invoice` where name=%s""", d.against_voucher)
|
||||
if bill_no and bill_no[0][0] and bill_no[0][0].lower().strip() \
|
||||
not in ['na', 'not applicable', 'none']:
|
||||
r.append(_('{0} against Bill {1} dated {2}').format(fmt_money(flt(d.debit), currency=bill_no[0][2]), bill_no[0][0],
|
||||
r.append(_('{0} against Bill {1} dated {2}').format(fmt_money(flt(d.debit), currency=company_currency), bill_no[0][0],
|
||||
bill_no[0][1] and formatdate(bill_no[0][1].strftime('%Y-%m-%d'))))
|
||||
|
||||
if d.against_purchase_order and d.debit:
|
||||
currency = frappe.db.get_value("Purchase Order", d.against_purchase_order, "currency")
|
||||
r.append(_("{0} against Purchase Order {1}").format(fmt_money(flt(d.credit), currency = currency), \
|
||||
r.append(_("{0} against Purchase Order {1}").format(fmt_money(flt(d.credit), currency = company_currency), \
|
||||
d.against_purchase_order))
|
||||
|
||||
if self.user_remark:
|
||||
@@ -544,7 +542,7 @@ def get_against_jv(doctype, txt, searchfield, start, page_len, filters):
|
||||
and (ifnull(jv_detail.against_invoice, '') = '' and ifnull(jv_detail.against_voucher, '') = ''
|
||||
and ifnull(jv_detail.against_jv, '') = '' )
|
||||
and jv.docstatus = 1 and jv.{0} like %s order by jv.name desc limit %s, %s""".format(searchfield),
|
||||
(filters["account"], cstr(filters["party"]), "%{0}%".format(txt), start, page_len))
|
||||
(filters.get("account"), cstr(filters.get("party")), "%{0}%".format(txt), start, page_len))
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_outstanding(args):
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -3,7 +3,7 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe.utils import cint, formatdate, flt
|
||||
from frappe.utils import cint, formatdate, flt, getdate
|
||||
from frappe import msgprint, _, throw
|
||||
from erpnext.setup.utils import get_company_currency
|
||||
import frappe.defaults
|
||||
@@ -88,9 +88,7 @@ class PurchaseInvoice(BuyingController):
|
||||
throw(_("Conversion rate cannot be 0 or 1"))
|
||||
|
||||
def validate_credit_to_acc(self):
|
||||
root_type, account_type = frappe.db.get_value("Account", self.credit_to, ["root_type", "account_type"])
|
||||
if root_type != "Liability":
|
||||
frappe.throw(_("Credit To account must be a liability account"))
|
||||
account_type = frappe.db.get_value("Account", self.credit_to, "account_type")
|
||||
if account_type != "Payable":
|
||||
frappe.throw(_("Credit To account must be a Payable account"))
|
||||
|
||||
@@ -389,7 +387,7 @@ class PurchaseInvoice(BuyingController):
|
||||
|
||||
def validate_supplier_invoice(self):
|
||||
if self.bill_date:
|
||||
if self.bill_date > self.posting_date:
|
||||
if getdate(self.bill_date) > getdate(self.posting_date):
|
||||
frappe.throw("Supplier Invoice Date cannot be greater than Posting Date")
|
||||
if self.bill_no:
|
||||
if cint(frappe.db.get_single_value("Accounts Settings", "check_supplier_invoice_uniqueness")):
|
||||
|
||||
@@ -38,7 +38,8 @@
|
||||
"options": "Customer",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"read_only": 0
|
||||
"read_only": 0,
|
||||
"search_index": 1
|
||||
},
|
||||
{
|
||||
"depends_on": "customer",
|
||||
@@ -502,7 +503,7 @@
|
||||
{
|
||||
"fieldname": "base_discount_amount",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Discount Amount (Company Currency)",
|
||||
"label": "Additional Discount Amount (Company Currency)",
|
||||
"options": "Company:company:default_currency",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
@@ -880,7 +881,7 @@
|
||||
"options": "Project",
|
||||
"permlevel": 0,
|
||||
"read_only": 0,
|
||||
"search_index": 1
|
||||
"search_index": 0
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.source == 'Campaign'",
|
||||
@@ -1243,7 +1244,7 @@
|
||||
"icon": "icon-file-text",
|
||||
"idx": 1,
|
||||
"is_submittable": 1,
|
||||
"modified": "2015-05-27 02:48:02.897865",
|
||||
"modified": "2015-06-16 16:45:06.618286",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Sales Invoice",
|
||||
|
||||
@@ -65,8 +65,7 @@ class SalesInvoice(SellingController):
|
||||
self.set_against_income_account()
|
||||
self.validate_c_form()
|
||||
self.validate_time_logs_are_submitted()
|
||||
self.validate_multiple_billing("Delivery Note", "dn_detail", "amount",
|
||||
"items")
|
||||
self.validate_multiple_billing("Delivery Note", "dn_detail", "amount", "items")
|
||||
|
||||
def on_submit(self):
|
||||
super(SalesInvoice, self).on_submit()
|
||||
@@ -236,9 +235,7 @@ class SalesInvoice(SellingController):
|
||||
reconcile_against_document(lst)
|
||||
|
||||
def validate_debit_to_acc(self):
|
||||
root_type, account_type = frappe.db.get_value("Account", self.debit_to, ["root_type", "account_type"])
|
||||
if root_type != "Asset":
|
||||
frappe.throw(_("Debit To account must be a liability account"))
|
||||
account_type = frappe.db.get_value("Account", self.debit_to, "account_type")
|
||||
if account_type != "Receivable":
|
||||
frappe.throw(_("Debit To account must be a Receivable account"))
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe.utils import flt, cstr
|
||||
from frappe.utils import flt, cstr, cint
|
||||
from frappe import _
|
||||
from frappe.model.meta import get_field_precision
|
||||
from erpnext.accounts.utils import validate_expense_against_budget
|
||||
@@ -82,14 +82,15 @@ def make_entry(args, adv_adj, update_outstanding):
|
||||
gle.submit()
|
||||
|
||||
def validate_account_for_auto_accounting_for_stock(gl_map):
|
||||
if gl_map[0].voucher_type=="Journal Entry":
|
||||
aii_accounts = [d[0] for d in frappe.db.sql("""select name from tabAccount
|
||||
where account_type = 'Warehouse' and ifnull(warehouse, '')!=''""")]
|
||||
if cint(frappe.db.get_single_value("Accounts Settings", "auto_accounting_for_stock")) \
|
||||
and gl_map[0].voucher_type=="Journal Entry":
|
||||
aii_accounts = [d[0] for d in frappe.db.sql("""select name from tabAccount
|
||||
where account_type = 'Warehouse' and ifnull(warehouse, '')!=''""")]
|
||||
|
||||
for entry in gl_map:
|
||||
if entry.account in aii_accounts:
|
||||
frappe.throw(_("Account: {0} can only be updated via Stock Transactions")
|
||||
.format(entry.account), StockAccountInvalidTransaction)
|
||||
for entry in gl_map:
|
||||
if entry.account in aii_accounts:
|
||||
frappe.throw(_("Account: {0} can only be updated via Stock Transactions")
|
||||
.format(entry.account), StockAccountInvalidTransaction)
|
||||
|
||||
def round_off_debit_credit(gl_map):
|
||||
precision = get_field_precision(frappe.get_meta("GL Entry").get_field("debit"),
|
||||
|
||||
@@ -51,7 +51,7 @@ class ReceivablePayableReport(object):
|
||||
currency_precision = get_currency_precision() or 2
|
||||
dr_or_cr = "debit" if args.get("party_type") == "Customer" else "credit"
|
||||
|
||||
voucher_details = self.get_voucher_details()
|
||||
voucher_details = self.get_voucher_details(args.get("party_type"))
|
||||
|
||||
future_vouchers = self.get_entries_after(self.filters.report_date, args.get("party_type"))
|
||||
|
||||
@@ -153,23 +153,26 @@ class ReceivablePayableReport(object):
|
||||
|
||||
return self.party_map
|
||||
|
||||
def get_voucher_details(self):
|
||||
def get_voucher_details(self, party_type):
|
||||
voucher_details = frappe._dict()
|
||||
|
||||
if party_type == "Customer":
|
||||
for si in frappe.db.sql("""select name, due_date
|
||||
from `tabSales Invoice` where docstatus=1""", as_dict=1):
|
||||
voucher_details.setdefault(si.name, si)
|
||||
|
||||
for si in frappe.db.sql("""select name, due_date
|
||||
from `tabSales Invoice` where docstatus=1""", as_dict=1):
|
||||
voucher_details.setdefault(si.name, si)
|
||||
|
||||
for pi in frappe.db.sql("""select name, due_date, bill_no, bill_date
|
||||
from `tabPurchase Invoice` where docstatus=1""", as_dict=1):
|
||||
voucher_details.setdefault(pi.name, pi)
|
||||
if party_type == "Supplier":
|
||||
for pi in frappe.db.sql("""select name, due_date, bill_no, bill_date
|
||||
from `tabPurchase Invoice` where docstatus=1""", as_dict=1):
|
||||
voucher_details.setdefault(pi.name, pi)
|
||||
|
||||
return voucher_details
|
||||
|
||||
def get_gl_entries(self, party_type):
|
||||
if not hasattr(self, "gl_entries"):
|
||||
conditions, values = self.prepare_conditions(party_type)
|
||||
self.gl_entries = frappe.db.sql("""select * from `tabGL Entry`
|
||||
self.gl_entries = frappe.db.sql("""select name, posting_date, account, party_type, party, debit, credit,
|
||||
voucher_type, voucher_no, against_voucher_type, against_voucher from `tabGL Entry`
|
||||
where docstatus < 2 and party_type=%s {0} order by posting_date, party"""
|
||||
.format(conditions), values, as_dict=True)
|
||||
|
||||
@@ -187,7 +190,7 @@ class ReceivablePayableReport(object):
|
||||
|
||||
if self.filters.get(party_type_field):
|
||||
conditions.append("party=%s")
|
||||
values.append(self.filters.get(party_type_field))
|
||||
values.append(self.filters.get(party_type_field))
|
||||
|
||||
return " and ".join(conditions), values
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@ def get_data(company, root_type, balance_must_be, period_list, ignore_closing_en
|
||||
gl_entries_by_account = get_gl_entries(company, period_list[0]["from_date"], period_list[-1]["to_date"],
|
||||
accounts[0].lft, accounts[0].rgt, ignore_closing_entries=ignore_closing_entries)
|
||||
|
||||
calculate_values(accounts, gl_entries_by_account, period_list)
|
||||
calculate_values(accounts_by_name, gl_entries_by_account, period_list)
|
||||
accumulate_values_into_parents(accounts, accounts_by_name, period_list)
|
||||
out = prepare_data(accounts, balance_must_be, period_list)
|
||||
|
||||
@@ -92,16 +92,14 @@ def get_data(company, root_type, balance_must_be, period_list, ignore_closing_en
|
||||
|
||||
return out
|
||||
|
||||
def calculate_values(accounts, gl_entries_by_account, period_list):
|
||||
for d in accounts:
|
||||
for name in ([d.name] + (d.collapsed_children or [])):
|
||||
for entry in gl_entries_by_account.get(name, []):
|
||||
for period in period_list:
|
||||
entry.posting_date = getdate(entry.posting_date)
|
||||
|
||||
# check if posting date is within the period
|
||||
if entry.posting_date <= period.to_date:
|
||||
d[period.key] = d.get(period.key, 0.0) + flt(entry.debit) - flt(entry.credit)
|
||||
def calculate_values(accounts_by_name, gl_entries_by_account, period_list):
|
||||
for entries in gl_entries_by_account.values():
|
||||
for entry in entries:
|
||||
d = accounts_by_name.get(entry.account)
|
||||
for period in period_list:
|
||||
# check if posting date is within the period
|
||||
if entry.posting_date <= period.to_date:
|
||||
d[period.key] = d.get(period.key, 0.0) + flt(entry.debit) - flt(entry.credit)
|
||||
|
||||
|
||||
def accumulate_values_into_parents(accounts, accounts_by_name, period_list):
|
||||
@@ -159,22 +157,8 @@ def add_total_row(out, balance_must_be, period_list):
|
||||
out.append({})
|
||||
|
||||
def get_accounts(company, root_type):
|
||||
# root lft, rgt
|
||||
root_account = frappe.db.sql("""select lft, rgt from `tabAccount`
|
||||
where company=%s and root_type=%s and ifnull(parent_account, '') = ''
|
||||
order by lft limit 1""",
|
||||
(company, root_type), as_dict=True)
|
||||
|
||||
if not root_account:
|
||||
return None
|
||||
|
||||
lft, rgt = root_account[0].lft, root_account[0].rgt
|
||||
|
||||
accounts = frappe.db.sql("""select * from `tabAccount`
|
||||
where company=%(company)s and lft >= %(lft)s and rgt <= %(rgt)s order by lft""",
|
||||
{ "company": company, "lft": lft, "rgt": rgt }, as_dict=True)
|
||||
|
||||
return accounts
|
||||
return frappe.db.sql("""select name, parent_account, lft, rgt, root_type, report_type, account_name from `tabAccount`
|
||||
where company=%s and root_type=%s order by lft""", (company, root_type), as_dict=True)
|
||||
|
||||
def filter_accounts(accounts, depth=10):
|
||||
parent_children_map = {}
|
||||
@@ -196,14 +180,6 @@ def filter_accounts(accounts, depth=10):
|
||||
filtered_accounts.append(child)
|
||||
add_to_list(child.name, level + 1)
|
||||
|
||||
else:
|
||||
# include all children at level lower than the depth
|
||||
parent_account = accounts_by_name[parent]
|
||||
parent_account["collapsed_children"] = []
|
||||
for d in accounts:
|
||||
if d.lft > parent_account.lft and d.rgt < parent_account.rgt:
|
||||
parent_account["collapsed_children"].append(d.name)
|
||||
|
||||
add_to_list(None, 0)
|
||||
|
||||
return filtered_accounts, accounts_by_name
|
||||
@@ -234,7 +210,7 @@ def get_gl_entries(company, from_date, to_date, root_lft, root_rgt, ignore_closi
|
||||
if from_date:
|
||||
additional_conditions.append("and posting_date >= %(from_date)s")
|
||||
|
||||
gl_entries = frappe.db.sql("""select * from `tabGL Entry`
|
||||
gl_entries = frappe.db.sql("""select posting_date, account, debit, credit, is_opening from `tabGL Entry`
|
||||
where company=%(company)s
|
||||
{additional_conditions}
|
||||
and posting_date <= %(to_date)s
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe.utils import flt, getdate
|
||||
from frappe.utils import flt, getdate, cstr
|
||||
from frappe import _
|
||||
|
||||
def execute(filters=None):
|
||||
@@ -66,7 +66,7 @@ def get_gl_entries(filters):
|
||||
|
||||
gl_entries = frappe.db.sql("""select posting_date, account, party_type, party,
|
||||
sum(ifnull(debit, 0)) as debit, sum(ifnull(credit, 0)) as credit,
|
||||
voucher_type, voucher_no, cost_center, remarks, is_opening, against
|
||||
voucher_type, voucher_no, cost_center, remarks, against, is_opening
|
||||
from `tabGL Entry`
|
||||
where company=%(company)s {conditions}
|
||||
{group_by_condition}
|
||||
@@ -91,6 +91,9 @@ def get_conditions(filters):
|
||||
|
||||
if filters.get("party"):
|
||||
conditions.append("party=%(party)s")
|
||||
|
||||
if not (filters.get("account") or filters.get("party") or filters.get("group_by_account")):
|
||||
conditions.append("posting_date >=%(from_date)s")
|
||||
|
||||
from frappe.desk.reportview import build_match_conditions
|
||||
match_conditions = build_match_conditions("GL Entry")
|
||||
@@ -148,14 +151,15 @@ def initialize_gle_map(gl_entries):
|
||||
|
||||
def get_accountwise_gle(filters, gl_entries, gle_map):
|
||||
opening, total_debit, total_credit = 0, 0, 0
|
||||
|
||||
from_date, to_date = getdate(filters.from_date), getdate(filters.to_date)
|
||||
for gle in gl_entries:
|
||||
amount = flt(gle.debit, 3) - flt(gle.credit, 3)
|
||||
if gle.posting_date < getdate(filters.from_date):
|
||||
if (filters.get("account") or filters.get("party") or filters.get("group_by_account")) \
|
||||
and (gle.posting_date < from_date or cstr(gle.is_opening) == "Yes"):
|
||||
gle_map[gle.account].opening += amount
|
||||
if filters.get("account") or filters.get("party"):
|
||||
opening += amount
|
||||
elif gle.posting_date <= getdate(filters.to_date):
|
||||
elif gle.posting_date <= to_date:
|
||||
gle_map[gle.account].entries.append(gle)
|
||||
gle_map[gle.account].total_debit += flt(gle.debit, 3)
|
||||
gle_map[gle.account].total_credit += flt(gle.credit, 3)
|
||||
|
||||
@@ -9,8 +9,9 @@ from frappe.utils import flt
|
||||
|
||||
def execute(filters=None):
|
||||
if not filters: filters = {}
|
||||
|
||||
columns = get_columns()
|
||||
validate_filters(filters)
|
||||
|
||||
columns = get_columns(filters)
|
||||
entries = get_entries(filters)
|
||||
invoice_posting_date_map = get_invoice_posting_date_map(filters)
|
||||
against_date = ""
|
||||
@@ -36,11 +37,18 @@ def execute(filters=None):
|
||||
data.append(row)
|
||||
|
||||
return columns, data
|
||||
|
||||
def validate_filters(filters):
|
||||
if (filters.get("payment_type") == "Incoming" and filters.get("party_type") == "Supplier") or \
|
||||
(filters.get("payment_type") == "Outgoing" and filters.get("party_type") == "Customer"):
|
||||
frappe.throw(_("{0} payment entries can not be filtered by {1}")\
|
||||
.format(filters.payment_type, filters.party_type))
|
||||
|
||||
def get_columns():
|
||||
def get_columns(filters):
|
||||
return [_("Journal Entry") + ":Link/Journal Entry:140",
|
||||
_("Party Type") + ":Link/DocType:100", _("Party") + ":Dynamic Link/party_type:140",
|
||||
_("Posting Date") + ":Date:100", _("Against Invoice") + ":Link/Purchase Invoice:130",
|
||||
_("Party Type") + ":Link/DocType:100", _("Party") + ":Dynamic Link/Party Type:140",
|
||||
_("Posting Date") + ":Date:100",
|
||||
_("Against Invoice") + (":Link/Purchase Invoice:130" if filters.get("payment_type") == "Outgoing" else ":Link/Sales Invoice:130"),
|
||||
_("Against Invoice Posting Date") + ":Date:130", _("Debit") + ":Currency:120", _("Credit") + ":Currency:120",
|
||||
_("Reference No") + "::100", _("Reference Date") + ":Date:100", _("Remarks") + "::150", _("Age") +":Int:40",
|
||||
"0-30:Currency:100", "30-60:Currency:100", "60-90:Currency:100", _("90-Above") + ":Currency:100"
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.utils import cint, flt, getdate, formatdate
|
||||
from frappe.utils import cint, flt, getdate, formatdate, cstr
|
||||
from erpnext.accounts.report.financial_statements import filter_accounts, get_gl_entries
|
||||
|
||||
value_fields = ("opening_debit", "opening_credit", "debit", "credit", "closing_debit", "closing_credit")
|
||||
|
||||
def execute(filters):
|
||||
def execute(filters=None):
|
||||
validate_filters(filters)
|
||||
data = get_data(filters)
|
||||
columns = get_columns()
|
||||
@@ -45,8 +45,8 @@ def validate_filters(filters):
|
||||
filters.to_date = filters.year_end_date
|
||||
|
||||
def get_data(filters):
|
||||
accounts = frappe.db.sql("""select * from `tabAccount` where company=%s order by lft""",
|
||||
filters.company, as_dict=True)
|
||||
accounts = frappe.db.sql("""select name, parent_account, account_name, root_type, report_type, lft, rgt
|
||||
from `tabAccount` where company=%s order by lft""", filters.company, as_dict=True)
|
||||
|
||||
if not accounts:
|
||||
return None
|
||||
@@ -56,17 +56,58 @@ def get_data(filters):
|
||||
min_lft, max_rgt = frappe.db.sql("""select min(lft), max(rgt) from `tabAccount`
|
||||
where company=%s""", (filters.company,))[0]
|
||||
|
||||
gl_entries_by_account = get_gl_entries(filters.company, None, filters.to_date, min_lft, max_rgt,
|
||||
gl_entries_by_account = get_gl_entries(filters.company, filters.from_date, filters.to_date, min_lft, max_rgt,
|
||||
ignore_closing_entries=not flt(filters.with_period_closing_entry))
|
||||
|
||||
total_row = calculate_values(accounts, gl_entries_by_account, filters)
|
||||
opening_balances = get_opening_balances(filters)
|
||||
|
||||
total_row = calculate_values(accounts, gl_entries_by_account, opening_balances, filters)
|
||||
accumulate_values_into_parents(accounts, accounts_by_name)
|
||||
|
||||
data = prepare_data(accounts, filters, total_row)
|
||||
|
||||
return data
|
||||
|
||||
def get_opening_balances(filters):
|
||||
balance_sheet_opening = get_rootwise_opening_balances(filters, "Balance Sheet")
|
||||
pl_opening = get_rootwise_opening_balances(filters, "Profit and Loss")
|
||||
|
||||
balance_sheet_opening.update(pl_opening)
|
||||
return balance_sheet_opening
|
||||
|
||||
|
||||
def get_rootwise_opening_balances(filters, report_type):
|
||||
additional_conditions = " and posting_date >= %(year_start_date)s" \
|
||||
if report_type == "Profit and Loss" else ""
|
||||
|
||||
if not flt(filters.with_period_closing_entry):
|
||||
additional_conditions += " and ifnull(voucher_type, '')!='Period Closing Voucher'"
|
||||
|
||||
gle = frappe.db.sql("""
|
||||
select
|
||||
account, sum(ifnull(debit, 0)) as opening_debit, sum(ifnull(credit, 0)) as opening_credit
|
||||
from `tabGL Entry`
|
||||
where
|
||||
company=%(company)s
|
||||
{additional_conditions}
|
||||
and (posting_date < %(from_date)s or ifnull(is_opening, 'No') = 'Yes')
|
||||
and account in (select name from `tabAccount` where report_type=%(report_type)s)
|
||||
group by account""".format(additional_conditions=additional_conditions),
|
||||
{
|
||||
"company": filters.company,
|
||||
"from_date": filters.from_date,
|
||||
"report_type": report_type,
|
||||
"year_start_date": filters.year_start_date
|
||||
},
|
||||
as_dict=True)
|
||||
|
||||
opening = frappe._dict()
|
||||
for d in gle:
|
||||
opening.setdefault(d.account, d)
|
||||
|
||||
return opening
|
||||
|
||||
def calculate_values(accounts, gl_entries_by_account, filters):
|
||||
def calculate_values(accounts, gl_entries_by_account, opening_balances, filters):
|
||||
init = {
|
||||
"opening_debit": 0.0,
|
||||
"opening_credit": 0.0,
|
||||
@@ -87,30 +128,18 @@ def calculate_values(accounts, gl_entries_by_account, filters):
|
||||
for d in accounts:
|
||||
d.update(init.copy())
|
||||
|
||||
# add opening
|
||||
d["opening_debit"] = opening_balances.get(d.name, {}).get("opening_debit", 0)
|
||||
d["opening_credit"] = opening_balances.get(d.name, {}).get("opening_credit", 0)
|
||||
|
||||
for entry in gl_entries_by_account.get(d.name, []):
|
||||
posting_date = getdate(entry.posting_date)
|
||||
|
||||
# opening
|
||||
if posting_date < filters.from_date:
|
||||
is_valid_opening = (d.root_type in ("Asset", "Liability", "Equity") or
|
||||
(filters.year_start_date <= posting_date < filters.from_date))
|
||||
|
||||
if is_valid_opening:
|
||||
d["opening_debit"] += flt(entry.debit)
|
||||
d["opening_credit"] += flt(entry.credit)
|
||||
|
||||
elif posting_date <= filters.to_date:
|
||||
|
||||
if entry.is_opening == "Yes" and d.root_type in ("Asset", "Liability", "Equity"):
|
||||
d["opening_debit"] += flt(entry.debit)
|
||||
d["opening_credit"] += flt(entry.credit)
|
||||
|
||||
else:
|
||||
d["debit"] += flt(entry.debit)
|
||||
d["credit"] += flt(entry.credit)
|
||||
if cstr(entry.is_opening) != "Yes":
|
||||
d["debit"] += flt(entry.debit)
|
||||
d["credit"] += flt(entry.credit)
|
||||
|
||||
total_row["debit"] += d["debit"]
|
||||
total_row["credit"] += d["credit"]
|
||||
|
||||
|
||||
return total_row
|
||||
|
||||
|
||||
@@ -91,7 +91,7 @@ def get_balance_on(account=None, date=None, party_type=None, party=None):
|
||||
# different filter for group and ledger - improved performance
|
||||
if acc.is_group:
|
||||
cond.append("""exists (
|
||||
select * from `tabAccount` ac where ac.name = gle.account
|
||||
select name from `tabAccount` ac where ac.name = gle.account
|
||||
and ac.lft >= %s and ac.rgt <= %s
|
||||
)""" % (acc.lft, acc.rgt))
|
||||
else:
|
||||
@@ -397,7 +397,7 @@ def get_outstanding_invoices(amount_query, account, party_type, party):
|
||||
|
||||
for d in outstanding_voucher_list:
|
||||
payment_amount = frappe.db.sql("""
|
||||
select ifnull(sum(ifnull({amount_query}, 0)), 0)
|
||||
select ifnull(sum({amount_query}), 0)
|
||||
from
|
||||
`tabGL Entry`
|
||||
where
|
||||
|
||||
@@ -457,7 +457,7 @@
|
||||
{
|
||||
"fieldname": "base_discount_amount",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Discount Amount (Company Currency)",
|
||||
"label": "Additional Discount Amount (Company Currency)",
|
||||
"options": "Company:company:default_currency",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
@@ -873,7 +873,7 @@
|
||||
"icon": "icon-file-text",
|
||||
"idx": 1,
|
||||
"is_submittable": 1,
|
||||
"modified": "2015-06-02 17:15:44.711032",
|
||||
"modified": "2015-06-15 15:38:56.794601",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Buying",
|
||||
"name": "Purchase Order",
|
||||
|
||||
@@ -439,7 +439,7 @@
|
||||
{
|
||||
"fieldname": "base_discount_amount",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Discount Amount (Company Currency)",
|
||||
"label": "Additional Discount Amount (Company Currency)",
|
||||
"options": "Company:company:default_currency",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
@@ -660,7 +660,7 @@
|
||||
"icon": "icon-shopping-cart",
|
||||
"idx": 1,
|
||||
"is_submittable": 1,
|
||||
"modified": "2015-06-02 17:15:57.283516",
|
||||
"modified": "2015-06-15 15:39:08.954248",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Buying",
|
||||
"name": "Supplier Quotation",
|
||||
|
||||
17
erpnext/change_log/v5/v5_0_25.md
Normal file
17
erpnext/change_log/v5/v5_0_25.md
Normal file
@@ -0,0 +1,17 @@
|
||||
- Performance upgrade in Trial Balance, General Ledger, AR/AP, Balance Sheet and P&L Statement reports
|
||||
- Add index on Account and GL Entry, Sales Invoice and Purchase Invoice table
|
||||
- Don't create Time Logs against Production Order if Workstation is not specified in Operations
|
||||
- Task should be mandatory in Time Log only when Project is mentioned but Production Order is not
|
||||
- Supplier invoice no unique validation and supplier invoice date can not be after posting date
|
||||
- Removed BOM No from mandatory from Stock Entry against Production Order
|
||||
- Load tasks in project for printing purpose
|
||||
- Added Customers Not Buying Since Long Time against Sales Invoice
|
||||
- POS - search by Item Group
|
||||
- Payment period based on invoice date: show party columns and filter based on party
|
||||
- Barcode added to Purchase Receipt
|
||||
- Fetch item name and desc on change of item code in Quality Inspection
|
||||
- Show item name in item grid view based 'In List View' property
|
||||
- Validate and update manufactured qty in Stock Entry
|
||||
- Show only users with Expense Approver role in Expense Claim Approver field
|
||||
- Over Production Allowance Percentage Setting added to Manufacturing Settings
|
||||
- Activity Cost - Mandatory removed for Employee
|
||||
@@ -103,6 +103,12 @@ def get_data():
|
||||
"name": "Completed Production Orders",
|
||||
"doctype": "Production Order"
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"is_query_report": True,
|
||||
"name": "BOM Search",
|
||||
"doctype": "BOM"
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -237,6 +237,12 @@ def get_data():
|
||||
"route": "query-report/Sales Person Target Variance Item Group-Wise",
|
||||
"doctype": "Sales Person",
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"is_query_report": True,
|
||||
"name": "BOM Search",
|
||||
"doctype": "BOM"
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"is_query_report": True,
|
||||
|
||||
@@ -5,7 +5,7 @@ app_publisher = "Frappe Technologies Pvt. Ltd. and Contributors"
|
||||
app_description = "Open Source Enterprise Resource Planning for Small and Midsized Organizations"
|
||||
app_icon = "icon-th"
|
||||
app_color = "#e74c3c"
|
||||
app_version = "5.0.22"
|
||||
app_version = "5.0.27"
|
||||
|
||||
error_report_email = "support@erpnext.com"
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ cur_frm.cscript.onload = function(doc,cdt,cdn) {
|
||||
|
||||
cur_frm.set_query("exp_approver", function() {
|
||||
return {
|
||||
filters: [["UserRole", "role", "=", "Expense Approver"]]
|
||||
query: "erpnext.hr.doctype.expense_claim.expense_claim.get_expense_approver"
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
@@ -58,4 +58,13 @@ class ExpenseClaim(Document):
|
||||
def validate_sanctioned_amount(self):
|
||||
for d in self.get('expenses'):
|
||||
if flt(d.sanctioned_amount) > flt(d.claim_amount):
|
||||
frappe.throw(_("Sanctioned Amount cannot be greater than Claim Amount in Row {0}.").format(d.idx))
|
||||
frappe.throw(_("Sanctioned Amount cannot be greater than Claim Amount in Row {0}.").format(d.idx))
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_expense_approver(doctype, txt, searchfield, start, page_len, filters):
|
||||
return frappe.db.sql("""
|
||||
select u.name, concat(u.first_name, ' ', u.last_name)
|
||||
from tabUser u, tabUserRole r
|
||||
where u.name = r.parent and r.role = 'Expense Approver' and u.name like %s
|
||||
""", ("%" + txt + "%"))
|
||||
@@ -339,6 +339,7 @@ def add_block_dates(events, start, end, employee, company):
|
||||
events.append({
|
||||
"doctype": "Leave Block List Date",
|
||||
"from_date": block_date.block_date,
|
||||
"to_date": block_date.block_date,
|
||||
"title": _("Leave Blocked") + ": " + block_date.reason,
|
||||
"name": "_" + str(cnt),
|
||||
})
|
||||
@@ -355,6 +356,7 @@ def add_holidays(events, start, end, employee, company):
|
||||
events.append({
|
||||
"doctype": "Holiday",
|
||||
"from_date": holiday.holiday_date,
|
||||
"to_date": holiday.holiday_date,
|
||||
"title": _("Holiday") + ": " + cstr(holiday.description),
|
||||
"name": holiday.name
|
||||
})
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
|
||||
from frappe.utils import cstr, flt
|
||||
from frappe.utils import cstr, flt, getdate
|
||||
from frappe.model.naming import make_autoname
|
||||
from frappe import _
|
||||
from frappe.model.mapper import get_mapped_doc
|
||||
@@ -14,6 +14,13 @@ from erpnext.hr.utils import set_employee_name
|
||||
class SalaryStructure(Document):
|
||||
def autoname(self):
|
||||
self.name = make_autoname(self.employee + '/.SST' + '/.#####')
|
||||
|
||||
def validate(self):
|
||||
self.check_existing()
|
||||
self.validate_amount()
|
||||
self.validate_employee()
|
||||
self.validate_joining_date()
|
||||
set_employee_name(self)
|
||||
|
||||
def get_employee_details(self):
|
||||
ret = {}
|
||||
@@ -77,14 +84,11 @@ class SalaryStructure(Document):
|
||||
old_employee = frappe.db.get_value("Salary Structure", self.name, "employee")
|
||||
if old_employee and self.employee != old_employee:
|
||||
frappe.throw(_("Employee can not be changed"))
|
||||
|
||||
|
||||
def validate(self):
|
||||
self.check_existing()
|
||||
self.validate_amount()
|
||||
self.validate_employee()
|
||||
set_employee_name(self)
|
||||
|
||||
|
||||
def validate_joining_date(self):
|
||||
joining_date = getdate(frappe.db.get_value("Employee", self.employee, "date_of_joining"))
|
||||
if getdate(self.from_date) < joining_date:
|
||||
frappe.throw(_("From Date in Salary Structure cannot be lesser than Employee Joining Date."))
|
||||
|
||||
@frappe.whitelist()
|
||||
def make_salary_slip(source_name, target_doc=None):
|
||||
|
||||
@@ -55,6 +55,13 @@
|
||||
"label": "Time Between Operations (in mins)",
|
||||
"permlevel": 0,
|
||||
"precision": ""
|
||||
},
|
||||
{
|
||||
"fieldname": "over_production_allowance_percentage",
|
||||
"fieldtype": "Percent",
|
||||
"label": "Over Production Allowance Percentage",
|
||||
"permlevel": 0,
|
||||
"precision": ""
|
||||
}
|
||||
],
|
||||
"hide_heading": 0,
|
||||
@@ -65,7 +72,7 @@
|
||||
"is_submittable": 0,
|
||||
"issingle": 1,
|
||||
"istable": 0,
|
||||
"modified": "2015-04-21 07:57:40.260862",
|
||||
"modified": "2015-06-15 05:52:22.986958",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Manufacturing",
|
||||
"name": "Manufacturing Settings",
|
||||
|
||||
@@ -90,8 +90,9 @@ class ProductionOrder(Document):
|
||||
(self.sales_order, self.production_item))[0][0]
|
||||
# total qty in SO
|
||||
so_qty = flt(so_item_qty) + flt(dnpi_qty)
|
||||
|
||||
if total_qty > so_qty:
|
||||
|
||||
allowance_percentage = flt(frappe.db.get_single_value("Manufacturing Settings", "over_production_allowance_percentage"))
|
||||
if total_qty > so_qty + (allowance_percentage/100 * so_qty):
|
||||
frappe.throw(_("Cannot produce more Item {0} than Sales Order quantity {1}").format(self.production_item,
|
||||
so_qty), OverProductionError)
|
||||
|
||||
@@ -217,12 +218,14 @@ class ProductionOrder(Document):
|
||||
for i, d in enumerate(self.operations):
|
||||
self.set_operation_start_end_time(i, d)
|
||||
|
||||
if not d.workstation:
|
||||
continue
|
||||
|
||||
time_log = make_time_log(self.name, d.operation, d.planned_start_time, d.planned_end_time,
|
||||
flt(self.qty) - flt(d.completed_qty), self.project_name, d.workstation, operation_id=d.name)
|
||||
|
||||
if d.workstation:
|
||||
# validate operating hours if workstation [not mandatory] is specified
|
||||
self.check_operation_fits_in_working_hours(d)
|
||||
# validate operating hours if workstation [not mandatory] is specified
|
||||
self.check_operation_fits_in_working_hours(d)
|
||||
|
||||
original_start_time = time_log.from_time
|
||||
while True:
|
||||
|
||||
@@ -165,4 +165,5 @@ erpnext.patches.v5_0.repost_gle_for_jv_with_multiple_party
|
||||
erpnext.patches.v5_0.portal_fixes
|
||||
erpnext.patches.v5_0.reset_values_in_tools
|
||||
execute:frappe.delete_doc("Page", "users")
|
||||
erpnext.patches.v5_0.update_material_transferred_for_manufacturing_again
|
||||
erpnext.patches.v5_0.update_material_transferred_for_manufacturing_again
|
||||
erpnext.patches.v5_0.index_on_account_and_gl_entry
|
||||
@@ -30,8 +30,8 @@ def create_receivable_payable_account():
|
||||
|
||||
account_id = account.name
|
||||
|
||||
frappe.db.set_value("Company", args["company"], ("default_receivable_account"
|
||||
if args["account_type"]=="Receivable" else "default_payable_account"), account_id)
|
||||
frappe.db.set_value("Company", args["company"], ("default_receivable_account"
|
||||
if args["account_type"]=="Receivable" else "default_payable_account"), account_id)
|
||||
|
||||
receivable_payable_accounts.setdefault(args["company"], {}).setdefault(args["account_type"], account_id)
|
||||
|
||||
|
||||
30
erpnext/patches/v5_0/index_on_account_and_gl_entry.py
Normal file
30
erpnext/patches/v5_0/index_on_account_and_gl_entry.py
Normal file
@@ -0,0 +1,30 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import frappe
|
||||
|
||||
def execute():
|
||||
index_map = {
|
||||
"Account": ["parent_account", "lft", "rgt"],
|
||||
"GL Entry": ["posting_date", "account", 'party', "voucher_no"],
|
||||
"Sales Invoice": ["posting_date", "debit_to", "customer"],
|
||||
"Purchase Invoice": ["posting_date", "credit_to", "supplier"]
|
||||
}
|
||||
|
||||
for dt, indexes in index_map.items():
|
||||
existing_indexes = [(d.Key_name, d.Column_name) for d in frappe.db.sql("""show index from `tab{0}`
|
||||
where Column_name != 'name'""".format(dt), as_dict=1)]
|
||||
|
||||
for old, column in existing_indexes:
|
||||
if column in ("parent", "group_or_ledger", "is_group", "is_pl_account", "debit_or_credit",
|
||||
"account_name", "company", "project_name", "voucher_date", "due_date", "bill_no",
|
||||
"bill_date", "is_opening", "fiscal_year", "outstanding_amount"):
|
||||
frappe.db.sql("alter table `tab{0}` drop index {1}".format(dt, old))
|
||||
|
||||
existing_indexes = [(d.Key_name, d.Column_name) for d in frappe.db.sql("""show index from `tab{0}`
|
||||
where Column_name != 'name'""".format(dt), as_dict=1)]
|
||||
|
||||
existing_indexed_columns = list(set([x[1] for x in existing_indexes]))
|
||||
|
||||
for new in indexes:
|
||||
if new not in existing_indexed_columns:
|
||||
frappe.db.sql("alter table `tab{0}` add index ({1})".format(dt, new))
|
||||
@@ -7,6 +7,6 @@ def execute():
|
||||
account_settings = frappe.get_doc("Accounts Settings")
|
||||
|
||||
if not account_settings.frozen_accounts_modifier and account_settings.bde_auth_role:
|
||||
frappe.db.set_value("Account Settings", None,
|
||||
frappe.db.set_value("Accounts Settings", None,
|
||||
"frozen_accounts_modifier", account_settings.bde_auth_role)
|
||||
|
||||
|
||||
@@ -9,41 +9,6 @@
|
||||
"doctype": "DocType",
|
||||
"document_type": "Master",
|
||||
"fields": [
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"fieldname": "employee",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Employee",
|
||||
"no_copy": 0,
|
||||
"options": "Employee",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "employee_name",
|
||||
"fieldtype": "Data",
|
||||
"label": "Employee Name",
|
||||
"options": "",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_2",
|
||||
"fieldtype": "Column Break",
|
||||
"permlevel": 0,
|
||||
"precision": ""
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"fieldname": "activity_type",
|
||||
@@ -64,6 +29,41 @@
|
||||
"search_index": 0,
|
||||
"set_only_once": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_2",
|
||||
"fieldtype": "Column Break",
|
||||
"permlevel": 0,
|
||||
"precision": ""
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"fieldname": "employee",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Employee",
|
||||
"no_copy": 0,
|
||||
"options": "Employee",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "employee_name",
|
||||
"fieldtype": "Data",
|
||||
"label": "Employee Name",
|
||||
"options": "",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "section_break_4",
|
||||
"fieldtype": "Section Break",
|
||||
@@ -136,7 +136,7 @@
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"modified": "2015-06-11 06:50:47.999788",
|
||||
"modified": "2015-06-16 03:12:25.644839",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Projects",
|
||||
"name": "Activity Cost",
|
||||
|
||||
@@ -15,12 +15,21 @@ class ActivityCost(Document):
|
||||
self.check_unique()
|
||||
|
||||
def set_title(self):
|
||||
if not self.employee_name:
|
||||
self.employee_name = frappe.db.get_value("Employee", self.employee, "employee_name")
|
||||
self.title = _("{0} for {1}").format(self.employee_name, self.activity_type)
|
||||
|
||||
if self.employee:
|
||||
if not self.employee_name:
|
||||
self.employee_name = frappe.db.get_value("Employee", self.employee, "employee_name")
|
||||
self.title = _("{0} for {1}").format(self.employee_name, self.activity_type)
|
||||
else:
|
||||
self.title = self.activity_type
|
||||
|
||||
def check_unique(self):
|
||||
if frappe.db.sql("""select name from `tabActivity Cost` where employee_name= %s and activity_type= %s and name != %s""",
|
||||
(self.employee_name, self.activity_type, self.name)):
|
||||
frappe.throw(_("Activity Cost exists for Employee {0} against Activity Type - {1}")
|
||||
.format(self.employee, self.activity_type), DuplicationError)
|
||||
if self.employee:
|
||||
if frappe.db.sql("""select name from `tabActivity Cost` where employee_name= %s and activity_type= %s and name != %s""",
|
||||
(self.employee_name, self.activity_type, self.name)):
|
||||
frappe.throw(_("Activity Cost exists for Employee {0} against Activity Type - {1}")
|
||||
.format(self.employee, self.activity_type), DuplicationError)
|
||||
else:
|
||||
if frappe.db.sql("""select name from `tabActivity Cost` where ifnull(employee, '')='' and activity_type= %s and name != %s""",
|
||||
(self.activity_type, self.name)):
|
||||
frappe.throw(_("Default Activity Cost exists for Activity Type - {0}")
|
||||
.format(self.activity_type), DuplicationError)
|
||||
|
||||
@@ -163,6 +163,7 @@
|
||||
"fieldtype": "Percent",
|
||||
"in_list_view": 0,
|
||||
"label": "% Tasks Completed",
|
||||
"no_copy": 1,
|
||||
"permlevel": 0,
|
||||
"read_only": 1
|
||||
},
|
||||
@@ -356,7 +357,7 @@
|
||||
"icon": "icon-puzzle-piece",
|
||||
"idx": 1,
|
||||
"max_attachments": 4,
|
||||
"modified": "2015-04-27 07:37:44.239930",
|
||||
"modified": "2015-06-12 09:00:54.080220",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Projects",
|
||||
"name": "Project",
|
||||
|
||||
@@ -128,7 +128,7 @@ class TimeLog(Document):
|
||||
|
||||
def update_production_order(self):
|
||||
"""Updates `start_date`, `end_date`, `status` for operation in Production Order."""
|
||||
|
||||
|
||||
if self.production_order and self.for_manufacturing:
|
||||
if not self.operation_id:
|
||||
frappe.throw(_("Operation ID not set"))
|
||||
@@ -208,22 +208,23 @@ class TimeLog(Document):
|
||||
self.production_order = None
|
||||
self.operation = None
|
||||
self.quantity = None
|
||||
|
||||
|
||||
def update_cost(self):
|
||||
rate = get_activity_cost(self.employee, self.activity_type)
|
||||
if rate:
|
||||
self.costing_rate = rate.get('costing_rate')
|
||||
self.billing_rate = rate.get('billing_rate')
|
||||
self.billing_rate = rate.get('billing_rate')
|
||||
self.costing_amount = self.costing_rate * self.hours
|
||||
if self.billable:
|
||||
self.billing_amount = self.billing_rate * self.hours
|
||||
else:
|
||||
self.billing_amount = 0
|
||||
|
||||
|
||||
def validate_task(self):
|
||||
if self.project and not self.task:
|
||||
# if a time log is being created against a project without production order
|
||||
if (self.project and not self.production_order) and not self.task:
|
||||
frappe.throw(_("Task is Mandatory if Time Log is against a project"))
|
||||
|
||||
|
||||
def update_task(self):
|
||||
if self.task and frappe.db.exists("Task", self.task):
|
||||
task = frappe.get_doc("Task", self.task)
|
||||
@@ -266,9 +267,12 @@ def get_events(start, end, filters=None):
|
||||
d.title += " for Project: " + d.project
|
||||
|
||||
return data
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_activity_cost(employee=None, activity_type=None):
|
||||
rate = frappe.db.sql("""select costing_rate, billing_rate from `tabActivity Cost` where employee= %s
|
||||
and activity_type= %s""", (employee, activity_type), as_dict=1)
|
||||
if not rate:
|
||||
rate = frappe.db.sql("""select costing_rate, billing_rate from `tabActivity Cost` where ifnull(employee, '')=''
|
||||
and activity_type= %s""", (activity_type), as_dict=1)
|
||||
return rate[0] if rate else {}
|
||||
|
||||
@@ -488,7 +488,7 @@
|
||||
{
|
||||
"fieldname": "base_discount_amount",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Discount Amount (Company Currency)",
|
||||
"label": "Additional Discount Amount (Company Currency)",
|
||||
"options": "Company:company:default_currency",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
@@ -858,7 +858,7 @@
|
||||
"idx": 1,
|
||||
"is_submittable": 1,
|
||||
"max_attachments": 1,
|
||||
"modified": "2015-05-27 02:48:00.388847",
|
||||
"modified": "2015-06-15 15:37:39.199814",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Selling",
|
||||
"name": "Quotation",
|
||||
|
||||
@@ -493,7 +493,7 @@
|
||||
{
|
||||
"fieldname": "base_discount_amount",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Discount Amount (Company Currency)",
|
||||
"label": "Additional Discount Amount (Company Currency)",
|
||||
"options": "Company:company:default_currency",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
@@ -1080,7 +1080,7 @@
|
||||
"idx": 1,
|
||||
"is_submittable": 1,
|
||||
"issingle": 0,
|
||||
"modified": "2015-05-27 02:48:01.160307",
|
||||
"modified": "2015-06-15 15:36:38.898462",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Selling",
|
||||
"name": "Sales Order",
|
||||
|
||||
@@ -26,7 +26,8 @@ class NamingSeries(Document):
|
||||
except frappe.DoesNotExistError:
|
||||
continue
|
||||
|
||||
prefixes = prefixes + "\n" + options
|
||||
if options:
|
||||
prefixes = prefixes + "\n" + options
|
||||
|
||||
prefixes.replace("\n\n", "\n")
|
||||
prefixes = "\n".join(sorted(prefixes.split()))
|
||||
|
||||
@@ -517,7 +517,7 @@
|
||||
{
|
||||
"fieldname": "base_discount_amount",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Discount Amount (Company Currency)",
|
||||
"label": "Additional Discount Amount (Company Currency)",
|
||||
"options": "Company:company:default_currency",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
@@ -1070,7 +1070,7 @@
|
||||
"idx": 1,
|
||||
"in_create": 0,
|
||||
"is_submittable": 1,
|
||||
"modified": "2015-05-27 02:47:59.778147",
|
||||
"modified": "2015-06-15 15:37:54.699371",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Stock",
|
||||
"name": "Delivery Note",
|
||||
|
||||
@@ -55,6 +55,9 @@ frappe.ui.form.on("Item", {
|
||||
// read only if any stock ledger entry exists
|
||||
erpnext.item.make_dashboard(frm);
|
||||
|
||||
// clear intro
|
||||
frm.set_intro();
|
||||
|
||||
if (frm.doc.has_variants) {
|
||||
frm.set_intro(__("This Item is a Template and cannot be used in transactions. Item attributes will be copied over into the variants unless 'No Copy' is set"), true);
|
||||
frm.add_custom_button(__("Show Variants"), function() {
|
||||
@@ -85,7 +88,7 @@ frappe.ui.form.on("Item", {
|
||||
erpnext.item.weight_to_validate(frm);
|
||||
erpnext.item.variants_can_not_be_created_manually(frm);
|
||||
},
|
||||
|
||||
|
||||
image: function(frm) {
|
||||
refresh_field("image_view");
|
||||
},
|
||||
@@ -209,11 +212,11 @@ $.extend(erpnext.item, {
|
||||
validated = 0;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
variants_can_not_be_created_manually: function(frm) {
|
||||
if (frm.doc.__islocal && frm.doc.variant_of)
|
||||
frappe.throw(__("Variants can not be created manually, add item attributes in the template item"))
|
||||
}
|
||||
|
||||
|
||||
|
||||
});
|
||||
|
||||
@@ -443,7 +443,7 @@
|
||||
{
|
||||
"fieldname": "base_discount_amount",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Discount Amount (Company Currency)",
|
||||
"label": "Additional Discount Amount (Company Currency)",
|
||||
"options": "Company:company:default_currency",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
@@ -854,7 +854,7 @@
|
||||
"icon": "icon-truck",
|
||||
"idx": 1,
|
||||
"is_submittable": 1,
|
||||
"modified": "2015-05-27 02:48:00.763945",
|
||||
"modified": "2015-06-15 15:38:43.754869",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Stock",
|
||||
"name": "Purchase Receipt",
|
||||
|
||||
@@ -54,7 +54,7 @@ def get_stock_ledger_entries(filters):
|
||||
return frappe.db.sql("""select item_code, batch_no, warehouse,
|
||||
posting_date, actual_qty
|
||||
from `tabStock Ledger Entry`
|
||||
where docstatus < 2 %s order by item_code, warehouse""" %
|
||||
where docstatus < 2 and ifnull(batch_no, '') != '' %s order by item_code, warehouse""" %
|
||||
conditions, as_dict=1)
|
||||
|
||||
def get_item_warehouse_batch_map(filters, float_precision):
|
||||
|
||||
0
erpnext/stock/report/bom_search/__init__.py
Normal file
0
erpnext/stock/report/bom_search/__init__.py
Normal file
42
erpnext/stock/report/bom_search/bom_search.js
Normal file
42
erpnext/stock/report/bom_search/bom_search.js
Normal file
@@ -0,0 +1,42 @@
|
||||
// Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and Contributors and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.query_reports["BOM Search"] = {
|
||||
"filters": [
|
||||
{
|
||||
fieldname: "item1",
|
||||
label: __("Item 1"),
|
||||
fieldtype: "Link",
|
||||
options: "Item"
|
||||
},
|
||||
{
|
||||
fieldname: "item2",
|
||||
label: __("Item 2"),
|
||||
fieldtype: "Link",
|
||||
options: "Item"
|
||||
},
|
||||
{
|
||||
fieldname: "item3",
|
||||
label: __("Item 3"),
|
||||
fieldtype: "Link",
|
||||
options: "Item"
|
||||
},
|
||||
{
|
||||
fieldname: "item4",
|
||||
label: __("Item 4"),
|
||||
fieldtype: "Link",
|
||||
options: "Item"
|
||||
},
|
||||
{
|
||||
fieldname: "item5",
|
||||
label: __("Item 5"),
|
||||
fieldtype: "Link",
|
||||
options: "Item"
|
||||
},
|
||||
{
|
||||
fieldname: "search_sub_assemblies",
|
||||
label: __("Search Sub Assemblies"),
|
||||
fieldtype: "Check",
|
||||
},
|
||||
]
|
||||
}
|
||||
17
erpnext/stock/report/bom_search/bom_search.json
Normal file
17
erpnext/stock/report/bom_search/bom_search.json
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"add_total_row": 0,
|
||||
"apply_user_permissions": 0,
|
||||
"creation": "2015-06-16 15:16:11.930954",
|
||||
"disabled": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "Report",
|
||||
"is_standard": "Yes",
|
||||
"modified": "2015-06-16 15:16:29.850834",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Stock",
|
||||
"name": "BOM Search",
|
||||
"owner": "Administrator",
|
||||
"ref_doctype": "BOM",
|
||||
"report_name": "BOM Search",
|
||||
"report_type": "Script Report"
|
||||
}
|
||||
43
erpnext/stock/report/bom_search/bom_search.py
Normal file
43
erpnext/stock/report/bom_search/bom_search.py
Normal file
@@ -0,0 +1,43 @@
|
||||
# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and Contributors and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe, json
|
||||
|
||||
def execute(filters=None):
|
||||
data = []
|
||||
parents = {
|
||||
"Sales BOM Item": "Sales BOM",
|
||||
"BOM Explosion Item": "BOM",
|
||||
"BOM Item": "BOM"
|
||||
}
|
||||
|
||||
for doctype in ("Sales BOM Item",
|
||||
"BOM Explosion Item" if filters.search_sub_assemblies else "BOM Item"):
|
||||
all_boms = {}
|
||||
for d in frappe.get_all(doctype, fields=["parent", "item_code"]):
|
||||
all_boms.setdefault(d.parent, []).append(d.item_code)
|
||||
|
||||
for parent, items in all_boms.iteritems():
|
||||
valid = True
|
||||
for key, item in filters.iteritems():
|
||||
if key != "search_sub_assemblies":
|
||||
if item and item not in items:
|
||||
valid = False
|
||||
|
||||
if valid:
|
||||
data.append((parent, parents[doctype]))
|
||||
|
||||
return [{
|
||||
"fieldname": "parent",
|
||||
"label": "BOM",
|
||||
"width": 200,
|
||||
"fieldtype": "Dynamic Link",
|
||||
"options": "doctype"
|
||||
},
|
||||
{
|
||||
"fieldname": "doctype",
|
||||
"label": "Type",
|
||||
"width": 200,
|
||||
"fieldtype": "Data"
|
||||
}], data
|
||||
Reference in New Issue
Block a user