diff --git a/.travis.yml b/.travis.yml index 14260e3d25c..869fe959c00 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,7 +15,7 @@ install: - sudo rm /etc/apt/sources.list.d/docker.list - sudo apt-get install hhvm && rm -rf /home/travis/.kiex/ - sudo apt-get purge -y mysql-common mysql-server mysql-client - - nvm install v7.10.0 + - nvm install 10 - pip install python-coveralls - wget https://raw.githubusercontent.com/frappe/bench/master/playbooks/install.py - sudo python install.py --develop --user travis --without-bench-setup diff --git a/README.md b/README.md index 8c13e1ed884..b1979d0045e 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,6 @@

[![Build Status](https://travis-ci.com/frappe/erpnext.png)](https://travis-ci.com/frappe/erpnext) -[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/frappe/erpnext?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Open Source Helpers](https://www.codetriage.com/frappe/erpnext/badges/users.svg)](https://www.codetriage.com/frappe/erpnext) [![Coverage Status](https://coveralls.io/repos/github/frappe/erpnext/badge.svg?branch=develop)](https://coveralls.io/github/frappe/erpnext?branch=develop) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index 24cc8ea79c2..993a4e60386 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__ = '11.1.8' +__version__ = '11.1.20' def get_default_company(user=None): '''Get default company for user''' diff --git a/erpnext/accounts/deferred_revenue.py b/erpnext/accounts/deferred_revenue.py index e638fc7b17f..3afb4bc8c6a 100644 --- a/erpnext/accounts/deferred_revenue.py +++ b/erpnext/accounts/deferred_revenue.py @@ -2,9 +2,9 @@ from __future__ import unicode_literals import frappe from frappe import _ -from frappe.utils import date_diff, add_months, today, getdate, add_days, flt +from frappe.utils import date_diff, add_months, today, getdate, add_days, flt, get_last_day from erpnext.accounts.utils import get_account_currency -from erpnext.accounts.general_ledger import make_gl_entries +from frappe.email import sendmail_to_system_managers def validate_service_stop_date(doc): ''' Validates service_stop_date for Purchase Invoice and Sales Invoice ''' @@ -33,47 +33,49 @@ def validate_service_stop_date(doc): frappe.throw(_("Cannot change Service Stop Date for item in row {0}".format(item.idx))) def convert_deferred_expense_to_expense(start_date=None, end_date=None): + # book the expense/income on the last day, but it will be trigger on the 1st of month at 12:00 AM + if not start_date: + start_date = add_months(today(), -1) + if not end_date: + end_date = add_days(today(), -1) + # check for the purchase invoice for which GL entries has to be done invoices = frappe.db.sql_list(''' - select distinct parent from `tabPurchase Invoice Item` where service_start_date<=%s and service_end_date>=%s + select distinct parent from `tabPurchase Invoice Item` + where service_start_date<=%s and service_end_date>=%s and enable_deferred_expense = 1 and docstatus = 1 and ifnull(amount, 0) > 0 - ''', (end_date or today(), start_date or add_months(today(), -1))) + ''', (end_date, start_date)) # For each invoice, book deferred expense for invoice in invoices: doc = frappe.get_doc("Purchase Invoice", invoice) - book_deferred_income_or_expense(doc, start_date, end_date) + book_deferred_income_or_expense(doc, end_date) def convert_deferred_revenue_to_income(start_date=None, end_date=None): + # book the expense/income on the last day, but it will be trigger on the 1st of month at 12:00 AM + if not start_date: + start_date = add_months(today(), -1) + if not end_date: + end_date = add_days(today(), -1) + # check for the sales invoice for which GL entries has to be done invoices = frappe.db.sql_list(''' - select distinct parent from `tabSales Invoice Item` where service_start_date<=%s and service_end_date>=%s + select distinct parent from `tabSales Invoice Item` + where service_start_date<=%s and service_end_date>=%s and enable_deferred_revenue = 1 and docstatus = 1 and ifnull(amount, 0) > 0 - ''', (end_date or today(), start_date or add_months(today(), -1))) + ''', (end_date, start_date)) - # For each invoice, book deferred revenue for invoice in invoices: doc = frappe.get_doc("Sales Invoice", invoice) - book_deferred_income_or_expense(doc, start_date, end_date) + book_deferred_income_or_expense(doc, end_date) + +def get_booking_dates(doc, item, posting_date=None): + if not posting_date: + posting_date = add_days(today(), -1) + + last_gl_entry = False -def get_booking_dates(doc, item, start_date=None, end_date=None): deferred_account = "deferred_revenue_account" if doc.doctype=="Sales Invoice" else "deferred_expense_account" - last_gl_entry, skip = False, False - - booking_end_date = getdate(add_days(today(), -1) if not end_date else end_date) - if booking_end_date < item.service_start_date or \ - (item.service_stop_date and booking_end_date.month > item.service_stop_date.month): - return None, None, None, True - elif booking_end_date >= item.service_end_date: - last_gl_entry = True - booking_end_date = item.service_end_date - elif item.service_stop_date and item.service_stop_date <= booking_end_date: - last_gl_entry = True - booking_end_date = item.service_stop_date - - booking_start_date = getdate(add_months(today(), -1) if not start_date else start_date) - booking_start_date = booking_start_date \ - if booking_start_date > item.service_start_date else item.service_start_date prev_gl_entry = frappe.db.sql(''' select name, posting_date from `tabGL Entry` where company=%s and account=%s and @@ -81,17 +83,28 @@ def get_booking_dates(doc, item, start_date=None, end_date=None): order by posting_date desc limit 1 ''', (doc.company, item.get(deferred_account), doc.doctype, doc.name, item.name), as_dict=True) - if not prev_gl_entry and item.service_start_date < booking_start_date: - booking_start_date = item.service_start_date - elif prev_gl_entry: - booking_start_date = getdate(add_days(prev_gl_entry[0].posting_date, 1)) - skip = True if booking_start_date > booking_end_date else False + if prev_gl_entry: + start_date = getdate(add_days(prev_gl_entry[0].posting_date, 1)) + else: + start_date = item.service_start_date - return last_gl_entry, booking_start_date, booking_end_date, skip + end_date = get_last_day(start_date) + if end_date >= item.service_end_date: + end_date = item.service_end_date + last_gl_entry = True + elif item.service_stop_date and end_date >= item.service_stop_date: + end_date = item.service_stop_date + last_gl_entry = True -def calculate_amount_and_base_amount(doc, item, last_gl_entry, total_days, total_booking_days): - account_currency = get_account_currency(item.expense_account) + if end_date > getdate(posting_date): + end_date = posting_date + if getdate(start_date) <= getdate(end_date): + return start_date, end_date, last_gl_entry + else: + return None, None, None + +def calculate_amount(doc, item, last_gl_entry, total_days, total_booking_days, account_currency): if doc.doctype == "Sales Invoice": total_credit_debit, total_credit_debit_currency = "debit", "debit_in_account_currency" deferred_account = "deferred_revenue_account" @@ -123,28 +136,15 @@ def calculate_amount_and_base_amount(doc, item, last_gl_entry, total_days, total return amount, base_amount -def book_deferred_income_or_expense(doc, start_date=None, end_date=None): - # book the expense/income on the last day, but it will be trigger on the 1st of month at 12:00 AM - # start_date: 1st of the last month or the start date - # end_date: end_date or today-1 +def book_deferred_income_or_expense(doc, posting_date=None): enable_check = "enable_deferred_revenue" \ if doc.doctype=="Sales Invoice" else "enable_deferred_expense" - gl_entries = [] - for item in doc.get('items'): - if not item.get(enable_check): continue - - skip = False - last_gl_entry, booking_start_date, booking_end_date, skip = \ - get_booking_dates(doc, item, start_date, end_date) - - if skip: continue - total_days = date_diff(item.service_end_date, item.service_start_date) + 1 - total_booking_days = date_diff(booking_end_date, booking_start_date) + 1 + def _book_deferred_revenue_or_expense(item): + start_date, end_date, last_gl_entry = get_booking_dates(doc, item, posting_date=posting_date) + if not (start_date and end_date): return account_currency = get_account_currency(item.expense_account) - amount, base_amount = calculate_amount_and_base_amount(doc, item, last_gl_entry, total_days, total_booking_days) - if doc.doctype == "Sales Invoice": against, project = doc.customer, doc.project credit_account, debit_account = item.income_account, item.deferred_revenue_account @@ -152,36 +152,62 @@ def book_deferred_income_or_expense(doc, start_date=None, end_date=None): against, project = doc.supplier, item.project credit_account, debit_account = item.deferred_expense_account, item.expense_account - # GL Entry for crediting the amount in the deferred expense - gl_entries.append( - doc.get_gl_dict({ - "account": credit_account, - "against": against, - "credit": base_amount, - "credit_in_account_currency": amount, - "cost_center": item.cost_center, - "voucher_detail_no": item.name, - 'posting_date': booking_end_date, - 'project': project - }, account_currency) - ) - # GL Entry to debit the amount from the expense - gl_entries.append( - doc.get_gl_dict({ - "account": debit_account, - "against": against, - "debit": base_amount, - "debit_in_account_currency": amount, - "cost_center": item.cost_center, - "voucher_detail_no": item.name, - 'posting_date': booking_end_date, - 'project': project - }, account_currency) - ) + total_days = date_diff(item.service_end_date, item.service_start_date) + 1 + total_booking_days = date_diff(end_date, start_date) + 1 + + amount, base_amount = calculate_amount(doc, item, last_gl_entry, + total_days, total_booking_days, account_currency) + + make_gl_entries(doc, credit_account, debit_account, against, + amount, base_amount, end_date, project, account_currency, item.cost_center, item.name) + + if getdate(end_date) < getdate(posting_date) and not last_gl_entry: + _book_deferred_revenue_or_expense(item) + + + for item in doc.get('items'): + if item.get(enable_check): + _book_deferred_revenue_or_expense(item) + +def make_gl_entries(doc, credit_account, debit_account, against, + amount, base_amount, posting_date, project, account_currency, cost_center, voucher_detail_no): + # GL Entry for crediting the amount in the deferred expense + from erpnext.accounts.general_ledger import make_gl_entries + + gl_entries = [] + gl_entries.append( + doc.get_gl_dict({ + "account": credit_account, + "against": against, + "credit": base_amount, + "credit_in_account_currency": amount, + "cost_center": cost_center, + "voucher_detail_no": voucher_detail_no, + 'posting_date': posting_date, + 'project': project + }, account_currency) + ) + # GL Entry to debit the amount from the expense + gl_entries.append( + doc.get_gl_dict({ + "account": debit_account, + "against": against, + "debit": base_amount, + "debit_in_account_currency": amount, + "cost_center": cost_center, + "voucher_detail_no": voucher_detail_no, + 'posting_date': posting_date, + 'project': project + }, account_currency) + ) + if gl_entries: try: make_gl_entries(gl_entries, cancel=(doc.docstatus == 2), merge_entries=True) frappe.db.commit() except: frappe.db.rollback() - frappe.log_error(message = frappe.get_traceback(), title = _("Error while processing deferred accounting for {0}").format(doc.name)) \ No newline at end of file + title = _("Error while processing deferred accounting for {0}").format(doc.name) + traceback = frappe.get_traceback() + frappe.log_error(message=traceback , title=title) + sendmail_to_system_managers(title, traceback) \ No newline at end of file diff --git a/erpnext/accounts/doctype/account/account.json b/erpnext/accounts/doctype/account/account.json index e47f8d22451..460c025b690 100644 --- a/erpnext/accounts/doctype/account/account.json +++ b/erpnext/accounts/doctype/account/account.json @@ -632,6 +632,39 @@ "set_only_once": 0, "translatable": 0, "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "eval:(doc.report_type == 'Profit and Loss' && !doc.is_group)", + "fieldname": "include_in_gross", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Include in gross", + "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 } ], "has_web_view": 0, @@ -645,7 +678,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2019-01-07 16:52:02.557837", + "modified": "2019-03-04 14:42:07.208893", "modified_by": "Administrator", "module": "Accounts", "name": "Account", diff --git a/erpnext/accounts/doctype/account/account.py b/erpnext/accounts/doctype/account/account.py index 5d504b94be6..3d9604d159c 100644 --- a/erpnext/accounts/doctype/account/account.py +++ b/erpnext/accounts/doctype/account/account.py @@ -5,7 +5,7 @@ from __future__ import unicode_literals import frappe from frappe.utils import cint, cstr from frappe import throw, _ -from frappe.utils.nestedset import NestedSet +from frappe.utils.nestedset import NestedSet, get_ancestors_of, get_descendants_of class RootNotEditable(frappe.ValidationError): pass class BalanceMismatchError(frappe.ValidationError): pass @@ -41,6 +41,7 @@ class Account(NestedSet): self.validate_frozen_accounts_modifier() self.validate_balance_must_be_debit_or_credit() self.validate_account_currency() + self.validate_root_company_and_sync_account_to_children() def validate_parent(self): """Fetch Parent Details and validate parent account""" @@ -90,6 +91,38 @@ class Account(NestedSet): if not self.parent_account and not self.is_group: frappe.throw(_("Root Account must be a group")) + def validate_root_company_and_sync_account_to_children(self): + # ignore validation while creating new compnay or while syncing to child companies + if frappe.local.flags.ignore_root_company_validation or self.flags.ignore_root_company_validation: + return + + ancestors = get_root_company(self.company) + if ancestors: + if frappe.get_value("Company", self.company, "allow_account_creation_against_child_company"): + return + frappe.throw(_("Please add the account to root level Company - %s" % ancestors[0])) + else: + descendants = get_descendants_of('Company', self.company) + if not descendants: return + + acc_name_map = {} + acc_name = frappe.db.get_value('Account', self.parent_account, "account_name") + for d in frappe.db.get_values('Account', + {"company": ["in", descendants], "account_name": acc_name}, + ["company", "name"], as_dict=True): + acc_name_map[d["company"]] = d["name"] + + if not acc_name_map: return + + for company in descendants: + doc = frappe.copy_doc(self) + doc.flags.ignore_root_company_validation = True + doc.update({"company": company, "account_currency": None, + "parent": acc_name_map[company], "parent_account": acc_name_map[company]}) + doc.save() + frappe.msgprint(_("Account {0} is added in the child company {1}") + .format(doc.name, company)) + def validate_group_or_ledger(self): if self.get("__islocal"): return @@ -250,3 +283,9 @@ def merge_account(old, new, is_group, root_type, company): frappe.rename_doc("Account", old, new, merge=1, ignore_permissions=1) return new + +@frappe.whitelist() +def get_root_company(company): + # return the topmost company in the hierarchy + ancestors = get_ancestors_of('Company', company, "lft asc") + return [ancestors[0]] if ancestors else [] diff --git a/erpnext/accounts/doctype/account/account_tree.js b/erpnext/accounts/doctype/account/account_tree.js index a9cbdd5dee7..27f5349e2b7 100644 --- a/erpnext/accounts/doctype/account/account_tree.js +++ b/erpnext/accounts/doctype/account/account_tree.js @@ -4,13 +4,42 @@ frappe.treeview_settings["Account"] = { breadcrumbs: "Accounts", title: __("Chart Of Accounts"), get_tree_root: false, - filters: [{ - fieldname: "company", - fieldtype:"Select", - options: erpnext.utils.get_tree_options("company"), - label: __("Company"), - default: erpnext.utils.get_tree_default("company") - }], + filters: [ + { + fieldname: "company", + fieldtype:"Select", + options: erpnext.utils.get_tree_options("company"), + label: __("Company"), + default: erpnext.utils.get_tree_default("company"), + on_change: function() { + var me = frappe.treeview_settings['Account'].treeview; + var company = me.page.fields_dict.company.get_value(); + frappe.call({ + method: "erpnext.accounts.doctype.account.account.get_root_company", + args: { + company: company, + }, + callback: function(r) { + if(r.message) { + let root_company = r.message.length ? r.message[0] : ""; + me.page.fields_dict.root_company.set_value(root_company); + + frappe.db.get_value("Company", {"name": company}, "allow_account_creation_against_child_company", (r) => { + frappe.flags.ignore_root_company_validation = r.allow_account_creation_against_child_company; + }); + } + } + }); + } + }, + { + fieldname: "root_company", + fieldtype:"Data", + label: __("Root Company"), + hidden: true, + disable_onchange: true + } + ], root_label: "Accounts", get_tree_nodes: 'erpnext.accounts.utils.get_children', add_tree_node: 'erpnext.accounts.utils.add_ac', @@ -42,8 +71,8 @@ frappe.treeview_settings["Account"] = { ], ignore_fields:["parent_account"], onload: function(treeview) { - frappe.treeview_settings['Account'].page = {}; - $.extend(frappe.treeview_settings['Account'].page, treeview.page); + frappe.treeview_settings['Account'].treeview = {}; + $.extend(frappe.treeview_settings['Account'].treeview, treeview); function get_company() { return treeview.page.fields_dict.company.get_value(); } @@ -78,6 +107,18 @@ frappe.treeview_settings["Account"] = { } }, + post_render: function(treeview) { + frappe.treeview_settings['Account'].treeview["tree"] = treeview.tree; + treeview.page.set_primary_action(__("New"), function() { + let root_company = treeview.page.fields_dict.root_company.get_value(); + + if(root_company) { + frappe.throw(__("Please add the account to root level Company - ") + root_company); + } else { + treeview.new_node(); + } + }, "octicon octicon-plus"); + }, onrender: function(node) { if(frappe.boot.user.can_read.indexOf("GL Entry") !== -1){ var dr_or_cr = node.data.balance < 0 ? "Cr" : "Dr"; @@ -93,6 +134,20 @@ frappe.treeview_settings["Account"] = { } }, toolbar: [ + { + label:__("Add Child"), + condition: function(node) { + return frappe.boot.user.can_create.indexOf("Account") !== -1 + && (!frappe.treeview_settings['Account'].treeview.page.fields_dict.root_company.get_value() + || frappe.flags.ignore_root_company_validation) + && node.expandable && !node.hide_add; + }, + click: function() { + var me = frappe.treeview_settings['Account'].treeview; + me.new_node(); + }, + btnClass: "hidden-xs" + }, { condition: function(node) { return !node.root && frappe.boot.user.can_read.indexOf("GL Entry") !== -1 @@ -103,7 +158,7 @@ frappe.treeview_settings["Account"] = { "account": node.label, "from_date": frappe.sys_defaults.year_start_date, "to_date": frappe.sys_defaults.year_end_date, - "company": frappe.treeview_settings['Account'].page.fields_dict.company.get_value() + "company": frappe.treeview_settings['Account'].treeview.page.fields_dict.company.get_value() }; frappe.set_route("query-report", "General Ledger"); }, diff --git a/erpnext/accounts/doctype/account/test_account.py b/erpnext/accounts/doctype/account/test_account.py index acaa0966a20..90177c630a8 100644 --- a/erpnext/accounts/doctype/account/test_account.py +++ b/erpnext/accounts/doctype/account/test_account.py @@ -97,6 +97,19 @@ class TestAccount(unittest.TestCase): self.assertRaises(frappe.ValidationError, merge_account, "Capital Stock - _TC",\ "Softwares - _TC", doc.is_group, doc.root_type, doc.company) + def test_account_sync(self): + del frappe.local.flags["ignore_root_company_validation"] + acc = frappe.new_doc("Account") + acc.account_name = "Test Sync Account" + acc.parent_account = "Temporary Accounts - _TC3" + acc.company = "_Test Company 3" + acc.insert() + + acc_tc_4 = frappe.db.get_value('Account', {'account_name': "Test Sync Account", "company": "_Test Company 4"}) + acc_tc_5 = frappe.db.get_value('Account', {'account_name': "Test Sync Account", "company": "_Test Company 5"}) + self.assertEqual(acc_tc_4, "Test Sync Account - _TC4") + self.assertEqual(acc_tc_5, "Test Sync Account - _TC5") + def _make_test_records(verbose): from frappe.test_runner import make_test_objects @@ -131,7 +144,7 @@ def _make_test_records(verbose): # related to Account Inventory Integration ["_Test Account Stock In Hand", "Current Assets", 0, None, None], - + # fixed asset depreciation ["_Test Fixed Asset", "Current Assets", 0, "Fixed Asset", None], ["_Test Accumulated Depreciations", "Current Assets", 0, None, None], @@ -168,13 +181,17 @@ def get_inventory_account(company, warehouse=None): return account def create_account(**kwargs): - account = frappe.get_doc(dict( - doctype = "Account", - account_name = kwargs.get('account_name'), - account_type = kwargs.get('account_type'), - parent_account = kwargs.get('parent_account'), - company = kwargs.get('company') - )) - - account.save() - return account.name + account = frappe.db.get_value("Account", filters={"account_name": kwargs.get("account_name"), "company": kwargs.get("company")}) + if account: + return account + else: + account = frappe.get_doc(dict( + doctype = "Account", + account_name = kwargs.get('account_name'), + account_type = kwargs.get('account_type'), + parent_account = kwargs.get('parent_account'), + company = kwargs.get('company') + )) + + account.save() + return account.name diff --git a/erpnext/accounts/doctype/bank_account/bank_account.json b/erpnext/accounts/doctype/bank_account/bank_account.json index 4897097b4ac..84a8e6857c3 100644 --- a/erpnext/accounts/doctype/bank_account/bank_account.json +++ b/erpnext/accounts/doctype/bank_account/bank_account.json @@ -1,5 +1,6 @@ { "allow_copy": 0, + "allow_events_in_timeline": 0, "allow_guest_to_view": 0, "allow_import": 0, "allow_rename": 1, @@ -290,7 +291,7 @@ "in_list_view": 1, "in_standard_filter": 0, "label": "IBAN", - "length": 25, + "length": 30, "no_copy": 0, "permlevel": 0, "precision": "", @@ -669,7 +670,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2018-07-20 13:55:36.996465", + "modified": "2019-03-05 17:56:05.103238", "modified_by": "Administrator", "module": "Accounts", "name": "Bank Account", diff --git a/erpnext/accounts/doctype/bank_reconciliation/bank_reconciliation.py b/erpnext/accounts/doctype/bank_reconciliation/bank_reconciliation.py index 917276293d2..fae5213f234 100644 --- a/erpnext/accounts/doctype/bank_reconciliation/bank_reconciliation.py +++ b/erpnext/accounts/doctype/bank_reconciliation/bank_reconciliation.py @@ -23,36 +23,36 @@ class BankReconciliation(Document): journal_entries = frappe.db.sql(""" - select - "Journal Entry" as payment_document, t1.name as payment_entry, - t1.cheque_no as cheque_number, t1.cheque_date, + select + "Journal Entry" as payment_document, t1.name as payment_entry, + t1.cheque_no as cheque_number, t1.cheque_date, 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 + t1.posting_date, t2.against_account, t1.clearance_date, t2.account_currency from `tabJournal Entry` t1, `tabJournal Entry Account` t2 where t2.parent = t1.name and t2.account = %s and t1.docstatus=1 - and t1.posting_date >= %s and t1.posting_date <= %s + and 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) payment_entries = frappe.db.sql(""" - select - "Payment Entry" as payment_document, name as payment_entry, - reference_no as cheque_number, reference_date as cheque_date, - if(paid_from=%(account)s, paid_amount, "") as credit, - if(paid_from=%(account)s, "", received_amount) as debit, + select + "Payment Entry" as payment_document, name as payment_entry, + reference_no as cheque_number, reference_date as cheque_date, + if(paid_from=%(account)s, paid_amount, 0) as credit, + if(paid_from=%(account)s, 0, received_amount) as debit, posting_date, ifnull(party,if(paid_from=%(account)s,paid_to,paid_from)) as against_account, clearance_date, if(paid_to=%(account)s, paid_to_account_currency, paid_from_account_currency) as account_currency from `tabPayment Entry` where (paid_from=%(account)s or paid_to=%(account)s) and docstatus=1 and posting_date >= %(from)s and posting_date <= %(to)s {0} - order by + order by posting_date ASC, name DESC - """.format(condition), + """.format(condition), {"account":self.bank_account, "from":self.from_date, "to":self.to_date}, as_dict=1) pos_entries = [] @@ -79,8 +79,12 @@ class BankReconciliation(Document): for d in entries: row = self.append('payment_entries', {}) - amount = d.debit if d.debit else d.credit - d.amount = fmt_money(amount, 2, d.account_currency) + " " + (_("Dr") if d.debit else _("Cr")) + + amount = flt(d.get('debit', 0)) - flt(d.get('credit', 0)) + + formatted_amount = fmt_money(abs(amount), 2, d.account_currency) + d.amount = formatted_amount + " " + (_("Dr") if amount > 0 else _("Cr")) + d.pop("credit") d.pop("debit") d.pop("account_currency") @@ -103,10 +107,10 @@ class BankReconciliation(Document): d.clearance_date = None frappe.db.set_value(d.payment_document, d.payment_entry, "clearance_date", d.clearance_date) - frappe.db.sql("""update `tab{0}` set clearance_date = %s, modified = %s - where name=%s""".format(d.payment_document), + frappe.db.sql("""update `tab{0}` set clearance_date = %s, modified = %s + where name=%s""".format(d.payment_document), (d.clearance_date, nowdate(), d.payment_entry)) - + clearance_date_updated = True if clearance_date_updated: diff --git a/erpnext/accounts/doctype/budget/budget.json b/erpnext/accounts/doctype/budget/budget.json index a803b655835..50ad2e5ebce 100644 --- a/erpnext/accounts/doctype/budget/budget.json +++ b/erpnext/accounts/doctype/budget/budget.json @@ -1,5 +1,6 @@ { "allow_copy": 0, + "allow_events_in_timeline": 0, "allow_guest_to_view": 0, "allow_import": 1, "allow_rename": 0, @@ -19,6 +20,7 @@ "collapsible": 0, "columns": 0, "default": "Cost Center", + "fetch_if_empty": 0, "fieldname": "budget_against", "fieldtype": "Select", "hidden": 0, @@ -52,6 +54,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "company", "fieldtype": "Link", "hidden": 0, @@ -86,6 +89,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval:doc.budget_against == 'Cost Center'", + "fetch_if_empty": 0, "fieldname": "cost_center", "fieldtype": "Link", "hidden": 0, @@ -120,6 +124,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval:doc.budget_against == 'Project'", + "fetch_if_empty": 0, "fieldname": "project", "fieldtype": "Link", "hidden": 0, @@ -153,6 +158,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "fiscal_year", "fieldtype": "Link", "hidden": 0, @@ -186,6 +192,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break_3", "fieldtype": "Column Break", "hidden": 0, @@ -218,6 +225,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval:in_list([\"Stop\", \"Warn\"], doc.action_if_accumulated_monthly_budget_exceeded_on_po || doc.action_if_accumulated_monthly_budget_exceeded_on_mr || doc.action_if_accumulated_monthly_budget_exceeded_on_actual)", + "fetch_if_empty": 0, "fieldname": "monthly_distribution", "fieldtype": "Link", "hidden": 0, @@ -251,6 +259,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "amended_from", "fieldtype": "Link", "hidden": 0, @@ -283,6 +292,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "section_break_6", "fieldtype": "Section Break", "hidden": 0, @@ -315,6 +325,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "applicable_on_material_request", "fieldtype": "Check", "hidden": 0, @@ -343,12 +354,13 @@ { "allow_bulk_edit": 0, "allow_in_quick_entry": 0, - "allow_on_submit": 0, + "allow_on_submit": 1, "bold": 0, "collapsible": 0, "columns": 0, "default": "Stop", "depends_on": "eval:doc.applicable_on_material_request == 1", + "fetch_if_empty": 0, "fieldname": "action_if_annual_budget_exceeded_on_mr", "fieldtype": "Select", "hidden": 0, @@ -378,12 +390,13 @@ { "allow_bulk_edit": 0, "allow_in_quick_entry": 0, - "allow_on_submit": 0, + "allow_on_submit": 1, "bold": 0, "collapsible": 0, "columns": 0, "default": "Warn", "depends_on": "eval:doc.applicable_on_material_request == 1", + "fetch_if_empty": 0, "fieldname": "action_if_accumulated_monthly_budget_exceeded_on_mr", "fieldtype": "Select", "hidden": 0, @@ -417,6 +430,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break_13", "fieldtype": "Column Break", "hidden": 0, @@ -448,6 +462,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "applicable_on_purchase_order", "fieldtype": "Check", "hidden": 0, @@ -476,12 +491,13 @@ { "allow_bulk_edit": 0, "allow_in_quick_entry": 0, - "allow_on_submit": 0, + "allow_on_submit": 1, "bold": 0, "collapsible": 0, "columns": 0, "default": "Stop", "depends_on": "eval:doc.applicable_on_purchase_order == 1", + "fetch_if_empty": 0, "fieldname": "action_if_annual_budget_exceeded_on_po", "fieldtype": "Select", "hidden": 0, @@ -511,12 +527,13 @@ { "allow_bulk_edit": 0, "allow_in_quick_entry": 0, - "allow_on_submit": 0, + "allow_on_submit": 1, "bold": 0, "collapsible": 0, "columns": 0, "default": "Warn", "depends_on": "eval:doc.applicable_on_purchase_order == 1", + "fetch_if_empty": 0, "fieldname": "action_if_accumulated_monthly_budget_exceeded_on_po", "fieldtype": "Select", "hidden": 0, @@ -550,6 +567,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "section_break_16", "fieldtype": "Section Break", "hidden": 0, @@ -581,6 +599,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "applicable_on_booking_actual_expenses", "fieldtype": "Check", "hidden": 0, @@ -609,12 +628,13 @@ { "allow_bulk_edit": 0, "allow_in_quick_entry": 0, - "allow_on_submit": 0, + "allow_on_submit": 1, "bold": 0, "collapsible": 0, "columns": 0, "default": "Stop", "depends_on": "eval:doc.applicable_on_booking_actual_expenses == 1", + "fetch_if_empty": 0, "fieldname": "action_if_annual_budget_exceeded", "fieldtype": "Select", "hidden": 0, @@ -644,12 +664,13 @@ { "allow_bulk_edit": 0, "allow_in_quick_entry": 0, - "allow_on_submit": 0, + "allow_on_submit": 1, "bold": 0, "collapsible": 0, "columns": 0, "default": "Warn", "depends_on": "eval:doc.applicable_on_booking_actual_expenses == 1", + "fetch_if_empty": 0, "fieldname": "action_if_accumulated_monthly_budget_exceeded", "fieldtype": "Select", "hidden": 0, @@ -683,6 +704,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "section_break_21", "fieldtype": "Section Break", "hidden": 0, @@ -715,6 +737,7 @@ "collapsible": 0, "columns": 0, "depends_on": "", + "fetch_if_empty": 0, "fieldname": "accounts", "fieldtype": "Table", "hidden": 0, @@ -735,7 +758,7 @@ "read_only": 0, "remember_last_selected_value": 0, "report_hide": 0, - "reqd": 1, + "reqd": 1, "search_index": 0, "set_only_once": 0, "translatable": 0, @@ -752,7 +775,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2018-09-12 11:02:41.825923", + "modified": "2019-03-22 12:06:02.323099", "modified_by": "Administrator", "module": "Accounts", "name": "Budget", @@ -785,7 +808,7 @@ "show_name_in_global_search": 0, "sort_field": "modified", "sort_order": "DESC", - "track_changes": 1, - "track_seen": 0, + "track_changes": 1, + "track_seen": 0, "track_views": 0 } \ No newline at end of file diff --git a/erpnext/accounts/doctype/cashier_closing/cashier_closing.json b/erpnext/accounts/doctype/cashier_closing/cashier_closing.json index 14e9070f302..115728dc7b6 100644 --- a/erpnext/accounts/doctype/cashier_closing/cashier_closing.json +++ b/erpnext/accounts/doctype/cashier_closing/cashier_closing.json @@ -1,426 +1,434 @@ { - "allow_copy": 0, - "allow_events_in_timeline": 0, - "allow_guest_to_view": 0, - "allow_import": 0, - "allow_rename": 0, - "autoname": "naming_series:", - "beta": 0, - "creation": "2018-06-18 16:51:49.994750", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "", - "editable_grid": 1, - "engine": "InnoDB", - "fields": [ - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "Cashier-closing-", - "fieldname": "naming_series", - "fieldtype": "Select", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 1, - "in_global_search": 1, - "in_list_view": 0, - "in_standard_filter": 1, - "label": "Series", - "length": 0, - "no_copy": 0, - "options": "Cashier-closing-", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "user", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 1, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 1, - "label": "User", - "length": 0, - "no_copy": 0, - "options": "User", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "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, - "default": "Today", - "fieldname": "date", - "fieldtype": "Date", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 1, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 1, - "label": "Date", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "from_time", - "fieldtype": "Time", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 1, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 1, - "label": "From Time", - "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": 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, - "default": "", - "fieldname": "time", - "fieldtype": "Time", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 1, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 1, - "label": "To Time", - "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": 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, - "default": "0.00", - "fieldname": "expense", - "fieldtype": "Float", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 1, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Expense", - "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, - "default": "0.00", - "fieldname": "custody", - "fieldtype": "Float", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 1, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Custody", - "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, - "default": "0.00", - "fieldname": "outstanding_amount", - "fieldtype": "Float", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Outstanding Amount", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "0.0", - "fieldname": "payments", - "fieldtype": "Table", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 1, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Payments", - "length": 0, - "no_copy": 0, - "options": "Cashier Closing Payments", - "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": "net_amount", - "fieldtype": "Float", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 1, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 1, - "label": "Net Amount", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "amended_from", - "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": "Amended From", - "length": 0, - "no_copy": 1, - "options": "Cashier Closing", - "permlevel": 0, - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - } - ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "idx": 0, - "image_view": 0, - "in_create": 0, - "is_submittable": 1, - "issingle": 0, - "istable": 0, - "max_attachments": 0, - "modified": "2019-02-19 08:35:23.157327", - "modified_by": "Administrator", - "module": "Accounts", - "name": "Cashier Closing", - "name_case": "", - "owner": "Administrator", - "permissions": [ - { - "amend": 0, - "cancel": 0, - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "System Manager", - "set_user_permissions": 0, - "share": 1, - "submit": 1, - "write": 1 - } - ], - "quick_entry": 0, - "read_only": 0, - "read_only_onload": 0, - "show_name_in_global_search": 0, - "sort_field": "modified", - "sort_order": "DESC", - "track_changes": 1, - "track_seen": 0, - "track_views": 0 -} \ No newline at end of file + "allow_copy": 0, + "allow_guest_to_view": 0, + "allow_import": 0, + "allow_rename": 0, + "autoname": "naming_series:", + "beta": 0, + "creation": "2018-06-18 16:51:49.994750", + "custom": 0, + "docstatus": 0, + "doctype": "DocType", + "document_type": "", + "editable_grid": 1, + "engine": "InnoDB", + "fields": [ + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "default": "POS-CLO-", + "fieldname": "naming_series", + "fieldtype": "Select", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 1, + "in_global_search": 1, + "in_list_view": 0, + "in_standard_filter": 1, + "label": "Series", + "length": 0, + "no_copy": 0, + "options": "POS-CLO-", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 1, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "user", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 1, + "in_global_search": 0, + "in_list_view": 1, + "in_standard_filter": 1, + "label": "User", + "length": 0, + "no_copy": 0, + "options": "User", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 1, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 1, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "default": "Today", + "fieldname": "date", + "fieldtype": "Date", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 1, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 1, + "label": "Date", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 1, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "from_time", + "fieldtype": "Time", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 1, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 1, + "label": "From Time", + "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": 1, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "default": "", + "fieldname": "time", + "fieldtype": "Time", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 1, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 1, + "label": "To Time", + "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": 1, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "default": "0.00", + "fieldname": "expense", + "fieldtype": "Float", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 1, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Expense", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "2", + "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, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "default": "0.00", + "fieldname": "custody", + "fieldtype": "Float", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 1, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Custody", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "2", + "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, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "default": "0.00", + "fieldname": "returns", + "fieldtype": "Float", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 1, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Returns", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "2", + "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, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "default": "0.00", + "fieldname": "outstanding_amount", + "fieldtype": "Float", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Outstanding Amount", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "2", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 1, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "default": "0.0", + "fieldname": "payments", + "fieldtype": "Table", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 1, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Payments", + "length": 0, + "no_copy": 0, + "options": "Cashier Closing Payments", + "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, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "net_amount", + "fieldtype": "Float", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 1, + "in_global_search": 0, + "in_list_view": 1, + "in_standard_filter": 1, + "label": "Net Amount", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 1, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "amended_from", + "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": "Amended From", + "length": 0, + "no_copy": 1, + "options": "Cashier Closing", + "permlevel": 0, + "print_hide": 1, + "print_hide_if_no_value": 0, + "read_only": 1, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + } + ], + "has_web_view": 0, + "hide_heading": 0, + "hide_toolbar": 0, + "idx": 0, + "image_view": 0, + "in_create": 0, + "is_submittable": 1, + "issingle": 0, + "istable": 0, + "max_attachments": 0, + "modified": "2019-03-14 09:14:26.727129", + "modified_by": "Administrator", + "module": "Accounts", + "name": "Cashier Closing", + "name_case": "", + "owner": "Administrator", + "permissions": [ + { + "amend": 0, + "apply_user_permissions": 0, + "cancel": 0, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "if_owner": 0, + "import": 0, + "permlevel": 0, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "set_user_permissions": 0, + "share": 1, + "submit": 1, + "write": 1 + } + ], + "quick_entry": 0, + "read_only": 0, + "read_only_onload": 0, + "show_name_in_global_search": 0, + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 1, + "track_seen": 0 + } \ No newline at end of file diff --git a/erpnext/accounts/doctype/cashier_closing/cashier_closing.py b/erpnext/accounts/doctype/cashier_closing/cashier_closing.py index 906bc7f18a5..6de62ee5777 100644 --- a/erpnext/accounts/doctype/cashier_closing/cashier_closing.py +++ b/erpnext/accounts/doctype/cashier_closing/cashier_closing.py @@ -29,8 +29,8 @@ class CashierClosing(Document): for i in self.payments: total += flt(i.amount) - self.net_amount = total + self.outstanding_amount + self.expense - self.custody + self.net_amount = total + self.outstanding_amount + self.expense - self.custody + self.returns def validate_time(self): if self.from_time >= self.time: - frappe.throw(_("From Time Should Be Less Than To Time")) + frappe.throw(_("From Time Should Be Less Than To Time")) \ No newline at end of file diff --git a/erpnext/accounts/doctype/gl_entry/gl_entry.py b/erpnext/accounts/doctype/gl_entry/gl_entry.py index 810b6f79b51..e719167e784 100644 --- a/erpnext/accounts/doctype/gl_entry/gl_entry.py +++ b/erpnext/accounts/doctype/gl_entry/gl_entry.py @@ -6,6 +6,7 @@ import frappe, erpnext from frappe import _ from frappe.utils import flt, fmt_money, getdate, formatdate from frappe.model.document import Document +from frappe.model.meta import get_field_precision from erpnext.accounts.party import validate_party_gle_currency, validate_party_frozen_disabled from erpnext.accounts.utils import get_account_currency from erpnext.accounts.utils import get_fiscal_year @@ -56,7 +57,7 @@ class GLEntry(Document): .format(self.voucher_type, self.voucher_no, self.account)) # Zero value transaction is not allowed - if not (flt(self.debit) or flt(self.credit)): + if not (flt(self.debit, self.precision("debit")) or flt(self.credit, self.precision("credit"))): frappe.throw(_("{0} {1}: Either debit or credit amount is required for {2}") .format(self.voucher_type, self.voucher_no, self.account)) @@ -74,7 +75,8 @@ class GLEntry(Document): def check_pl_account(self): if self.is_opening=='Yes' and \ - frappe.db.get_value("Account", self.account, "report_type")=="Profit and Loss": + frappe.db.get_value("Account", self.account, "report_type")=="Profit and Loss" and \ + self.voucher_type not in ['Purchase Invoice', 'Sales Invoice']: frappe.throw(_("{0} {1}: 'Profit and Loss' type account {2} not allowed in Opening Entry") .format(self.voucher_type, self.voucher_no, self.account)) @@ -215,17 +217,23 @@ def validate_frozen_account(account, adv_adj=None): def update_against_account(voucher_type, voucher_no): entries = frappe.db.get_all("GL Entry", filters={"voucher_type": voucher_type, "voucher_no": voucher_no}, - fields=["name", "party", "against", "debit", "credit", "account"]) + fields=["name", "party", "against", "debit", "credit", "account", "company"]) + + if not entries: + return + company_currency = erpnext.get_company_currency(entries[0].company) + precision = get_field_precision(frappe.get_meta("GL Entry") + .get_field("debit"), company_currency) accounts_debited, accounts_credited = [], [] for d in entries: - if flt(d.debit > 0): accounts_debited.append(d.party or d.account) - if flt(d.credit) > 0: accounts_credited.append(d.party or d.account) + if flt(d.debit, precision) > 0: accounts_debited.append(d.party or d.account) + if flt(d.credit, precision) > 0: accounts_credited.append(d.party or d.account) for d in entries: - if flt(d.debit > 0): + if flt(d.debit, precision) > 0: new_against = ", ".join(list(set(accounts_credited))) - if flt(d.credit > 0): + if flt(d.credit, precision) > 0: new_against = ", ".join(list(set(accounts_debited))) if d.against != new_against: diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py index 259172e4488..92342f4d7c8 100644 --- a/erpnext/accounts/doctype/journal_entry/journal_entry.py +++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py @@ -52,6 +52,7 @@ class JournalEntry(AccountsController): self.update_loan() self.update_inter_company_jv() + def get_title(self): return self.pay_to_recd_from or self.accounts[0].account diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.js b/erpnext/accounts/doctype/payment_entry/payment_entry.js index 30ae54b18b0..5707d154c19 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.js +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.js @@ -232,6 +232,13 @@ frappe.ui.form.on('Payment Entry', { }, party_type: function(frm) { + + let party_types = Object.keys(frappe.boot.party_account_types); + if(frm.doc.party_type && !party_types.includes(frm.doc.party_type)){ + frm.set_value("party_type", ""); + frappe.throw(__("Party can only be one of "+ party_types.join(", "))); + } + if(frm.doc.party) { $.each(["party", "party_balance", "paid_from", "paid_to", "paid_from_account_currency", "paid_from_account_balance", diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.json b/erpnext/accounts/doctype/payment_entry/payment_entry.json index 9354c61addb..96e1e1eb162 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.json +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.json @@ -1,2200 +1,2264 @@ { - "allow_copy": 0, - "allow_events_in_timeline": 0, - "allow_guest_to_view": 0, - "allow_import": 1, - "allow_rename": 0, - "autoname": "naming_series:", - "beta": 0, - "creation": "2016-06-01 14:38:51.012597", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "", - "editable_grid": 0, + "allow_copy": 0, + "allow_events_in_timeline": 0, + "allow_guest_to_view": 0, + "allow_import": 1, + "allow_rename": 0, + "autoname": "naming_series:", + "beta": 0, + "creation": "2016-06-01 14:38:51.012597", + "custom": 0, + "docstatus": 0, + "doctype": "DocType", + "document_type": "", + "editable_grid": 0, "fields": [ { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "type_of_payment", - "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": "Type of Payment", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "type_of_payment", + "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": "Type of Payment", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 1, - "collapsible": 0, - "columns": 0, - "default": "", - "fieldname": "naming_series", - "fieldtype": "Select", - "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": "Series", - "length": 0, - "no_copy": 0, - "options": "ACC-PAY-.YYYY.-", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "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": 1, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 1, + "collapsible": 0, + "columns": 0, + "default": "", + "fetch_if_empty": 0, + "fieldname": "naming_series", + "fieldtype": "Select", + "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": "Series", + "length": 0, + "no_copy": 0, + "options": "ACC-PAY-.YYYY.-", + "permlevel": 0, + "precision": "", + "print_hide": 1, + "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": 1, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 1, - "collapsible": 0, - "columns": 0, - "fieldname": "payment_type", - "fieldtype": "Select", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 1, - "label": "Payment Type", - "length": 0, - "no_copy": 0, - "options": "Receive\nPay\nInternal Transfer", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 1, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "payment_type", + "fieldtype": "Select", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 1, + "in_standard_filter": 1, + "label": "Payment Type", + "length": 0, + "no_copy": 0, + "options": "Receive\nPay\nInternal Transfer", + "permlevel": 0, + "precision": "", + "print_hide": 1, + "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": "column_break_5", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "column_break_5", + "fieldtype": "Column Break", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 1, - "collapsible": 0, - "columns": 0, - "default": "Today", - "fieldname": "posting_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": "Posting Date", - "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": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 1, + "collapsible": 0, + "columns": 0, + "default": "Today", + "fetch_if_empty": 0, + "fieldname": "posting_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": "Posting Date", + "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": 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": "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, - "options": "Company", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 1, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 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, + "options": "Company", + "permlevel": 0, + "precision": "", + "print_hide": 1, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 1, + "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": "cost_center", - "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": "Cost Center", - "length": 0, - "no_copy": 0, - "options": "Cost Center", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "cost_center", + "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": "Cost Center", + "length": 0, + "no_copy": 0, + "options": "Cost Center", + "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": "mode_of_payment", - "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": "Mode of Payment", - "length": 0, - "no_copy": 0, - "options": "Mode of Payment", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "mode_of_payment", + "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": "Mode of Payment", + "length": 0, + "no_copy": 0, + "options": "Mode of Payment", + "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, - "depends_on": "eval:in_list([\"Receive\", \"Pay\"], doc.payment_type)", - "fieldname": "party_section", - "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": "Payment From / To", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "eval:in_list([\"Receive\", \"Pay\"], doc.payment_type)", + "fetch_if_empty": 0, + "fieldname": "party_section", + "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": "Payment From / To", + "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, - "default": "", - "depends_on": "eval:in_list([\"Receive\", \"Pay\"], doc.payment_type) && doc.docstatus==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": 1, - "label": "Party Type", - "length": 0, - "no_copy": 0, - "options": "DocType", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 1, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "default": "", + "depends_on": "eval:in_list([\"Receive\", \"Pay\"], doc.payment_type) && doc.docstatus==0", + "fetch_if_empty": 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": 1, + "label": "Party Type", + "length": 0, + "no_copy": 0, + "options": "DocType", + "permlevel": 0, + "precision": "", + "print_hide": 1, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 1, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 1, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:in_list([\"Receive\", \"Pay\"], doc.payment_type) && doc.party_type", - "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": 1, - "label": "Party", - "length": 0, - "no_copy": 0, - "options": "party_type", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 1, + "collapsible": 0, + "columns": 0, + "depends_on": "eval:in_list([\"Receive\", \"Pay\"], doc.payment_type) && doc.party_type", + "fetch_if_empty": 0, + "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": 1, + "label": "Party", + "length": 0, + "no_copy": 0, + "options": "party_type", + "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": 1, - "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", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 1, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Party Name", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 1, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "eval:in_list([\"Receive\", \"Pay\"], doc.payment_type) && doc.party_type", + "description": "", + "fetch_if_empty": 0, + "fieldname": "party_name", + "fieldtype": "Data", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 1, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Party Name", + "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": "column_break_11", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "column_break_11", + "fieldtype": "Column Break", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "party", - "fieldname": "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": "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "party", + "fetch_if_empty": 0, + "fieldname": "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": "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, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "contact_person", - "fieldname": "contact_email", - "fieldtype": "Data", - "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": "Email", - "length": 0, - "no_copy": 0, - "options": "Email", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "party", + "fetch_if_empty": 0, + "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, - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "contact_person", + "fetch_if_empty": 0, + "fieldname": "contact_email", + "fieldtype": "Data", + "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": "Email", + "length": 0, + "no_copy": 0, + "options": "Email", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 1, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 1, - "columns": 0, - "fieldname": "payment_accounts_section", - "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": "Accounts", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 1, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "payment_accounts_section", + "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": "Accounts", + "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, - "depends_on": "party", - "fieldname": "party_balance", - "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": "Party Balance", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "party", + "fetch_if_empty": 0, + "fieldname": "party_balance", + "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": "Party Balance", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 1, + "print_hide_if_no_value": 0, + "read_only": 1, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 1, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:(in_list([\"Internal Transfer\", \"Pay\"], doc.payment_type) || doc.party)", - "fieldname": "paid_from", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 1, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Account Paid From", - "length": 0, - "no_copy": 0, - "options": "Account", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 1, + "collapsible": 0, + "columns": 0, + "depends_on": "eval:(in_list([\"Internal Transfer\", \"Pay\"], doc.payment_type) || doc.party)", + "fetch_if_empty": 0, + "fieldname": "paid_from", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 1, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Account Paid From", + "length": 0, + "no_copy": 0, + "options": "Account", + "permlevel": 0, + "precision": "", + "print_hide": 1, + "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": "paid_from", - "fieldname": "paid_from_account_currency", - "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": "Account Currency", - "length": 0, - "no_copy": 0, - "options": "Currency", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "paid_from", + "fetch_if_empty": 0, + "fieldname": "paid_from_account_currency", + "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": "Account Currency", + "length": 0, + "no_copy": 0, + "options": "Currency", + "permlevel": 0, + "precision": "", + "print_hide": 1, + "print_hide_if_no_value": 0, + "read_only": 1, + "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": "paid_from", - "fieldname": "paid_from_account_balance", - "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": "Account Balance", - "length": 0, - "no_copy": 0, - "options": "paid_from_account_currency", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "paid_from", + "fetch_if_empty": 0, + "fieldname": "paid_from_account_balance", + "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": "Account Balance", + "length": 0, + "no_copy": 0, + "options": "paid_from_account_currency", + "permlevel": 0, + "precision": "", + "print_hide": 1, + "print_hide_if_no_value": 0, + "read_only": 1, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_18", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "column_break_18", + "fieldtype": "Column Break", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:(in_list([\"Internal Transfer\", \"Receive\"], doc.payment_type) || doc.party)", - "fieldname": "paid_to", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 1, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Account Paid To", - "length": 0, - "no_copy": 0, - "options": "Account", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "eval:(in_list([\"Internal Transfer\", \"Receive\"], doc.payment_type) || doc.party)", + "fetch_if_empty": 0, + "fieldname": "paid_to", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 1, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Account Paid To", + "length": 0, + "no_copy": 0, + "options": "Account", + "permlevel": 0, + "precision": "", + "print_hide": 1, + "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": "paid_to", - "fieldname": "paid_to_account_currency", - "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": "Account Currency", - "length": 0, - "no_copy": 0, - "options": "Currency", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "paid_to", + "fetch_if_empty": 0, + "fieldname": "paid_to_account_currency", + "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": "Account Currency", + "length": 0, + "no_copy": 0, + "options": "Currency", + "permlevel": 0, + "precision": "", + "print_hide": 1, + "print_hide_if_no_value": 0, + "read_only": 1, + "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": "paid_to", - "fieldname": "paid_to_account_balance", - "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": "Account Balance", - "length": 0, - "no_copy": 0, - "options": "paid_to_account_currency", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "paid_to", + "fetch_if_empty": 0, + "fieldname": "paid_to_account_balance", + "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": "Account Balance", + "length": 0, + "no_copy": 0, + "options": "paid_to_account_currency", + "permlevel": 0, + "precision": "", + "print_hide": 1, + "print_hide_if_no_value": 0, + "read_only": 1, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "collapsible_depends_on": "", - "columns": 0, - "depends_on": "eval:(doc.paid_to && doc.paid_from)", - "fieldname": "payment_amounts_section", - "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": "Amount", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "collapsible_depends_on": "", + "columns": 0, + "depends_on": "eval:(doc.paid_to && doc.paid_from)", + "fetch_if_empty": 0, + "fieldname": "payment_amounts_section", + "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": "Amount", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 1, - "collapsible": 0, - "columns": 0, - "depends_on": "", - "fieldname": "paid_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": "Paid Amount", - "length": 0, - "no_copy": 0, - "options": "paid_from_account_currency", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 1, + "collapsible": 0, + "columns": 0, + "depends_on": "", + "fetch_if_empty": 0, + "fieldname": "paid_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": "Paid Amount", + "length": 0, + "no_copy": 0, + "options": "paid_from_account_currency", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 1, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "", - "fieldname": "source_exchange_rate", - "fieldtype": "Float", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Exchange Rate", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 1, - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "", + "fetch_if_empty": 0, + "fieldname": "source_exchange_rate", + "fieldtype": "Float", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Exchange Rate", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 1, + "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": "base_paid_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": "Paid Amount (Company Currency)", - "length": 0, - "no_copy": 0, - "options": "Company:company:default_currency", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "", + "fetch_if_empty": 0, + "fieldname": "base_paid_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": "Paid Amount (Company Currency)", + "length": 0, + "no_copy": 0, + "options": "Company:company:default_currency", + "permlevel": 0, + "precision": "", + "print_hide": 1, + "print_hide_if_no_value": 0, + "read_only": 1, + "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": "column_break_21", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "column_break_21", + "fieldtype": "Column Break", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 1, - "collapsible": 0, - "columns": 0, - "depends_on": "", - "fieldname": "received_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": "Received Amount", - "length": 0, - "no_copy": 0, - "options": "paid_to_account_currency", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 1, + "collapsible": 0, + "columns": 0, + "depends_on": "", + "fetch_if_empty": 0, + "fieldname": "received_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": "Received Amount", + "length": 0, + "no_copy": 0, + "options": "paid_to_account_currency", + "permlevel": 0, + "precision": "", + "print_hide": 1, + "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": "target_exchange_rate", - "fieldtype": "Float", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Exchange Rate", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 1, - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "", + "fetch_if_empty": 0, + "fieldname": "target_exchange_rate", + "fieldtype": "Float", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Exchange Rate", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 1, + "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": "base_received_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": "Received Amount (Company Currency)", - "length": 0, - "no_copy": 0, - "options": "Company:company:default_currency", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "", + "fetch_if_empty": 0, + "fieldname": "base_received_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": "Received Amount (Company Currency)", + "length": 0, + "no_copy": 0, + "options": "Company:company:default_currency", + "permlevel": 0, + "precision": "", + "print_hide": 1, + "print_hide_if_no_value": 0, + "read_only": 1, + "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": 1, - "collapsible_depends_on": "references", - "columns": 0, - "depends_on": "eval:(doc.party && doc.paid_from && doc.paid_to && doc.paid_amount && doc.received_amount)", - "fieldname": "section_break_14", - "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": "Reference", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 1, + "collapsible_depends_on": "references", + "columns": 0, + "depends_on": "eval:(doc.party && doc.paid_from && doc.paid_to && doc.paid_amount && doc.received_amount)", + "fetch_if_empty": 0, + "fieldname": "section_break_14", + "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": "Reference", + "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, - "default": "1", - "depends_on": "eval:in_list(['Pay', 'Receive'], doc.payment_type)", - "fieldname": "allocate_payment_amount", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Allocate Payment Amount", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "default": "1", + "depends_on": "eval:in_list(['Pay', 'Receive'], doc.payment_type)", + "fetch_if_empty": 0, + "fieldname": "allocate_payment_amount", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Allocate Payment Amount", + "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, - "depends_on": "", - "fieldname": "references", - "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": "Payment References", - "length": 0, - "no_copy": 0, - "options": "Payment Entry Reference", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "", + "fetch_if_empty": 0, + "fieldname": "references", + "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": "Payment References", + "length": 0, + "no_copy": 0, + "options": "Payment Entry Reference", + "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, - "depends_on": "", - "fieldname": "section_break_34", - "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": "Writeoff", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "", + "fetch_if_empty": 0, + "fieldname": "section_break_34", + "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": "Writeoff", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 1, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:(doc.paid_amount && doc.received_amount && doc.references)", - "fieldname": "total_allocated_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": "Total Allocated Amount", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 1, + "collapsible": 0, + "columns": 0, + "depends_on": "eval:(doc.paid_amount && doc.received_amount && doc.references)", + "fetch_if_empty": 0, + "fieldname": "total_allocated_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": "Total Allocated Amount", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 1, + "print_hide_if_no_value": 0, + "read_only": 1, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "", - "fieldname": "base_total_allocated_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": "Total Allocated Amount (Company Currency)", - "length": 0, - "no_copy": 0, - "options": "Company:company:default_currency", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "", + "fetch_if_empty": 0, + "fieldname": "base_total_allocated_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": "Total Allocated Amount (Company Currency)", + "length": 0, + "no_copy": 0, + "options": "Company:company:default_currency", + "permlevel": 0, + "precision": "", + "print_hide": 1, + "print_hide_if_no_value": 0, + "read_only": 1, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "set_exchange_gain_loss", - "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": "Set Exchange Gain / Loss", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "set_exchange_gain_loss", + "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": "Set Exchange Gain / Loss", + "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": "column_break_36", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "column_break_36", + "fieldtype": "Column Break", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:(doc.paid_amount && doc.received_amount && doc.references)", - "fieldname": "unallocated_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": "Unallocated Amount", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 1, - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "eval:(doc.paid_amount && doc.received_amount && doc.references)", + "fetch_if_empty": 0, + "fieldname": "unallocated_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": "Unallocated Amount", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 1, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 1, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:(doc.paid_amount && doc.received_amount)", - "fieldname": "difference_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": "Difference Amount (Company Currency)", - "length": 0, - "no_copy": 0, - "options": "Company:company:default_currency", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 1, + "collapsible": 0, + "columns": 0, + "depends_on": "eval:(doc.paid_amount && doc.received_amount)", + "fetch_if_empty": 0, + "fieldname": "difference_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": "Difference Amount (Company Currency)", + "length": 0, + "no_copy": 0, + "options": "Company:company:default_currency", + "permlevel": 0, + "precision": "", + "print_hide": 1, + "print_hide_if_no_value": 0, + "read_only": 1, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "difference_amount", - "fieldname": "write_off_difference_amount", - "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": "Write Off Difference Amount", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "difference_amount", + "fetch_if_empty": 0, + "fieldname": "write_off_difference_amount", + "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": "Write Off Difference Amount", + "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": 1, - "collapsible_depends_on": "deductions", - "columns": 0, - "depends_on": "eval:(doc.paid_amount && doc.received_amount)", - "fieldname": "deductions_or_loss_section", - "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": "Deductions or Loss", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 1, + "collapsible_depends_on": "deductions", + "columns": 0, + "depends_on": "eval:(doc.paid_amount && doc.received_amount)", + "fetch_if_empty": 0, + "fieldname": "deductions_or_loss_section", + "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": "Deductions or Loss", + "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": "deductions", - "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": "Payment Deductions or Loss", - "length": 0, - "no_copy": 0, - "options": "Payment Entry Deduction", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "deductions", + "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": "Payment Deductions or Loss", + "length": 0, + "no_copy": 0, + "options": "Payment Entry Deduction", + "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": "transaction_references", - "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": "Transaction ID", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "transaction_references", + "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": "Transaction ID", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 1, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:(doc.paid_from && doc.paid_to)", - "fieldname": "reference_no", - "fieldtype": "Data", - "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": "Cheque/Reference 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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 1, + "collapsible": 0, + "columns": 0, + "depends_on": "eval:(doc.paid_from && doc.paid_to)", + "fetch_if_empty": 0, + "fieldname": "reference_no", + "fieldtype": "Data", + "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": "Cheque/Reference 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, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_23", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "column_break_23", + "fieldtype": "Column Break", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 1, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:(doc.paid_from && doc.paid_to)", - "fieldname": "reference_date", - "fieldtype": "Date", - "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": "Cheque/Reference Date", - "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": 1, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 1, + "collapsible": 0, + "columns": 0, + "depends_on": "eval:(doc.paid_from && doc.paid_to)", + "fetch_if_empty": 0, + "fieldname": "reference_date", + "fieldtype": "Date", + "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": "Cheque/Reference Date", + "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": 1, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:doc.docstatus==1", - "fieldname": "clearance_date", - "fieldtype": "Date", - "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": "Clearance Date", - "length": 0, - "no_copy": 1, - "permlevel": 0, - "precision": "", - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "eval:doc.docstatus==1", + "fetch_if_empty": 0, + "fieldname": "clearance_date", + "fieldtype": "Date", + "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": "Clearance Date", + "length": 0, + "no_copy": 1, + "permlevel": 0, + "precision": "", + "print_hide": 1, + "print_hide_if_no_value": 0, + "read_only": 1, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 1, - "collapsible_depends_on": "", - "columns": 0, - "depends_on": "eval:(doc.paid_from && doc.paid_to && doc.paid_amount && doc.received_amount)", - "fieldname": "section_break_12", - "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": "More Information", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 1, + "collapsible_depends_on": "", + "columns": 0, + "depends_on": "eval:(doc.paid_from && doc.paid_to && doc.paid_amount && doc.received_amount)", + "fetch_if_empty": 0, + "fieldname": "section_break_12", + "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": "More Information", + "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, - "depends_on": "", - "fieldname": "project", - "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": "Project", - "length": 0, - "no_copy": 0, - "options": "Project", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "", + "fetch_if_empty": 0, + "fieldname": "project", + "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": "Project", + "length": 0, + "no_copy": 0, + "options": "Project", + "permlevel": 0, + "precision": "", + "print_hide": 1, + "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": "remarks", - "fieldtype": "Small Text", - "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": "Remarks", - "length": 0, - "no_copy": 1, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "remarks", + "fieldtype": "Small Text", + "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": "Remarks", + "length": 0, + "no_copy": 1, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 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": "column_break_16", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "column_break_16", + "fieldtype": "Column Break", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "letter_head", - "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": "Letter Head", - "length": 0, - "no_copy": 0, - "options": "Letter Head", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "letter_head", + "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": "Letter Head", + "length": 0, + "no_copy": 0, + "options": "Letter Head", + "permlevel": 0, + "precision": "", + "print_hide": 1, + "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": "print_heading", - "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": "Print Heading", - "length": 0, - "no_copy": 0, - "options": "Print Heading", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "print_heading", + "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": "Print Heading", + "length": 0, + "no_copy": 0, + "options": "Print Heading", + "permlevel": 0, + "precision": "", + "print_hide": 1, + "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", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_from": "bank_account.bank", + "fetch_if_empty": 0, + "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, + "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", + "fetch_if_empty": 0, + "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, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "payment_order", - "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": "Payment Order", - "length": 0, - "no_copy": 1, - "options": "Payment Order", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "payment_order", + "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": "Payment Order", + "length": 0, + "no_copy": 1, + "options": "Payment Order", + "permlevel": 0, + "precision": "", + "print_hide": 1, + "print_hide_if_no_value": 0, + "read_only": 1, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "subscription_section", - "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": "Subscription Section", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "subscription_section", + "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": "Subscription Section", + "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": 1, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "auto_repeat", - "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": "Auto Repeat", - "length": 0, - "no_copy": 1, - "options": "Auto Repeat", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 1, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "auto_repeat", + "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": "Auto Repeat", + "length": 0, + "no_copy": 1, + "options": "Auto Repeat", + "permlevel": 0, + "precision": "", + "print_hide": 1, + "print_hide_if_no_value": 0, + "read_only": 1, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "amended_from", - "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": "Amended From", - "length": 0, - "no_copy": 1, - "options": "Payment Entry", - "permlevel": 0, - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "amended_from", + "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": "Amended From", + "length": 0, + "no_copy": 1, + "options": "Payment Entry", + "permlevel": 0, + "print_hide": 1, + "print_hide_if_no_value": 0, + "read_only": 1, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "title", - "fieldtype": "Data", - "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Title", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 1, - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "title", + "fieldtype": "Data", + "hidden": 1, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Title", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 1, + "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 } - ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "idx": 0, - "image_view": 0, - "in_create": 0, - "is_submittable": 1, - "issingle": 0, - "istable": 0, - "max_attachments": 0, - "modified": "2019-01-15 15:58:40.742601", - "modified_by": "Administrator", - "module": "Accounts", - "name": "Payment Entry", - "name_case": "", - "owner": "Administrator", + ], + "has_web_view": 0, + "hide_heading": 0, + "hide_toolbar": 0, + "idx": 0, + "image_view": 0, + "in_create": 0, + "is_submittable": 1, + "issingle": 0, + "istable": 0, + "max_attachments": 0, + "modified": "2019-03-27 17:39:54.163016", + "modified_by": "Administrator", + "module": "Accounts", + "name": "Payment Entry", + "name_case": "", + "owner": "Administrator", "permissions": [ { - "amend": 1, - "cancel": 1, - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "if_owner": 0, - "import": 1, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "Accounts User", - "set_user_permissions": 0, - "share": 1, - "submit": 1, + "amend": 1, + "cancel": 1, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "if_owner": 0, + "import": 1, + "permlevel": 0, + "print": 1, + "read": 1, + "report": 1, + "role": "Accounts User", + "set_user_permissions": 0, + "share": 1, + "submit": 1, "write": 1 - }, + }, { - "amend": 1, - "cancel": 1, - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "if_owner": 0, - "import": 1, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "Accounts Manager", - "set_user_permissions": 0, - "share": 1, - "submit": 1, + "amend": 1, + "cancel": 1, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "if_owner": 0, + "import": 1, + "permlevel": 0, + "print": 1, + "read": 1, + "report": 1, + "role": "Accounts Manager", + "set_user_permissions": 0, + "share": 1, + "submit": 1, "write": 1 } - ], - "quick_entry": 0, - "read_only": 0, - "read_only_onload": 0, - "show_name_in_global_search": 1, - "sort_field": "modified", - "sort_order": "DESC", - "title_field": "title", - "track_changes": 1, - "track_seen": 0, + ], + "quick_entry": 0, + "read_only": 0, + "read_only_onload": 0, + "show_name_in_global_search": 1, + "sort_field": "modified", + "sort_order": "DESC", + "title_field": "title", + "track_changes": 1, + "track_seen": 0, "track_views": 0 } \ No newline at end of file diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py index f303301a33a..443c8fb9805 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py @@ -6,7 +6,7 @@ from __future__ import unicode_literals import frappe, erpnext, json from frappe import _, scrub, ValidationError from frappe.utils import flt, comma_or, nowdate, getdate -from erpnext.accounts.utils import get_outstanding_invoices, get_account_currency, get_balance_on +from erpnext.accounts.utils import get_outstanding_invoices, get_account_currency, get_balance_on, get_allow_cost_center_in_entry_of_bs_account from erpnext.accounts.party import get_party_account from erpnext.accounts.doctype.journal_entry.journal_entry import get_default_bank_cash_account from erpnext.setup.utils import get_exchange_rate @@ -70,6 +70,7 @@ class PaymentEntry(AccountsController): self.update_advance_paid() self.update_expense_claim() + def on_cancel(self): self.setup_party_account_field() self.make_gl_entries(cancel=1) @@ -564,8 +565,8 @@ def get_outstanding_reference_documents(args): .format(frappe.db.escape(args["voucher_type"]), frappe.db.escape(args["voucher_no"])) # Add cost center condition - if args.get("cost_center"): - condition += " and cost_center='%s'" % args.get("cost_center") + if args.get("cost_center") and get_allow_cost_center_in_entry_of_bs_account(): + condition += " and cost_center='%s'" % args.get("cost_center") outstanding_invoices = get_outstanding_invoices(args.get("party_type"), args.get("party"), args.get("party_account"), condition=condition) @@ -748,7 +749,7 @@ def get_outstanding_on_journal_entry(name): @frappe.whitelist() def get_reference_details(reference_doctype, reference_name, party_account_currency): - total_amount = outstanding_amount = exchange_rate = None + total_amount = outstanding_amount = exchange_rate = bill_no = None ref_doc = frappe.get_doc(reference_doctype, reference_name) company_currency = ref_doc.get("company_currency") or erpnext.get_company_currency(ref_doc.company) @@ -782,6 +783,7 @@ def get_reference_details(reference_doctype, reference_name, party_account_curre if reference_doctype in ("Sales Invoice", "Purchase Invoice"): outstanding_amount = ref_doc.get("outstanding_amount") + bill_no = ref_doc.get("bill_no") elif reference_doctype == "Expense Claim": outstanding_amount = flt(ref_doc.get("total_sanctioned_amount")) \ - flt(ref_doc.get("total_amount+reimbursed")) - flt(ref_doc.get("total_advance_amount")) @@ -798,7 +800,8 @@ def get_reference_details(reference_doctype, reference_name, party_account_curre "due_date": ref_doc.get("due_date"), "total_amount": total_amount, "outstanding_amount": outstanding_amount, - "exchange_rate": exchange_rate + "exchange_rate": exchange_rate, + "bill_no": bill_no }) diff --git a/erpnext/accounts/doctype/payment_request/payment_request.py b/erpnext/accounts/doctype/payment_request/payment_request.py index 014efd948c4..64c4124da66 100644 --- a/erpnext/accounts/doctype/payment_request/payment_request.py +++ b/erpnext/accounts/doctype/payment_request/payment_request.py @@ -214,9 +214,10 @@ class PaymentRequest(Document): def check_if_payment_entry_exists(self): if self.status == "Paid": - payment_entry = frappe.db.sql_list("""select parent from `tabPayment Entry Reference` - where reference_name=%s""", self.reference_name) - if payment_entry: + if frappe.get_all("Payment Entry Reference", + filters={"reference_name": self.reference_name, "docstatus": ["<", 2]}, + fields=["parent"], + limit=1): frappe.throw(_("Payment Entry already exists"), title=_('Error')) def make_communication_entry(self): diff --git a/erpnext/accounts/doctype/payment_terms_template/payment_terms_template.js b/erpnext/accounts/doctype/payment_terms_template/payment_terms_template.js index 558297fea76..f5c5bca87a7 100644 --- a/erpnext/accounts/doctype/payment_terms_template/payment_terms_template.js +++ b/erpnext/accounts/doctype/payment_terms_template/payment_terms_template.js @@ -8,5 +8,6 @@ frappe.ui.form.on('Payment Terms Template', { frm.add_fetch("payment_term", "due_date_based_on", "due_date_based_on"); frm.add_fetch("payment_term", "credit_days", "credit_days"); frm.add_fetch("payment_term", "credit_months", "credit_months"); + frm.add_fetch("payment_term", "mode_of_payment", "mode_of_payment"); } }); diff --git a/erpnext/accounts/doctype/pos_profile/pos_profile.js b/erpnext/accounts/doctype/pos_profile/pos_profile.js index 13d53d1f6ab..a6386ddc4bf 100755 --- a/erpnext/accounts/doctype/pos_profile/pos_profile.js +++ b/erpnext/accounts/doctype/pos_profile/pos_profile.js @@ -33,6 +33,14 @@ frappe.ui.form.on('POS Profile', { }; }); + frm.set_query("account_for_change_amount", function() { + return { + filters: { + account_type: ['in', ["Cash", "Bank"]] + } + }; + }); + frm.set_query("print_format", function() { return { filters: { doc_type: "Sales Invoice", print_format_type: "Js"} }; }); diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js index b4fd91f6e43..97b60365f88 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js @@ -468,7 +468,7 @@ cur_frm.fields_dict["items"].grid.get_field("cost_center").get_query = function( cur_frm.cscript.cost_center = function(doc, cdt, cdn){ var d = locals[cdt][cdn]; - if(d.idx == 1 && d.cost_center){ + if(d.cost_center){ var cl = doc.items || []; for(var i = 0; i < cl.length; i++){ if(!cl[i].cost_center) cl[i].cost_center = d.cost_center; @@ -510,6 +510,15 @@ frappe.ui.form.on("Purchase Invoice", { } } } + + frm.set_query("cost_center", function() { + return { + filters: { + company: frm.doc.company, + is_group: 0 + } + }; + }); }, onload: function(frm) { diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json index 41b3c13a3b9..9ee9c1ecc86 100755 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json @@ -21,6 +21,7 @@ "collapsible": 0, "columns": 0, "default": "{supplier_name}", + "fetch_if_empty": 0, "fieldname": "title", "fieldtype": "Data", "hidden": 1, @@ -54,6 +55,7 @@ "collapsible": 0, "columns": 0, "default": "", + "fetch_if_empty": 0, "fieldname": "naming_series", "fieldtype": "Select", "hidden": 0, @@ -88,6 +90,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "supplier", "fieldtype": "Link", "hidden": 0, @@ -124,6 +127,7 @@ "columns": 0, "depends_on": "supplier", "fetch_from": "supplier.supplier_name", + "fetch_if_empty": 0, "fieldname": "supplier_name", "fieldtype": "Data", "hidden": 0, @@ -159,6 +163,7 @@ "collapsible": 0, "columns": 0, "fetch_from": "supplier.tax_id", + "fetch_if_empty": 0, "fieldname": "tax_id", "fieldtype": "Read Only", "hidden": 0, @@ -192,6 +197,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "due_date", "fieldtype": "Date", "hidden": 0, @@ -225,6 +231,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "is_paid", "fieldtype": "Check", "hidden": 0, @@ -258,6 +265,7 @@ "collapsible": 0, "columns": 0, "default": "0", + "fetch_if_empty": 0, "fieldname": "is_return", "fieldtype": "Check", "hidden": 0, @@ -291,6 +299,7 @@ "collapsible": 0, "columns": 0, "default": "", + "fetch_if_empty": 0, "fieldname": "apply_tds", "fieldtype": "Check", "hidden": 0, @@ -323,6 +332,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break1", "fieldtype": "Column Break", "hidden": 0, @@ -355,6 +365,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "company", "fieldtype": "Link", "hidden": 0, @@ -387,6 +398,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "cost_center", "fieldtype": "Link", "hidden": 0, @@ -421,6 +433,7 @@ "collapsible": 0, "columns": 0, "default": "Today", + "fetch_if_empty": 0, "fieldname": "posting_date", "fieldtype": "Date", "hidden": 0, @@ -454,6 +467,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "posting_time", "fieldtype": "Time", "hidden": 0, @@ -489,6 +503,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval:doc.docstatus==0", + "fetch_if_empty": 0, "fieldname": "set_posting_time", "fieldtype": "Check", "hidden": 0, @@ -521,6 +536,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "amended_from", "fieldtype": "Link", "hidden": 0, @@ -556,6 +572,7 @@ "collapsible": 1, "collapsible_depends_on": "eval:doc.on_hold", "columns": 0, + "fetch_if_empty": 0, "fieldname": "sb_14", "fieldtype": "Section Break", "hidden": 0, @@ -589,6 +606,7 @@ "collapsible": 0, "columns": 0, "default": "0", + "fetch_if_empty": 0, "fieldname": "on_hold", "fieldtype": "Check", "hidden": 0, @@ -623,6 +641,7 @@ "columns": 0, "depends_on": "eval:doc.on_hold", "description": "Once set, this invoice will be on hold till the set date", + "fetch_if_empty": 0, "fieldname": "release_date", "fieldtype": "Date", "hidden": 0, @@ -655,6 +674,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "cb_17", "fieldtype": "Column Break", "hidden": 0, @@ -687,6 +707,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval:doc.on_hold", + "fetch_if_empty": 0, "fieldname": "hold_comment", "fieldtype": "Small Text", "hidden": 0, @@ -720,6 +741,7 @@ "collapsible": 1, "collapsible_depends_on": "bill_no", "columns": 0, + "fetch_if_empty": 0, "fieldname": "supplier_invoice_details", "fieldtype": "Section Break", "hidden": 0, @@ -753,6 +775,7 @@ "collapsible": 0, "columns": 0, "description": "", + "fetch_if_empty": 0, "fieldname": "bill_no", "fieldtype": "Data", "hidden": 0, @@ -786,6 +809,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break_15", "fieldtype": "Column Break", "hidden": 0, @@ -817,6 +841,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "bill_date", "fieldtype": "Date", "hidden": 0, @@ -851,6 +876,7 @@ "collapsible": 0, "columns": 0, "depends_on": "return_against", + "fetch_if_empty": 0, "fieldname": "returns", "fieldtype": "Section Break", "hidden": 0, @@ -884,6 +910,7 @@ "collapsible": 0, "columns": 0, "depends_on": "return_against", + "fetch_if_empty": 0, "fieldname": "return_against", "fieldtype": "Link", "hidden": 0, @@ -917,6 +944,7 @@ "bold": 0, "collapsible": 1, "columns": 0, + "fetch_if_empty": 0, "fieldname": "section_addresses", "fieldtype": "Section Break", "hidden": 0, @@ -949,6 +977,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "supplier_address", "fieldtype": "Link", "hidden": 0, @@ -982,6 +1011,7 @@ "collapsible": 0, "columns": 0, "depends_on": "", + "fetch_if_empty": 0, "fieldname": "address_display", "fieldtype": "Small Text", "hidden": 0, @@ -1013,6 +1043,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "contact_person", "fieldtype": "Link", "hidden": 0, @@ -1045,6 +1076,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "contact_display", "fieldtype": "Small Text", "hidden": 0, @@ -1076,6 +1108,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "contact_mobile", "fieldtype": "Small Text", "hidden": 0, @@ -1107,6 +1140,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "contact_email", "fieldtype": "Small Text", "hidden": 0, @@ -1138,6 +1172,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "col_break_address", "fieldtype": "Column Break", "hidden": 0, @@ -1170,6 +1205,7 @@ "collapsible": 0, "columns": 0, "depends_on": "", + "fetch_if_empty": 0, "fieldname": "shipping_address", "fieldtype": "Link", "hidden": 0, @@ -1203,6 +1239,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "shipping_address_display", "fieldtype": "Small Text", "hidden": 0, @@ -1235,6 +1272,7 @@ "bold": 0, "collapsible": 1, "columns": 0, + "fetch_if_empty": 0, "fieldname": "currency_and_price_list", "fieldtype": "Section Break", "hidden": 0, @@ -1267,6 +1305,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "currency", "fieldtype": "Link", "hidden": 0, @@ -1302,6 +1341,7 @@ "collapsible": 0, "columns": 0, "description": "", + "fetch_if_empty": 0, "fieldname": "conversion_rate", "fieldtype": "Float", "hidden": 0, @@ -1336,6 +1376,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break2", "fieldtype": "Column Break", "hidden": 0, @@ -1366,6 +1407,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "buying_price_list", "fieldtype": "Link", "hidden": 0, @@ -1398,6 +1440,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "price_list_currency", "fieldtype": "Link", "hidden": 0, @@ -1430,6 +1473,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "plc_conversion_rate", "fieldtype": "Float", "hidden": 0, @@ -1462,6 +1506,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "ignore_pricing_rule", "fieldtype": "Check", "hidden": 0, @@ -1493,6 +1538,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "sec_warehouse", "fieldtype": "Section Break", "hidden": 0, @@ -1525,6 +1571,7 @@ "collapsible": 0, "columns": 0, "depends_on": "update_stock", + "fetch_if_empty": 0, "fieldname": "set_warehouse", "fieldtype": "Link", "hidden": 0, @@ -1560,6 +1607,7 @@ "columns": 0, "depends_on": "update_stock", "description": "Warehouse where you are maintaining stock of rejected items", + "fetch_if_empty": 0, "fieldname": "rejected_warehouse", "fieldtype": "Link", "hidden": 0, @@ -1593,6 +1641,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "col_break_warehouse", "fieldtype": "Column Break", "hidden": 0, @@ -1625,6 +1674,7 @@ "collapsible": 0, "columns": 0, "default": "No", + "fetch_if_empty": 0, "fieldname": "is_subcontracted", "fieldtype": "Select", "hidden": 0, @@ -1659,6 +1709,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval:doc.is_subcontracted==\"Yes\"", + "fetch_if_empty": 0, "fieldname": "supplier_warehouse", "fieldtype": "Link", "hidden": 0, @@ -1694,6 +1745,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "items_section", "fieldtype": "Section Break", "hidden": 0, @@ -1728,6 +1780,7 @@ "collapsible": 0, "columns": 0, "default": "0", + "fetch_if_empty": 0, "fieldname": "update_stock", "fieldtype": "Check", "hidden": 0, @@ -1760,6 +1813,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "scan_barcode", "fieldtype": "Data", "hidden": 0, @@ -1792,6 +1846,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "items", "fieldtype": "Table", "hidden": 0, @@ -1828,6 +1883,7 @@ "collapsible_depends_on": "supplied_items", "columns": 0, "depends_on": "", + "fetch_if_empty": 0, "fieldname": "raw_materials_supplied", "fieldtype": "Section Break", "hidden": 0, @@ -1860,6 +1916,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "supplied_items", "fieldtype": "Table", "hidden": 0, @@ -1893,6 +1950,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "section_break_26", "fieldtype": "Section Break", "hidden": 0, @@ -1923,6 +1981,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "total_qty", "fieldtype": "Float", "hidden": 0, @@ -1955,6 +2014,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "base_total", "fieldtype": "Currency", "hidden": 0, @@ -1989,6 +2049,7 @@ "collapsible": 0, "columns": 0, "description": "", + "fetch_if_empty": 0, "fieldname": "base_net_total", "fieldtype": "Currency", "hidden": 0, @@ -2023,6 +2084,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break_28", "fieldtype": "Column Break", "hidden": 0, @@ -2053,6 +2115,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "total", "fieldtype": "Currency", "hidden": 0, @@ -2086,6 +2149,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "net_total", "fieldtype": "Currency", "hidden": 0, @@ -2120,6 +2184,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "total_net_weight", "fieldtype": "Float", "hidden": 0, @@ -2152,6 +2217,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "taxes_section", "fieldtype": "Section Break", "hidden": 0, @@ -2185,6 +2251,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "taxes_and_charges", "fieldtype": "Link", "hidden": 0, @@ -2219,6 +2286,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break_49", "fieldtype": "Column Break", "hidden": 0, @@ -2250,6 +2318,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "shipping_rule", "fieldtype": "Link", "hidden": 0, @@ -2283,6 +2352,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "section_break_51", "fieldtype": "Section Break", "hidden": 0, @@ -2314,6 +2384,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "taxes", "fieldtype": "Table", "hidden": 0, @@ -2348,6 +2419,7 @@ "bold": 0, "collapsible": 1, "columns": 0, + "fetch_if_empty": 0, "fieldname": "sec_tax_breakup", "fieldtype": "Section Break", "hidden": 0, @@ -2380,6 +2452,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "other_charges_calculation", "fieldtype": "Text", "hidden": 0, @@ -2412,6 +2485,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "totals", "fieldtype": "Section Break", "hidden": 0, @@ -2445,6 +2519,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "base_taxes_and_charges_added", "fieldtype": "Currency", "hidden": 0, @@ -2479,6 +2554,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "base_taxes_and_charges_deducted", "fieldtype": "Currency", "hidden": 0, @@ -2513,6 +2589,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "base_total_taxes_and_charges", "fieldtype": "Currency", "hidden": 0, @@ -2547,6 +2624,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break_40", "fieldtype": "Column Break", "hidden": 0, @@ -2578,6 +2656,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "taxes_and_charges_added", "fieldtype": "Currency", "hidden": 0, @@ -2612,6 +2691,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "taxes_and_charges_deducted", "fieldtype": "Currency", "hidden": 0, @@ -2646,6 +2726,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "total_taxes_and_charges", "fieldtype": "Currency", "hidden": 0, @@ -2680,6 +2761,7 @@ "collapsible": 1, "collapsible_depends_on": "discount_amount", "columns": 0, + "fetch_if_empty": 0, "fieldname": "section_break_44", "fieldtype": "Section Break", "hidden": 0, @@ -2713,6 +2795,7 @@ "collapsible": 0, "columns": 0, "default": "Grand Total", + "fetch_if_empty": 0, "fieldname": "apply_discount_on", "fieldtype": "Select", "hidden": 0, @@ -2746,6 +2829,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "base_discount_amount", "fieldtype": "Currency", "hidden": 0, @@ -2779,6 +2863,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break_46", "fieldtype": "Column Break", "hidden": 0, @@ -2810,6 +2895,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "additional_discount_percentage", "fieldtype": "Float", "hidden": 0, @@ -2842,6 +2928,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "discount_amount", "fieldtype": "Currency", "hidden": 0, @@ -2875,6 +2962,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "section_break_49", "fieldtype": "Section Break", "hidden": 0, @@ -2906,6 +2994,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "base_grand_total", "fieldtype": "Currency", "hidden": 0, @@ -2940,6 +3029,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "base_rounding_adjustment", "fieldtype": "Currency", "hidden": 0, @@ -2974,6 +3064,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval:!doc.disable_rounded_total", + "fetch_if_empty": 0, "fieldname": "base_rounded_total", "fieldtype": "Currency", "hidden": 0, @@ -3008,6 +3099,7 @@ "collapsible": 0, "columns": 0, "description": "", + "fetch_if_empty": 0, "fieldname": "base_in_words", "fieldtype": "Data", "hidden": 0, @@ -3041,6 +3133,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break8", "fieldtype": "Column Break", "hidden": 0, @@ -3073,6 +3166,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "grand_total", "fieldtype": "Currency", "hidden": 0, @@ -3107,6 +3201,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "rounding_adjustment", "fieldtype": "Currency", "hidden": 0, @@ -3141,6 +3236,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval:!doc.disable_rounded_total", + "fetch_if_empty": 0, "fieldname": "rounded_total", "fieldtype": "Currency", "hidden": 0, @@ -3174,6 +3270,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "in_words", "fieldtype": "Data", "hidden": 0, @@ -3207,6 +3304,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "total_advance", "fieldtype": "Currency", "hidden": 0, @@ -3241,6 +3339,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "outstanding_amount", "fieldtype": "Currency", "hidden": 0, @@ -3276,6 +3375,7 @@ "collapsible": 0, "columns": 0, "depends_on": "grand_total", + "fetch_if_empty": 0, "fieldname": "disable_rounded_total", "fieldtype": "Check", "hidden": 0, @@ -3310,6 +3410,7 @@ "collapsible_depends_on": "paid_amount", "columns": 0, "depends_on": "eval:doc.is_paid===1||(doc.advances && doc.advances.length>0)", + "fetch_if_empty": 0, "fieldname": "payments_section", "fieldtype": "Section Break", "hidden": 0, @@ -3342,6 +3443,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "mode_of_payment", "fieldtype": "Link", "hidden": 0, @@ -3375,6 +3477,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "cash_bank_account", "fieldtype": "Link", "hidden": 0, @@ -3408,6 +3511,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "col_br_payments", "fieldtype": "Column Break", "hidden": 0, @@ -3440,6 +3544,7 @@ "collapsible": 0, "columns": 0, "depends_on": "is_paid", + "fetch_if_empty": 0, "fieldname": "paid_amount", "fieldtype": "Currency", "hidden": 0, @@ -3473,6 +3578,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "base_paid_amount", "fieldtype": "Currency", "hidden": 0, @@ -3508,6 +3614,7 @@ "collapsible_depends_on": "write_off_amount", "columns": 0, "depends_on": "grand_total", + "fetch_if_empty": 0, "fieldname": "write_off", "fieldtype": "Section Break", "hidden": 0, @@ -3540,6 +3647,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "write_off_amount", "fieldtype": "Currency", "hidden": 0, @@ -3572,6 +3680,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "base_write_off_amount", "fieldtype": "Currency", "hidden": 0, @@ -3605,6 +3714,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break_61", "fieldtype": "Column Break", "hidden": 0, @@ -3637,6 +3747,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval:flt(doc.write_off_amount)!=0", + "fetch_if_empty": 0, "fieldname": "write_off_account", "fieldtype": "Link", "hidden": 0, @@ -3670,6 +3781,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval:flt(doc.write_off_amount)!=0", + "fetch_if_empty": 0, "fieldname": "write_off_cost_center", "fieldtype": "Link", "hidden": 0, @@ -3703,6 +3815,7 @@ "collapsible": 1, "collapsible_depends_on": "advances", "columns": 0, + "fetch_if_empty": 0, "fieldname": "advances_section", "fieldtype": "Section Break", "hidden": 0, @@ -3736,6 +3849,8 @@ "bold": 0, "collapsible": 0, "columns": 0, + "default": "1", + "fetch_if_empty": 0, "fieldname": "allocate_advances_automatically", "fieldtype": "Check", "hidden": 0, @@ -3769,6 +3884,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval:!doc.allocate_advances_automatically", + "fetch_if_empty": 0, "fieldname": "get_advances", "fieldtype": "Button", "hidden": 0, @@ -3802,6 +3918,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "advances", "fieldtype": "Table", "hidden": 0, @@ -3837,6 +3954,7 @@ "collapsible": 1, "collapsible_depends_on": "eval:(!doc.is_return)", "columns": 0, + "fetch_if_empty": 0, "fieldname": "payment_schedule_section", "fieldtype": "Section Break", "hidden": 0, @@ -3869,6 +3987,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "payment_terms_template", "fieldtype": "Link", "hidden": 0, @@ -3902,6 +4021,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "payment_schedule", "fieldtype": "Table", "hidden": 0, @@ -3936,6 +4056,7 @@ "collapsible": 1, "collapsible_depends_on": "terms", "columns": 0, + "fetch_if_empty": 0, "fieldname": "terms_section_break", "fieldtype": "Section Break", "hidden": 0, @@ -3968,6 +4089,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "tc_name", "fieldtype": "Link", "hidden": 0, @@ -4000,6 +4122,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "terms", "fieldtype": "Text Editor", "hidden": 0, @@ -4031,6 +4154,7 @@ "bold": 0, "collapsible": 1, "columns": 0, + "fetch_if_empty": 0, "fieldname": "printing_settings", "fieldtype": "Section Break", "hidden": 0, @@ -4063,6 +4187,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "letter_head", "fieldtype": "Link", "hidden": 0, @@ -4096,6 +4221,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "group_same_items", "fieldtype": "Check", "hidden": 0, @@ -4128,6 +4254,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break_112", "fieldtype": "Column Break", "hidden": 0, @@ -4159,6 +4286,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "select_print_heading", "fieldtype": "Link", "hidden": 0, @@ -4193,6 +4321,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "language", "fieldtype": "Data", "hidden": 0, @@ -4225,6 +4354,7 @@ "bold": 0, "collapsible": 1, "columns": 0, + "fetch_if_empty": 0, "fieldname": "more_info", "fieldtype": "Section Break", "hidden": 0, @@ -4259,6 +4389,7 @@ "collapsible": 0, "columns": 0, "description": "", + "fetch_if_empty": 0, "fieldname": "credit_to", "fieldtype": "Link", "hidden": 0, @@ -4293,6 +4424,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "party_account_currency", "fieldtype": "Link", "hidden": 1, @@ -4328,6 +4460,7 @@ "columns": 0, "default": "No", "description": "", + "fetch_if_empty": 0, "fieldname": "is_opening", "fieldtype": "Select", "hidden": 0, @@ -4362,6 +4495,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "against_expense_account", "fieldtype": "Small Text", "hidden": 1, @@ -4395,6 +4529,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break_63", "fieldtype": "Column Break", "hidden": 0, @@ -4426,6 +4561,7 @@ "collapsible": 0, "columns": 0, "default": "Draft", + "fetch_if_empty": 0, "fieldname": "status", "fieldtype": "Select", "hidden": 0, @@ -4459,6 +4595,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "inter_company_invoice_reference", "fieldtype": "Link", "hidden": 0, @@ -4492,6 +4629,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "remarks", "fieldtype": "Small Text", "hidden": 0, @@ -4525,6 +4663,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "subscription_section", "fieldtype": "Section Break", "hidden": 0, @@ -4559,6 +4698,7 @@ "columns": 0, "depends_on": "", "description": "Start date of current invoice's period", + "fetch_if_empty": 0, "fieldname": "from_date", "fieldtype": "Date", "hidden": 0, @@ -4592,6 +4732,7 @@ "columns": 0, "depends_on": "", "description": "End date of current invoice's period", + "fetch_if_empty": 0, "fieldname": "to_date", "fieldtype": "Date", "hidden": 0, @@ -4623,6 +4764,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break_114", "fieldtype": "Column Break", "hidden": 0, @@ -4654,6 +4796,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "auto_repeat", "fieldtype": "Link", "hidden": 0, @@ -4688,6 +4831,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval: doc.auto_repeat", + "fetch_if_empty": 0, "fieldname": "update_auto_repeat_reference", "fieldtype": "Button", "hidden": 0, @@ -4726,7 +4870,7 @@ "istable": 0, "max_attachments": 0, "menu_index": 0, - "modified": "2019-01-07 16:51:59.800081", + "modified": "2019-04-10 16:08:22.288425", "modified_by": "Administrator", "module": "Accounts", "name": "Purchase Invoice", diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py index 0dd716df3ff..450f2d0eb7b 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -8,6 +8,7 @@ from frappe.utils import cint, cstr, formatdate, flt, getdate, nowdate from frappe import _, throw import frappe.defaults +from erpnext.assets.doctype.asset_category.asset_category import get_asset_category_account from erpnext.controllers.buying_controller import BuyingController from erpnext.accounts.party import get_party_account, get_due_date from erpnext.accounts.utils import get_account_currency, get_fiscal_year @@ -17,7 +18,7 @@ from erpnext.accounts.general_ledger import make_gl_entries, merge_similar_entri from erpnext.accounts.doctype.gl_entry.gl_entry import update_outstanding_amt from erpnext.buying.utils import check_for_closed_status from erpnext.accounts.general_ledger import get_round_off_account_and_cost_center -from erpnext.assets.doctype.asset.asset import get_asset_account +from erpnext.assets.doctype.asset.asset import get_asset_account, is_cwip_accounting_disabled from frappe.model.mapper import get_mapped_doc from six import iteritems from erpnext.accounts.doctype.sales_invoice.sales_invoice import validate_inter_company_party, update_linked_invoice,\ @@ -46,6 +47,7 @@ class PurchaseInvoice(BuyingController): }] def onload(self): + super(PurchaseInvoice, self).onload() supplier_tds = frappe.db.get_value("Supplier", self.supplier, "tax_withholding_category") self.set_onload("supplier_tds", supplier_tds) @@ -53,6 +55,7 @@ class PurchaseInvoice(BuyingController): if not self.on_hold: self.release_date = '' + def invoice_is_blocked(self): return self.on_hold and (not self.release_date or self.release_date > getdate(nowdate())) @@ -215,7 +218,7 @@ class PurchaseInvoice(BuyingController): self.validate_item_code() self.validate_warehouse() if auto_accounting_for_stock: - warehouse_account = get_warehouse_account_map() + warehouse_account = get_warehouse_account_map(self.company) for item in self.get("items"): # in case of auto inventory accounting, @@ -231,6 +234,13 @@ class PurchaseInvoice(BuyingController): item.expense_account = warehouse_account[item.warehouse]["account"] else: item.expense_account = stock_not_billed_account + elif item.is_fixed_asset and is_cwip_accounting_disabled(): + if not item.asset: + frappe.throw(_("Row {0}: asset is required for item {1}") + .format(item.idx, item.item_code)) + + item.expense_account = get_asset_category_account(item.asset, 'fixed_asset_account', + company = self.company) elif item.is_fixed_asset and item.pr_detail: item.expense_account = asset_received_but_not_billed elif not item.expense_account and for_validate: @@ -359,7 +369,8 @@ class PurchaseInvoice(BuyingController): if repost_future_gle and cint(self.update_stock) and self.auto_accounting_for_stock: from erpnext.controllers.stock_controller import update_gl_entries_after items, warehouses = self.get_items_and_warehouses() - update_gl_entries_after(self.posting_date, self.posting_time, warehouses, items) + update_gl_entries_after(self.posting_date, self.posting_time, + warehouses, items, company = self.company) elif self.docstatus == 2 and cint(self.update_stock) and self.auto_accounting_for_stock: delete_gl_entries(voucher_type=self.doctype, voucher_no=self.name) @@ -376,7 +387,9 @@ class PurchaseInvoice(BuyingController): self.make_supplier_gl_entry(gl_entries) self.make_item_gl_entries(gl_entries) - self.get_asset_gl_entry(gl_entries) + if not is_cwip_accounting_disabled(): + self.get_asset_gl_entry(gl_entries) + self.make_tax_gl_entries(gl_entries) gl_entries = merge_similar_entries(gl_entries) @@ -416,7 +429,7 @@ class PurchaseInvoice(BuyingController): stock_items = self.get_stock_items() expenses_included_in_valuation = self.get_company_default("expenses_included_in_valuation") if self.update_stock and self.auto_accounting_for_stock: - warehouse_account = get_warehouse_account_map() + warehouse_account = get_warehouse_account_map(self.company) voucher_wise_stock_value = {} if self.update_stock: @@ -468,7 +481,7 @@ class PurchaseInvoice(BuyingController): "remarks": self.get("remarks") or _("Accounting Entry for Stock"), "credit": flt(item.rm_supp_cost) }, warehouse_account[self.supplier_warehouse]["account_currency"])) - elif not item.is_fixed_asset: + elif not item.is_fixed_asset or (item.is_fixed_asset and is_cwip_accounting_disabled()): gl_entries.append( self.get_gl_dict({ "account": item.expense_account if not item.enable_deferred_expense else item.deferred_expense_account, @@ -513,7 +526,7 @@ class PurchaseInvoice(BuyingController): base_asset_amount = flt(item.base_net_amount + item.item_tax_amount) if (not item.expense_account or frappe.db.get_value('Account', - item.expense_account, 'account_type') != 'Asset Received But Not Billed'): + item.expense_account, 'account_type') not in ['Asset Received But Not Billed', 'Fixed Asset']): arbnb_account = self.get_company_default("asset_received_but_not_billed") item.expense_account = arbnb_account diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py index c8c23c74e9c..dde12d79c7a 100644 --- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py @@ -344,6 +344,7 @@ class TestPurchaseInvoice(unittest.TestCase): pi = frappe.copy_doc(test_records[0]) pi.disable_rounded_total = 1 + pi.allocate_advances_automatically = 0 pi.append("advances", { "reference_type": "Journal Entry", "reference_name": jv.name, @@ -383,6 +384,7 @@ class TestPurchaseInvoice(unittest.TestCase): pi = frappe.copy_doc(test_records[0]) pi.disable_rounded_total = 1 + pi.allocate_advances_automatically = 0 pi.append("advances", { "reference_type": "Journal Entry", "reference_name": jv.name, @@ -551,7 +553,7 @@ class TestPurchaseInvoice(unittest.TestCase): sum(credit) as credit, debit_in_account_currency, credit_in_account_currency from `tabGL Entry` where voucher_type='Purchase Invoice' and voucher_no=%s group by account, voucher_no order by account asc;""", pi.name, as_dict=1) - + stock_in_hand_account = get_inventory_account(pi.company, pi.get("items")[0].warehouse) self.assertTrue(gl_entries) @@ -634,7 +636,7 @@ class TestPurchaseInvoice(unittest.TestCase): self.assertEqual(frappe.db.get_value("Serial No", pi.get("items")[0].rejected_serial_no, "warehouse"), pi.get("items")[0].rejected_warehouse) - + def test_outstanding_amount_after_advance_jv_cancelation(self): from erpnext.accounts.doctype.journal_entry.test_journal_entry \ import test_records as jv_test_records @@ -656,14 +658,14 @@ class TestPurchaseInvoice(unittest.TestCase): pi.insert() pi.submit() pi.load_from_db() - + #check outstanding after advance allocation self.assertEqual(flt(pi.outstanding_amount), flt(pi.rounded_total - pi.total_advance)) - + #added to avoid Document has been modified exception jv = frappe.get_doc("Journal Entry", jv.name) jv.cancel() - + pi.load_from_db() #check outstanding after advance cancellation self.assertEqual(flt(pi.outstanding_amount), flt(pi.rounded_total + pi.total_advance)) @@ -722,7 +724,7 @@ class TestPurchaseInvoice(unittest.TestCase): shipping_rule = create_shipping_rule(shipping_rule_type = "Buying", shipping_rule_name = "Shipping Rule - Purchase Invoice Test") pi = frappe.copy_doc(test_records[0]) - + pi.shipping_rule = shipping_rule.name pi.insert() @@ -740,14 +742,14 @@ class TestPurchaseInvoice(unittest.TestCase): "tax_amount": shipping_amount, "description": shipping_rule.name, "add_deduct_tax": "Add" - } + } pi.append("taxes", shipping_charge) pi.save() self.assertEqual(pi.net_total, 1250) self.assertEqual(pi.total_taxes_and_charges, 462.3) - self.assertEqual(pi.grand_total, 1712.3) + self.assertEqual(pi.grand_total, 1712.3) def test_make_pi_without_terms(self): pi = make_purchase_invoice(do_not_save=1) diff --git a/erpnext/accounts/doctype/sales_invoice/regional/italy.js b/erpnext/accounts/doctype/sales_invoice/regional/italy.js new file mode 100644 index 00000000000..1c47d3ab9fd --- /dev/null +++ b/erpnext/accounts/doctype/sales_invoice/regional/italy.js @@ -0,0 +1,3 @@ +{% include "erpnext/regional/italy/sales_invoice.js" %} + +erpnext.setup_e_invoice_button('Sales Invoice') \ No newline at end of file diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js index 8911ddf4645..0399cf95839 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js @@ -201,7 +201,8 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte get_query: function() { var filters = { docstatus: 1, - company: me.frm.doc.company + company: me.frm.doc.company, + is_return: 0 }; if(me.frm.doc.customer) filters["customer"] = me.frm.doc.customer; return { @@ -555,6 +556,23 @@ frappe.ui.form.on('Sales Invoice', { frm.add_fetch('payment_term', 'invoice_portion', 'invoice_portion'); frm.add_fetch('payment_term', 'description', 'description'); + frm.set_query("account_for_change_amount", function() { + return { + filters: { + account_type: ['in', ["Cash", "Bank"]] + } + }; + }); + + frm.set_query("cost_center", function() { + return { + filters: { + company: frm.doc.company, + is_group: 0 + } + }; + }); + frm.custom_make_buttons = { 'Delivery Note': 'Delivery', 'Sales Invoice': 'Sales Return', diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json index 077d99512ac..7f7e6f981a9 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json @@ -22,6 +22,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "customer_section", "fieldtype": "Section Break", "hidden": 0, @@ -55,6 +56,7 @@ "collapsible": 0, "columns": 0, "default": "{customer_name}", + "fetch_if_empty": 0, "fieldname": "title", "fieldtype": "Data", "hidden": 1, @@ -88,6 +90,7 @@ "collapsible": 0, "columns": 0, "default": "", + "fetch_if_empty": 0, "fieldname": "naming_series", "fieldtype": "Select", "hidden": 0, @@ -122,6 +125,7 @@ "bold": 1, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "customer", "fieldtype": "Link", "hidden": 0, @@ -158,6 +162,7 @@ "columns": 0, "depends_on": "customer", "fetch_from": "customer.customer_name", + "fetch_if_empty": 0, "fieldname": "customer_name", "fieldtype": "Data", "hidden": 0, @@ -192,6 +197,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "tax_id", "fieldtype": "Data", "hidden": 0, @@ -224,6 +230,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "project", "fieldtype": "Link", "hidden": 0, @@ -258,6 +265,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "is_pos", "fieldtype": "Check", "hidden": 0, @@ -292,6 +300,7 @@ "collapsible": 0, "columns": 0, "depends_on": "is_pos", + "fetch_if_empty": 0, "fieldname": "pos_profile", "fieldtype": "Link", "hidden": 0, @@ -325,6 +334,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "offline_pos_name", "fieldtype": "Data", "hidden": 1, @@ -358,6 +368,7 @@ "collapsible": 0, "columns": 0, "depends_on": "", + "fetch_if_empty": 0, "fieldname": "is_return", "fieldtype": "Check", "hidden": 0, @@ -390,6 +401,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break1", "fieldtype": "Column Break", "hidden": 0, @@ -421,6 +433,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "company", "fieldtype": "Link", "hidden": 0, @@ -455,6 +468,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "cost_center", "fieldtype": "Link", "hidden": 0, @@ -489,6 +503,7 @@ "collapsible": 0, "columns": 0, "default": "Today", + "fetch_if_empty": 0, "fieldname": "posting_date", "fieldtype": "Date", "hidden": 0, @@ -522,6 +537,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "posting_time", "fieldtype": "Time", "hidden": 0, @@ -556,6 +572,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval:doc.docstatus==0", + "fetch_if_empty": 0, "fieldname": "set_posting_time", "fieldtype": "Check", "hidden": 0, @@ -588,6 +605,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "due_date", "fieldtype": "Date", "hidden": 0, @@ -621,6 +639,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "amended_from", "fieldtype": "Link", "hidden": 0, @@ -656,6 +675,7 @@ "collapsible": 0, "columns": 0, "depends_on": "return_against", + "fetch_if_empty": 0, "fieldname": "returns", "fieldtype": "Section Break", "hidden": 0, @@ -689,6 +709,7 @@ "collapsible": 0, "columns": 0, "depends_on": "return_against", + "fetch_if_empty": 0, "fieldname": "return_against", "fieldtype": "Link", "hidden": 0, @@ -722,6 +743,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break_21", "fieldtype": "Column Break", "hidden": 0, @@ -754,6 +776,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval: doc.is_return && doc.return_against", + "fetch_if_empty": 0, "fieldname": "update_billed_amount_in_sales_order", "fieldtype": "Check", "hidden": 0, @@ -787,6 +810,7 @@ "collapsible": 1, "collapsible_depends_on": "po_no", "columns": 0, + "fetch_if_empty": 0, "fieldname": "customer_po_details", "fieldtype": "Section Break", "hidden": 0, @@ -819,6 +843,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "po_no", "fieldtype": "Data", "hidden": 0, @@ -851,6 +876,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break_23", "fieldtype": "Column Break", "hidden": 0, @@ -882,6 +908,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "po_date", "fieldtype": "Date", "hidden": 0, @@ -915,6 +942,7 @@ "collapsible": 1, "columns": 0, "depends_on": "", + "fetch_if_empty": 0, "fieldname": "address_and_contact", "fieldtype": "Section Break", "hidden": 0, @@ -947,6 +975,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "customer_address", "fieldtype": "Link", "hidden": 0, @@ -979,6 +1008,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "address_display", "fieldtype": "Small Text", "hidden": 0, @@ -1010,6 +1040,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "contact_person", "fieldtype": "Link", "hidden": 0, @@ -1042,6 +1073,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "contact_display", "fieldtype": "Small Text", "hidden": 0, @@ -1073,6 +1105,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "contact_mobile", "fieldtype": "Small Text", "hidden": 1, @@ -1104,6 +1137,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "contact_email", "fieldtype": "Data", "hidden": 1, @@ -1136,6 +1170,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "territory", "fieldtype": "Link", "hidden": 0, @@ -1169,6 +1204,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "col_break4", "fieldtype": "Column Break", "hidden": 0, @@ -1200,6 +1236,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "shipping_address_name", "fieldtype": "Link", "hidden": 0, @@ -1233,6 +1270,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "shipping_address", "fieldtype": "Small Text", "hidden": 0, @@ -1265,6 +1303,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "company_address", "fieldtype": "Link", "hidden": 0, @@ -1298,6 +1337,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "company_address_display", "fieldtype": "Small Text", "hidden": 1, @@ -1331,6 +1371,7 @@ "collapsible": 1, "columns": 0, "depends_on": "customer", + "fetch_if_empty": 0, "fieldname": "currency_and_price_list", "fieldtype": "Section Break", "hidden": 0, @@ -1363,6 +1404,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "currency", "fieldtype": "Link", "hidden": 0, @@ -1398,6 +1440,7 @@ "collapsible": 0, "columns": 0, "description": "Rate at which Customer Currency is converted to customer's base currency", + "fetch_if_empty": 0, "fieldname": "conversion_rate", "fieldtype": "Float", "hidden": 0, @@ -1432,6 +1475,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break2", "fieldtype": "Column Break", "hidden": 0, @@ -1463,6 +1507,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "selling_price_list", "fieldtype": "Link", "hidden": 0, @@ -1497,6 +1542,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "price_list_currency", "fieldtype": "Link", "hidden": 0, @@ -1530,6 +1576,7 @@ "collapsible": 0, "columns": 0, "description": "Rate at which Price list currency is converted to customer's base currency", + "fetch_if_empty": 0, "fieldname": "plc_conversion_rate", "fieldtype": "Float", "hidden": 0, @@ -1562,6 +1609,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "ignore_pricing_rule", "fieldtype": "Check", "hidden": 0, @@ -1593,6 +1641,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "sec_warehouse", "fieldtype": "Section Break", "hidden": 0, @@ -1625,6 +1674,7 @@ "collapsible": 0, "columns": 0, "depends_on": "update_stock", + "fetch_if_empty": 0, "fieldname": "set_warehouse", "fieldtype": "Link", "hidden": 0, @@ -1658,6 +1708,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "items_section", "fieldtype": "Section Break", "hidden": 0, @@ -1691,6 +1742,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "update_stock", "fieldtype": "Check", "hidden": 0, @@ -1724,6 +1776,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "scan_barcode", "fieldtype": "Data", "hidden": 0, @@ -1756,6 +1809,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "items", "fieldtype": "Table", "hidden": 0, @@ -1790,6 +1844,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "packing_list", "fieldtype": "Section Break", "hidden": 0, @@ -1822,6 +1877,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "packed_items", "fieldtype": "Table", "hidden": 0, @@ -1854,6 +1910,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "product_bundle_help", "fieldtype": "HTML", "hidden": 0, @@ -1887,6 +1944,7 @@ "collapsible_depends_on": "eval:doc.total_billing_amount > 0", "columns": 0, "depends_on": "", + "fetch_if_empty": 0, "fieldname": "time_sheet_list", "fieldtype": "Section Break", "hidden": 0, @@ -1919,6 +1977,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "timesheets", "fieldtype": "Table", "hidden": 0, @@ -1953,6 +2012,7 @@ "collapsible": 0, "columns": 0, "default": "0", + "fetch_if_empty": 0, "fieldname": "total_billing_amount", "fieldtype": "Currency", "hidden": 0, @@ -1985,6 +2045,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "section_break_30", "fieldtype": "Section Break", "hidden": 0, @@ -2015,6 +2076,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "total_qty", "fieldtype": "Float", "hidden": 0, @@ -2047,6 +2109,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "base_total", "fieldtype": "Currency", "hidden": 0, @@ -2080,6 +2143,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "base_net_total", "fieldtype": "Currency", "hidden": 0, @@ -2114,6 +2178,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break_32", "fieldtype": "Column Break", "hidden": 0, @@ -2144,6 +2209,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "total", "fieldtype": "Currency", "hidden": 0, @@ -2177,6 +2243,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "net_total", "fieldtype": "Currency", "hidden": 0, @@ -2209,6 +2276,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "total_net_weight", "fieldtype": "Float", "hidden": 0, @@ -2241,6 +2309,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "taxes_section", "fieldtype": "Section Break", "hidden": 0, @@ -2274,6 +2343,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "taxes_and_charges", "fieldtype": "Link", "hidden": 0, @@ -2308,6 +2378,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break_38", "fieldtype": "Column Break", "hidden": 0, @@ -2338,6 +2409,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "shipping_rule", "fieldtype": "Link", "hidden": 0, @@ -2371,6 +2443,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "section_break_40", "fieldtype": "Section Break", "hidden": 0, @@ -2401,6 +2474,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "taxes", "fieldtype": "Table", "hidden": 0, @@ -2435,6 +2509,7 @@ "bold": 0, "collapsible": 1, "columns": 0, + "fetch_if_empty": 0, "fieldname": "sec_tax_breakup", "fieldtype": "Section Break", "hidden": 0, @@ -2467,6 +2542,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "other_charges_calculation", "fieldtype": "Text", "hidden": 0, @@ -2499,6 +2575,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "section_break_43", "fieldtype": "Section Break", "hidden": 0, @@ -2529,6 +2606,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "base_total_taxes_and_charges", "fieldtype": "Currency", "hidden": 0, @@ -2563,6 +2641,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break_47", "fieldtype": "Column Break", "hidden": 0, @@ -2594,6 +2673,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "total_taxes_and_charges", "fieldtype": "Currency", "hidden": 0, @@ -2628,6 +2708,7 @@ "collapsible_depends_on": "", "columns": 0, "depends_on": "", + "fetch_if_empty": 0, "fieldname": "loyalty_points_redemption", "fieldtype": "Section Break", "hidden": 0, @@ -2661,6 +2742,7 @@ "collapsible": 0, "columns": 0, "depends_on": "redeem_loyalty_points", + "fetch_if_empty": 0, "fieldname": "loyalty_points", "fieldtype": "Int", "hidden": 0, @@ -2694,6 +2776,7 @@ "collapsible": 0, "columns": 0, "depends_on": "redeem_loyalty_points", + "fetch_if_empty": 0, "fieldname": "loyalty_amount", "fieldtype": "Currency", "hidden": 0, @@ -2727,6 +2810,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "redeem_loyalty_points", "fieldtype": "Check", "hidden": 0, @@ -2759,6 +2843,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break_77", "fieldtype": "Column Break", "hidden": 0, @@ -2792,6 +2877,7 @@ "columns": 0, "depends_on": "", "fetch_from": "customer.loyalty_program", + "fetch_if_empty": 0, "fieldname": "loyalty_program", "fieldtype": "Link", "hidden": 0, @@ -2826,6 +2912,7 @@ "collapsible": 0, "columns": 0, "depends_on": "redeem_loyalty_points", + "fetch_if_empty": 0, "fieldname": "loyalty_redemption_account", "fieldtype": "Link", "hidden": 0, @@ -2860,6 +2947,7 @@ "collapsible": 0, "columns": 0, "depends_on": "redeem_loyalty_points", + "fetch_if_empty": 0, "fieldname": "loyalty_redemption_cost_center", "fieldtype": "Link", "hidden": 0, @@ -2894,6 +2982,7 @@ "collapsible": 1, "collapsible_depends_on": "discount_amount", "columns": 0, + "fetch_if_empty": 0, "fieldname": "section_break_49", "fieldtype": "Section Break", "hidden": 0, @@ -2927,6 +3016,7 @@ "collapsible": 0, "columns": 0, "default": "Grand Total", + "fetch_if_empty": 0, "fieldname": "apply_discount_on", "fieldtype": "Select", "hidden": 0, @@ -2960,6 +3050,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "base_discount_amount", "fieldtype": "Currency", "hidden": 0, @@ -2993,6 +3084,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break_51", "fieldtype": "Column Break", "hidden": 0, @@ -3023,6 +3115,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "additional_discount_percentage", "fieldtype": "Float", "hidden": 0, @@ -3055,6 +3148,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "discount_amount", "fieldtype": "Currency", "hidden": 0, @@ -3087,6 +3181,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "totals", "fieldtype": "Section Break", "hidden": 0, @@ -3120,6 +3215,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "base_grand_total", "fieldtype": "Currency", "hidden": 0, @@ -3154,6 +3250,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "base_rounding_adjustment", "fieldtype": "Currency", "hidden": 0, @@ -3187,6 +3284,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "base_rounded_total", "fieldtype": "Currency", "hidden": 0, @@ -3222,6 +3320,7 @@ "collapsible": 0, "columns": 0, "description": "In Words will be visible once you save the Sales Invoice.", + "fetch_if_empty": 0, "fieldname": "base_in_words", "fieldtype": "Data", "hidden": 0, @@ -3255,6 +3354,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break5", "fieldtype": "Column Break", "hidden": 0, @@ -3287,6 +3387,7 @@ "bold": 1, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "grand_total", "fieldtype": "Currency", "hidden": 0, @@ -3321,6 +3422,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "rounding_adjustment", "fieldtype": "Currency", "hidden": 0, @@ -3354,6 +3456,7 @@ "bold": 1, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "rounded_total", "fieldtype": "Currency", "hidden": 0, @@ -3388,6 +3491,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "in_words", "fieldtype": "Data", "hidden": 0, @@ -3421,6 +3525,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "total_advance", "fieldtype": "Currency", "hidden": 0, @@ -3455,6 +3560,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "outstanding_amount", "fieldtype": "Currency", "hidden": 0, @@ -3490,6 +3596,7 @@ "collapsible": 1, "collapsible_depends_on": "advances", "columns": 0, + "fetch_if_empty": 0, "fieldname": "advances_section", "fieldtype": "Section Break", "hidden": 0, @@ -3523,6 +3630,8 @@ "bold": 0, "collapsible": 0, "columns": 0, + "default": "1", + "fetch_if_empty": 0, "fieldname": "allocate_advances_automatically", "fieldtype": "Check", "hidden": 0, @@ -3556,6 +3665,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval:!doc.allocate_advances_automatically", + "fetch_if_empty": 0, "fieldname": "get_advances", "fieldtype": "Button", "hidden": 0, @@ -3589,6 +3699,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "advances", "fieldtype": "Table", "hidden": 0, @@ -3624,6 +3735,7 @@ "collapsible": 1, "collapsible_depends_on": "eval:(!doc.is_pos && !doc.is_return)", "columns": 0, + "fetch_if_empty": 0, "fieldname": "payment_schedule_section", "fieldtype": "Section Break", "hidden": 0, @@ -3657,6 +3769,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval:(!doc.is_pos && !doc.is_return)", + "fetch_if_empty": 0, "fieldname": "payment_terms_template", "fieldtype": "Link", "hidden": 0, @@ -3691,6 +3804,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval:(!doc.is_pos && !doc.is_return)", + "fetch_if_empty": 0, "fieldname": "payment_schedule", "fieldtype": "Table", "hidden": 0, @@ -3726,6 +3840,7 @@ "collapsible_depends_on": "", "columns": 0, "depends_on": "eval:doc.is_pos===1||(doc.advances && doc.advances.length>0)", + "fetch_if_empty": 0, "fieldname": "payments_section", "fieldtype": "Section Break", "hidden": 0, @@ -3759,6 +3874,7 @@ "collapsible": 0, "columns": 0, "depends_on": "is_pos", + "fetch_if_empty": 0, "fieldname": "cash_bank_account", "fieldtype": "Link", "hidden": 1, @@ -3794,6 +3910,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval:doc.is_pos===1", + "fetch_if_empty": 0, "fieldname": "payments", "fieldtype": "Table", "hidden": 0, @@ -3827,6 +3944,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "section_break_84", "fieldtype": "Section Break", "hidden": 0, @@ -3858,6 +3976,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "base_paid_amount", "fieldtype": "Currency", "hidden": 0, @@ -3891,6 +4010,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break_86", "fieldtype": "Column Break", "hidden": 0, @@ -3923,6 +4043,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval: doc.is_pos || doc.redeem_loyalty_points", + "fetch_if_empty": 0, "fieldname": "paid_amount", "fieldtype": "Currency", "hidden": 0, @@ -3957,6 +4078,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "section_break_88", "fieldtype": "Section Break", "hidden": 0, @@ -3989,6 +4111,7 @@ "collapsible": 0, "columns": 0, "depends_on": "is_pos", + "fetch_if_empty": 0, "fieldname": "base_change_amount", "fieldtype": "Currency", "hidden": 0, @@ -4022,6 +4145,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break_90", "fieldtype": "Column Break", "hidden": 0, @@ -4054,6 +4178,7 @@ "collapsible": 0, "columns": 0, "depends_on": "is_pos", + "fetch_if_empty": 0, "fieldname": "change_amount", "fieldtype": "Currency", "hidden": 0, @@ -4088,6 +4213,7 @@ "collapsible": 0, "columns": 0, "depends_on": "is_pos", + "fetch_if_empty": 0, "fieldname": "account_for_change_amount", "fieldtype": "Link", "hidden": 0, @@ -4123,6 +4249,7 @@ "collapsible_depends_on": "write_off_amount", "columns": 0, "depends_on": "grand_total", + "fetch_if_empty": 0, "fieldname": "column_break4", "fieldtype": "Section Break", "hidden": 0, @@ -4156,6 +4283,7 @@ "collapsible": 0, "columns": 0, "depends_on": "", + "fetch_if_empty": 0, "fieldname": "write_off_amount", "fieldtype": "Currency", "hidden": 0, @@ -4188,6 +4316,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "base_write_off_amount", "fieldtype": "Currency", "hidden": 0, @@ -4222,6 +4351,7 @@ "collapsible": 0, "columns": 0, "depends_on": "is_pos", + "fetch_if_empty": 0, "fieldname": "write_off_outstanding_amount_automatically", "fieldtype": "Check", "hidden": 0, @@ -4254,6 +4384,7 @@ "collapsible": 0, "columns": 0, "depends_on": "", + "fetch_if_empty": 0, "fieldname": "column_break_74", "fieldtype": "Column Break", "hidden": 0, @@ -4286,6 +4417,7 @@ "collapsible": 0, "columns": 0, "depends_on": "", + "fetch_if_empty": 0, "fieldname": "write_off_account", "fieldtype": "Link", "hidden": 0, @@ -4319,6 +4451,7 @@ "collapsible": 0, "columns": 0, "depends_on": "", + "fetch_if_empty": 0, "fieldname": "write_off_cost_center", "fieldtype": "Link", "hidden": 0, @@ -4352,6 +4485,7 @@ "collapsible": 1, "collapsible_depends_on": "terms", "columns": 0, + "fetch_if_empty": 0, "fieldname": "terms_section_break", "fieldtype": "Section Break", "hidden": 0, @@ -4385,6 +4519,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "tc_name", "fieldtype": "Link", "hidden": 0, @@ -4419,6 +4554,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "terms", "fieldtype": "Text Editor", "hidden": 0, @@ -4452,6 +4588,7 @@ "bold": 0, "collapsible": 1, "columns": 0, + "fetch_if_empty": 0, "fieldname": "edit_printing_settings", "fieldtype": "Section Break", "hidden": 0, @@ -4484,6 +4621,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "letter_head", "fieldtype": "Link", "hidden": 0, @@ -4518,6 +4656,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "group_same_items", "fieldtype": "Check", "hidden": 0, @@ -4550,6 +4689,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "language", "fieldtype": "Data", "hidden": 0, @@ -4582,6 +4722,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break_84", "fieldtype": "Column Break", "hidden": 0, @@ -4613,6 +4754,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "select_print_heading", "fieldtype": "Link", "hidden": 0, @@ -4648,6 +4790,7 @@ "collapsible": 1, "columns": 0, "depends_on": "customer", + "fetch_if_empty": 0, "fieldname": "more_information", "fieldtype": "Section Break", "hidden": 0, @@ -4680,6 +4823,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "inter_company_invoice_reference", "fieldtype": "Link", "hidden": 0, @@ -4714,6 +4858,7 @@ "collapsible": 0, "columns": 0, "description": "", + "fetch_if_empty": 0, "fieldname": "customer_group", "fieldtype": "Link", "hidden": 1, @@ -4747,6 +4892,7 @@ "collapsible": 0, "columns": 0, "depends_on": "", + "fetch_if_empty": 0, "fieldname": "campaign", "fieldtype": "Link", "hidden": 0, @@ -4781,6 +4927,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "col_break23", "fieldtype": "Column Break", "hidden": 0, @@ -4813,6 +4960,7 @@ "collapsible": 0, "columns": 0, "default": "Draft", + "fetch_if_empty": 0, "fieldname": "status", "fieldtype": "Select", "hidden": 0, @@ -4846,6 +4994,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "source", "fieldtype": "Link", "hidden": 0, @@ -4880,6 +5029,7 @@ "bold": 0, "collapsible": 1, "columns": 0, + "fetch_if_empty": 0, "fieldname": "more_info", "fieldtype": "Section Break", "hidden": 0, @@ -4914,6 +5064,7 @@ "collapsible": 0, "columns": 0, "description": "", + "fetch_if_empty": 0, "fieldname": "debit_to", "fieldtype": "Link", "hidden": 0, @@ -4948,6 +5099,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "party_account_currency", "fieldtype": "Link", "hidden": 1, @@ -4983,6 +5135,7 @@ "columns": 0, "default": "No", "description": "", + "fetch_if_empty": 0, "fieldname": "is_opening", "fieldtype": "Select", "hidden": 0, @@ -5017,6 +5170,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "c_form_applicable", "fieldtype": "Select", "hidden": 0, @@ -5049,6 +5203,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "c_form_no", "fieldtype": "Link", "hidden": 0, @@ -5081,6 +5236,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break8", "fieldtype": "Column Break", "hidden": 0, @@ -5112,6 +5268,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "remarks", "fieldtype": "Small Text", "hidden": 0, @@ -5146,6 +5303,7 @@ "collapsible": 1, "collapsible_depends_on": "sales_partner", "columns": 0, + "fetch_if_empty": 0, "fieldname": "sales_team_section_break", "fieldtype": "Section Break", "hidden": 0, @@ -5179,6 +5337,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "sales_partner", "fieldtype": "Link", "hidden": 0, @@ -5213,6 +5372,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break10", "fieldtype": "Column Break", "hidden": 0, @@ -5245,6 +5405,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "commission_rate", "fieldtype": "Float", "hidden": 0, @@ -5278,6 +5439,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "total_commission", "fieldtype": "Currency", "hidden": 0, @@ -5313,6 +5475,7 @@ "collapsible": 1, "collapsible_depends_on": "sales_team", "columns": 0, + "fetch_if_empty": 0, "fieldname": "section_break2", "fieldtype": "Section Break", "hidden": 0, @@ -5344,6 +5507,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "sales_team", "fieldtype": "Table", "hidden": 0, @@ -5378,6 +5542,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "subscription_section", "fieldtype": "Section Break", "hidden": 0, @@ -5412,6 +5577,7 @@ "columns": 0, "depends_on": "", "description": "", + "fetch_if_empty": 0, "fieldname": "from_date", "fieldtype": "Date", "hidden": 0, @@ -5445,6 +5611,7 @@ "columns": 0, "depends_on": "", "description": "", + "fetch_if_empty": 0, "fieldname": "to_date", "fieldtype": "Date", "hidden": 0, @@ -5476,6 +5643,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break_140", "fieldtype": "Column Break", "hidden": 0, @@ -5507,6 +5675,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "auto_repeat", "fieldtype": "Link", "hidden": 0, @@ -5541,6 +5710,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval: doc.auto_repeat", + "fetch_if_empty": 0, "fieldname": "update_auto_repeat_reference", "fieldtype": "Button", "hidden": 0, @@ -5573,6 +5743,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "against_income_account", "fieldtype": "Small Text", "hidden": 1, @@ -5606,6 +5777,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "pos_total_qty", "fieldtype": "Float", "hidden": 1, @@ -5644,7 +5816,7 @@ "istable": 0, "max_attachments": 0, "menu_index": 0, - "modified": "2019-02-18 18:56:51.265257", + "modified": "2019-04-10 16:10:34.266458", "modified_by": "Administrator", "module": "Accounts", "name": "Sales Invoice", diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index 895ca07da2f..489343c00c8 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -205,6 +205,7 @@ class SalesInvoice(SellingController): def before_cancel(self): self.update_time_sheet(None) + def on_cancel(self): self.check_close_sales_order("sales_order") @@ -399,7 +400,7 @@ class SalesInvoice(SellingController): for fieldname in ('territory', 'naming_series', 'currency', 'taxes_and_charges', 'letter_head', 'tc_name', 'company', 'select_print_heading', 'cash_bank_account', 'company_address', - 'write_off_account', 'write_off_cost_center', 'apply_discount_on'): + 'write_off_account', 'write_off_cost_center', 'apply_discount_on', 'cost_center'): if (not for_validate) or (for_validate and not self.get(fieldname)): self.set(fieldname, pos.get(fieldname)) @@ -523,8 +524,8 @@ class SalesInvoice(SellingController): def validate_pos(self): if self.is_return: - if flt(self.paid_amount) + flt(self.write_off_amount) - flt(self.grand_total) < \ - 1/(10**(self.precision("grand_total") + 1)): + if flt(self.paid_amount) + flt(self.write_off_amount) - flt(self.grand_total) > \ + 1.0/(10.0**(self.precision("grand_total") + 1.0)): frappe.throw(_("Paid amount + Write Off Amount can not be greater than Grand Total")) def validate_item_code(self): @@ -689,7 +690,8 @@ class SalesInvoice(SellingController): if repost_future_gle and cint(self.update_stock) \ and cint(auto_accounting_for_stock): items, warehouses = self.get_items_and_warehouses() - update_gl_entries_after(self.posting_date, self.posting_time, warehouses, items) + update_gl_entries_after(self.posting_date, self.posting_time, + warehouses, items, company = self.company) elif self.docstatus == 2 and cint(self.update_stock) \ and cint(auto_accounting_for_stock): from erpnext.accounts.general_ledger import delete_gl_entries @@ -1012,9 +1014,10 @@ class SalesInvoice(SellingController): for serial_no in item.serial_no.split("\n"): sales_invoice = frappe.db.get_value("Serial No", serial_no, "sales_invoice") if sales_invoice and self.name != sales_invoice: - frappe.throw(_("Serial Number: {0} is already referenced in Sales Invoice: {1}".format( - serial_no, sales_invoice - ))) + sales_invoice_company = frappe.db.get_value("Sales Invoice", sales_invoice, "company") + if sales_invoice_company == self.company: + frappe.throw(_("Serial Number: {0} is already referenced in Sales Invoice: {1}" + .format(serial_no, sales_invoice))) def update_project(self): if self.project: diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index f9364e2d847..b39da3c4af4 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -14,8 +14,9 @@ from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_per from erpnext.exceptions import InvalidAccountCurrency, InvalidCurrency from erpnext.stock.doctype.serial_no.serial_no import SerialNoWarehouseError from frappe.model.naming import make_autoname -from erpnext.accounts.doctype.account.test_account import get_inventory_account +from erpnext.accounts.doctype.account.test_account import get_inventory_account, create_account from erpnext.controllers.taxes_and_totals import get_itemised_tax_breakup_data +from erpnext.stock.doctype.item.test_item import create_item from six import iteritems class TestSalesInvoice(unittest.TestCase): def make(self): @@ -762,7 +763,7 @@ class TestSalesInvoice(unittest.TestCase): set_perpetual_inventory(0) frappe.db.sql("delete from `tabPOS Profile`") - + def test_pos_si_without_payment(self): set_perpetual_inventory() make_pos_profile() @@ -854,6 +855,7 @@ class TestSalesInvoice(unittest.TestCase): jv.submit() si = frappe.copy_doc(test_records[0]) + si.allocate_advances_automatically = 0 si.append("advances", { "doctype": "Sales Invoice Advance", "reference_type": "Journal Entry", @@ -1514,6 +1516,56 @@ class TestSalesInvoice(unittest.TestCase): accounts_settings.allow_cost_center_in_entry_of_bs_account = 0 accounts_settings.save() + def test_deferred_revenue(self): + deferred_account = create_account(account_name="Deferred Revenue", + parent_account="Current Liabilities - _TC", company="_Test Company") + + item = create_item("_Test Item for Deferred Accounting") + item.enable_deferred_revenue = 1 + item.deferred_revenue_account = deferred_account + item.no_of_months = 12 + item.save() + + si = create_sales_invoice(item=item.name, posting_date="2019-01-10", do_not_submit=True) + si.items[0].enable_deferred_revenue = 1 + si.items[0].service_start_date = "2019-01-10" + si.items[0].service_end_date = "2019-03-15" + si.items[0].deferred_revenue_account = deferred_account + si.save() + si.submit() + + from erpnext.accounts.deferred_revenue import convert_deferred_revenue_to_income + convert_deferred_revenue_to_income(start_date="2019-01-01", end_date="2019-01-31") + + expected_gle = [ + [deferred_account, 33.85, 0.0, "2019-01-31"], + ["Sales - _TC", 0.0, 33.85, "2019-01-31"] + ] + + self.check_gl_entries(si.name, expected_gle, "2019-01-10") + + convert_deferred_revenue_to_income(start_date="2019-01-01", end_date="2019-03-31") + + expected_gle = [ + [deferred_account, 43.08, 0.0, "2019-02-28"], + ["Sales - _TC", 0.0, 43.08, "2019-02-28"], + [deferred_account, 23.07, 0.0, "2019-03-15"], + ["Sales - _TC", 0.0, 23.07, "2019-03-15"] + ] + + self.check_gl_entries(si.name, expected_gle, "2019-01-31") + + def check_gl_entries(self, voucher_no, expected_gle, posting_date): + gl_entries = frappe.db.sql("""select account, debit, credit, posting_date + from `tabGL Entry` + where voucher_type='Sales Invoice' and voucher_no=%s and posting_date > %s + order by posting_date asc, account asc""", (voucher_no, posting_date), as_dict=1) + + for i, gle in enumerate(gl_entries): + self.assertEqual(expected_gle[i][0], gle.account) + self.assertEqual(expected_gle[i][1], gle.debit) + self.assertEqual(expected_gle[i][2], gle.credit) + self.assertEqual(getdate(expected_gle[i][3]), gle.posting_date) def create_sales_invoice(**args): si = frappe.new_doc("Sales Invoice") @@ -1611,4 +1663,4 @@ def get_outstanding_amount(against_voucher_type, against_voucher, account, party if against_voucher_type == 'Purchase Invoice': bal = bal * -1 - return bal + return bal \ No newline at end of file diff --git a/erpnext/accounts/doctype/sales_invoice_payment/sales_invoice_payment.json b/erpnext/accounts/doctype/sales_invoice_payment/sales_invoice_payment.json index ccdabfe5444..1c5962acf6e 100644 --- a/erpnext/accounts/doctype/sales_invoice_payment/sales_invoice_payment.json +++ b/erpnext/accounts/doctype/sales_invoice_payment/sales_invoice_payment.json @@ -20,6 +20,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval:parent.doctype == 'POS Profile'", + "fetch_if_empty": 0, "fieldname": "default", "fieldtype": "Check", "hidden": 0, @@ -52,6 +53,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "mode_of_payment", "fieldtype": "Link", "hidden": 0, @@ -85,8 +87,9 @@ "bold": 0, "collapsible": 0, "columns": 0, - "default": "", + "default": "0", "depends_on": "eval:parent.doctype == 'Sales Invoice'", + "fetch_if_empty": 0, "fieldname": "amount", "fieldtype": "Currency", "hidden": 0, @@ -120,6 +123,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break_3", "fieldtype": "Column Break", "hidden": 0, @@ -151,6 +155,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "account", "fieldtype": "Link", "hidden": 0, @@ -185,6 +190,7 @@ "collapsible": 0, "columns": 0, "fetch_from": "mode_of_payment.type", + "fetch_if_empty": 0, "fieldname": "type", "fieldtype": "Read Only", "hidden": 0, @@ -218,6 +224,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "base_amount", "fieldtype": "Currency", "hidden": 0, @@ -251,6 +258,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "clearance_date", "fieldtype": "Date", "hidden": 0, @@ -287,7 +295,7 @@ "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2019-02-18 15:03:59.720469", + "modified": "2019-03-06 15:58:37.839241", "modified_by": "Administrator", "module": "Accounts", "name": "Sales Invoice Payment", diff --git a/erpnext/accounts/page/pos/pos.js b/erpnext/accounts/page/pos/pos.js index c3274b9fb5b..4550dedba94 100755 --- a/erpnext/accounts/page/pos/pos.js +++ b/erpnext/accounts/page/pos/pos.js @@ -333,6 +333,7 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({ var me = this; this.frm = {} this.load_data(true); + this.frm.doc.offline_pos_name = ''; this.setup(); this.set_default_customer() }, @@ -345,7 +346,6 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({ if (load_doc) { this.frm.doc = JSON.parse(localStorage.getItem('doc')); - this.frm.doc.offline_pos_name = null; } $.each(this.meta, function (i, data) { @@ -641,7 +641,7 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({ me.list_customers_btn.toggleClass("view_customer"); me.pos_bill.show(); me.list_customers_btn.show(); - me.frm.doc.offline_pos_name = $(this).parents().attr('invoice-name') + me.frm.doc.offline_pos_name = $(this).parents().attr('invoice-name'); me.edit_record(); }) @@ -984,7 +984,7 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({ } if(!this.customer_doc.fields_dict.customer_pos_id.value) { - this.customer_doc.set_value("customer_pos_id", $.now()) + this.customer_doc.set_value("customer_pos_id", frappe.datetime.now_datetime()) } }, @@ -1686,10 +1686,18 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({ create_invoice: function () { var me = this; + var existing_pos_list = []; var invoice_data = {}; this.si_docs = this.get_doc_from_localstorage(); - if (this.frm.doc.offline_pos_name) { + if(this.si_docs) { + this.si_docs.forEach((row) => { + existing_pos_list.push(Object.keys(row)); + }); + } + + if (this.frm.doc.offline_pos_name + && in_list(existing_pos_list, this.frm.doc.offline_pos_name)) { this.update_invoice() //to retrieve and set the default payment invoice_data[this.frm.doc.offline_pos_name] = this.frm.doc; @@ -1698,8 +1706,8 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({ this.frm.doc.paid_amount = this.frm.doc.net_total this.frm.doc.outstanding_amount = 0 - } else { - this.frm.doc.offline_pos_name = $.now(); + } else if(!this.frm.doc.offline_pos_name) { + this.frm.doc.offline_pos_name = frappe.datetime.now_datetime(); this.frm.doc.posting_date = frappe.datetime.get_today(); this.frm.doc.posting_time = frappe.datetime.now_time(); this.frm.doc.pos_total_qty = this.frm.doc.qty_total; diff --git a/erpnext/accounts/party.py b/erpnext/accounts/party.py index 5855ac3bcd5..67bd0bd8c70 100644 --- a/erpnext/accounts/party.py +++ b/erpnext/accounts/party.py @@ -573,11 +573,17 @@ def get_party_shipping_address(doctype, name): else: return '' -def get_partywise_advanced_payment_amount(party_type="Customer"): +def get_partywise_advanced_payment_amount(party_type, posting_date = None): + cond = "1=1" + if posting_date: + cond = "posting_date <= '{0}'".format(posting_date) + 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) + WHERE + party_type = %s and against_voucher is null + and {1} GROUP BY party""" + .format(("credit") if party_type == "Customer" else "debit", cond) , party_type) if data: return frappe._dict(data) \ No newline at end of file diff --git a/erpnext/accounts/print_format/bank_and_cash_payment_voucher/__init__.py b/erpnext/accounts/print_format/bank_and_cash_payment_voucher/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/erpnext/accounts/print_format/bank_and_cash_payment_voucher/bank_and_cash_payment_voucher.html b/erpnext/accounts/print_format/bank_and_cash_payment_voucher/bank_and_cash_payment_voucher.html new file mode 100644 index 00000000000..2eadb2a92ac --- /dev/null +++ b/erpnext/accounts/print_format/bank_and_cash_payment_voucher/bank_and_cash_payment_voucher.html @@ -0,0 +1,82 @@ +{%- from "templates/print_formats/standard_macros.html" import add_header -%} + +
+ {%- if not doc.get("print_heading") and not doc.get("select_print_heading") + and doc.set("select_print_heading", _("Payment Entry")) -%}{%- endif -%} + {{ add_header(0, 1, doc, letter_head, no_letterhead, print_settings) }} +
+
+ + +
Voucher No: {{ doc.name }}
+
+
+ + +
Date: {{ frappe.utils.formatdate(doc.creation) }}
+
+
+
+ + + + + + + + + + + {% set total_credit = 0 -%} + {% for entries in doc.gl_entries %} + {% if entries.debit == 0.0 %} + + + + + + {% set total_credit = total_credit + entries.credit -%} + + + + + + + + + {% endif %} + {% endfor %} + + + + + + + {% set total_debit = 0 -%} + {% for entries in doc.gl_entries %} + {% if entries.credit == 0.0 %} + + + + + {% set total_debit = total_debit + entries.debit -%} + + + + + + + + + + {% endif %} + {% endfor %} +
AccountParty TypePartyAmount
Credit
{{ entries.account }}{{ entries.party_type }}{{ entries.party }}{{ entries.credit }}
Narration
{{ entries.remarks }}
Total (credit) {{total_credit}}
Debit
{{ entries.account }}{{ entries.party_type }}{{ entries.party }}{{ entries.debit }}
Narration
{{ entries.remarks }}
Total (debit) {{total_debit}}
+
+
\ No newline at end of file diff --git a/erpnext/accounts/print_format/bank_and_cash_payment_voucher/bank_and_cash_payment_voucher.json b/erpnext/accounts/print_format/bank_and_cash_payment_voucher/bank_and_cash_payment_voucher.json new file mode 100644 index 00000000000..e3afaec2ad0 --- /dev/null +++ b/erpnext/accounts/print_format/bank_and_cash_payment_voucher/bank_and_cash_payment_voucher.json @@ -0,0 +1,22 @@ +{ + "align_labels_right": 0, + "creation": "2019-02-15 11:49:08.608619", + "custom_format": 0, + "default_print_language": "en", + "disabled": 0, + "doc_type": "Payment Entry", + "docstatus": 0, + "doctype": "Print Format", + "font": "Default", + "idx": 0, + "line_breaks": 0, + "modified": "2019-02-15 11:49:08.608619", + "modified_by": "Administrator", + "module": "Accounts", + "name": "Bank and Cash Payment Voucher", + "owner": "Administrator", + "print_format_builder": 0, + "print_format_type": "Server", + "show_section_headings": 0, + "standard": "Yes" +} \ No newline at end of file diff --git a/erpnext/accounts/print_format/gst_purchase_invoice/gst_purchase_invoice.json b/erpnext/accounts/print_format/gst_purchase_invoice/gst_purchase_invoice.json index 2b7f9ce757a..6d7c3d31ae4 100644 --- a/erpnext/accounts/print_format/gst_purchase_invoice/gst_purchase_invoice.json +++ b/erpnext/accounts/print_format/gst_purchase_invoice/gst_purchase_invoice.json @@ -7,10 +7,10 @@ "docstatus": 0, "doctype": "Print Format", "font": "Default", - "format_data": "[{\"fieldname\": \"print_heading_template\", \"fieldtype\": \"Custom HTML\", \"options\": \"
\\t\\t\\t\\t

Purchase Invoice
{{ doc.name }}\\t\\t\\t\\t

\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"supplier_name\", \"label\": \"Supplier Name\"}, {\"print_hide\": 0, \"fieldname\": \"due_date\", \"label\": \"Due Date\"}, {\"fieldtype\": \"Column Break\"}, {\"fieldtype\": \"Section Break\", \"label\": \"Address\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"address_display\", \"label\": \"Address\"}, {\"print_hide\": 0, \"fieldname\": \"contact_display\", \"label\": \"Contact\"}, {\"print_hide\": 0, \"fieldname\": \"contact_mobile\", \"label\": \"Mobile No\"}, {\"fieldtype\": \"Column Break\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"visible_columns\": [{\"print_hide\": 0, \"fieldname\": \"item_name\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"description\", \"print_width\": \"300px\"}, {\"print_hide\": 0, \"fieldname\": \"image\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"received_qty\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"qty\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"rejected_qty\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"discount_percentage\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"rate\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"amount\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"pricing_rule\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"weight_per_unit\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"total_weight\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"weight_uom\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"warehouse\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"rejected_warehouse\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"batch_no\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"serial_no\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"bom\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"asset\", \"print_width\": \"\"}], \"print_hide\": 0, \"fieldname\": \"items\", \"label\": \"Items\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"total\", \"label\": \"Total\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"visible_columns\": [{\"print_hide\": 0, \"fieldname\": \"category\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"add_deduct_tax\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"charge_type\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"row_id\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"included_in_print_rate\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"account_head\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"cost_center\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"description\", \"print_width\": \"300px\"}, {\"print_hide\": 0, \"fieldname\": \"rate\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"tax_amount\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"total\", \"print_width\": \"\"}], \"print_hide\": 0, \"fieldname\": \"taxes\", \"label\": \"Purchase Taxes and Charges\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"grand_total\", \"label\": \"Grand Total\"}, {\"print_hide\": 0, \"fieldname\": \"in_words\", \"label\": \"In Words\"}, {\"print_hide\": 0, \"fieldname\": \"disable_rounded_total\", \"label\": \"Disable Rounded Total\"}, {\"fieldtype\": \"Section Break\", \"label\": \"Payments\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"cash_bank_account\", \"label\": \"Cash/Bank Account\"}, {\"fieldtype\": \"Column Break\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"other_charges_calculation\", \"align\": \"left\", \"label\": \"Tax Breakup\"}, {\"fieldtype\": \"Section Break\", \"label\": \"Raw\"}, {\"fieldtype\": \"Column Break\"}, {\"visible_columns\": [{\"print_hide\": 0, \"fieldname\": \"main_item_code\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"rm_item_code\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"description\", \"print_width\": \"300px\"}, {\"print_hide\": 0, \"fieldname\": \"batch_no\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"serial_no\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"required_qty\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"consumed_qty\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"stock_uom\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"rate\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"amount\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"conversion_factor\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"current_stock\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"reference_name\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"bom_detail_no\", \"print_width\": \"\"}], \"print_hide\": 0, \"fieldname\": \"supplied_items\", \"label\": \"Supplied Items\"}, {\"fieldtype\": \"Section Break\", \"label\": \"Terms\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"terms\", \"label\": \"Terms and Conditions1\"}]", + "format_data": "[{\"fieldname\": \"print_heading_template\", \"fieldtype\": \"Custom HTML\", \"options\": \"
\\t\\t\\t\\t

Purchase Invoice
{{ doc.name }}\\t\\t\\t\\t

\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"supplier_name\", \"label\": \"Supplier Name\"}, {\"print_hide\": 0, \"fieldname\": \"due_date\", \"label\": \"Due Date\"}, {\"fieldtype\": \"Column Break\"}, {\"fieldtype\": \"Section Break\", \"label\": \"Address\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"address_display\", \"label\": \"Address\"}, {\"print_hide\": 0, \"fieldname\": \"contact_display\", \"label\": \"Contact\"}, {\"print_hide\": 0, \"fieldname\": \"contact_mobile\", \"label\": \"Mobile No\"}, {\"fieldtype\": \"Column Break\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"visible_columns\": [{\"print_hide\": 0, \"fieldname\": \"item_name\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"description\", \"print_width\": \"300px\"}, {\"print_hide\": 0, \"fieldname\": \"image\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"received_qty\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"qty\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"rejected_qty\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"discount_percentage\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"rate\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"amount\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"pricing_rule\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"weight_per_unit\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"total_weight\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"weight_uom\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"warehouse\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"rejected_warehouse\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"batch_no\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"serial_no\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"bom\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"asset\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"gst_hsn_code\", \"print_width\": \"\"}], \"print_hide\": 0, \"fieldname\": \"items\", \"label\": \"Items\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"total\", \"label\": \"Total\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"visible_columns\": [{\"print_hide\": 0, \"fieldname\": \"category\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"add_deduct_tax\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"charge_type\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"row_id\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"included_in_print_rate\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"account_head\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"cost_center\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"description\", \"print_width\": \"300px\"}, {\"print_hide\": 0, \"fieldname\": \"rate\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"tax_amount\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"total\", \"print_width\": \"\"}], \"print_hide\": 0, \"fieldname\": \"taxes\", \"label\": \"Purchase Taxes and Charges\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"grand_total\", \"label\": \"Grand Total\"}, {\"print_hide\": 0, \"fieldname\": \"in_words\", \"label\": \"In Words\"}, {\"print_hide\": 0, \"fieldname\": \"disable_rounded_total\", \"label\": \"Disable Rounded Total\"}, {\"fieldtype\": \"Section Break\", \"label\": \"Payments\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"cash_bank_account\", \"label\": \"Cash/Bank Account\"}, {\"fieldtype\": \"Column Break\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"other_charges_calculation\", \"align\": \"left\", \"label\": \"Tax Breakup\"}, {\"fieldtype\": \"Section Break\", \"label\": \"Raw\"}, {\"fieldtype\": \"Column Break\"}, {\"visible_columns\": [{\"print_hide\": 0, \"fieldname\": \"main_item_code\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"rm_item_code\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"description\", \"print_width\": \"300px\"}, {\"print_hide\": 0, \"fieldname\": \"batch_no\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"serial_no\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"required_qty\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"consumed_qty\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"stock_uom\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"rate\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"amount\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"conversion_factor\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"current_stock\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"reference_name\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"bom_detail_no\", \"print_width\": \"\"}], \"print_hide\": 0, \"fieldname\": \"supplied_items\", \"label\": \"Supplied Items\"}, {\"fieldtype\": \"Section Break\", \"label\": \"Terms\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"terms\", \"label\": \"Terms and Conditions1\"}]", "idx": 0, "line_breaks": 0, - "modified": "2018-04-07 13:06:08.060353", + "modified": "2019-03-04 13:38:47.362002", "modified_by": "Administrator", "module": "Accounts", "name": "GST Purchase Invoice", diff --git a/erpnext/accounts/print_format/journal_auditing_voucher/__init__.py b/erpnext/accounts/print_format/journal_auditing_voucher/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/erpnext/accounts/print_format/journal_auditing_voucher/journal_auditing_voucher.html b/erpnext/accounts/print_format/journal_auditing_voucher/journal_auditing_voucher.html new file mode 100644 index 00000000000..4565559084a --- /dev/null +++ b/erpnext/accounts/print_format/journal_auditing_voucher/journal_auditing_voucher.html @@ -0,0 +1,76 @@ +{%- from "templates/print_formats/standard_macros.html" import add_header -%} + +
+ {%- if not doc.get("print_heading") and not doc.get("select_print_heading") + and doc.set("select_print_heading", _("Journal Entry")) -%}{%- endif -%} + {{ add_header(0, 1, doc, letter_head, no_letterhead, print_settings) }} +
+
+ + +
Voucher No: {{ doc.name }}
+
+
+ + +
Date: {{ frappe.utils.formatdate(doc.creation) }}
+
+
+
+ + + + + + + + + + + {% set total_credit = 0 -%} + {% for entries in doc.gl_entries %} + {% if entries.debit == 0.0 %} + + + + + + {% set total_credit = total_credit + entries.credit -%} + + + + + + {% endif %} + {% endfor %} + + + + + + + {% set total_debit = 0 -%} + {% for entries in doc.gl_entries %} + {% if entries.credit == 0.0 %} + + + + + {% set total_debit = total_debit + entries.debit -%} + + + + + + + {% endif %} + {% endfor %} +
AccountParty TypePartyAmount
Credit
{{ entries.account }}{{ entries.party_type }}{{ entries.party }}{{ entries.credit }}
Total (credit) {{total_credit}}
Debit
{{ entries.account }}{{ entries.party_type }}{{ entries.party }}{{ entries.debit }}
Total (debit) {{total_debit}}
+
+
\ No newline at end of file diff --git a/erpnext/accounts/print_format/journal_auditing_voucher/journal_auditing_voucher.json b/erpnext/accounts/print_format/journal_auditing_voucher/journal_auditing_voucher.json new file mode 100644 index 00000000000..927e818e017 --- /dev/null +++ b/erpnext/accounts/print_format/journal_auditing_voucher/journal_auditing_voucher.json @@ -0,0 +1,22 @@ +{ + "align_labels_right": 0, + "creation": "2019-02-15 14:13:05.721784", + "custom_format": 0, + "default_print_language": "en", + "disabled": 0, + "doc_type": "Journal Entry", + "docstatus": 0, + "doctype": "Print Format", + "font": "Default", + "idx": 0, + "line_breaks": 0, + "modified": "2019-02-15 14:13:05.721784", + "modified_by": "Administrator", + "module": "Accounts", + "name": "Journal Auditing Voucher", + "owner": "Administrator", + "print_format_builder": 0, + "print_format_type": "Server", + "show_section_headings": 0, + "standard": "Yes" +} \ No newline at end of file diff --git a/erpnext/accounts/print_format/purchase_auditing_voucher/__init__.py b/erpnext/accounts/print_format/purchase_auditing_voucher/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/erpnext/accounts/print_format/purchase_auditing_voucher/purchase_auditing_voucher.html b/erpnext/accounts/print_format/purchase_auditing_voucher/purchase_auditing_voucher.html new file mode 100644 index 00000000000..35852e1e1c8 --- /dev/null +++ b/erpnext/accounts/print_format/purchase_auditing_voucher/purchase_auditing_voucher.html @@ -0,0 +1,99 @@ +{%- from "templates/print_formats/standard_macros.html" import add_header -%} +
+ {%- if not doc.get("print_heading") and not doc.get("select_print_heading") + and doc.set("select_print_heading", _("Purchase Invoice")) -%}{%- endif -%} + {{ add_header(0, 1, doc, letter_head, no_letterhead, print_settings) }} +
+
+ + + + + + +
Supplier Name: {{ doc.supplier }}
Due Date: {{ frappe.utils.formatdate(doc.due_date) }}
Address: {{doc.address_display}}
Contact: {{doc.contact_display}}
Mobile no: {{doc.contact_mobile}}
+
+
+ + + +
Voucher No: {{ doc.name }}
Date: {{ frappe.utils.formatdate(doc.creation) }}
+
+
+
+ + + + + + + + + + + + + {% for item in doc.items %} + + + + + + + + + + + + {% endfor %} +
SLItem CodeItem NameUOMReceived Qty.Rejected QtyQtyBasic RateAmount
{{ loop.index }}{{ item.item_code }}{{ item.item_name }}{{ item.uom }}{{ item.received_qty }}{{ item.rejected_qty }}{{ item.qty}}{{ item.rate }}{{ item.amount }}
+
+
+
+ + + + +
Total Quantity: {{ doc.total_qty }}
Total: {{doc.total}}
Net Weight: {{ doc.total_net_weight }}
+
+
+ + + {% for tax in doc.taxes %} + + {% endfor %} + + + + +
Tax and Charges: {{doc.taxes_and_charges}}
{{ tax.account_head }}: {{ tax.tax_amount_after_discount_amount }}
Taxes and Charges Added: {{ doc.taxes_and_charges_added }}
Taxes and Charges Deducted: {{ doc.taxes_and_charges_deducted }}
Total Taxes and Charges: {{ doc.total_taxes_and_charges }}
Net Payable: {{ doc.grand_total }}
+
+
+
+ + + + + + + + + + {% for entries in doc.gl_entries %} + + + + + + + + + {% endfor %} + + + + + +
SLAccountParty TypePartyCredit AmountDebit Amount
{{ loop.index }}{{ entries.account }}{{ entries.party_type }}{{ entries.party }}{{ entries.credit }}{{ entries.debit }}
Total{{ doc.grand_total|flt }}{{ doc.grand_total|flt }}
+
+
\ No newline at end of file diff --git a/erpnext/accounts/print_format/purchase_auditing_voucher/purchase_auditing_voucher.json b/erpnext/accounts/print_format/purchase_auditing_voucher/purchase_auditing_voucher.json new file mode 100644 index 00000000000..73779d49aab --- /dev/null +++ b/erpnext/accounts/print_format/purchase_auditing_voucher/purchase_auditing_voucher.json @@ -0,0 +1,22 @@ +{ + "align_labels_right": 0, + "creation": "2019-02-14 14:42:35.151611", + "custom_format": 0, + "default_print_language": "en", + "disabled": 0, + "doc_type": "Purchase Invoice", + "docstatus": 0, + "doctype": "Print Format", + "font": "Default", + "idx": 0, + "line_breaks": 0, + "modified": "2019-02-14 14:42:35.151611", + "modified_by": "Administrator", + "module": "Accounts", + "name": "Purchase Auditing Voucher", + "owner": "Administrator", + "print_format_builder": 0, + "print_format_type": "Server", + "show_section_headings": 0, + "standard": "Yes" +} \ No newline at end of file diff --git a/erpnext/accounts/print_format/sales_auditing_voucher/__init__.py b/erpnext/accounts/print_format/sales_auditing_voucher/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/erpnext/accounts/print_format/sales_auditing_voucher/sales_auditing_voucher.html b/erpnext/accounts/print_format/sales_auditing_voucher/sales_auditing_voucher.html new file mode 100644 index 00000000000..04de83de708 --- /dev/null +++ b/erpnext/accounts/print_format/sales_auditing_voucher/sales_auditing_voucher.html @@ -0,0 +1,93 @@ +{%- from "templates/print_formats/standard_macros.html" import add_header -%} +
+ {%- if not doc.get("print_heading") and not doc.get("select_print_heading") + and doc.set("select_print_heading", _("Sales Invoice")) -%}{%- endif -%} + {{ add_header(0, 1, doc, letter_head, no_letterhead, print_settings) }} +
+
+ + + + + + +
Customer Name: {{ doc.customer }}
Due Date: {{ frappe.utils.formatdate(doc.due_date) }}
Address: {{doc.address_display}}
Contact: {{doc.contact_display}}
Mobile no: {{doc.contact_mobile}}
+
+
+ + + +
Voucher No: {{ doc.name }}
Date: {{ frappe.utils.formatdate(doc.creation) }}
+
+
+
+ + + + + + + + + + + {% for item in doc.items %} + + + + + + + + + + {% endfor %} +
SLItem CodeItem NameUOMQuantityBasic RateAmount
{{ loop.index }}{{ item.item_code }}{{ item.item_name }}{{ item.uom }}{{ item.qty}}{{ item.rate }}{{ item.amount }}
+
+
+
+ + + + +
Total Quantity: {{ doc.total_qty }}
Total: {{doc.total}}
Net Weight: {{ doc.total_net_weight }}
+
+
+ + + {% for tax in doc.taxes %} + + {% endfor %} + + +
Tax and Charges: {{doc.taxes_and_charges}}
{{ tax.account_head }}: {{ tax.tax_amount_after_discount_amount }}
Total Taxes and Charges: {{ doc.total_taxes_and_charges }}
Net Payable: {{ doc.grand_total }}
+
+
+
+ + + + + + + + + + {% for entries in doc.gl_entries %} + + + + + + + + + {% endfor %} + + + + + +
SLAccountParty TypePartyCredit AmountDebit Amount
{{ loop.index }}{{ entries.account }}{{ entries.party_type }}{{ entries.party }}{{ entries.credit }}{{ entries.debit }}
Total{{ doc.grand_total|flt }}{{ doc.grand_total|flt }}
+
+
\ No newline at end of file diff --git a/erpnext/accounts/print_format/sales_auditing_voucher/sales_auditing_voucher.json b/erpnext/accounts/print_format/sales_auditing_voucher/sales_auditing_voucher.json new file mode 100644 index 00000000000..0544e0bc9e8 --- /dev/null +++ b/erpnext/accounts/print_format/sales_auditing_voucher/sales_auditing_voucher.json @@ -0,0 +1,22 @@ +{ + "align_labels_right": 0, + "creation": "2019-02-15 15:02:51.454754", + "custom_format": 0, + "default_print_language": "en", + "disabled": 0, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype": "Print Format", + "font": "Default", + "idx": 0, + "line_breaks": 0, + "modified": "2019-02-15 15:02:51.454754", + "modified_by": "Administrator", + "module": "Accounts", + "name": "Sales Auditing Voucher", + "owner": "Administrator", + "print_format_builder": 0, + "print_format_type": "Server", + "show_section_headings": 0, + "standard": "Yes" +} \ No newline at end of file diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.html b/erpnext/accounts/report/accounts_receivable/accounts_receivable.html index fd462a628e8..5ce80d1baf3 100644 --- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.html +++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.html @@ -107,26 +107,28 @@ {% if(report.report_name === "Accounts Receivable" || report.report_name === "Accounts Payable") { %} - {%= __("Date") %} - {%= __("Age (Days)") %} - {%= __("Reference") %} - {% if(report.report_name === "Accounts Receivable") { %} - {%= __("Sales Person") %} + {%= __("Date") %} + {%= __("Age (Days)") %} + + {% if(report.report_name === "Accounts Receivable" && filters.show_sales_person_in_print) { %} + {%= __("Reference") %} + {%= __("Sales Person") %} + {% } else { %} + {%= __("Reference") %} {% } %} {% if(!filters.show_pdc_in_print) { %} - {%= (filters.customer || filters.supplier) ? __("Remarks"): __("Party") %} + {%= (filters.customer || filters.supplier) ? __("Remarks"): __("Party") %} {% } %} {%= __("Invoiced Amount") %} {% if(!filters.show_pdc_in_print) { %} {%= __("Paid Amount") %} {%= report.report_name === "Accounts Receivable" ? __('Credit Note') : __('Debit Note') %} {% } %} - {%= __("Outstanding Amount") %} + {%= __("Outstanding Amount") %} {% if(filters.show_pdc_in_print) { %} {% if(report.report_name === "Accounts Receivable") { %} {%= __("Customer LPO No.") %} {% } %} - {%= __("PDC/LC Date") %} {%= __("PDC/LC Ref") %} {%= __("PDC/LC Amount") %} {%= __("Remaining Balance") %} @@ -155,7 +157,7 @@ {%= data[i]["voucher_no"] %} - {% if(report.report_name === "Accounts Receivable") { %} + {% if(report.report_name === "Accounts Receivable" && filters.show_sales_person_in_print) { %} {%= data[i]["sales_person"] %} {% } %} @@ -195,7 +197,6 @@ {%= data[i]["po_no"] %} {% } %} - {%= frappe.datetime.str_to_user(data[i][("pdc/lc_date")]) %} {%= data[i][("pdc/lc_ref")] %} {%= format_currency(data[i][("pdc/lc_amount")], data[i]["currency"]) %} {%= format_currency(data[i][("remaining_balance")], data[i]["currency"]) %} @@ -226,7 +227,6 @@ {%= data[i][__("Customer LPO")] %} {% } %} - {%= frappe.datetime.str_to_user(data[i][__("PDC/LC Date")]) %} {%= data[i][("pdc/lc_ref")] %} {%= format_currency(data[i][("pdc/lc_amount")], data[i]["currency"]) %} {%= format_currency(data[i][("remaining_balance")], data[i]["currency"]) %} diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.js b/erpnext/accounts/report/accounts_receivable/accounts_receivable.js index bbfee1112f6..041335ddd11 100644 --- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.js +++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.js @@ -102,14 +102,19 @@ frappe.query_reports["Accounts Receivable"] = { "fieldtype": "Link", "options": "Sales Person" }, + { + "fieldname":"based_on_payment_terms", + "label": __("Based On Payment Terms"), + "fieldtype": "Check", + }, { "fieldname":"show_pdc_in_print", "label": __("Show PDC in Print"), "fieldtype": "Check", }, { - "fieldname":"based_on_payment_terms", - "label": __("Based On Payment Terms"), + "fieldname":"show_sales_person_in_print", + "label": __("Show Sales Person in Print"), "fieldtype": "Check", }, { 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 73ca8b48ef5..244aa8af6a8 100644 --- a/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py +++ b/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py @@ -136,7 +136,8 @@ 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 {} + partywise_advance_amount = get_partywise_advanced_payment_amount(args.get("party_type"), + self.filters.get("report_date")) or {} for party, party_dict in iteritems(partywise_total): row = [party] @@ -145,8 +146,12 @@ class AccountsReceivableSummary(ReceivablePayableReport): row += [partywise_advance_amount.get(party, 0)] + paid_amt = 0 + if party_dict.paid_amt > 0: + paid_amt = flt(party_dict.paid_amt - 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.invoiced_amt, paid_amt, party_dict.credit_amt, party_dict.outstanding_amt, party_dict.range1, party_dict.range2, party_dict.range3, party_dict.range4, ] @@ -205,7 +210,7 @@ class AccountsReceivableSummary(ReceivablePayableReport): cols += ["invoiced_amt", "paid_amt", "credit_amt", "outstanding_amt", "age", "range1", "range2", "range3", "range4", "currency", "pdc/lc_date", "pdc/lc_ref", - "pdc/lc_amount", "remaining_balance"] + "pdc/lc_amount"] if args.get("party_type") == "Supplier": cols += ["supplier_group", "remarks"] diff --git a/erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.py b/erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.py index e33bd61411e..23b963b759e 100644 --- a/erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.py +++ b/erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.py @@ -4,7 +4,7 @@ from __future__ import unicode_literals import frappe import erpnext -from frappe import _ +from frappe import _, scrub from frappe.utils import getdate, nowdate from six import iteritems, itervalues @@ -14,6 +14,9 @@ class PartyLedgerSummaryReport(object): self.filters.from_date = getdate(self.filters.from_date or nowdate()) self.filters.to_date = getdate(self.filters.to_date or nowdate()) + if not self.filters.get("company"): + self.filters["company"] = frappe.db.get_single_value('Global Defaults', 'default_company') + def run(self, args): if self.filters.from_date > self.filters.to_date: frappe.throw(_("From Date must be before To Date")) @@ -21,10 +24,9 @@ class PartyLedgerSummaryReport(object): 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]) + self.get_gl_entries() + self.get_return_invoices() + self.get_party_adjustment_amounts() columns = self.get_columns() data = self.get_data() @@ -48,7 +50,6 @@ class PartyLedgerSummaryReport(object): }) 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 += [ { @@ -79,27 +80,19 @@ class PartyLedgerSummaryReport(object): "options": "currency", "width": 120 }, - { - "label": _(discount_allowed_or_received), - "fieldname": "discount_amount", + ] + + for account in self.party_adjustment_accounts: + columns.append({ + "label": account, + "fieldname": "adj_" + scrub(account), "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 - }, + "width": 120, + "is_adjustment": 1 + }) + + columns += [ { "label": _("Closing Balance"), "fieldname": "closing_balance", @@ -119,17 +112,10 @@ class PartyLedgerSummaryReport(object): 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({ @@ -146,7 +132,7 @@ class PartyLedgerSummaryReport(object): 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: + if gle.posting_date < self.filters.from_date or gle.is_opening == "Yes": self.party_data[gle.party].opening_balance += amount else: if amount > 0: @@ -161,9 +147,10 @@ class PartyLedgerSummaryReport(object): 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 + + adjustments = self.party_adjustment_details.get(party, {}) + for account in self.party_adjustment_accounts: + row["adj_" + scrub(account)] = adjustments.get(account, 0) out.append(row) @@ -182,7 +169,7 @@ class PartyLedgerSummaryReport(object): 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} + gle.against_voucher, gle.debit, gle.credit, gle.is_opening {join_field} from `tabGL Entry` gle {join} where @@ -195,7 +182,7 @@ class PartyLedgerSummaryReport(object): conditions = [""] if self.filters.company: - conditions.append("company=%(company)s") + conditions.append("gle.company=%(company)s") self.filters.company_finance_book = erpnext.get_default_finance_book(self.filters.company) @@ -254,9 +241,10 @@ class PartyLedgerSummaryReport(object): def get_party_adjustment_amounts(self): conditions = self.prepare_conditions() - income_or_expense = "Expense" if self.filters.party_type == "Customer" else "Income" + income_or_expense = "Expense Account" if self.filters.party_type == "Customer" else "Income Account" 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" + round_off_account = frappe.get_cached_value('Company', self.filters.company, "round_off_account") gl_entries = frappe.db.sql(""" select @@ -267,7 +255,7 @@ class PartyLedgerSummaryReport(object): 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}' + where acc.name = gle.account and acc.account_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 @@ -277,6 +265,7 @@ class PartyLedgerSummaryReport(object): """.format(conditions=conditions, income_or_expense=income_or_expense), self.filters, as_dict=True) self.party_adjustment_details = {} + self.party_adjustment_accounts = set() adjustment_voucher_entries = {} for gle in gl_entries: adjustment_voucher_entries.setdefault((gle.voucher_type, gle.voucher_no), []) @@ -288,12 +277,12 @@ class PartyLedgerSummaryReport(object): has_irrelevant_entry = False for gle in voucher_gl_entries: - if gle.account == self.round_off_account: + if gle.account == 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: + elif frappe.get_cached_value("Account", gle.account, "account_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: @@ -303,11 +292,13 @@ class PartyLedgerSummaryReport(object): if len(parties) == 1: party = parties.keys()[0] for account, amount in iteritems(accounts): + self.party_adjustment_accounts.add(account) 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] + self.party_adjustment_accounts.add(account) for party, amount in iteritems(parties): self.party_adjustment_details.setdefault(party, {}) self.party_adjustment_details[party].setdefault(account, 0) diff --git a/erpnext/accounts/report/financial_statements.html b/erpnext/accounts/report/financial_statements.html index 4b3b5f2d539..449fb845d74 100644 --- a/erpnext/accounts/report/financial_statements.html +++ b/erpnext/accounts/report/financial_statements.html @@ -15,7 +15,7 @@ height: 37px; } -{% var letterhead= filters.letter_head || (frappe.get_doc(":Company", filters.company) && frappe.get_doc(":Company", filters.company).default_letter_head) || frappe.defaults.get_default("letter_head"); %} +{% var letterhead= filters.letter_head || (frappe.get_doc(":Company", filters.company) && frappe.get_doc(":Company", filters.company).default_letter_head) %} {% if(letterhead) { %}
{%= frappe.boot.letter_heads[letterhead].header %} diff --git a/erpnext/accounts/report/financial_statements.py b/erpnext/accounts/report/financial_statements.py index 09cf5b1d2fc..e9aecfb394e 100644 --- a/erpnext/accounts/report/financial_statements.py +++ b/erpnext/accounts/report/financial_statements.py @@ -126,7 +126,7 @@ def get_label(periodicity, from_date, to_date): def get_data( company, root_type, balance_must_be, period_list, filters=None, accumulated_values=1, only_current_fiscal_year=True, ignore_closing_entries=False, - ignore_accumulated_values_for_fy=False): + ignore_accumulated_values_for_fy=False , total = True): accounts = get_accounts(company, root_type) if not accounts: @@ -154,7 +154,7 @@ def get_data( out = prepare_data(accounts, balance_must_be, period_list, company_currency) out = filter_out_zero_value_rows(out, parent_children_map) - if out: + if out and total: add_total_row(out, root_type, balance_must_be, period_list, company_currency) return out @@ -218,6 +218,9 @@ def prepare_data(accounts, balance_must_be, period_list, company_currency): "year_start_date": year_start_date, "year_end_date": year_end_date, "currency": company_currency, + "include_in_gross": d.include_in_gross, + "account_type": d.account_type, + "is_group": d.is_group, "opening_balance": d.get("opening_balance", 0.0) * (1 if balance_must_be=="Debit" else -1), "account_name": ('%s - %s' %(_(d.account_number), _(d.account_name)) if d.account_number else _(d.account_name)) @@ -270,7 +273,7 @@ def add_total_row(out, root_type, balance_must_be, period_list, company_currency for period in period_list: total_row.setdefault(period.key, 0.0) total_row[period.key] += row.get(period.key, 0.0) - row[period.key] = 0.0 + row[period.key] = row.get(period.key, 0.0) total_row.setdefault("total", 0.0) total_row["total"] += flt(row["total"]) @@ -285,7 +288,7 @@ def add_total_row(out, root_type, balance_must_be, period_list, company_currency def get_accounts(company, root_type): return frappe.db.sql(""" - select name, account_number, parent_account, lft, rgt, root_type, report_type, account_name + select name, account_number, parent_account, lft, rgt, root_type, report_type, account_name, include_in_gross, account_type, is_group, lft, rgt from `tabAccount` where company=%s and root_type=%s order by lft""", (company, root_type), as_dict=True) diff --git a/erpnext/accounts/report/general_ledger/general_ledger.py b/erpnext/accounts/report/general_ledger/general_ledger.py index be6633282ac..ecb18f78b18 100644 --- a/erpnext/accounts/report/general_ledger/general_ledger.py +++ b/erpnext/accounts/report/general_ledger/general_ledger.py @@ -53,7 +53,7 @@ def validate_filters(filters, account_details): frappe.throw(_("Can not filter based on Account, if grouped by Account")) if (filters.get("voucher_no") - and filters.get("group_by") in [_('Group by Voucher'), _('Group by Voucher (Consolidated)')]): + and filters.get("group_by") in [_('Group by Voucher')]): frappe.throw(_("Can not filter based on Voucher No, if grouped by Voucher")) if filters.from_date > filters.to_date: diff --git a/erpnext/accounts/report/gross_and_net_profit_report/__init__.py b/erpnext/accounts/report/gross_and_net_profit_report/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/erpnext/accounts/report/gross_and_net_profit_report/gross_and_net_profit_report.html b/erpnext/accounts/report/gross_and_net_profit_report/gross_and_net_profit_report.html new file mode 100644 index 00000000000..40ba20c4ac6 --- /dev/null +++ b/erpnext/accounts/report/gross_and_net_profit_report/gross_and_net_profit_report.html @@ -0,0 +1 @@ +{% include "accounts/report/financial_statements.html" %} \ No newline at end of file diff --git a/erpnext/accounts/report/gross_and_net_profit_report/gross_and_net_profit_report.js b/erpnext/accounts/report/gross_and_net_profit_report/gross_and_net_profit_report.js new file mode 100644 index 00000000000..63ac281cdb5 --- /dev/null +++ b/erpnext/accounts/report/gross_and_net_profit_report/gross_and_net_profit_report.js @@ -0,0 +1,51 @@ +// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt +/* eslint-disable */ + +frappe.query_reports["Gross and Net Profit Report"] = { + "filters": [ + + ] +} +frappe.require("assets/erpnext/js/financial_statements.js", function() { + frappe.query_reports["Gross and Net Profit Report"] = $.extend({}, + erpnext.financial_statements); + + frappe.query_reports["Gross and Net Profit Report"]["filters"].push( + { + "fieldname":"project", + "label": __("Project"), + "fieldtype": "MultiSelect", + get_data: function() { + var projects = frappe.query_report.get_filter_value("project") || ""; + + const values = projects.split(/\s*,\s*/).filter(d => d); + const txt = projects.match(/[^,\s*]*$/)[0] || ''; + let data = []; + + frappe.call({ + type: "GET", + method:'frappe.desk.search.search_link', + async: false, + no_spinner: true, + args: { + doctype: "Project", + txt: txt, + filters: { + "name": ["not in", values] + } + }, + callback: function(r) { + data = r.results; + } + }); + return data; + } + }, + { + "fieldname": "accumulated_values", + "label": __("Accumulated Values"), + "fieldtype": "Check" + } + ); +}); diff --git a/erpnext/accounts/report/gross_and_net_profit_report/gross_and_net_profit_report.json b/erpnext/accounts/report/gross_and_net_profit_report/gross_and_net_profit_report.json new file mode 100644 index 00000000000..994b47faef2 --- /dev/null +++ b/erpnext/accounts/report/gross_and_net_profit_report/gross_and_net_profit_report.json @@ -0,0 +1,30 @@ +{ + "add_total_row": 0, + "creation": "2019-02-08 10:58:55.763090", + "disable_prepared_report": 0, + "disabled": 0, + "docstatus": 0, + "doctype": "Report", + "idx": 0, + "is_standard": "Yes", + "modified": "2019-02-08 10:58:55.763090", + "modified_by": "Administrator", + "module": "Accounts", + "name": "Gross and Net Profit Report", + "owner": "Administrator", + "prepared_report": 0, + "ref_doctype": "GL Entry", + "report_name": "Gross and Net Profit Report", + "report_type": "Script Report", + "roles": [ + { + "role": "Accounts User" + }, + { + "role": "Accounts Manager" + }, + { + "role": "Auditor" + } + ] +} \ No newline at end of file diff --git a/erpnext/accounts/report/gross_and_net_profit_report/gross_and_net_profit_report.py b/erpnext/accounts/report/gross_and_net_profit_report/gross_and_net_profit_report.py new file mode 100644 index 00000000000..6550981a146 --- /dev/null +++ b/erpnext/accounts/report/gross_and_net_profit_report/gross_and_net_profit_report.py @@ -0,0 +1,154 @@ +# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +from __future__ import unicode_literals +import frappe +from frappe import _ +from frappe.utils import flt +from erpnext.accounts.report.financial_statements import (get_period_list, get_columns, get_data) +import copy + + +def execute(filters=None): + period_list = get_period_list(filters.from_fiscal_year, filters.to_fiscal_year, + filters.periodicity, filters.accumulated_values, filters.company) + + columns, data = [], [] + + income = get_data(filters.company, "Income", "Credit", period_list, filters = filters, + accumulated_values=filters.accumulated_values, + ignore_closing_entries=True, ignore_accumulated_values_for_fy= True, total= False) + + expense = get_data(filters.company, "Expense", "Debit", period_list, filters=filters, + accumulated_values=filters.accumulated_values, + ignore_closing_entries=True, ignore_accumulated_values_for_fy= True, total= False) + + columns = get_columns(filters.periodicity, period_list, filters.accumulated_values, filters.company) + + + gross_income = get_revenue(income, period_list) + + gross_expense = get_revenue(expense, period_list) + + if(len(gross_income)==0 and len(gross_expense)== 0): + data.append({"account_name": "'" + _("Nothing is included in gross") + "'", + "account": "'" + _("Nothing is included in gross") + "'"}) + + return columns, data + + data.append({"account_name": "'" + _("Included in Gross Profit") + "'", + "account": "'" + _("Included in Gross Profit") + "'"}) + + data.append({}) + data.extend(gross_income or []) + + data.append({}) + data.extend(gross_expense or []) + + data.append({}) + gross_profit = get_profit(gross_income, gross_expense, period_list, filters.company, 'Gross Profit',filters.presentation_currency) + data.append(gross_profit) + + non_gross_income = get_revenue(income, period_list, 0) + data.append({}) + data.extend(non_gross_income or []) + + non_gross_expense = get_revenue(expense, period_list, 0) + data.append({}) + data.extend(non_gross_expense or []) + + net_profit = get_net_profit(non_gross_income, gross_income, gross_expense, non_gross_expense, period_list, filters.company,filters.presentation_currency) + data.append({}) + data.append(net_profit) + + return columns, data + +def get_revenue(data, period_list, include_in_gross=1): + revenue = [item for item in data if item['include_in_gross']==include_in_gross or item['is_group']==1] + + data_to_be_removed =True + while data_to_be_removed: + revenue, data_to_be_removed = remove_parent_with_no_child(revenue, period_list) + revenue = adjust_account(revenue, period_list) + return copy.deepcopy(revenue) + +def remove_parent_with_no_child(data, period_list): + data_to_be_removed = False + for parent in data: + if 'is_group' in parent and parent.get("is_group") == 1: + have_child = False + for child in data: + if 'parent_account' in child and child.get("parent_account") == parent.get("account"): + have_child = True + break + + if not have_child: + data_to_be_removed = True + data.remove(parent) + + return data, data_to_be_removed + +def adjust_account(data, period_list, consolidated= False): + leaf_nodes = [item for item in data if item['is_group'] == 0] + totals = {} + for node in leaf_nodes: + set_total(node, node["total"], data, totals) + for d in data: + for period in period_list: + key = period if consolidated else period.key + d[key] = totals[d["account"]] + d['total'] = totals[d["account"]] + return data + +def set_total(node, value, complete_list, totals): + if not totals.get(node['account']): + totals[node["account"]] = 0 + totals[node["account"]] += value + + parent = node['parent_account'] + if not parent == '': + return set_total(next(item for item in complete_list if item['account'] == parent), value, complete_list, totals) + + +def get_profit(gross_income, gross_expense, period_list, company, profit_type, currency=None, consolidated=False): + + profit_loss = { + "account_name": "'" + _(profit_type) + "'", + "account": "'" + _(profit_type) + "'", + "warn_if_negative": True, + "currency": currency or frappe.get_cached_value('Company', company, "default_currency") + } + + has_value = False + + for period in period_list: + key = period if consolidated else period.key + profit_loss[key] = flt(gross_income[0].get(key, 0)) - flt(gross_expense[0].get(key, 0)) + + if profit_loss[key]: + has_value=True + + if has_value: + return profit_loss + +def get_net_profit(non_gross_income, gross_income, gross_expense, non_gross_expense, period_list, company, currency=None, consolidated=False): + profit_loss = { + "account_name": "'" + _("Net Profit") + "'", + "account": "'" + _("Net Profit") + "'", + "warn_if_negative": True, + "currency": currency or frappe.get_cached_value('Company', company, "default_currency") + } + + has_value = False + + for period in period_list: + key = period if consolidated else period.key + total_income = flt(gross_income[0].get(key, 0)) + flt(non_gross_income[0].get(key, 0)) + total_expense = flt(gross_expense[0].get(key, 0)) + flt(non_gross_expense[0].get(key, 0)) + profit_loss[key] = flt(total_income) - flt(total_expense) + + if profit_loss[key]: + has_value=True + + if has_value: + return profit_loss diff --git a/erpnext/accounts/report/gross_profit/gross_profit.py b/erpnext/accounts/report/gross_profit/gross_profit.py index 01211a976f3..e5aaafaff49 100644 --- a/erpnext/accounts/report/gross_profit/gross_profit.py +++ b/erpnext/accounts/report/gross_profit/gross_profit.py @@ -6,7 +6,7 @@ import frappe from frappe import _, scrub from erpnext.stock.utils import get_incoming_rate from erpnext.controllers.queries import get_match_cond -from frappe.utils import flt +from frappe.utils import flt, cint def execute(filters=None): @@ -106,11 +106,14 @@ class GrossProfitGenerator(object): self.grouped = {} self.grouped_data = [] + self.currency_precision = cint(frappe.db.get_default("currency_precision")) or 3 + self.float_precision = cint(frappe.db.get_default("float_precision")) or 2 + for row in self.si_list: if self.skip_row(row, self.product_bundles): continue - row.base_amount = flt(row.base_net_amount) + row.base_amount = flt(row.base_net_amount, self.currency_precision) product_bundles = [] if row.update_stock: @@ -122,22 +125,23 @@ class GrossProfitGenerator(object): # get buying amount if row.item_code in product_bundles: - row.buying_amount = self.get_buying_amount_from_product_bundle(row, - product_bundles[row.item_code]) + row.buying_amount = flt(self.get_buying_amount_from_product_bundle(row, + product_bundles[row.item_code]), self.currency_precision) else: - row.buying_amount = self.get_buying_amount(row, row.item_code) + row.buying_amount = flt(self.get_buying_amount(row, row.item_code), + self.currency_precision) # get buying rate if row.qty: - row.buying_rate = row.buying_amount / row.qty - row.base_rate = row.base_amount / row.qty + row.buying_rate = flt(row.buying_amount / row.qty, self.float_precision) + row.base_rate = flt(row.base_amount / row.qty, self.float_precision) else: row.buying_rate, row.base_rate = 0.0, 0.0 # calculate gross profit - row.gross_profit = row.base_amount - row.buying_amount + row.gross_profit = flt(row.base_amount - row.buying_amount, self.currency_precision) if row.base_amount: - row.gross_profit_percent = (row.gross_profit / row.base_amount) * 100.0 + row.gross_profit_percent = flt((row.gross_profit / row.base_amount) * 100.0, self.currency_precision) else: row.gross_profit_percent = 0.0 @@ -156,8 +160,8 @@ class GrossProfitGenerator(object): new_row = row else: new_row.qty += row.qty - new_row.buying_amount += row.buying_amount - new_row.base_amount += row.base_amount + new_row.buying_amount += flt(row.buying_amount, self.currency_precision) + new_row.base_amount += flt(row.base_amount, self.currency_precision) new_row = self.set_average_rate(new_row) self.grouped_data.append(new_row) else: @@ -167,18 +171,19 @@ class GrossProfitGenerator(object): returned_item_rows = self.returned_invoices[row.parent][row.item_code] for returned_item_row in returned_item_rows: row.qty += returned_item_row.qty - row.base_amount += returned_item_row.base_amount - row.buying_amount = row.qty * row.buying_rate + row.base_amount += flt(returned_item_row.base_amount, self.currency_precision) + row.buying_amount = flt(row.qty * row.buying_rate, self.currency_precision) if row.qty or row.base_amount: row = self.set_average_rate(row) self.grouped_data.append(row) def set_average_rate(self, new_row): - new_row.gross_profit = new_row.base_amount - new_row.buying_amount - new_row.gross_profit_percent = ((new_row.gross_profit / new_row.base_amount) * 100.0) \ + new_row.gross_profit = flt(new_row.base_amount - new_row.buying_amount, self.currency_precision) + new_row.gross_profit_percent = flt(((new_row.gross_profit / new_row.base_amount) * 100.0), self.currency_precision) \ if new_row.base_amount else 0 - new_row.buying_rate = (new_row.buying_amount / new_row.qty) if new_row.qty else 0 - new_row.base_rate = (new_row.base_amount / new_row.qty) if new_row.qty else 0 + new_row.buying_rate = flt(new_row.buying_amount / new_row.qty, self.float_precision) if new_row.qty else 0 + new_row.base_rate = flt(new_row.base_amount / new_row.qty, self.float_precision) if new_row.qty else 0 + return new_row def get_returned_invoice_items(self): @@ -211,7 +216,7 @@ class GrossProfitGenerator(object): if packed_item.get("parent_detail_docname")==row.item_row: buying_amount += self.get_buying_amount(row, packed_item.item_code) - return buying_amount + return flt(buying_amount, self.currency_precision) def get_buying_amount(self, row, item_code): # IMP NOTE diff --git a/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py b/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py index 88c612e7f6c..e8b19b40249 100644 --- a/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py +++ b/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py @@ -54,8 +54,10 @@ def _execute(filters=None, additional_table_columns=None, additional_query_colum delivery_note, d.income_account, d.cost_center, d.stock_qty, d.stock_uom ] - row += [(d.base_net_rate * d.qty)/d.stock_qty, d.base_net_amount] \ - if d.stock_uom != d.uom and d.stock_qty != 0 else [d.base_net_rate, d.base_net_amount] + if d.stock_uom != d.uom and d.stock_qty: + row += [(d.base_net_rate * d.qty)/d.stock_qty, d.base_net_amount] + else: + row += [d.base_net_rate, d.base_net_amount] total_tax = 0 for tax in tax_columns: @@ -108,13 +110,13 @@ def get_conditions(filters): conditions += """ and exists(select name from `tabSales Invoice Payment` where parent=`tabSales Invoice`.name and ifnull(`tabSales Invoice Payment`.mode_of_payment, '') = %(mode_of_payment)s)""" - + if filters.get("warehouse"): conditions += """ and exists(select name from `tabSales Invoice Item` where parent=`tabSales Invoice`.name and ifnull(`tabSales Invoice Item`.warehouse, '') = %(warehouse)s)""" - + if filters.get("brand"): conditions += """ and exists(select name from `tabSales Invoice Item` where parent=`tabSales Invoice`.name @@ -131,10 +133,10 @@ def get_conditions(filters): def get_items(filters, additional_query_columns): conditions = get_conditions(filters) match_conditions = frappe.build_match_conditions("Sales Invoice") - + if match_conditions: match_conditions = " and {0} ".format(match_conditions) - + if additional_query_columns: additional_query_columns = ', ' + ', '.join(additional_query_columns) diff --git a/erpnext/accounts/report/profitability_analysis/profitability_analysis.py b/erpnext/accounts/report/profitability_analysis/profitability_analysis.py index 39706acde0f..a0d8c5f0e4e 100644 --- a/erpnext/accounts/report/profitability_analysis/profitability_analysis.py +++ b/erpnext/accounts/report/profitability_analysis/profitability_analysis.py @@ -133,6 +133,13 @@ def get_columns(filters): "options": filters.get("based_on"), "width": 300 }, + { + "fieldname": "currency", + "label": _("Currency"), + "fieldtype": "Link", + "options": "Currency", + "hidden": 1 + }, { "fieldname": "income", "label": _("Income"), @@ -153,13 +160,6 @@ def get_columns(filters): "fieldtype": "Currency", "options": "currency", "width": 120 - }, - { - "fieldname": "currency", - "label": _("Currency"), - "fieldtype": "Link", - "options": "Currency", - "hidden": 1 } ] @@ -191,4 +191,4 @@ def set_gl_entries_by_account(company, from_date, to_date, based_on, gl_entries_ for entry in gl_entries: gl_entries_by_account.setdefault(entry.based_on, []).append(entry) - return gl_entries_by_account \ No newline at end of file + return gl_entries_by_account diff --git a/erpnext/accounts/report/purchase_register/purchase_register.py b/erpnext/accounts/report/purchase_register/purchase_register.py index e33b90d0196..3f8abb76e26 100644 --- a/erpnext/accounts/report/purchase_register/purchase_register.py +++ b/erpnext/accounts/report/purchase_register/purchase_register.py @@ -66,8 +66,8 @@ def _execute(filters=None, additional_table_columns=None, additional_query_colum total_tax += tax_amount row.append(tax_amount) - # total tax, grand total, outstanding amount & rounded total - row += [total_tax, inv.base_grand_total, flt(inv.base_grand_total, 2), inv.outstanding_amount] + # total tax, grand total, rounded total & outstanding amount + row += [total_tax, inv.base_grand_total, flt(inv.base_grand_total, 0), inv.outstanding_amount] data.append(row) return columns, data diff --git a/erpnext/accounts/report/supplier_ledger_summary/supplier_ledger_summary.js b/erpnext/accounts/report/supplier_ledger_summary/supplier_ledger_summary.js index 6fd16f20908..f81297760ed 100644 --- a/erpnext/accounts/report/supplier_ledger_summary/supplier_ledger_summary.js +++ b/erpnext/accounts/report/supplier_ledger_summary/supplier_ledger_summary.js @@ -35,9 +35,9 @@ frappe.query_reports["Supplier Ledger Summary"] = { }, { "fieldname":"party", - "label": __("Customer"), + "label": __("Supplier"), "fieldtype": "Link", - "options": "Customer", + "options": "Supplier", on_change: () => { var party = frappe.query_report.get_filter_value('party'); if (party) { 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 e55c022452d..8ca466e4b88 100644 --- a/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py +++ b/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py @@ -55,12 +55,15 @@ def get_result(filters): supplier = supplier_map[d] tds_doc = tds_docs[supplier.tax_withholding_category] - account = [i.account for i in tds_doc.accounts if i.company == filters.company][0] + account_list = [i.account for i in tds_doc.accounts if i.company == filters.company] + + if account_list: + account = account_list[0] for k in gle_map[d]: if k.party == supplier_map[d] and k.credit > 0: total_amount_credited += k.credit - elif k.account == account and k.credit > 0: + elif account_list and k.account == account and k.credit > 0: tds_deducted = k.credit total_amount_credited += k.credit diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py index 226776e9858..e9ae6ee21ac 100644 --- a/erpnext/accounts/utils.py +++ b/erpnext/accounts/utils.py @@ -544,14 +544,14 @@ def fix_total_debit_credit(): (dr_or_cr, dr_or_cr, '%s', '%s', '%s', dr_or_cr), (d.diff, d.voucher_type, d.voucher_no)) -def get_stock_and_account_difference(account_list=None, posting_date=None): +def get_stock_and_account_difference(account_list=None, posting_date=None, company=None): from erpnext.stock.utils import get_stock_value_on from erpnext.stock import get_warehouse_account_map if not posting_date: posting_date = nowdate() difference = {} - warehouse_account = get_warehouse_account_map() + warehouse_account = get_warehouse_account_map(company) for warehouse, account_data in iteritems(warehouse_account): if account_data.get('account') in account_list: diff --git a/erpnext/assets/doctype/asset/asset.js b/erpnext/assets/doctype/asset/asset.js index ed02d87e446..18ba8f9b5cb 100644 --- a/erpnext/assets/doctype/asset/asset.js +++ b/erpnext/assets/doctype/asset/asset.js @@ -31,7 +31,7 @@ frappe.ui.form.on('Asset', { } }; }); - + frm.set_query("cost_center", function() { return { "filters": { @@ -206,12 +206,10 @@ frappe.ui.form.on('Asset', { erpnext.asset.set_accululated_depreciation(frm); }, - depreciation_method: function(frm) { - frm.events.make_schedules_editable(frm); - }, - make_schedules_editable: function(frm) { - var is_editable = frm.doc.depreciation_method==="Manual" ? true : false; + var is_editable = frm.doc.finance_books.filter(d => d.depreciation_method == "Manual").length > 0 + ? true : false; + frm.toggle_enable("schedules", is_editable); frm.fields_dict["schedules"].grid.toggle_enable("schedule_date", is_editable); frm.fields_dict["schedules"].grid.toggle_enable("depreciation_amount", is_editable); @@ -296,6 +294,44 @@ frappe.ui.form.on('Asset', { }) frm.toggle_reqd("finance_books", frm.doc.calculate_depreciation); + }, + + set_depreciation_rate: function(frm, row) { + if (row.total_number_of_depreciations && row.frequency_of_depreciation) { + frappe.call({ + method: "get_depreciation_rate", + doc: frm.doc, + args: row, + callback: function(r) { + if (r.message) { + frappe.model.set_value(row.doctype, row.name, "rate_of_depreciation", r.message); + } + } + }); + } + } +}); + +frappe.ui.form.on('Asset Finance Book', { + depreciation_method: function(frm, cdt, cdn) { + const row = locals[cdt][cdn]; + frm.events.set_depreciation_rate(frm, row); + frm.events.make_schedules_editable(frm); + }, + + expected_value_after_useful_life: function(frm, cdt, cdn) { + const row = locals[cdt][cdn]; + frm.events.set_depreciation_rate(frm, row); + }, + + frequency_of_depreciation: function(frm, cdt, cdn) { + const row = locals[cdt][cdn]; + frm.events.set_depreciation_rate(frm, row); + }, + + total_number_of_depreciations: function(frm, cdt, cdn) { + const row = locals[cdt][cdn]; + frm.events.set_depreciation_rate(frm, row); } }); diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py index a38b40bc60b..8011038b1b1 100644 --- a/erpnext/assets/doctype/asset/asset.py +++ b/erpnext/assets/doctype/asset/asset.py @@ -3,8 +3,9 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe, erpnext +import frappe, erpnext, math, json from frappe import _ +from six import string_types from frappe.utils import flt, add_months, cint, nowdate, getdate, today, date_diff from frappe.model.document import Document from erpnext.assets.doctype.asset_category.asset_category import get_asset_category_account @@ -20,6 +21,7 @@ class Asset(AccountsController): self.validate_item() self.set_missing_values() if self.calculate_depreciation: + self.set_depreciation_rate() self.make_depreciation_schedule() self.set_accumulated_depreciation() else: @@ -33,7 +35,7 @@ class Asset(AccountsController): self.validate_in_use_date() self.set_status() self.update_stock_movement() - if not self.booked_fixed_asset: + if not self.booked_fixed_asset and not is_cwip_accounting_disabled(): self.make_gl_entries() def on_cancel(self): @@ -71,14 +73,15 @@ class Asset(AccountsController): if not flt(self.gross_purchase_amount): frappe.throw(_("Gross Purchase Amount is mandatory"), frappe.MandatoryError) - if not self.is_existing_asset and not (self.purchase_receipt or self.purchase_invoice): - frappe.throw(_("Please create purchase receipt or purchase invoice for the item {0}"). - format(self.item_code)) + if not is_cwip_accounting_disabled(): + if not self.is_existing_asset and not (self.purchase_receipt or self.purchase_invoice): + frappe.throw(_("Please create purchase receipt or purchase invoice for the item {0}"). + format(self.item_code)) - if (not self.purchase_receipt and self.purchase_invoice - and not frappe.db.get_value('Purchase Invoice', self.purchase_invoice, 'update_stock')): - frappe.throw(_("Update stock must be enable for the purchase invoice {0}"). - format(self.purchase_invoice)) + if (not self.purchase_receipt and self.purchase_invoice + and not frappe.db.get_value('Purchase Invoice', self.purchase_invoice, 'update_stock')): + frappe.throw(_("Update stock must be enable for the purchase invoice {0}"). + format(self.purchase_invoice)) if not self.calculate_depreciation: return @@ -88,17 +91,22 @@ class Asset(AccountsController): if self.is_existing_asset: return - date = nowdate() docname = self.purchase_receipt or self.purchase_invoice if docname: doctype = 'Purchase Receipt' if self.purchase_receipt else 'Purchase Invoice' date = frappe.db.get_value(doctype, docname, 'posting_date') - if self.available_for_use_date and getdate(self.available_for_use_date) < getdate(date): + if self.available_for_use_date and getdate(self.available_for_use_date) < getdate(self.purchase_date): frappe.throw(_("Available-for-use Date should be after purchase date")) + def set_depreciation_rate(self): + for d in self.get("finance_books"): + d.rate_of_depreciation = self.get_depreciation_rate(d) + def make_depreciation_schedule(self): - if self.depreciation_method != 'Manual': + depreciation_method = [d.depreciation_method for d in self.finance_books] + + if 'Manual' not in depreciation_method: self.schedules = [] if not self.get("schedules") and self.available_for_use_date: @@ -253,14 +261,16 @@ class Asset(AccountsController): return flt(self.get('finance_books')[cint(idx)-1].value_after_depreciation) def get_depreciation_amount(self, depreciable_value, total_number_of_depreciations, row): - percentage_value = 100.0 if row.depreciation_method == 'Written Down Value' else 200.0 + if row.depreciation_method in ["Straight Line", "Manual"]: + amt = (flt(self.gross_purchase_amount) - flt(row.expected_value_after_useful_life) - + flt(self.opening_accumulated_depreciation)) - factor = percentage_value / total_number_of_depreciations - depreciation_amount = flt(depreciable_value * factor / 100, 0) - - value_after_depreciation = flt(depreciable_value) - depreciation_amount - if value_after_depreciation < flt(row.expected_value_after_useful_life): - depreciation_amount = flt(depreciable_value) - flt(row.expected_value_after_useful_life) + depreciation_amount = amt * row.rate_of_depreciation + else: + depreciation_amount = flt(depreciable_value) * (flt(row.rate_of_depreciation) / 100) + value_after_depreciation = flt(depreciable_value) - depreciation_amount + if value_after_depreciation < flt(row.expected_value_after_useful_life): + depreciation_amount = flt(depreciable_value) - flt(row.expected_value_after_useful_life) return depreciation_amount @@ -275,7 +285,7 @@ class Asset(AccountsController): flt(row.expected_value_after_useful_life)) / (cint(row.total_number_of_depreciations) - cint(self.number_of_depreciations_booked)) * prorata_temporis else: - depreciation_amount = self.get_depreciation_amount(depreciable_value, row) + depreciation_amount = self.get_depreciation_amount(depreciable_value, row.total_number_of_depreciations, row) return depreciation_amount @@ -393,6 +403,32 @@ class Asset(AccountsController): make_gl_entries(gl_entries) self.db_set('booked_fixed_asset', 1) + def get_depreciation_rate(self, args): + if isinstance(args, string_types): + args = json.loads(args) + + number_of_depreciations_booked = 0 + if self.is_existing_asset: + number_of_depreciations_booked = self.number_of_depreciations_booked + + float_precision = cint(frappe.db.get_default("float_precision")) or 2 + tot_no_of_depreciation = flt(args.get("total_number_of_depreciations")) - flt(number_of_depreciations_booked) + + if args.get("depreciation_method") in ["Straight Line", "Manual"]: + return 1.0 / tot_no_of_depreciation + + if args.get("depreciation_method") == 'Double Declining Balance': + return 200.0 / args.get("total_number_of_depreciations") + + if args.get("depreciation_method") == "Written Down Value" and not args.get("rate_of_depreciation"): + no_of_years = flt(args.get("total_number_of_depreciations") * flt(args.get("frequency_of_depreciation"))) / 12 + value = flt(args.get("expected_value_after_useful_life")) / flt(self.gross_purchase_amount) + + # square root of flt(salvage_value) / flt(asset_cost) + depreciation_rate = math.pow(value, 1.0/flt(no_of_years, 2)) + + return 100 * (1 - flt(depreciation_rate, float_precision)) + def update_maintenance_status(): assets = frappe.get_all('Asset', filters = {'docstatus': 1, 'maintenance_required': 1}) @@ -404,6 +440,9 @@ def update_maintenance_status(): asset.set_status('Out of Order') def make_post_gl_entry(): + if is_cwip_accounting_disabled(): + return + assets = frappe.db.sql_list(""" select name from `tabAsset` where ifnull(booked_fixed_asset, 0) = 0 and available_for_use_date = %s""", nowdate()) @@ -476,7 +515,6 @@ def create_asset_adjustment(asset, asset_category, company): @frappe.whitelist() def transfer_asset(args): - import json args = json.loads(args) if args.get('serial_no'): @@ -551,3 +589,6 @@ def make_journal_entry(asset_name): }) return je + +def is_cwip_accounting_disabled(): + return cint(frappe.db.get_single_value("Asset Settings", "disable_cwip_accounting")) diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py index a12348e451b..985097b447d 100644 --- a/erpnext/assets/doctype/asset/test_asset.py +++ b/erpnext/assets/doctype/asset/test_asset.py @@ -160,9 +160,9 @@ class TestAsset(unittest.TestCase): asset.save() expected_schedules = [ - ["2020-06-06", 66667.0, 66667.0], - ["2021-04-06", 22222.0, 88889.0], - ["2022-02-06", 1111.0, 90000.0] + ["2020-06-06", 66666.67, 66666.67], + ["2021-04-06", 22222.22, 88888.89], + ["2022-02-06", 1111.11, 90000.0] ] schedules = [[cstr(d.schedule_date), d.depreciation_amount, d.accumulated_depreciation_amount] @@ -192,8 +192,8 @@ class TestAsset(unittest.TestCase): asset.save() expected_schedules = [ - ["2020-06-06", 33333.0, 83333.0], - ["2021-04-06", 6667.0, 90000.0] + ["2020-06-06", 33333.33, 83333.33], + ["2021-04-06", 6666.67, 90000.0] ] schedules = [[cstr(d.schedule_date), d.depreciation_amount, d.accumulated_depreciation_amount] @@ -209,7 +209,7 @@ class TestAsset(unittest.TestCase): asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, 'name') asset = frappe.get_doc('Asset', asset_name) asset.calculate_depreciation = 1 - asset.purchase_date = '2020-06-06' + asset.purchase_date = '2020-01-30' asset.is_existing_asset = 0 asset.available_for_use_date = "2020-01-30" asset.append("finance_books", { @@ -244,7 +244,7 @@ class TestAsset(unittest.TestCase): asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, 'name') asset = frappe.get_doc('Asset', asset_name) asset.calculate_depreciation = 1 - asset.purchase_date = '2020-06-06' + asset.purchase_date = '2020-01-30' asset.available_for_use_date = "2020-01-30" asset.append("finance_books", { "expected_value_after_useful_life": 10000, @@ -277,6 +277,37 @@ class TestAsset(unittest.TestCase): self.assertEqual(gle, expected_gle) self.assertEqual(asset.get("value_after_depreciation"), 0) + def test_depreciation_entry_for_wdv(self): + pr = make_purchase_receipt(item_code="Macbook Pro", + qty=1, rate=8000.0, location="Test Location") + + asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, 'name') + asset = frappe.get_doc('Asset', asset_name) + asset.calculate_depreciation = 1 + asset.available_for_use_date = '2030-06-06' + asset.purchase_date = '2030-06-06' + asset.append("finance_books", { + "expected_value_after_useful_life": 1000, + "depreciation_method": "Written Down Value", + "total_number_of_depreciations": 3, + "frequency_of_depreciation": 12, + "depreciation_start_date": "2030-12-31" + }) + asset.save(ignore_permissions=True) + + self.assertEqual(asset.finance_books[0].rate_of_depreciation, 50.0) + + expected_schedules = [ + ["2030-12-31", 4000.0, 4000.0], + ["2031-12-31", 2000.0, 6000.0], + ["2032-12-31", 1000.0, 7000.0], + ] + + schedules = [[cstr(d.schedule_date), flt(d.depreciation_amount, 2), flt(d.accumulated_depreciation_amount, 2)] + for d in asset.get("schedules")] + + self.assertEqual(schedules, expected_schedules) + def test_depreciation_entry_cancellation(self): pr = make_purchase_receipt(item_code="Macbook Pro", qty=1, rate=100000.0, location="Test Location") diff --git a/erpnext/assets/doctype/asset_finance_book/asset_finance_book.json b/erpnext/assets/doctype/asset_finance_book/asset_finance_book.json index f75c8510dcb..c80f95e1555 100644 --- a/erpnext/assets/doctype/asset_finance_book/asset_finance_book.json +++ b/erpnext/assets/doctype/asset_finance_book/asset_finance_book.json @@ -1,5 +1,6 @@ { "allow_copy": 0, + "allow_events_in_timeline": 0, "allow_guest_to_view": 0, "allow_import": 0, "allow_rename": 0, @@ -14,11 +15,13 @@ "fields": [ { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, "columns": 0, "depends_on": "", + "fetch_if_empty": 0, "fieldname": "finance_book", "fieldtype": "Link", "hidden": 0, @@ -42,14 +45,17 @@ "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_if_empty": 0, "fieldname": "depreciation_method", "fieldtype": "Select", "hidden": 0, @@ -73,14 +79,17 @@ "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, + "fetch_if_empty": 0, "fieldname": "total_number_of_depreciations", "fieldtype": "Int", "hidden": 0, @@ -103,14 +112,17 @@ "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, + "fetch_if_empty": 0, "fieldname": "column_break_5", "fieldtype": "Column Break", "hidden": 0, @@ -133,14 +145,17 @@ "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_if_empty": 0, "fieldname": "frequency_of_depreciation", "fieldtype": "Int", "hidden": 0, @@ -163,15 +178,18 @@ "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": "eval:parent.doctype == 'Asset'", + "fetch_if_empty": 0, "fieldname": "depreciation_start_date", "fieldtype": "Date", "hidden": 0, @@ -194,16 +212,19 @@ "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, "default": "0", "depends_on": "eval:parent.doctype == 'Asset'", + "fetch_if_empty": 0, "fieldname": "expected_value_after_useful_life", "fieldtype": "Currency", "hidden": 0, @@ -227,14 +248,17 @@ "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_if_empty": 0, "fieldname": "value_after_depreciation", "fieldtype": "Currency", "hidden": 1, @@ -258,20 +282,54 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "eval:doc.depreciation_method == 'Written Down Value'", + "description": "In Percentage", + "fetch_if_empty": 0, + "fieldname": "rate_of_depreciation", + "fieldtype": "Percent", + "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": "Rate of Depreciation", + "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 } ], "has_web_view": 0, - "hide_heading": 0, "hide_toolbar": 0, "idx": 0, - "image_view": 0, "in_create": 0, "is_submittable": 0, "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2018-05-12 14:56:44.800046", + "modified": "2019-04-09 19:45:14.523488", "modified_by": "Administrator", "module": "Assets", "name": "Asset Finance Book", @@ -280,10 +338,10 @@ "permissions": [], "quick_entry": 1, "read_only": 0, - "read_only_onload": 0, "show_name_in_global_search": 0, "sort_field": "modified", "sort_order": "DESC", "track_changes": 1, - "track_seen": 0 + "track_seen": 0, + "track_views": 0 } \ No newline at end of file diff --git a/erpnext/assets/doctype/asset_settings/asset_settings.json b/erpnext/assets/doctype/asset_settings/asset_settings.json index d6ddd33c302..a3fee96f4ee 100644 --- a/erpnext/assets/doctype/asset_settings/asset_settings.json +++ b/erpnext/assets/doctype/asset_settings/asset_settings.json @@ -1,5 +1,6 @@ { "allow_copy": 0, + "allow_events_in_timeline": 0, "allow_guest_to_view": 0, "allow_import": 0, "allow_rename": 0, @@ -14,10 +15,12 @@ "fields": [ { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "depreciation_options", "fieldtype": "Section Break", "hidden": 0, @@ -40,14 +43,17 @@ "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_if_empty": 0, "fieldname": "schedule_based_on_fiscal_year", "fieldtype": "Check", "hidden": 0, @@ -70,10 +76,12 @@ "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, @@ -81,6 +89,7 @@ "default": "360", "depends_on": "eval:doc.schedule_based_on_fiscal_year", "description": "This value is used for pro-rata temporis calculation", + "fetch_if_empty": 0, "fieldname": "number_of_days_in_fiscal_year", "fieldtype": "Data", "hidden": 0, @@ -103,6 +112,40 @@ "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_if_empty": 0, + "fieldname": "disable_cwip_accounting", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Disable CWIP Accounting", + "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 } ], @@ -116,7 +159,7 @@ "issingle": 1, "istable": 0, "max_attachments": 0, - "modified": "2018-01-05 10:10:39.803255", + "modified": "2019-03-08 10:44:41.924547", "modified_by": "Administrator", "module": "Assets", "name": "Asset Settings", @@ -125,7 +168,6 @@ "permissions": [ { "amend": 0, - "apply_user_permissions": 0, "cancel": 0, "create": 1, "delete": 1, @@ -145,7 +187,6 @@ }, { "amend": 0, - "apply_user_permissions": 0, "cancel": 0, "create": 1, "delete": 1, @@ -171,5 +212,6 @@ "sort_field": "modified", "sort_order": "DESC", "track_changes": 1, - "track_seen": 0 + "track_seen": 0, + "track_views": 0 } \ No newline at end of file diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.py b/erpnext/buying/doctype/purchase_order/purchase_order.py index a4a636d6baa..e259c04acec 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.py +++ b/erpnext/buying/doctype/purchase_order/purchase_order.py @@ -379,7 +379,9 @@ def make_purchase_invoice(source_name, target_doc=None): def postprocess(source, target): set_missing_values(source, target) #Get the advance paid Journal Entries in Purchase Invoice Advance - target.set_advances() + + if target.get("allocate_advances_automatically"): + target.set_advances() def update_item(obj, target, source_parent): target.amount = flt(obj.amount) - flt(obj.billed_amt) @@ -388,9 +390,10 @@ def make_purchase_invoice(source_name, target_doc=None): item = get_item_defaults(target.item_code, source_parent.company) item_group = get_item_group_defaults(target.item_code, source_parent.company) - target.cost_center = frappe.db.get_value("Project", obj.project, "cost_center") \ - or item.get("buying_cost_center") \ - or item_group.get("buying_cost_center") + target.cost_center = (obj.cost_center + or frappe.db.get_value("Project", obj.project, "cost_center") + or item.get("buying_cost_center") + or item_group.get("buying_cost_center")) doc = get_mapped_doc("Purchase Order", source_name, { "Purchase Order": { diff --git a/erpnext/config/selling.py b/erpnext/config/selling.py index 94f31028311..99b8ce0e5ec 100644 --- a/erpnext/config/selling.py +++ b/erpnext/config/selling.py @@ -325,7 +325,7 @@ def get_data(): { "type": "help", "label": _("Sales Order to Payment"), - "youtube_id": "7AMq4lqkN4A" + "youtube_id": "1eP90MWoDQM" }, { "type": "help", diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index c10e6dcda74..2e3d9724dd9 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -116,6 +116,12 @@ class AccountsController(TransactionBase): self.validate_non_invoice_documents_schedule() def before_print(self): + if self.doctype in ['Journal Entry', 'Payment Entry', 'Sales Invoice', 'Purchase Invoice']: + self.gl_entries = frappe.get_list("GL Entry", filters={ + "voucher_type": self.doctype, + "voucher_no": self.name + }, fields=["account", "party_type", "party", "debit", "credit", "remarks"]) + if self.doctype in ['Purchase Order', 'Sales Order', 'Sales Invoice', 'Purchase Invoice', 'Supplier Quotation', 'Purchase Receipt', 'Delivery Note', 'Quotation']: if self.get("group_same_items"): diff --git a/erpnext/controllers/queries.py b/erpnext/controllers/queries.py index 4c16323ca3d..f8f1e544596 100644 --- a/erpnext/controllers/queries.py +++ b/erpnext/controllers/queries.py @@ -172,8 +172,8 @@ def item_query(doctype, txt, searchfield, start, page_len, filters, as_dict=Fals or tabItem.item_code LIKE %(txt)s or tabItem.item_group LIKE %(txt)s or tabItem.item_name LIKE %(txt)s - or tabItem.item_code IN (select parent from `tabItem Barcode` where barcode LIKE %(txt)s - {description_cond})) + or tabItem.item_code IN (select parent from `tabItem Barcode` where barcode LIKE %(txt)s) + {description_cond}) {fcond} {mcond} order by if(locate(%(_txt)s, name), locate(%(_txt)s, name), 99999), diff --git a/erpnext/controllers/sales_and_purchase_return.py b/erpnext/controllers/sales_and_purchase_return.py index 15294f633f5..f2b15ad20ce 100644 --- a/erpnext/controllers/sales_and_purchase_return.py +++ b/erpnext/controllers/sales_and_purchase_return.py @@ -2,8 +2,9 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe +import frappe, erpnext from frappe import _ +from frappe.model.meta import get_field_precision from frappe.utils import flt, get_datetime, format_datetime class StockOverReturnError(frappe.ValidationError): pass @@ -116,6 +117,10 @@ def validate_quantity(doc, args, ref, valid_items, already_returned_items): already_returned_data = already_returned_items.get(args.item_code) or {} + company_currency = erpnext.get_company_currency(doc.company) + stock_qty_precision = get_field_precision(frappe.get_meta(doc.doctype + " Item") + .get_field("stock_qty"), company_currency) + for column in fields: returned_qty = flt(already_returned_data.get(column, 0)) if len(already_returned_data) > 0 else 0 @@ -126,7 +131,7 @@ def validate_quantity(doc, args, ref, valid_items, already_returned_items): reference_qty = ref.get(column) * ref.get("conversion_factor", 1.0) current_stock_qty = args.get(column) * args.get("conversion_factor", 1.0) - max_returnable_qty = flt(reference_qty) - returned_qty + max_returnable_qty = flt(reference_qty, stock_qty_precision) - returned_qty label = column.replace('_', ' ').title() if reference_qty: @@ -135,7 +140,7 @@ def validate_quantity(doc, args, ref, valid_items, already_returned_items): elif returned_qty >= reference_qty and args.get(column): frappe.throw(_("Item {0} has already been returned") .format(args.item_code), StockOverReturnError) - elif abs(current_stock_qty) > max_returnable_qty: + elif abs(flt(current_stock_qty, stock_qty_precision)) > max_returnable_qty: frappe.throw(_("Row # {0}: Cannot return more than {1} for Item {2}") .format(args.idx, max_returnable_qty, args.item_code), StockOverReturnError) @@ -239,6 +244,10 @@ def make_return_doc(doctype, source_name, target_doc=None): doc.paid_amount = -1 * source.paid_amount doc.base_paid_amount = -1 * source.base_paid_amount + if doc.get("is_return") and hasattr(doc, "packed_items"): + for d in doc.get("packed_items"): + d.qty = d.qty * -1 + doc.discount_amount = -1 * source.discount_amount doc.run_method("calculate_taxes_and_totals") diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py index 0a3cd3499b1..d1ffd7db66d 100644 --- a/erpnext/controllers/stock_controller.py +++ b/erpnext/controllers/stock_controller.py @@ -26,7 +26,7 @@ class StockController(AccountsController): delete_gl_entries(voucher_type=self.doctype, voucher_no=self.name) if cint(erpnext.is_perpetual_inventory_enabled(self.company)): - warehouse_account = get_warehouse_account_map() + warehouse_account = get_warehouse_account_map(self.company) if self.docstatus==1: if not gl_entries: @@ -36,7 +36,7 @@ class StockController(AccountsController): if repost_future_gle: items, warehouses = self.get_items_and_warehouses() update_gl_entries_after(self.posting_date, self.posting_time, warehouses, items, - warehouse_account) + warehouse_account, company=self.company) elif self.doctype in ['Purchase Receipt', 'Purchase Invoice'] and self.docstatus == 1: gl_entries = [] gl_entries = self.get_asset_gl_entry(gl_entries) @@ -46,7 +46,7 @@ class StockController(AccountsController): default_cost_center=None): if not warehouse_account: - warehouse_account = get_warehouse_account_map() + warehouse_account = get_warehouse_account_map(self.company) sle_map = self.get_stock_ledger_details() voucher_details = self.get_voucher_details(default_expense_account, default_cost_center, sle_map) @@ -199,7 +199,8 @@ class StockController(AccountsController): def make_adjustment_entry(self, expected_gle, voucher_obj): from erpnext.accounts.utils import get_stock_and_account_difference account_list = [d.account for d in expected_gle] - acc_diff = get_stock_and_account_difference(account_list, expected_gle[0].posting_date) + acc_diff = get_stock_and_account_difference(account_list, + expected_gle[0].posting_date, self.company) cost_center = self.get_company_default("cost_center") stock_adjustment_account = self.get_company_default("stock_adjustment_account") @@ -361,13 +362,13 @@ class StockController(AccountsController): frappe.get_doc("Blanket Order", blanket_order).update_ordered_qty() def update_gl_entries_after(posting_date, posting_time, for_warehouses=None, for_items=None, - warehouse_account=None): + warehouse_account=None, company=None): def _delete_gl_entries(voucher_type, voucher_no): frappe.db.sql("""delete from `tabGL Entry` where voucher_type=%s and voucher_no=%s""", (voucher_type, voucher_no)) if not warehouse_account: - warehouse_account = get_warehouse_account_map() + warehouse_account = get_warehouse_account_map(company) future_stock_vouchers = get_future_stock_vouchers(posting_date, posting_time, for_warehouses, for_items) gle = get_voucherwise_gl_entries(future_stock_vouchers, posting_date) diff --git a/erpnext/controllers/tests/test_item_variant.py b/erpnext/controllers/tests/test_item_variant.py index d4b5dd2e1ef..c257215e718 100644 --- a/erpnext/controllers/tests/test_item_variant.py +++ b/erpnext/controllers/tests/test_item_variant.py @@ -42,10 +42,10 @@ def create_variant_with_tables(item, args): return variant def make_item_variant(): - frappe.delete_doc_if_exists("Item", "_Test Variant Item-S", force=1) - variant = create_variant_with_tables("_Test Variant Item", '{"Test Size": "Small"}') - variant.item_code = "_Test Variant Item-S" - variant.item_name = "_Test Variant Item-S" + frappe.delete_doc_if_exists("Item", "_Test Variant Item-XSL", force=1) + variant = create_variant_with_tables("_Test Variant Item", '{"Test Size": "Extra Small"}') + variant.item_code = "_Test Variant Item-XSL" + variant.item_name = "_Test Variant Item-XSL" variant.save() return variant diff --git a/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_methods.py b/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_methods.py index 3234e7a332a..124910e35de 100644 --- a/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_methods.py +++ b/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_methods.py @@ -162,6 +162,8 @@ def create_item_code(amazon_item_json, sku): igroup.parent_item_group = mws_settings.item_group igroup.insert() + item.append("item_defaults", {'company':mws_settings.company}) + item.insert(ignore_permissions=True) create_item_price(amazon_item_json, item.item_code) @@ -213,7 +215,7 @@ def get_orders(after_date): fulfillment_channels=["MFN", "AFN"], lastupdatedafter=after_date, orderstatus=statuses, - max_results='20') + max_results='50') while True: orders_list = [] @@ -432,8 +434,8 @@ def get_order_items(market_place_order_id): return final_order_items def get_item_code(order_item): - asin = order_item.ASIN - item_code = frappe.db.get_value("Item", {"amazon_item_code": asin}, "item_code") + sku = order_item.SellerSKU + item_code = frappe.db.get_value("Item", {"item_code": sku}, "item_code") if item_code: return item_code @@ -451,11 +453,16 @@ def get_charges_and_fees(market_place_order_id): shipment_item_list = return_as_list(shipment_event.ShipmentEvent.ShipmentItemList.ShipmentItem) for shipment_item in shipment_item_list: - charges = return_as_list(shipment_item.ItemChargeList.ChargeComponent) - fees = return_as_list(shipment_item.ItemFeeList.FeeComponent) + charges, fees = [] + + if 'ItemChargeList' in shipment_item.keys(): + charges = return_as_list(shipment_item.ItemChargeList.ChargeComponent) + + if 'ItemFeeList' in shipment_item.keys(): + fees = return_as_list(shipment_item.ItemFeeList.FeeComponent) for charge in charges: - if(charge.ChargeType != "Principal"): + if(charge.ChargeType != "Principal") and float(charge.ChargeAmount.CurrencyAmount) != 0: charge_account = get_account(charge.ChargeType) charges_fees.get("charges").append({ "charge_type":"Actual", @@ -465,13 +472,14 @@ def get_charges_and_fees(market_place_order_id): }) for fee in fees: - fee_account = get_account(fee.FeeType) - charges_fees.get("fees").append({ - "charge_type":"Actual", - "account_head": fee_account, - "tax_amount": fee.FeeAmount.CurrencyAmount, - "description": fee.FeeType + " for " + shipment_item.SellerSKU - }) + if float(fee.FeeAmount.CurrencyAmount) != 0: + fee_account = get_account(fee.FeeType) + charges_fees.get("fees").append({ + "charge_type":"Actual", + "account_head": fee_account, + "tax_amount": fee.FeeAmount.CurrencyAmount, + "description": fee.FeeType + " for " + shipment_item.SellerSKU + }) return charges_fees diff --git a/erpnext/erpnext_integrations/doctype/woocommerce_settings/woocommerce_settings.py b/erpnext/erpnext_integrations/doctype/woocommerce_settings/woocommerce_settings.py index 1edc1029565..10e307134d0 100644 --- a/erpnext/erpnext_integrations/doctype/woocommerce_settings/woocommerce_settings.py +++ b/erpnext/erpnext_integrations/doctype/woocommerce_settings/woocommerce_settings.py @@ -65,7 +65,7 @@ class WoocommerceSettings(Document): if not frappe.get_value("Item Group",{"name": "WooCommerce Products"}): item_group = frappe.new_doc("Item Group") item_group.item_group_name = "WooCommerce Products" - item_group.parent_item_group = "All Item Groups" + item_group.parent_item_group = _("All Item Groups") item_group.save() diff --git a/erpnext/healthcare/doctype/healthcare_service_unit_type/healthcare_service_unit_type.js b/erpnext/healthcare/doctype/healthcare_service_unit_type/healthcare_service_unit_type.js index 84255b2930b..288ebc40b4e 100644 --- a/erpnext/healthcare/doctype/healthcare_service_unit_type/healthcare_service_unit_type.js +++ b/erpnext/healthcare/doctype/healthcare_service_unit_type/healthcare_service_unit_type.js @@ -49,7 +49,7 @@ frappe.ui.form.on('Healthcare Service Unit Type', { var disable = function(frm){ var doc = frm.doc; frappe.call({ - method: "erpnext.healthcare.doctype.healthcare_service_unit_type.healthcare_service_unit_type.disable_enable", + method: "erpnext.healthcare.doctype.healthcare_service_unit_type.healthcare_service_unit_type.disable_enable", args: {status: 1, doc_name: doc.name, item: doc.item, is_billable: doc.is_billable}, callback: function(){ cur_frm.reload_doc(); @@ -60,7 +60,7 @@ var disable = function(frm){ var enable = function(frm){ var doc = frm.doc; frappe.call({ - method: "erpnext.healthcare.doctype.healthcare_service_unit_type.healthcare_service_unit_type.disable_enable", + method: "erpnext.healthcare.doctype.healthcare_service_unit_type.healthcare_service_unit_type.disable_enable", args: {status: 0, doc_name: doc.name, item: doc.item, is_billable: doc.is_billable}, callback: function(){ cur_frm.reload_doc(); diff --git a/erpnext/healthcare/doctype/healthcare_service_unit_type/healthcare_service_unit_type.py b/erpnext/healthcare/doctype/healthcare_service_unit_type/healthcare_service_unit_type.py index 727d035a80f..650499454b9 100644 --- a/erpnext/healthcare/doctype/healthcare_service_unit_type/healthcare_service_unit_type.py +++ b/erpnext/healthcare/doctype/healthcare_service_unit_type/healthcare_service_unit_type.py @@ -111,7 +111,7 @@ def change_item_code(item, item_code, doc_name): frappe.db.set_value("Healthcare Service Unit Type", doc_name, "item_code", item_code) @frappe.whitelist() -def disable_enable(status, doc_name, item, is_billable): +def disable_enable(status, doc_name, item=None, is_billable=None): frappe.db.set_value("Healthcare Service Unit Type", doc_name, "disabled", status) if(is_billable == 1): frappe.db.set_value("Item", item, "disabled", status) diff --git a/erpnext/hr/doctype/additional_salary/additional_salary.py b/erpnext/hr/doctype/additional_salary/additional_salary.py index 6f87954f502..968a1c4571c 100644 --- a/erpnext/hr/doctype/additional_salary/additional_salary.py +++ b/erpnext/hr/doctype/additional_salary/additional_salary.py @@ -11,16 +11,14 @@ from frappe.utils import getdate, date_diff class AdditionalSalary(Document): def validate(self): self.validate_dates() - if self.amount <= 0: - frappe.throw(_("Amount should be greater than zero.")) + if self.amount < 0: + frappe.throw(_("Amount should not be less than zero.")) def validate_dates(self): date_of_joining, relieving_date = frappe.db.get_value("Employee", self.employee, ["date_of_joining", "relieving_date"]) if date_of_joining and getdate(self.payroll_date) < getdate(date_of_joining): frappe.throw(_("Payroll date can not be less than employee's joining date")) - elif relieving_date and getdate(self.payroll_date) > getdate(relieving_date): - frappe.throw(_("To date can not greater than employee's relieving date")) def get_amount(self, sal_start_date, sal_end_date): start_date = getdate(sal_start_date) diff --git a/erpnext/hr/doctype/expense_claim/expense_claim.js b/erpnext/hr/doctype/expense_claim/expense_claim.js index 6bdab61d9df..6da718402bf 100644 --- a/erpnext/hr/doctype/expense_claim/expense_claim.js +++ b/erpnext/hr/doctype/expense_claim/expense_claim.js @@ -35,6 +35,7 @@ $.extend(cur_frm.cscript, new erpnext.hr.ExpenseClaimController({frm: cur_frm})) cur_frm.add_fetch('employee', 'company', 'company'); cur_frm.add_fetch('employee','employee_name','employee_name'); +cur_frm.add_fetch('expense_type','description','description'); cur_frm.cscript.onload = function(doc) { if (doc.__islocal) { diff --git a/erpnext/hr/doctype/expense_claim_detail/expense_claim_detail.json b/erpnext/hr/doctype/expense_claim_detail/expense_claim_detail.json index b8089908502..d4e70575e91 100644 --- a/erpnext/hr/doctype/expense_claim_detail/expense_claim_detail.json +++ b/erpnext/hr/doctype/expense_claim_detail/expense_claim_detail.json @@ -1,366 +1,378 @@ { - "allow_copy": 0, - "allow_guest_to_view": 0, - "allow_import": 0, - "allow_rename": 0, - "beta": 0, - "creation": "2013-02-22 01:27:46", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "editable_grid": 1, + "allow_copy": 0, + "allow_events_in_timeline": 0, + "allow_guest_to_view": 0, + "allow_import": 0, + "allow_rename": 0, + "beta": 0, + "creation": "2013-02-22 01:27:46", + "custom": 0, + "docstatus": 0, + "doctype": "DocType", + "editable_grid": 1, "fields": [ { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "expense_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": "Expense Date", - "length": 0, - "no_copy": 0, - "oldfieldname": "expense_date", - "oldfieldtype": "Date", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "print_width": "150px", - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "expense_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": "Expense Date", + "length": 0, + "no_copy": 0, + "oldfieldname": "expense_date", + "oldfieldtype": "Date", + "permlevel": 0, + "print_hide": 0, + "print_hide_if_no_value": 0, + "print_width": "150px", + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, "translatable": 0, - "unique": 0, + "unique": 0, "width": "150px" - }, + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_2", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "column_break_2", + "fieldtype": "Column Break", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "expense_type", - "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": "Expense Claim Type", - "length": 0, - "no_copy": 0, - "oldfieldname": "expense_type", - "oldfieldtype": "Link", - "options": "Expense Claim Type", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "print_width": "150px", - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "expense_type", + "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": "Expense Claim Type", + "length": 0, + "no_copy": 0, + "oldfieldname": "expense_type", + "oldfieldtype": "Link", + "options": "Expense Claim Type", + "permlevel": 0, + "print_hide": 0, + "print_hide_if_no_value": 0, + "print_width": "150px", + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 1, + "search_index": 0, + "set_only_once": 0, "translatable": 0, - "unique": 0, + "unique": 0, "width": "150px" - }, + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "expense_type", - "fieldname": "default_account", - "fieldtype": "Link", - "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Default Account", - "length": 0, - "no_copy": 0, - "options": "Account", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "expense_type", + "fieldname": "default_account", + "fieldtype": "Link", + "hidden": 1, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Default Account", + "length": 0, + "no_copy": 0, + "options": "Account", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 1, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "section_break_4", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "section_break_4", + "fieldtype": "Section Break", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_from": "expense_type.description", - "fieldname": "description", - "fieldtype": "Text Editor", - "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": "Description", - "length": 0, - "no_copy": 0, - "oldfieldname": "description", - "oldfieldtype": "Small Text", - "options": "", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "print_width": "300px", - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_from": "", + "fieldname": "description", + "fieldtype": "Text Editor", + "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": "Description", + "length": 0, + "no_copy": 0, + "oldfieldname": "description", + "oldfieldtype": "Small Text", + "options": "", + "permlevel": 0, + "print_hide": 0, + "print_hide_if_no_value": 0, + "print_width": "300px", + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, "translatable": 0, - "unique": 0, + "unique": 0, "width": "300px" - }, + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "section_break_6", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "section_break_6", + "fieldtype": "Section Break", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "claim_amount", - "fieldtype": "Currency", - "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": "Claim Amount", - "length": 0, - "no_copy": 0, - "oldfieldname": "claim_amount", - "oldfieldtype": "Currency", - "options": "Company:company:default_currency", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "print_width": "150px", - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "claim_amount", + "fieldtype": "Currency", + "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": "Claim Amount", + "length": 0, + "no_copy": 0, + "oldfieldname": "claim_amount", + "oldfieldtype": "Currency", + "options": "Company:company:default_currency", + "permlevel": 0, + "print_hide": 0, + "print_hide_if_no_value": 0, + "print_width": "150px", + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 1, + "search_index": 0, + "set_only_once": 0, "translatable": 0, - "unique": 0, + "unique": 0, "width": "150px" - }, + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_8", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "column_break_8", + "fieldtype": "Column Break", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "sanctioned_amount", - "fieldtype": "Currency", - "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": "Sanctioned Amount", - "length": 0, - "no_copy": 1, - "oldfieldname": "sanctioned_amount", - "oldfieldtype": "Currency", - "options": "Company:company:default_currency", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "print_width": "150px", - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "sanctioned_amount", + "fieldtype": "Currency", + "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": "Sanctioned Amount", + "length": 0, + "no_copy": 1, + "oldfieldname": "sanctioned_amount", + "oldfieldtype": "Currency", + "options": "Company:company:default_currency", + "permlevel": 0, + "print_hide": 0, + "print_hide_if_no_value": 0, + "print_width": "150px", + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, "translatable": 0, - "unique": 0, + "unique": 0, "width": "150px" } - ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "idx": 1, - "image_view": 0, - "in_create": 0, - "is_submittable": 0, - "issingle": 0, - "istable": 1, - "max_attachments": 0, - "modified": "2018-05-16 22:42:56.727863", - "modified_by": "Administrator", - "module": "HR", - "name": "Expense Claim Detail", - "owner": "harshada@webnotestech.com", - "permissions": [], - "quick_entry": 0, - "read_only": 0, - "read_only_onload": 0, - "show_name_in_global_search": 0, - "sort_field": "modified", - "sort_order": "DESC", - "track_changes": 0, - "track_seen": 0 + ], + "has_web_view": 0, + "hide_heading": 0, + "hide_toolbar": 0, + "idx": 1, + "image_view": 0, + "in_create": 0, + "is_submittable": 0, + "issingle": 0, + "istable": 1, + "max_attachments": 0, + "modified": "2019-02-24 08:41:36.122565", + "modified_by": "Administrator", + "module": "HR", + "name": "Expense Claim Detail", + "owner": "harshada@webnotestech.com", + "permissions": [], + "quick_entry": 0, + "read_only": 0, + "read_only_onload": 0, + "show_name_in_global_search": 0, + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 0, + "track_seen": 0, + "track_views": 0 } \ No newline at end of file diff --git a/erpnext/hr/doctype/leave_application/leave_application.py b/erpnext/hr/doctype/leave_application/leave_application.py index 6b7c0f7e79d..560dd1d3bfd 100755 --- a/erpnext/hr/doctype/leave_application/leave_application.py +++ b/erpnext/hr/doctype/leave_application/leave_application.py @@ -399,6 +399,19 @@ def get_leave_balance_on(employee, leave_type, date, allocation_records=None, do return flt(allocation.total_leaves_allocated) - (flt(leaves_taken) + flt(leaves_encashed)) +def get_total_allocated_leaves(employee, leave_type, date): + filters= { + 'from_date': ['<=', date], + 'to_date': ['>=', date], + 'docstatus': 1, + 'leave_type': leave_type, + 'employee': employee + } + + leave_allocation_records = frappe.db.get_all('Leave Allocation', filters=filters, fields=['total_leaves_allocated']) + + return flt(leave_allocation_records[0]['total_leaves_allocated']) if leave_allocation_records else flt(0) + def get_leaves_for_period(employee, leave_type, from_date, to_date, status, docname=None): leave_applications = frappe.db.sql(""" select name, employee, leave_type, from_date, to_date, total_leave_days @@ -487,7 +500,6 @@ def get_events(start, end, filters=None): add_block_dates(events, start, end, employee, company) add_holidays(events, start, end, employee, company) - return events def add_department_leaves(events, start, end, employee, company): @@ -500,19 +512,32 @@ def add_department_leaves(events, start, end, employee, company): department_employees = frappe.db.sql_list("""select name from tabEmployee where department=%s and company=%s""", (department, company)) - match_conditions = "and employee in (\"%s\")" % '", "'.join(department_employees) - add_leaves(events, start, end, match_conditions=match_conditions) + filter_conditions = " and employee in (\"%s\")" % '", "'.join(department_employees) + add_leaves(events, start, end, filter_conditions=filter_conditions) + +def add_leaves(events, start, end, filter_conditions=None): + conditions = [] + + + if not cint(frappe.db.get_value("HR Settings", None, "show_leaves_of_all_department_members_in_calendar")): + from frappe.desk.reportview import build_match_conditions + match_conditions = build_match_conditions("Leave Application") + + if match_conditions: + conditions.append(match_conditions) -def add_leaves(events, start, end, match_conditions=None): query = """select name, from_date, to_date, employee_name, half_day, status, employee, docstatus from `tabLeave Application` where from_date <= %(end)s and to_date >= %(start)s <= to_date and docstatus < 2 - and status!="Rejected" """ + and status!='Rejected' """ - if match_conditions: - query += match_conditions + if conditions: + query += ' and ' + ' and '.join(conditions) + + if filter_conditions: + query += filter_conditions for d in frappe.db.sql(query, {"start":start, "end": end}, as_dict=True): e = { diff --git a/erpnext/hr/doctype/salary_slip/salary_slip.py b/erpnext/hr/doctype/salary_slip/salary_slip.py index 3fd266b4bba..684f3483f06 100644 --- a/erpnext/hr/doctype/salary_slip/salary_slip.py +++ b/erpnext/hr/doctype/salary_slip/salary_slip.py @@ -441,7 +441,7 @@ class SalarySlip(TransactionBase): def calculate_net_pay(self): if self.salary_structure: self.calculate_component_amounts() - + disable_rounded_total = cint(frappe.db.get_value("Global Defaults", None, "disable_rounded_total")) precision = frappe.defaults.get_global_default("currency_precision") self.total_deduction = 0 @@ -452,10 +452,10 @@ class SalarySlip(TransactionBase): self.set_loan_repayment() - self.net_pay = flt(self.gross_pay) - (flt(self.total_deduction) + flt(self.total_loan_repayment)) + self.net_pay = (flt(self.gross_pay) - (flt(self.total_deduction) + flt(self.total_loan_repayment))) * flt(self.payment_days / self.total_working_days) self.rounded_total = rounded(self.net_pay, self.precision("net_pay") if disable_rounded_total else 0) - + if self.net_pay < 0: frappe.throw(_("Net Pay cannnot be negative")) diff --git a/erpnext/hr/doctype/staffing_plan/staffing_plan.py b/erpnext/hr/doctype/staffing_plan/staffing_plan.py index 70e185cde56..83e53135ef4 100644 --- a/erpnext/hr/doctype/staffing_plan/staffing_plan.py +++ b/erpnext/hr/doctype/staffing_plan/staffing_plan.py @@ -20,6 +20,7 @@ class StaffingPlan(Document): self.total_estimated_budget = 0 for detail in self.get("staffing_details"): + self.set_vacancies(detail) self.validate_overlap(detail) self.validate_with_subsidiary_plans(detail) self.validate_with_parent_plan(detail) @@ -39,6 +40,15 @@ class StaffingPlan(Document): else: detail.vacancies = detail.number_of_positions = detail.total_estimated_cost = 0 self.total_estimated_budget += detail.total_estimated_cost + def set_vacancies(self, row): + if not row.vacancies: + current_openings = 0 + for field in ['current_count', 'current_openings']: + if row.get(field): + current_openings += row.get(field) + + row.vacancies = row.number_of_positions - current_openings + def validate_overlap(self, staffing_plan_detail): # Validate if any submitted Staffing Plan exist for any Designations in this plan # and spd.vacancies>0 ? diff --git a/erpnext/hr/doctype/staffing_plan/test_staffing_plan.py b/erpnext/hr/doctype/staffing_plan/test_staffing_plan.py index 66d9cdd07a5..22dba99af00 100644 --- a/erpnext/hr/doctype/staffing_plan/test_staffing_plan.py +++ b/erpnext/hr/doctype/staffing_plan/test_staffing_plan.py @@ -18,7 +18,7 @@ class TestStaffingPlan(unittest.TestCase): if frappe.db.exists("Staffing Plan", "Test"): return staffing_plan = frappe.new_doc("Staffing Plan") - staffing_plan.company = "_Test Company 3" + staffing_plan.company = "_Test Company 10" staffing_plan.name = "Test" staffing_plan.from_date = nowdate() staffing_plan.to_date = add_days(nowdate(), 10) @@ -67,7 +67,7 @@ class TestStaffingPlan(unittest.TestCase): if frappe.db.exists("Staffing Plan", "Test 1"): return staffing_plan = frappe.new_doc("Staffing Plan") - staffing_plan.company = "_Test Company 3" + staffing_plan.company = "_Test Company 10" staffing_plan.name = "Test 1" staffing_plan.from_date = nowdate() staffing_plan.to_date = add_days(nowdate(), 10) @@ -85,11 +85,11 @@ def _set_up(): make_company() def make_company(): - if frappe.db.exists("Company", "_Test Company 3"): + if frappe.db.exists("Company", "_Test Company 10"): return company = frappe.new_doc("Company") - company.company_name = "_Test Company 3" - company.abbr = "_TC3" + company.company_name = "_Test Company 10" + company.abbr = "_TC10" company.parent_company = "_Test Company" company.default_currency = "INR" company.country = "India" diff --git a/erpnext/hr/doctype/training_feedback/training_feedback.py b/erpnext/hr/doctype/training_feedback/training_feedback.py index b7eae38ae48..b47e2b4be88 100644 --- a/erpnext/hr/doctype/training_feedback/training_feedback.py +++ b/erpnext/hr/doctype/training_feedback/training_feedback.py @@ -15,9 +15,11 @@ class TrainingFeedback(Document): def on_submit(self): training_event = frappe.get_doc("Training Event", self.training_event) + status = None for e in training_event.employees: if e.employee == self.employee: - training_event.status = 'Feedback Submitted' + status = 'Feedback Submitted' break - training_event.save() + if status: + frappe.db.set_value("Training Event", self.training_event, "status", status) diff --git a/erpnext/hr/report/employee_leave_balance/employee_leave_balance.py b/erpnext/hr/report/employee_leave_balance/employee_leave_balance.py index ed44d639f52..95cb30b7918 100644 --- a/erpnext/hr/report/employee_leave_balance/employee_leave_balance.py +++ b/erpnext/hr/report/employee_leave_balance/employee_leave_balance.py @@ -5,21 +5,21 @@ from __future__ import unicode_literals import frappe from frappe import _ from erpnext.hr.doctype.leave_application.leave_application \ - import get_leave_allocation_records, get_leave_balance_on, get_approved_leaves_for_period + import get_leave_allocation_records, get_leave_balance_on, get_approved_leaves_for_period, get_total_allocated_leaves def execute(filters=None): leave_types = frappe.db.sql_list("select name from `tabLeave Type` order by name asc") - + columns = get_columns(leave_types) data = get_data(filters, leave_types) - + return columns, data - + def get_columns(leave_types): columns = [ - _("Employee") + ":Link/Employee:150", - _("Employee Name") + "::200", + _("Employee") + ":Link/Employee:150", + _("Employee Name") + "::200", _("Department") +"::150" ] @@ -27,18 +27,18 @@ def get_columns(leave_types): columns.append(_(leave_type) + " " + _("Opening") + ":Float:160") columns.append(_(leave_type) + " " + _("Taken") + ":Float:160") columns.append(_(leave_type) + " " + _("Balance") + ":Float:160") - + return columns - + def get_data(filters, leave_types): user = frappe.session.user allocation_records_based_on_to_date = get_leave_allocation_records(filters.to_date) allocation_records_based_on_from_date = get_leave_allocation_records(filters.from_date) - active_employees = frappe.get_all("Employee", - filters = { "status": "Active", "company": filters.company}, + active_employees = frappe.get_all("Employee", + filters = { "status": "Active", "company": filters.company}, fields = ["name", "employee_name", "department", "user_id"]) - + data = [] for employee in active_employees: leave_approvers = get_approvers(employee.department) @@ -51,8 +51,7 @@ def get_data(filters, leave_types): filters.from_date, filters.to_date) # opening balance - opening = get_leave_balance_on(employee.name, leave_type, filters.from_date, - allocation_records_based_on_from_date.get(employee.name, frappe._dict())) + opening = get_total_allocated_leaves(employee.name, leave_type, filters.to_date) # closing balance closing = get_leave_balance_on(employee.name, leave_type, filters.to_date, @@ -61,7 +60,7 @@ def get_data(filters, leave_types): row += [opening, leaves_taken, closing] data.append(row) - + return data def get_approvers(department): diff --git a/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.py b/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.py index 6d082bd2005..2f2ad00e023 100644 --- a/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.py +++ b/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.py @@ -41,12 +41,19 @@ class MaintenanceVisit(TransactionBase): work_done = nm and nm[0][3] or '' else: status = 'Open' - mntc_date = '' - service_person = '' - work_done = '' + mntc_date = None + service_person = None + work_done = None - frappe.db.sql("update `tabWarranty Claim` set resolution_date=%s, resolved_by=%s, resolution_details=%s, status=%s where name =%s",(mntc_date,service_person,work_done,status,d.prevdoc_docname)) + wc_doc = frappe.get_doc('Warranty Claim', d.prevdoc_docname) + wc_doc.update({ + 'resolution_date': mntc_date, + 'resolved_by': service_person, + 'resolution_details': work_done, + 'status': status + }) + wc_doc.db_update() def check_if_last_visit(self): """check if last maintenance visit against same sales order/ Warranty Claim""" diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py index 88d346ff0f3..c65693bddf6 100644 --- a/erpnext/manufacturing/doctype/bom/bom.py +++ b/erpnext/manufacturing/doctype/bom/bom.py @@ -580,7 +580,7 @@ def get_list_context(context): context.title = _("Bill of Materials") # context.introduction = _('Boms') -def get_bom_items_as_dict(bom, company, qty=1, fetch_exploded=1, fetch_scrap_items=0, include_non_stock_items=False): +def get_bom_items_as_dict(bom, company, qty=1, fetch_exploded=1, fetch_scrap_items=0, include_non_stock_items=False, fetch_qty_in_stock_uom=True): item_dict = {} # Did not use qty_consumed_per_unit in the query, as it leads to rounding loss @@ -588,7 +588,7 @@ def get_bom_items_as_dict(bom, company, qty=1, fetch_exploded=1, fetch_scrap_ite bom_item.item_code, bom_item.idx, item.item_name, - sum(bom_item.stock_qty/ifnull(bom.quantity, 1)) * %(qty)s as qty, + sum(bom_item.{qty_field}/ifnull(bom.quantity, 1)) * %(qty)s as qty, item.description, item.image, item.stock_uom, @@ -616,16 +616,18 @@ def get_bom_items_as_dict(bom, company, qty=1, fetch_exploded=1, fetch_scrap_ite query = query.format(table="BOM Explosion Item", where_conditions="", is_stock_item=is_stock_item, + qty_field="stock_qty", select_columns = """, bom_item.source_warehouse, bom_item.operation, bom_item.include_item_in_manufacturing, - (Select idx from `tabBOM Item` where item_code = bom_item.item_code and parent = %(parent)s ) as idx""") + (Select idx from `tabBOM Item` where item_code = bom_item.item_code and parent = %(parent)s limit 1) as idx""") items = frappe.db.sql(query, { "parent": bom, "qty": qty, "bom": bom, "company": company }, as_dict=True) elif fetch_scrap_items: - query = query.format(table="BOM Scrap Item", where_conditions="", select_columns=", bom_item.idx", is_stock_item=is_stock_item) + query = query.format(table="BOM Scrap Item", where_conditions="", select_columns=", bom_item.idx", is_stock_item=is_stock_item, qty_field="stock_qty") items = frappe.db.sql(query, { "qty": qty, "bom": bom, "company": company }, as_dict=True) else: query = query.format(table="BOM Item", where_conditions="", is_stock_item=is_stock_item, - select_columns = ", bom_item.source_warehouse, bom_item.idx, bom_item.operation, bom_item.include_item_in_manufacturing") + qty_field="stock_qty" if fetch_qty_in_stock_uom else "qty", + select_columns = ", bom_item.uom, bom_item.conversion_factor, bom_item.source_warehouse, bom_item.idx, bom_item.operation, bom_item.include_item_in_manufacturing") items = frappe.db.sql(query, { "qty": qty, "bom": bom, "company": company }, as_dict=True) for item in items: @@ -706,8 +708,11 @@ def get_children(doctype, parent=None, is_root=False, **filters): def get_boms_in_bottom_up_order(bom_no=None): def _get_parent(bom_no): - return frappe.db.sql_list("""select distinct parent from `tabBOM Item` - where bom_no = %s and docstatus=1 and parenttype='BOM'""", bom_no) + return frappe.db.sql_list(""" + select distinct bom_item.parent from `tabBOM Item` bom_item + where bom_item.bom_no = %s and bom_item.docstatus=1 and bom_item.parenttype='BOM' + and exists(select bom.name from `tabBOM` bom where bom.name=bom_item.parent and bom.is_active=1) + """, bom_no) count = 0 bom_list = [] @@ -715,9 +720,10 @@ def get_boms_in_bottom_up_order(bom_no=None): bom_list.append(bom_no) else: # get all leaf BOMs - bom_list = frappe.db.sql_list("""select name from `tabBOM` bom where docstatus=1 - and not exists(select bom_no from `tabBOM Item` - where parent=bom.name and ifnull(bom_no, '')!='')""") + bom_list = frappe.db.sql_list("""select name from `tabBOM` bom + where docstatus=1 and is_active=1 + and not exists(select bom_no from `tabBOM Item` + where parent=bom.name and ifnull(bom_no, '')!='')""") while(count < len(bom_list)): for child_bom in _get_parent(bom_list[count]): diff --git a/erpnext/manufacturing/doctype/bom_item/bom_item.json b/erpnext/manufacturing/doctype/bom_item/bom_item.json index 22583605777..febf315988c 100644 --- a/erpnext/manufacturing/doctype/bom_item/bom_item.json +++ b/erpnext/manufacturing/doctype/bom_item/bom_item.json @@ -78,6 +78,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": "operation", + "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": "Item operation", + "length": 0, + "no_copy": 0, + "options": "Operation", + "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, @@ -893,6 +926,38 @@ "translatable": 0, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "allow_alternative_item", + "fieldtype": "Check", + "hidden": 1, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Allow Alternative Item", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 1, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, { "allow_bulk_edit": 0, "allow_in_quick_entry": 0, @@ -958,71 +1023,6 @@ "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": "operation", - "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": "Item operation", - "length": 0, - "no_copy": 0, - "options": "Operation", - "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": "allow_alternative_item", - "fieldtype": "Check", - "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Allow Alternative Item", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 } ], "has_web_view": 0, @@ -1035,7 +1035,7 @@ "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2018-11-23 15:05:55.187136", + "modified": "2019-02-21 19:19:54.872459", "modified_by": "Administrator", "module": "Manufacturing", "name": "BOM Item", @@ -1050,4 +1050,4 @@ "track_changes": 0, "track_seen": 0, "track_views": 0 -} +} \ No newline at end of file diff --git a/erpnext/manufacturing/doctype/job_card/job_card.js b/erpnext/manufacturing/doctype/job_card/job_card.js index 3fe9b8af30d..95549d5a248 100644 --- a/erpnext/manufacturing/doctype/job_card/job_card.js +++ b/erpnext/manufacturing/doctype/job_card/job_card.js @@ -18,20 +18,27 @@ frappe.ui.form.on('Job Card', { } if (frm.doc.docstatus == 0) { - if (!frm.doc.actual_start_date || !frm.doc.actual_end_date) { - frm.trigger("make_dashboard"); - } + frm.trigger("make_dashboard"); - if (!frm.doc.actual_start_date) { + if (!frm.doc.job_started) { frm.add_custom_button(__("Start Job"), () => { - frm.set_value('actual_start_date', frappe.datetime.now_datetime()); + let row = frappe.model.add_child(frm.doc, 'Job Card Time Log', 'time_logs'); + row.from_time = frappe.datetime.now_datetime(); + frm.set_value('job_started', 1); + frm.set_value('started_time' , row.from_time); frm.save(); }); - } else if (!frm.doc.actual_end_date) { + } else { frm.add_custom_button(__("Complete Job"), () => { - frm.set_value('actual_end_date', frappe.datetime.now_datetime()); - frm.save(); - frm.savesubmit(); + let completed_time = frappe.datetime.now_datetime(); + frm.doc.time_logs.forEach(d => { + if (d.from_time && !d.to_time) { + d.to_time = completed_time; + frm.set_value('started_time' , ''); + frm.set_value('job_started', 0); + frm.save(); + } + }) }); } } @@ -53,8 +60,8 @@ frappe.ui.form.on('Job Card', { var section = frm.dashboard.add_section(timer); - if (frm.doc.actual_start_date) { - let currentIncrement = moment(frappe.datetime.now_datetime()).diff(moment(frm.doc.actual_start_date),"seconds"); + if (frm.doc.started_time) { + let currentIncrement = moment(frappe.datetime.now_datetime()).diff(moment(frm.doc.started_time),"seconds"); initialiseTimer(); function initialiseTimer() { diff --git a/erpnext/manufacturing/doctype/job_card/job_card.json b/erpnext/manufacturing/doctype/job_card/job_card.json index b020c89053c..39c5cce313b 100644 --- a/erpnext/manufacturing/doctype/job_card/job_card.json +++ b/erpnext/manufacturing/doctype/job_card/job_card.json @@ -21,6 +21,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "work_order", "fieldtype": "Link", "hidden": 0, @@ -54,6 +55,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "bom_no", "fieldtype": "Link", "hidden": 0, @@ -87,6 +89,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "workstation", "fieldtype": "Link", "hidden": 0, @@ -120,6 +123,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "operation", "fieldtype": "Link", "hidden": 0, @@ -153,6 +157,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break_4", "fieldtype": "Column Break", "hidden": 0, @@ -185,6 +190,7 @@ "collapsible": 0, "columns": 0, "default": "Today", + "fetch_if_empty": 0, "fieldname": "posting_date", "fieldtype": "Date", "hidden": 0, @@ -217,6 +223,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "company", "fieldtype": "Link", "hidden": 0, @@ -250,6 +257,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "for_quantity", "fieldtype": "Float", "hidden": 0, @@ -282,6 +290,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "wip_warehouse", "fieldtype": "Link", "hidden": 0, @@ -315,6 +324,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "timing_detail", "fieldtype": "Section Break", "hidden": 0, @@ -347,6 +357,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "employee", "fieldtype": "Link", "hidden": 0, @@ -380,7 +391,74 @@ "bold": 0, "collapsible": 0, "columns": 0, - "fieldname": "time_in_mins", + "fetch_if_empty": 0, + "fieldname": "time_logs", + "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": "Time Logs", + "length": 0, + "no_copy": 0, + "options": "Job Card Time Log", + "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_if_empty": 0, + "fieldname": "section_break_13", + "fieldtype": "Section Break", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "total_completed_qty", "fieldtype": "Float", "hidden": 0, "ignore_user_permissions": 0, @@ -389,7 +467,7 @@ "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, - "label": "Time In Mins", + "label": "Total Completed Qty", "length": 0, "no_copy": 0, "permlevel": 0, @@ -412,7 +490,8 @@ "bold": 0, "collapsible": 0, "columns": 0, - "fieldname": "column_break_13", + "fetch_if_empty": 0, + "fieldname": "column_break_15", "fieldtype": "Column Break", "hidden": 0, "ignore_user_permissions": 0, @@ -443,8 +522,9 @@ "bold": 0, "collapsible": 0, "columns": 0, - "fieldname": "actual_start_date", - "fieldtype": "Datetime", + "fetch_if_empty": 0, + "fieldname": "total_time_in_mins", + "fieldtype": "Float", "hidden": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, @@ -452,46 +532,14 @@ "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, - "label": "Actual Start Date", + "label": "Total Time in Mins", "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": "actual_end_date", - "fieldtype": "Datetime", - "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": "Actual End Date", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, + "read_only": 1, "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, @@ -507,6 +555,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "section_break_8", "fieldtype": "Section Break", "hidden": 0, @@ -539,6 +588,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "items", "fieldtype": "Table", "hidden": 0, @@ -572,6 +622,7 @@ "bold": 0, "collapsible": 1, "columns": 0, + "fetch_if_empty": 0, "fieldname": "more_information", "fieldtype": "Section Break", "hidden": 0, @@ -604,6 +655,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "operation_id", "fieldtype": "Data", "hidden": 1, @@ -637,6 +689,7 @@ "collapsible": 0, "columns": 0, "default": "0", + "fetch_if_empty": 0, "fieldname": "transferred_qty", "fieldtype": "Float", "hidden": 0, @@ -670,6 +723,7 @@ "collapsible": 0, "columns": 0, "default": "0", + "fetch_if_empty": 0, "fieldname": "requested_qty", "fieldtype": "Float", "hidden": 0, @@ -702,6 +756,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "project", "fieldtype": "Link", "hidden": 0, @@ -735,6 +790,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "remarks", "fieldtype": "Small Text", "hidden": 0, @@ -767,6 +823,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break_20", "fieldtype": "Column Break", "hidden": 0, @@ -799,6 +856,7 @@ "collapsible": 0, "columns": 0, "default": "Open", + "fetch_if_empty": 0, "fieldname": "status", "fieldtype": "Select", "hidden": 0, @@ -832,6 +890,73 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, + "fieldname": "job_started", + "fieldtype": "Check", + "hidden": 1, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Job Started", + "length": 0, + "no_copy": 1, + "permlevel": 0, + "precision": "", + "print_hide": 1, + "print_hide_if_no_value": 0, + "read_only": 1, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "started_time", + "fieldtype": "Datetime", + "hidden": 1, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Started Time", + "length": 0, + "no_copy": 1, + "permlevel": 0, + "precision": "", + "print_hide": 1, + "print_hide_if_no_value": 0, + "read_only": 1, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, "fieldname": "amended_from", "fieldtype": "Link", "hidden": 0, @@ -868,7 +993,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2018-12-13 17:23:57.986381", + "modified": "2019-03-10 17:38:37.499871", "modified_by": "Administrator", "module": "Manufacturing", "name": "Job Card", diff --git a/erpnext/manufacturing/doctype/job_card/job_card.py b/erpnext/manufacturing/doctype/job_card/job_card.py index ea9f714fc84..23a4e5105c0 100644 --- a/erpnext/manufacturing/doctype/job_card/job_card.py +++ b/erpnext/manufacturing/doctype/job_card/job_card.py @@ -11,44 +11,56 @@ from frappe.model.document import Document class JobCard(Document): def validate(self): - self.validate_actual_dates() - self.set_time_in_mins() + self.validate_time_logs() self.set_status() - def validate_actual_dates(self): - if get_datetime(self.actual_start_date) > get_datetime(self.actual_end_date): - frappe.throw(_("Actual start date must be less than actual end date")) + def validate_time_logs(self): + self.total_completed_qty = 0.0 + self.total_time_in_mins = 0.0 - if not (self.employee and self.actual_start_date and self.actual_end_date): - return + for d in self.get('time_logs'): + if get_datetime(d.from_time) > get_datetime(d.to_time): + frappe.throw(_("Row {0}: From time must be less than to time").format(d.idx)) - data = frappe.db.sql(""" select name from `tabJob Card` - where - ((%(actual_start_date)s > actual_start_date and %(actual_start_date)s < actual_end_date) or - (%(actual_end_date)s > actual_start_date and %(actual_end_date)s < actual_end_date) or - (%(actual_start_date)s <= actual_start_date and %(actual_end_date)s >= actual_end_date)) and - name != %(name)s and employee = %(employee)s and docstatus =1 - """, { - 'actual_start_date': self.actual_start_date, - 'actual_end_date': self.actual_end_date, - 'employee': self.employee, - 'name': self.name - }, as_dict=1) + data = self.get_overlap_for(d) + if data: + frappe.throw(_("Row {0}: From Time and To Time of {1} is overlapping with {2}") + .format(d.idx, self.name, data.name)) - if data: - frappe.throw(_("Start date and end date is overlapping with the job card {1}") - .format(data[0].name, data[0].name)) + if d.from_time and d.to_time: + d.time_in_mins = time_diff_in_hours(d.to_time, d.from_time) * 60 + self.total_time_in_mins += d.time_in_mins - def set_time_in_mins(self): - if self.actual_start_date and self.actual_end_date: - self.time_in_mins = time_diff_in_hours(self.actual_end_date, self.actual_start_date) * 60 + if d.completed_qty: + self.total_completed_qty += d.completed_qty + + def get_overlap_for(self, args): + existing = frappe.db.sql("""select jc.name as name from + `tabJob Card Time Log` jctl, `tabJob Card` jc where jctl.parent = jc.name and + ( + (%(from_time)s > jctl.from_time and %(from_time)s < jctl.to_time) or + (%(to_time)s > jctl.from_time and %(to_time)s < jctl.to_time) or + (%(from_time)s <= jctl.from_time and %(to_time)s >= jctl.to_time)) + and jctl.name!=%(name)s + and jc.name!=%(parent)s + and jc.docstatus < 2 + and jc.employee = %(employee)s """, + { + "from_time": args.from_time, + "to_time": args.to_time, + "name": args.name or "No Name", + "parent": args.parent or "No Name", + "employee": self.employee + }, as_dict=True) + + return existing[0] if existing else None def get_required_items(self): if not self.get('work_order'): return doc = frappe.get_doc('Work Order', self.get('work_order')) - if doc.transfer_material_against == 'Work Order' and doc.skip_transfer: + if doc.transfer_material_against == 'Work Order' or doc.skip_transfer: return for d in doc.required_items: @@ -67,36 +79,51 @@ class JobCard(Document): }) def on_submit(self): - self.validate_dates() + self.validate_job_card() self.update_work_order() self.set_transferred_qty() - def validate_dates(self): - if not self.actual_start_date and not self.actual_end_date: - frappe.throw(_("Actual start date and actual end date is mandatory")) - def on_cancel(self): self.update_work_order() self.set_transferred_qty() + def validate_job_card(self): + if not self.time_logs: + frappe.throw(_("Time logs are required for job card {0}").format(self.name)) + + if self.total_completed_qty <= 0.0: + frappe.throw(_("Total completed qty must be greater than zero")) + + if self.total_completed_qty > self.for_quantity: + frappe.throw(_("Total completed qty can not be greater than for quantity")) + def update_work_order(self): if not self.work_order: return - data = frappe.db.get_value("Job Card", {'docstatus': 1, 'operation_id': self.operation_id}, - ['sum(time_in_mins)', 'min(actual_start_date)', 'max(actual_end_date)', 'sum(for_quantity)']) + for_quantity, time_in_mins = 0, 0 + from_time_list, to_time_list = [], [] - if data: - time_in_mins, actual_start_date, actual_end_date, for_quantity = data + for d in frappe.get_all('Job Card', + filters = {'docstatus': 1, 'operation_id': self.operation_id}): + doc = frappe.get_doc('Job Card', d.name) + + for_quantity += doc.total_completed_qty + time_in_mins += doc.total_time_in_mins + for time_log in doc.time_logs: + from_time_list.append(time_log.from_time) + to_time_list.append(time_log.to_time) + + if for_quantity: wo = frappe.get_doc('Work Order', self.work_order) for data in wo.operations: if data.name == self.operation_id: data.completed_qty = for_quantity data.actual_operation_time = time_in_mins - data.actual_start_time = actual_start_date - data.actual_end_time = actual_end_date + data.actual_start_time = min(from_time_list) + data.actual_end_time = max(to_time_list) wo.flags.ignore_validate_update_after_submit = True wo.update_operation_status() @@ -132,9 +159,11 @@ class JobCard(Document): break if completed: - job_cards = frappe.get_all('Job Card', filters = {'work_order': self.work_order, + job_cards = frappe.get_all('Job Card', filters = {'work_order': self.work_order, 'docstatus': ('!=', 2)}, fields = 'sum(transferred_qty) as qty', group_by='operation_id') - qty = min([d.qty for d in job_cards]) + + if job_cards: + qty = min([d.qty for d in job_cards]) doc.db_set('material_transferred_for_manufacturing', qty) @@ -147,7 +176,7 @@ class JobCard(Document): 2: "Cancelled" }[self.docstatus or 0] - if self.actual_start_date: + if self.time_logs: self.status = 'Work In Progress' if (self.docstatus == 1 and diff --git a/erpnext/manufacturing/doctype/job_card_time_log/__init__.py b/erpnext/manufacturing/doctype/job_card_time_log/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/erpnext/manufacturing/doctype/job_card_time_log/job_card_time_log.json b/erpnext/manufacturing/doctype/job_card_time_log/job_card_time_log.json new file mode 100644 index 00000000000..2aab71dee4f --- /dev/null +++ b/erpnext/manufacturing/doctype/job_card_time_log/job_card_time_log.json @@ -0,0 +1,208 @@ +{ + "allow_copy": 0, + "allow_events_in_timeline": 0, + "allow_guest_to_view": 0, + "allow_import": 0, + "allow_rename": 0, + "beta": 0, + "creation": "2019-03-08 23:56:43.187569", + "custom": 0, + "docstatus": 0, + "doctype": "DocType", + "document_type": "", + "editable_grid": 1, + "engine": "InnoDB", + "fields": [ + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "from_time", + "fieldtype": "Datetime", + "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 Time", + "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_if_empty": 0, + "fieldname": "to_time", + "fieldtype": "Datetime", + "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 Time", + "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_if_empty": 0, + "fieldname": "column_break_2", + "fieldtype": "Column Break", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "time_in_mins", + "fieldtype": "Float", + "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": "Time In Mins", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 1, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "default": "0", + "fetch_if_empty": 0, + "fieldname": "completed_qty", + "fieldtype": "Float", + "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": "Completed Qty", + "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": 1, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + } + ], + "has_web_view": 0, + "hide_heading": 0, + "hide_toolbar": 0, + "idx": 0, + "image_view": 0, + "in_create": 0, + "is_submittable": 0, + "issingle": 0, + "istable": 1, + "max_attachments": 0, + "modified": "2019-03-10 17:08:46.504910", + "modified_by": "Administrator", + "module": "Manufacturing", + "name": "Job Card Time Log", + "name_case": "", + "owner": "Administrator", + "permissions": [], + "quick_entry": 1, + "read_only": 0, + "read_only_onload": 0, + "show_name_in_global_search": 0, + "sort_field": "modified", + "sort_order": "ASC", + "track_changes": 1, + "track_seen": 0, + "track_views": 0 +} \ No newline at end of file diff --git a/erpnext/manufacturing/doctype/job_card_time_log/job_card_time_log.py b/erpnext/manufacturing/doctype/job_card_time_log/job_card_time_log.py new file mode 100644 index 00000000000..3dc66891216 --- /dev/null +++ b/erpnext/manufacturing/doctype/job_card_time_log/job_card_time_log.py @@ -0,0 +1,9 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +from __future__ import unicode_literals +from frappe.model.document import Document + +class JobCardTimeLog(Document): + pass diff --git a/erpnext/manufacturing/doctype/work_order/test_work_order.py b/erpnext/manufacturing/doctype/work_order/test_work_order.py index 69381c53b3e..b292047aa63 100644 --- a/erpnext/manufacturing/doctype/work_order/test_work_order.py +++ b/erpnext/manufacturing/doctype/work_order/test_work_order.py @@ -302,6 +302,19 @@ class TestWorkOrder(unittest.TestCase): self.assertEqual(len(ste.additional_costs), 1) self.assertEqual(ste.total_additional_costs, 1000) + def test_job_card(self): + data = frappe.get_cached_value('BOM', + {'docstatus': 1, 'with_operations': 1, 'company': '_Test Company'}, ['name', 'item']) + + if data: + bom, bom_item = data + + bom_doc = frappe.get_doc('BOM', bom) + work_order = make_wo_order_test_record(item=bom_item, qty=1, bom_no=bom) + + job_cards = frappe.get_all('Job Card', filters = {'work_order': work_order}) + self.assertEqual(len(job_cards), len(bom_doc.operations)) + def test_work_order_with_non_transfer_item(self): items = {'Finished Good Transfer Item': 1, '_Test FG Item': 1, '_Test FG Item 1': 0} for item, allow_transfer in items.items(): @@ -346,7 +359,7 @@ def make_wo_order_test_record(**args): wo_order = frappe.new_doc("Work Order") wo_order.production_item = args.production_item or args.item or args.item_code or "_Test FG Item" - wo_order.bom_no = frappe.db.get_value("BOM", {"item": wo_order.production_item, + wo_order.bom_no = args.bom_no or frappe.db.get_value("BOM", {"item": wo_order.production_item, "is_active": 1, "is_default": 1}) wo_order.qty = args.qty or 10 wo_order.wip_warehouse = args.wip_warehouse or "_Test Warehouse - _TC" diff --git a/erpnext/manufacturing/doctype/work_order/work_order.py b/erpnext/manufacturing/doctype/work_order/work_order.py index 9873efa124b..947d6931e21 100644 --- a/erpnext/manufacturing/doctype/work_order/work_order.py +++ b/erpnext/manufacturing/doctype/work_order/work_order.py @@ -282,6 +282,10 @@ class WorkOrder(Document): total_bundle_qty = frappe.db.sql(""" select sum(qty) from `tabProduct Bundle Item` where parent = %s""", (frappe.db.escape(self.product_bundle_item)))[0][0] + if not total_bundle_qty: + # product bundle is 0 (product bundle allows 0 qty for items) + total_bundle_qty = 1 + cond = "product_bundle_item = %s" if self.product_bundle_item else "production_item = %s" qty = frappe.db.sql(""" select sum(qty) from diff --git a/erpnext/patches.txt b/erpnext/patches.txt index b1a393bdf3e..9dcb285a0a3 100755 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -571,7 +571,7 @@ execute:frappe.delete_doc_if_exists("Page", "sales-analytics") execute:frappe.delete_doc_if_exists("Page", "purchase-analytics") execute:frappe.delete_doc_if_exists("Page", "stock-analytics") execute:frappe.delete_doc_if_exists("Page", "production-analytics") -erpnext.patches.v11_0.ewaybill_fields_gst_india #2018-11-13 #2019-01-09 +erpnext.patches.v11_0.ewaybill_fields_gst_india #2018-11-13 #2019-01-09 #2019-04-01 erpnext.patches.v11_0.drop_column_max_days_allowed erpnext.patches.v11_0.change_healthcare_desktop_icons erpnext.patches.v10_0.update_user_image_in_employee @@ -587,4 +587,6 @@ erpnext.patches.v11_1.setup_guardian_role execute:frappe.delete_doc('DocType', 'Notification Control') erpnext.patches.v11_0.remove_barcodes_field_from_copy_fields_to_variants erpnext.patches.v10_0.item_barcode_childtable_migrate # 16-02-2019 -erpnext.patches.v11_0.make_italian_localization_fields +erpnext.patches.v11_0.make_italian_localization_fields # 26-03-2019 +erpnext.patches.v11_1.make_job_card_time_logs +erpnext.patches.v11_1.set_variant_based_on \ No newline at end of file diff --git a/erpnext/patches/v10_0/item_barcode_childtable_migrate.py b/erpnext/patches/v10_0/item_barcode_childtable_migrate.py index bc6005677db..e30e0a74c00 100644 --- a/erpnext/patches/v10_0/item_barcode_childtable_migrate.py +++ b/erpnext/patches/v10_0/item_barcode_childtable_migrate.py @@ -27,5 +27,5 @@ def execute(): 'parent': item.name, 'parentfield': 'barcodes' }).insert() - except frappe.DuplicateEntryError: + except (frappe.DuplicateEntryError, frappe.UniqueValidationError): continue diff --git a/erpnext/patches/v11_0/make_italian_localization_fields.py b/erpnext/patches/v11_0/make_italian_localization_fields.py index cb65f23ab12..79958b9189c 100644 --- a/erpnext/patches/v11_0/make_italian_localization_fields.py +++ b/erpnext/patches/v11_0/make_italian_localization_fields.py @@ -6,23 +6,32 @@ from erpnext.regional.italy.setup import make_custom_fields, setup_report from erpnext.regional.italy import state_codes import frappe - def execute(): + company = frappe.get_all('Company', filters = {'country': 'Italy'}) + if not company: + return - company = frappe.get_all('Company', filters = {'country': 'Italy'}) - if not company: - return + frappe.reload_doc('regional', 'report', 'electronic_invoice_register') + make_custom_fields() + setup_report() - make_custom_fields() - setup_report() + # Set state codes + condition = "" + for state, code in state_codes.items(): + condition += " when '{0}' then '{1}'".format(frappe.db.escape(state), frappe.db.escape(code)) - # Set state codes - condition = "" - for state, code in state_codes.items(): - condition += " when '{0}' then '{1}'".format(frappe.db.escape(state), frappe.db.escape(code)) + if condition: + condition = "state_code = (case state {0} end),".format(condition) - if condition: - frappe.db.sql(""" - UPDATE tabAddress set state_code = (case state {condition} end) - WHERE country in ('Italy', 'Italia', 'Italian Republic', 'Repubblica Italiana') - """.format(condition=condition)) + frappe.db.sql(""" + UPDATE tabAddress set {condition} country_code = UPPER(ifnull((select code + from `tabCountry` where name = `tabAddress`.country), '')) + where country_code is null and state_code is null + """.format(condition=condition)) + + frappe.db.sql(""" + UPDATE `tabSales Invoice Item` si, `tabSales Order` so + set si.customer_po_no = so.po_no, si.customer_po_date = so.po_date + WHERE + si.sales_order = so.name and so.po_no is not null + """) diff --git a/erpnext/patches/v11_1/make_job_card_time_logs.py b/erpnext/patches/v11_1/make_job_card_time_logs.py new file mode 100644 index 00000000000..6e708df48d8 --- /dev/null +++ b/erpnext/patches/v11_1/make_job_card_time_logs.py @@ -0,0 +1,29 @@ +# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors +# License: GNU General Public License v3. See license.txt + +from __future__ import unicode_literals +import frappe + +def execute(): + frappe.reload_doc('manufacturing', 'doctype', 'job_card_time_log') + + if (frappe.db.table_exists("Job Card") + and frappe.get_meta("Job Card").has_field("actual_start_date")): + time_logs = [] + for d in frappe.get_all('Job Card', + fields = ["actual_start_date", "actual_end_date", "time_in_mins", "name", "for_quantity"], + filters = {'docstatus': ("<", 2)}): + if d.actual_start_date: + time_logs.append([d.actual_start_date, d.actual_end_date, d.time_in_mins, + d.for_quantity, d.name, 'Job Card', 'time_logs', frappe.generate_hash("", 10)]) + + if time_logs: + frappe.db.sql(""" INSERT INTO + `tabJob Card Time Log` + (from_time, to_time, time_in_mins, completed_qty, parent, parenttype, parentfield, name) + values {values} + """.format(values = ','.join(['%s'] * len(time_logs))), tuple(time_logs)) + + frappe.reload_doc('manufacturing', 'doctype', 'job_card') + frappe.db.sql(""" update `tabJob Card` set total_completed_qty = for_quantity, + total_time_in_mins = time_in_mins where docstatus < 2 """) \ No newline at end of file diff --git a/erpnext/patches/v11_1/set_variant_based_on.py b/erpnext/patches/v11_1/set_variant_based_on.py new file mode 100644 index 00000000000..019eefd68f4 --- /dev/null +++ b/erpnext/patches/v11_1/set_variant_based_on.py @@ -0,0 +1,11 @@ +# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors +# License: GNU General Public License v3. See license.txt + +from __future__ import unicode_literals +import frappe + +def execute(): + frappe.db.sql("""update tabItem set variant_based_on = 'Item Attribute' + where ifnull(variant_based_on, '') = '' + and (has_variants=1 or ifnull(variant_of, '') != '') + """) \ No newline at end of file diff --git a/erpnext/patches/v7_0/repost_future_gle_for_purchase_invoice.py b/erpnext/patches/v7_0/repost_future_gle_for_purchase_invoice.py index 22f9db6b2be..9e21fb699b9 100644 --- a/erpnext/patches/v7_0/repost_future_gle_for_purchase_invoice.py +++ b/erpnext/patches/v7_0/repost_future_gle_for_purchase_invoice.py @@ -10,14 +10,15 @@ from erpnext.controllers.stock_controller import update_gl_entries_after def execute(): company_list = frappe.db.sql_list("""Select name from tabCompany where enable_perpetual_inventory = 1""") frappe.reload_doc('accounts', 'doctype', 'sales_invoice') - - frappe.reload_doctype("Purchase Invoice") + + frappe.reload_doctype("Purchase Invoice") wh_account = get_warehouse_account_map() - + for pi in frappe.get_all("Purchase Invoice", fields=["name", "company"], filters={"docstatus": 1, "update_stock": 1}): if pi.company in company_list: pi_doc = frappe.get_doc("Purchase Invoice", pi.name) items, warehouses = pi_doc.get_items_and_warehouses() - update_gl_entries_after(pi_doc.posting_date, pi_doc.posting_time, warehouses, items, wh_account) - + update_gl_entries_after(pi_doc.posting_date, pi_doc.posting_time, + warehouses, items, wh_account, company = pi.company) + frappe.db.commit() \ No newline at end of file diff --git a/erpnext/projects/doctype/task/task.py b/erpnext/projects/doctype/task/task.py index fffa9c1657c..12302789a9b 100755 --- a/erpnext/projects/doctype/task/task.py +++ b/erpnext/projects/doctype/task/task.py @@ -159,6 +159,13 @@ class Task(NestedSet): self.update_nsm_model() + def update_status(self): + if self.status not in ('Cancelled', 'Closed') and self.exp_end_date: + from datetime import datetime + if self.exp_end_date < datetime.now().date(): + self.db_set('status', 'Overdue') + self.update_project() + @frappe.whitelist() def check_if_child_exists(name): child_tasks = frappe.get_all("Task", filters={"parent_task": name}) @@ -186,10 +193,9 @@ def set_multiple_status(names, status): task.save() def set_tasks_as_overdue(): - frappe.db.sql("""update tabTask set `status`='Overdue' - where exp_end_date is not null - and exp_end_date < CURDATE() - and `status` not in ('Closed', 'Cancelled')""") + tasks = frappe.get_all("Task", filters={'status':['not in',['Cancelled', 'Closed']]}) + for task in tasks: + frappe.get_doc("Task", task.name).update_status() @frappe.whitelist() def get_children(doctype, parent, task=None, project=None, is_root=False): diff --git a/erpnext/projects/doctype/task/test_task.py b/erpnext/projects/doctype/task/test_task.py index 9971946cb4f..b733f67a980 100644 --- a/erpnext/projects/doctype/task/test_task.py +++ b/erpnext/projects/doctype/task/test_task.py @@ -117,4 +117,4 @@ def create_task(subject, start=None, end=None, depends_on=None, project=None, sa if save: task.save() - return task \ No newline at end of file + return task diff --git a/erpnext/projects/doctype/timesheet/timesheet.js b/erpnext/projects/doctype/timesheet/timesheet.js index 8811ab95438..8ffc10ee972 100644 --- a/erpnext/projects/doctype/timesheet/timesheet.js +++ b/erpnext/projects/doctype/timesheet/timesheet.js @@ -10,8 +10,8 @@ frappe.ui.form.on("Timesheet", { filters:{ 'status': 'Active' } - } - } + }; + }; frm.fields_dict['time_logs'].grid.get_field('task').get_query = function(frm, cdt, cdn) { var child = locals[cdt][cdn]; @@ -20,33 +20,37 @@ frappe.ui.form.on("Timesheet", { 'project': child.project, 'status': ["!=", "Cancelled"] } - } - } + }; + }; frm.fields_dict['time_logs'].grid.get_field('project').get_query = function() { return{ filters: { 'company': frm.doc.company } - } - } + }; + }; }, onload: function(frm){ if (frm.doc.__islocal && frm.doc.time_logs) { calculate_time_and_amount(frm); } + + if (frm.is_new()) { + set_employee_and_company(frm); + } }, refresh: function(frm) { if(frm.doc.docstatus==1) { if(frm.doc.per_billed < 100 && frm.doc.total_billable_hours && frm.doc.total_billable_hours > frm.doc.total_billed_hours){ - frm.add_custom_button(__("Make Sales Invoice"), function() { frm.trigger("make_invoice") }, + frm.add_custom_button(__("Make Sales Invoice"), function() { frm.trigger("make_invoice"); }, "fa fa-file-alt"); } if(!frm.doc.salary_slip && frm.doc.employee){ - frm.add_custom_button(__("Make Salary Slip"), function() { frm.trigger("make_salary_slip") }, + frm.add_custom_button(__("Make Salary Slip"), function() { frm.trigger("make_salary_slip"); }, "fa fa-file-alt"); } } @@ -58,7 +62,7 @@ frappe.ui.form.on("Timesheet", { if ((row.from_time <= frappe.datetime.now_datetime()) && !row.completed) { button = 'Resume Timer'; } - }) + }); frm.add_custom_button(__(button), function() { var flag = true; @@ -77,7 +81,7 @@ frappe.ui.form.on("Timesheet", { erpnext.timesheet.timer(frm, row, timestamp); flag = false; } - }) + }); // If no activities found to start a timer, create new if (flag) { erpnext.timesheet.timer(frm); @@ -94,7 +98,7 @@ frappe.ui.form.on("Timesheet", { frappe.db.get_value('Company', { 'company_name' : frm.doc.company }, 'standard_working_hours') .then(({ message }) => { (frappe.working_hours = message.standard_working_hours || 0); - }); + }); }, make_invoice: function(frm) { @@ -125,8 +129,8 @@ frappe.ui.form.on("Timesheet", { frappe.set_route("Form", r.message.doctype, r.message.name); } } - }) - }) + }); + }); dialog.show(); }, @@ -136,7 +140,7 @@ frappe.ui.form.on("Timesheet", { frm: frm }); }, -}) +}); frappe.ui.form.on("Timesheet Detail", { time_logs_remove: function(frm) { @@ -171,22 +175,22 @@ frappe.ui.form.on("Timesheet Detail", { .find('[data-fieldname="timer"]') .append(frappe.render_template("timesheet")); frm.trigger("control_timer"); - }) + }); }, hours: function(frm, cdt, cdn) { - calculate_end_time(frm, cdt, cdn) + calculate_end_time(frm, cdt, cdn); }, billing_hours: function(frm, cdt, cdn) { - calculate_billing_costing_amount(frm, cdt, cdn) + calculate_billing_costing_amount(frm, cdt, cdn); }, billing_rate: function(frm, cdt, cdn) { - calculate_billing_costing_amount(frm, cdt, cdn) + calculate_billing_costing_amount(frm, cdt, cdn); }, costing_rate: function(frm, cdt, cdn) { - calculate_billing_costing_amount(frm, cdt, cdn) + calculate_billing_costing_amount(frm, cdt, cdn); }, billable: function(frm, cdt, cdn) { @@ -212,7 +216,7 @@ frappe.ui.form.on("Timesheet Detail", { calculate_billing_costing_amount(frm, cdt, cdn); } } - }) + }); } }); @@ -240,23 +244,23 @@ var calculate_end_time = function(frm, cdt, cdn) { frm._setting_hours = true; frappe.model.set_value(cdt, cdn, "to_time", d.format(frappe.defaultDatetimeFormat)).then(() => { - frm._setting_hours = false; - }); + frm._setting_hours = false; + }); } } -} +}; var update_billing_hours = function(frm, cdt, cdn){ var child = locals[cdt][cdn]; if(!child.billable) frappe.model.set_value(cdt, cdn, 'billing_hours', 0.0); -} +}; var update_time_rates = function(frm, cdt, cdn){ var child = locals[cdt][cdn]; if(!child.billable){ frappe.model.set_value(cdt, cdn, 'billing_rate', 0.0); } -} +}; var calculate_billing_costing_amount = function(frm, cdt, cdn){ var child = locals[cdt][cdn]; @@ -270,7 +274,7 @@ var calculate_billing_costing_amount = function(frm, cdt, cdn){ frappe.model.set_value(cdt, cdn, 'billing_amount', billing_amount); frappe.model.set_value(cdt, cdn, 'costing_amount', costing_amount); calculate_time_and_amount(frm); -} +}; var calculate_time_and_amount = function(frm) { var tl = frm.doc.time_logs || []; @@ -294,4 +298,17 @@ var calculate_time_and_amount = function(frm) { frm.set_value("total_hours", total_working_hr); frm.set_value("total_billable_amount", total_billable_amount); frm.set_value("total_costing_amount", total_costing_amount); -} \ No newline at end of file +}; + +// set employee (and company) to the one that's currently logged in +const set_employee_and_company = function(frm) { + const options = { user_id: frappe.session.user }; + const fields = ['name', 'company']; + frappe.db.get_value('Employee', options, fields).then(({ message }) => { + if (message) { + // there is an employee with the currently logged in user_id + frm.set_value("employee", message.name); + frm.set_value("company", message.company); + } + }); +}; diff --git a/erpnext/projects/doctype/timesheet/timesheet.json b/erpnext/projects/doctype/timesheet/timesheet.json index 5ad2ab3a379..c29c11b7465 100644 --- a/erpnext/projects/doctype/timesheet/timesheet.json +++ b/erpnext/projects/doctype/timesheet/timesheet.json @@ -739,7 +739,7 @@ "collapsible": 0, "columns": 0, "fieldname": "total_costing_amount", - "fieldtype": "Float", + "fieldtype": "Currency", "hidden": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, @@ -805,7 +805,7 @@ "depends_on": "", "description": "", "fieldname": "total_billable_amount", - "fieldtype": "Float", + "fieldtype": "Currency", "hidden": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, @@ -837,7 +837,7 @@ "collapsible": 0, "columns": 0, "fieldname": "total_billed_amount", - "fieldtype": "Float", + "fieldtype": "Currency", "hidden": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, @@ -1000,7 +1000,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2019-01-30 11:28:18.518590", + "modified": "2019-03-05 21:54:02.654690", "modified_by": "Administrator", "module": "Projects", "name": "Timesheet", diff --git a/erpnext/projects/report/billing_summary.py b/erpnext/projects/report/billing_summary.py new file mode 100644 index 00000000000..80bf926a54c --- /dev/null +++ b/erpnext/projects/report/billing_summary.py @@ -0,0 +1,147 @@ +# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + + +from __future__ import unicode_literals +import frappe +from frappe import _ +from frappe.utils import time_diff_in_hours + +def get_columns(): + return [ + { + "label": _("Employee ID"), + "fieldtype": "Link", + "fieldname": "employee", + "options": "Employee", + "width": 300 + }, + { + "label": _("Employee Name"), + "fieldtype": "data", + "fieldname": "employee_name", + "hidden": 1, + "width": 200 + }, + { + "label": _("Timesheet"), + "fieldtype": "Link", + "fieldname": "timesheet", + "options": "Timesheet", + "width": 150 + }, + { + "label": _("Billable Hours"), + "fieldtype": "Float", + "fieldname": "total_billable_hours", + "width": 50 + }, + { + "label": _("Working Hours"), + "fieldtype": "Float", + "fieldname": "total_hours", + "width": 50 + }, + { + "label": _("Amount"), + "fieldtype": "Currency", + "fieldname": "amount", + "width": 100 + } + ] + +def get_data(filters): + data = [] + record = get_records(filters) + + billable_hours_worked = 0 + hours_worked = 0 + working_cost = 0 + for entries in record: + total_hours = 0 + total_billable_hours = 0 + total_amount = 0 + entries_exists = False + timesheet_details = get_timesheet_details(filters, entries.name) + + for activity in timesheet_details: + entries_exists = True + time_start = activity.from_time + time_end = frappe.utils.add_to_date(activity.from_time, hours=activity.hours) + from_date = frappe.utils.get_datetime(filters.from_date) + to_date = frappe.utils.get_datetime(filters.to_date) + + if time_start <= from_date and time_end >= from_date: + total_hours, total_billable_hours, total_amount = get_billable_and_total_hours(activity, + time_end, from_date, total_hours, total_billable_hours, total_amount) + + billable_hours_worked += total_billable_hours + hours_worked += total_hours + working_cost += total_amount + elif time_start >= from_date and time_end >= to_date: + total_hours, total_billable_hours, total_amount = get_billable_and_total_hours(activity, + to_date, time_start, total_hours, total_billable_hours, total_amount) + + billable_hours_worked += total_billable_hours + hours_worked += total_hours + working_cost += total_amount + elif time_start >= from_date and time_end <= to_date: + total_hours, total_billable_hours, total_amount = get_billable_and_total_hours(activity, + time_end, time_start, total_hours, total_billable_hours, total_amount) + + billable_hours_worked += total_billable_hours + hours_worked += total_hours + working_cost += total_amount + + row = { + "employee": entries.employee, + "employee_name": entries.employee_name, + "timesheet": entries.name, + "total_billable_hours": total_billable_hours, + "total_hours": total_hours, + "amount": total_amount + } + + if entries_exists: + data.append(row) + entries_exists = False + + total = { + "total_billable_hours": billable_hours_worked, + "total_hours": hours_worked, + "amount": working_cost + } + if billable_hours_worked !=0 or hours_worked !=0 or working_cost !=0: + data.append(total) + return data + +def get_records(filters): + record_filters = [ + ["start_date", "<=", filters.to_date], + ["end_date", ">=", filters.from_date], + ["docstatus", "=", 1] + ] + + if "employee" in filters: + record_filters.append(["employee", "=", filters.employee]) + + return frappe.get_all("Timesheet", filters=record_filters, fields=[" * "] ) + +def get_billable_and_total_hours(activity, end, start, total_hours, total_billable_hours, total_amount): + total_hours += abs(time_diff_in_hours(end, start)) + if activity.billable: + total_billable_hours += abs(time_diff_in_hours(end, start)) + total_amount += total_billable_hours * activity.billing_rate + return total_hours, total_billable_hours, total_amount + +def get_timesheet_details(filters, parent): + timesheet_details_filter = {"parent": parent} + + if "project" in filters: + timesheet_details_filter["project"] = filters.project + + return frappe.get_all( + "Timesheet Detail", + filters = timesheet_details_filter, + fields=["*"] + ) diff --git a/erpnext/projects/report/employee_billing_summary/__init__.py b/erpnext/projects/report/employee_billing_summary/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/erpnext/projects/report/employee_billing_summary/employee_billing_summary.js b/erpnext/projects/report/employee_billing_summary/employee_billing_summary.js new file mode 100644 index 00000000000..13f49ed6bed --- /dev/null +++ b/erpnext/projects/report/employee_billing_summary/employee_billing_summary.js @@ -0,0 +1,29 @@ +// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt +/* eslint-disable */ + +frappe.query_reports["Employee Billing Summary"] = { + "filters": [ + { + fieldname: "employee", + label: __("Employee"), + fieldtype: "Link", + options: "Employee", + reqd: 1 + }, + { + fieldname:"from_date", + label: __("From Date"), + fieldtype: "Date", + default: frappe.datetime.add_months(frappe.datetime.month_start(), -1), + reqd: 1 + }, + { + fieldname:"to_date", + label: __("To Date"), + fieldtype: "Date", + default: frappe.datetime.add_days(frappe.datetime.month_start(), -1), + reqd: 1 + }, + ] +} diff --git a/erpnext/projects/report/employee_billing_summary/employee_billing_summary.json b/erpnext/projects/report/employee_billing_summary/employee_billing_summary.json new file mode 100644 index 00000000000..433ebac5ddf --- /dev/null +++ b/erpnext/projects/report/employee_billing_summary/employee_billing_summary.json @@ -0,0 +1,36 @@ +{ + "add_total_row": 0, + "creation": "2019-03-08 15:08:19.929728", + "disable_prepared_report": 0, + "disabled": 0, + "docstatus": 0, + "doctype": "Report", + "idx": 0, + "is_standard": "Yes", + "modified": "2019-03-08 15:08:19.929728", + "modified_by": "Administrator", + "module": "Projects", + "name": "Employee Billing Summary", + "owner": "Administrator", + "prepared_report": 0, + "ref_doctype": "Timesheet", + "report_name": "Employee Billing Summary", + "report_type": "Script Report", + "roles": [ + { + "role": "Projects User" + }, + { + "role": "HR User" + }, + { + "role": "Manufacturing User" + }, + { + "role": "Employee" + }, + { + "role": "Accounts User" + } + ] +} \ No newline at end of file diff --git a/erpnext/projects/report/employee_billing_summary/employee_billing_summary.py b/erpnext/projects/report/employee_billing_summary/employee_billing_summary.py new file mode 100644 index 00000000000..cd5ad7803a5 --- /dev/null +++ b/erpnext/projects/report/employee_billing_summary/employee_billing_summary.py @@ -0,0 +1,14 @@ +# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +from __future__ import unicode_literals +import frappe +from frappe import _ +from erpnext.projects.report.billing_summary import get_columns, get_data + +def execute(filters=None): + filters = frappe._dict(filters or {}) + columns = get_columns() + + data = get_data(filters) + return columns, data \ No newline at end of file diff --git a/erpnext/projects/report/project_billing_summary/__init__.py b/erpnext/projects/report/project_billing_summary/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/erpnext/projects/report/project_billing_summary/project_billing_summary.js b/erpnext/projects/report/project_billing_summary/project_billing_summary.js new file mode 100644 index 00000000000..caac1d86b45 --- /dev/null +++ b/erpnext/projects/report/project_billing_summary/project_billing_summary.js @@ -0,0 +1,29 @@ +// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt +/* eslint-disable */ + +frappe.query_reports["Project Billing Summary"] = { + "filters": [ + { + fieldname: "project", + label: __("Project"), + fieldtype: "Link", + options: "Project", + reqd: 1 + }, + { + fieldname:"from_date", + label: __("From Date"), + fieldtype: "Date", + default: frappe.datetime.add_months(frappe.datetime.month_start(), -1), + reqd: 1 + }, + { + fieldname:"to_date", + label: __("To Date"), + fieldtype: "Date", + default: frappe.datetime.add_days(frappe.datetime.month_start(),-1), + reqd: 1 + }, + ] +} diff --git a/erpnext/projects/report/project_billing_summary/project_billing_summary.json b/erpnext/projects/report/project_billing_summary/project_billing_summary.json new file mode 100644 index 00000000000..a3f91c802d5 --- /dev/null +++ b/erpnext/projects/report/project_billing_summary/project_billing_summary.json @@ -0,0 +1,36 @@ +{ + "add_total_row": 0, + "creation": "2019-03-11 16:22:39.460524", + "disable_prepared_report": 0, + "disabled": 0, + "docstatus": 0, + "doctype": "Report", + "idx": 0, + "is_standard": "Yes", + "modified": "2019-03-11 16:22:39.460524", + "modified_by": "Administrator", + "module": "Projects", + "name": "Project Billing Summary", + "owner": "Administrator", + "prepared_report": 0, + "ref_doctype": "Timesheet", + "report_name": "Project Billing Summary", + "report_type": "Script Report", + "roles": [ + { + "role": "Projects User" + }, + { + "role": "HR User" + }, + { + "role": "Manufacturing User" + }, + { + "role": "Employee" + }, + { + "role": "Accounts User" + } + ] +} \ No newline at end of file diff --git a/erpnext/projects/report/project_billing_summary/project_billing_summary.py b/erpnext/projects/report/project_billing_summary/project_billing_summary.py new file mode 100644 index 00000000000..cd5ad7803a5 --- /dev/null +++ b/erpnext/projects/report/project_billing_summary/project_billing_summary.py @@ -0,0 +1,14 @@ +# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +from __future__ import unicode_literals +import frappe +from frappe import _ +from erpnext.projects.report.billing_summary import get_columns, get_data + +def execute(filters=None): + filters = frappe._dict(filters or {}) + columns = get_columns() + + data = get_data(filters) + return columns, data \ No newline at end of file diff --git a/erpnext/public/js/conf.js b/erpnext/public/js/conf.js index 56e6bdb8dbe..477781bc805 100644 --- a/erpnext/public/js/conf.js +++ b/erpnext/public/js/conf.js @@ -27,8 +27,6 @@ $(document).bind('toolbar_setup', function() { target="_blank">'+__('Documentation')+'').insertBefore($help_menu); $('
  • '+__('User Forum')+'
  • ').insertBefore($help_menu); - $('').insertBefore($help_menu); $('
  • '+__('Report an Issue')+'
  • ').insertBefore($help_menu); diff --git a/erpnext/public/js/controllers/stock_controller.js b/erpnext/public/js/controllers/stock_controller.js index 1b8e0791323..1c12c352ed4 100644 --- a/erpnext/public/js/controllers/stock_controller.js +++ b/erpnext/public/js/controllers/stock_controller.js @@ -73,7 +73,7 @@ erpnext.stock.StockController = frappe.ui.form.Controller.extend({ from_date: me.frm.doc.posting_date, to_date: me.frm.doc.posting_date, company: me.frm.doc.company, - group_by: "" + group_by: "Group by Voucher (Consolidated)" }; frappe.set_route("query-report", "General Ledger"); }, __("View")); diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js index cf62af7b70e..168a727f270 100644 --- a/erpnext/public/js/controllers/transaction.js +++ b/erpnext/public/js/controllers/transaction.js @@ -314,14 +314,21 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ show_description(row_to_modify.idx, row_to_modify.item_code); + this.frm.from_barcode = true; frappe.model.set_value(row_to_modify.doctype, row_to_modify.name, { item_code: data.item_code, qty: (row_to_modify.qty || 0) + 1 }); - this.frm.refresh_field('items'); + ['serial_no', 'batch_no', 'barcode'].forEach(field => { + if (data[field] && frappe.meta.has_field(row_to_modify.doctype, field)) { + frappe.model.set_value(row_to_modify.doctype, + row_to_modify.name, field, data[field]); + } + }); + + scan_barcode_field.set_value(''); }); - scan_barcode_field.set_value(''); } return false; }, @@ -384,10 +391,12 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ // barcode cleared, remove item d.item_code = ""; } - this.item_code(doc, cdt, cdn, true); + + this.frm.from_barcode = true; + this.item_code(doc, cdt, cdn); }, - item_code: function(doc, cdt, cdn, from_barcode) { + item_code: function(doc, cdt, cdn) { var me = this; var item = frappe.get_doc(cdt, cdn); var update_stock = 0, show_batch_dialog = 0; @@ -400,9 +409,11 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ show_batch_dialog = 1; } // clear barcode if setting item (else barcode will take priority) - if(!from_barcode) { + if(!this.frm.from_barcode) { item.barcode = null; } + + this.frm.from_barcode = false; if(item.item_code || item.barcode || item.serial_no) { if(!this.validate_company_and_party()) { this.frm.fields_dict["items"].grid.grid_rows[item.idx - 1].remove(); diff --git a/erpnext/public/js/utils.js b/erpnext/public/js/utils.js index 64085a83cdf..389e25ece10 100755 --- a/erpnext/public/js/utils.js +++ b/erpnext/public/js/utils.js @@ -255,11 +255,16 @@ $.extend(erpnext.utils, { // get valid options for tree based on user permission & locals dict let unscrub_option = frappe.model.unscrub(option); let user_permission = frappe.defaults.get_user_permissions(); + let options; + if(user_permission && user_permission[unscrub_option]) { - return user_permission[unscrub_option].map(perm => perm.doc); + options = user_permission[unscrub_option].map(perm => perm.doc); } else { - return $.map(locals[`:${unscrub_option}`], function(c) { return c.name; }).sort(); + options = $.map(locals[`:${unscrub_option}`], function(c) { return c.name; }).sort(); } + + // filter unique values, as there may be multiple user permissions for any value + return options.filter((value, index, self) => self.indexOf(value) === index); }, get_tree_default: function(option) { // set default for a field based on user permission diff --git a/erpnext/regional/india/setup.py b/erpnext/regional/india/setup.py index c5498c77700..34d5991e7e0 100644 --- a/erpnext/regional/india/setup.py +++ b/erpnext/regional/india/setup.py @@ -93,7 +93,7 @@ def add_print_formats(): def make_custom_fields(update=True): hsn_sac_field = dict(fieldname='gst_hsn_code', label='HSN/SAC', fieldtype='Data', fetch_from='item_code.gst_hsn_code', insert_after='description', - allow_on_submit=1, print_hide=1) + allow_on_submit=1, print_hide=1, fetch_if_empty=1) invoice_gst_fields = [ dict(fieldname='gst_section', label='GST Details', fieldtype='Section Break', insert_after='language', print_hide=1, collapsible=1), @@ -243,6 +243,7 @@ def make_custom_fields(update=True): 'Purchase Order Item': [hsn_sac_field], 'Purchase Receipt Item': [hsn_sac_field], 'Purchase Invoice Item': [hsn_sac_field], + 'Material Request Item': [hsn_sac_field], 'Employee': [ dict(fieldname='ifsc_code', label='IFSC Code', fieldtype='Data', insert_after='bank_ac_no', print_hide=1, diff --git a/erpnext/regional/india/utils.py b/erpnext/regional/india/utils.py index e7d0d5052ec..9747b245694 100644 --- a/erpnext/regional/india/utils.py +++ b/erpnext/regional/india/utils.py @@ -9,6 +9,8 @@ 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 hasattr(doc, 'gst_state') and doc.gst_state: + doc.gst_state_number = state_numbers[doc.gst_state] if not hasattr(doc, 'gstin') or not doc.gstin: return diff --git a/erpnext/regional/italy/e-invoice.xml b/erpnext/regional/italy/e-invoice.xml index 34053bdc99a..b725b964f2e 100644 --- a/erpnext/regional/italy/e-invoice.xml +++ b/erpnext/regional/italy/e-invoice.xml @@ -9,7 +9,7 @@ {%- if address.state_code %} {{ address.state_code }} {%- endif %} -{{ address.country_code|upper }} +{{ address.country_code }} {%- endmacro %} {%- macro render_discount_or_margin(item) -%} @@ -32,15 +32,15 @@ {%- endmacro -%} - - {{ doc.company_address_data.country_code|upper or "IT" }} + {{ doc.company_address_data.country_code }} {{ doc.company_fiscal_code or doc.company_tax_id | replace("IT","") }} {{ doc.progressive_number }} @@ -56,7 +56,7 @@ - {{ doc.company_address_data.country_code|upper or "IT"}} + {{ doc.company_address_data.country_code }} {{ doc.company_tax_id | replace("IT","") }} {%- if doc.company_fiscal_code %} @@ -95,13 +95,12 @@ {{ doc.customer_data.last_name }} {%- else %} - {%- if doc.customer_data.is_public_administration %} - {{ doc.customer_data.fiscal_code }} - {%- else %} - {{ doc.customer_address_data.country_code|upper or "IT" }} + {{ doc.customer_address_data.country_code }} {{ doc.tax_id | replace("IT","") }} + {%- if doc.customer_data.fiscal_code %} + {{ doc.customer_data.fiscal_code }} {%- endif %} {{ doc.customer_name }} @@ -128,22 +127,42 @@ {{ format_float(doc.stamp_duty) }} {%- endif %} - {{ format_float(doc.grand_total) }} + {%- if doc.discount_amount %} + + {%- if doc.discount_amount > 0.0 %} + SC + {%- else %} + MG + {%- endif %} + {%- if doc.additional_discount_percentage > 0.0 %} + {{ format_float(doc.additional_discount_percentage) }} + {%- endif %} + {{ format_float(doc.discount_amount) }} + + {%- endif %} + {{ format_float(doc.rounded_total or doc.grand_total) }} VENDITA - {%- if doc.po_no %} - - {{ doc.po_no }} - {%- if doc.po_date %} - {{ doc.po_date }} - {%- endif %} - - {%- endif %} + {%- for po_no, po_date in doc.customer_po_data.items() %} + + {{ po_no }} + {{ po_date }} + + {%- endfor %} {%- if doc.is_return and doc.return_against_unamended %} {{ doc.return_against_unamended }} {%- endif %} + {%- for row in doc.e_invoice_items %} + {%- if row.delivery_note %} + + {{ row.delivery_note }} + {{ frappe.db.get_value('Delivery Note', row.delivery_note, 'posting_date') }} + {{ row.idx }} + + {%- endif %} + {%- endfor %} {%- if doc.shipping_address_data %} @@ -160,7 +179,7 @@ CODICE {{ item.item_code }} - {{ item.description or item.item_name }} + {{ html2text(item.description or '') or item.item_name }} {{ format_float(item.qty) }} {{ item.stock_uom }} {{ format_float(item.price_list_rate or item.rate) }} @@ -199,7 +218,17 @@ {{ payment_term.mode_of_payment_code.split("-")[0] }} {{ payment_term.due_date }} {{ format_float(payment_term.payment_amount) }} - {%- if payment_term.bank_account_iban %}{{ payment_term.bank_account_iban }}{%- endif %} + {%- if payment_term.bank_account_name %} + {{ payment_term.bank_account_name }} + {%- endif %} + {%- if payment_term.bank_account_iban %} + {{ payment_term.bank_account_iban }} + {{ payment_term.bank_account_iban[5:10] }} + {{ payment_term.bank_account_iban[10:15] }} + {%- endif %} + {%- if payment_term.bank_account_swift_number %} + {{ payment_term.bank_account_swift_number }} + {%- endif %} {%- endfor %} diff --git a/erpnext/regional/italy/sales_invoice.js b/erpnext/regional/italy/sales_invoice.js new file mode 100644 index 00000000000..586a52937b5 --- /dev/null +++ b/erpnext/regional/italy/sales_invoice.js @@ -0,0 +1,30 @@ +erpnext.setup_e_invoice_button = (doctype) => { + frappe.ui.form.on(doctype, { + refresh: (frm) => { + if(frm.doc.docstatus == 1) { + frm.add_custom_button('Generate E-Invoice', () => { + frm.call({ + method: "erpnext.regional.italy.utils.generate_single_invoice", + args: { + docname: frm.doc.name + }, + callback: function(r) { + frm.reload_doc(); + if(r.message) { + var w = window.open( + frappe.urllib.get_full_url( + "/api/method/erpnext.regional.italy.utils.download_e_invoice_file?" + + "file_name=" + r.message + ) + ) + if (!w) { + frappe.msgprint(__("Please enable pop-ups")); return; + } + } + } + }); + }); + } + } + }); +}; diff --git a/erpnext/regional/italy/setup.py b/erpnext/regional/italy/setup.py index 3e9d7a29e50..1526d6f62f0 100644 --- a/erpnext/regional/italy/setup.py +++ b/erpnext/regional/italy/setup.py @@ -10,12 +10,12 @@ from frappe.custom.doctype.custom_field.custom_field import create_custom_fields from erpnext.regional.italy import fiscal_regimes, tax_exemption_reasons, mode_of_payment_codes, vat_collectability_options def setup(company=None, patch=True): - make_custom_fields() - setup_report() + make_custom_fields() + setup_report() def make_custom_fields(update=True): - invoice_item_fields = [ - dict(fieldname='tax_rate', label='Tax Rate', + invoice_item_fields = [ + dict(fieldname='tax_rate', label='Tax Rate', fieldtype='Float', insert_after='description', print_hide=1, hidden=1, read_only=1), dict(fieldname='tax_amount', label='Tax Amount', @@ -24,135 +24,154 @@ def make_custom_fields(update=True): dict(fieldname='total_amount', label='Total Amount', fieldtype='Currency', insert_after='tax_amount', print_hide=1, hidden=1, read_only=1, options="currency") - ] + ] - custom_fields = { - 'Company': [ - dict(fieldname='sb_e_invoicing', label='E-Invoicing', - fieldtype='Section Break', insert_after='date_of_establishment', print_hide=1), - dict(fieldname='fiscal_regime', label='Fiscal Regime', - fieldtype='Select', insert_after='sb_e_invoicing', print_hide=1, - options="\n".join(map(lambda x: x.decode('utf-8'), fiscal_regimes))), - dict(fieldname='fiscal_code', label='Fiscal Code', fieldtype='Data', insert_after='fiscal_regime', print_hide=1, - description=_("Applicable if the company is an Individual or a Proprietorship")), - dict(fieldname='vat_collectability', label='VAT Collectability', - fieldtype='Select', insert_after='fiscal_code', print_hide=1, - options="\n".join(map(lambda x: x.decode('utf-8'), vat_collectability_options))), - dict(fieldname='cb_e_invoicing1', fieldtype='Column Break', insert_after='vat_collectability', print_hide=1), - dict(fieldname='registrar_office_province', label='Province of the Registrar Office', - fieldtype='Data', insert_after='cb_e_invoicing1', print_hide=1, length=2), - dict(fieldname='registration_number', label='Registration Number', - fieldtype='Data', insert_after='registrar_office_province', print_hide=1, length=20), - dict(fieldname='share_capital_amount', label='Share Capital', - fieldtype='Currency', insert_after='registration_number', print_hide=1, - description=_('Applicable if the company is SpA, SApA or SRL')), - dict(fieldname='no_of_members', label='No of Members', - fieldtype='Select', insert_after='share_capital_amount', print_hide=1, - options="\nSU-Socio Unico\nSM-Piu Soci", description=_("Applicable if the company is a limited liability company")), - dict(fieldname='liquidation_state', label='Liquidation State', - fieldtype='Select', insert_after='no_of_members', print_hide=1, - options="\nLS-In Liquidazione\nLN-Non in Liquidazione") - ], - 'Sales Taxes and Charges': [ - dict(fieldname='tax_exemption_reason', label='Tax Exemption Reason', - fieldtype='Select', insert_after='included_in_print_rate', print_hide=1, - depends_on='eval:doc.charge_type!="Actual" && doc.rate==0.0', - options="\n" + "\n".join(map(lambda x: x.decode('utf-8'), tax_exemption_reasons))), - dict(fieldname='tax_exemption_law', label='Tax Exempt Under', - fieldtype='Text', insert_after='tax_exemption_reason', print_hide=1, - depends_on='eval:doc.charge_type!="Actual" && doc.rate==0.0') - ], - 'Customer': [ - dict(fieldname='fiscal_code', label='Fiscal Code', fieldtype='Data', insert_after='tax_id', print_hide=1), - dict(fieldname='recipient_code', label='Recipient Code', - fieldtype='Data', insert_after='fiscal_code', print_hide=1, default="0000000"), - dict(fieldname='pec', label='Recipient PEC', - fieldtype='Data', insert_after='fiscal_code', print_hide=1), - dict(fieldname='is_public_administration', label='Is Public Administration', - fieldtype='Check', insert_after='is_internal_customer', print_hide=1, - description=_("Set this if the customer is a Public Administration company."), - depends_on='eval:doc.customer_type=="Company"'), - dict(fieldname='first_name', label='First Name', fieldtype='Data', - insert_after='salutation', print_hide=1, depends_on='eval:doc.customer_type!="Company"'), - dict(fieldname='last_name', label='Last Name', fieldtype='Data', - insert_after='first_name', print_hide=1, depends_on='eval:doc.customer_type!="Company"') - ], - 'Mode of Payment': [ - dict(fieldname='mode_of_payment_code', label='Code', - fieldtype='Select', insert_after='included_in_print_rate', print_hide=1, - options="\n".join(map(lambda x: x.decode('utf-8'), mode_of_payment_codes))) - ], - 'Payment Schedule': [ - dict(fieldname='mode_of_payment_code', label='Code', - fieldtype='Select', insert_after='mode_of_payment', print_hide=1, - options="\n".join(map(lambda x: x.decode('utf-8'), mode_of_payment_codes)), - fetch_from="mode_of_payment.mode_of_payment_code", read_only=1), - dict(fieldname='bank_account', label='Bank Account', - fieldtype='Link', insert_after='mode_of_payment_code', print_hide=1, - options="Bank Account"), - dict(fieldname='bank_account_name', label='Bank Account Name', - fieldtype='Data', insert_after='bank_account', print_hide=1, - fetch_from="bank_account.account_name", read_only=1), - dict(fieldname='bank_account_no', label='Bank Account No', - fieldtype='Data', insert_after='bank_account_name', print_hide=1, - fetch_from="bank_account.bank_account_no", read_only=1), - dict(fieldname='bank_account_iban', label='IBAN', - fieldtype='Data', insert_after='bank_account_name', print_hide=1, - fetch_from="bank_account.iban", read_only=1), - ], - "Sales Invoice": [ - dict(fieldname='vat_collectability', label='VAT Collectability', - fieldtype='Select', insert_after='taxes_and_charges', print_hide=1, - options="\n".join(map(lambda x: x.decode('utf-8'), vat_collectability_options)), - fetch_from="company.vat_collectability"), - dict(fieldname='sb_e_invoicing_reference', label='E-Invoicing', - fieldtype='Section Break', insert_after='pos_total_qty', print_hide=1), - dict(fieldname='company_tax_id', label='Company Tax ID', - fieldtype='Data', insert_after='sb_e_invoicing_reference', print_hide=1, read_only=1, - fetch_from="company.tax_id"), - dict(fieldname='company_fiscal_code', label='Company Fiscal Code', - fieldtype='Data', insert_after='company_tax_id', print_hide=1, read_only=1, - fetch_from="company.fiscal_code"), - dict(fieldname='company_fiscal_regime', label='Company Fiscal Regime', - fieldtype='Data', insert_after='company_fiscal_code', print_hide=1, read_only=1, - fetch_from="company.fiscal_regime"), - dict(fieldname='cb_e_invoicing_reference', fieldtype='Column Break', - insert_after='company_fiscal_regime', print_hide=1), - dict(fieldname='customer_fiscal_code', label='Customer Fiscal Code', - fieldtype='Data', insert_after='cb_e_invoicing_reference', read_only=1, - fetch_from="customer.fiscal_code"), - ], - 'Purchase Invoice Item': invoice_item_fields, + customer_po_fields = [ + dict(fieldname='customer_po_details', label='Customer PO', + fieldtype='Section Break', insert_after='image'), + dict(fieldname='customer_po_no', label='Customer PO No', + fieldtype='Data', insert_after='customer_po_details', + fetch_from = 'sales_order.po_no', + print_hide=1, allow_on_submit=1, fetch_if_empty= 1, read_only=1, no_copy=1), + dict(fieldname='customer_po_clm_brk', label='', + fieldtype='Column Break', insert_after='customer_po_no', + print_hide=1, read_only=1), + dict(fieldname='customer_po_date', label='Customer PO Date', + fieldtype='Date', insert_after='customer_po_clm_brk', + fetch_from = 'sales_order.po_date', + print_hide=1, allow_on_submit=1, fetch_if_empty= 1, read_only=1, no_copy=1) + ] + + custom_fields = { + 'Company': [ + dict(fieldname='sb_e_invoicing', label='E-Invoicing', + fieldtype='Section Break', insert_after='date_of_establishment', print_hide=1), + dict(fieldname='fiscal_regime', label='Fiscal Regime', + fieldtype='Select', insert_after='sb_e_invoicing', print_hide=1, + options="\n".join(map(lambda x: frappe.safe_decode(x, encoding='utf-8'), fiscal_regimes))), + dict(fieldname='fiscal_code', label='Fiscal Code', fieldtype='Data', insert_after='fiscal_regime', print_hide=1, + description=_("Applicable if the company is an Individual or a Proprietorship")), + dict(fieldname='vat_collectability', label='VAT Collectability', + fieldtype='Select', insert_after='fiscal_code', print_hide=1, + options="\n".join(map(lambda x: frappe.safe_decode(x, encoding='utf-8'), vat_collectability_options))), + dict(fieldname='cb_e_invoicing1', fieldtype='Column Break', insert_after='vat_collectability', print_hide=1), + dict(fieldname='registrar_office_province', label='Province of the Registrar Office', + fieldtype='Data', insert_after='cb_e_invoicing1', print_hide=1, length=2), + dict(fieldname='registration_number', label='Registration Number', + fieldtype='Data', insert_after='registrar_office_province', print_hide=1, length=20), + dict(fieldname='share_capital_amount', label='Share Capital', + fieldtype='Currency', insert_after='registration_number', print_hide=1, + description=_('Applicable if the company is SpA, SApA or SRL')), + dict(fieldname='no_of_members', label='No of Members', + fieldtype='Select', insert_after='share_capital_amount', print_hide=1, + options="\nSU-Socio Unico\nSM-Piu Soci", description=_("Applicable if the company is a limited liability company")), + dict(fieldname='liquidation_state', label='Liquidation State', + fieldtype='Select', insert_after='no_of_members', print_hide=1, + options="\nLS-In Liquidazione\nLN-Non in Liquidazione") + ], + 'Sales Taxes and Charges': [ + dict(fieldname='tax_exemption_reason', label='Tax Exemption Reason', + fieldtype='Select', insert_after='included_in_print_rate', print_hide=1, + depends_on='eval:doc.charge_type!="Actual" && doc.rate==0.0', + options="\n" + "\n".join(map(lambda x: frappe.safe_decode(x, encoding='utf-8'), tax_exemption_reasons))), + dict(fieldname='tax_exemption_law', label='Tax Exempt Under', + fieldtype='Text', insert_after='tax_exemption_reason', print_hide=1, + depends_on='eval:doc.charge_type!="Actual" && doc.rate==0.0') + ], + 'Customer': [ + dict(fieldname='fiscal_code', label='Fiscal Code', fieldtype='Data', insert_after='tax_id', print_hide=1), + dict(fieldname='recipient_code', label='Recipient Code', + fieldtype='Data', insert_after='fiscal_code', print_hide=1, default="0000000"), + dict(fieldname='pec', label='Recipient PEC', + fieldtype='Data', insert_after='fiscal_code', print_hide=1), + dict(fieldname='is_public_administration', label='Is Public Administration', + fieldtype='Check', insert_after='is_internal_customer', print_hide=1, + description=_("Set this if the customer is a Public Administration company."), + depends_on='eval:doc.customer_type=="Company"'), + dict(fieldname='first_name', label='First Name', fieldtype='Data', + insert_after='salutation', print_hide=1, depends_on='eval:doc.customer_type!="Company"'), + dict(fieldname='last_name', label='Last Name', fieldtype='Data', + insert_after='first_name', print_hide=1, depends_on='eval:doc.customer_type!="Company"') + ], + 'Mode of Payment': [ + dict(fieldname='mode_of_payment_code', label='Code', + fieldtype='Select', insert_after='included_in_print_rate', print_hide=1, + options="\n".join(map(lambda x: frappe.safe_decode(x, encoding='utf-8'), mode_of_payment_codes))) + ], + 'Payment Schedule': [ + dict(fieldname='mode_of_payment_code', label='Code', + fieldtype='Select', insert_after='mode_of_payment', print_hide=1, + options="\n".join(map(lambda x: frappe.safe_decode(x, encoding='utf-8'), mode_of_payment_codes)), + fetch_from="mode_of_payment.mode_of_payment_code", read_only=1), + dict(fieldname='bank_account', label='Bank Account', + fieldtype='Link', insert_after='mode_of_payment_code', print_hide=1, + options="Bank Account"), + dict(fieldname='bank_account_name', label='Bank Name', + fieldtype='Data', insert_after='bank_account', print_hide=1, + fetch_from="bank_account.bank", read_only=1), + dict(fieldname='bank_account_no', label='Bank Account No', + fieldtype='Data', insert_after='bank_account_name', print_hide=1, + fetch_from="bank_account.bank_account_no", read_only=1), + dict(fieldname='bank_account_iban', label='IBAN', + fieldtype='Data', insert_after='bank_account_name', print_hide=1, + fetch_from="bank_account.iban", read_only=1), + dict(fieldname='bank_account_swift_number', label='Swift Code (BIC)', + fieldtype='Data', insert_after='bank_account_iban', print_hide=1, + fetch_from="bank_account.swift_number", read_only=1), + ], + "Sales Invoice": [ + dict(fieldname='vat_collectability', label='VAT Collectability', + fieldtype='Select', insert_after='taxes_and_charges', print_hide=1, + options="\n".join(map(lambda x: frappe.safe_decode(x, encoding='utf-8'), vat_collectability_options)), + fetch_from="company.vat_collectability"), + dict(fieldname='sb_e_invoicing_reference', label='E-Invoicing', + fieldtype='Section Break', insert_after='pos_total_qty', print_hide=1), + dict(fieldname='company_tax_id', label='Company Tax ID', + fieldtype='Data', insert_after='sb_e_invoicing_reference', print_hide=1, read_only=1, + fetch_from="company.tax_id"), + dict(fieldname='company_fiscal_code', label='Company Fiscal Code', + fieldtype='Data', insert_after='company_tax_id', print_hide=1, read_only=1, + fetch_from="company.fiscal_code"), + dict(fieldname='company_fiscal_regime', label='Company Fiscal Regime', + fieldtype='Data', insert_after='company_fiscal_code', print_hide=1, read_only=1, + fetch_from="company.fiscal_regime"), + dict(fieldname='cb_e_invoicing_reference', fieldtype='Column Break', + insert_after='company_fiscal_regime', print_hide=1), + dict(fieldname='customer_fiscal_code', label='Customer Fiscal Code', + fieldtype='Data', insert_after='cb_e_invoicing_reference', read_only=1, + fetch_from="customer.fiscal_code"), + ], + 'Purchase Invoice Item': invoice_item_fields, 'Sales Order Item': invoice_item_fields, 'Delivery Note Item': invoice_item_fields, - 'Sales Invoice Item': invoice_item_fields, + 'Sales Invoice Item': invoice_item_fields + customer_po_fields, 'Quotation Item': invoice_item_fields, 'Purchase Order Item': invoice_item_fields, 'Purchase Receipt Item': invoice_item_fields, 'Supplier Quotation Item': invoice_item_fields, - 'Address': [ - dict(fieldname='country_code', label='Country Code', - fieldtype='Data', insert_after='country', print_hide=1, read_only=1, - fetch_from="country.code"), - dict(fieldname='state_code', label='State Code', - fieldtype='Data', insert_after='state', print_hide=1) - ] - } + 'Address': [ + dict(fieldname='country_code', label='Country Code', + fieldtype='Data', insert_after='country', print_hide=1, read_only=0, + fetch_from="country.code"), + dict(fieldname='state_code', label='State Code', + fieldtype='Data', insert_after='state', print_hide=1) + ] + } - create_custom_fields(custom_fields, ignore_validate = frappe.flags.in_patch, update=update) + create_custom_fields(custom_fields, ignore_validate = frappe.flags.in_patch, update=update) def setup_report(): - report_name = 'Electronic Invoice Register' + report_name = 'Electronic Invoice Register' - frappe.db.sql(""" update `tabReport` set disabled = 0 where - name = %s """, report_name) + frappe.db.sql(""" update `tabReport` set disabled = 0 where + name = %s """, report_name) - if not frappe.db.get_value('Custom Role', dict(report=report_name)): - frappe.get_doc(dict( - doctype='Custom Role', - report=report_name, - roles= [ - dict(role='Accounts User'), - dict(role='Accounts Manager') - ] - )).insert() + if not frappe.db.get_value('Custom Role', dict(report=report_name)): + frappe.get_doc(dict( + doctype='Custom Role', + report=report_name, + roles= [ + dict(role='Accounts User'), + dict(role='Accounts Manager') + ] + )).insert() diff --git a/erpnext/regional/italy/utils.py b/erpnext/regional/italy/utils.py index c86ad78cbc9..5fae858efeb 100644 --- a/erpnext/regional/italy/utils.py +++ b/erpnext/regional/italy/utils.py @@ -4,6 +4,7 @@ import frappe, json, os from frappe.utils import flt, cstr from erpnext.controllers.taxes_and_totals import get_itemised_tax from frappe import _ +from six import string_types from frappe.utils.file_manager import save_file, remove_file from frappe.desk.form.load import get_attachments from erpnext.regional.italy import state_codes @@ -82,6 +83,14 @@ def prepare_invoice(invoice, progressive_number): if item.tax_rate == 0.0 and item.tax_amount == 0.0: item.tax_exemption_reason = tax_data["0.0"]["tax_exemption_reason"] + customer_po_data = {} + for d in invoice.e_invoice_items: + if (d.customer_po_no and d.customer_po_date + and d.customer_po_no not in customer_po_data): + customer_po_data[d.customer_po_no] = d.customer_po_date + + invoice.customer_po_data = customer_po_data + return invoice def get_conditions(filters): @@ -134,6 +143,7 @@ def get_invoice_summary(items, taxes): idx=len(items)+1, item_code=reference_row.description, item_name=reference_row.description, + description=reference_row.description, rate=reference_row.tax_amount, qty=1.0, amount=reference_row.tax_amount, @@ -142,7 +152,7 @@ def get_invoice_summary(items, taxes): tax_amount=(reference_row.tax_amount * tax.rate) / 100, net_amount=reference_row.tax_amount, taxable_amount=reference_row.tax_amount, - item_tax_rate="{}", + item_tax_rate={tax.account_head: tax.rate}, charges=True ) ) @@ -150,10 +160,16 @@ def get_invoice_summary(items, taxes): #Check item tax rates if tax rate is zero. if tax.rate == 0: for item in items: - item_tax_rate = json.loads(item.item_tax_rate) - if tax.account_head in item_tax_rate: + item_tax_rate = item.item_tax_rate + if isinstance(item.item_tax_rate, string_types): + item_tax_rate = json.loads(item.item_tax_rate) + + if item_tax_rate and tax.account_head in item_tax_rate: key = cstr(item_tax_rate[tax.account_head]) - summary_data.setdefault(key, {"tax_amount": 0.0, "taxable_amount": 0.0, "tax_exemption_reason": "", "tax_exemption_law": ""}) + if key not in summary_data: + summary_data.setdefault(key, {"tax_amount": 0.0, "taxable_amount": 0.0, + "tax_exemption_reason": "", "tax_exemption_law": ""}) + summary_data[key]["tax_amount"] += item.tax_amount summary_data[key]["taxable_amount"] += item.net_amount if key == "0.0": @@ -189,28 +205,41 @@ def sales_invoice_validate(doc): if not doc.company_address: frappe.throw(_("Please set an Address on the Company '%s'" % doc.company), title=_("E-Invoicing Information Missing")) else: - validate_address(doc.company_address, "Company") + validate_address(doc.company_address) + company_fiscal_regime = frappe.get_cached_value("Company", doc.company, 'fiscal_regime') + if not company_fiscal_regime: + frappe.throw(_("Fiscal Regime is mandatory, kindly set the fiscal regime in the company {0}") + .format(doc.company)) + else: + doc.company_fiscal_regime = company_fiscal_regime + + doc.company_tax_id = frappe.get_cached_value("Company", doc.company, 'tax_id') + doc.company_fiscal_code = frappe.get_cached_value("Company", doc.company, 'fiscal_code') if not doc.company_tax_id and not doc.company_fiscal_code: frappe.throw(_("Please set either the Tax ID or Fiscal Code on Company '%s'" % doc.company), title=_("E-Invoicing Information Missing")) #Validate customer details - customer_type, is_public_administration = frappe.db.get_value("Customer", doc.customer, ["customer_type", "is_public_administration"]) - if customer_type == _("Individual"): + customer = frappe.get_doc("Customer", doc.customer) + + if customer.customer_type == _("Individual"): + doc.customer_fiscal_code = customer.fiscal_code if not doc.customer_fiscal_code: frappe.throw(_("Please set Fiscal Code for the customer '%s'" % doc.customer), title=_("E-Invoicing Information Missing")) else: - if is_public_administration: + if customer.is_public_administration: + doc.customer_fiscal_code = customer.fiscal_code if not doc.customer_fiscal_code: frappe.throw(_("Please set Fiscal Code for the public administration '%s'" % doc.customer), title=_("E-Invoicing Information Missing")) else: + doc.tax_id = customer.tax_id if not doc.tax_id: frappe.throw(_("Please set Tax ID for the customer '%s'" % doc.customer), title=_("E-Invoicing Information Missing")) if not doc.customer_address: frappe.throw(_("Please set the Customer Address"), title=_("E-Invoicing Information Missing")) else: - validate_address(doc.customer_address, "Customer") + validate_address(doc.customer_address) if not len(doc.taxes): frappe.throw(_("Please set at least one row in the Taxes and Charges Table"), title=_("E-Invoicing Information Missing")) @@ -220,6 +249,10 @@ def sales_invoice_validate(doc): frappe.throw(_("Row {0}: Please set at Tax Exemption Reason in Sales Taxes and Charges".format(row.idx)), title=_("E-Invoicing Information Missing")) + for schedule in doc.payment_schedule: + if schedule.mode_of_payment and not schedule.mode_of_payment_code: + schedule.mode_of_payment_code = frappe.get_cached_value('Mode of Payment', + schedule.mode_of_payment, 'mode_of_payment_code') #Ensure payment details are valid for e-invoice. def sales_invoice_on_submit(doc, method): @@ -241,14 +274,34 @@ def sales_invoice_on_submit(doc, method): prepare_and_attach_invoice(doc) -def prepare_and_attach_invoice(doc): - progressive_name, progressive_number = get_progressive_name_and_number(doc) +def prepare_and_attach_invoice(doc, replace=False): + progressive_name, progressive_number = get_progressive_name_and_number(doc, replace) invoice = prepare_invoice(doc, progressive_number) invoice_xml = frappe.render_template('erpnext/regional/italy/e-invoice.xml', context={"doc": invoice}, is_path=True) + invoice_xml = invoice_xml.replace("&", "&") xml_filename = progressive_name + ".xml" - save_file(xml_filename, invoice_xml, dt=doc.doctype, dn=doc.name, is_private=True) + return save_file(xml_filename, invoice_xml, dt=doc.doctype, dn=doc.name, is_private=True) + +@frappe.whitelist() +def generate_single_invoice(docname): + doc = frappe.get_doc("Sales Invoice", docname) + + + e_invoice = prepare_and_attach_invoice(doc, True) + + return e_invoice.file_name + +@frappe.whitelist() +def download_e_invoice_file(file_name): + content = None + with open(frappe.get_site_path('private', 'files', file_name), "r") as f: + content = f.read() + + frappe.local.response.filename = file_name + frappe.local.response.filecontent = content + frappe.local.response.type = "download" #Delete e-invoice attachment on cancel. def sales_invoice_on_cancel(doc, method): @@ -268,18 +321,19 @@ def get_e_invoice_attachments(invoice): company_tax_id = invoice.company_tax_id if invoice.company_tax_id.startswith("IT") else "IT" + invoice.company_tax_id for attachment in attachments: - if attachment.file_name.startswith(company_tax_id) and attachment.file_name.endswith(".xml"): + if attachment.file_name and attachment.file_name.startswith(company_tax_id) and attachment.file_name.endswith(".xml"): out.append(attachment) return out -def validate_address(address_name, address_context): - pincode, city = frappe.db.get_value("Address", address_name, ["pincode", "city"]) - if not pincode: - frappe.throw(_("Please set pin code on %s Address" % address_context), title=_("E-Invoicing Information Missing")) - if not city: - frappe.throw(_("Please set city on %s Address" % address_context), title=_("E-Invoicing Information Missing")) +def validate_address(address_name): + fields = ["pincode", "city", "country_code"] + data = frappe.get_cached_value("Address", address_name, fields, as_dict=1) or {} + for field in fields: + if not data.get(field): + frappe.throw(_("Please set {0} for address {1}".format(field.replace('-',''), address_name)), + title=_("E-Invoicing Information Missing")) def get_unamended_name(doc): attributes = ["naming_series", "amended_from"] @@ -292,7 +346,13 @@ def get_unamended_name(doc): else: return doc.name -def get_progressive_name_and_number(doc): +def get_progressive_name_and_number(doc, replace=False): + if replace: + for attachment in get_e_invoice_attachments(doc): + remove_file(attachment.name, attached_to_doctype=doc.doctype, attached_to_name=doc.name) + filename = attachment.file_name.split(".xml")[0] + return filename, filename.split("_")[1] + company_tax_id = doc.company_tax_id if doc.company_tax_id.startswith("IT") else "IT" + doc.company_tax_id progressive_name = frappe.model.naming.make_autoname(company_tax_id + "_.#####") progressive_number = progressive_name.split("_")[1] @@ -300,8 +360,17 @@ def get_progressive_name_and_number(doc): return progressive_name, progressive_number def set_state_code(doc, method): + if doc.get('country_code'): + doc.country_code = doc.country_code.upper() + + if not doc.get('state'): + return + if not (hasattr(doc, "state_code") and doc.country in ["Italy", "Italia", "Italian Republic", "Repubblica Italiana"]): return state_codes_lower = {key.lower():value for key,value in state_codes.items()} - doc.state_code = state_codes_lower.get(doc.get('state','').lower()) + + state = doc.get('state','').lower() + if state_codes_lower.get(state): + doc.state_code = state_codes_lower.get(state) diff --git a/erpnext/regional/report/fichier_des_ecritures_comptables_[fec]/fichier_des_ecritures_comptables_[fec].py b/erpnext/regional/report/fichier_des_ecritures_comptables_[fec]/fichier_des_ecritures_comptables_[fec].py index 5fbf7007f4c..6b8d3f0139e 100644 --- a/erpnext/regional/report/fichier_des_ecritures_comptables_[fec]/fichier_des_ecritures_comptables_[fec].py +++ b/erpnext/regional/report/fichier_des_ecritures_comptables_[fec]/fichier_des_ecritures_comptables_[fec].py @@ -87,8 +87,8 @@ def get_gl_entries(filters): left join `tabPurchase Invoice` pur on gl.voucher_no = pur.name left join `tabJournal Entry` jnl on gl.voucher_no = jnl.name left join `tabPayment Entry` pay on gl.voucher_no = pay.name - left join `tabCustomer` cus on gl.party = cus.customer_name - left join `tabSupplier` sup on gl.party = sup.supplier_name + left join `tabCustomer` cus on gl.party = cus.name + left join `tabSupplier` sup on gl.party = sup.name where gl.company=%(company)s and gl.fiscal_year=%(fiscal_year)s {group_by_condition} order by GlPostDate, voucher_no"""\ diff --git a/erpnext/regional/united_arab_emirates/setup.py b/erpnext/regional/united_arab_emirates/setup.py index 3c8328b1074..250659e54da 100644 --- a/erpnext/regional/united_arab_emirates/setup.py +++ b/erpnext/regional/united_arab_emirates/setup.py @@ -28,24 +28,24 @@ def make_custom_fields(): purchase_invoice_fields = [ dict(fieldname='company_trn', label='Company TRN', fieldtype='Read Only', insert_after='shipping_address', - options='company.tax_id', print_hide=1), + fetch_from='company.tax_id', print_hide=1), dict(fieldname='supplier_name_in_arabic', label='Supplier Name in Arabic', fieldtype='Read Only', insert_after='supplier_name', - options='supplier.supplier_name_in_arabic', print_hide=1) + fetch_from='supplier.supplier_name_in_arabic', print_hide=1) ] sales_invoice_fields = [ dict(fieldname='company_trn', label='Company TRN', fieldtype='Read Only', insert_after='company_address', - options='company.tax_id', print_hide=1), + fetch_from='company.tax_id', print_hide=1), dict(fieldname='customer_name_in_arabic', label='Customer Name in Arabic', fieldtype='Read Only', insert_after='customer_name', - options='customer.customer_name_in_arabic', print_hide=1), + fetch_from='customer.customer_name_in_arabic', print_hide=1), ] invoice_item_fields = [ dict(fieldname='tax_code', label='Tax Code', - fieldtype='Read Only', options='item_code.tax_code', insert_after='description', + fieldtype='Read Only', fetch_from='item_code.tax_code', insert_after='description', allow_on_submit=1, print_hide=1), dict(fieldname='tax_rate', label='Tax Rate', fieldtype='Float', insert_after='tax_code', diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py index b589cdeaa43..8e81c13357c 100755 --- a/erpnext/selling/doctype/sales_order/sales_order.py +++ b/erpnext/selling/doctype/sales_order/sales_order.py @@ -388,6 +388,7 @@ class SalesOrder(SellingController): items.append(dict( name= i.name, item_code= i.item_code, + description= i.description, bom = bom, warehouse = i.warehouse, pending_qty = pending_qty, @@ -398,6 +399,7 @@ class SalesOrder(SellingController): items.append(dict( name= i.name, item_code= i.item_code, + description= i.description, bom = '', warehouse = i.warehouse, pending_qty = pending_qty, @@ -610,7 +612,8 @@ def make_sales_invoice(source_name, target_doc=None, ignore_permissions=False): def postprocess(source, target): set_missing_values(source, target) #Get the advance paid Journal Entries in Sales Invoice Advance - target.set_advances() + if target.get("allocate_advances_automatically"): + target.set_advances() def set_missing_values(source, target): target.is_pos = 0 @@ -901,7 +904,8 @@ def make_work_orders(items, sales_order, company, project=None): sales_order=sales_order, sales_order_item=i['sales_order_item'], project=project, - fg_warehouse=i['warehouse'] + fg_warehouse=i['warehouse'], + description=i['description'] )).insert() work_order.set_work_order_operations() work_order.save() diff --git a/erpnext/selling/doctype/sales_order/test_sales_order.py b/erpnext/selling/doctype/sales_order/test_sales_order.py index 0eb19e3417c..f270938ad3a 100644 --- a/erpnext/selling/doctype/sales_order/test_sales_order.py +++ b/erpnext/selling/doctype/sales_order/test_sales_order.py @@ -573,7 +573,8 @@ class TestSalesOrder(unittest.TestCase): "item_code": item.get("item_code"), "pending_qty": item.get("pending_qty"), "sales_order_item": item.get("sales_order_item"), - "bom": item.get("bom") + "bom": item.get("bom"), + "description": item.get("description") }) so_item_name[item.get("sales_order_item")]= item.get("pending_qty") make_work_orders(json.dumps({"items":po_items}), so.name, so.company) diff --git a/erpnext/selling/page/point_of_sale/point_of_sale.js b/erpnext/selling/page/point_of_sale/point_of_sale.js index c54430fd560..26cadae4ef9 100644 --- a/erpnext/selling/page/point_of_sale/point_of_sale.js +++ b/erpnext/selling/page/point_of_sale/point_of_sale.js @@ -446,16 +446,15 @@ erpnext.pos.PointOfSale = class PointOfSale { } setup_company() { - this.company = frappe.sys_defaults.company; return new Promise(resolve => { - if(!this.company) { + if(!frappe.sys_defaults.company) { frappe.prompt({fieldname:"company", options: "Company", fieldtype:"Link", label: __("Select Company"), reqd: 1}, (data) => { this.company = data.company; resolve(this.company); }, __("Select Company")); } else { - resolve(this.company); + resolve(); } }) } @@ -509,7 +508,9 @@ erpnext.pos.PointOfSale = class PointOfSale { } set_pos_profile_data() { - this.frm.doc.company = this.company; + if (this.company) { + this.frm.doc.company = this.company; + } return new Promise(resolve => { return this.frm.call({ diff --git a/erpnext/selling/page/point_of_sale/point_of_sale.py b/erpnext/selling/page/point_of_sale/point_of_sale.py index 56d91518d8c..e088679917b 100644 --- a/erpnext/selling/page/point_of_sale/point_of_sale.py +++ b/erpnext/selling/page/point_of_sale/point_of_sale.py @@ -39,7 +39,7 @@ def get_items(start, page_length, price_list, item_group, search_value="", pos_p if display_items_in_stock == 0: - res = frappe.db.sql("""select i.name as item_code, i.item_name, i.image as item_image, + res = frappe.db.sql("""select i.name as item_code, i.item_name, i.image as item_image, i.idx as idx, i.is_stock_item, item_det.price_list_rate, item_det.currency from `tabItem` i LEFT JOIN (select item_code, price_list_rate, currency from @@ -49,7 +49,7 @@ def get_items(start, page_length, price_list, item_group, search_value="", pos_p where i.disabled = 0 and i.has_variants = 0 and i.is_sales_item = 1 and i.item_group in (select name from `tabItem Group` where lft >= {lft} and rgt <= {rgt}) - and {condition} limit {start}, {page_length}""".format(start=start,page_length=page_length,lft=lft, rgt=rgt, condition=condition), + and {condition} order by idx desc limit {start}, {page_length}""".format(start=start,page_length=page_length,lft=lft, rgt=rgt, condition=condition), { 'item_code': item_code, 'price_list': price_list @@ -60,7 +60,7 @@ def get_items(start, page_length, price_list, item_group, search_value="", pos_p } elif display_items_in_stock == 1: - query = """select i.name as item_code, i.item_name, i.image as item_image, + query = """select i.name as item_code, i.item_name, i.image as item_image, i.idx as idx, i.is_stock_item, item_det.price_list_rate, item_det.currency from `tabItem` i LEFT JOIN (select item_code, price_list_rate, currency from @@ -79,7 +79,7 @@ def get_items(start, page_length, price_list, item_group, search_value="", pos_p where i.disabled = 0 and i.has_variants = 0 and i.is_sales_item = 1 and i.item_group in (select name from `tabItem Group` where lft >= {lft} and rgt <= {rgt}) - and {condition} limit {start}, {page_length}""".format + and {condition} order by idx desc limit {start}, {page_length}""".format (start=start,page_length=page_length,lft=lft, rgt=rgt, condition=condition), { 'item_code': item_code, diff --git a/erpnext/selling/report/address_and_contacts/address_and_contacts.py b/erpnext/selling/report/address_and_contacts/address_and_contacts.py index eb242d0a737..a9e43034b48 100644 --- a/erpnext/selling/report/address_and_contacts/address_and_contacts.py +++ b/erpnext/selling/report/address_and_contacts/address_and_contacts.py @@ -102,8 +102,7 @@ def get_party_details(party_type, party_list, doctype, party_details): records = frappe.get_list(doctype, filters=filters, fields=fields, as_list=True) for d in records: details = party_details.get(d[0]) - if details: - details.setdefault(frappe.scrub(doctype), []).append(d[1:]) + details.setdefault(frappe.scrub(doctype), []).append(d[1:]) return party_details diff --git a/erpnext/selling/report/sales_person_wise_transaction_summary/sales_person_wise_transaction_summary.js b/erpnext/selling/report/sales_person_wise_transaction_summary/sales_person_wise_transaction_summary.js index 67051c8b5e5..b236151bad9 100644 --- a/erpnext/selling/report/sales_person_wise_transaction_summary/sales_person_wise_transaction_summary.js +++ b/erpnext/selling/report/sales_person_wise_transaction_summary/sales_person_wise_transaction_summary.js @@ -33,7 +33,8 @@ frappe.query_reports["Sales Person-wise Transaction Summary"] = { label: __("Company"), fieldtype: "Link", options: "Company", - default: frappe.defaults.get_user_default("Company") + default: frappe.defaults.get_user_default("Company"), + reqd: 1 }, { fieldname:"item_group", diff --git a/erpnext/selling/report/sales_person_wise_transaction_summary/sales_person_wise_transaction_summary.py b/erpnext/selling/report/sales_person_wise_transaction_summary/sales_person_wise_transaction_summary.py index db11ae95c2f..41c7f765175 100644 --- a/erpnext/selling/report/sales_person_wise_transaction_summary/sales_person_wise_transaction_summary.py +++ b/erpnext/selling/report/sales_person_wise_transaction_summary/sales_person_wise_transaction_summary.py @@ -15,7 +15,7 @@ def execute(filters=None): item_details = get_item_details() data = [] - company_currency = get_company_currency(filters["company"]) + company_currency = get_company_currency(filters.get("company")) for d in entries: if d.stock_qty > 0 or filters.get('show_return_entries', 0): diff --git a/erpnext/setup/doctype/brand/test_records.json b/erpnext/setup/doctype/brand/test_records.json index d2a4ad4e238..e4f892eef50 100644 --- a/erpnext/setup/doctype/brand/test_records.json +++ b/erpnext/setup/doctype/brand/test_records.json @@ -1,6 +1,6 @@ [ { - "brand": "_Test Brand", + "brand": "_Test Brand", "doctype": "Brand" } ] \ No newline at end of file diff --git a/erpnext/setup/doctype/company/company.js b/erpnext/setup/doctype/company/company.js index 70e047a4e80..aff4baf9314 100644 --- a/erpnext/setup/doctype/company/company.js +++ b/erpnext/setup/doctype/company/company.js @@ -16,6 +16,12 @@ frappe.ui.form.on("Company", { filters: {"is_additional_component": 1} } }); + + frm.set_query("parent_company", function() { + return { + filters: {"is_group": 1} + } + }); }, company_name: function(frm) { @@ -28,6 +34,13 @@ frappe.ui.form.on("Company", { } }, + parent_company: function(frm) { + var bool = frm.doc.parent_company ? true : false; + frm.set_value('create_chart_of_accounts_based_on', bool ? "Existing Company" : ""); + frm.set_value('existing_company', bool ? frm.doc.parent_company : ""); + disbale_coa_fields(frm, bool); + }, + date_of_commencement: function(frm) { if(frm.doc.date_of_commencement date_sub(curdate(), interval 1 year) + st.sales_person = %s and st.parent = dt.name and dt.transaction_date > date_sub(curdate(), interval 1 year) group by dt.transaction_date ''', name))) sales_invoice = dict(frappe.db.sql('''select @@ -75,7 +76,7 @@ def get_timeline_data(doctype, name): where st.sales_person = %s and st.parent = dt.name and dt.posting_date > date_sub(curdate(), interval 1 year) group by dt.posting_date ''', name)) - + for key in sales_invoice: if out.get(key): out[key] += sales_invoice[key] @@ -97,5 +98,3 @@ def get_timeline_data(doctype, name): out[key] = delivery_note[key] return out - - diff --git a/erpnext/setup/doctype/setup_progress/setup_progress.py b/erpnext/setup/doctype/setup_progress/setup_progress.py index 9187eb79962..e1402f5844b 100644 --- a/erpnext/setup/doctype/setup_progress/setup_progress.py +++ b/erpnext/setup/doctype/setup_progress/setup_progress.py @@ -16,8 +16,9 @@ def get_setup_progress(): return frappe.local.setup_progress def get_action_completed_state(action_name): - return [d.is_completed for d in get_setup_progress().actions - if d.action_name == action_name][0] + for d in get_setup_progress().actions: + if d.action_name == action_name: + return d.is_completed def update_action_completed_state(action_name): action_table_doc = [d for d in get_setup_progress().actions diff --git a/erpnext/startup/boot.py b/erpnext/startup/boot.py index 62c9e7b90c5..8a164f9d136 100644 --- a/erpnext/startup/boot.py +++ b/erpnext/startup/boot.py @@ -33,7 +33,7 @@ def boot_session(bootinfo): tabCompany limit 1""") and 'Yes' or 'No' bootinfo.docs += frappe.db.sql("""select name, default_currency, cost_center, default_terms, - default_letter_head, default_bank_account, enable_perpetual_inventory from `tabCompany`""", + default_letter_head, default_bank_account, enable_perpetual_inventory, country from `tabCompany`""", as_dict=1, update={"doctype":":Company"}) party_account_types = frappe.db.sql(""" select name, ifnull(account_type, '') from `tabParty Type`""") diff --git a/erpnext/stock/__init__.py b/erpnext/stock/__init__.py index ea3d1036d2d..32a03e7373c 100644 --- a/erpnext/stock/__init__.py +++ b/erpnext/stock/__init__.py @@ -8,16 +8,21 @@ install_docs = [ {"doctype":"Role", "role_name":"Stock User", "name":"Stock User"}, {"doctype":"Role", "role_name":"Quality Manager", "name":"Quality Manager"}, {"doctype":"Item Group", "item_group_name":"All Item Groups", "is_group": 1}, - {"doctype":"Item Group", "item_group_name":"Default", + {"doctype":"Item Group", "item_group_name":"Default", "parent_item_group":"All Item Groups", "is_group": 0}, ] -def get_warehouse_account_map(): +def get_warehouse_account_map(company=None): if not frappe.flags.warehouse_account_map or frappe.flags.in_test: warehouse_account = frappe._dict() + filters = {} + if company: + filters['company'] = company + for d in frappe.get_all('Warehouse', fields = ["name", "account", "parent_warehouse", "company"], + filters = filters, order_by="lft, rgt"): if not d.account: d.account = get_warehouse_account(d, warehouse_account) @@ -57,6 +62,6 @@ def get_warehouse_account(warehouse, warehouse_account=None): frappe.throw(_("Please set Account in Warehouse {0} or Default Inventory Account in Company {1}") .format(warehouse.name, warehouse.company)) return account - + def get_company_default_inventory_account(company): return frappe.get_cached_value('Company', company, 'default_inventory_account') diff --git a/erpnext/stock/dashboard/item_dashboard.py b/erpnext/stock/dashboard/item_dashboard.py index 6242fa767ef..487c7656595 100644 --- a/erpnext/stock/dashboard/item_dashboard.py +++ b/erpnext/stock/dashboard/item_dashboard.py @@ -28,7 +28,7 @@ def get_data(item_code=None, warehouse=None, item_group=None, # user does not have access on warehouse return [] - return frappe.db.get_all('Bin', fields=['item_code', 'warehouse', 'projected_qty', + items = 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], @@ -41,3 +41,10 @@ def get_data(item_code=None, warehouse=None, item_group=None, order_by=sort_by + ' ' + sort_order, limit_start=start, limit_page_length='21') + + for item in items: + item.update({ + 'item_name': frappe.get_cached_value("Item", item.item_code, 'item_name') + }) + + return items diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py index 50996edddaa..1eb2b0985ac 100644 --- a/erpnext/stock/doctype/delivery_note/delivery_note.py +++ b/erpnext/stock/doctype/delivery_note/delivery_note.py @@ -391,7 +391,7 @@ def get_invoiced_qty_map(delivery_note): return invoiced_qty_map -def get_returned_qty_map(sales_orders): +def get_returned_qty_map_against_so(sales_orders): """returns a map: {so_detail: returned_qty}""" returned_qty_map = {} @@ -403,12 +403,25 @@ def get_returned_qty_map(sales_orders): return returned_qty_map +def get_returned_qty_map_against_dn(delivery_note): + """returns a map: {so_detail: returned_qty}""" + returned_qty_map = frappe._dict(frappe.db.sql("""select dn_item.item_code, sum(abs(dn_item.qty)) as qty + from `tabDelivery Note Item` dn_item, `tabDelivery Note` dn + where dn.name = dn_item.parent + and dn.docstatus = 1 + and dn.is_return = 1 + and dn.return_against = %s + group by dn_item.item_code + """, delivery_note)) + + return returned_qty_map + @frappe.whitelist() def make_sales_invoice(source_name, target_doc=None): doc = frappe.get_doc('Delivery Note', source_name) sales_orders = [d.against_sales_order for d in doc.items] - returned_qty_map = get_returned_qty_map(sales_orders) - + returned_qty_map_against_so = get_returned_qty_map_against_so(sales_orders) + returned_qty_map_against_dn = get_returned_qty_map_against_dn(source_name) invoiced_qty_map = get_invoiced_qty_map(source_name) def set_missing_values(source, target): @@ -428,13 +441,26 @@ def make_sales_invoice(source_name, target_doc=None): target.update(get_fetch_values("Sales Invoice", 'company_address', target.company_address)) def update_item(source_doc, target_doc, source_parent): - target_doc.qty = (source_doc.qty - - invoiced_qty_map.get(source_doc.name, 0) - returned_qty_map.get(source_doc.so_detail, 0)) + target_doc.qty, returned_qty = get_pending_qty(source_doc) + if not source_doc.so_detail: + returned_qty_map_against_dn[source_doc.item_code] = returned_qty if source_doc.serial_no and source_parent.per_billed > 0: target_doc.serial_no = get_delivery_note_serial_no(source_doc.item_code, target_doc.qty, source_parent.name) + def get_pending_qty(item_row): + pending_qty = item_row.qty - invoiced_qty_map.get(item_row.name, 0) - returned_qty_map_against_so.get(item_row.so_detail, 0) + returned_qty = flt(returned_qty_map_against_dn.get(item_row.item_code, 0)) + if not item_row.so_detail: + if returned_qty >= pending_qty: + pending_qty = 0 + returned_qty -= pending_qty + else: + pending_qty -= returned_qty + returned_qty = 0 + return pending_qty, returned_qty + doc = get_mapped_doc("Delivery Note", source_name, { "Delivery Note": { "doctype": "Sales Invoice", @@ -453,7 +479,7 @@ def make_sales_invoice(source_name, target_doc=None): "cost_center": "cost_center" }, "postprocess": update_item, - "filter": lambda d: abs(d.qty) - abs(invoiced_qty_map.get(d.name, 0))<=0 + "filter": lambda d: get_pending_qty(d)[0]<=0 }, "Sales Taxes and Charges": { "doctype": "Sales Taxes and Charges", diff --git a/erpnext/stock/doctype/delivery_note/test_delivery_note.py b/erpnext/stock/doctype/delivery_note/test_delivery_note.py index 0c5a71c30c0..5c031213d8a 100644 --- a/erpnext/stock/doctype/delivery_note/test_delivery_note.py +++ b/erpnext/stock/doctype/delivery_note/test_delivery_note.py @@ -636,7 +636,7 @@ class TestDeliveryNote(unittest.TestCase): self.assertEqual(expected_values[gle.account]["cost_center"], gle.cost_center) set_perpetual_inventory(0, company) - + def test_make_sales_invoice_from_dn_for_returned_qty(self): from erpnext.selling.doctype.sales_order.sales_order import make_delivery_note from erpnext.stock.doctype.delivery_note.delivery_note import make_sales_invoice @@ -655,6 +655,33 @@ class TestDeliveryNote(unittest.TestCase): si = make_sales_invoice(dn.name) self.assertEquals(si.items[0].qty, 1) + def test_make_sales_invoice_from_dn_with_returned_qty_against_dn(self): + from erpnext.stock.doctype.delivery_note.delivery_note import make_sales_invoice + + dn = create_delivery_note(qty=8, do_not_submit=True) + dn.append("items", { + "item_code": "_Test Item", + "warehouse": "_Test Warehouse - _TC", + "qty": 1, + "rate": 100, + "conversion_factor": 1.0, + "expense_account": "Cost of Goods Sold - _TC", + "cost_center": "_Test Cost Center - _TC" + }) + dn.submit() + + si1 = make_sales_invoice(dn.name) + si1.items[0].qty = 4 + si1.items.pop(1) + si1.save() + si1.submit() + + create_delivery_note(is_return=1, return_against=dn.name, qty=-2) + + si2 = make_sales_invoice(dn.name) + self.assertEquals(si2.items[0].qty, 2) + self.assertEquals(si2.items[1].qty, 1) + def create_delivery_note(**args): dn = frappe.new_doc("Delivery Note") args = frappe._dict(args) diff --git a/erpnext/stock/doctype/item/item.json b/erpnext/stock/doctype/item/item.json index 58c907793a7..2d9f6e9acd9 100644 --- a/erpnext/stock/doctype/item/item.json +++ b/erpnext/stock/doctype/item/item.json @@ -23,6 +23,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "name_and_description_section", "fieldtype": "Section Break", "hidden": 0, @@ -57,6 +58,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "naming_series", "fieldtype": "Select", "hidden": 0, @@ -91,6 +93,7 @@ "collapsible": 0, "columns": 0, "description": "", + "fetch_if_empty": 0, "fieldname": "item_code", "fieldtype": "Data", "hidden": 0, @@ -127,6 +130,7 @@ "columns": 0, "depends_on": "variant_of", "description": "If item is a variant of another item then description, image, pricing, taxes etc will be set from the template unless explicitly specified", + "fetch_if_empty": 0, "fieldname": "variant_of", "fieldtype": "Link", "hidden": 0, @@ -160,6 +164,7 @@ "bold": 1, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "item_name", "fieldtype": "Data", "hidden": 0, @@ -195,6 +200,7 @@ "collapsible": 0, "columns": 0, "description": "", + "fetch_if_empty": 0, "fieldname": "item_group", "fieldtype": "Link", "hidden": 0, @@ -230,6 +236,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "is_item_from_hub", "fieldtype": "Check", "hidden": 0, @@ -263,6 +270,7 @@ "collapsible": 0, "columns": 0, "description": "", + "fetch_if_empty": 0, "fieldname": "stock_uom", "fieldtype": "Link", "hidden": 0, @@ -298,6 +306,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break0", "fieldtype": "Column Break", "hidden": 0, @@ -329,6 +338,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "disabled", "fieldtype": "Check", "hidden": 0, @@ -361,6 +371,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "allow_alternative_item", "fieldtype": "Check", "hidden": 0, @@ -395,6 +406,7 @@ "columns": 0, "default": "1", "description": "", + "fetch_if_empty": 0, "fieldname": "is_stock_item", "fieldtype": "Check", "hidden": 0, @@ -431,6 +443,7 @@ "collapsible": 0, "columns": 0, "default": "1", + "fetch_if_empty": 0, "fieldname": "include_item_in_manufacturing", "fieldtype": "Check", "hidden": 0, @@ -464,6 +477,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval:(doc.__islocal&&doc.is_stock_item && !doc.has_serial_no && !doc.has_batch_no)", + "fetch_if_empty": 0, "fieldname": "opening_stock", "fieldtype": "Float", "hidden": 0, @@ -497,6 +511,7 @@ "collapsible": 0, "columns": 0, "depends_on": "is_stock_item", + "fetch_if_empty": 0, "fieldname": "valuation_rate", "fieldtype": "Currency", "hidden": 0, @@ -530,6 +545,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval:doc.__islocal", + "fetch_if_empty": 0, "fieldname": "standard_rate", "fieldtype": "Currency", "hidden": 0, @@ -562,6 +578,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "is_fixed_asset", "fieldtype": "Check", "hidden": 0, @@ -595,6 +612,7 @@ "collapsible": 0, "columns": 0, "depends_on": "is_fixed_asset", + "fetch_if_empty": 0, "fieldname": "asset_category", "fieldtype": "Link", "hidden": 0, @@ -629,6 +647,7 @@ "collapsible": 0, "columns": 0, "depends_on": "is_fixed_asset", + "fetch_if_empty": 0, "fieldname": "asset_naming_series", "fieldtype": "Select", "hidden": 0, @@ -663,6 +682,7 @@ "columns": 0, "depends_on": "eval:!doc.__islocal", "description": "", + "fetch_if_empty": 0, "fieldname": "tolerance", "fieldtype": "Float", "hidden": 0, @@ -697,6 +717,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "image", "fieldtype": "Attach Image", "hidden": 1, @@ -730,6 +751,7 @@ "bold": 0, "collapsible": 1, "columns": 0, + "fetch_if_empty": 0, "fieldname": "section_break_11", "fieldtype": "Section Break", "hidden": 0, @@ -762,6 +784,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "brand", "fieldtype": "Link", "hidden": 0, @@ -797,6 +820,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "description", "fieldtype": "Text Editor", "hidden": 0, @@ -831,6 +855,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "sb_barcodes", "fieldtype": "Section Break", "hidden": 0, @@ -863,6 +888,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "barcodes", "fieldtype": "Table", "hidden": 0, @@ -898,6 +924,7 @@ "collapsible_depends_on": "is_stock_item", "columns": 0, "depends_on": "is_stock_item", + "fetch_if_empty": 0, "fieldname": "inventory_section", "fieldtype": "Section Break", "hidden": 0, @@ -932,6 +959,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "shelf_life_in_days", "fieldtype": "Int", "hidden": 0, @@ -966,6 +994,7 @@ "columns": 0, "default": "2099-12-31", "depends_on": "is_stock_item", + "fetch_if_empty": 0, "fieldname": "end_of_life", "fieldtype": "Date", "hidden": 0, @@ -1001,6 +1030,7 @@ "collapsible": 0, "columns": 0, "default": "Purchase", + "fetch_if_empty": 0, "fieldname": "default_material_request_type", "fieldtype": "Select", "hidden": 0, @@ -1035,6 +1065,7 @@ "collapsible": 0, "columns": 0, "depends_on": "is_stock_item", + "fetch_if_empty": 0, "fieldname": "valuation_method", "fieldtype": "Select", "hidden": 0, @@ -1069,6 +1100,7 @@ "collapsible": 0, "columns": 0, "depends_on": "is_stock_item", + "fetch_if_empty": 0, "fieldname": "column_break1", "fieldtype": "Column Break", "hidden": 0, @@ -1103,6 +1135,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval:doc.is_stock_item", + "fetch_if_empty": 0, "fieldname": "warranty_period", "fieldtype": "Data", "hidden": 0, @@ -1139,6 +1172,7 @@ "columns": 0, "depends_on": "is_stock_item", "description": "", + "fetch_if_empty": 0, "fieldname": "weight_per_unit", "fieldtype": "Float", "hidden": 0, @@ -1172,6 +1206,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval:doc.is_stock_item", + "fetch_if_empty": 0, "fieldname": "weight_uom", "fieldtype": "Link", "hidden": 0, @@ -1207,6 +1242,7 @@ "columns": 0, "depends_on": "is_stock_item", "description": "", + "fetch_if_empty": 0, "fieldname": "reorder_section", "fieldtype": "Section Break", "hidden": 0, @@ -1242,6 +1278,7 @@ "columns": 0, "depends_on": "", "description": "Will also apply for variants unless overrridden", + "fetch_if_empty": 0, "fieldname": "reorder_levels", "fieldtype": "Table", "hidden": 0, @@ -1276,6 +1313,7 @@ "collapsible": 1, "columns": 0, "depends_on": "", + "fetch_if_empty": 0, "fieldname": "unit_of_measure_conversion", "fieldtype": "Section Break", "hidden": 0, @@ -1310,6 +1348,7 @@ "columns": 0, "depends_on": "", "description": "Will also apply for variants", + "fetch_if_empty": 0, "fieldname": "uoms", "fieldtype": "Table", "hidden": 0, @@ -1347,6 +1386,7 @@ "collapsible_depends_on": "eval:doc.has_batch_no || doc.has_serial_no || doc.is_fixed_asset", "columns": 0, "depends_on": "eval:doc.is_stock_item || doc.is_fixed_asset", + "fetch_if_empty": 0, "fieldname": "serial_nos_and_batches", "fieldtype": "Section Break", "hidden": 0, @@ -1381,6 +1421,7 @@ "columns": 0, "default": "", "depends_on": "eval:doc.is_stock_item", + "fetch_if_empty": 0, "fieldname": "has_batch_no", "fieldtype": "Check", "hidden": 0, @@ -1418,6 +1459,7 @@ "columns": 0, "depends_on": "has_batch_no", "description": "", + "fetch_if_empty": 0, "fieldname": "create_new_batch", "fieldtype": "Check", "hidden": 0, @@ -1452,6 +1494,7 @@ "columns": 0, "depends_on": "eval:doc.has_batch_no==1 && doc.create_new_batch==1", "description": "Example: ABCD.#####. If series is set and Batch No is not mentioned in transactions,then automatic batch number will be created based on this series. If you always want to explicitly mention Batch No for this item,leave this blank. Note: this setting will take priority over the Naming Series Prefix in Stock Settings.", + "fetch_if_empty": 0, "fieldname": "batch_number_series", "fieldtype": "Data", "hidden": 0, @@ -1485,6 +1528,7 @@ "collapsible": 0, "columns": 0, "depends_on": "has_batch_no", + "fetch_if_empty": 0, "fieldname": "has_expiry_date", "fieldtype": "Check", "hidden": 0, @@ -1518,6 +1562,7 @@ "collapsible": 0, "columns": 0, "depends_on": "has_batch_no", + "fetch_if_empty": 0, "fieldname": "retain_sample", "fieldtype": "Check", "hidden": 0, @@ -1552,6 +1597,7 @@ "columns": 0, "depends_on": "eval: (doc.retain_sample && doc.has_batch_no)", "description": "Maximum sample quantity that can be retained", + "fetch_if_empty": 0, "fieldname": "sample_quantity", "fieldtype": "Int", "hidden": 0, @@ -1584,6 +1630,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break_37", "fieldtype": "Column Break", "hidden": 0, @@ -1618,6 +1665,7 @@ "default": "", "depends_on": "eval:doc.is_stock_item || doc.is_fixed_asset", "description": "", + "fetch_if_empty": 0, "fieldname": "has_serial_no", "fieldtype": "Check", "hidden": 0, @@ -1655,6 +1703,7 @@ "columns": 0, "depends_on": "eval:doc.is_stock_item || doc.is_fixed_asset", "description": "Example: ABCD.#####\nIf series is set and Serial No is not mentioned in transactions,then automatic serial number will be created based on this series. If you always want to explicitly mention Serial Nos for this item. leave this blank.", + "fetch_if_empty": 0, "fieldname": "serial_no_series", "fieldtype": "Data", "hidden": 0, @@ -1689,6 +1738,7 @@ "collapsible_depends_on": "attributes", "columns": 0, "depends_on": "", + "fetch_if_empty": 0, "fieldname": "variants_section", "fieldtype": "Section Break", "hidden": 0, @@ -1724,6 +1774,7 @@ "default": "0", "depends_on": "eval:!doc.variant_of", "description": "If this item has variants,then it cannot be selected in sales orders etc.", + "fetch_if_empty": 0, "fieldname": "has_variants", "fieldtype": "Check", "hidden": 0, @@ -1759,6 +1810,7 @@ "columns": 0, "default": "Item Attribute", "depends_on": "has_variants", + "fetch_if_empty": 0, "fieldname": "variant_based_on", "fieldtype": "Select", "hidden": 0, @@ -1781,7 +1833,7 @@ "report_hide": 0, "reqd": 0, "search_index": 0, - "set_only_once": 1, + "set_only_once": 0, "translatable": 0, "unique": 0 }, @@ -1793,6 +1845,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval:(doc.has_variants || doc.variant_of) && doc.variant_based_on==='Item Attribute'", + "fetch_if_empty": 0, "fieldname": "attributes", "fieldtype": "Table", "hidden": 1, @@ -1826,6 +1879,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "defaults", "fieldtype": "Section Break", "hidden": 0, @@ -1858,6 +1912,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "item_defaults", "fieldtype": "Table", "hidden": 0, @@ -1891,6 +1946,7 @@ "bold": 0, "collapsible": 1, "columns": 0, + "fetch_if_empty": 0, "fieldname": "purchase_details", "fieldtype": "Section Break", "hidden": 0, @@ -1926,6 +1982,7 @@ "collapsible": 0, "columns": 0, "default": "1", + "fetch_if_empty": 0, "fieldname": "is_purchase_item", "fieldtype": "Check", "hidden": 0, @@ -1958,6 +2015,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "purchase_uom", "fieldtype": "Link", "hidden": 0, @@ -1994,6 +2052,7 @@ "default": "0.00", "depends_on": "is_stock_item", "description": "", + "fetch_if_empty": 0, "fieldname": "min_order_qty", "fieldtype": "Float", "hidden": 0, @@ -2028,6 +2087,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "safety_stock", "fieldtype": "Float", "hidden": 0, @@ -2060,6 +2120,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "purchase_details_cb", "fieldtype": "Column Break", "hidden": 0, @@ -2094,6 +2155,7 @@ "columns": 0, "depends_on": "", "description": "Average time taken by the supplier to deliver", + "fetch_if_empty": 0, "fieldname": "lead_time_days", "fieldtype": "Int", "hidden": 0, @@ -2129,6 +2191,7 @@ "collapsible": 0, "columns": 0, "depends_on": "", + "fetch_if_empty": 0, "fieldname": "last_purchase_rate", "fieldtype": "Float", "hidden": 0, @@ -2164,6 +2227,7 @@ "collapsible": 1, "columns": 0, "depends_on": "", + "fetch_if_empty": 0, "fieldname": "supplier_details", "fieldtype": "Section Break", "hidden": 0, @@ -2196,6 +2260,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "delivered_by_supplier", "fieldtype": "Check", "hidden": 0, @@ -2229,6 +2294,7 @@ "collapsible": 0, "columns": 0, "depends_on": "", + "fetch_if_empty": 0, "fieldname": "manufacturer", "fieldtype": "Link", "hidden": 0, @@ -2263,6 +2329,7 @@ "collapsible": 0, "columns": 0, "depends_on": "", + "fetch_if_empty": 0, "fieldname": "manufacturer_part_no", "fieldtype": "Data", "hidden": 0, @@ -2296,6 +2363,7 @@ "collapsible": 0, "columns": 0, "depends_on": "", + "fetch_if_empty": 0, "fieldname": "column_break2", "fieldtype": "Column Break", "hidden": 0, @@ -2331,6 +2399,7 @@ "collapsible": 0, "columns": 0, "depends_on": "", + "fetch_if_empty": 0, "fieldname": "supplier_items", "fieldtype": "Table", "hidden": 0, @@ -2364,6 +2433,7 @@ "bold": 0, "collapsible": 1, "columns": 0, + "fetch_if_empty": 0, "fieldname": "foreign_trade_details", "fieldtype": "Section Break", "hidden": 0, @@ -2396,6 +2466,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "country_of_origin", "fieldtype": "Link", "hidden": 0, @@ -2429,6 +2500,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break_59", "fieldtype": "Column Break", "hidden": 0, @@ -2460,6 +2532,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "customs_tariff_number", "fieldtype": "Link", "hidden": 0, @@ -2493,6 +2566,7 @@ "bold": 0, "collapsible": 1, "columns": 0, + "fetch_if_empty": 0, "fieldname": "sales_details", "fieldtype": "Section Break", "hidden": 0, @@ -2527,6 +2601,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "sales_uom", "fieldtype": "Link", "hidden": 0, @@ -2561,6 +2636,7 @@ "collapsible": 0, "columns": 0, "default": "1", + "fetch_if_empty": 0, "fieldname": "is_sales_item", "fieldtype": "Check", "hidden": 0, @@ -2594,6 +2670,7 @@ "collapsible": 0, "columns": 0, "depends_on": "", + "fetch_if_empty": 0, "fieldname": "column_break3", "fieldtype": "Column Break", "hidden": 0, @@ -2629,6 +2706,7 @@ "collapsible": 0, "columns": 0, "depends_on": "", + "fetch_if_empty": 0, "fieldname": "max_discount", "fieldtype": "Float", "hidden": 0, @@ -2663,6 +2741,7 @@ "bold": 0, "collapsible": 1, "columns": 0, + "fetch_if_empty": 0, "fieldname": "deferred_revenue", "fieldtype": "Section Break", "hidden": 0, @@ -2696,6 +2775,7 @@ "collapsible": 0, "columns": 0, "depends_on": "enable_deferred_revenue", + "fetch_if_empty": 0, "fieldname": "deferred_revenue_account", "fieldtype": "Link", "hidden": 0, @@ -2729,6 +2809,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "enable_deferred_revenue", "fieldtype": "Check", "hidden": 0, @@ -2761,6 +2842,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break_85", "fieldtype": "Column Break", "hidden": 0, @@ -2793,6 +2875,7 @@ "collapsible": 0, "columns": 0, "depends_on": "enable_deferred_revenue", + "fetch_if_empty": 0, "fieldname": "no_of_months", "fieldtype": "Int", "hidden": 0, @@ -2825,6 +2908,7 @@ "bold": 0, "collapsible": 1, "columns": 0, + "fetch_if_empty": 0, "fieldname": "deferred_expense_section", "fieldtype": "Section Break", "hidden": 0, @@ -2858,6 +2942,7 @@ "collapsible": 0, "columns": 0, "depends_on": "enable_deferred_expense", + "fetch_if_empty": 0, "fieldname": "deferred_expense_account", "fieldtype": "Link", "hidden": 0, @@ -2891,6 +2976,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "enable_deferred_expense", "fieldtype": "Check", "hidden": 0, @@ -2923,6 +3009,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break_88", "fieldtype": "Column Break", "hidden": 0, @@ -2955,6 +3042,7 @@ "collapsible": 0, "columns": 0, "depends_on": "enable_deferred_expense", + "fetch_if_empty": 0, "fieldname": "no_of_months_exp", "fieldtype": "Int", "hidden": 0, @@ -2987,6 +3075,7 @@ "bold": 0, "collapsible": 1, "columns": 0, + "fetch_if_empty": 0, "fieldname": "customer_details", "fieldtype": "Section Break", "hidden": 0, @@ -3021,6 +3110,7 @@ "columns": 0, "depends_on": "", "description": "", + "fetch_if_empty": 0, "fieldname": "customer_items", "fieldtype": "Table", "hidden": 0, @@ -3054,6 +3144,7 @@ "bold": 0, "collapsible": 1, "columns": 0, + "fetch_if_empty": 0, "fieldname": "item_tax_section_break", "fieldtype": "Section Break", "hidden": 0, @@ -3089,6 +3180,7 @@ "collapsible": 0, "columns": 0, "description": "Will also apply for variants", + "fetch_if_empty": 0, "fieldname": "taxes", "fieldtype": "Table", "hidden": 0, @@ -3124,6 +3216,7 @@ "bold": 0, "collapsible": 1, "columns": 0, + "fetch_if_empty": 0, "fieldname": "inspection_criteria", "fieldtype": "Section Break", "hidden": 0, @@ -3159,6 +3252,7 @@ "collapsible": 0, "columns": 0, "default": "", + "fetch_if_empty": 0, "fieldname": "inspection_required_before_purchase", "fieldtype": "Check", "hidden": 0, @@ -3194,6 +3288,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "inspection_required_before_delivery", "fieldtype": "Check", "hidden": 0, @@ -3227,6 +3322,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval:(doc.inspection_required_before_purchase || doc.inspection_required_before_delivery)", + "fetch_if_empty": 0, "fieldname": "quality_inspection_template", "fieldtype": "Link", "hidden": 0, @@ -3261,6 +3357,7 @@ "collapsible": 1, "columns": 0, "depends_on": "is_stock_item", + "fetch_if_empty": 0, "fieldname": "manufacturing", "fieldtype": "Section Break", "hidden": 0, @@ -3296,6 +3393,7 @@ "collapsible": 0, "columns": 0, "depends_on": "", + "fetch_if_empty": 0, "fieldname": "default_bom", "fieldtype": "Link", "hidden": 0, @@ -3333,6 +3431,7 @@ "columns": 0, "default": "", "description": "If subcontracted to a vendor", + "fetch_if_empty": 0, "fieldname": "is_sub_contracted_item", "fieldtype": "Check", "hidden": 0, @@ -3368,6 +3467,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break_74", "fieldtype": "Column Break", "hidden": 0, @@ -3399,6 +3499,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "customer_code", "fieldtype": "Data", "hidden": 1, @@ -3431,6 +3532,7 @@ "bold": 0, "collapsible": 1, "columns": 0, + "fetch_if_empty": 0, "fieldname": "website_section", "fieldtype": "Section Break", "hidden": 0, @@ -3465,6 +3567,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval:!doc.variant_of", + "fetch_if_empty": 0, "fieldname": "show_in_website", "fieldtype": "Check", "hidden": 0, @@ -3498,6 +3601,7 @@ "collapsible": 0, "columns": 0, "depends_on": "variant_of", + "fetch_if_empty": 0, "fieldname": "show_variant_in_website", "fieldtype": "Check", "hidden": 0, @@ -3531,6 +3635,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval: doc.show_in_website || doc.show_variant_in_website", + "fetch_if_empty": 0, "fieldname": "route", "fieldtype": "Small Text", "hidden": 0, @@ -3565,6 +3670,7 @@ "columns": 0, "depends_on": "eval: doc.show_in_website || doc.show_variant_in_website", "description": "Items with higher weightage will be shown higher", + "fetch_if_empty": 0, "fieldname": "weightage", "fieldtype": "Int", "hidden": 0, @@ -3599,6 +3705,7 @@ "columns": 0, "depends_on": "eval: doc.show_in_website || doc.show_variant_in_website", "description": "Show a slideshow at the top of the page", + "fetch_if_empty": 0, "fieldname": "slideshow", "fieldtype": "Link", "hidden": 0, @@ -3634,6 +3741,7 @@ "columns": 0, "depends_on": "eval: doc.show_in_website || doc.show_variant_in_website", "description": "Item Image (if not slideshow)", + "fetch_if_empty": 0, "fieldname": "website_image", "fieldtype": "Attach", "hidden": 0, @@ -3667,6 +3775,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "thumbnail", "fieldtype": "Data", "hidden": 0, @@ -3699,6 +3808,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "cb72", "fieldtype": "Column Break", "hidden": 0, @@ -3732,6 +3842,7 @@ "columns": 0, "depends_on": "eval: doc.show_in_website || doc.show_variant_in_website", "description": "Show \"In Stock\" or \"Not in Stock\" based on stock available in this warehouse.", + "fetch_if_empty": 0, "fieldname": "website_warehouse", "fieldtype": "Link", "hidden": 0, @@ -3767,6 +3878,7 @@ "columns": 0, "depends_on": "eval: doc.show_in_website || doc.show_variant_in_website", "description": "List this Item in multiple groups on the website.", + "fetch_if_empty": 0, "fieldname": "website_item_groups", "fieldtype": "Table", "hidden": 0, @@ -3802,6 +3914,7 @@ "collapsible_depends_on": "website_specifications", "columns": 0, "depends_on": "eval: doc.show_in_website || doc.show_variant_in_website", + "fetch_if_empty": 0, "fieldname": "sb72", "fieldtype": "Section Break", "hidden": 0, @@ -3835,6 +3948,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval: doc.show_in_website || doc.show_variant_in_website", + "fetch_if_empty": 0, "fieldname": "copy_from_item_group", "fieldtype": "Button", "hidden": 0, @@ -3868,6 +3982,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval: doc.show_in_website || doc.show_variant_in_website", + "fetch_if_empty": 0, "fieldname": "website_specifications", "fieldtype": "Table", "hidden": 0, @@ -3902,6 +4017,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval: doc.show_in_website || doc.show_variant_in_website", + "fetch_if_empty": 0, "fieldname": "web_long_description", "fieldtype": "Text Editor", "hidden": 0, @@ -3934,6 +4050,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "total_projected_qty", "fieldtype": "Float", "hidden": 1, @@ -3967,6 +4084,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval:(!doc.is_item_from_hub)", + "fetch_if_empty": 0, "fieldname": "hub_publishing_sb", "fieldtype": "Section Break", "hidden": 0, @@ -4001,6 +4119,7 @@ "columns": 0, "default": "0", "description": "Publish Item to hub.erpnext.com", + "fetch_if_empty": 0, "fieldname": "publish_in_hub", "fieldtype": "Check", "hidden": 0, @@ -4033,6 +4152,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "hub_category_to_publish", "fieldtype": "Data", "hidden": 0, @@ -4067,6 +4187,7 @@ "collapsible": 0, "columns": 0, "description": "Publish \"In Stock\" or \"Not in Stock\" on Hub based on stock available in this warehouse.", + "fetch_if_empty": 0, "fieldname": "hub_warehouse", "fieldtype": "Link", "hidden": 0, @@ -4101,6 +4222,7 @@ "collapsible": 0, "columns": 0, "default": "0", + "fetch_if_empty": 0, "fieldname": "synced_with_hub", "fieldtype": "Check", "hidden": 0, @@ -4139,7 +4261,7 @@ "issingle": 0, "istable": 0, "max_attachments": 1, - "modified": "2019-02-16 17:43:56.039611", + "modified": "2019-04-05 12:03:24.530849", "modified_by": "Administrator", "module": "Stock", "name": "Item", diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py index bd06688caa2..e93e7d9b615 100644 --- a/erpnext/stock/doctype/item/item.py +++ b/erpnext/stock/doctype/item/item.py @@ -9,11 +9,11 @@ import erpnext import frappe import copy from erpnext.controllers.item_variant import (ItemVariantExistsError, - copy_attributes_to_variant, get_variant, make_variant_item_code, validate_item_variant_attributes) + copy_attributes_to_variant, get_variant, make_variant_item_code, validate_item_variant_attributes) from erpnext.setup.doctype.item_group.item_group import (get_parent_item_groups, invalidate_cache_for) from frappe import _, msgprint from frappe.utils import (cint, cstr, flt, formatdate, get_timestamp, getdate, - now_datetime, random_string, strip) + now_datetime, random_string, strip) from frappe.utils.html_utils import clean_html from frappe.website.doctype.website_slideshow.website_slideshow import \ get_slideshow @@ -49,9 +49,6 @@ class Item(WebsiteGenerator): self.set_onload('stock_exists', self.stock_ledger_created()) self.set_asset_naming_series() - if self.is_fixed_asset: - asset = self.asset_exists() - self.set_onload("asset_exists", True if asset else False) def set_asset_naming_series(self): if not hasattr(self, '_asset_naming_series'): @@ -118,9 +115,9 @@ class Item(WebsiteGenerator): self.validate_has_variants() self.validate_stock_exists_for_template_item() - self.validate_asset_exists_for_serialized_asset() self.validate_attributes() self.validate_variant_attributes() + self.validate_variant_based_on_change() self.validate_website_image() self.make_thumbnail() self.validate_fixed_asset() @@ -128,6 +125,7 @@ class Item(WebsiteGenerator): self.validate_uom_conversion_factor() self.validate_item_defaults() self.update_defaults_from_item_group() + self.validate_stock_for_has_batch_and_has_serial() if not self.get("__islocal"): self.old_item_group = frappe.db.get_value(self.doctype, self.name, "item_group") @@ -151,7 +149,7 @@ class Item(WebsiteGenerator): '''Add a new price''' if not price_list: price_list = (frappe.db.get_single_value('Selling Settings', 'selling_price_list') - or frappe.db.get_value('Price List', _('Standard Selling'))) + or frappe.db.get_value('Price List', _('Standard Selling'))) if price_list: item_price = frappe.get_doc({ "doctype": "Item Price", @@ -190,7 +188,7 @@ class Item(WebsiteGenerator): def make_route(self): if not self.route: return cstr(frappe.db.get_value('Item Group', self.item_group, - 'route')) + '/' + self.scrub((self.item_name if self.item_name else self.item_code) + '-' + random_string(5)) + 'route')) + '/' + self.scrub((self.item_name if self.item_name else self.item_code) + '-' + random_string(5)) def validate_website_image(self): """Validate if the website image is a public file""" @@ -213,7 +211,7 @@ class Item(WebsiteGenerator): if not file_doc: if not auto_set_website_image: frappe.msgprint(_("Website Image {0} attached to Item {1} cannot be found") - .format(self.website_image, self.name)) + .format(self.website_image, self.name)) self.website_image = None @@ -314,8 +312,8 @@ class Item(WebsiteGenerator): # load variants # also used in set_attribute_context context.variants = frappe.get_all("Item", - filters={"variant_of": self.name, "show_variant_in_website": 1}, - order_by="name asc") + filters={"variant_of": self.name, "show_variant_in_website": 1}, + order_by="name asc") variant = frappe.form_dict.variant if not variant and context.variants: @@ -326,7 +324,7 @@ class Item(WebsiteGenerator): context.variant = frappe.get_doc("Item", variant) for fieldname in ("website_image", "web_long_description", "description", - "website_specifications"): + "website_specifications"): if context.variant.get(fieldname): value = context.variant.get(fieldname) if isinstance(value, list): @@ -349,7 +347,7 @@ class Item(WebsiteGenerator): # load attributes for v in context.variants: v.attributes = frappe.get_all("Item Variant Attribute", - fields=["attribute", "attribute_value"], + fields=["attribute", "attribute_value"], filters={"parent": v.name}) for attr in v.attributes: @@ -530,7 +528,7 @@ class Item(WebsiteGenerator): warehouse += [d.get("warehouse")] else: frappe.throw(_("Row {0}: An Reorder entry already exists for this warehouse {1}") - .format(d.idx, d.warehouse), DuplicateReorderRows) + .format(d.idx, d.warehouse), DuplicateReorderRows) if d.warehouse_reorder_level and not d.warehouse_reorder_qty: frappe.throw(_("Row #{0}: Please set reorder quantity").format(d.idx)) @@ -550,7 +548,7 @@ class Item(WebsiteGenerator): def update_item_price(self): frappe.db.sql("""update `tabItem Price` set item_name=%s, item_description=%s, brand=%s where item_code=%s""", - (self.item_name, self.description, self.brand, self.name)) + (self.item_name, self.description, self.brand, self.name)) def on_trash(self): super(Item, self).on_trash() @@ -572,7 +570,7 @@ class Item(WebsiteGenerator): new_properties = [cstr(d) for d in frappe.db.get_value("Item", new_name, field_list)] if new_properties != [cstr(self.get(fld)) for fld in field_list]: frappe.throw(_("To merge, following properties must be same for both items") - + ": \n" + ", ".join([self.meta.get_label(fld) for fld in field_list])) + + ": \n" + ", ".join([self.meta.get_label(fld) for fld in field_list])) def after_rename(self, old_name, new_name, merge): if self.route: @@ -595,7 +593,7 @@ class Item(WebsiteGenerator): item_wise_tax_detail.pop(old_name) frappe.db.set_value(dt, d.name, "item_wise_tax_detail", - json.dumps(item_wise_tax_detail), update_modified=False) + json.dumps(item_wise_tax_detail), update_modified=False) def set_last_purchase_rate(self, new_name): last_purchase_rate = get_last_purchase_details(new_name).get("base_rate", 0) @@ -623,7 +621,7 @@ class Item(WebsiteGenerator): self.set("website_specifications", []) if self.item_group: for label, desc in frappe.db.get_values("Item Website Specification", - {"parent": self.item_group}, ["label", "description"]): + {"parent": self.item_group}, ["label", "description"]): row = self.append("website_specifications") row.label = label row.description = desc @@ -697,7 +695,7 @@ class Item(WebsiteGenerator): def update_variants(self): if self.flags.dont_update_variants or \ - frappe.db.get_single_value('Item Variant Settings', 'do_not_update_variants'): + frappe.db.get_single_value('Item Variant Settings', 'do_not_update_variants'): return if self.has_variants: variants = frappe.db.get_all("Item", fields=["item_code"], filters={"variant_of": self.name}) @@ -726,17 +724,10 @@ class Item(WebsiteGenerator): frappe.throw( _('Cannot change Attributes after stock transaction. Make a new Item and transfer stock to the new Item')) - def validate_asset_exists_for_serialized_asset(self): - if (not self.get("__islocal") and self.asset_exists() and - cint(self.has_serial_no) != cint(frappe.db.get_value('Item', self.name, 'has_serial_no'))): - frappe.throw(_("Asset is already exists against the item {0}, you cannot change the has serial no value") - .format(self.name)) - - def asset_exists(self): - if not hasattr(self, '_asset_created'): - self._asset_created = frappe.db.get_all("Asset", - filters={"item_code": self.name, "docstatus": 1}, limit=1) - return self._asset_created + def validate_variant_based_on_change(self): + if not self.is_new() and (self.variant_of or (self.has_variants and frappe.get_all("Item", {"variant_of": self.name}))): + if self.variant_based_on != frappe.db.get_value("Item", self.name, "variant_based_on"): + frappe.throw(_("Variant Based On cannot be changed")) def validate_uom(self): if not self.get("__islocal"): @@ -748,7 +739,7 @@ class Item(WebsiteGenerator): template_uom = frappe.db.get_value("Item", self.variant_of, "stock_uom") if template_uom != self.stock_uom: frappe.throw(_("Default Unit of Measure for Variant '{0}' must be same as in Template '{1}'") - .format(self.stock_uom, template_uom)) + .format(self.stock_uom, template_uom)) def validate_uom_conversion_factor(self): if self.uoms: @@ -758,7 +749,13 @@ class Item(WebsiteGenerator): d.conversion_factor = value def validate_attributes(self): - if (self.has_variants or self.variant_of) and self.variant_based_on == 'Item Attribute': + if not (self.has_variants or self.variant_of): + return + + if not self.variant_based_on: + self.variant_based_on = 'Item Attribute' + + if self.variant_based_on == 'Item Attribute': attributes = [] if not self.attributes: frappe.throw(_("Attribute table is mandatory")) @@ -780,10 +777,15 @@ class Item(WebsiteGenerator): variant = get_variant(self.variant_of, args, self.name) if variant: frappe.throw(_("Item variant {0} exists with same attributes") - .format(variant), ItemVariantExistsError) + .format(variant), ItemVariantExistsError) validate_item_variant_attributes(self, args) + def validate_stock_for_has_batch_and_has_serial(self): + if self.stock_ledger_created(): + for value in ["has_batch_no", "has_serial_no"]: + if frappe.db.get_value("Item", self.name, value) != self.get_value(value): + frappe.throw(_("Cannot change {0} as Stock Transaction for Item {1} exist.".format(value, self.name))) def get_timeline_data(doctype, name): '''returns timeline data based on stock ledger entry''' @@ -863,18 +865,18 @@ def get_last_purchase_details(item_code, doc_name=None, conversion_rate=1.0): limit 1""", (item_code, cstr(doc_name)), as_dict=1) purchase_order_date = getdate(last_purchase_order and last_purchase_order[0].transaction_date - or "1900-01-01") + or "1900-01-01") purchase_receipt_date = getdate(last_purchase_receipt and - last_purchase_receipt[0].posting_date or "1900-01-01") + last_purchase_receipt[0].posting_date or "1900-01-01") if (purchase_order_date > purchase_receipt_date) or \ - (last_purchase_order and not last_purchase_receipt): + (last_purchase_order and not last_purchase_receipt): # use purchase order last_purchase = last_purchase_order[0] purchase_date = purchase_order_date elif (purchase_receipt_date > purchase_order_date) or \ - (last_purchase_receipt and not last_purchase_order): + (last_purchase_receipt and not last_purchase_order): # use purchase receipt last_purchase = last_purchase_receipt[0] purchase_date = purchase_receipt_date @@ -904,7 +906,7 @@ def invalidate_cache_for_item(doc): invalidate_cache_for(doc, doc.item_group) website_item_groups = list(set((doc.get("old_website_item_groups") or []) - + [d.item_group for d in doc.get({"doctype": "Website Item Group"}) if d.item_group])) + + [d.item_group for d in doc.get({"doctype": "Website Item Group"}) if d.item_group])) for item_group in website_item_groups: invalidate_cache_for(doc, item_group) @@ -919,7 +921,7 @@ def check_stock_uom_with_bin(item, stock_uom): matched = True ref_uom = frappe.db.get_value("Stock Ledger Entry", - {"item_code": item}, "stock_uom") + {"item_code": item}, "stock_uom") if ref_uom: if cstr(ref_uom) != cstr(stock_uom): @@ -928,7 +930,7 @@ def check_stock_uom_with_bin(item, stock_uom): bin_list = frappe.db.sql("select * from tabBin where item_code=%s", item, as_dict=1) for bin in bin_list: if (bin.reserved_qty > 0 or bin.ordered_qty > 0 or bin.indented_qty > 0 - or bin.planned_qty > 0) and cstr(bin.stock_uom) != cstr(stock_uom): + or bin.planned_qty > 0) and cstr(bin.stock_uom) != cstr(stock_uom): matched = False break @@ -1005,4 +1007,4 @@ def update_variants(variants, template, publish_progress=True): variant.save() count+=1 if publish_progress: - frappe.publish_progress(count*100/len(variants), title = _("Updating Variants...")) \ No newline at end of file + frappe.publish_progress(count*100/len(variants), title = _("Updating Variants...")) diff --git a/erpnext/stock/doctype/item/test_item.py b/erpnext/stock/doctype/item/test_item.py index d02559ebcb1..ac499e0965e 100644 --- a/erpnext/stock/doctype/item/test_item.py +++ b/erpnext/stock/doctype/item/test_item.py @@ -17,7 +17,7 @@ from erpnext.stock.get_item_details import get_item_details from six import iteritems test_ignore = ["BOM"] -test_dependencies = ["Warehouse", "Item Group"] +test_dependencies = ["Warehouse", "Item Group", "Brand"] def make_item(item_code, properties=None): if frappe.db.exists("Item", item_code): @@ -393,3 +393,6 @@ def create_item(item_code, is_stock_item=None, valuation_rate=0, warehouse=None, "company": "_Test Company" }) item.save() + else: + item = frappe.get_doc("Item", item_code) + return item diff --git a/erpnext/stock/doctype/item_attribute/test_records.json b/erpnext/stock/doctype/item_attribute/test_records.json index 0208c176d32..d346979496f 100644 --- a/erpnext/stock/doctype/item_attribute/test_records.json +++ b/erpnext/stock/doctype/item_attribute/test_records.json @@ -6,7 +6,8 @@ "item_attribute_values": [ {"attribute_value": "Small", "abbr": "S"}, {"attribute_value": "Medium", "abbr": "M"}, - {"attribute_value": "Large", "abbr": "L"} + {"attribute_value": "Large", "abbr": "L"}, + {"attribute_value": "Extra Small", "abbr": "XSL"} ] }, { diff --git a/erpnext/stock/doctype/item_price/test_item_price.py b/erpnext/stock/doctype/item_price/test_item_price.py index 455dff4e154..3782f540cf2 100644 --- a/erpnext/stock/doctype/item_price/test_item_price.py +++ b/erpnext/stock/doctype/item_price/test_item_price.py @@ -11,7 +11,7 @@ from erpnext.stock.doctype.item_price.item_price import ItemPriceDuplicateItem class TestItemPrice(unittest.TestCase): def setUp(self): - frappe.db.sql("delete from `tabItem Price`") + frappe.db.sql("delete from `tabItem Price`") make_test_records_for_doctype("Item Price", force=True) def test_duplicate_item(self): diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py index f006d00176e..ed7f2ca4323 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py @@ -13,7 +13,7 @@ from erpnext.controllers.buying_controller import BuyingController from erpnext.accounts.utils import get_account_currency from frappe.desk.notifications import clear_doctype_notifications from erpnext.buying.utils import check_for_closed_status -from erpnext.assets.doctype.asset.asset import get_asset_account +from erpnext.assets.doctype.asset.asset import get_asset_account, is_cwip_accounting_disabled from six import iteritems form_grid_templates = { @@ -125,7 +125,7 @@ class PurchaseReceipt(BuyingController): else: self.status = "Completed" - + # Updating stock ledger should always be called after updating prevdoc status, # because updating ordered qty, reserved_qty_for_subcontract in bin # depends upon updated ordered qty in PO @@ -258,7 +258,8 @@ class PurchaseReceipt(BuyingController): d.rejected_warehouse not in warehouse_with_no_account: warehouse_with_no_account.append(d.warehouse) - self.get_asset_gl_entry(gl_entries) + if not is_cwip_accounting_disabled(): + self.get_asset_gl_entry(gl_entries) # Cost center-wise amount breakup for other charges included for valuation valuation_tax = {} for tax in self.get("taxes"): @@ -311,7 +312,7 @@ class PurchaseReceipt(BuyingController): "\n".join(warehouse_with_no_account)) return process_gl_map(gl_entries) - + def get_asset_gl_entry(self, gl_entries): for d in self.get("items"): if d.is_fixed_asset: @@ -405,6 +406,11 @@ def update_billed_amount_based_on_po(po_detail, update_modified=True): @frappe.whitelist() def make_purchase_invoice(source_name, target_doc=None): from frappe.model.mapper import get_mapped_doc + doc = frappe.get_doc('Purchase Receipt', source_name) + purchase_orders = [d.purchase_order for d in doc.items] + returned_qty_map_against_po = get_returned_qty_map_against_po(purchase_orders) + returned_qty_map_against_pr = get_returned_qty_map_against_pr(source_name) + invoiced_qty_map = get_invoiced_qty_map(source_name) def set_missing_values(source, target): @@ -417,7 +423,23 @@ def make_purchase_invoice(source_name, target_doc=None): doc.run_method("calculate_taxes_and_totals") def update_item(source_doc, target_doc, source_parent): - target_doc.qty = source_doc.qty - invoiced_qty_map.get(source_doc.name, 0) + target_doc.qty, returned_qty = get_pending_qty(source_doc) + if not source_doc.purchase_order_item: + returned_qty_map_against_pr[source_doc.item_code] = returned_qty + + def get_pending_qty(item_row): + pending_qty = item_row.qty - invoiced_qty_map.get(item_row.name, 0) \ + - returned_qty_map_against_po.get(item_row.purchase_order_item, 0) + returned_qty = flt(returned_qty_map_against_pr.get(item_row.item_code, 0)) + if not item_row.purchase_order_item: + if returned_qty >= pending_qty: + pending_qty = 0 + returned_qty -= pending_qty + else: + pending_qty -= returned_qty + returned_qty = 0 + return pending_qty, returned_qty + doclist = get_mapped_doc("Purchase Receipt", source_name, { "Purchase Receipt": { @@ -440,7 +462,7 @@ def make_purchase_invoice(source_name, target_doc=None): "asset": "asset", }, "postprocess": update_item, - "filter": lambda d: abs(d.qty) - abs(invoiced_qty_map.get(d.name, 0))<=0 + "filter": lambda d: get_pending_qty(d)[0]<=0 }, "Purchase Taxes and Charges": { "doctype": "Purchase Taxes and Charges", @@ -462,6 +484,31 @@ def get_invoiced_qty_map(purchase_receipt): return invoiced_qty_map +def get_returned_qty_map_against_po(purchase_orders): + """returns a map: {so_detail: returned_qty}""" + returned_qty_map = {} + + for name, returned_qty in frappe.get_all('Purchase Order Item', fields = ["name", "returned_qty"], + filters = {'parent': ('in', purchase_orders), 'docstatus': 1}, as_list=1): + if not returned_qty_map.get(name): + returned_qty_map[name] = 0 + returned_qty_map[name] += returned_qty + + return returned_qty_map + +def get_returned_qty_map_against_pr(purchase_receipt): + """returns a map: {so_detail: returned_qty}""" + returned_qty_map = frappe._dict(frappe.db.sql("""select pr_item.item_code, sum(abs(pr_item.qty)) as qty + from `tabPurchase Receipt Item` pr_item, `tabPurchase Receipt` pr + where pr.name = pr_item.parent + and pr.docstatus = 1 + and pr.is_return = 1 + and pr.return_against = %s + group by pr_item.item_code + """, purchase_receipt)) + + return returned_qty_map + @frappe.whitelist() def make_purchase_return(source_name, target_doc=None): from erpnext.controllers.sales_and_purchase_return import make_return_doc diff --git a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py index 472083b5a11..c5ae838c8f0 100644 --- a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py @@ -404,6 +404,44 @@ class TestPurchaseReceipt(unittest.TestCase): set_perpetual_inventory(0, pr.company) + def test_make_purchase_invoice_from_pr_for_returned_qty(self): + from erpnext.buying.doctype.purchase_order.test_purchase_order import create_purchase_order, create_pr_against_po + + po = create_purchase_order() + pr = create_pr_against_po(po.name) + + pr1 = make_purchase_receipt(is_return=1, return_against=pr.name, qty=-1, do_not_submit=True) + pr1.items[0].purchase_order = po.name + pr1.items[0].purchase_order_item = po.items[0].name + pr1.submit() + + pi = make_purchase_invoice(pr.name) + self.assertEquals(pi.items[0].qty, 3) + + def test_make_purchase_invoice_from_dn_with_returned_qty_against_dn(self): + pr1 = make_purchase_receipt(qty=8, do_not_submit=True) + pr1.append("items", { + "item_code": "_Test Item", + "warehouse": "_Test Warehouse - _TC", + "qty": 1, + "received_qty": 1, + "rate": 100, + "conversion_factor": 1.0, + }) + pr1.submit() + + pi1 = make_purchase_invoice(pr1.name) + pi1.items[0].qty = 4 + pi1.items.pop(1) + pi1.save() + pi1.submit() + + make_purchase_receipt(is_return=1, return_against=pr1.name, qty=-2) + + pi2 = make_purchase_invoice(pr1.name) + self.assertEquals(pi2.items[0].qty, 2) + self.assertEquals(pi2.items[1].qty, 1) + def get_gl_entries(voucher_type, voucher_no): return frappe.db.sql("""select account, debit, credit, cost_center from `tabGL Entry` where voucher_type=%s and voucher_no=%s diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index 3a5253019af..dc9c4fc3fe8 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -802,7 +802,7 @@ class StockEntry(StockController): # item dict = { item_code: {qty, description, stock_uom} } item_dict = get_bom_items_as_dict(self.bom_no, self.company, qty=qty, - fetch_exploded = self.use_multi_level_bom) + fetch_exploded = self.use_multi_level_bom, fetch_qty_in_stock_uom=False) used_alternative_items = get_used_alternative_items(work_order = self.work_order) for item in itervalues(item_dict): @@ -1031,7 +1031,7 @@ class StockEntry(StockController): se_child.item_code = item_dict[d].get('item_code') or cstr(d) se_child.item_name = item_dict[d]["item_name"] se_child.description = item_dict[d]["description"] - se_child.uom = stock_uom + se_child.uom = item_dict[d]["uom"] if item_dict[d].get("uom") else stock_uom se_child.stock_uom = stock_uom se_child.qty = flt(item_dict[d]["qty"], se_child.precision("qty")) se_child.expense_account = item_dict[d].get("expense_account") or expense_account @@ -1049,8 +1049,9 @@ class StockEntry(StockController): se_child.t_warehouse = self.to_warehouse # in stock uom - se_child.transfer_qty = flt(item_dict[d]["qty"], se_child.precision("qty")) - se_child.conversion_factor = 1.00 + se_child.conversion_factor = flt(item_dict[d].get("conversion_factor")) or 1 + se_child.transfer_qty = flt(item_dict[d]["qty"]*se_child.conversion_factor, se_child.precision("qty")) + # to be assigned for finished item se_child.bom_no = bom_no diff --git a/erpnext/stock/doctype/warehouse/warehouse.json b/erpnext/stock/doctype/warehouse/warehouse.json index 0d60a5ca384..63e374f6d78 100644 --- a/erpnext/stock/doctype/warehouse/warehouse.json +++ b/erpnext/stock/doctype/warehouse/warehouse.json @@ -51,6 +51,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "description": "If blank, parent Warehouse Account or company default will be considered", "fieldname": "warehouse_name", "fieldtype": "Data", "hidden": 0, @@ -870,7 +871,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2018-08-29 06:26:48.647225", + "modified": "2018-08-29 06:26:49.647225", "modified_by": "Administrator", "module": "Stock", "name": "Warehouse", diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py index 74f35953e2a..8b81972b4d1 100644 --- a/erpnext/stock/get_item_details.py +++ b/erpnext/stock/get_item_details.py @@ -490,7 +490,7 @@ def get_price_list_rate_for(args, item_code): price_list_rate = get_item_price(item_price_args, item_code) if price_list_rate: desired_qty = args.get("qty") - if check_packing_list(price_list_rate[0][0], desired_qty, item_code): + if desired_qty and check_packing_list(price_list_rate[0][0], desired_qty, item_code): item_price_data = price_list_rate else: for field in ["customer", "supplier", "min_qty"]: @@ -521,12 +521,15 @@ def check_packing_list(price_list_rate_name, desired_qty, item_code): :param qty: Derised Qt """ + flag = True item_price = frappe.get_doc("Item Price", price_list_rate_name) - if desired_qty and item_price.packing_unit: + if item_price.packing_unit: packing_increment = desired_qty % item_price.packing_unit - if packing_increment == 0: - return True + if packing_increment != 0: + flag = False + + return flag def validate_price_list(args): if args.get("price_list"): @@ -603,28 +606,39 @@ def get_pos_profile_item_details(company, args, pos_profile=None, update_data=Fa @frappe.whitelist() def get_pos_profile(company, pos_profile=None, user=None): - if pos_profile: - return frappe.get_cached_doc('POS Profile', pos_profile) + if pos_profile: return frappe.get_cached_doc('POS Profile', pos_profile) if not user: user = frappe.session['user'] + condition = "pfu.user = %(user)s AND pfu.default=1" + if user and company: + condition = "pfu.user = %(user)s AND pf.company = %(company)s AND pfu.default=1" + pos_profile = frappe.db.sql("""SELECT pf.* FROM `tabPOS Profile` pf LEFT JOIN `tabPOS Profile User` pfu ON pf.name = pfu.parent WHERE - ( - (pfu.user = %(user)s AND pf.company = %(company)s AND pfu.default=1) - OR (pfu.user = %(user)s AND pfu.default=1) - OR (ifnull(pfu.user, '') = '' AND pf.company = %(company)s) - ) AND pf.disabled = 0 - """, { + {cond} AND pf.disabled = 0 + """.format(cond = condition), { 'user': user, 'company': company }, as_dict=1) + if not pos_profile and company: + pos_profile = frappe.db.sql("""SELECT pf.* + FROM + `tabPOS Profile` pf LEFT JOIN `tabPOS Profile User` pfu + ON + pf.name = pfu.parent + WHERE + pf.company = %(company)s AND pf.disabled = 0 + """, { + 'company': company + }, as_dict=1) + return pos_profile and pos_profile[0] or None def get_serial_nos_by_fifo(args, sales_order=None): diff --git a/erpnext/stock/report/total_stock_summary/total_stock_summary.js b/erpnext/stock/report/total_stock_summary/total_stock_summary.js index 223a603004c..b7461c485f6 100644 --- a/erpnext/stock/report/total_stock_summary/total_stock_summary.js +++ b/erpnext/stock/report/total_stock_summary/total_stock_summary.js @@ -18,7 +18,9 @@ frappe.query_reports["Total Stock Summary"] = { "label": __("Company"), "fieldtype": "Link", "width": "80", - "options": "Company" + "options": "Company", + "default": frappe.defaults.get_user_default("Company"), + "reqd": 1 }, ] } diff --git a/erpnext/templates/pages/cart.html b/erpnext/templates/pages/cart.html index fb0c05fcddb..04d737f0557 100644 --- a/erpnext/templates/pages/cart.html +++ b/erpnext/templates/pages/cart.html @@ -60,7 +60,7 @@ {{doc.terms}}
    {% endif %} diff --git a/erpnext/templates/pages/regional/india/update-gstin.html b/erpnext/templates/pages/regional/india/update-gstin.html index 3d9ab5d1253..d738fb4993e 100644 --- a/erpnext/templates/pages/regional/india/update-gstin.html +++ b/erpnext/templates/pages/regional/india/update-gstin.html @@ -32,7 +32,7 @@

    Please update your GSTIN for us to issue correct tax invoice

    - {% for address in party.__onload.addr_list %} + {% for address in party.get_onload('addr_list') %}
    {{ address.display }}