diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py index 079f599706..c5260a1239 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -711,7 +711,8 @@ class PurchaseInvoice(BuyingController): item.item_tax_amount / self.conversion_rate) }, item=item)) else: - cwip_account = get_asset_account("capital_work_in_progress_account", company = self.company) + cwip_account = get_asset_account("capital_work_in_progress_account", + asset_category=item.asset_category,company=self.company) cwip_account_currency = get_account_currency(cwip_account) gl_entries.append(self.get_gl_dict({ diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py index 9a666bf9f8..2e5a7142a3 100644 --- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py @@ -1002,7 +1002,8 @@ def make_purchase_invoice(**args): "cost_center": args.cost_center or "_Test Cost Center - _TC", "project": args.project, "rejected_warehouse": args.rejected_warehouse or "", - "rejected_serial_no": args.rejected_serial_no or "" + "rejected_serial_no": args.rejected_serial_no or "", + "asset_location": args.location or "" }) if args.get_taxes_and_charges: diff --git a/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py b/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py index 83d7967f79..8b5e68b359 100644 --- a/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py +++ b/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py @@ -106,6 +106,7 @@ def get_tds_amount(suppliers, net_total, company, tax_details, fiscal_year_detai from `tabGL Entry` where company = %s and party in %s and fiscal_year=%s and credit > 0 + and is_opening = 'No' """, (company, tuple(suppliers), fiscal_year), as_dict=1) vouchers = [d.voucher_no for d in entries] @@ -192,6 +193,7 @@ def get_advance_vouchers(suppliers, fiscal_year=None, company=None, from_date=No select distinct voucher_no from `tabGL Entry` where party in %s and %s and debit > 0 + and is_opening = 'No' """, (tuple(suppliers), condition)) or [] def get_debit_note_amount(suppliers, year_start_date, year_end_date, company=None): diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py index efdbdb1fbf..fca9559504 100644 --- a/erpnext/assets/doctype/asset/asset.py +++ b/erpnext/assets/doctype/asset/asset.py @@ -466,50 +466,63 @@ class Asset(AccountsController): def validate_make_gl_entry(self): purchase_document = self.get_purchase_document() - asset_bought_with_invoice = purchase_document == self.purchase_invoice - fixed_asset_account, cwip_account = self.get_asset_accounts() - cwip_enabled = is_cwip_accounting_enabled(self.asset_category) - # check if expense already has been booked in case of cwip was enabled after purchasing asset - expense_booked = False - cwip_booked = False - - if asset_bought_with_invoice: - expense_booked = frappe.db.sql("""SELECT name FROM `tabGL Entry` WHERE voucher_no = %s and account = %s""", - (purchase_document, fixed_asset_account), as_dict=1) - else: - cwip_booked = frappe.db.sql("""SELECT name FROM `tabGL Entry` WHERE voucher_no = %s and account = %s""", - (purchase_document, cwip_account), as_dict=1) - - if cwip_enabled and (expense_booked or not cwip_booked): - # if expense has already booked from invoice or cwip is booked from receipt + if not purchase_document: return False - elif not cwip_enabled and (not expense_booked or cwip_booked): - # if cwip is disabled but expense hasn't been booked yet - return True - elif cwip_enabled: - # default condition - return True + + asset_bought_with_invoice = (purchase_document == self.purchase_invoice) + fixed_asset_account = self.get_fixed_asset_account() + + cwip_enabled = is_cwip_accounting_enabled(self.asset_category) + cwip_account = self.get_cwip_account(cwip_enabled=cwip_enabled) + + query = """SELECT name FROM `tabGL Entry` WHERE voucher_no = %s and account = %s""" + if asset_bought_with_invoice: + # with invoice purchase either expense or cwip has been booked + expense_booked = frappe.db.sql(query, (purchase_document, fixed_asset_account), as_dict=1) + if expense_booked: + # if expense is already booked from invoice then do not make gl entries regardless of cwip enabled/disabled + return False + + cwip_booked = frappe.db.sql(query, (purchase_document, cwip_account), as_dict=1) + if cwip_booked: + # if cwip is booked from invoice then make gl entries regardless of cwip enabled/disabled + return True + else: + # with receipt purchase either cwip has been booked or no entries have been made + if not cwip_account: + # if cwip account isn't available do not make gl entries + return False + + cwip_booked = frappe.db.sql(query, (purchase_document, cwip_account), as_dict=1) + # if cwip is not booked from receipt then do not make gl entries + # if cwip is booked from receipt then make gl entries + return cwip_booked def get_purchase_document(self): asset_bought_with_invoice = self.purchase_invoice and frappe.db.get_value('Purchase Invoice', self.purchase_invoice, 'update_stock') purchase_document = self.purchase_invoice if asset_bought_with_invoice else self.purchase_receipt return purchase_document + + def get_fixed_asset_account(self): + return get_asset_category_account('fixed_asset_account', None, self.name, None, self.asset_category, self.company) + + def get_cwip_account(self, cwip_enabled=False): + cwip_account = None + try: + cwip_account = get_asset_account("capital_work_in_progress_account", self.name, self.asset_category, self.company) + except: + # if no cwip account found in category or company and "cwip is enabled" then raise else silently pass + if cwip_enabled: + raise - def get_asset_accounts(self): - fixed_asset_account = get_asset_category_account('fixed_asset_account', asset=self.name, - asset_category = self.asset_category, company = self.company) - - cwip_account = get_asset_account("capital_work_in_progress_account", - self.name, self.asset_category, self.company) - - return fixed_asset_account, cwip_account + return cwip_account def make_gl_entries(self): gl_entries = [] purchase_document = self.get_purchase_document() - fixed_asset_account, cwip_account = self.get_asset_accounts() + fixed_asset_account, cwip_account = self.get_fixed_asset_account(), self.get_cwip_account() if (purchase_document and self.purchase_receipt_amount and self.available_for_use_date <= nowdate()): diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py index 52039c183b..a0d76031fc 100644 --- a/erpnext/assets/doctype/asset/test_asset.py +++ b/erpnext/assets/doctype/asset/test_asset.py @@ -9,6 +9,7 @@ from frappe.utils import cstr, nowdate, getdate, flt, get_last_day, add_days, ad from erpnext.assets.doctype.asset.depreciation import post_depreciation_entries, scrap_asset, restore_asset from erpnext.assets.doctype.asset.asset import make_sales_invoice from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt +from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice from erpnext.stock.doctype.purchase_receipt.purchase_receipt import make_purchase_invoice as make_invoice class TestAsset(unittest.TestCase): @@ -558,81 +559,6 @@ class TestAsset(unittest.TestCase): self.assertEqual(gle, expected_gle) - def test_gle_with_cwip_toggling(self): - # TEST: purchase an asset with cwip enabled and then disable cwip and try submitting the asset - frappe.db.set_value("Asset Category", "Computers", "enable_cwip_accounting", 1) - - pr = make_purchase_receipt(item_code="Macbook Pro", - qty=1, rate=5000, do_not_submit=True, location="Test Location") - pr.set('taxes', [{ - 'category': 'Total', - 'add_deduct_tax': 'Add', - 'charge_type': 'On Net Total', - 'account_head': '_Test Account Service Tax - _TC', - 'description': '_Test Account Service Tax', - 'cost_center': 'Main - _TC', - 'rate': 5.0 - }, { - 'category': 'Valuation and Total', - 'add_deduct_tax': 'Add', - 'charge_type': 'On Net Total', - 'account_head': '_Test Account Shipping Charges - _TC', - 'description': '_Test Account Shipping Charges', - 'cost_center': 'Main - _TC', - 'rate': 5.0 - }]) - pr.submit() - expected_gle = ( - ("Asset Received But Not Billed - _TC", 0.0, 5250.0), - ("CWIP Account - _TC", 5250.0, 0.0) - ) - pr_gle = frappe.db.sql("""select account, debit, credit from `tabGL Entry` - where voucher_type='Purchase Receipt' and voucher_no = %s - order by account""", pr.name) - self.assertEqual(pr_gle, expected_gle) - - pi = make_invoice(pr.name) - pi.submit() - expected_gle = ( - ("_Test Account Service Tax - _TC", 250.0, 0.0), - ("_Test Account Shipping Charges - _TC", 250.0, 0.0), - ("Asset Received But Not Billed - _TC", 5250.0, 0.0), - ("Creditors - _TC", 0.0, 5500.0), - ("Expenses Included In Asset Valuation - _TC", 0.0, 250.0), - ) - pi_gle = frappe.db.sql("""select account, debit, credit from `tabGL Entry` - where voucher_type='Purchase Invoice' and voucher_no = %s - order by account""", pi.name) - self.assertEqual(pi_gle, expected_gle) - - asset = frappe.db.get_value('Asset', {'purchase_receipt': pr.name, 'docstatus': 0}, 'name') - asset_doc = frappe.get_doc('Asset', asset) - month_end_date = get_last_day(nowdate()) - asset_doc.available_for_use_date = nowdate() if nowdate() != month_end_date else add_days(nowdate(), -15) - self.assertEqual(asset_doc.gross_purchase_amount, 5250.0) - asset_doc.append("finance_books", { - "expected_value_after_useful_life": 200, - "depreciation_method": "Straight Line", - "total_number_of_depreciations": 3, - "frequency_of_depreciation": 10, - "depreciation_start_date": month_end_date - }) - - # disable cwip and try submitting - frappe.db.set_value("Asset Category", "Computers", "enable_cwip_accounting", 0) - asset_doc.submit() - # asset should have gl entries even if cwip is disabled - expected_gle = ( - ("_Test Fixed Asset - _TC", 5250.0, 0.0), - ("CWIP Account - _TC", 0.0, 5250.0) - ) - gle = frappe.db.sql("""select account, debit, credit from `tabGL Entry` - where voucher_type='Asset' and voucher_no = %s - order by account""", asset_doc.name) - self.assertEqual(gle, expected_gle) - - frappe.db.set_value("Asset Category", "Computers", "enable_cwip_accounting", 1) - def test_expense_head(self): pr = make_purchase_receipt(item_code="Macbook Pro", qty=2, rate=200000.0, location="Test Location") @@ -640,6 +566,74 @@ class TestAsset(unittest.TestCase): doc = make_invoice(pr.name) self.assertEquals('Asset Received But Not Billed - _TC', doc.items[0].expense_account) + + def test_asset_cwip_toggling_cases(self): + cwip = frappe.db.get_value("Asset Category", "Computers", "enable_cwip_accounting") + name = frappe.db.get_value("Asset Category Account", filters={"parent": "Computers"}, fieldname=["name"]) + cwip_acc = "CWIP Account - _TC" + + frappe.db.set_value("Asset Category", "Computers", "enable_cwip_accounting", 0) + frappe.db.set_value("Asset Category Account", name, "capital_work_in_progress_account", "") + frappe.db.get_value("Company", "_Test Company", "capital_work_in_progress_account", "") + + # case 0 -- PI with cwip disable, Asset with cwip disabled, No cwip account set + pi = make_purchase_invoice(item_code="Macbook Pro", qty=1, rate=200000.0, location="Test Location", update_stock=1) + asset = frappe.db.get_value('Asset', {'purchase_invoice': pi.name, 'docstatus': 0}, 'name') + asset_doc = frappe.get_doc('Asset', asset) + asset_doc.available_for_use_date = nowdate() + asset_doc.calculate_depreciation = 0 + asset_doc.submit() + gle = frappe.db.sql("""select name from `tabGL Entry` where voucher_type='Asset' and voucher_no = %s""", asset_doc.name) + self.assertFalse(gle) + + # case 1 -- PR with cwip disabled, Asset with cwip enabled + pr = make_purchase_receipt(item_code="Macbook Pro", qty=1, rate=200000.0, location="Test Location") + frappe.db.set_value("Asset Category", "Computers", "enable_cwip_accounting", 1) + frappe.db.set_value("Asset Category Account", name, "capital_work_in_progress_account", cwip_acc) + asset = frappe.db.get_value('Asset', {'purchase_receipt': pr.name, 'docstatus': 0}, 'name') + asset_doc = frappe.get_doc('Asset', asset) + asset_doc.available_for_use_date = nowdate() + asset_doc.calculate_depreciation = 0 + asset_doc.submit() + gle = frappe.db.sql("""select name from `tabGL Entry` where voucher_type='Asset' and voucher_no = %s""", asset_doc.name) + self.assertFalse(gle) + + # case 2 -- PR with cwip enabled, Asset with cwip disabled + pr = make_purchase_receipt(item_code="Macbook Pro", qty=1, rate=200000.0, location="Test Location") + frappe.db.set_value("Asset Category", "Computers", "enable_cwip_accounting", 0) + asset = frappe.db.get_value('Asset', {'purchase_receipt': pr.name, 'docstatus': 0}, 'name') + asset_doc = frappe.get_doc('Asset', asset) + asset_doc.available_for_use_date = nowdate() + asset_doc.calculate_depreciation = 0 + asset_doc.submit() + gle = frappe.db.sql("""select name from `tabGL Entry` where voucher_type='Asset' and voucher_no = %s""", asset_doc.name) + self.assertTrue(gle) + + # case 3 -- PI with cwip disabled, Asset with cwip enabled + pi = make_purchase_invoice(item_code="Macbook Pro", qty=1, rate=200000.0, location="Test Location", update_stock=1) + frappe.db.set_value("Asset Category", "Computers", "enable_cwip_accounting", 1) + asset = frappe.db.get_value('Asset', {'purchase_invoice': pi.name, 'docstatus': 0}, 'name') + asset_doc = frappe.get_doc('Asset', asset) + asset_doc.available_for_use_date = nowdate() + asset_doc.calculate_depreciation = 0 + asset_doc.submit() + gle = frappe.db.sql("""select name from `tabGL Entry` where voucher_type='Asset' and voucher_no = %s""", asset_doc.name) + self.assertFalse(gle) + + # case 4 -- PI with cwip enabled, Asset with cwip disabled + pi = make_purchase_invoice(item_code="Macbook Pro", qty=1, rate=200000.0, location="Test Location", update_stock=1) + frappe.db.set_value("Asset Category", "Computers", "enable_cwip_accounting", 0) + asset = frappe.db.get_value('Asset', {'purchase_invoice': pi.name, 'docstatus': 0}, 'name') + asset_doc = frappe.get_doc('Asset', asset) + asset_doc.available_for_use_date = nowdate() + asset_doc.calculate_depreciation = 0 + asset_doc.submit() + gle = frappe.db.sql("""select name from `tabGL Entry` where voucher_type='Asset' and voucher_no = %s""", asset_doc.name) + self.assertTrue(gle) + + frappe.db.set_value("Asset Category", "Computers", "enable_cwip_accounting", cwip) + frappe.db.set_value("Asset Category Account", name, "capital_work_in_progress_account", cwip_acc) + frappe.db.get_value("Company", "_Test Company", "capital_work_in_progress_account", cwip_acc) def create_asset_data(): if not frappe.db.exists("Asset Category", "Computers"): diff --git a/erpnext/assets/doctype/asset_category/asset_category.py b/erpnext/assets/doctype/asset_category/asset_category.py index 9a33fc14ac..46620d56e9 100644 --- a/erpnext/assets/doctype/asset_category/asset_category.py +++ b/erpnext/assets/doctype/asset_category/asset_category.py @@ -5,7 +5,7 @@ from __future__ import unicode_literals import frappe from frappe import _ -from frappe.utils import cint +from frappe.utils import cint, get_link_to_form from frappe.model.document import Document class AssetCategory(Document): @@ -13,6 +13,7 @@ class AssetCategory(Document): self.validate_finance_books() self.validate_account_types() self.validate_account_currency() + self.valide_cwip_account() def validate_finance_books(self): for d in self.finance_books: @@ -58,6 +59,21 @@ class AssetCategory(Document): frappe.throw(_("Row #{}: {} of {} should be {}. Please modify the account or select a different account.") .format(d.idx, frappe.unscrub(key_to_match), frappe.bold(selected_account), frappe.bold(expected_key_type)), title=_("Invalid Account")) + + def valide_cwip_account(self): + if self.enable_cwip_accounting: + missing_cwip_accounts_for_company = [] + for d in self.accounts: + if (not d.capital_work_in_progress_account and + not frappe.db.get_value("Company", d.company_name, "capital_work_in_progress_account")): + missing_cwip_accounts_for_company.append(get_link_to_form("Company", d.company_name)) + + if missing_cwip_accounts_for_company: + msg = _("""To enable Capital Work in Progress Accounting, """) + msg += _("""you must select Capital Work in Progress Account in accounts table""") + msg += "

" + msg += _("You can also set default CWIP account in Company {}").format(", ".join(missing_cwip_accounts_for_company)) + frappe.throw(msg, title=_("Missing Account")) @frappe.whitelist() diff --git a/erpnext/assets/doctype/asset_category/test_asset_category.py b/erpnext/assets/doctype/asset_category/test_asset_category.py index b32f9b5020..39b79d6c50 100644 --- a/erpnext/assets/doctype/asset_category/test_asset_category.py +++ b/erpnext/assets/doctype/asset_category/test_asset_category.py @@ -26,4 +26,22 @@ class TestAssetCategory(unittest.TestCase): asset_category.insert() except frappe.DuplicateEntryError: pass - \ No newline at end of file + + def test_cwip_accounting(self): + company_cwip_acc = frappe.db.get_value("Company", "_Test Company", "capital_work_in_progress_account") + frappe.db.set_value("Company", "_Test Company", "capital_work_in_progress_account", "") + + asset_category = frappe.new_doc("Asset Category") + asset_category.asset_category_name = "Computers" + asset_category.enable_cwip_accounting = 1 + + asset_category.total_number_of_depreciations = 3 + asset_category.frequency_of_depreciation = 3 + asset_category.append("accounts", { + "company_name": "_Test Company", + "fixed_asset_account": "_Test Fixed Asset - _TC", + "accumulated_depreciation_account": "_Test Accumulated Depreciations - _TC", + "depreciation_expense_account": "_Test Depreciations - _TC" + }) + + self.assertRaises(frappe.ValidationError, asset_category.insert) \ No newline at end of file diff --git a/erpnext/manufacturing/doctype/production_plan/production_plan.py b/erpnext/manufacturing/doctype/production_plan/production_plan.py index c8892376b7..5b14d054af 100644 --- a/erpnext/manufacturing/doctype/production_plan/production_plan.py +++ b/erpnext/manufacturing/doctype/production_plan/production_plan.py @@ -381,7 +381,6 @@ class ProductionPlan(Document): "transaction_date": nowdate(), "status": "Draft", "company": self.company, - "requested_by": frappe.session.user, 'material_request_type': material_request_type, 'customer': item_doc.customer or '' }) diff --git a/erpnext/manufacturing/doctype/work_order/work_order.py b/erpnext/manufacturing/doctype/work_order/work_order.py index b7d968e974..3173b6c483 100644 --- a/erpnext/manufacturing/doctype/work_order/work_order.py +++ b/erpnext/manufacturing/doctype/work_order/work_order.py @@ -434,7 +434,7 @@ class WorkOrder(Document): elif flt(d.completed_qty) <= max_allowed_qty_for_wo: d.status = "Completed" else: - frappe.throw(_("Completed Qty can not be greater than 'Qty to Manufacture'")) + frappe.throw(_("Completed Qty cannot be greater than 'Qty to Manufacture'")) def set_actual_dates(self): if self.get("operations"): diff --git a/erpnext/payroll/doctype/salary_component/salary_component.json b/erpnext/payroll/doctype/salary_component/salary_component.json index 225b048293..c97e45cd53 100644 --- a/erpnext/payroll/doctype/salary_component/salary_component.json +++ b/erpnext/payroll/doctype/salary_component/salary_component.json @@ -217,7 +217,7 @@ "fieldname": "help", "fieldtype": "HTML", "label": "Help", - "options": "

Help

\n\n

Notes:

\n\n
    \n
  1. Use field base for using base salary of the Employee
  2. \n
  3. Use Salary Component abbreviations in conditions and formulas. BS = Basic Salary
  4. \n
  5. Use field name for employee details in conditions and formulas. Employment Type = employment_typeBranch = branch
  6. \n
  7. Use field name from Salary Slip in conditions and formulas. Payment Days = payment_daysLeave without pay = leave_without_pay
  8. \n
  9. Direct Amount can also be entered based on Condtion. See example 3
\n\n

Examples

\n
    \n
  1. Calculating Basic Salary based on base\n
    Condition: base < 10000
    \n
    Formula: base * .2
  2. \n
  3. Calculating HRA based on Basic SalaryBS \n
    Condition: BS > 2000
    \n
    Formula: BS * .1
  4. \n
  5. Calculating TDS based on Employment Typeemployment_type \n
    Condition: employment_type==\"Intern\"
    \n
    Amount: 1000
  6. \n
" + "options": "

Help

\n\n

Notes:

\n\n
    \n
  1. Use field base for using base salary of the Employee
  2. \n
  3. Use Salary Component abbreviations in conditions and formulas. BS = Basic Salary
  4. \n
  5. Use field name for employee details in conditions and formulas. Employment Type = employment_typeBranch = branch
  6. \n
  7. Use field name from Salary Slip in conditions and formulas. Payment Days = payment_daysLeave without pay = leave_without_pay
  8. \n
  9. Direct Amount can also be entered based on Condition. See example 3
\n\n

Examples

\n
    \n
  1. Calculating Basic Salary based on base\n
    Condition: base < 10000
    \n
    Formula: base * .2
  2. \n
  3. Calculating HRA based on Basic SalaryBS \n
    Condition: BS > 2000
    \n
    Formula: BS * .1
  4. \n
  5. Calculating TDS based on Employment Typeemployment_type \n
    Condition: employment_type==\"Intern\"
    \n
    Amount: 1000
  6. \n
" }, { "default": "0", @@ -238,14 +238,13 @@ "depends_on": "eval:doc.type == \"Deduction\"", "fieldname": "is_income_tax_component", "fieldtype": "Check", - "label": "Is Income Tax Component", - "show_days": 1, - "show_seconds": 1 + "label": "Is Income Tax Component" } ], "icon": "fa fa-flag", + "index_web_pages_for_search": 1, "links": [], - "modified": "2020-06-22 15:39:20.826565", + "modified": "2020-10-07 20:38:33.795853", "modified_by": "Administrator", "module": "Payroll", "name": "Salary Component", diff --git a/erpnext/payroll/doctype/salary_detail/salary_detail.json b/erpnext/payroll/doctype/salary_detail/salary_detail.json index cc87caeae1..eedb56ec08 100644 --- a/erpnext/payroll/doctype/salary_detail/salary_detail.json +++ b/erpnext/payroll/doctype/salary_detail/salary_detail.json @@ -117,7 +117,7 @@ "depends_on": "eval:doc.is_flexible_benefit != 1", "fieldname": "section_break_2", "fieldtype": "Section Break", - "label": "Condtion and formula" + "label": "Condition and formula" }, { "allow_on_submit": 1, @@ -206,38 +206,28 @@ "collapsible": 1, "fieldname": "section_break_5", "fieldtype": "Section Break", - "label": "Component properties and references ", - "show_days": 1, - "show_seconds": 1 + "label": "Component properties and references " }, { "fieldname": "column_break_11", - "fieldtype": "Column Break", - "show_days": 1, - "show_seconds": 1 + "fieldtype": "Column Break" }, { "fieldname": "section_break_19", - "fieldtype": "Section Break", - "show_days": 1, - "show_seconds": 1 + "fieldtype": "Section Break" }, { "fieldname": "column_break_18", - "fieldtype": "Column Break", - "show_days": 1, - "show_seconds": 1 + "fieldtype": "Column Break" }, { "fieldname": "column_break_24", - "fieldtype": "Column Break", - "show_days": 1, - "show_seconds": 1 + "fieldtype": "Column Break" } ], "istable": 1, "links": [], - "modified": "2020-07-01 12:13:41.956495", + "modified": "2020-10-07 20:39:41.619283", "modified_by": "Administrator", "module": "Payroll", "name": "Salary Detail", diff --git a/erpnext/selling/doctype/quotation/tests/test_quotation.js b/erpnext/selling/doctype/quotation/tests/test_quotation.js index d69d799d0d..ad942fe497 100644 --- a/erpnext/selling/doctype/quotation/tests/test_quotation.js +++ b/erpnext/selling/doctype/quotation/tests/test_quotation.js @@ -46,7 +46,7 @@ QUnit.test("test: quotation", function (assert) { assert.ok(cur_frm.doc.items[0].rate == 200, "Price Changed Manually"); assert.equal(cur_frm.doc.total, 1000, "New Total Calculated"); - // Check Terms and Condtions + // Check Terms and Conditions assert.ok(cur_frm.doc.tc_name == "Test Term 1", "Terms and Conditions Checked"); assert.ok(cur_frm.doc.payment_terms_template, "Payment Terms Template is correct"); diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py index f88289871e..62a5d4e68f 100755 --- a/erpnext/selling/doctype/sales_order/sales_order.py +++ b/erpnext/selling/doctype/sales_order/sales_order.py @@ -989,7 +989,6 @@ def make_raw_material_request(items, company, sales_order, project=None): doctype = 'Material Request', transaction_date = nowdate(), company = company, - requested_by = frappe.session.user, material_request_type = 'Purchase' )) for item in raw_materials: diff --git a/erpnext/stock/doctype/item_price/item_price.py b/erpnext/stock/doctype/item_price/item_price.py index 8e39eb5037..51b47c50a3 100644 --- a/erpnext/stock/doctype/item_price/item_price.py +++ b/erpnext/stock/doctype/item_price/item_price.py @@ -50,16 +50,18 @@ class ItemPrice(Document): def check_duplicates(self): conditions = "where item_code=%(item_code)s and price_list=%(price_list)s and name != %(name)s" + condition_data_dict = dict(item_code=self.item_code, price_list=self.price_list, name=self.name) for field in ['uom', 'valid_from', 'valid_upto', 'packing_unit', 'customer', 'supplier']: if self.get(field): conditions += " and {0} = %({1})s".format(field, field) + condition_data_dict[field] = self.get(field) price_list_rate = frappe.db.sql(""" SELECT price_list_rate FROM `tabItem Price` - {conditions} """.format(conditions=conditions), self.as_dict()) + {conditions} """.format(conditions=conditions), condition_data_dict) if price_list_rate : frappe.throw(_("Item Price appears multiple times based on Price List, Supplier/Customer, Currency, Item, UOM, Qty and Dates."), ItemPriceDuplicateItem) diff --git a/erpnext/stock/doctype/material_request/material_request.js b/erpnext/stock/doctype/material_request/material_request.js index 3c4e35349e..8c470988c8 100644 --- a/erpnext/stock/doctype/material_request/material_request.js +++ b/erpnext/stock/doctype/material_request/material_request.js @@ -280,7 +280,8 @@ frappe.ui.form.on('Material Request', { fieldname:'default_supplier', fieldtype: 'Link', options: 'Supplier', - description: __('Select a Supplier from the Default Supplier List of the items below.'), + description: __('Select a Supplier from the Default Suppliers of the items below. \ + On selection, a Purchase Order will be made against items belonging to the selected Supplier only.'), get_query: () => { return{ query: "erpnext.stock.doctype.material_request.material_request.get_default_supplier_query", diff --git a/erpnext/stock/doctype/material_request/material_request.json b/erpnext/stock/doctype/material_request/material_request.json index 44503d22a3..d73349dd39 100644 --- a/erpnext/stock/doctype/material_request/material_request.json +++ b/erpnext/stock/doctype/material_request/material_request.json @@ -13,7 +13,9 @@ "material_request_type", "transfer_status", "customer", + "status", "column_break_2", + "transaction_date", "schedule_date", "company", "amended_from", @@ -25,11 +27,8 @@ "scan_barcode", "items", "more_info", - "requested_by", - "transaction_date", - "column_break2", - "status", "per_ordered", + "column_break2", "per_received", "printing_details", "letter_head", @@ -82,7 +81,8 @@ "fieldname": "customer", "fieldtype": "Link", "label": "Customer", - "options": "Customer" + "options": "Customer", + "print_hide": 1 }, { "fieldname": "column_break_2", @@ -92,12 +92,12 @@ "allow_on_submit": 1, "fieldname": "schedule_date", "fieldtype": "Date", + "in_list_view": 1, "label": "Required By" }, { "fieldname": "company", "fieldtype": "Link", - "in_list_view": 1, "in_standard_filter": 1, "label": "Company", "oldfieldname": "company", @@ -153,18 +153,10 @@ "oldfieldtype": "Section Break", "options": "fa fa-file-text" }, - { - "fieldname": "requested_by", - "fieldtype": "Data", - "in_standard_filter": 1, - "label": "Requested For", - "options": "Email" - }, { "default": "Today", "fieldname": "transaction_date", "fieldtype": "Date", - "in_list_view": 1, "label": "Transaction Date", "no_copy": 1, "oldfieldname": "transaction_date", @@ -197,7 +189,7 @@ "width": "100px" }, { - "depends_on": "eval:doc.docstatus==1", + "depends_on": "eval:doc.per_ordered > 0", "fieldname": "per_ordered", "fieldtype": "Percent", "label": "% Ordered", @@ -208,7 +200,7 @@ "read_only": 1 }, { - "depends_on": "eval:doc.docstatus==1", + "depends_on": "eval:doc.per_received > 0", "fieldname": "per_received", "fieldtype": "Percent", "label": "% Received", @@ -282,13 +274,15 @@ }, { "fieldname": "warehouse_section", - "fieldtype": "Section Break" + "fieldtype": "Section Break", + "label": "Warehouse" }, { - "description": "Sets 'For Warehouse' in each row of the Items table.", + "description": "Sets 'Target Warehouse' in each row of the Items table.", "fieldname": "set_warehouse", "fieldtype": "Link", - "label": "Set Warehouse", + "in_list_view": 1, + "label": "Set Target Warehouse", "options": "Warehouse" }, { @@ -300,9 +294,10 @@ }, { "depends_on": "eval:doc.material_request_type == 'Material Transfer'", + "description": "Sets 'Source Warehouse' in each row of the Items table.", "fieldname": "set_from_warehouse", "fieldtype": "Link", - "label": "Set From Warehouse", + "label": "Set Source Warehouse", "options": "Warehouse" }, { @@ -319,7 +314,7 @@ "idx": 70, "is_submittable": 1, "links": [], - "modified": "2020-08-10 13:27:54.891058", + "modified": "2020-09-19 01:04:09.285862", "modified_by": "Administrator", "module": "Stock", "name": "Material Request", diff --git a/erpnext/stock/doctype/material_request/material_request_dashboard.py b/erpnext/stock/doctype/material_request/material_request_dashboard.py index 0e4fb7a6dd..f3e5e5db25 100644 --- a/erpnext/stock/doctype/material_request/material_request_dashboard.py +++ b/erpnext/stock/doctype/material_request/material_request_dashboard.py @@ -7,7 +7,7 @@ def get_data(): 'fieldname': 'material_request', 'transactions': [ { - 'label': _('Related'), + 'label': _('Reference'), 'items': ['Request for Quotation', 'Supplier Quotation', 'Purchase Order'] }, { diff --git a/erpnext/stock/doctype/material_request_item/material_request_item.json b/erpnext/stock/doctype/material_request_item/material_request_item.json index 32bd4a0a57..25bbbbd4b3 100644 --- a/erpnext/stock/doctype/material_request_item/material_request_item.json +++ b/erpnext/stock/doctype/material_request_item/material_request_item.json @@ -13,12 +13,10 @@ "schedule_date", "section_break_4", "description", + "column_break_12", "item_group", "brand", - "image_section", "image", - "column_break_12", - "manufacturer_part_no", "quantity_and_warehouse", "qty", "stock_uom", @@ -28,12 +26,26 @@ "uom", "conversion_factor", "stock_qty", + "qty_info_sec_break", + "min_order_qty", + "projected_qty", + "qty_info_col_break", + "actual_qty", + "ordered_qty", + "received_qty", "rate_and_amount_section_break", "rate", "col_break3", "amount", "manufacture_details", "manufacturer", + "manufacturer_part_no", + "col_break_mfg", + "bom_no", + "accounting_dimensions_section", + "project", + "dimension_col_break", + "cost_center", "more_info", "lead_time_date", "sales_order", @@ -41,19 +53,7 @@ "production_plan", "material_request_plan_item", "col_break4", - "min_order_qty", - "projected_qty", - "actual_qty", - "ordered_qty", - "received_qty", - "accounting_details", "expense_account", - "accounting_dimensions_section", - "project", - "dimension_col_break", - "cost_center", - "section_break_37", - "bom_no", "section_break_46", "page_break" ], @@ -164,7 +164,7 @@ "fieldname": "warehouse", "fieldtype": "Link", "in_list_view": 1, - "label": "For Warehouse", + "label": "Target Warehouse", "oldfieldname": "warehouse", "oldfieldtype": "Link", "options": "Warehouse", @@ -191,12 +191,14 @@ { "fieldname": "rate", "fieldtype": "Currency", - "label": "Rate" + "label": "Rate", + "print_hide": 1 }, { "fieldname": "amount", "fieldtype": "Currency", "label": "Amount", + "print_hide": 1, "read_only": 1 }, { @@ -326,6 +328,7 @@ "report_hide": 1 }, { + "depends_on": "eval:doc.docstatus==1", "fieldname": "ordered_qty", "fieldtype": "Float", "label": "Completed Qty", @@ -335,12 +338,6 @@ "print_hide": 1, "read_only": 1 }, - { - "collapsible": 1, - "fieldname": "accounting_details", - "fieldtype": "Section Break", - "label": "Accounting Details" - }, { "fieldname": "expense_account", "fieldtype": "Link", @@ -367,21 +364,10 @@ "print_hide": 1 }, { - "collapsible": 1, - "fieldname": "image_section", - "fieldtype": "Section Break", - "label": "Image" - }, - { - "depends_on": "eval:parent.material_request_type == \"Manufacture\"", - "fieldname": "section_break_37", - "fieldtype": "Section Break", - "label": "Manufacturing" - }, - { + "depends_on": "eval:doc.docstatus==1", "fieldname": "received_qty", "fieldtype": "Float", - "label": "Received Quantity", + "label": "Received Qty", "no_copy": 1, "print_hide": 1, "read_only": 1 @@ -398,6 +384,7 @@ }, { "collapsible": 1, + "depends_on": "eval:in_list([\"Manufacture\", \"Purchase\"], parent.material_request_type)", "fieldname": "manufacture_details", "fieldtype": "Section Break", "label": "Manufacture" @@ -430,10 +417,11 @@ "depends_on": "eval:parent.material_request_type == \"Material Transfer\"", "fieldname": "from_warehouse", "fieldtype": "Link", - "label": "Source Warehouse (Material Transfer)", + "label": "Source Warehouse", "options": "Warehouse" }, { + "allow_on_submit": 1, "fieldname": "bom_no", "fieldtype": "Link", "label": "BOM No", @@ -444,12 +432,25 @@ { "fieldname": "section_break_46", "fieldtype": "Section Break" + }, + { + "fieldname": "col_break_mfg", + "fieldtype": "Column Break" + }, + { + "fieldname": "qty_info_sec_break", + "fieldtype": "Section Break" + }, + { + "fieldname": "qty_info_col_break", + "fieldtype": "Column Break" } ], "idx": 1, + "index_web_pages_for_search": 1, "istable": 1, "links": [], - "modified": "2020-05-15 09:00:00.992835", + "modified": "2020-10-02 11:44:36.553064", "modified_by": "Administrator", "module": "Stock", "name": "Material Request Item",