diff --git a/.travis.yml b/.travis.yml index 747de20ba99..14260e3d25c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -33,16 +33,16 @@ before_script: - cd ~/frappe-bench - bench get-app erpnext $TRAVIS_BUILD_DIR - bench use test_site + - bench reinstall --mariadb-root-username root --mariadb-root-password travis --yes + - bench scheduler disable + - sed -i 's/9000/9001/g' sites/common_site_config.json + - bench start & + - sleep 10 jobs: include: - stage: test script: - - bench reinstall --mariadb-root-username root --mariadb-root-password travis --yes - - bench scheduler disable - - sed -i 's/9000/9001/g' sites/common_site_config.json - - bench start & - - sleep 10 - set -e - bench run-tests --app erpnext --coverage after_script: diff --git a/erpnext/__init__.py b/erpnext/__init__.py index 29e42440dd9..a482dac2dfe 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -5,7 +5,7 @@ import frappe from erpnext.hooks import regional_overrides from frappe.utils import getdate -__version__ = '10.1.78' +__version__ = '10.1.80' def get_default_company(user=None): '''Get default company for user''' diff --git a/erpnext/accounts/doctype/bank_account/bank_account.py b/erpnext/accounts/doctype/bank_account/bank_account.py index 08f8248f3d7..b13259b55d3 100644 --- a/erpnext/accounts/doctype/bank_account/bank_account.py +++ b/erpnext/accounts/doctype/bank_account/bank_account.py @@ -31,3 +31,13 @@ def make_bank_account(doctype, docname): doc.is_default = 1 return doc + +@frappe.whitelist() +def get_party_bank_account(party_type, party): + return frappe.db.get_value(party_type, + party, 'default_bank_account') + +@frappe.whitelist() +def get_bank_account_details(bank_account): + return frappe.db.get_value("Bank Account", + bank_account, ['account', 'bank', 'bank_account_no'], as_dict=1) diff --git a/erpnext/accounts/doctype/bank_reconciliation/bank_reconciliation.py b/erpnext/accounts/doctype/bank_reconciliation/bank_reconciliation.py index 7814b0883da..917276293d2 100644 --- a/erpnext/accounts/doctype/bank_reconciliation/bank_reconciliation.py +++ b/erpnext/accounts/doctype/bank_reconciliation/bank_reconciliation.py @@ -26,7 +26,7 @@ class BankReconciliation(Document): select "Journal Entry" as payment_document, t1.name as payment_entry, t1.cheque_no as cheque_number, t1.cheque_date, - t2.debit_in_account_currency as debit, t2.credit_in_account_currency as credit, + sum(t2.debit_in_account_currency) as debit, sum(t2.credit_in_account_currency) as credit, t1.posting_date, t2.against_account, t1.clearance_date, t2.account_currency from `tabJournal Entry` t1, `tabJournal Entry Account` t2 @@ -34,6 +34,7 @@ class BankReconciliation(Document): 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} + group by t2.account, t1.name order by t1.posting_date ASC, t1.name DESC """.format(condition), (self.bank_account, self.from_date, self.to_date), as_dict=1) diff --git a/erpnext/accounts/doctype/cost_center/cost_center.js b/erpnext/accounts/doctype/cost_center/cost_center.js index 8f3ae194da0..3df4da52efc 100644 --- a/erpnext/accounts/doctype/cost_center/cost_center.js +++ b/erpnext/accounts/doctype/cost_center/cost_center.js @@ -46,7 +46,7 @@ frappe.ui.form.on('Cost Center', { doctype_name: frm.doc.doctype, name: frm.doc.name, field_name: d.fields[0].fieldname, - field_value: data.cost_center_number, + number_value: data.cost_center_number, company: frm.doc.company }, callback: function(r) { diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.js b/erpnext/accounts/doctype/payment_entry/payment_entry.js index afb44e8f92f..30ae54b18b0 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.js +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.js @@ -284,7 +284,12 @@ frappe.ui.form.on('Payment Entry', { () => frm.events.get_outstanding_documents(frm), () => frm.events.hide_unhide_fields(frm), () => frm.events.set_dynamic_labels(frm), - () => { frm.set_party_account_based_on_party = false; } + () => { + frm.set_party_account_based_on_party = false; + if (r.message.bank_account) { + frm.set_value("bank_account", r.message.bank_account); + } + } ]); } } @@ -833,6 +838,25 @@ frappe.ui.form.on('Payment Entry', { } }) } + }, + + bank_account: function(frm) { + const field = frm.doc.payment_type == "Pay" ? "paid_from":"paid_to"; + if (frm.doc.bank_account && in_list(['Pay', 'Receive'], frm.doc.payment_type)) { + frappe.call({ + method: "erpnext.accounts.doctype.bank_account.bank_account.get_bank_account_details", + args: { + bank_account: frm.doc.bank_account + }, + callback: function(r) { + if (r.message) { + frm.set_value(field, r.message.account); + frm.set_value('bank', r.message.bank); + frm.set_value('bank_account_no', r.message.bank_account_no); + } + } + }); + } } }); diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.json b/erpnext/accounts/doctype/payment_entry/payment_entry.json index bc9062b96c9..9354c61addb 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.json +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.json @@ -1,5 +1,6 @@ { "allow_copy": 0, + "allow_events_in_timeline": 0, "allow_guest_to_view": 0, "allow_import": 1, "allow_rename": 0, @@ -379,24 +380,24 @@ { "allow_bulk_edit": 0, "allow_in_quick_entry": 0, - "allow_on_submit": 0, + "allow_on_submit": 1, "bold": 0, "collapsible": 0, "columns": 0, - "depends_on": "party", - "fieldname": "contact_person", - "fieldtype": "Link", + "depends_on": "eval:in_list([\"Receive\", \"Pay\"], doc.payment_type) && doc.party_type", + "description": "", + "fieldname": "party_name", + "fieldtype": "Data", "hidden": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, - "in_global_search": 0, + "in_global_search": 1, "in_list_view": 0, "in_standard_filter": 0, - "label": "Contact", + "label": "Party Name", "length": 0, "no_copy": 0, - "options": "Contact", "permlevel": 0, "precision": "", "print_hide": 0, @@ -444,24 +445,24 @@ { "allow_bulk_edit": 0, "allow_in_quick_entry": 0, - "allow_on_submit": 1, + "allow_on_submit": 0, "bold": 0, "collapsible": 0, "columns": 0, - "depends_on": "eval:in_list([\"Receive\", \"Pay\"], doc.payment_type) && doc.party_type", - "description": "", - "fieldname": "party_name", - "fieldtype": "Data", + "depends_on": "party", + "fieldname": "bank_account", + "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, - "in_global_search": 1, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, - "label": "Party Name", + "label": "Bank Account", "length": 0, "no_copy": 0, + "options": "Bank Account", "permlevel": 0, "precision": "", "print_hide": 0, @@ -509,6 +510,40 @@ "translatable": 0, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "party", + "fieldname": "contact_person", + "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": "Contact", + "length": 0, + "no_copy": 0, + "options": "Contact", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, { "allow_bulk_edit": 0, "allow_in_quick_entry": 0, @@ -1867,6 +1902,72 @@ "translatable": 0, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_from": "bank_account.bank", + "fieldname": "bank", + "fieldtype": "Read Only", + "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": "Bank", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_from": "bank_account.bank_account_no", + "fieldname": "bank_account_no", + "fieldtype": "Read Only", + "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": "Bank Account No", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, { "allow_bulk_edit": 0, "allow_in_quick_entry": 0, @@ -2040,7 +2141,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2018-09-25 14:38:48.312629", + "modified": "2019-01-15 15:58:40.742601", "modified_by": "Administrator", "module": "Accounts", "name": "Payment Entry", diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py index f213ffa6580..7f1f55005c0 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py @@ -12,6 +12,7 @@ from erpnext.accounts.doctype.journal_entry.journal_entry import get_default_ban from erpnext.setup.utils import get_exchange_rate from erpnext.accounts.general_ledger import make_gl_entries from erpnext.hr.doctype.expense_claim.expense_claim import update_reimbursed_amount +from erpnext.accounts.doctype.bank_account.bank_account import get_party_bank_account, get_bank_account_details from erpnext.controllers.accounts_controller import AccountsController, get_supplier_block_status from six import string_types, iteritems @@ -88,6 +89,16 @@ class PaymentEntry(AccountsController): .format(d.idx, d.reference_doctype, d.reference_name)) reference_names.append((d.reference_doctype, d.reference_name)) + def set_bank_account_data(self): + if self.bank_account: + bank_data = get_bank_account_details(self.bank_account) + + field = "paid_from" if self.payment_type == "Pay" else "paid_to" + + self.bank = bank_data.bank + self.bank_account_no = bank_data.bank_account_no + self.set(field, bank_data.account) + def validate_allocated_amount(self): for d in self.get("references"): if (flt(d.allocated_amount))> 0: @@ -670,6 +681,7 @@ def get_negative_outstanding_invoices(party_type, party, party_account, party_ac @frappe.whitelist() def get_party_details(company, party_type, party, date, cost_center=None): + bank_account = '' if not frappe.db.exists(party_type, party): frappe.throw(_("Invalid {0}: {1}").format(party_type, party)) @@ -680,13 +692,16 @@ def get_party_details(company, party_type, party, date, cost_center=None): _party_name = "title" if party_type == "Student" else party_type.lower() + "_name" party_name = frappe.db.get_value(party_type, party, _party_name) party_balance = get_balance_on(party_type=party_type, party=party, cost_center=cost_center) + if party_type in ["Customer", "Supplier"]: + bank_account = get_party_bank_account(party_type, party) return { "party_account": party_account, "party_name": party_name, "party_account_currency": account_currency, "party_balance": party_balance, - "account_balance": account_balance + "account_balance": account_balance, + "bank_account": bank_account } @@ -890,6 +905,11 @@ def get_payment_entry(dt, dn, party_amount=None, bank_account=None, bank_amount= pe.allocate_payment_amount = 1 pe.letter_head = doc.get("letter_head") + if pe.party_type in ["Customer", "Supplier"]: + bank_account = get_party_bank_account(pe.party_type, pe.party) + pe.set("bank_account", bank_account) + pe.set_bank_account_data() + # only Purchase Invoice can be blocked individually if doc.doctype == "Purchase Invoice" and doc.invoice_is_blocked(): frappe.msgprint(_('{0} is on hold till {1}'.format(doc.name, doc.release_date))) diff --git a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.json b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.json index b211b500a15..cfb24c3954c 100644 --- a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.json +++ b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.json @@ -1,23 +1,34 @@ { "allow_copy": 1, + "allow_events_in_timeline": 0, + "allow_guest_to_view": 0, "allow_import": 0, "allow_rename": 0, + "beta": 0, "creation": "2014-07-09 12:04:51.681583", "custom": 0, "docstatus": 0, "doctype": "DocType", "document_type": "", + "editable_grid": 0, + "engine": "InnoDB", "fields": [ { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, + "columns": 0, "fieldname": "company", "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": "Company", "length": 0, "no_copy": 0, @@ -26,22 +37,30 @@ "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": 0 }, { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, + "columns": 0, "fieldname": "party_type", "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": "Party Type", "length": 0, "no_copy": 0, @@ -50,23 +69,31 @@ "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": 0 }, { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, + "columns": 0, "depends_on": "", "fieldname": "party", "fieldtype": "Dynamic 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": "Party", "length": 0, "no_copy": 0, @@ -75,22 +102,30 @@ "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": 0 }, { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, + "columns": 0, "fieldname": "receivable_payable_account", "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": "Receivable / Payable Account", "length": 0, "no_copy": 0, @@ -100,22 +135,30 @@ "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": 0 }, { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, + "columns": 0, "fieldname": "bank_cash_account", "fieldtype": "Link", "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": "Bank / Cash Account", "length": 0, "no_copy": 0, @@ -124,22 +167,30 @@ "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 0, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, + "columns": 0, "fieldname": "col_break1", "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, @@ -147,22 +198,30 @@ "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 0, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, + "columns": 0, "fieldname": "from_date", "fieldtype": "Date", "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": "From Invoice Date", "length": 0, "no_copy": 0, @@ -170,22 +229,30 @@ "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, + "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, + "columns": 0, "fieldname": "to_date", "fieldtype": "Date", "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": "To Invoice Date", "length": 0, "no_copy": 0, @@ -193,22 +260,30 @@ "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, + "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, + "columns": 0, "fieldname": "minimum_amount", "fieldtype": "Currency", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Minimum Invoice Amount", "length": 0, "no_copy": 0, @@ -216,22 +291,30 @@ "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 0, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, + "columns": 0, "fieldname": "maximum_amount", "fieldtype": "Currency", "hidden": 0, "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Maximum Invoice Amount", "length": 0, "no_copy": 0, @@ -239,22 +322,63 @@ "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 0, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, + "columns": 0, + "description": "System will fetch all the entries if limit value is zero.", + "fieldname": "limit", + "fieldtype": "Int", + "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": "Limit", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, "fieldname": "get_unreconciled_entries", "fieldtype": "Button", "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": "Get Unreconciled Entries", "length": 0, "no_copy": 0, @@ -262,22 +386,30 @@ "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 0, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, + "columns": 0, "fieldname": "sec_break1", "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": "Unreconciled Payment Details", "length": 0, "no_copy": 0, @@ -285,22 +417,30 @@ "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 0, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, + "columns": 0, "fieldname": "payments", "fieldtype": "Table", "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": "Payments", "length": 0, "no_copy": 0, @@ -309,22 +449,30 @@ "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 0, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, + "columns": 0, "fieldname": "reconcile", "fieldtype": "Button", "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": "Reconcile", "length": 0, "no_copy": 0, @@ -332,22 +480,30 @@ "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 0, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, + "columns": 0, "fieldname": "sec_break2", "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": "Invoice/Journal Entry Details", "length": 0, "no_copy": 0, @@ -355,22 +511,30 @@ "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 0, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, + "columns": 0, "fieldname": "invoices", "fieldtype": "Table", "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": "Invoices", "length": 0, "no_copy": 0, @@ -379,25 +543,28 @@ "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 } ], + "has_web_view": 0, "hide_heading": 0, "hide_toolbar": 1, - "icon": "fa fa-resize-horizontal", + "icon": "icon-resize-horizontal", "idx": 0, + "image_view": 0, "in_create": 0, - "is_submittable": 0, "issingle": 1, "istable": 0, "max_attachments": 0, "menu_index": 0, - "modified": "2016-01-04 02:26:58.807921", + "modified": "2019-01-15 17:42:21.135214", "modified_by": "Administrator", "module": "Accounts", "name": "Payment Reconciliation", @@ -406,7 +573,6 @@ "permissions": [ { "amend": 0, - "apply_user_permissions": 0, "cancel": 0, "create": 1, "delete": 1, @@ -426,7 +592,6 @@ }, { "amend": 0, - "apply_user_permissions": 0, "cancel": 0, "create": 1, "delete": 1, @@ -445,8 +610,13 @@ "write": 1 } ], + "quick_entry": 0, "read_only": 0, "read_only_onload": 0, + "show_name_in_global_search": 0, "sort_field": "modified", - "sort_order": "DESC" + "sort_order": "DESC", + "track_changes": 1, + "track_seen": 0, + "track_views": 0 } \ No newline at end of file diff --git a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py index 7cd951aba46..094ece95e81 100644 --- a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py +++ b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py @@ -25,7 +25,7 @@ class PaymentReconciliation(Document): def get_payment_entries(self): order_doctype = "Sales Order" if self.party_type=="Customer" else "Purchase Order" payment_entries = get_advance_payment_entries(self.party_type, self.party, - self.receivable_payable_account, order_doctype, against_all_orders=True) + self.receivable_payable_account, order_doctype, against_all_orders=True, limit=self.limit) return payment_entries @@ -36,6 +36,8 @@ class PaymentReconciliation(Document): bank_account_condition = "t2.against_account like %(bank_cash_account)s" \ if self.bank_cash_account else "1=1" + limit_cond = "limit %s" % (self.limit or 1000) + journal_entries = frappe.db.sql(""" select "Journal Entry" as reference_type, t1.name as reference_name, @@ -55,10 +57,11 @@ class PaymentReconciliation(Document): THEN 1=1 ELSE {bank_account_condition} END) - order by t1.posting_date + order by t1.posting_date {limit_cond} """.format(**{ "dr_or_cr": dr_or_cr, "bank_account_condition": bank_account_condition, + "limit_cond": limit_cond }), { "party_type": self.party_type, "party": self.party, @@ -80,7 +83,7 @@ class PaymentReconciliation(Document): condition = self.check_condition() non_reconciled_invoices = get_outstanding_invoices(self.party_type, self.party, - self.receivable_payable_account, condition=condition) + self.receivable_payable_account, condition=condition, limit=self.limit) self.add_invoice_entries(non_reconciled_invoices) diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py index 9138739253a..f2d5006cd0a 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -1,8 +1,8 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # License: GNU General Public License v3. See license.txt +# -*- coding: utf-8 -*- + from __future__ import unicode_literals - - import frappe, erpnext from frappe.utils import cint, cstr, formatdate, flt, getdate, nowdate from frappe import _, throw diff --git a/erpnext/accounts/doctype/sales_invoice/pos.py b/erpnext/accounts/doctype/sales_invoice/pos.py index d6e60d1277b..c5ce0f79c38 100755 --- a/erpnext/accounts/doctype/sales_invoice/pos.py +++ b/erpnext/accounts/doctype/sales_invoice/pos.py @@ -332,10 +332,12 @@ def get_bin_data(pos_profile): itemwise_bin_data = {} cond = "1=1" if pos_profile.get('warehouse'): - cond = "warehouse = '{0}'".format(pos_profile.get('warehouse')) + cond = "warehouse = %(warehouse)s" bin_data = frappe.db.sql(""" select item_code, warehouse, actual_qty from `tabBin` - where actual_qty > 0 and {cond}""".format(cond=cond), as_dict=1) + where actual_qty > 0 and {cond}""".format(cond=cond), { + 'warehouse': frappe.db.escape(pos_profile.get('warehouse')) + }, as_dict=1) for bins in bin_data: if bins.item_code not in itemwise_bin_data: diff --git a/erpnext/accounts/party.py b/erpnext/accounts/party.py index a69a1722845..1e1f8b5b830 100644 --- a/erpnext/accounts/party.py +++ b/erpnext/accounts/party.py @@ -14,7 +14,7 @@ from frappe.contacts.doctype.address.address import (get_address_display, from frappe.contacts.doctype.contact.contact import get_contact_details, get_default_contact from erpnext.exceptions import PartyFrozen, PartyDisabled, InvalidAccountCurrency from erpnext.accounts.utils import get_fiscal_year -from erpnext import get_default_currency, get_company_currency +from erpnext import get_company_currency from six import iteritems @@ -562,3 +562,12 @@ def get_party_shipping_address(doctype, name): return out[0][0] else: return '' + +def get_partywise_advanced_payment_amount(party_type="Customer"): + data = frappe.db.sql(""" SELECT party, sum({0}) as amount + FROM `tabGL Entry` + WHERE party_type = %s and against_voucher is null GROUP BY party""" + .format(("credit - debit") if party_type == "Customer" else "debit") , party_type) + + if data: + return frappe._dict(data) \ No newline at end of file diff --git a/erpnext/accounts/print_format/gst_pos_invoice/gst_pos_invoice.json b/erpnext/accounts/print_format/gst_pos_invoice/gst_pos_invoice.json index 33af3135dd2..8a313688b98 100644 --- a/erpnext/accounts/print_format/gst_pos_invoice/gst_pos_invoice.json +++ b/erpnext/accounts/print_format/gst_pos_invoice/gst_pos_invoice.json @@ -7,10 +7,10 @@ "docstatus": 0, "doctype": "Print Format", "font": "Default", - "html": "\n\n
\n\t{{ doc.company }}
\n\t{% if doc.company_address_display %}\n\t\t{% set company_address = doc.company_address_display.replace(\"\\n\", \" \").replace(\"
\", \" \") %}\n\t\t{% if \"GSTIN\" not in company_address %}\n\t\t\t{{ company_address }}\n\t\t\t{{ _(\"GSTIN\") }}:{{ doc.company_gstin }}\n\t\t{% else %}\n\t\t\t{{ company_address.replace(\"GSTIN\", \"
GSTIN\") }}\n\t\t{% endif %}\n\t{% endif %}\n\t
\n\t{% if doc.docstatus == 0 %}\n\t\t{{ doc.status + \" \"+ (doc.select_print_heading or _(\"Invoice\")) }}
\n\t{% else %}\n\t\t{{ doc.select_print_heading or _(\"Invoice\") }}
\n\t{% endif %}\n
\n\t{{ _(\"Receipt No\") }}: {{ doc.name }}
\n\t{{ _(\"Date\") }}: {{ doc.get_formatted(\"posting_date\") }}
\n\t{% if doc.grand_total > 50000 %}\n\t\t{% set customer_address = doc.address_display.replace(\"\\n\", \" \").replace(\"
\", \" \") %}\n\t\t{{ _(\"Customer\") }}:
\n\t\t{{ doc.customer_name }}
\n\t\t{{ customer_address }}\n\t{% endif %}\n
| {{ _(\"Item\") }} | \n\t\t\t{{ _(\"Qty\") }} | \n\t\t\t{{ _(\"Amount\") }} | \n\t\t
|---|---|---|
| \n\t\t\t\t{{ item.item_code }}\n\t\t\t\t{%- if item.item_name != item.item_code -%}\n\t\t\t\t\t {{ item.item_name }}\n\t\t\t\t{%- endif -%}\n\t\t\t\t{%- if item.gst_hsn_code -%}\n\t\t\t\t\t {{ _(\"HSN/SAC\") }}: {{ item.gst_hsn_code }}\n\t\t\t\t{%- endif -%}\n\t\t\t\t{%- if item.serial_no -%}\n\t\t\t\t\t {{ _(\"Serial No\") }}: {{ item.serial_no }}\n\t\t\t\t{%- endif -%}\n\t\t\t | \n\t\t\t{{ item.qty }} @ {{ item.rate }} | \n\t\t\t{{ item.get_formatted(\"amount\") }} | \n\t\t
| \n\t\t\t\t\t{{ _(\"Total Excl. Tax\") }}\n\t\t\t\t | \n\t\t\t\t\n\t\t\t\t\t{{ doc.get_formatted(\"net_total\", doc) }}\n\t\t\t\t | \n\t\t\t{% else %}\n\t\t\t\t\n\t\t\t\t\t{{ _(\"Total\") }}\n\t\t\t\t | \n\t\t\t\t\n\t\t\t\t\t{{ doc.get_formatted(\"total\", doc) }}\n\t\t\t\t | \n\t\t\t{% endif %}\n\t\t
| \n\t\t\t\t\t{{ row.description }}\n\t\t\t\t | \n\t\t\t\t\n\t\t\t\t\t{{ row.get_formatted(\"tax_amount\", doc) }}\n\t\t\t\t | \n\t\t\t||
| \n\t\t\t\t{{ _(\"Discount\") }}\n\t\t\t | \n\t\t\t\n\t\t\t\t{{ doc.get_formatted(\"discount_amount\") }}\n\t\t\t | \n\t\t||
| \n\t\t\t\t{{ _(\"Grand Total\") }}\n\t\t\t | \n\t\t\t\n\t\t\t\t{{ doc.get_formatted(\"grand_total\") }}\n\t\t\t | \n\t\t||
| \n\t\t\t\t{{ _(\"Rounded Total\") }}\n\t\t\t | \n\t\t\t\n\t\t\t\t{{ doc.get_formatted(\"rounded_total\") }}\n\t\t\t | \n\t\t||
| \n\t\t\t\t{{ _(\"Paid Amount\") }}\n\t\t\t | \n\t\t\t\n\t\t\t\t{{ doc.get_formatted(\"paid_amount\") }}\n\t\t\t | \n\t\t||
| \n\t\t\t\t{{ _(\"Change Amount\") }}\n\t\t\t | \n\t\t\t\n\t\t\t\t{{ doc.get_formatted(\"change_amount\") }}\n\t\t\t | \n\t\t
Tax Breakup:
\n{{ doc.terms or \"\" }}
\n{{ _(\"Thank you, please visit again.\") }}
", + "html": "\n\n\n\t{{ doc.company }}
\n\t{% if doc.company_address_display %}\n\t\t{% set company_address = doc.company_address_display.replace(\"\\n\", \" \").replace(\"
\", \" \") %}\n\t\t{% if \"GSTIN\" not in company_address %}\n\t\t\t{{ company_address }}\n\t\t\t{{ _(\"GSTIN\") }}:{{ doc.company_gstin }}\n\t\t{% else %}\n\t\t\t{{ company_address.replace(\"GSTIN\", \"
GSTIN\") }}\n\t\t{% endif %}\n\t{% endif %}\n\t
\n\t{% if doc.docstatus == 0 %}\n\t\t{{ doc.status + \" \"+ (doc.select_print_heading or _(\"Invoice\")) }}
\n\t{% else %}\n\t\t{{ doc.select_print_heading or _(\"Invoice\") }}
\n\t{% endif %}\n
\n\t{{ _(\"Receipt No\") }}: {{ doc.name }}
\n\t{{ _(\"Date\") }}: {{ doc.get_formatted(\"posting_date\") }}
\n\t{% if doc.grand_total > 50000 %}\n\t\t{% set customer_address = doc.address_display.replace(\"\\n\", \" \").replace(\"
\", \" \") %}\n\t\t{{ _(\"Customer\") }}:
\n\t\t{{ doc.customer_name }}
\n\t\t{{ customer_address }}\n\t{% endif %}\n
| {{ _(\"Item\") }} | \n\t\t\t{{ _(\"Qty\") }} | \n\t\t\t{{ _(\"Amount\") }} | \n\t\t
|---|---|---|
| \n\t\t\t\t{{ item.item_code }}\n\t\t\t\t{%- if item.item_name != item.item_code -%}\n\t\t\t\t\t {{ item.item_name }}\n\t\t\t\t{%- endif -%}\n\t\t\t\t{%- if item.gst_hsn_code -%}\n\t\t\t\t\t {{ _(\"HSN/SAC\") }}: {{ item.gst_hsn_code }}\n\t\t\t\t{%- endif -%}\n\t\t\t\t{%- if item.serial_no -%}\n\t\t\t\t\t {{ _(\"Serial No\") }}: {{ item.serial_no }}\n\t\t\t\t{%- endif -%}\n\t\t\t | \n\t\t\t{{ item.qty }} @ {{ item.rate }} | \n\t\t\t{{ item.get_formatted(\"amount\") }} | \n\t\t
| \n\t\t\t\t\t{{ _(\"Total Excl. Tax\") }}\n\t\t\t\t | \n\t\t\t\t\n\t\t\t\t\t{{ doc.get_formatted(\"net_total\", doc) }}\n\t\t\t\t | \n\t\t\t{% else %}\n\t\t\t\t\n\t\t\t\t\t{{ _(\"Total\") }}\n\t\t\t\t | \n\t\t\t\t\n\t\t\t\t\t{{ doc.get_formatted(\"total\", doc) }}\n\t\t\t\t | \n\t\t\t{% endif %}\n\t\t
| \n\t\t\t\t\t{{ row.description }}\n\t\t\t\t | \n\t\t\t\t\n\t\t\t\t\t{{ row.get_formatted(\"tax_amount\", doc) }}\n\t\t\t\t | \n\t\t\t||
| \n\t\t\t\t{{ _(\"Discount\") }}\n\t\t\t | \n\t\t\t\n\t\t\t\t{{ doc.get_formatted(\"discount_amount\") }}\n\t\t\t | \n\t\t||
| \n\t\t\t\t{{ _(\"Grand Total\") }}\n\t\t\t | \n\t\t\t\n\t\t\t\t{{ doc.get_formatted(\"grand_total\") }}\n\t\t\t | \n\t\t||
| \n\t\t\t\t{{ _(\"Rounded Total\") }}\n\t\t\t | \n\t\t\t\n\t\t\t\t{{ doc.get_formatted(\"rounded_total\") }}\n\t\t\t | \n\t\t||
| \n\t\t\t\t{{ _(\"Paid Amount\") }}\n\t\t\t | \n\t\t\t\n\t\t\t\t{{ doc.get_formatted(\"paid_amount\") }}\n\t\t\t | \n\t\t||
| \n\t\t\t\t{{ _(\"Change Amount\") }}\n\t\t\t | \n\t\t\t\n\t\t\t\t{{ doc.get_formatted(\"change_amount\") }}\n\t\t\t | \n\t\t
{{ doc.terms or \"\" }}
\n{{ _(\"Thank you, please visit again.\") }}
", "idx": 0, "line_breaks": 0, - "modified": "2018-03-20 14:24:08.167930", + "modified": "2019-01-24 17:09:27.190929", "modified_by": "Administrator", "module": "Accounts", "name": "GST POS Invoice", diff --git a/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py b/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py index 842ecdb8e93..cc21d3427d3 100644 --- a/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py +++ b/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py @@ -5,6 +5,7 @@ from __future__ import unicode_literals import frappe from frappe import _, scrub from frappe.utils import flt +from erpnext.accounts.party import get_partywise_advanced_payment_amount from erpnext.accounts.report.accounts_receivable.accounts_receivable import ReceivablePayableReport from six import iteritems @@ -24,6 +25,12 @@ class AccountsReceivableSummary(ReceivablePayableReport): credit_debit_label = "Credit Note Amt" if args.get('party_type') == 'Customer' else "Debit Note Amt" columns += [{ + "label": _("Advance Amount"), + "fieldname": "advance_amount", + "fieldtype": "Currency", + "options": "currency", + "width": 100 + },{ "label": _("Total Invoiced Amt"), "fieldname": "total_invoiced_amt", "fieldtype": "Currency", @@ -129,12 +136,15 @@ class AccountsReceivableSummary(ReceivablePayableReport): partywise_total = self.get_partywise_total(party_naming_by, args) + partywise_advance_amount = get_partywise_advanced_payment_amount(args.get("party_type")) or {} for party, party_dict in iteritems(partywise_total): row = [party] if party_naming_by == "Naming Series": row += [self.get_party_name(args.get("party_type"), party)] + row += [partywise_advance_amount.get(party, 0)] + row += [ party_dict.invoiced_amt, party_dict.paid_amt, party_dict.credit_amt, party_dict.outstanding_amt, party_dict.range1, party_dict.range2, party_dict.range3, party_dict.range4, @@ -185,6 +195,9 @@ class AccountsReceivableSummary(ReceivablePayableReport): if party_naming_by == "Naming Series": cols += ["party_name"] + if args.get("party_type") == 'Customer': + cols += ["contact"] + cols += ["voucher_type", "voucher_no", "due_date"] if args.get("party_type") == "Supplier": diff --git a/erpnext/accounts/report/bank_clearance_summary/bank_clearance_summary.py b/erpnext/accounts/report/bank_clearance_summary/bank_clearance_summary.py index 13424dbcb56..0861b20f14a 100644 --- a/erpnext/accounts/report/bank_clearance_summary/bank_clearance_summary.py +++ b/erpnext/accounts/report/bank_clearance_summary/bank_clearance_summary.py @@ -36,8 +36,8 @@ def get_conditions(filters): def get_entries(filters): conditions = get_conditions(filters) journal_entries = frappe.db.sql("""SELECT - "Journal Entry", jv.name, jv.posting_date, jv.cheque_no, jv.clearance_date, jvd.against_account, - if((jvd.debit - jvd.credit) < 0, (jvd.debit - jvd.credit) * -1, (jvd.debit - jvd.credit)) + "Journal Entry", jv.name, jv.posting_date, jv.cheque_no, + jv.clearance_date, jvd.against_account, jvd.debit - jvd.credit FROM `tabJournal Entry Account` jvd, `tabJournal Entry` jv WHERE @@ -46,7 +46,7 @@ def get_entries(filters): payment_entries = frappe.db.sql("""SELECT "Payment Entry", name, posting_date, reference_no, clearance_date, party, - if(paid_from=%(account)s, paid_amount, received_amount) + if(paid_from=%(account)s, paid_amount * -1, received_amount) FROM `tabPayment Entry` WHERE diff --git a/erpnext/accounts/report/customer_ledger_summary/__init__.py b/erpnext/accounts/report/customer_ledger_summary/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.js b/erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.js new file mode 100644 index 00000000000..a1236316638 --- /dev/null +++ b/erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.js @@ -0,0 +1,97 @@ +// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt +/* eslint-disable */ + +frappe.query_reports["Customer Ledger Summary"] = { + "filters": [ + { + "fieldname":"company", + "label": __("Company"), + "fieldtype": "Link", + "options": "Company", + "default": frappe.defaults.get_user_default("Company") + }, + { + "fieldname":"from_date", + "label": __("From Date"), + "fieldtype": "Date", + "default": frappe.datetime.add_months(frappe.datetime.get_today(), -1), + "reqd": 1, + "width": "60px" + }, + { + "fieldname":"to_date", + "label": __("To Date"), + "fieldtype": "Date", + "default": frappe.datetime.get_today(), + "reqd": 1, + "width": "60px" + }, + { + "fieldname":"finance_book", + "label": __("Finance Book"), + "fieldtype": "Link", + "options": "Finance Book" + }, + { + "fieldname":"party", + "label": __("Customer"), + "fieldtype": "Link", + "options": "Customer", + on_change: () => { + var party = frappe.query_report.get_filter_value('party'); + if (party) { + frappe.db.get_value('Customer', party, ["tax_id", "customer_name"], function(value) { + frappe.query_report.set_filter_value('tax_id', value["tax_id"]); + frappe.query_report.set_filter_value('customer_name', value["customer_name"]); + }); + } else { + frappe.query_report.set_filter_value('tax_id', ""); + frappe.query_report.set_filter_value('customer_name', ""); + } + } + }, + { + "fieldname":"customer_group", + "label": __("Customer Group"), + "fieldtype": "Link", + "options": "Customer Group" + }, + { + "fieldname":"payment_terms_template", + "label": __("Payment Terms Template"), + "fieldtype": "Link", + "options": "Payment Terms Template" + }, + { + "fieldname":"territory", + "label": __("Territory"), + "fieldtype": "Link", + "options": "Territory" + }, + { + "fieldname":"sales_partner", + "label": __("Sales Partner"), + "fieldtype": "Link", + "options": "Sales Partner" + }, + { + "fieldname":"sales_person", + "label": __("Sales Person"), + "fieldtype": "Link", + "options": "Sales Person" + }, + { + "fieldname":"tax_id", + "label": __("Tax Id"), + "fieldtype": "Data", + "hidden": 1 + }, + { + "fieldname":"customer_name", + "label": __("Customer Name"), + "fieldtype": "Data", + "hidden": 1 + } + ] +}; diff --git a/erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.json b/erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.json new file mode 100644 index 00000000000..91e4e197d3a --- /dev/null +++ b/erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.json @@ -0,0 +1,26 @@ +{ + "add_total_row": 1, + "creation": "2018-12-11 00:58:19.078506", + "disabled": 0, + "docstatus": 0, + "doctype": "Report", + "idx": 0, + "is_standard": "Yes", + "modified": "2018-12-11 00:59:21.708343", + "modified_by": "Administrator", + "module": "Accounts", + "name": "Customer Ledger Summary", + "owner": "Administrator", + "prepared_report": 0, + "ref_doctype": "Sales Invoice", + "report_name": "Customer Ledger Summary", + "report_type": "Script Report", + "roles": [ + { + "role": "Accounts Manager" + }, + { + "role": "Accounts User" + } + ] +} \ No newline at end of file diff --git a/erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.py b/erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.py new file mode 100644 index 00000000000..e33bd61411e --- /dev/null +++ b/erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.py @@ -0,0 +1,321 @@ +# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +from __future__ import unicode_literals +import frappe +import erpnext +from frappe import _ +from frappe.utils import getdate, nowdate +from six import iteritems, itervalues + +class PartyLedgerSummaryReport(object): + def __init__(self, filters=None): + self.filters = frappe._dict(filters or {}) + self.filters.from_date = getdate(self.filters.from_date or nowdate()) + self.filters.to_date = getdate(self.filters.to_date or nowdate()) + + def run(self, args): + if self.filters.from_date > self.filters.to_date: + frappe.throw(_("From Date must be before To Date")) + + self.filters.party_type = args.get("party_type") + self.party_naming_by = frappe.db.get_value(args.get("naming_by")[0], None, args.get("naming_by")[1]) + + discount_account_field = "discount_allowed_account" if self.filters.party_type == "Customer" \ + else "discount_received_account" + self.round_off_account, self.write_off_account, self.discount_account = frappe.get_cached_value('Company', + self.filters.company, ["round_off_account", "write_off_account", discount_account_field]) + + columns = self.get_columns() + data = self.get_data() + return columns, data + + def get_columns(self): + columns = [{ + "label": _(self.filters.party_type), + "fieldtype": "Link", + "fieldname": "party", + "options": self.filters.party_type, + "width": 200 + }] + + if self.party_naming_by == "Naming Series": + columns.append({ + "label": _(self.filters.party_type + "Name"), + "fieldtype": "Data", + "fieldname": "party_name", + "width": 110 + }) + + credit_or_debit_note = "Credit Note" if self.filters.party_type == "Customer" else "Debit Note" + discount_allowed_or_received = "Discount Allowed" if self.filters.party_type == "Customer" else "Discount Received" + + columns += [ + { + "label": _("Opening Balance"), + "fieldname": "opening_balance", + "fieldtype": "Currency", + "options": "currency", + "width": 120 + }, + { + "label": _("Invoiced Amount"), + "fieldname": "invoiced_amount", + "fieldtype": "Currency", + "options": "currency", + "width": 120 + }, + { + "label": _("Paid Amount"), + "fieldname": "paid_amount", + "fieldtype": "Currency", + "options": "currency", + "width": 120 + }, + { + "label": _(credit_or_debit_note), + "fieldname": "return_amount", + "fieldtype": "Currency", + "options": "currency", + "width": 120 + }, + { + "label": _(discount_allowed_or_received), + "fieldname": "discount_amount", + "fieldtype": "Currency", + "options": "currency", + "width": 120 + }, + { + "label": _("Write Off Amount"), + "fieldname": "write_off_amount", + "fieldtype": "Currency", + "options": "currency", + "width": 120 + }, + { + "label": _("Other Adjustments"), + "fieldname": "adjustment_amount", + "fieldtype": "Currency", + "options": "currency", + "width": 120 + }, + { + "label": _("Closing Balance"), + "fieldname": "closing_balance", + "fieldtype": "Currency", + "options": "currency", + "width": 120 + }, + { + "label": _("Currency"), + "fieldname": "currency", + "fieldtype": "Link", + "options": "Currency", + "width": 50 + } + ] + + return columns + + def get_data(self): + if not self.filters.get("company"): + self.filters["company"] = frappe.db.get_single_value('Global Defaults', 'default_company') + + company_currency = frappe.get_cached_value('Company', self.filters.get("company"), "default_currency") + invoice_dr_or_cr = "debit" if self.filters.party_type == "Customer" else "credit" + reverse_dr_or_cr = "credit" if self.filters.party_type == "Customer" else "debit" + + self.get_gl_entries() + self.get_return_invoices() + self.get_party_adjustment_amounts() + + self.party_data = frappe._dict({}) + for gle in self.gl_entries: + self.party_data.setdefault(gle.party, frappe._dict({ + "party": gle.party, + "party_name": gle.party_name, + "opening_balance": 0, + "invoiced_amount": 0, + "paid_amount": 0, + "return_amount": 0, + "closing_balance": 0, + "currency": company_currency + })) + + amount = gle.get(invoice_dr_or_cr) - gle.get(reverse_dr_or_cr) + self.party_data[gle.party].closing_balance += amount + + if gle.posting_date < self.filters.from_date: + self.party_data[gle.party].opening_balance += amount + else: + if amount > 0: + self.party_data[gle.party].invoiced_amount += amount + elif gle.voucher_no in self.return_invoices: + self.party_data[gle.party].return_amount -= amount + else: + self.party_data[gle.party].paid_amount -= amount + + out = [] + for party, row in iteritems(self.party_data): + if row.opening_balance or row.invoiced_amount or row.paid_amount or row.return_amount or row.closing_amount: + total_party_adjustment = sum([amount for amount in itervalues(self.party_adjustment_details.get(party, {}))]) + row.paid_amount -= total_party_adjustment + row.discount_amount = self.party_adjustment_details.get(party, {}).get(self.discount_account, 0) + row.write_off_amount = self.party_adjustment_details.get(party, {}).get(self.write_off_account, 0) + row.adjustment_amount = total_party_adjustment - row.discount_amount - row.write_off_amount + + out.append(row) + + return out + + def get_gl_entries(self): + conditions = self.prepare_conditions() + join = join_field = "" + if self.filters.party_type == "Customer": + join_field = ", p.customer_name as party_name" + join = "left join `tabCustomer` p on gle.party = p.name" + elif self.filters.party_type == "Supplier": + join_field = ", p.supplier_name as party_name" + join = "left join `tabSupplier` p on gle.party = p.name" + + self.gl_entries = frappe.db.sql(""" + select + gle.posting_date, gle.party, gle.voucher_type, gle.voucher_no, gle.against_voucher_type, + gle.against_voucher, gle.debit, gle.credit {join_field} + from `tabGL Entry` gle + {join} + where + gle.docstatus < 2 and gle.party_type=%(party_type)s and ifnull(gle.party, '') != '' + and gle.posting_date <= %(to_date)s {conditions} + order by gle.posting_date + """.format(join=join, join_field=join_field, conditions=conditions), self.filters, as_dict=True) + + def prepare_conditions(self): + conditions = [""] + + if self.filters.company: + conditions.append("company=%(company)s") + + self.filters.company_finance_book = erpnext.get_default_finance_book(self.filters.company) + + if not self.filters.finance_book or (self.filters.finance_book == self.filters.company_finance_book): + conditions.append("ifnull(finance_book,'') in (%(company_finance_book)s, '')") + elif self.filters.finance_book: + conditions.append("ifnull(finance_book,'') = %(finance_book)s") + + if self.filters.get("party"): + conditions.append("party=%(party)s") + + if self.filters.party_type == "Customer": + if self.filters.get("customer_group"): + lft, rgt = frappe.db.get_value("Customer Group", + self.filters.get("customer_group"), ["lft", "rgt"]) + + conditions.append("""party in (select name from tabCustomer + where exists(select name from `tabCustomer Group` where lft >= {0} and rgt <= {1} + and name=tabCustomer.customer_group))""".format(lft, rgt)) + + if self.filters.get("territory"): + lft, rgt = frappe.db.get_value("Territory", + self.filters.get("territory"), ["lft", "rgt"]) + + conditions.append("""party in (select name from tabCustomer + where exists(select name from `tabTerritory` where lft >= {0} and rgt <= {1} + and name=tabCustomer.territory))""".format(lft, rgt)) + + if self.filters.get("payment_terms_template"): + conditions.append("party in (select name from tabCustomer where payment_terms=%(payment_terms_template)s)") + + if self.filters.get("sales_partner"): + conditions.append("party in (select name from tabCustomer where default_sales_partner=%(sales_partner)s)") + + if self.filters.get("sales_person"): + lft, rgt = frappe.db.get_value("Sales Person", + self.filters.get("sales_person"), ["lft", "rgt"]) + + conditions.append("""exists(select name from `tabSales Team` steam where + steam.sales_person in (select name from `tabSales Person` where lft >= {0} and rgt <= {1}) + and ((steam.parent = voucher_no and steam.parenttype = voucher_type) + or (steam.parent = against_voucher and steam.parenttype = against_voucher_type) + or (steam.parent = party and steam.parenttype = 'Customer')))""".format(lft, rgt)) + + if self.filters.party_type == "Supplier": + if self.filters.get("supplier_group"): + conditions.append("""party in (select name from tabSupplier + where supplier_group=%(supplier_group)s)""") + + return " and ".join(conditions) + + def get_return_invoices(self): + doctype = "Sales Invoice" if self.filters.party_type == "Customer" else "Purchase Invoice" + self.return_invoices = [d.name for d in frappe.get_all(doctype, filters={"is_return": 1, "docstatus": 1, + "posting_date": ["between", [self.filters.from_date, self.filters.to_date]]})] + + def get_party_adjustment_amounts(self): + conditions = self.prepare_conditions() + income_or_expense = "Expense" if self.filters.party_type == "Customer" else "Income" + invoice_dr_or_cr = "debit" if self.filters.party_type == "Customer" else "credit" + reverse_dr_or_cr = "credit" if self.filters.party_type == "Customer" else "debit" + + gl_entries = frappe.db.sql(""" + select + posting_date, account, party, voucher_type, voucher_no, debit, credit + from + `tabGL Entry` + where + docstatus < 2 + and (voucher_type, voucher_no) in ( + select voucher_type, voucher_no from `tabGL Entry` gle, `tabAccount` acc + where acc.name = gle.account and acc.root_type = '{income_or_expense}' + and gle.posting_date between %(from_date)s and %(to_date)s and gle.docstatus < 2 + ) and (voucher_type, voucher_no) in ( + select voucher_type, voucher_no from `tabGL Entry` gle + where gle.party_type=%(party_type)s and ifnull(party, '') != '' + and gle.posting_date between %(from_date)s and %(to_date)s and gle.docstatus < 2 {conditions} + ) + """.format(conditions=conditions, income_or_expense=income_or_expense), self.filters, as_dict=True) + + self.party_adjustment_details = {} + adjustment_voucher_entries = {} + for gle in gl_entries: + adjustment_voucher_entries.setdefault((gle.voucher_type, gle.voucher_no), []) + adjustment_voucher_entries[(gle.voucher_type, gle.voucher_no)].append(gle) + + for voucher_gl_entries in itervalues(adjustment_voucher_entries): + parties = {} + accounts = {} + has_irrelevant_entry = False + + for gle in voucher_gl_entries: + if gle.account == self.round_off_account: + continue + elif gle.party: + parties.setdefault(gle.party, 0) + parties[gle.party] += gle.get(reverse_dr_or_cr) - gle.get(invoice_dr_or_cr) + elif frappe.get_cached_value("Account", gle.account, "root_type") == income_or_expense: + accounts.setdefault(gle.account, 0) + accounts[gle.account] += gle.get(invoice_dr_or_cr) - gle.get(reverse_dr_or_cr) + else: + has_irrelevant_entry = True + + if parties and accounts: + if len(parties) == 1: + party = parties.keys()[0] + for account, amount in iteritems(accounts): + self.party_adjustment_details.setdefault(party, {}) + self.party_adjustment_details[party].setdefault(account, 0) + self.party_adjustment_details[party][account] += amount + elif len(accounts) == 1 and not has_irrelevant_entry: + account = accounts.keys()[0] + for party, amount in iteritems(parties): + self.party_adjustment_details.setdefault(party, {}) + self.party_adjustment_details[party].setdefault(account, 0) + self.party_adjustment_details[party][account] += amount + +def execute(filters=None): + args = { + "party_type": "Customer", + "naming_by": ["Selling Settings", "cust_master_name"], + } + return PartyLedgerSummaryReport(filters).run(args) diff --git a/erpnext/accounts/report/supplier_ledger_summary/__init__.py b/erpnext/accounts/report/supplier_ledger_summary/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/erpnext/accounts/report/supplier_ledger_summary/supplier_ledger_summary.js b/erpnext/accounts/report/supplier_ledger_summary/supplier_ledger_summary.js new file mode 100644 index 00000000000..6fd16f20908 --- /dev/null +++ b/erpnext/accounts/report/supplier_ledger_summary/supplier_ledger_summary.js @@ -0,0 +1,97 @@ +// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt +/* eslint-disable */ + +frappe.query_reports["Supplier Ledger Summary"] = { + "filters": [ + { + "fieldname":"company", + "label": __("Company"), + "fieldtype": "Link", + "options": "Company", + "default": frappe.defaults.get_user_default("Company") + }, + { + "fieldname":"from_date", + "label": __("From Date"), + "fieldtype": "Date", + "default": frappe.datetime.add_months(frappe.datetime.get_today(), -1), + "reqd": 1, + "width": "60px" + }, + { + "fieldname":"to_date", + "label": __("To Date"), + "fieldtype": "Date", + "default": frappe.datetime.get_today(), + "reqd": 1, + "width": "60px" + }, + { + "fieldname":"finance_book", + "label": __("Finance Book"), + "fieldtype": "Link", + "options": "Finance Book" + }, + { + "fieldname":"party", + "label": __("Customer"), + "fieldtype": "Link", + "options": "Customer", + on_change: () => { + var party = frappe.query_report.get_filter_value('party'); + if (party) { + frappe.db.get_value('Supplier', party, ["tax_id", "supplier_name"], function(value) { + frappe.query_report.set_filter_value('tax_id', value["tax_id"]); + frappe.query_report.set_filter_value('supplier_name', value["supplier_name"]); + }); + } else { + frappe.query_report.set_filter_value('tax_id', ""); + frappe.query_report.set_filter_value('supplier_name', ""); + } + } + }, + { + "fieldname":"supplier_group", + "label": __("Supplier Group"), + "fieldtype": "Link", + "options": "Supplier Group" + }, + { + "fieldname":"payment_terms_template", + "label": __("Payment Terms Template"), + "fieldtype": "Link", + "options": "Payment Terms Template" + }, + { + "fieldname":"territory", + "label": __("Territory"), + "fieldtype": "Link", + "options": "Territory" + }, + { + "fieldname":"sales_partner", + "label": __("Sales Partner"), + "fieldtype": "Link", + "options": "Sales Partner" + }, + { + "fieldname":"sales_person", + "label": __("Sales Person"), + "fieldtype": "Link", + "options": "Sales Person" + }, + { + "fieldname":"tax_id", + "label": __("Tax Id"), + "fieldtype": "Data", + "hidden": 1 + }, + { + "fieldname":"supplier_name", + "label": __("Supplier Name"), + "fieldtype": "Data", + "hidden": 1 + } + ] +}; diff --git a/erpnext/accounts/report/supplier_ledger_summary/supplier_ledger_summary.json b/erpnext/accounts/report/supplier_ledger_summary/supplier_ledger_summary.json new file mode 100644 index 00000000000..eb3b4123e23 --- /dev/null +++ b/erpnext/accounts/report/supplier_ledger_summary/supplier_ledger_summary.json @@ -0,0 +1,27 @@ +{ + "add_total_row": 1, + "creation": "2018-12-12 05:10:02.987274", + "disabled": 0, + "docstatus": 0, + "doctype": "Report", + "idx": 0, + "is_standard": "Yes", + "letter_head": "Capital Traders", + "modified": "2018-12-12 05:10:02.987274", + "modified_by": "Administrator", + "module": "Accounts", + "name": "Supplier Ledger Summary", + "owner": "Administrator", + "prepared_report": 0, + "ref_doctype": "Purchase Invoice", + "report_name": "Supplier Ledger Summary", + "report_type": "Script Report", + "roles": [ + { + "role": "Accounts Manager" + }, + { + "role": "Accounts User" + } + ] +} \ No newline at end of file diff --git a/erpnext/accounts/report/supplier_ledger_summary/supplier_ledger_summary.py b/erpnext/accounts/report/supplier_ledger_summary/supplier_ledger_summary.py new file mode 100644 index 00000000000..d2c23ee4e78 --- /dev/null +++ b/erpnext/accounts/report/supplier_ledger_summary/supplier_ledger_summary.py @@ -0,0 +1,13 @@ +# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +from __future__ import unicode_literals +import frappe +from erpnext.accounts.report.customer_ledger_summary.customer_ledger_summary import PartyLedgerSummaryReport + +def execute(filters=None): + args = { + "party_type": "Supplier", + "naming_by": ["Buying Settings", "supp_master_name"], + } + return PartyLedgerSummaryReport(filters).run(args) \ No newline at end of file diff --git a/erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py b/erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py index 3869d685a18..2e805f8d3f5 100644 --- a/erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py +++ b/erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py @@ -9,7 +9,9 @@ from erpnext.accounts.doctype.tax_withholding_category.tax_withholding_category def execute(filters=None): validate_filters(filters) - columns = get_columns() + filters.naming_series = frappe.db.get_single_value('Buying Settings', 'supp_master_name') + + columns = get_columns(filters) res = get_result(filters) return columns, res @@ -30,7 +32,8 @@ def get_result(filters): # if no supplier selected, fetch data for all tds applicable supplier # else fetch relevant data for selected supplier pan = "pan" if frappe.db.has_column("Supplier", "pan") else "tax_id" - fields = ["name", pan+" as pan", "tax_withholding_category", "supplier_type"] + fields = ["name", pan+" as pan", "tax_withholding_category", "supplier_type", "supplier_name"] + if filters.supplier: filters.supplier = frappe.db.get_list('Supplier', {"name": filters.supplier}, fields) @@ -50,8 +53,13 @@ def get_result(filters): filters.company, filters.from_date, filters.to_date) if total_invoiced_amount or tds_deducted: - out.append([supplier.pan, supplier.name, tds.name, supplier.supplier_type, - rate, total_invoiced_amount, tds_deducted]) + row = [supplier.pan, supplier.name] + + if filters.naming_series == 'Naming Series': + row.append(supplier.supplier_name) + + row.extend([tds.name, supplier.supplier_type, rate, total_invoiced_amount, tds_deducted]) + out.append(row) return out @@ -87,7 +95,7 @@ def get_invoice_and_tds_amount(supplier, account, company, from_date, to_date): return total_invoiced_amount, tds_deducted -def get_columns(): +def get_columns(filters): columns = [ { "label": _("PAN"), @@ -101,7 +109,17 @@ def get_columns(): "fieldname": "supplier", "fieldtype": "Link", "width": 180 - }, + }] + + if filters.naming_series == 'Naming Series': + columns.append({ + "label": _("Supplier Name"), + "fieldname": "supplier_name", + "fieldtype": "Data", + "width": 180 + }) + + columns.extend([ { "label": _("Section Code"), "options": "Tax Withholding Category", @@ -133,6 +151,6 @@ def get_columns(): "fieldtype": "Float", "width": 90 } - ] + ]) return columns diff --git a/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py b/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py index 843b58f4486..e55c022452d 100644 --- a/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py +++ b/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py @@ -11,7 +11,7 @@ def execute(filters=None): validate_filters(filters) set_filters(filters) - columns = get_columns() + columns = get_columns(filters) if not filters["invoices"]: return columns, [] @@ -43,6 +43,7 @@ def set_filters(filters): invoices.append(d) filters["invoices"] = invoices if invoices else filters["invoices"] + filters.naming_series = frappe.db.get_single_value('Buying Settings', 'supp_master_name') def get_result(filters): supplier_map, tds_docs = get_supplier_map(filters) @@ -71,9 +72,14 @@ def get_result(filters): if getdate(filters.from_date) <= gle_map[d][0].posting_date \ and getdate(filters.to_date) >= gle_map[d][0].posting_date: - out.append([supplier.pan, supplier.name, tds_doc.name, - supplier.supplier_type, rate, total_amount_credited, tds_deducted, - gle_map[d][0].posting_date, "Purchase Invoice", d]) + row = [supplier.pan, supplier.name] + + if filters.naming_series == 'Naming Series': + row.append(supplier.supplier_name) + + row.extend([tds_doc.name, supplier.supplier_type, rate, total_amount_credited, + tds_deducted, gle_map[d][0].posting_date, "Purchase Invoice", d]) + out.append(row) return out @@ -84,7 +90,7 @@ def get_supplier_map(filters): pan = "pan" if frappe.db.has_column("Supplier", "pan") else "tax_id" supplier_detail = frappe.db.get_all('Supplier', {"name": ["in", [d.supplier for d in filters["invoices"]]]}, - ["tax_withholding_category", "name", pan+" as pan", "supplier_type"]) + ["tax_withholding_category", "name", pan+" as pan", "supplier_type", "supplier_name"]) for d in filters["invoices"]: supplier_map[d.get("name")] = [k for k in supplier_detail @@ -113,7 +119,7 @@ def get_gle_map(filters): return gle_map -def get_columns(): +def get_columns(filters): pan = "pan" if frappe.db.has_column("Supplier", "pan") else "tax_id" columns = [ { @@ -128,7 +134,17 @@ def get_columns(): "fieldname": "supplier", "fieldtype": "Link", "width": 180 - }, + }] + + if filters.naming_series == 'Naming Series': + columns.append({ + "label": _("Supplier Name"), + "fieldname": "supplier_name", + "fieldtype": "Data", + "width": 180 + }) + + columns.extend([ { "label": _("Section Code"), "options": "Tax Withholding Category", @@ -178,7 +194,7 @@ def get_columns(): "options": "transaction_type", "width": 90 } - ] + ]) return columns diff --git a/erpnext/accounts/report/trial_balance/trial_balance.js b/erpnext/accounts/report/trial_balance/trial_balance.js index c09fa715753..cdc77456d0a 100644 --- a/erpnext/accounts/report/trial_balance/trial_balance.js +++ b/erpnext/accounts/report/trial_balance/trial_balance.js @@ -12,21 +12,6 @@ frappe.require("assets/erpnext/js/financial_statements.js", function() { "default": frappe.defaults.get_user_default("Company"), "reqd": 1 }, - { - "fieldname":"cost_center", - "label": __("Cost Center"), - "fieldtype": "Link", - "options": "Cost Center", - "get_query": function() { - var company = frappe.query_report.get_filter_value('company'); - return { - "doctype": "Cost Center", - "filters": { - "company": company, - } - } - } - }, { "fieldname": "fiscal_year", "label": __("Fiscal Year"), @@ -60,6 +45,27 @@ frappe.require("assets/erpnext/js/financial_statements.js", function() { "fieldtype": "Date", "default": frappe.defaults.get_user_default("year_end_date"), }, + { + "fieldname":"cost_center", + "label": __("Cost Center"), + "fieldtype": "Link", + "options": "Cost Center", + "get_query": function() { + var company = frappe.query_report.get_filter_value('company'); + return { + "doctype": "Cost Center", + "filters": { + "company": company, + } + } + } + }, + { + "fieldname":"finance_book", + "label": __("Finance Book"), + "fieldtype": "Link", + "options": "Finance Book", + }, { "fieldname": "with_period_closing_entry", "label": __("Period Closing Entry"), @@ -75,6 +81,11 @@ frappe.require("assets/erpnext/js/financial_statements.js", function() { "fieldname": "show_unclosed_fy_pl_balances", "label": __("Show unclosed fiscal year's P&L balances"), "fieldtype": "Check" + }, + { + "fieldname": "include_default_book_entries", + "label": __("Include Default Book Entries"), + "fieldtype": "Check" } ], "formatter": erpnext.financial_statements.formatter, diff --git a/erpnext/accounts/report/trial_balance/trial_balance.py b/erpnext/accounts/report/trial_balance/trial_balance.py index 07dcd4e7a94..6b18c5d8731 100644 --- a/erpnext/accounts/report/trial_balance/trial_balance.py +++ b/erpnext/accounts/report/trial_balance/trial_balance.py @@ -67,11 +67,10 @@ def get_data(filters): gl_entries_by_account = {} + opening_balances = get_opening_balances(filters) set_gl_entries_by_account(filters.company, filters.from_date, filters.to_date, min_lft, max_rgt, filters, gl_entries_by_account, ignore_closing_entries=not flt(filters.with_period_closing_entry)) - opening_balances = get_opening_balances(filters) - total_row = calculate_values(accounts, gl_entries_by_account, opening_balances, filters, company_currency) accumulate_values_into_parents(accounts, accounts_by_name) @@ -98,6 +97,18 @@ def get_rootwise_opening_balances(filters, report_type): if not flt(filters.with_period_closing_entry): additional_conditions += " and ifnull(voucher_type, '')!='Period Closing Voucher'" + if filters.cost_center: + lft, rgt = frappe.db.get_value('Cost Center', filters.cost_center, ['lft', 'rgt']) + additional_conditions += """ and cost_center in (select name from `tabCost Center` + where lft >= %s and rgt <= %s)""" % (lft, rgt) + + if filters.finance_book: + 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) or finance_book is null)" + + additional_conditions += fb_conditions + gle = frappe.db.sql(""" select account, sum(debit) as opening_debit, sum(credit) as opening_credit @@ -112,7 +123,9 @@ def get_rootwise_opening_balances(filters, report_type): "company": filters.company, "from_date": filters.from_date, "report_type": report_type, - "year_start_date": filters.year_start_date + "year_start_date": filters.year_start_date, + "finance_book": filters.finance_book, + "company_fb": frappe.db.get_value("Company", filters.company, 'default_finance_book') }, as_dict=True) diff --git a/erpnext/accounts/report/trial_balance_simple/__init__.py b/erpnext/accounts/report/trial_balance_simple/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/erpnext/accounts/report/trial_balance_simple/trial_balance_simple.json b/erpnext/accounts/report/trial_balance_simple/trial_balance_simple.json index ea5a97b1067..fab3a76a0c4 100644 --- a/erpnext/accounts/report/trial_balance_simple/trial_balance_simple.json +++ b/erpnext/accounts/report/trial_balance_simple/trial_balance_simple.json @@ -6,13 +6,13 @@ "doctype": "Report", "idx": 0, "is_standard": "Yes", - "modified": "2018-11-22 17:40:11.317567", + "modified": "2019-01-17 17:20:42.374958", "modified_by": "Administrator", "module": "Accounts", "name": "Trial Balance (Simple)", "owner": "Administrator", "prepared_report": 0, - "query": "select fiscal_year as \"Fiscal Year:Data:80\",\n\tcompany as \"Company:Data:220\",\n\tposting_date as \"Posting Date:Date:100\",\n\taccount as \"Account:Data:380\",\n\tsum(debit) as \"Debit:Currency:140\",\n\tsum(credit) as \"Credit:Currency:140\"\nfrom `tabGL Entry`\ngroup by fiscal_year, company, posting_date, account\norder by fiscal_year, company, posting_date, account", + "query": "select fiscal_year as \"Fiscal Year:Data:80\",\n\tcompany as \"Company:Data:220\",\n\tposting_date as \"Posting Date:Date:100\",\n\taccount as \"Account:Data:380\",\n\tsum(debit) as \"Debit:Currency:140\",\n\tsum(credit) as \"Credit:Currency:140\",\n\tfinance_book as \"Finance Book:Link/Finance Book:140\"\nfrom `tabGL Entry`\ngroup by fiscal_year, company, posting_date, account\norder by fiscal_year, company, posting_date, account", "ref_doctype": "GL Entry", "report_name": "Trial Balance (Simple)", "report_type": "Query Report", diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py index 6fbe97de3e1..e145a35b17f 100644 --- a/erpnext/accounts/utils.py +++ b/erpnext/accounts/utils.py @@ -615,7 +615,7 @@ def get_held_invoices(party_type, party): return held_invoices -def get_outstanding_invoices(party_type, party, account, condition=None): +def get_outstanding_invoices(party_type, party, account, condition=None, limit=1000): outstanding_invoices = [] precision = frappe.get_precision("Sales Invoice", "outstanding_amount") @@ -628,6 +628,7 @@ def get_outstanding_invoices(party_type, party, account, condition=None): invoice = 'Sales Invoice' if erpnext.get_party_account_type(party_type) == 'Receivable' else 'Purchase Invoice' held_invoices = get_held_invoices(party_type, party) + limit_cond = "limit %s" % (limit or 1000) invoice_list = frappe.db.sql(""" select @@ -655,11 +656,12 @@ def get_outstanding_invoices(party_type, party, account, condition=None): or (voucher_type not in ('Journal Entry', 'Payment Entry'))) group by voucher_type, voucher_no having (invoice_amount - payment_amount) > 0.005 - order by posting_date, name""".format( + order by posting_date, name {limit_cond}""".format( dr_or_cr=dr_or_cr, invoice = invoice, payment_dr_or_cr=payment_dr_or_cr, - condition=condition or "" + condition=condition or "", + limit_cond = limit_cond ), { "party_type": party_type, "party": party, diff --git a/erpnext/buying/doctype/supplier/supplier.json b/erpnext/buying/doctype/supplier/supplier.json index 3b1f4e0dfcc..4586c647155 100644 --- a/erpnext/buying/doctype/supplier/supplier.json +++ b/erpnext/buying/doctype/supplier/supplier.json @@ -149,6 +149,39 @@ "translatable": 0, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "default_bank_account", + "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": "Default 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, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, { "allow_bulk_edit": 0, "allow_in_quick_entry": 0, @@ -1463,7 +1496,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2019-01-07 16:52:04.660271", + "modified": "2019-01-17 13:58:08.597792", "modified_by": "Administrator", "module": "Buying", "name": "Supplier", diff --git a/erpnext/config/accounts.py b/erpnext/config/accounts.py index 9d8e1bf3c34..42d0df0a06f 100644 --- a/erpnext/config/accounts.py +++ b/erpnext/config/accounts.py @@ -351,6 +351,36 @@ def get_data(): "is_query_report": True, "doctype": "Sales Invoice" }, + { + "type": "report", + "name": "Item-wise Sales Register", + "is_query_report": True, + "doctype": "Sales Invoice" + }, + { + "type": "report", + "name": "Item-wise Purchase Register", + "is_query_report": True, + "doctype": "Purchase Invoice" + }, + { + "type": "report", + "name": "Profitability Analysis", + "doctype": "GL Entry", + "is_query_report": True, + }, + { + "type": "report", + "name": "Customer Ledger Summary", + "doctype": "Sales Invoice", + "is_query_report": True, + }, + { + "type": "report", + "name": "Supplier Ledger Summary", + "doctype": "Sales Invoice", + "is_query_report": True, + } ] }, { @@ -363,12 +393,6 @@ def get_data(): "doctype": "GL Entry", "is_query_report": True, }, - { - "type": "report", - "name": "Profitability Analysis", - "doctype": "GL Entry", - "is_query_report": True, - }, { "type": "report", "name": "Payment Period Based On Invoice Date", @@ -381,18 +405,6 @@ def get_data(): "is_query_report": True, "doctype": "Sales Invoice" }, - { - "type": "report", - "name": "Item-wise Sales Register", - "is_query_report": True, - "doctype": "Sales Invoice" - }, - { - "type": "report", - "name": "Item-wise Purchase Register", - "is_query_report": True, - "doctype": "Purchase Invoice" - }, { "type": "report", "name": "Accounts Receivable Summary", diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index cd373b84d7e..197b9554f8a 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -248,7 +248,6 @@ class AccountsController(TransactionBase): if self.get("is_subcontracted"): args["is_subcontracted"] = self.is_subcontracted ret = get_item_details(args) - for fieldname, value in ret.items(): if item.meta.get_field(fieldname) and value is not None: if (item.get(fieldname) is None or fieldname in force_item_fields): @@ -267,9 +266,10 @@ class AccountsController(TransactionBase): if ret.get("pricing_rule"): # if user changed the discount percentage then set user's discount percentage ? + item.set("pricing_rule", ret.get("pricing_rule")) item.set("discount_percentage", ret.get("discount_percentage")) - if ret.get("pricing_rule_for") == "Price": - item.set("pricing_list_rate", ret.get("pricing_list_rate")) + if ret.get("pricing_rule_for") == "Rate": + item.set("price_list_rate", ret.get("price_list_rate")) if item.price_list_rate: item.rate = flt(item.price_list_rate * @@ -953,11 +953,12 @@ def get_advance_journal_entries(party_type, party, party_account, amount_field, return list(journal_entries) -def get_advance_payment_entries(party_type, party, party_account, - order_doctype, order_list=None, include_unallocated=True, against_all_orders=False): +def get_advance_payment_entries(party_type, party, party_account, order_doctype, + order_list=None, include_unallocated=True, against_all_orders=False, limit=1000): party_account_field = "paid_from" if party_type == "Customer" else "paid_to" payment_type = "Receive" if party_type == "Customer" else "Pay" payment_entries_against_order, unallocated_payment_entries = [], [] + limit_cond = "limit %s" % (limit or 1000) if order_list or against_all_orders: if order_list: @@ -977,8 +978,8 @@ def get_advance_payment_entries(party_type, party, party_account, t1.name = t2.parent and t1.{0} = %s and t1.payment_type = %s and t1.party_type = %s and t1.party = %s and t1.docstatus = 1 and t2.reference_doctype = %s {1} - order by t1.posting_date - """.format(party_account_field, reference_condition), + order by t1.posting_date {2} + """.format(party_account_field, reference_condition, limit_cond), [party_account, payment_type, party_type, party, order_doctype] + order_list, as_dict=1) @@ -990,8 +991,8 @@ def get_advance_payment_entries(party_type, party, party_account, where {0} = %s and party_type = %s and party = %s and payment_type = %s and docstatus = 1 and unallocated_amount > 0 - order by posting_date - """.format(party_account_field), (party_account, party_type, party, payment_type), as_dict=1) + order by posting_date {1} + """.format(party_account_field, limit_cond), (party_account, party_type, party, payment_type), as_dict=1) return list(payment_entries_against_order) + list(unallocated_payment_entries) diff --git a/erpnext/controllers/item_variant.py b/erpnext/controllers/item_variant.py index 24726ad03b1..646f23879a9 100644 --- a/erpnext/controllers/item_variant.py +++ b/erpnext/controllers/item_variant.py @@ -260,8 +260,6 @@ def generate_keyed_value_combinations(args): return results def copy_attributes_to_variant(item, variant): - from frappe.model import no_value_fields - # copy non no-copy fields exclude_fields = ["naming_series", "item_code", "item_name", "show_in_website", diff --git a/erpnext/controllers/selling_controller.py b/erpnext/controllers/selling_controller.py index 684a2cdbcbe..a9883017cfa 100644 --- a/erpnext/controllers/selling_controller.py +++ b/erpnext/controllers/selling_controller.py @@ -8,7 +8,7 @@ from frappe import _, throw from erpnext.stock.get_item_details import get_bin_details from erpnext.stock.utils import get_incoming_rate from erpnext.stock.get_item_details import get_conversion_factor -from erpnext.stock.doctype.item.item import get_item_defaults, set_item_default +from erpnext.stock.doctype.item.item import set_item_default from frappe.contacts.doctype.address.address import get_address_display from erpnext.controllers.stock_controller import StockController diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py index 0b19b7aaf9a..0a3cd3499b1 100644 --- a/erpnext/controllers/stock_controller.py +++ b/erpnext/controllers/stock_controller.py @@ -4,7 +4,7 @@ from __future__ import unicode_literals import frappe, erpnext from frappe.utils import cint, flt, cstr -from frappe import msgprint, _ +from frappe import _ import frappe.defaults from erpnext.accounts.utils import get_fiscal_year from erpnext.accounts.general_ledger import make_gl_entries, delete_gl_entries, process_gl_map diff --git a/erpnext/crm/doctype/lead/.py b/erpnext/crm/doctype/lead/.py deleted file mode 100644 index 70a6b22a99f..00000000000 --- a/erpnext/crm/doctype/lead/.py +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors and contributors -# For license information, please see license.txt - -from __future__ import unicode_literals -import frappe -from frappe.model.document import Document - -class Lead(Document): - pass diff --git a/erpnext/hooks.py b/erpnext/hooks.py index bbadd7f150f..3c3750a4fbb 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -12,7 +12,7 @@ app_license = "GNU General Public License (v3)" source_link = "https://github.com/frappe/erpnext" develop_version = '12.x.x-develop' -staging_version = '11.0.3-beta.35' +staging_version = '11.0.3-beta.37' error_report_email = "support@erpnext.com" diff --git a/erpnext/hub_node/api.py b/erpnext/hub_node/api.py index c236822490d..0c94df31596 100644 --- a/erpnext/hub_node/api.py +++ b/erpnext/hub_node/api.py @@ -2,10 +2,6 @@ from __future__ import unicode_literals import frappe import json -import io -import base64 -import os -import requests from frappe import _ from frappe.frappeclient import FrappeClient diff --git a/erpnext/manufacturing/doctype/work_order/.py b/erpnext/manufacturing/doctype/work_order/.py deleted file mode 100644 index 4476b16dbc9..00000000000 --- a/erpnext/manufacturing/doctype/work_order/.py +++ /dev/null @@ -1,8 +0,0 @@ -import frappe - -def set_required_items(production_order): - pass - -def reserve_for_production(production_order): - '''Reserve pending raw materials for production''' - pass \ No newline at end of file diff --git a/erpnext/projects/doctype/project/project.py b/erpnext/projects/doctype/project/project.py index 9654ca345eb..dcf485a8030 100644 --- a/erpnext/projects/doctype/project/project.py +++ b/erpnext/projects/doctype/project/project.py @@ -162,7 +162,7 @@ class Project(Document): def is_row_updated(self, row, existing_task_data, fields): if self.get("__islocal") or not existing_task_data: return True - d = existing_task_data.get(row.task_id) + d = existing_task_data.get(row.task_id, {}) for field in fields: if row.get(field) != d.get(field): diff --git a/erpnext/regional/india/utils.py b/erpnext/regional/india/utils.py index fd9ac4c81b3..e7d0d5052ec 100644 --- a/erpnext/regional/india/utils.py +++ b/erpnext/regional/india/utils.py @@ -9,7 +9,7 @@ from erpnext.hr.utils import get_salary_assignment from erpnext.hr.doctype.salary_structure.salary_structure import make_salary_slip def validate_gstin_for_india(doc, method): - if not hasattr(doc, 'gstin'): + if not hasattr(doc, 'gstin') or not doc.gstin: return doc.gstin = doc.gstin.upper().strip() if doc.gstin else "" diff --git a/erpnext/regional/report/eway_bill/eway_bill.py b/erpnext/regional/report/eway_bill/eway_bill.py index 1b5de274c58..5b9896be2a1 100644 --- a/erpnext/regional/report/eway_bill/eway_bill.py +++ b/erpnext/regional/report/eway_bill/eway_bill.py @@ -16,7 +16,7 @@ def execute(filters=None): return columns, data def get_data(filters): - + conditions = get_conditions(filters) data = frappe.db.sql(""" @@ -25,7 +25,7 @@ def get_data(filters): FROM `tabDelivery Note` AS dn join `tabDelivery Note Item` AS dni on (dni.parent = dn.name) WHERE - dn.docstatus < 2 + dn.docstatus < 2 %s """ % conditions, as_dict=1) unit = { @@ -40,14 +40,14 @@ def get_data(filters): 'Set': "SETS" } - # Regular expression set to remove all the special characters + # Regular expression set to remove all the special characters special_characters = "[$%^*()+\\[\]{};':\"\\|<>.?]" for row in data: set_defaults(row) set_taxes(row, filters) set_address_details(row, special_characters) - + # Eway Bill accepts date as dd/mm/yyyy and not dd-mm-yyyy row.posting_date = '/'.join(str(row.posting_date).replace("-", "/").split('/')[::-1]) row.lr_date = '/'.join(str(row.lr_date).replace("-", "/").split('/')[::-1]) @@ -66,7 +66,7 @@ def get_data(filters): return data def get_conditions(filters): - + conditions = "" conditions += filters.get('company') and " AND dn.company = '%s' " % filters.get('company') or "" @@ -92,7 +92,7 @@ def set_address_details(row, special_characters): row.update({'from_pin_code': pincode and pincode.replace(" ", "") or ''}) row.update({'from_state': state and state.upper() or ''}) row.update({'dispatch_state': row.from_state}) - + if row.get('shipping_address_name'): address_line1, address_line2, city, pincode, state = frappe.db.get_value("Address", row.get('shipping_address_name'), ['address_line1', 'address_line2', 'city', 'pincode', 'state']) @@ -104,20 +104,23 @@ def set_address_details(row, special_characters): row.update({'ship_to_state': row.to_state}) def set_taxes(row, filters): - taxes = frappe.get_list("Sales Taxes and Charges", + taxes = frappe.get_list("Sales Taxes and Charges", filters={ 'parent': row.dn_id - }, + }, fields=('item_wise_tax_detail', 'account_head')) account_list = ["cgst_account", "sgst_account", "igst_account", "cess_account"] taxes_list = frappe.get_list("GST Account", filters={ - "parent": "GST Settings", + "parent": "GST Settings", "company": filters.company }, fields=account_list) + if not taxes_list: + frappe.throw(_("Please set GST Accounts in GST Settings")) + item_tax_rate = {} for tax in taxes: diff --git a/erpnext/selling/doctype/customer/customer.json b/erpnext/selling/doctype/customer/customer.json index 608c0e950ed..a82042f4a16 100644 --- a/erpnext/selling/doctype/customer/customer.json +++ b/erpnext/selling/doctype/customer/customer.json @@ -217,6 +217,39 @@ "translatable": 0, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "default_bank_account", + "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": "Default 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, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, { "allow_bulk_edit": 0, "allow_in_quick_entry": 0, @@ -1873,7 +1906,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2018-10-01 10:07:34.510264", + "modified": "2019-01-17 13:10:24.360875", "modified_by": "Administrator", "module": "Selling", "name": "Customer", diff --git a/erpnext/setup/doctype/company/company.js b/erpnext/setup/doctype/company/company.js index 16676ac78af..70e047a4e80 100644 --- a/erpnext/setup/doctype/company/company.js +++ b/erpnext/setup/doctype/company/company.js @@ -206,6 +206,8 @@ erpnext.company.setup_queries = function(frm) { ["default_payroll_payable_account", {"root_type": "Liability"}], ["round_off_account", {"root_type": "Expense"}], ["write_off_account", {"root_type": "Expense"}], + ["discount_allowed_account", {"root_type": "Expense"}], + ["discount_received_account", {"root_type": "Income"}], ["exchange_gain_loss_account", {"root_type": "Expense"}], ["unrealized_exchange_gain_loss_account", {"root_type": "Expense"}], ["accumulated_depreciation_account", diff --git a/erpnext/setup/doctype/company/company.json b/erpnext/setup/doctype/company/company.json index 01f8956a826..77c371e0cdd 100644 --- a/erpnext/setup/doctype/company/company.json +++ b/erpnext/setup/doctype/company/company.json @@ -1250,6 +1250,72 @@ "translatable": 0, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "discount_allowed_account", + "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": "Discount Allowed Account", + "length": 0, + "no_copy": 0, + "options": "Account", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "discount_received_account", + "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": "Discount Received Account", + "length": 0, + "no_copy": 0, + "options": "Account", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, { "allow_bulk_edit": 0, "allow_in_quick_entry": 0, @@ -2903,7 +2969,7 @@ "istable": 0, "max_attachments": 0, "menu_index": 0, - "modified": "2018-10-24 12:57:46.776452", + "modified": "2019-01-15 13:29:54.510379", "modified_by": "Administrator", "module": "Setup", "name": "Company", diff --git a/erpnext/setup/utils.py b/erpnext/setup/utils.py index 0216c3ba69a..01e0b7d441a 100644 --- a/erpnext/setup/utils.py +++ b/erpnext/setup/utils.py @@ -109,6 +109,7 @@ def get_exchange_rate(from_currency, to_currency, transaction_date=None, args=No cache.setex(key, value, 6 * 60 * 60) return flt(value) except: + frappe.log_error(title="Get Exchange Rate") frappe.msgprint(_("Unable to find exchange rate for {0} to {1} for key date {2}. Please create a Currency Exchange record manually").format(from_currency, to_currency, transaction_date)) return 0.0 diff --git a/erpnext/shopping_cart/product_info.py b/erpnext/shopping_cart/product_info.py index b5f129b4aa2..3af5afa0442 100644 --- a/erpnext/shopping_cart/product_info.py +++ b/erpnext/shopping_cart/product_info.py @@ -6,7 +6,7 @@ from __future__ import unicode_literals import frappe from erpnext.shopping_cart.cart import _get_cart_quotation from erpnext.shopping_cart.doctype.shopping_cart_settings.shopping_cart_settings \ - import is_cart_enabled, get_shopping_cart_settings, show_quantity_in_website + import get_shopping_cart_settings, show_quantity_in_website from erpnext.utilities.product import get_price, get_qty_in_stock @frappe.whitelist(allow_guest=True) diff --git a/erpnext/startup/__init__.py b/erpnext/startup/__init__.py index b65fc0f10e4..deef4ba4d68 100644 --- a/erpnext/startup/__init__.py +++ b/erpnext/startup/__init__.py @@ -19,7 +19,6 @@ # default settings that can be made for a user. from __future__ import unicode_literals -import frappe product_name = "ERPNext" user_defaults = { diff --git a/erpnext/stock/dashboard/item_dashboard.py b/erpnext/stock/dashboard/item_dashboard.py index f95daafd384..d817e5ff2d9 100644 --- a/erpnext/stock/dashboard/item_dashboard.py +++ b/erpnext/stock/dashboard/item_dashboard.py @@ -1,43 +1,37 @@ from __future__ import unicode_literals import frappe +from frappe.model.db_query import DatabaseQuery @frappe.whitelist() def get_data(item_code=None, warehouse=None, item_group=None, start=0, sort_by='actual_qty', sort_order='desc'): '''Return data to render the item dashboard''' - conditions = [] - values = [] + filters = [] if item_code: - conditions.append('b.item_code=%s') - values.append(item_code) + filters.append(['item_code', '=', item_code]) if warehouse: - conditions.append('b.warehouse=%s') - values.append(warehouse) + filters.append(['warehouse', '=', warehouse]) if item_group: - conditions.append('i.item_group=%s') - values.append(item_group) + filters.append(['item_group', '=', item_group]) + try: + # check if user has any restrictions based on user permissions on warehouse + if DatabaseQuery('Warehouse', user=frappe.session.user).build_match_conditions(): + filters.append(['warehouse', 'in', [w.name for w in frappe.get_list('Warehouse')]]) + except frappe.PermissionError: + # user does not have access on warehouse + return [] - if conditions: - conditions = ' and ' + ' and '.join(conditions) - else: - conditions = '' - - return frappe.db.sql(''' - select - b.item_code, b.warehouse, b.projected_qty, b.reserved_qty, - b.reserved_qty_for_production, b.reserved_qty_for_sub_contract, b.actual_qty, b.valuation_rate, i.item_name - from - tabBin b, tabItem i - where - b.item_code = i.name - and - (b.projected_qty != 0 or b.reserved_qty != 0 or b.reserved_qty_for_production != 0 - or b.reserved_qty_for_sub_contract != 0 or b.actual_qty != 0) - {conditions} - order by - {sort_by} {sort_order} - limit - {start}, 21 - '''.format(conditions=conditions, sort_by=sort_by, sort_order=sort_order, - start=start), values, as_dict=True) + return frappe.db.get_all('Bin', fields=['item_code', 'warehouse', 'projected_qty', + 'reserved_qty', 'reserved_qty_for_production', 'reserved_qty_for_sub_contract', 'actual_qty', 'valuation_rate'], + or_filters={ + 'projected_qty': ['!=', 0], + 'reserved_qty': ['!=', 0], + 'reserved_qty_for_production': ['!=', 0], + 'reserved_qty_for_sub_contract': ['!=', 0], + 'actual_qty': ['!=', 0], + }, + filters=filters, + order_by=sort_by + ' ' + sort_order, + limit_start=start, + limit_page_length='21') diff --git a/erpnext/stock/stock_balance.py b/erpnext/stock/stock_balance.py index 09d4e438406..045bee52d92 100644 --- a/erpnext/stock/stock_balance.py +++ b/erpnext/stock/stock_balance.py @@ -257,7 +257,7 @@ def repost_all_stock_vouchers(): doc.update_stock_ledger() doc.make_gl_entries(repost_future_gle=False) frappe.db.commit() - except Exception as e: + except Exception: print(frappe.get_traceback()) rejected.append([voucher_type, voucher_no]) frappe.db.rollback() diff --git a/erpnext/templates/includes/cart/cart_items.html b/erpnext/templates/includes/cart/cart_items.html index b2e68585a70..65b81d93209 100644 --- a/erpnext/templates/includes/cart/cart_items.html +++ b/erpnext/templates/includes/cart/cart_items.html @@ -21,12 +21,11 @@ + - +{{ - _("Rate: {0}").format(d.get_formatted("rate")) }}
+{{ _("Rate") }} {{ d.get_formatted("rate") }}
{{ - _("Delivered: {0}").format(d.delivered_qty) }}
+{{ _("Delivered") }} {{ d.delivered_qty }}
{% endif %}{{ - _("@ {0}").format(d.get_formatted("rate")) }}
+{{ _("Rate:") }} {{ d.get_formatted("rate") }}