diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py index 0a385d0af7..34c262e27f 100644 --- a/erpnext/accounts/doctype/journal_entry/journal_entry.py +++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py @@ -1023,7 +1023,7 @@ def make_inter_company_journal_entry(name, voucher_type, company): return journal_entry.as_dict() @frappe.whitelist() -def make_reverse_journal_entry(source_name, target_doc=None, ignore_permissions=False): +def make_reverse_journal_entry(source_name, target_doc=None): from frappe.model.mapper import get_mapped_doc def update_accounts(source, target, source_parent): @@ -1049,6 +1049,6 @@ def make_reverse_journal_entry(source_name, target_doc=None, ignore_permissions= }, "postprocess": update_accounts, }, - }, target_doc, ignore_permissions=ignore_permissions) + }, target_doc) return doclist \ No newline at end of file diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js index 4f6be59c65..2bfa4a572e 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js @@ -25,6 +25,12 @@ erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({ this.frm.set_df_property("credit_to", "print_hide", 0); } } + + // Trigger supplier event on load if supplier is available + // The reason for this is PI can be created from PR or PO and supplier is pre populated + if (this.frm.doc.supplier) { + this.frm.trigger('supplier'); + } }, refresh: function(doc) { @@ -135,6 +141,8 @@ erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({ } }); } + + this.frm.set_df_property("tax_withholding_category", "hidden", doc.apply_tds ? 0 : 1); }, unblock_invoice: function() { diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py index 7b1062f654..b4ee7c999e 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -132,6 +132,11 @@ class PurchaseInvoice(BuyingController): if not self.due_date: self.due_date = get_due_date(self.posting_date, "Supplier", self.supplier, self.company, self.bill_date) + tds_category = frappe.db.get_value("Supplier", self.supplier, "tax_withholding_category") + if tds_category and not for_validate: + self.apply_tds = 1 + self.tax_withholding_category = tds_category + super(PurchaseInvoice, self).set_missing_values(for_validate) def check_conversion_rate(self): diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py index 0bd03a8dbe..9d08d9212d 100644 --- a/erpnext/assets/doctype/asset/asset.py +++ b/erpnext/assets/doctype/asset/asset.py @@ -146,7 +146,7 @@ class Asset(AccountsController): 'assets': assets, 'purpose': 'Receipt', 'company': self.company, - 'transaction_date': getdate(nowdate()), + 'transaction_date': getdate(self.purchase_date), 'reference_doctype': reference_doctype, 'reference_name': reference_docname }).insert() diff --git a/erpnext/controllers/status_updater.py b/erpnext/controllers/status_updater.py index e776dc96ac..2555edf06b 100644 --- a/erpnext/controllers/status_updater.py +++ b/erpnext/controllers/status_updater.py @@ -257,7 +257,7 @@ class StatusUpdater(Document): args['second_source_condition'] = """ + ifnull((select sum(%(second_source_field)s) from `tab%(second_source_dt)s` where `%(second_join_field)s`="%(detail_id)s" - and (`tab%(second_source_dt)s`.docstatus=1) %(second_source_extra_cond)s), 0) """ % args + and (`tab%(second_source_dt)s`.docstatus=1) %(second_source_extra_cond)s FOR UPDATE), 0)""" % args if args['detail_id']: if not args.get("extra_cond"): args["extra_cond"] = "" diff --git a/erpnext/loan_management/doctype/loan/test_loan.py b/erpnext/loan_management/doctype/loan/test_loan.py index f225409f62..5a4a19a0fb 100644 --- a/erpnext/loan_management/doctype/loan/test_loan.py +++ b/erpnext/loan_management/doctype/loan/test_loan.py @@ -317,6 +317,11 @@ class TestLoan(unittest.TestCase): self.assertEqual(loan.status, 'Closed') self.assertEquals(sum(pledged_qty.values()), 0) + amounts = amounts = calculate_amounts(loan.name, add_days(last_date, 6), "Regular Repayment") + self.assertEqual(amounts['pending_principal_amount'], 0) + self.assertEqual(amounts['payable_principal_amount'], 0) + self.assertEqual(amounts['interest_amount'], 0) + def test_disbursal_check_with_shortfall(self): pledges = [{ "loan_security": "Test Security 2", diff --git a/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py b/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py index 47fb885f8a..97dbc44bf1 100644 --- a/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py +++ b/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py @@ -327,7 +327,7 @@ def get_amounts(amounts, against_loan, posting_date, payment_type): if not final_due_date: final_due_date = add_days(due_date, loan_type_details.grace_period_in_days) - if against_loan_doc.status in ('Disbursed', 'Loan Closure Requested'): + if against_loan_doc.status in ('Disbursed', 'Loan Closure Requested', 'Closed'): pending_principal_amount = against_loan_doc.total_payment - against_loan_doc.total_principal_paid - against_loan_doc.total_interest_payable else: pending_principal_amount = against_loan_doc.disbursed_amount diff --git a/erpnext/patches.txt b/erpnext/patches.txt index aa7996e3e1..6c58f2f452 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -697,7 +697,7 @@ erpnext.patches.v12_0.update_bom_in_so_mr execute:frappe.delete_doc("Report", "Department Analytics") execute:frappe.rename_doc("Desk Page", "Loan Management", "Loan", force=True) erpnext.patches.v12_0.update_uom_conversion_factor -execute:frappe.delete_doc_if_exists("Page", "pos") #29-05-2020 +erpnext.patches.v13_0.replace_pos_page_with_point_of_sale_page erpnext.patches.v13_0.delete_old_purchase_reports erpnext.patches.v12_0.set_italian_import_supplier_invoice_permissions erpnext.patches.v13_0.update_subscription diff --git a/erpnext/patches/v13_0/replace_pos_page_with_point_of_sale_page.py b/erpnext/patches/v13_0/replace_pos_page_with_point_of_sale_page.py new file mode 100644 index 0000000000..390e217cad --- /dev/null +++ b/erpnext/patches/v13_0/replace_pos_page_with_point_of_sale_page.py @@ -0,0 +1,6 @@ +from __future__ import unicode_literals +import frappe + +def execute(): + if frappe.db.exists("Page", "point-of-sale"): + frappe.rename_doc("Page", "pos", "point-of-sale", 1, 1) \ No newline at end of file diff --git a/erpnext/portal/product_configurator/utils.py b/erpnext/portal/product_configurator/utils.py index 9eef16bed3..9ba4cdc514 100644 --- a/erpnext/portal/product_configurator/utils.py +++ b/erpnext/portal/product_configurator/utils.py @@ -13,13 +13,15 @@ def get_field_filter_data(): for f in fields: doctype = f.get_link_doctype() - # apply enable/disable filter + # apply enable/disable/show_in_website filter meta = frappe.get_meta(doctype) filters = {} if meta.has_field('enabled'): filters['enabled'] = 1 if meta.has_field('disabled'): filters['disabled'] = 0 + if meta.has_field('show_in_website'): + filters['show_in_website'] = 1 values = [d.name for d in frappe.get_all(doctype, filters)] filter_data.append([f, values]) diff --git a/erpnext/regional/report/irs_1099/irs_1099.py b/erpnext/regional/report/irs_1099/irs_1099.py index 67834d1221..d3509e500f 100644 --- a/erpnext/regional/report/irs_1099/irs_1099.py +++ b/erpnext/regional/report/irs_1099/irs_1099.py @@ -16,9 +16,15 @@ from frappe.utils.jinja import render_template def execute(filters=None): filters = filters if isinstance(filters, _dict) else _dict(filters) + if not filters: filters.setdefault('fiscal_year', get_fiscal_year(nowdate())[0]) filters.setdefault('company', frappe.db.get_default("company")) + + region = frappe.db.get_value("Company", fieldname = ["country"], filters = { "name": filters.company }) + if region != 'United States': + return [],[] + data = [] columns = get_columns() data = frappe.db.sql(""" diff --git a/erpnext/regional/united_states/test_united_states.py b/erpnext/regional/united_states/test_united_states.py index 688f14576c..ad95010a9a 100644 --- a/erpnext/regional/united_states/test_united_states.py +++ b/erpnext/regional/united_states/test_united_states.py @@ -24,7 +24,7 @@ class TestUnitedStates(unittest.TestCase): def test_irs_1099_report(self): make_payment_entry_to_irs_1099_supplier() - filters = frappe._dict({"fiscal_year": "_Test Fiscal Year 2016", "company": "_Test Company"}) + filters = frappe._dict({"fiscal_year": "_Test Fiscal Year 2016", "company": "_Test Company 1"}) columns, data = execute_1099_report(filters) print(columns, data) expected_row = {'supplier': '_US 1099 Test Supplier', @@ -42,10 +42,10 @@ def make_payment_entry_to_irs_1099_supplier(): pe = frappe.new_doc("Payment Entry") pe.payment_type = "Pay" - pe.company = "_Test Company" + pe.company = "_Test Company 1" pe.posting_date = "2016-01-10" - pe.paid_from = "_Test Bank USD - _TC" - pe.paid_to = "_Test Payable USD - _TC" + pe.paid_from = "_Test Bank USD - _TC1" + pe.paid_to = "_Test Payable USD - _TC1" pe.paid_amount = 100 pe.received_amount = 100 pe.reference_no = "For IRS 1099 testing" diff --git a/erpnext/stock/desk_page/stock/stock.json b/erpnext/stock/desk_page/stock/stock.json index 1bf81f7f0e..2fba5fa804 100644 --- a/erpnext/stock/desk_page/stock/stock.json +++ b/erpnext/stock/desk_page/stock/stock.json @@ -33,7 +33,7 @@ { "hidden": 0, "label": "Key Reports", - "links": "[\n {\n \"dependencies\": [\n \"Item Price\"\n ],\n \"doctype\": \"Item Price\",\n \"is_query_report\": false,\n \"label\": \"Item-wise Price List Rate\",\n \"name\": \"Item-wise Price List Rate\",\n \"onboard\": 1,\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Stock Entry\"\n ],\n \"doctype\": \"Stock Entry\",\n \"is_query_report\": true,\n \"label\": \"Stock Analytics\",\n \"name\": \"Stock Analytics\",\n \"onboard\": 1,\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Delivery Note\"\n ],\n \"doctype\": \"Delivery Note\",\n \"is_query_report\": true,\n \"label\": \"Delivery Note Trends\",\n \"name\": \"Delivery Note Trends\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Purchase Receipt\"\n ],\n \"doctype\": \"Purchase Receipt\",\n \"is_query_report\": true,\n \"label\": \"Purchase Receipt Trends\",\n \"name\": \"Purchase Receipt Trends\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Order\"\n ],\n \"doctype\": \"Sales Order\",\n \"is_query_report\": true,\n \"label\": \"Sales Order Analysis\",\n \"name\": \"Sales Order Analysis\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Purchase Order\"\n ],\n \"doctype\": \"Purchase Order\",\n \"is_query_report\": true,\n \"label\": \"Purchase Order Analysis\",\n \"name\": \"Purchase Order Analysis\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Bin\"\n ],\n \"doctype\": \"Bin\",\n \"is_query_report\": true,\n \"label\": \"Item Shortage Report\",\n \"name\": \"Item Shortage Report\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Batch\"\n ],\n \"doctype\": \"Batch\",\n \"is_query_report\": true,\n \"label\": \"Batch-Wise Balance History\",\n \"name\": \"Batch-Wise Balance History\",\n \"type\": \"report\"\n }\n]" + "links": "[\n {\n \"dependencies\": [\n \"Item Price\"\n ],\n \"doctype\": \"Item Price\",\n \"is_query_report\": false,\n \"label\": \"Item-wise Price List Rate\",\n \"name\": \"Item-wise Price List Rate\",\n \"onboard\": 1,\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Stock Entry\"\n ],\n \"doctype\": \"Stock Entry\",\n \"is_query_report\": true,\n \"label\": \"Stock Analytics\",\n \"name\": \"Stock Analytics\",\n \"onboard\": 1,\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Item\"\n ],\n \"doctype\": \"Item\",\n \"is_query_report\": true,\n \"label\": \"Stock Qty vs Serial No Count\",\n \"name\": \"Stock Qty vs Serial No Count\",\n \"onboard\": 1,\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Delivery Note\"\n ],\n \"doctype\": \"Delivery Note\",\n \"is_query_report\": true,\n \"label\": \"Delivery Note Trends\",\n \"name\": \"Delivery Note Trends\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Purchase Receipt\"\n ],\n \"doctype\": \"Purchase Receipt\",\n \"is_query_report\": true,\n \"label\": \"Purchase Receipt Trends\",\n \"name\": \"Purchase Receipt Trends\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Order\"\n ],\n \"doctype\": \"Sales Order\",\n \"is_query_report\": true,\n \"label\": \"Sales Order Analysis\",\n \"name\": \"Sales Order Analysis\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Purchase Order\"\n ],\n \"doctype\": \"Purchase Order\",\n \"is_query_report\": true,\n \"label\": \"Purchase Order Analysis\",\n \"name\": \"Purchase Order Analysis\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Bin\"\n ],\n \"doctype\": \"Bin\",\n \"is_query_report\": true,\n \"label\": \"Item Shortage Report\",\n \"name\": \"Item Shortage Report\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Batch\"\n ],\n \"doctype\": \"Batch\",\n \"is_query_report\": true,\n \"label\": \"Batch-Wise Balance History\",\n \"name\": \"Batch-Wise Balance History\",\n \"type\": \"report\"\n }\n]" }, { "hidden": 0, @@ -58,7 +58,7 @@ "idx": 0, "is_standard": 1, "label": "Stock", - "modified": "2020-05-30 17:32:11.062681", + "modified": "2020-08-11 17:29:32.626067", "modified_by": "Administrator", "module": "Stock", "name": "Stock", diff --git a/erpnext/stock/report/stock_qty_vs_serial_no_count/__init__.py b/erpnext/stock/report/stock_qty_vs_serial_no_count/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/stock/report/stock_qty_vs_serial_no_count/stock_qty_vs_serial_no_count.js b/erpnext/stock/report/stock_qty_vs_serial_no_count/stock_qty_vs_serial_no_count.js new file mode 100644 index 0000000000..2a0fd4025c --- /dev/null +++ b/erpnext/stock/report/stock_qty_vs_serial_no_count/stock_qty_vs_serial_no_count.js @@ -0,0 +1,42 @@ +// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt +/* eslint-disable */ + +frappe.query_reports["Stock Qty vs Serial No Count"] = { + "filters": [ + { + "fieldname":"company", + "label": __("Company"), + "fieldtype": "Link", + "options": "Company", + "default": frappe.defaults.get_user_default("Company"), + "reqd": 1 + }, + { + "fieldname":"warehouse", + "label": __("Warehouse"), + "fieldtype": "Link", + "options": "Warehouse", + "get_query": function() { + const company = frappe.query_report.get_filter_value('company'); + return { + filters: { 'company': company } + } + }, + "reqd": 1 + }, + ], + + "formatter": function (value, row, column, data, default_formatter) { + value = default_formatter(value, row, column, data); + if (column.fieldname == "difference" && data) { + if (data.difference > 0) { + value = "" + value + ""; + } + else if (data.difference < 0) { + value = "" + value + ""; + } + } + return value; + } +}; diff --git a/erpnext/stock/report/stock_qty_vs_serial_no_count/stock_qty_vs_serial_no_count.json b/erpnext/stock/report/stock_qty_vs_serial_no_count/stock_qty_vs_serial_no_count.json new file mode 100644 index 0000000000..c7108b513e --- /dev/null +++ b/erpnext/stock/report/stock_qty_vs_serial_no_count/stock_qty_vs_serial_no_count.json @@ -0,0 +1,27 @@ +{ + "add_total_row": 0, + "creation": "2020-07-23 19:31:32.395011", + "disable_prepared_report": 0, + "disabled": 0, + "docstatus": 0, + "doctype": "Report", + "idx": 0, + "is_standard": "Yes", + "modified": "2020-07-23 19:32:02.168185", + "modified_by": "Administrator", + "module": "Stock", + "name": "Stock Qty vs Serial No Count", + "owner": "Administrator", + "prepared_report": 0, + "ref_doctype": "Item", + "report_name": "Stock Qty vs Serial No Count", + "report_type": "Script Report", + "roles": [ + { + "role": "Stock Manager" + }, + { + "role": "Stock User" + } + ] +} \ No newline at end of file diff --git a/erpnext/stock/report/stock_qty_vs_serial_no_count/stock_qty_vs_serial_no_count.py b/erpnext/stock/report/stock_qty_vs_serial_no_count/stock_qty_vs_serial_no_count.py new file mode 100644 index 0000000000..55f041c95c --- /dev/null +++ b/erpnext/stock/report/stock_qty_vs_serial_no_count/stock_qty_vs_serial_no_count.py @@ -0,0 +1,80 @@ +# 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 _ + +def execute(filters=None): + columns = get_columns() + data = get_data(filters.warehouse) + return columns, data + +def get_columns(): + columns = [ + { + "label": _("Item Code"), + "fieldname": "item_code", + "fieldtype": "Link", + "options": "Item", + "width": 200 + }, + { + "label": _("Item Name"), + "fieldname": "item_name", + "fieldtype": "Data", + "width": 200 + }, + { + "label": _("Serial No Count"), + "fieldname": "total", + "fieldtype": "Float", + "width": 150 + }, + { + "label": _("Stock Qty"), + "fieldname": "stock_qty", + "fieldtype": "Float", + "width": 150 + }, + { + "label": _("Difference"), + "fieldname": "difference", + "fieldtype": "Float", + "width": 150 + }, + ] + + return columns + +def get_data(warehouse): + serial_item_list = frappe.get_all("Item", filters={ + 'has_serial_no': True, + }, fields=['item_code', 'item_name']) + + status_list = ['Active', 'Expired'] + data = [] + for item in serial_item_list: + total_serial_no = frappe.db.count("Serial No", + filters={"item_code": item.item_code, "status": ("in", status_list), "warehouse": warehouse}) + + actual_qty = frappe.db.get_value('Bin', fieldname=['actual_qty'], + filters={"warehouse": warehouse, "item_code": item.item_code}) + + # frappe.db.get_value returns null if no record exist. + if not actual_qty: + actual_qty = 0 + + difference = total_serial_no - actual_qty + + row = { + "item_code": item.item_code, + "item_name": item.item_name, + "total": total_serial_no, + "stock_qty": actual_qty, + "difference": difference, + } + + data.append(row) + + return data \ No newline at end of file