diff --git a/erpnext/accounts/doctype/account/account.json b/erpnext/accounts/doctype/account/account.json index af252e61911..d2659d429b0 100644 --- a/erpnext/accounts/doctype/account/account.json +++ b/erpnext/accounts/doctype/account/account.json @@ -34,11 +34,15 @@ { "fieldname": "properties", "fieldtype": "Section Break", - "oldfieldtype": "Section Break" + "oldfieldtype": "Section Break", + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "column_break0", "fieldtype": "Column Break", + "show_days": 1, + "show_seconds": 1, "width": "50%" }, { @@ -49,7 +53,9 @@ "no_copy": 1, "oldfieldname": "account_name", "oldfieldtype": "Data", - "reqd": 1 + "reqd": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "account_number", @@ -57,13 +63,17 @@ "in_list_view": 1, "in_standard_filter": 1, "label": "Account Number", - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "default": "0", "fieldname": "is_group", "fieldtype": "Check", - "label": "Is Group" + "label": "Is Group", + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "company", @@ -75,7 +85,9 @@ "options": "Company", "read_only": 1, "remember_last_selected_value": 1, - "reqd": 1 + "reqd": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "root_type", @@ -83,7 +95,9 @@ "in_standard_filter": 1, "label": "Root Type", "options": "\nAsset\nLiability\nIncome\nExpense\nEquity", - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "report_type", @@ -91,24 +105,32 @@ "in_standard_filter": 1, "label": "Report Type", "options": "\nBalance Sheet\nProfit and Loss", - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "depends_on": "eval:doc.is_group==0", "fieldname": "account_currency", "fieldtype": "Link", "label": "Currency", - "options": "Currency" + "options": "Currency", + "show_days": 1, + "show_seconds": 1 }, { "default": "0", "fieldname": "inter_company_account", "fieldtype": "Check", - "label": "Inter Company Account" + "label": "Inter Company Account", + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "column_break1", "fieldtype": "Column Break", + "show_days": 1, + "show_seconds": 1, "width": "50%" }, { @@ -120,7 +142,9 @@ "oldfieldtype": "Link", "options": "Account", "reqd": 1, - "search_index": 1 + "search_index": 1, + "show_days": 1, + "show_seconds": 1 }, { "description": "Setting Account Type helps in selecting this Account in transactions.", @@ -130,7 +154,9 @@ "label": "Account Type", "oldfieldname": "account_type", "oldfieldtype": "Select", - "options": "\nAccumulated Depreciation\nAsset Received But Not Billed\nBank\nCash\nChargeable\nCapital Work in Progress\nCost of Goods Sold\nDepreciation\nEquity\nExpense Account\nExpenses Included In Asset Valuation\nExpenses Included In Valuation\nFixed Asset\nIncome Account\nPayable\nReceivable\nRound Off\nStock\nStock Adjustment\nStock Received But Not Billed\nTax\nTemporary" + "options": "\nAccumulated Depreciation\nAsset Received But Not Billed\nBank\nCash\nChargeable\nCapital Work in Progress\nCost of Goods Sold\nDepreciation\nEquity\nExpense Account\nExpenses Included In Asset Valuation\nExpenses Included In Valuation\nFixed Asset\nIncome Account\nPayable\nReceivable\nRound Off\nStock\nStock Adjustment\nStock Received But Not Billed\nService Received But Not Billed\nTax\nTemporary", + "show_days": 1, + "show_seconds": 1 }, { "description": "Rate at which this tax is applied", @@ -138,7 +164,9 @@ "fieldtype": "Float", "label": "Rate", "oldfieldname": "tax_rate", - "oldfieldtype": "Currency" + "oldfieldtype": "Currency", + "show_days": 1, + "show_seconds": 1 }, { "description": "If the account is frozen, entries are allowed to restricted users.", @@ -147,13 +175,17 @@ "label": "Frozen", "oldfieldname": "freeze_account", "oldfieldtype": "Select", - "options": "No\nYes" + "options": "No\nYes", + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "balance_must_be", "fieldtype": "Select", "label": "Balance must be", - "options": "\nDebit\nCredit" + "options": "\nDebit\nCredit", + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "lft", @@ -162,7 +194,9 @@ "label": "Lft", "print_hide": 1, "read_only": 1, - "search_index": 1 + "search_index": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "rgt", @@ -171,7 +205,9 @@ "label": "Rgt", "print_hide": 1, "read_only": 1, - "search_index": 1 + "search_index": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "old_parent", @@ -179,27 +215,33 @@ "hidden": 1, "label": "Old Parent", "print_hide": 1, - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "default": "0", "depends_on": "eval:(doc.report_type == 'Profit and Loss' && !doc.is_group)", "fieldname": "include_in_gross", "fieldtype": "Check", - "label": "Include in gross" + "label": "Include in gross", + "show_days": 1, + "show_seconds": 1 }, { "default": "0", "fieldname": "disabled", "fieldtype": "Check", - "label": "Disable" + "label": "Disable", + "show_days": 1, + "show_seconds": 1 } ], "icon": "fa fa-money", "idx": 1, "is_tree": 1, "links": [], - "modified": "2020-03-18 17:57:52.063233", + "modified": "2020-06-11 15:15:54.338622", "modified_by": "Administrator", "module": "Accounts", "name": "Account", diff --git a/erpnext/accounts/doctype/invoice_discounting/invoice_discounting.js b/erpnext/accounts/doctype/invoice_discounting/invoice_discounting.js index 0fab8b70f43..db4f7c423f9 100644 --- a/erpnext/accounts/doctype/invoice_discounting/invoice_discounting.js +++ b/erpnext/accounts/doctype/invoice_discounting/invoice_discounting.js @@ -188,14 +188,15 @@ frappe.ui.form.on('Invoice Discounting', { }, show_general_ledger: (frm) => { - if(frm.doc.docstatus===1) { + if(frm.doc.docstatus > 0) { cur_frm.add_custom_button(__('Accounting Ledger'), function() { frappe.route_options = { voucher_no: frm.doc.name, from_date: frm.doc.posting_date, - to_date: frm.doc.posting_date, + to_date: moment(frm.doc.modified).format('YYYY-MM-DD'), company: frm.doc.company, - group_by: "Group by Voucher (Consolidated)" + group_by: "Group by Voucher (Consolidated)", + show_cancelled_entries: frm.doc.docstatus === 2 }; frappe.set_route("query-report", "General Ledger"); }, __("View")); diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.js b/erpnext/accounts/doctype/journal_entry/journal_entry.js index 5685f839fe8..a09face7918 100644 --- a/erpnext/accounts/doctype/journal_entry/journal_entry.js +++ b/erpnext/accounts/doctype/journal_entry/journal_entry.js @@ -13,15 +13,16 @@ frappe.ui.form.on("Journal Entry", { refresh: function(frm) { erpnext.toggle_naming_series(); - if(frm.doc.docstatus==1) { + if(frm.doc.docstatus > 0) { frm.add_custom_button(__('Ledger'), function() { frappe.route_options = { "voucher_no": frm.doc.name, "from_date": frm.doc.posting_date, - "to_date": frm.doc.posting_date, + "to_date": moment(frm.doc.modified).format('YYYY-MM-DD'), "company": frm.doc.company, "finance_book": frm.doc.finance_book, - "group_by_voucher": 0 + "group_by": '', + "show_cancelled_entries": frm.doc.docstatus === 2 }; frappe.set_route("query-report", "General Ledger"); }, __('View')); diff --git a/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json b/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json index ad0ecc4a0d8..774159d6919 100644 --- a/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json +++ b/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json @@ -280,7 +280,7 @@ "idx": 1, "istable": 1, "links": [], - "modified": "2020-06-18 14:06:54.833738", + "modified": "2020-06-24 14:06:54.833738", "modified_by": "Administrator", "module": "Accounts", "name": "Journal Entry Account", diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.js b/erpnext/accounts/doctype/payment_entry/payment_entry.js index a378a51cdf7..42c9fdeba46 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.js +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.js @@ -172,8 +172,8 @@ frappe.ui.form.on('Payment Entry', { frm.toggle_display("base_paid_amount", frm.doc.paid_from_account_currency != company_currency); frm.toggle_display("base_received_amount", ( - frm.doc.paid_to_account_currency != company_currency - && frm.doc.paid_from_account_currency != frm.doc.paid_to_account_currency + frm.doc.paid_to_account_currency != company_currency + && frm.doc.paid_from_account_currency != frm.doc.paid_to_account_currency && frm.doc.base_paid_amount != frm.doc.base_received_amount )); @@ -234,14 +234,15 @@ frappe.ui.form.on('Payment Entry', { }, show_general_ledger: function(frm) { - if(frm.doc.docstatus==1) { + if(frm.doc.docstatus > 0) { frm.add_custom_button(__('Ledger'), function() { frappe.route_options = { "voucher_no": frm.doc.name, "from_date": frm.doc.posting_date, - "to_date": frm.doc.posting_date, + "to_date": moment(frm.doc.modified).format('YYYY-MM-DD'), "company": frm.doc.company, - group_by: "" + "group_by": "", + "show_cancelled_entries": frm.doc.docstatus === 2 }; frappe.set_route("query-report", "General Ledger"); }, "fa fa-table"); diff --git a/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.js b/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.js index 87e02fef1b1..e923d4ed5e6 100644 --- a/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.js +++ b/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.js @@ -25,9 +25,10 @@ frappe.ui.form.on('Period Closing Voucher', { frappe.route_options = { "voucher_no": frm.doc.name, "from_date": frm.doc.posting_date, - "to_date": frm.doc.posting_date, + "to_date": moment(frm.doc.modified).format('YYYY-MM-DD'), "company": frm.doc.company, - group_by_voucher: 0 + "group_by": "", + "show_cancelled_entries": frm.doc.docstatus === 2 }; frappe.set_route("query-report", "General Ledger"); }, "fa fa-table"); diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py index 870718c22d5..3cd57d403a2 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -587,6 +587,20 @@ class PurchaseInvoice(BuyingController): else: amount = flt(item.base_net_amount + item.item_tax_amount, item.precision("base_net_amount")) + auto_accounting_for_non_stock_items = cint(frappe.db.get_value('Company', self.company, 'enable_perpetual_inventory_for_non_stock_items')) + + if auto_accounting_for_non_stock_items: + service_received_but_not_billed_account = self.get_company_default("service_received_but_not_billed") + + if item.purchase_receipt: + # Post reverse entry for Stock-Received-But-Not-Billed if it is booked in Purchase Receipt + expense_booked_in_pr = frappe.db.get_value('GL Entry', {'is_cancelled': 0, + 'voucher_type': 'Purchase Receipt', 'voucher_no': item.purchase_receipt, 'voucher_detail_no': item.pr_detail, + 'account':service_received_but_not_billed_account}, ['name']) + + if expense_booked_in_pr: + expense_account = service_received_but_not_billed_account + gl_entries.append(self.get_gl_dict({ "account": expense_account, "against": self.supplier, diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py index 2ecabe60f03..9ae5a87e6bc 100644 --- a/erpnext/assets/doctype/asset/asset.py +++ b/erpnext/assets/doctype/asset/asset.py @@ -408,6 +408,8 @@ class Asset(AccountsController): row.expected_value_after_useful_life = asset_value_after_full_schedule def validate_cancellation(self): + if self.status in ("In Maintenance", "Out of Order"): + frappe.throw(_("There are active maintenance or repairs against the asset. You must complete all of them before cancelling the asset.")) if self.status not in ("Submitted", "Partially Depreciated", "Fully Depreciated"): frappe.throw(_("Asset cannot be cancelled, as it is already {0}").format(self.status)) diff --git a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py index dfdb487f9e0..56af4d90279 100644 --- a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py +++ b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py @@ -51,7 +51,7 @@ class RequestforQuotation(BuyingController): def validate_email_id(self, args): if not args.email_id: - frappe.throw(_("Row {0}: For supplier {0} Email Address is required to send email").format(args.idx, args.supplier)) + frappe.throw(_("Row {0}: For Supplier {0}, Email Address is Required to Send Email").format(args.idx, args.supplier)) def on_submit(self): frappe.db.set(self, 'status', 'Submitted') @@ -154,7 +154,7 @@ class RequestforQuotation(BuyingController): sender=sender,attachments = attachments, send_email=True, doctype=self.doctype, name=self.name)["name"] - frappe.msgprint(_("Email sent to supplier {0}").format(data.supplier)) + frappe.msgprint(_("Email Sent to Supplier {0}").format(data.supplier)) def get_attachments(self): attachments = [d.name for d in get_attachments(self.doctype, self.name)] @@ -193,7 +193,7 @@ def send_supplier_emails(rfq_name): def check_portal_enabled(reference_doctype): if not frappe.db.get_value('Portal Menu Item', {'reference_doctype': reference_doctype}, 'enabled'): - frappe.throw(_("Request for Quotation is disabled to access from portal, for more check portal settings.")) + frappe.throw(_("The Access to Request for Quotation From Portal is Disabled. To Allow Access, Enable it in Portal Settings.")) def get_list_context(context=None): from erpnext.controllers.website_list_for_contact import get_list_context @@ -259,7 +259,7 @@ def create_supplier_quotation(doc): sq_doc.flags.ignore_permissions = True sq_doc.run_method("set_missing_values") sq_doc.save() - frappe.msgprint(_("Supplier Quotation {0} created").format(sq_doc.name)) + frappe.msgprint(_("Supplier Quotation {0} Created").format(sq_doc.name)) return sq_doc.name except Exception: return None diff --git a/erpnext/controllers/trends.py b/erpnext/controllers/trends.py index 092baa4018f..9b4b0eb9173 100644 --- a/erpnext/controllers/trends.py +++ b/erpnext/controllers/trends.py @@ -33,7 +33,7 @@ def validate_filters(filters): frappe.throw(_("{0} is mandatory").format(f)) if not frappe.db.exists("Fiscal Year", filters.get("fiscal_year")): - frappe.throw(_("Fiscal Year: {0} does not exists").format(filters.get("fiscal_year"))) + frappe.throw(_("Fiscal Year {0} Does Not Exist").format(filters.get("fiscal_year"))) if filters.get("based_on") == filters.get("group_by"): frappe.throw(_("'Based On' and 'Group By' can not be same")) diff --git a/erpnext/crm/doctype/contract/contract.json b/erpnext/crm/doctype/contract/contract.json index e04ad30ea72..0026e4a02eb 100755 --- a/erpnext/crm/doctype/contract/contract.json +++ b/erpnext/crm/doctype/contract/contract.json @@ -29,6 +29,9 @@ "requires_fulfilment", "fulfilment_deadline", "fulfilment_terms", + "authorised_by_section", + "signee_company", + "signed_by_company", "sb_references", "document_type", "cb_links", @@ -223,10 +226,28 @@ "options": "Contract", "print_hide": 1, "read_only": 1 + }, + { + "fieldname": "signee_company", + "fieldtype": "Signature", + "label": "Signee (Company)" + }, + { + "fieldname": "signed_by_company", + "fieldtype": "Link", + "label": "Signed By (Company)", + "options": "User", + "read_only": 1 + }, + { + "fieldname": "authorised_by_section", + "fieldtype": "Section Break", + "label": "Authorised By" } ], "is_submittable": 1, - "modified": "2019-09-30 00:56:41.559681", + "links": [], + "modified": "2020-03-30 06:56:07.257932", "modified_by": "Administrator", "module": "CRM", "name": "Contract", diff --git a/erpnext/crm/doctype/contract/contract.py b/erpnext/crm/doctype/contract/contract.py index 18444cc7e6e..c39397bf4b4 100644 --- a/erpnext/crm/doctype/contract/contract.py +++ b/erpnext/crm/doctype/contract/contract.py @@ -29,6 +29,9 @@ class Contract(Document): self.update_contract_status() self.update_fulfilment_status() + def before_submit(self): + self.signed_by_company = frappe.session.user + def before_update_after_submit(self): self.update_contract_status() self.update_fulfilment_status() diff --git a/erpnext/crm/doctype/contract_template/contract_template.json b/erpnext/crm/doctype/contract_template/contract_template.json index b883ce20c9b..ef9974f8636 100644 --- a/erpnext/crm/doctype/contract_template/contract_template.json +++ b/erpnext/crm/doctype/contract_template/contract_template.json @@ -1,306 +1,106 @@ { - "allow_copy": 0, - "allow_guest_to_view": 0, - "allow_import": 0, - "allow_rename": 0, - "autoname": "field:title", - "beta": 0, - "creation": "2018-04-16 06:44:48.791312", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "", - "editable_grid": 1, - "engine": "InnoDB", + "actions": [], + "allow_rename": 1, + "autoname": "field:title", + "creation": "2018-04-16 06:44:48.791312", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "title", + "contract_terms", + "sb_fulfilment", + "requires_fulfilment", + "fulfilment_terms" + ], "fields": [ { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "title", - "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": "Title", - "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, - "unique": 0 - }, + "fieldname": "title", + "fieldtype": "Data", + "label": "Title", + "unique": 1 + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "sb_terms", - "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": "", - "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, - "unique": 0 - }, + "fieldname": "contract_terms", + "fieldtype": "Text Editor", + "label": "Contract Terms and Conditions", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "contract_terms", - "fieldtype": "Text Editor", - "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": "Contract Terms and Conditions", - "length": 0, - "no_copy": 0, - "options": "", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, + "fieldname": "sb_fulfilment", + "fieldtype": "Section Break" + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "sb_fulfilment", - "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": "", - "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, - "unique": 0 - }, + "default": "0", + "fieldname": "requires_fulfilment", + "fieldtype": "Check", + "label": "Requires Fulfilment" + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "requires_fulfilment", - "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": "Requires Fulfilment", - "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, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:doc.requires_fulfilment==1", - "fieldname": "fulfilment_terms", - "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": "Fulfilment Terms and Conditions", - "length": 0, - "no_copy": 0, - "options": "Contract Template Fulfilment Terms", - "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 + "depends_on": "eval:doc.requires_fulfilment==1", + "fieldname": "fulfilment_terms", + "fieldtype": "Table", + "label": "Fulfilment Terms and Conditions", + "options": "Contract Template Fulfilment Terms" } - ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "idx": 0, - "image_view": 0, - "in_create": 0, - "is_submittable": 0, - "issingle": 0, - "istable": 0, - "max_attachments": 0, - "modified": "2018-04-17 07:36:05.217599", - "modified_by": "Administrator", - "module": "CRM", - "name": "Contract Template", - "name_case": "", - "owner": "Administrator", + ], + "links": [], + "modified": "2020-06-03 00:24:58.179816", + "modified_by": "Administrator", + "module": "CRM", + "name": "Contract Template", + "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": 0, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "share": 1, "write": 1 - }, + }, { - "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": "Sales Manager", - "set_user_permissions": 0, - "share": 1, - "submit": 0, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Sales Manager", + "share": 1, "write": 1 - }, + }, { - "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": "Purchase Manager", - "set_user_permissions": 0, - "share": 1, - "submit": 0, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Purchase Manager", + "share": 1, "write": 1 - }, + }, { - "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": "HR Manager", - "set_user_permissions": 0, - "share": 1, - "submit": 0, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "HR Manager", + "share": 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 + ], + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 1 } \ No newline at end of file diff --git a/erpnext/education/doctype/fees/fees.js b/erpnext/education/doctype/fees/fees.js index 17ef44954b1..867866fbf14 100644 --- a/erpnext/education/doctype/fees/fees.js +++ b/erpnext/education/doctype/fees/fees.js @@ -55,14 +55,15 @@ frappe.ui.form.on("Fees", { frm.set_df_property('posting_date', 'read_only', 1); frm.set_df_property('posting_time', 'read_only', 1); } - if(frm.doc.docstatus===1) { + if(frm.doc.docstatus > 0) { frm.add_custom_button(__('Accounting Ledger'), function() { frappe.route_options = { voucher_no: frm.doc.name, from_date: frm.doc.posting_date, - to_date: frm.doc.posting_date, + to_date: moment(frm.doc.modified).format('YYYY-MM-DD'), company: frm.doc.company, - group_by_voucher: false + group_by: '', + show_cancelled_entries: frm.doc.docstatus === 2 }; frappe.set_route("query-report", "General Ledger"); }, __("View")); diff --git a/erpnext/education/report/absent_student_report/absent_student_report.json b/erpnext/education/report/absent_student_report/absent_student_report.json index 0d5eebabf8c..92ad860cc65 100644 --- a/erpnext/education/report/absent_student_report/absent_student_report.json +++ b/erpnext/education/report/absent_student_report/absent_student_report.json @@ -1,20 +1,21 @@ { - "add_total_row": 0, - "apply_user_permissions": 1, - "creation": "2013-05-13 14:04:03", - "disabled": 0, - "docstatus": 0, - "doctype": "Report", - "idx": 3, - "is_standard": "Yes", - "modified": "2017-11-10 19:42:36.457449", - "modified_by": "Administrator", - "module": "Education", - "name": "Absent Student Report", - "owner": "Administrator", - "ref_doctype": "Student Attendance", - "report_name": "Absent Student Report", - "report_type": "Script Report", + "add_total_row": 0, + "creation": "2013-05-13 14:04:03", + "disable_prepared_report": 0, + "disabled": 0, + "docstatus": 0, + "doctype": "Report", + "idx": 3, + "is_standard": "Yes", + "modified": "2020-06-24 17:16:40.251116", + "modified_by": "Administrator", + "module": "Education", + "name": "Absent Student Report", + "owner": "Administrator", + "prepared_report": 0, + "ref_doctype": "Student Attendance", + "report_name": "Absent Student Report", + "report_type": "Script Report", "roles": [ { "role": "Academics User" diff --git a/erpnext/education/report/assessment_plan_status/assessment_plan_status.json b/erpnext/education/report/assessment_plan_status/assessment_plan_status.json index 3000bec1f8d..cbca648d572 100644 --- a/erpnext/education/report/assessment_plan_status/assessment_plan_status.json +++ b/erpnext/education/report/assessment_plan_status/assessment_plan_status.json @@ -1,20 +1,21 @@ { - "add_total_row": 0, - "apply_user_permissions": 1, - "creation": "2017-11-09 15:07:30.404428", - "disabled": 0, - "docstatus": 0, - "doctype": "Report", - "idx": 0, - "is_standard": "Yes", - "modified": "2017-11-28 18:35:44.903665", - "modified_by": "Administrator", - "module": "Education", - "name": "Assessment Plan Status", - "owner": "Administrator", - "ref_doctype": "Assessment Plan", - "report_name": "Assessment Plan Status", - "report_type": "Script Report", + "add_total_row": 0, + "creation": "2017-11-09 15:07:30.404428", + "disable_prepared_report": 0, + "disabled": 0, + "docstatus": 0, + "doctype": "Report", + "idx": 0, + "is_standard": "Yes", + "modified": "2020-06-24 17:16:02.027410", + "modified_by": "Administrator", + "module": "Education", + "name": "Assessment Plan Status", + "owner": "Administrator", + "prepared_report": 0, + "ref_doctype": "Assessment Plan", + "report_name": "Assessment Plan Status", + "report_type": "Script Report", "roles": [ { "role": "Academics User" diff --git a/erpnext/education/report/course_wise_assessment_report/course_wise_assessment_report.json b/erpnext/education/report/course_wise_assessment_report/course_wise_assessment_report.json index 61976b4508b..416db9d00f3 100644 --- a/erpnext/education/report/course_wise_assessment_report/course_wise_assessment_report.json +++ b/erpnext/education/report/course_wise_assessment_report/course_wise_assessment_report.json @@ -1,24 +1,26 @@ { - "add_total_row": 0, - "apply_user_permissions": 1, - "creation": "2017-05-05 14:46:13.776133", - "disabled": 0, - "docstatus": 0, - "doctype": "Report", - "idx": 0, - "is_standard": "Yes", - "modified": "2018-02-08 15:11:24.904628", - "modified_by": "Administrator", - "module": "Education", - "name": "Course wise Assessment Report", - "owner": "Administrator", - "ref_doctype": "Assessment Result", - "report_name": "Course wise Assessment Report", - "report_type": "Script Report", + "add_total_row": 0, + "creation": "2017-05-05 14:46:13.776133", + "disable_prepared_report": 0, + "disabled": 0, + "docstatus": 0, + "doctype": "Report", + "idx": 0, + "is_standard": "Yes", + "modified": "2020-06-24 17:15:15.477530", + "modified_by": "Administrator", + "module": "Education", + "name": "Course wise Assessment Report", + "owner": "Administrator", + "prepared_report": 0, + "query": "", + "ref_doctype": "Assessment Result", + "report_name": "Course wise Assessment Report", + "report_type": "Script Report", "roles": [ { "role": "Instructor" - }, + }, { "role": "Education Manager" } diff --git a/erpnext/education/report/final_assessment_grades/final_assessment_grades.json b/erpnext/education/report/final_assessment_grades/final_assessment_grades.json index 4d444b46ce9..6a234947688 100644 --- a/erpnext/education/report/final_assessment_grades/final_assessment_grades.json +++ b/erpnext/education/report/final_assessment_grades/final_assessment_grades.json @@ -1,24 +1,25 @@ { - "add_total_row": 0, - "apply_user_permissions": 1, - "creation": "2018-01-22 17:04:43.412054", - "disabled": 0, - "docstatus": 0, - "doctype": "Report", - "idx": 0, - "is_standard": "Yes", - "modified": "2019-02-08 15:11:35.339434", - "modified_by": "Administrator", - "module": "Education", - "name": "Final Assessment Grades", - "owner": "Administrator", - "ref_doctype": "Assessment Result", - "report_name": "Final Assessment Grades", - "report_type": "Script Report", + "add_total_row": 0, + "creation": "2018-01-22 17:04:43.412054", + "disable_prepared_report": 0, + "disabled": 0, + "docstatus": 0, + "doctype": "Report", + "idx": 0, + "is_standard": "Yes", + "modified": "2020-06-24 17:13:35.373756", + "modified_by": "Administrator", + "module": "Education", + "name": "Final Assessment Grades", + "owner": "Administrator", + "prepared_report": 0, + "ref_doctype": "Assessment Result", + "report_name": "Final Assessment Grades", + "report_type": "Script Report", "roles": [ { "role": "Instructor" - }, + }, { "role": "Education Manager" } diff --git a/erpnext/education/report/student_and_guardian_contact_details/student_and_guardian_contact_details.json b/erpnext/education/report/student_and_guardian_contact_details/student_and_guardian_contact_details.json index fe7d1586c86..fa9be656810 100644 --- a/erpnext/education/report/student_and_guardian_contact_details/student_and_guardian_contact_details.json +++ b/erpnext/education/report/student_and_guardian_contact_details/student_and_guardian_contact_details.json @@ -1,24 +1,25 @@ { - "add_total_row": 0, - "apply_user_permissions": 1, - "creation": "2017-03-27 17:47:16.831433", - "disabled": 0, - "docstatus": 0, - "doctype": "Report", - "idx": 0, - "is_standard": "Yes", - "modified": "2017-11-10 19:42:30.300729", - "modified_by": "Administrator", - "module": "Education", - "name": "Student and Guardian Contact Details", - "owner": "Administrator", - "ref_doctype": "Program Enrollment", - "report_name": "Student and Guardian Contact Details", - "report_type": "Script Report", + "add_total_row": 0, + "creation": "2017-03-27 17:47:16.831433", + "disable_prepared_report": 0, + "disabled": 0, + "docstatus": 0, + "doctype": "Report", + "idx": 0, + "is_standard": "Yes", + "modified": "2020-06-24 17:16:50.639488", + "modified_by": "Administrator", + "module": "Education", + "name": "Student and Guardian Contact Details", + "owner": "Administrator", + "prepared_report": 0, + "ref_doctype": "Program Enrollment", + "report_name": "Student and Guardian Contact Details", + "report_type": "Script Report", "roles": [ { "role": "Instructor" - }, + }, { "role": "Academics User" } diff --git a/erpnext/education/report/student_batch_wise_attendance/student_batch_wise_attendance.json b/erpnext/education/report/student_batch_wise_attendance/student_batch_wise_attendance.json index eb547b71025..8baf8f9fe0e 100644 --- a/erpnext/education/report/student_batch_wise_attendance/student_batch_wise_attendance.json +++ b/erpnext/education/report/student_batch_wise_attendance/student_batch_wise_attendance.json @@ -1,20 +1,21 @@ { - "add_total_row": 0, - "apply_user_permissions": 1, - "creation": "2016-11-28 22:07:03.859124", - "disabled": 0, - "docstatus": 0, - "doctype": "Report", - "idx": 2, - "is_standard": "Yes", - "modified": "2017-11-10 19:41:12.328346", - "modified_by": "Administrator", - "module": "Education", - "name": "Student Batch-Wise Attendance", - "owner": "Administrator", - "ref_doctype": "Student Attendance", - "report_name": "Student Batch-Wise Attendance", - "report_type": "Script Report", + "add_total_row": 0, + "creation": "2016-11-28 22:07:03.859124", + "disable_prepared_report": 0, + "disabled": 0, + "docstatus": 0, + "doctype": "Report", + "idx": 2, + "is_standard": "Yes", + "modified": "2020-06-24 17:16:59.823709", + "modified_by": "Administrator", + "module": "Education", + "name": "Student Batch-Wise Attendance", + "owner": "Administrator", + "prepared_report": 0, + "ref_doctype": "Student Attendance", + "report_name": "Student Batch-Wise Attendance", + "report_type": "Script Report", "roles": [ { "role": "Academics User" diff --git a/erpnext/education/report/student_fee_collection/student_fee_collection.json b/erpnext/education/report/student_fee_collection/student_fee_collection.json index eb945cfffb8..8deb865ebcd 100644 --- a/erpnext/education/report/student_fee_collection/student_fee_collection.json +++ b/erpnext/education/report/student_fee_collection/student_fee_collection.json @@ -1,21 +1,22 @@ { - "add_total_row": 0, - "creation": "2016-06-22 02:58:41.024538", - "disabled": 0, - "docstatus": 0, - "doctype": "Report", - "idx": 3, - "is_standard": "Yes", - "modified": "2018-12-17 16:46:46.176620", - "modified_by": "Administrator", - "module": "Education", - "name": "Student Fee Collection", - "owner": "Administrator", - "prepared_report": 0, - "query": "SELECT\n student as \"Student:Link/Student:200\",\n student_name as \"Student Name::200\",\n sum(grand_total) - sum(outstanding_amount) as \"Paid Amount:Currency:150\",\n sum(outstanding_amount) as \"Outstanding Amount:Currency:150\",\n sum(grand_total) as \"Grand Total:Currency:150\"\nFROM\n `tabFees` \nGROUP BY\n student", - "ref_doctype": "Fees", - "report_name": "Student Fee Collection", - "report_type": "Query Report", + "add_total_row": 0, + "creation": "2016-06-22 02:58:41.024538", + "disable_prepared_report": 0, + "disabled": 0, + "docstatus": 0, + "doctype": "Report", + "idx": 3, + "is_standard": "Yes", + "modified": "2020-06-24 17:14:39.452551", + "modified_by": "Administrator", + "module": "Education", + "name": "Student Fee Collection", + "owner": "Administrator", + "prepared_report": 0, + "query": "SELECT\n student as \"Student:Link/Student:200\",\n student_name as \"Student Name::200\",\n sum(grand_total) - sum(outstanding_amount) as \"Paid Amount:Currency:150\",\n sum(outstanding_amount) as \"Outstanding Amount:Currency:150\",\n sum(grand_total) as \"Grand Total:Currency:150\"\nFROM\n `tabFees` \nGROUP BY\n student", + "ref_doctype": "Fees", + "report_name": "Student Fee Collection", + "report_type": "Query Report", "roles": [ { "role": "Academics User" diff --git a/erpnext/education/report/student_monthly_attendance_sheet/student_monthly_attendance_sheet.json b/erpnext/education/report/student_monthly_attendance_sheet/student_monthly_attendance_sheet.json index e10f190e1c7..1423d4fee1a 100644 --- a/erpnext/education/report/student_monthly_attendance_sheet/student_monthly_attendance_sheet.json +++ b/erpnext/education/report/student_monthly_attendance_sheet/student_monthly_attendance_sheet.json @@ -1,20 +1,21 @@ { - "add_total_row": 0, - "apply_user_permissions": 1, - "creation": "2013-05-13 14:04:03", - "disabled": 0, - "docstatus": 0, - "doctype": "Report", - "idx": 3, - "is_standard": "Yes", - "modified": "2017-11-10 19:42:43.376658", - "modified_by": "Administrator", - "module": "Education", - "name": "Student Monthly Attendance Sheet", - "owner": "Administrator", - "ref_doctype": "Student Attendance", - "report_name": "Student Monthly Attendance Sheet", - "report_type": "Script Report", + "add_total_row": 0, + "creation": "2013-05-13 14:04:03", + "disable_prepared_report": 0, + "disabled": 0, + "docstatus": 0, + "doctype": "Report", + "idx": 3, + "is_standard": "Yes", + "modified": "2020-06-24 17:16:13.307053", + "modified_by": "Administrator", + "module": "Education", + "name": "Student Monthly Attendance Sheet", + "owner": "Administrator", + "prepared_report": 0, + "ref_doctype": "Student Attendance", + "report_name": "Student Monthly Attendance Sheet", + "report_type": "Script Report", "roles": [ { "role": "Academics User" diff --git a/erpnext/hr/doctype/expense_claim/expense_claim.js b/erpnext/hr/doctype/expense_claim/expense_claim.js index 6bb9af98263..fa63ec2834a 100644 --- a/erpnext/hr/doctype/expense_claim/expense_claim.js +++ b/erpnext/hr/doctype/expense_claim/expense_claim.js @@ -213,12 +213,15 @@ frappe.ui.form.on("Expense Claim", { refresh: function(frm) { frm.trigger("toggle_fields"); - if(frm.doc.docstatus === 1 && frm.doc.approval_status !== "Rejected") { + if(frm.doc.docstatus > 0 && frm.doc.approval_status !== "Rejected") { frm.add_custom_button(__('Accounting Ledger'), function() { frappe.route_options = { voucher_no: frm.doc.name, company: frm.doc.company, - group_by_voucher: false + from_date: frm.doc.posting_date, + to_date: moment(frm.doc.modified).format('YYYY-MM-DD'), + group_by: '', + show_cancelled_entries: frm.doc.docstatus === 2 }; frappe.set_route("query-report", "General Ledger"); }, __("View")); diff --git a/erpnext/loan_management/loan_common.js b/erpnext/loan_management/loan_common.js index 3a47a88cbe7..d9dd415296e 100644 --- a/erpnext/loan_management/loan_common.js +++ b/erpnext/loan_management/loan_common.js @@ -9,12 +9,15 @@ frappe.ui.form.on(cur_frm.doctype, { } if (['Loan Disbursement', 'Loan Repayment', 'Loan Interest Accrual'].includes(frm.doc.doctype) - && frm.doc.docstatus == 1) { + && frm.doc.docstatus > 0) { frm.add_custom_button(__("Accounting Ledger"), function() { frappe.route_options = { voucher_no: frm.doc.name, - company: frm.doc.company + company: frm.doc.company, + from_date: frm.doc.posting_date, + to_date: moment(frm.doc.modified).format('YYYY-MM-DD'), + show_cancelled_entries: frm.doc.docstatus === 2 }; frappe.set_route("query-report", "General Ledger"); diff --git a/erpnext/manufacturing/doctype/production_plan/production_plan.py b/erpnext/manufacturing/doctype/production_plan/production_plan.py index 560286e68af..016ab14d5fd 100644 --- a/erpnext/manufacturing/doctype/production_plan/production_plan.py +++ b/erpnext/manufacturing/doctype/production_plan/production_plan.py @@ -98,11 +98,17 @@ class ProductionPlan(Document): elif self.get_items_from == "Material Request": self.get_mr_items() + def get_so_mr_list(self, field, table): + """Returns a list of Sales Orders or Material Requests from the respective tables""" + so_mr_list = [d.get(field) for d in self.get(table) if d.get(field)] + return so_mr_list + def get_so_items(self): - so_list = [d.sales_order for d in self.sales_orders if d.sales_order] - if not so_list: - msgprint(_("Please enter Sales Orders in the above table")) - return [] + # Check for empty table or empty rows + if not self.get("sales_orders") or not self.get_so_mr_list("sales_order", "sales_orders"): + frappe.throw(_("Please fill the Sales Orders table"), title=_("Sales Orders Required")) + + so_list = self.get_so_mr_list("sales_order", "sales_orders") item_condition = "" if self.item_code: @@ -134,10 +140,11 @@ class ProductionPlan(Document): self.calculate_total_planned_qty() def get_mr_items(self): - mr_list = [d.material_request for d in self.material_requests if d.material_request] - if not mr_list: - msgprint(_("Please enter Material Requests in the above table")) - return [] + # Check for empty table or empty rows + if not self.get("material_requests") or not self.get_so_mr_list("material_request", "material_requests"): + frappe.throw(_("Please fill the Material Requests table"), title=_("Material Requests Required")) + + mr_list = self.get_so_mr_list("material_request", "material_requests") item_condition = "" if self.item_code: @@ -628,16 +635,18 @@ def get_items_for_material_requests(doc, warehouses=None): if warehouse_list: warehouses = list(set(warehouse_list)) - + if doc.get("for_warehouse") and doc.get("for_warehouse") in warehouses: warehouses.remove(doc.get("for_warehouse")) warehouse_list = None doc['mr_items'] = [] - po_items = doc.get('po_items') if doc.get('po_items') else doc.get('items') - if not po_items: - frappe.throw(_("Items are required to pull the raw materials which is associated with it.")) + + po_items = doc.get('po_items') + if not po_items or not [row.get('item_code') for row in po_items if row.get('item_code')]: + frappe.throw(_("Items to Manufacture are required to pull the Raw Materials associated with it."), + title=_("Items Required")) company = doc.get('company') ignore_existing_ordered_qty = doc.get('ignore_existing_ordered_qty') diff --git a/erpnext/portal/product_configurator/utils.py b/erpnext/portal/product_configurator/utils.py index 6b6b8c579be..f8af30a1c30 100644 --- a/erpnext/portal/product_configurator/utils.py +++ b/erpnext/portal/product_configurator/utils.py @@ -239,13 +239,12 @@ def get_next_attribute_and_values(item_code, selected_attributes): if exact_match: data = get_product_info_for_website(exact_match[0]) product_info = data.product_info + product_info["allow_items_not_in_stock"] = cint(data.cart_settings.allow_items_not_in_stock) if not data.cart_settings.show_price: product_info = None else: product_info = None - product_info["allow_items_not_in_stock"] = cint(data.cart_settings.allow_items_not_in_stock) - return { 'next_attribute': next_attribute, 'valid_options_for_attributes': valid_options_for_attributes, diff --git a/erpnext/projects/doctype/timesheet/test_timesheet.py b/erpnext/projects/doctype/timesheet/test_timesheet.py index 03b67b10231..a5ce44dcf24 100644 --- a/erpnext/projects/doctype/timesheet/test_timesheet.py +++ b/erpnext/projects/doctype/timesheet/test_timesheet.py @@ -140,52 +140,6 @@ class TestTimesheet(unittest.TestCase): settings.ignore_employee_time_overlap = initial_setting settings.save() - def test_timesheet_std_working_hours(self): - emp = make_employee("test_employee_6@salary.com") - - company = frappe.get_doc('Company', "_Test Company") - company.standard_working_hours = 8 - company.save() - - timesheet = frappe.new_doc("Timesheet") - timesheet.employee = emp - timesheet.company = '_Test Company' - timesheet.append( - 'time_logs', - { - "activity_type": "_Test Activity Type", - "from_time": now_datetime(), - "to_time": now_datetime() + datetime.timedelta(days= 4) - } - ) - timesheet.save() - - ts = frappe.get_doc('Timesheet', timesheet.name) - self.assertEqual(ts.total_hours, 32) - ts.submit() - ts.cancel() - - company = frappe.get_doc('Company', "_Test Company") - company.standard_working_hours = 0 - company.save() - - timesheet = frappe.new_doc("Timesheet") - timesheet.employee = emp - timesheet.company = '_Test Company' - timesheet.append( - 'time_logs', - { - "activity_type": "_Test Activity Type", - "from_time": now_datetime(), - "to_time": now_datetime() + datetime.timedelta(days= 4) - } - ) - timesheet.save() - - ts = frappe.get_doc('Timesheet', timesheet.name) - self.assertEqual(ts.total_hours, 96) - ts.submit() - ts.cancel() def make_salary_structure_for_timesheet(employee): salary_structure_name = "Timesheet Salary Structure Test" diff --git a/erpnext/projects/doctype/timesheet/timesheet.js b/erpnext/projects/doctype/timesheet/timesheet.js index defc18bf4e9..5de2930c1cd 100644 --- a/erpnext/projects/doctype/timesheet/timesheet.js +++ b/erpnext/projects/doctype/timesheet/timesheet.js @@ -162,19 +162,11 @@ frappe.ui.form.on("Timesheet Detail", { to_time: function(frm, cdt, cdn) { var child = locals[cdt][cdn]; - var time_diff = (moment(child.to_time).diff(moment(child.from_time),"seconds")) / ( 60 * 60 * 24); - var std_working_hours = 0; if(frm._setting_hours) return; var hours = moment(child.to_time).diff(moment(child.from_time), "seconds") / 3600; - std_working_hours = time_diff * frappe.working_hours; - - if (std_working_hours < hours && std_working_hours > 0) { - frappe.model.set_value(cdt, cdn, "hours", std_working_hours); - } else { - frappe.model.set_value(cdt, cdn, "hours", hours); - } + frappe.model.set_value(cdt, cdn, "hours", hours); }, time_logs_add: function(frm) { @@ -236,23 +228,12 @@ var calculate_end_time = function(frm, cdt, cdn) { let d = moment(child.from_time); if(child.hours) { - var time_diff = (moment(child.to_time).diff(moment(child.from_time),"seconds")) / (60 * 60 * 24); - var std_working_hours = 0; - var hours = moment(child.to_time).diff(moment(child.from_time), "seconds") / 3600; - - std_working_hours = time_diff * frappe.working_hours; - - if (std_working_hours < hours && std_working_hours > 0) { - frappe.model.set_value(cdt, cdn, "hours", std_working_hours); - frappe.model.set_value(cdt, cdn, "to_time", d.add(hours, "hours").format(frappe.defaultDatetimeFormat)); - } else { - d.add(child.hours, "hours"); - frm._setting_hours = true; - frappe.model.set_value(cdt, cdn, "to_time", - d.format(frappe.defaultDatetimeFormat)).then(() => { - frm._setting_hours = false; - }); - } + d.add(child.hours, "hours"); + frm._setting_hours = true; + frappe.model.set_value(cdt, cdn, "to_time", + d.format(frappe.defaultDatetimeFormat)).then(() => { + frm._setting_hours = false; + }); } }; diff --git a/erpnext/projects/doctype/timesheet/timesheet.py b/erpnext/projects/doctype/timesheet/timesheet.py index e90821689bd..7fe22bec4b2 100644 --- a/erpnext/projects/doctype/timesheet/timesheet.py +++ b/erpnext/projects/doctype/timesheet/timesheet.py @@ -24,7 +24,6 @@ class Timesheet(Document): self.set_status() self.validate_dates() self.validate_time_logs() - self.calculate_std_hours() self.update_cost() self.calculate_total_amounts() self.calculate_percentage_billed() @@ -91,17 +90,6 @@ class Timesheet(Document): self.start_date = getdate(start_date) self.end_date = getdate(end_date) - def calculate_std_hours(self): - std_working_hours = frappe.get_value("Company", self.company, 'standard_working_hours') - - for time in self.time_logs: - if time.from_time and time.to_time: - if flt(std_working_hours) and date_diff(time.to_time, time.from_time): - time.hours = flt(std_working_hours) * date_diff(time.to_time, time.from_time) - else: - if not time.hours: - time.hours = time_diff_in_hours(time.to_time, time.from_time) - def before_cancel(self): self.set_status() diff --git a/erpnext/public/js/controllers/stock_controller.js b/erpnext/public/js/controllers/stock_controller.js index 2ce49e766b9..87b21b78de8 100644 --- a/erpnext/public/js/controllers/stock_controller.js +++ b/erpnext/public/js/controllers/stock_controller.js @@ -55,8 +55,9 @@ erpnext.stock.StockController = frappe.ui.form.Controller.extend({ frappe.route_options = { voucher_no: me.frm.doc.name, from_date: me.frm.doc.posting_date, - to_date: me.frm.doc.posting_date, - company: me.frm.doc.company + to_date: moment(me.frm.doc.modified).format('YYYY-MM-DD'), + company: me.frm.doc.company, + show_cancelled_entries: me.frm.doc.docstatus === 2 }; frappe.set_route("query-report", "Stock Ledger"); }, __("View")); @@ -71,9 +72,10 @@ erpnext.stock.StockController = frappe.ui.form.Controller.extend({ frappe.route_options = { voucher_no: me.frm.doc.name, from_date: me.frm.doc.posting_date, - to_date: me.frm.doc.posting_date, + to_date: moment(me.frm.doc.modified).format('YYYY-MM-DD'), company: me.frm.doc.company, - group_by: "Group by Voucher (Consolidated)" + group_by: "Group by Voucher (Consolidated)", + show_cancelled_entries: me.frm.doc.docstatus === 2 }; frappe.set_route("query-report", "General Ledger"); }, __("View")); diff --git a/erpnext/selling/report/item_wise_sales_history/item_wise_sales_history.py b/erpnext/selling/report/item_wise_sales_history/item_wise_sales_history.py index bd59be663ad..1bc4657f295 100644 --- a/erpnext/selling/report/item_wise_sales_history/item_wise_sales_history.py +++ b/erpnext/selling/report/item_wise_sales_history/item_wise_sales_history.py @@ -9,6 +9,9 @@ from frappe.utils.nestedset import get_descendants_of def execute(filters=None): filters = frappe._dict(filters or {}) + if filters.from_date > filters.to_date: + frappe.throw(_('From Date cannot be greater than To Date')) + columns = get_columns(filters) data = get_data(filters) diff --git a/erpnext/setup/doctype/company/company.js b/erpnext/setup/doctype/company/company.js index 875904fe6fe..7ae5385a23c 100644 --- a/erpnext/setup/doctype/company/company.js +++ b/erpnext/setup/doctype/company/company.js @@ -264,7 +264,10 @@ erpnext.company.setup_queries = function(frm) { ["expenses_included_in_valuation", {"root_type": "Expense", "account_type": "Expenses Included in Valuation"}], ["stock_received_but_not_billed", - {"root_type": "Liability", "account_type": "Stock Received But Not Billed"}] + {"root_type": "Liability", "account_type": "Stock Received But Not Billed"}], + ["service_received_but_not_billed", + {"root_type": "Liability", "account_type": "Service Received But Not Billed"}], + ], function(i, v) { erpnext.company.set_custom_query(frm, v); }); diff --git a/erpnext/setup/doctype/company/company.json b/erpnext/setup/doctype/company/company.json index 020a93ff6ac..221044df3a7 100644 --- a/erpnext/setup/doctype/company/company.json +++ b/erpnext/setup/doctype/company/company.json @@ -22,7 +22,6 @@ "default_letter_head", "default_holiday_list", "default_finance_book", - "standard_working_hours", "default_selling_terms", "default_buying_terms", "default_warehouse_for_sales_return", @@ -67,10 +66,12 @@ "payment_terms", "auto_accounting_for_stock_settings", "enable_perpetual_inventory", + "enable_perpetual_inventory_for_non_stock_items", "default_inventory_account", "stock_adjustment_account", "column_break_32", "stock_received_but_not_billed", + "service_received_but_not_billed", "expenses_included_in_valuation", "fixed_asset_depreciation_settings", "accumulated_depreciation_account", @@ -238,11 +239,6 @@ "label": "Default Holiday List", "options": "Holiday List" }, - { - "fieldname": "standard_working_hours", - "fieldtype": "Float", - "label": "Standard Working Hours" - }, { "fieldname": "default_warehouse_for_sales_return", "fieldtype": "Link", @@ -723,6 +719,20 @@ "fieldtype": "Link", "label": "Default Buying Terms", "options": "Terms and Conditions" + }, + { + "fieldname": "service_received_but_not_billed", + "fieldtype": "Link", + "ignore_user_permissions": 1, + "label": "Service Received But Not Billed", + "no_copy": 1, + "options": "Account" + }, + { + "default": "0", + "fieldname": "enable_perpetual_inventory_for_non_stock_items", + "fieldtype": "Check", + "label": "Enable Perpetual Inventory For Non Stock Items" } ], "icon": "fa fa-building", @@ -730,7 +740,7 @@ "image_field": "company_logo", "is_tree": 1, "links": [], - "modified": "2020-03-21 18:09:53.534211", + "modified": "2020-06-24 12:45:31.462195", "modified_by": "Administrator", "module": "Setup", "name": "Company", diff --git a/erpnext/setup/doctype/company/company.py b/erpnext/setup/doctype/company/company.py index 8bcaa287072..47b41a97ad3 100644 --- a/erpnext/setup/doctype/company/company.py +++ b/erpnext/setup/doctype/company/company.py @@ -46,6 +46,7 @@ class Company(NestedSet): self.validate_currency() self.validate_coa_input() self.validate_perpetual_inventory() + self.validate_perpetual_inventory_for_non_stock_items() self.check_country_change() self.set_chart_of_accounts() self.validate_parent_company() @@ -182,6 +183,12 @@ class Company(NestedSet): frappe.msgprint(_("Set default inventory account for perpetual inventory"), alert=True, indicator='orange') + def validate_perpetual_inventory_for_non_stock_items(self): + if not self.get("__islocal"): + if cint(self.enable_perpetual_inventory_for_non_stock_items) == 1 and not self.service_received_but_not_billed: + frappe.throw(_("Set default {0} account for perpetual inventory for non stock items").format( + frappe.bold('Service Received But Not Billed'))) + def check_country_change(self): frappe.flags.country_change = False diff --git a/erpnext/setup/doctype/customer_group/customer_group.js b/erpnext/setup/doctype/customer_group/customer_group.js index c199a8e57f1..44a50191209 100644 --- a/erpnext/setup/doctype/customer_group/customer_group.js +++ b/erpnext/setup/doctype/customer_group/customer_group.js @@ -8,7 +8,7 @@ cur_frm.cscript.refresh = function(doc, cdt, cdn) { cur_frm.cscript.set_root_readonly = function(doc) { // read-only for root customer group - if(!doc.parent_customer_group) { + if(!doc.parent_customer_group && !doc.__islocal) { cur_frm.set_read_only(); cur_frm.set_intro(__("This is a root customer group and cannot be edited.")); } else { @@ -20,7 +20,8 @@ cur_frm.cscript.set_root_readonly = function(doc) { cur_frm.fields_dict['parent_customer_group'].get_query = function(doc,cdt,cdn) { return { filters: { - 'is_group': 1 + 'is_group': 1, + 'name': ['!=', cur_frm.doc.customer_group_name] } } } diff --git a/erpnext/setup/doctype/email_digest/email_digest.py b/erpnext/setup/doctype/email_digest/email_digest.py index 7c0be3bff63..b30bd7814b6 100644 --- a/erpnext/setup/doctype/email_digest/email_digest.py +++ b/erpnext/setup/doctype/email_digest/email_digest.py @@ -405,8 +405,8 @@ class EmailDigest(Document): value, count = frappe.db.sql("""select ifnull((sum(grand_total)) - (sum(grand_total*per_billed/100)),0), count(*) from `tabSales Order` - where (transaction_date <= %(to_date)s) and billing_status != "Fully Billed" - and status not in ('Closed','Cancelled', 'Completed') """, {"to_date": self.future_to_date})[0] + where (transaction_date <= %(to_date)s) and billing_status != "Fully Billed" and company = %(company)s + and status not in ('Closed','Cancelled', 'Completed') """, {"to_date": self.future_to_date, "company": self.company})[0] label = get_link_to_report('Sales Order', label=self.meta.get_label("sales_orders_to_bill"), report_type="Report Builder", @@ -430,8 +430,8 @@ class EmailDigest(Document): value, count = frappe.db.sql("""select ifnull((sum(grand_total)) - (sum(grand_total*per_delivered/100)),0), count(*) from `tabSales Order` - where (transaction_date <= %(to_date)s) and delivery_status != "Fully Delivered" - and status not in ('Closed','Cancelled', 'Completed') """, {"to_date": self.future_to_date})[0] + where (transaction_date <= %(to_date)s) and delivery_status != "Fully Delivered" and company = %(company)s + and status not in ('Closed','Cancelled', 'Completed') """, {"to_date": self.future_to_date, "company": self.company})[0] label = get_link_to_report('Sales Order', label=self.meta.get_label("sales_orders_to_deliver"), report_type="Report Builder", @@ -455,8 +455,8 @@ class EmailDigest(Document): value, count = frappe.db.sql("""select ifnull((sum(grand_total))-(sum(grand_total*per_received/100)),0), count(*) from `tabPurchase Order` - where (transaction_date <= %(to_date)s) and per_received < 100 - and status not in ('Closed','Cancelled', 'Completed') """, {"to_date": self.future_to_date})[0] + where (transaction_date <= %(to_date)s) and per_received < 100 and company = %(company)s + and status not in ('Closed','Cancelled', 'Completed') """, {"to_date": self.future_to_date, "company": self.company})[0] label = get_link_to_report('Purchase Order', label=self.meta.get_label("purchase_orders_to_receive"), report_type="Report Builder", @@ -480,8 +480,8 @@ class EmailDigest(Document): value, count = frappe.db.sql("""select ifnull((sum(grand_total)) - (sum(grand_total*per_billed/100)),0), count(*) from `tabPurchase Order` - where (transaction_date <= %(to_date)s) and per_billed < 100 - and status not in ('Closed','Cancelled', 'Completed') """, {"to_date": self.future_to_date})[0] + where (transaction_date <= %(to_date)s) and per_billed < 100 and company = %(company)s + and status not in ('Closed','Cancelled', 'Completed') """, {"to_date": self.future_to_date, "company": self.company})[0] label = get_link_to_report('Purchase Order', label=self.meta.get_label("purchase_orders_to_bill"), report_type="Report Builder", diff --git a/erpnext/setup/doctype/item_group/item_group.js b/erpnext/setup/doctype/item_group/item_group.js index df2223192bd..9892dc3dcc0 100644 --- a/erpnext/setup/doctype/item_group/item_group.js +++ b/erpnext/setup/doctype/item_group/item_group.js @@ -66,7 +66,7 @@ frappe.ui.form.on("Item Group", { set_root_readonly: function(frm) { // read-only for root item group frm.set_intro(""); - if(!frm.doc.parent_item_group) { + if(!frm.doc.parent_item_group && !frm.doc.__islocal) { frm.set_read_only(); frm.set_intro(__("This is a root item group and cannot be edited."), true); } diff --git a/erpnext/setup/doctype/sales_person/sales_person.js b/erpnext/setup/doctype/sales_person/sales_person.js index 89ca4a9dd74..8f7593d6eef 100644 --- a/erpnext/setup/doctype/sales_person/sales_person.js +++ b/erpnext/setup/doctype/sales_person/sales_person.js @@ -19,7 +19,7 @@ frappe.ui.form.on('Sales Person', { } } }; - + frm.make_methods = { 'Sales Order': () => frappe.new_doc("Sales Order") .then(() => frm.add_child("sales_team", {"sales_person": frm.doc.name})) @@ -33,7 +33,7 @@ cur_frm.cscript.refresh = function(doc, cdt, cdn) { cur_frm.cscript.set_root_readonly = function(doc) { // read-only for root - if(!doc.parent_sales_person) { + if(!doc.parent_sales_person && !doc.__islocal) { cur_frm.set_read_only(); cur_frm.set_intro(__("This is a root sales person and cannot be edited.")); } else { diff --git a/erpnext/setup/doctype/supplier_group/supplier_group.js b/erpnext/setup/doctype/supplier_group/supplier_group.js index ac5bda6e2c6..e75030d4414 100644 --- a/erpnext/setup/doctype/supplier_group/supplier_group.js +++ b/erpnext/setup/doctype/supplier_group/supplier_group.js @@ -8,7 +8,7 @@ cur_frm.cscript.refresh = function(doc) { cur_frm.cscript.set_root_readonly = function(doc) { // read-only for root customer group - if(!doc.parent_supplier_group) { + if(!doc.parent_supplier_group && !doc.__islocal) { cur_frm.set_read_only(); cur_frm.set_intro(__("This is a root supplier group and cannot be edited.")); } else { @@ -20,7 +20,8 @@ cur_frm.cscript.set_root_readonly = function(doc) { cur_frm.fields_dict['parent_supplier_group'].get_query = function() { return { filters: { - 'is_group': 1 + 'is_group': 1, + 'name': ['!=', cur_frm.doc.supplier_group_name] } }; }; diff --git a/erpnext/setup/doctype/territory/territory.js b/erpnext/setup/doctype/territory/territory.js index 1eb9958ce70..ceec47ae8c6 100644 --- a/erpnext/setup/doctype/territory/territory.js +++ b/erpnext/setup/doctype/territory/territory.js @@ -20,7 +20,7 @@ cur_frm.cscript.refresh = function(doc, cdt, cdn) { cur_frm.cscript.set_root_readonly = function(doc) { // read-only for root territory - if(!doc.parent_territory) { + if(!doc.parent_territory && !doc.__islocal) { cur_frm.set_read_only(); cur_frm.set_intro(__("This is a root territory and cannot be edited.")); } else { diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py index e6ab8d634d8..d0ba001d7e1 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py @@ -211,6 +211,7 @@ class PurchaseReceipt(BuyingController): stock_rbnb = self.get_company_default("stock_received_but_not_billed") landed_cost_entries = get_item_account_wise_additional_cost(self.name) expenses_included_in_valuation = self.get_company_default("expenses_included_in_valuation") + auto_accounting_for_non_stock_items = cint(frappe.db.get_value('Company', self.company, 'enable_perpetual_inventory_for_non_stock_items')) gl_entries = [] warehouse_with_no_account = [] @@ -301,6 +302,32 @@ class PurchaseReceipt(BuyingController): elif d.warehouse not in warehouse_with_no_account or \ d.rejected_warehouse not in warehouse_with_no_account: warehouse_with_no_account.append(d.warehouse) + elif d.item_code not in stock_items and flt(d.qty) and auto_accounting_for_non_stock_items: + + service_received_but_not_billed_account = self.get_company_default("service_received_but_not_billed") + credit_currency = get_account_currency(service_received_but_not_billed_account) + + gl_entries.append(self.get_gl_dict({ + "account": service_received_but_not_billed_account, + "against": d.expense_account, + "cost_center": d.cost_center, + "remarks": self.get("remarks") or _("Accounting Entry for Service"), + "project": d.project, + "credit": d.amount, + "voucher_detail_no": d.name + }, credit_currency, item=d)) + + debit_currency = get_account_currency(d.expense_account) + + gl_entries.append(self.get_gl_dict({ + "account": d.expense_account, + "against": service_received_but_not_billed_account, + "cost_center": d.cost_center, + "remarks": self.get("remarks") or _("Accounting Entry for Service"), + "project": d.project, + "debit": d.amount, + "voucher_detail_no": d.name + }, debit_currency, item=d)) self.get_asset_gl_entry(gl_entries) # Cost center-wise amount breakup for other charges included for valuation diff --git a/erpnext/stock/doctype/stock_settings/stock_settings.json b/erpnext/stock/doctype/stock_settings/stock_settings.json index c9a3527e919..9c5d3d8340e 100644 --- a/erpnext/stock/doctype/stock_settings/stock_settings.json +++ b/erpnext/stock/doctype/stock_settings/stock_settings.json @@ -216,7 +216,7 @@ "idx": 1, "issingle": 1, "links": [], - "modified": "2020-04-01 18:11:25.417678", + "modified": "2020-06-20 11:39:15.344112", "modified_by": "Administrator", "module": "Stock", "name": "Stock Settings", diff --git a/erpnext/stock/report/stock_ageing/stock_ageing.py b/erpnext/stock/report/stock_ageing/stock_ageing.py index 723ed5c1c46..d5878cb6624 100644 --- a/erpnext/stock/report/stock_ageing/stock_ageing.py +++ b/erpnext/stock/report/stock_ageing/stock_ageing.py @@ -187,7 +187,7 @@ def get_fifo_queue(filters, sle=None): transferred_item_details[(d.voucher_no, d.name)].append(fifo_queue.pop(0)) else: # all from current batch - batch[0] -= qty_to_pop + batch[0] = flt(batch[0]) - qty_to_pop transferred_item_details[(d.voucher_no, d.name)].append([qty_to_pop, batch[1]]) qty_to_pop = 0 diff --git a/erpnext/support/doctype/issue/issue.py b/erpnext/support/doctype/issue/issue.py index 883e603fd31..87168e151e6 100644 --- a/erpnext/support/doctype/issue/issue.py +++ b/erpnext/support/doctype/issue/issue.py @@ -79,47 +79,52 @@ class Issue(Document): def handle_hold_time(self, status): if self.service_level_agreement: - # set response and resolution variance as None as the issue is on Hold for status as Replied + # set response and resolution variance as None as the issue is on Hold pause_sla_on = frappe.db.get_all("Pause SLA On Status", fields=["status"], filters={"parent": self.service_level_agreement}) hold_statuses = [entry.status for entry in pause_sla_on] update_values = {} - if self.status in hold_statuses and status not in hold_statuses: - update_values['on_hold_since'] = frappe.flags.current_time or now_datetime() - if not self.first_responded_on: - update_values['response_by'] = None - update_values['response_by_variance'] = 0 - update_values['resolution_by'] = None - update_values['resolution_by_variance'] = 0 + if hold_statuses: + if self.status in hold_statuses and status not in hold_statuses: + update_values['on_hold_since'] = frappe.flags.current_time or now_datetime() + if not self.first_responded_on: + update_values['response_by'] = None + update_values['response_by_variance'] = 0 + update_values['resolution_by'] = None + update_values['resolution_by_variance'] = 0 - # calculate hold time when status is changed from Replied to any other status - if self.status not in hold_statuses and status in hold_statuses: - hold_time = self.total_hold_time if self.total_hold_time else 0 - now_time = frappe.flags.current_time or now_datetime() - update_values['total_hold_time'] = hold_time + time_diff_in_seconds(now_time, self.on_hold_since) + # calculate hold time when status is changed from any hold status to any non-hold status + if self.status not in hold_statuses and status in hold_statuses: + hold_time = self.total_hold_time if self.total_hold_time else 0 + now_time = frappe.flags.current_time or now_datetime() + last_hold_time = 0 + if self.on_hold_since: + # last_hold_time will be added to the sla variables + last_hold_time = time_diff_in_seconds(now_time, self.on_hold_since) + update_values['total_hold_time'] = hold_time + last_hold_time - # re-calculate SLA variables after issue changes from Replied to Open - # add hold time to SLA variables - if self.status == "Open" and status in hold_statuses: - start_date_time = get_datetime(self.service_level_agreement_creation) - priority = get_priority(self) - now_time = frappe.flags.current_time or now_datetime() - hold_time = time_diff_in_seconds(now_time, self.on_hold_since) + # re-calculate SLA variables after issue changes from any hold status to any non-hold status + # add hold time to SLA variables + start_date_time = get_datetime(self.service_level_agreement_creation) + priority = get_priority(self) + now_time = frappe.flags.current_time or now_datetime() - if not self.first_responded_on: - response_by = get_expected_time_for(parameter="response", service_level=priority, start_date_time=start_date_time) - update_values['response_by'] = add_to_date(response_by, seconds=round(hold_time)) - response_by_variance = round(time_diff_in_hours(self.response_by, now_time)) - update_values['response_by_variance'] = response_by_variance + (hold_time // 3600) + if not self.first_responded_on: + response_by = get_expected_time_for(parameter="response", service_level=priority, start_date_time=start_date_time) + response_by = add_to_date(response_by, seconds=round(last_hold_time)) + response_by_variance = round(time_diff_in_hours(response_by, now_time)) + update_values['response_by'] = response_by + update_values['response_by_variance'] = response_by_variance + (last_hold_time // 3600) - resolution_by = get_expected_time_for(parameter="resolution", service_level=priority, start_date_time=start_date_time) - update_values['resolution_by'] = add_to_date(resolution_by, seconds=round(hold_time)) - resolution_by_variance = round(time_diff_in_hours(self.resolution_by, now_time)) - update_values['resolution_by_variance'] = resolution_by_variance + (hold_time // 3600) - update_values['on_hold_since'] = None + resolution_by = get_expected_time_for(parameter="resolution", service_level=priority, start_date_time=start_date_time) + resolution_by = add_to_date(resolution_by, seconds=round(last_hold_time)) + resolution_by_variance = round(time_diff_in_hours(resolution_by, now_time)) + update_values['resolution_by'] = resolution_by + update_values['resolution_by_variance'] = resolution_by_variance + (last_hold_time // 3600) + update_values['on_hold_since'] = None - self.db_set(update_values) + self.db_set(update_values) def update_agreement_status(self): if self.service_level_agreement and self.agreement_fulfilled == "Ongoing":