From 447f0e495a56335d3b7e3b508736ae2289498600 Mon Sep 17 00:00:00 2001 From: Ranjith Date: Wed, 16 May 2018 12:13:46 +0530 Subject: [PATCH 01/18] remove duplicate fields --- .../salary_component/salary_component.json | 318 +----------------- 1 file changed, 2 insertions(+), 316 deletions(-) diff --git a/erpnext/hr/doctype/salary_component/salary_component.json b/erpnext/hr/doctype/salary_component/salary_component.json index f08b1d7a0b..5bb69c7cad 100644 --- a/erpnext/hr/doctype/salary_component/salary_component.json +++ b/erpnext/hr/doctype/salary_component/salary_component.json @@ -893,320 +893,6 @@ "translatable": 0, "unique": 0 }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "help", - "fieldtype": "HTML", - "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": "Help", - "length": 0, - "no_copy": 0, - "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
", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 1, - "columns": 0, - "fieldname": "condition_and_formula", - "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": "Condition and Formula", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "condition", - "fieldtype": "Code", - "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": "Condition", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "description": "If selected, the value specified or calculated in this component will not contribute to the earnings or deductions. However, it's value can be referenced by other components that can be added or deducted. ", - "fieldname": "statistical_component", - "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": "Statistical Component", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "depends_on_lwp", - "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": "Depends on Leave Without Pay", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "do_not_include_in_total", - "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": "Do not include in total", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "1", - "fieldname": "amount_based_on_formula", - "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": "Amount based on formula", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:doc.amount_based_on_formula!==0", - "fieldname": "formula", - "fieldtype": "Code", - "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": "Formula", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:doc.amount_based_on_formula!==1", - "fieldname": "amount", - "fieldtype": "Currency", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Amount", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_28", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, { "allow_bulk_edit": 0, "allow_on_submit": 0, @@ -1251,7 +937,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2018-05-09 17:35:11.073733", + "modified": "2018-05-16 12:13:12.831051", "modified_by": "Administrator", "module": "HR", "name": "Salary Component", @@ -1286,4 +972,4 @@ "sort_order": "DESC", "track_changes": 0, "track_seen": 0 -} +} \ No newline at end of file From db120fb0bc7d2fe4ab6358cb9b0734b061411a07 Mon Sep 17 00:00:00 2001 From: Ranjith Date: Wed, 16 May 2018 12:17:16 +0530 Subject: [PATCH 02/18] Salary Component - fields is_tax_applicable, is_payable --- .../salary_component/salary_component.json | 67 ++++++++++++++++++- 1 file changed, 66 insertions(+), 1 deletion(-) diff --git a/erpnext/hr/doctype/salary_component/salary_component.json b/erpnext/hr/doctype/salary_component/salary_component.json index 5bb69c7cad..cf85af4a76 100644 --- a/erpnext/hr/doctype/salary_component/salary_component.json +++ b/erpnext/hr/doctype/salary_component/salary_component.json @@ -108,6 +108,70 @@ "translatable": 0, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "eval:doc.type==\"Earning\"", + "fieldname": "is_tax_applicable", + "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": "Is Tax Applicable", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "default": "1", + "fieldname": "is_payable", + "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": "Is Payable", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, { "allow_bulk_edit": 0, "allow_on_submit": 0, @@ -554,6 +618,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "depends_on": "is_payable", "fieldname": "section_break_5", "fieldtype": "Section Break", "hidden": 0, @@ -937,7 +1002,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2018-05-16 12:13:12.831051", + "modified": "2018-05-16 12:15:43.117948", "modified_by": "Administrator", "module": "HR", "name": "Salary Component", From 4bbf705e58be1acc3591ca324b29281d61fa7c7f Mon Sep 17 00:00:00 2001 From: Ranjith Date: Wed, 16 May 2018 12:17:57 +0530 Subject: [PATCH 03/18] fix intendation --- erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py | 3 +-- erpnext/accounts/utils.py | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py index 9599d1f53f..08e3d10fd8 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -750,7 +750,7 @@ class PurchaseInvoice(BuyingController): self.db_set('on_hold', 0) self.db_set('release_date', None) - def set_tax_withholding(self): + def set_tax_withholding(self): """ 1. Get TDS Configurations against Supplier """ @@ -812,4 +812,3 @@ def block_invoice(name, hold_comment): def make_inter_company_sales_invoice(source_name, target_doc=None): from erpnext.accounts.doctype.sales_invoice.sales_invoice import make_inter_company_invoice return make_inter_company_invoice("Purchase Invoice", source_name, target_doc) - diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py index 8c86887186..a33f867d12 100644 --- a/erpnext/accounts/utils.py +++ b/erpnext/accounts/utils.py @@ -602,7 +602,7 @@ def get_outstanding_invoices(party_type, party, account, condition=None): invoice = 'Sales Invoice' if erpnext.get_party_account_type(party_type) == 'Receivable' else 'Purchase Invoice' held_invoices = get_held_invoices(party_type, party) - invoice_list = frappe.db.sql(""" + invoice_list = frappe.db.sql(""" select voucher_no, voucher_type, posting_date, ifnull(sum({dr_or_cr}), 0) as invoice_amount, ( From 29e0ed3da13c1f8bff58f06d3e39a05675268280 Mon Sep 17 00:00:00 2001 From: Ranjith Date: Wed, 16 May 2018 19:10:35 +0530 Subject: [PATCH 04/18] Exemption Declaration - field total_amount --- .../employee_tax_exemption_declaration.json | 33 ++++++++++++++++++- .../employee_tax_exemption_declaration.py | 3 ++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/erpnext/hr/doctype/employee_tax_exemption_declaration/employee_tax_exemption_declaration.json b/erpnext/hr/doctype/employee_tax_exemption_declaration/employee_tax_exemption_declaration.json index 9dee848029..c5691f72ee 100644 --- a/erpnext/hr/doctype/employee_tax_exemption_declaration/employee_tax_exemption_declaration.json +++ b/erpnext/hr/doctype/employee_tax_exemption_declaration/employee_tax_exemption_declaration.json @@ -139,6 +139,37 @@ "translatable": 0, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "total_exemption_amount", + "fieldtype": "Currency", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Total Exemption Amount", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 1, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, { "allow_bulk_edit": 0, "allow_on_submit": 0, @@ -243,7 +274,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2018-05-15 16:16:46.075493", + "modified": "2018-05-16 19:03:57.624215", "modified_by": "Administrator", "module": "HR", "name": "Employee Tax Exemption Declaration", diff --git a/erpnext/hr/doctype/employee_tax_exemption_declaration/employee_tax_exemption_declaration.py b/erpnext/hr/doctype/employee_tax_exemption_declaration/employee_tax_exemption_declaration.py index 52746d4cff..22e1638751 100644 --- a/erpnext/hr/doctype/employee_tax_exemption_declaration/employee_tax_exemption_declaration.py +++ b/erpnext/hr/doctype/employee_tax_exemption_declaration/employee_tax_exemption_declaration.py @@ -19,3 +19,6 @@ class EmployeeTaxExemptionDeclaration(Document): "docstatus": 1}): frappe.throw(_("Tax Declaration of {0} for period {1} already submitted.")\ .format(self.employee, self.payroll_period), frappe.DocstatusTransitionError) + self.total_exemption_amount = 0 + for item in self.declarations: + self.total_exemption_amount += item.amount From 8e4f676c8c1ab927c438a011abb939ac12335eeb Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Wed, 16 May 2018 19:55:52 +0530 Subject: [PATCH 05/18] [Fix] onload set default employee, leave approver, company --- .../consolidated_financial_statement.py | 4 ++++ .../doctype/leave_application/leave_application.js | 14 ++++++++++++-- .../doctype/leave_application/leave_application.py | 14 +++++++++++++- 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py b/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py index 0b1fc6da84..750120b997 100644 --- a/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py +++ b/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py @@ -15,6 +15,10 @@ from erpnext.accounts.report.cash_flow.cash_flow import (get_cash_flow_accounts, def execute(filters=None): columns, data, message, chart = [], [], [], [] + + if not filters.get('company'): + return columns, data, message, chart + fiscal_year = get_fiscal_year_data(filters.get('from_fiscal_year'), filters.get('to_fiscal_year')) companies_column, companies = get_companies(filters) columns = get_columns(companies_column) diff --git a/erpnext/hr/doctype/leave_application/leave_application.js b/erpnext/hr/doctype/leave_application/leave_application.js index 5f1c8830fb..7a6b24658b 100755 --- a/erpnext/hr/doctype/leave_application/leave_application.js +++ b/erpnext/hr/doctype/leave_application/leave_application.js @@ -50,8 +50,11 @@ frappe.ui.form.on("Leave Application", { date: frm.doc.posting_date }, callback: function(r) { - if (!r.exc && r.message) { - leave_details = r.message; + if (!r.exc && r.message['leave_allocation']) { + leave_details = r.message['leave_allocation']; + } + if (!r.exc && r.message['leave_approver']) { + frm.set_value('leave_approver', r.message['leave_approver']); } } }); @@ -74,6 +77,13 @@ frappe.ui.form.on("Leave Application", { if(frm.doc.__islocal && !in_list(frappe.user_roles, "Employee")) { frm.set_intro(__("Fill the form and save it")); } + + if (!frm.doc.employee && frappe.defaults.get_user_permissions()) { + const perm = frappe.defaults.get_user_permissions(); + if (perm && perm['Employee']) { + frm.set_value('employee', perm['Employee']["docs"][0]) + } + } }, employee: function(frm) { diff --git a/erpnext/hr/doctype/leave_application/leave_application.py b/erpnext/hr/doctype/leave_application/leave_application.py index d0305c3902..c58e0cf5cc 100755 --- a/erpnext/hr/doctype/leave_application/leave_application.py +++ b/erpnext/hr/doctype/leave_application/leave_application.py @@ -374,7 +374,12 @@ def get_leave_details(employee, date): "pending_leaves": leaves_pending, "remaining_leaves": remaining_leaves} - return leave_allocation + ret = { + 'leave_allocation': leave_allocation, + 'leave_approver': get_leave_approver(employee) + } + + return ret @frappe.whitelist() def get_leave_balance_on(employee, leave_type, date, allocation_records=None, @@ -603,3 +608,10 @@ def get_approved_leaves_for_period(employee, leave_type, from_date, to_date): return leave_days +def get_leave_approver(employee, department=None): + if not department: + department = frappe.db.get_value('Employee', employee, 'department') + + if department: + return frappe.db.get_value('Department Approver', {'parent': department, + 'parentfield': 'leave_approver', 'idx': 1}, 'approver') From 1a328d02d23614d439b90fe5a203432474cf915e Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Wed, 16 May 2018 21:34:06 +0530 Subject: [PATCH 06/18] [Fix] Gl Enrty issue --- .../accounts/doctype/purchase_invoice/purchase_invoice.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py index 5d26d8a0e9..729c101a7c 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -176,7 +176,8 @@ class PurchaseInvoice(BuyingController): if self.update_stock: for d in self.get('items'): if not d.warehouse: - frappe.throw(_("Warehouse required at Row No {0}").format(d.idx)) + frappe.throw(_("Warehouse required at Row No {0}, please set default warehouse for the item {1} for the company {2}"). + format(d.idx, d.item_code, self.company)) super(PurchaseInvoice, self).validate_warehouse() @@ -390,10 +391,10 @@ class PurchaseInvoice(BuyingController): warehouse_account = get_warehouse_account_map() for item in self.get("items"): - if flt(item.base_net_amount) and item.item_code in stock_items: + if flt(item.base_net_amount): account_currency = get_account_currency(item.expense_account) - if self.update_stock and self.auto_accounting_for_stock: + if self.update_stock and self.auto_accounting_for_stock and item.item_code in stock_items: val_rate_db_precision = 6 if cint(item.precision("valuation_rate")) <= 6 else 9 # warehouse account From 976af6b422baedbb19297c8b8bc44e84a1a35329 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Wed, 16 May 2018 21:43:16 +0530 Subject: [PATCH 07/18] [Fix] Cystom buttons not showing --- erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js | 1 - 1 file changed, 1 deletion(-) diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js index c1a2c9741b..9a6deada72 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js @@ -115,7 +115,6 @@ erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({ } this.frm.toggle_reqd("supplier_warehouse", this.frm.doc.is_subcontracted==="Yes"); - var me = this; if (doc.docstatus == 1 && !doc.inter_company_invoice_reference) { frappe.model.with_doc("Supplier", me.frm.doc.supplier, function() { var supplier = frappe.model.get_doc("Supplier", me.frm.doc.supplier); From e6acd4c57aef5e964bb03403a35e098b0f76cda7 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Wed, 16 May 2018 22:12:39 +0530 Subject: [PATCH 08/18] Multiple fixes in asset --- erpnext/assets/doctype/asset/asset.js | 7 +++++++ erpnext/assets/doctype/asset/asset.py | 5 ++++- erpnext/assets/doctype/asset_movement/asset_movement.py | 6 ++---- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/erpnext/assets/doctype/asset/asset.js b/erpnext/assets/doctype/asset/asset.js index c05667a767..88e7f78a02 100644 --- a/erpnext/assets/doctype/asset/asset.js +++ b/erpnext/assets/doctype/asset/asset.js @@ -157,6 +157,13 @@ frappe.ui.form.on('Asset', { } }, + available_for_use_date: function(frm) { + $.each(frm.doc.finance_books || [], function(i, d) { + if(!d.depreciation_start_date) d.depreciation_start_date = frm.doc.available_for_use_date; + }); + refresh_field("finance_books"); + }, + is_existing_asset: function(frm) { // frm.toggle_reqd("next_depreciation_date", (!frm.doc.is_existing_asset && frm.doc.calculate_depreciation)); }, diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py index e37038a5a8..75e808870f 100644 --- a/erpnext/assets/doctype/asset/asset.py +++ b/erpnext/assets/doctype/asset/asset.py @@ -51,7 +51,7 @@ class Asset(AccountsController): def validate_in_use_date(self): if not self.available_for_use_date: - frappe.throw(_("Available for use data is required")) + frappe.throw(_("Available for use date is required")) def set_missing_values(self): if not self.asset_category: @@ -162,6 +162,9 @@ class Asset(AccountsController): frappe.throw(_("Row {0}: Expected Value After Useful Life must be less than Gross Purchase Amount") .format(row.idx)) + if not row.depreciation_start_date: + frappe.throw(_("Row {0}: Depreciation Start Date is required").format(row.idx)) + if not self.is_existing_asset: self.opening_accumulated_depreciation = 0 self.number_of_depreciations_booked = 0 diff --git a/erpnext/assets/doctype/asset_movement/asset_movement.py b/erpnext/assets/doctype/asset_movement/asset_movement.py index e34d2a3066..638987ee96 100644 --- a/erpnext/assets/doctype/asset_movement/asset_movement.py +++ b/erpnext/assets/doctype/asset_movement/asset_movement.py @@ -55,7 +55,5 @@ class AssetMovement(Document): frappe.db.set_value("Asset", self.asset, "location", location) if self.serial_no: - serial_nos = get_serial_nos(self.serial_no) - - frappe.db.sql(""" update `tabSerial No` set location = %s where name in (%s)""" - %('%s', ','.join(['%s'] * len(serial_nos))), (location, tuple(serial_nos))) + for d in get_serial_nos(self.serial_no): + frappe.db.set_value('Serial No', d, 'location', location) From c6b2575a9cecc86fc848ea78e9358afe252ccb39 Mon Sep 17 00:00:00 2001 From: Ranjith Date: Wed, 16 May 2018 22:59:21 +0530 Subject: [PATCH 09/18] fields in salary detail, copy data from salary component on change --- .../doctype/salary_detail/salary_detail.json | 109 +++++++++++++++++- .../salary_structure/salary_structure.js | 17 +-- 2 files changed, 118 insertions(+), 8 deletions(-) diff --git a/erpnext/hr/doctype/salary_detail/salary_detail.json b/erpnext/hr/doctype/salary_detail/salary_detail.json index 01d02779b7..862728afb7 100644 --- a/erpnext/hr/doctype/salary_detail/salary_detail.json +++ b/erpnext/hr/doctype/salary_detail/salary_detail.json @@ -40,6 +40,7 @@ "reqd": 1, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -72,6 +73,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -101,6 +103,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -132,6 +135,100 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "is_tax_applicable", + "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": "Is Tax Applicable", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "is_flexible_benefit", + "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": "Is Flexible Benefit", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "variable_based_on_taxable_salary", + "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": "Variable Based On Taxable Salary", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -161,6 +258,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -192,6 +290,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -225,6 +324,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -258,6 +358,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -290,6 +391,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -321,6 +423,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -351,6 +454,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -383,6 +487,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -413,6 +518,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -445,6 +551,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 } ], @@ -458,7 +565,7 @@ "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2017-10-02 13:57:22.769751", + "modified": "2018-05-16 22:42:59.974450", "modified_by": "Administrator", "module": "HR", "name": "Salary Detail", diff --git a/erpnext/hr/doctype/salary_structure/salary_structure.js b/erpnext/hr/doctype/salary_structure/salary_structure.js index ca92234461..8fd51d990f 100755 --- a/erpnext/hr/doctype/salary_structure/salary_structure.js +++ b/erpnext/hr/doctype/salary_structure/salary_structure.js @@ -201,17 +201,20 @@ frappe.ui.form.on('Salary Detail', { callback: function(data) { if(data.message){ var result = data.message; - frappe.model.set_value(cdt, cdn, 'condition',result.condition); - frappe.model.set_value(cdt, cdn, 'amount_based_on_formula',result.amount_based_on_formula); + frappe.model.set_value(cdt, cdn, 'condition', result.condition); + frappe.model.set_value(cdt, cdn, 'amount_based_on_formula', result.amount_based_on_formula); if(result.amount_based_on_formula == 1){ - frappe.model.set_value(cdt, cdn, 'formula',result.formula); + frappe.model.set_value(cdt, cdn, 'formula', result.formula); } else{ - frappe.model.set_value(cdt, cdn, 'amount',result.amount); + frappe.model.set_value(cdt, cdn, 'amount', result.amount); } - frappe.model.set_value(cdt, cdn, 'statistical_component',result.statistical_component); - frappe.model.set_value(cdt, cdn, 'depends_on_lwp',result.depends_on_lwp); - frappe.model.set_value(cdt, cdn, 'do_not_include_in_total',result.do_not_include_in_total); + frappe.model.set_value(cdt, cdn, 'statistical_component', result.statistical_component); + frappe.model.set_value(cdt, cdn, 'depends_on_lwp', result.depends_on_lwp); + frappe.model.set_value(cdt, cdn, 'do_not_include_in_total', result.do_not_include_in_total); + frappe.model.set_value(cdt, cdn, 'variable_based_on_taxable_salary', result.variable_based_on_taxable_salary); + frappe.model.set_value(cdt, cdn, 'is_tax_applicable', result.is_tax_applicable); + frappe.model.set_value(cdt, cdn, 'is_flexible_benefit', result.is_flexible_benefit); refresh_field("earnings"); refresh_field("deductions"); } From b485b1ef804deadfe1ed2c6eb3d36deb8c0095b8 Mon Sep 17 00:00:00 2001 From: Ranjith Date: Wed, 16 May 2018 23:01:40 +0530 Subject: [PATCH 10/18] Salary Slip calc tax, except for flexi benefits --- .../salary_component/salary_component.py | 11 +++- erpnext/hr/doctype/salary_slip/salary_slip.py | 51 +++++++++++++++++++ .../taxable_salary_slab.json | 4 +- erpnext/hr/utils.py | 7 +++ 4 files changed, 70 insertions(+), 3 deletions(-) diff --git a/erpnext/hr/doctype/salary_component/salary_component.py b/erpnext/hr/doctype/salary_component/salary_component.py index 9108f31f9b..beffaec21f 100644 --- a/erpnext/hr/doctype/salary_component/salary_component.py +++ b/erpnext/hr/doctype/salary_component/salary_component.py @@ -18,4 +18,13 @@ class SalaryComponent(Document): self.salary_component_abbr = self.salary_component_abbr.strip() self.salary_component_abbr = append_number_if_name_exists('Salary Component', self.salary_component_abbr, - 'salary_component_abbr', separator='_', filters={"name": ["!=", self.name]}) \ No newline at end of file + 'salary_component_abbr', separator='_', filters={"name": ["!=", self.name]}) + + def calculate_tax(self, annual_earning): + taxable_amount = 0 + for slab in self.taxable_salary_slabs: + if annual_earning > slab.from_amount and annual_earning < slab.to_amount: + taxable_amount += (annual_earning - slab.from_amount) * slab.percent_deduction *.01 + elif annual_earning > slab.from_amount and annual_earning > slab.to_amount: + taxable_amount += (slab.to_amount - slab.from_amount) * slab.percent_deduction * .01 + return taxable_amount diff --git a/erpnext/hr/doctype/salary_slip/salary_slip.py b/erpnext/hr/doctype/salary_slip/salary_slip.py index 984a78c75f..ba8cc0235d 100644 --- a/erpnext/hr/doctype/salary_slip/salary_slip.py +++ b/erpnext/hr/doctype/salary_slip/salary_slip.py @@ -13,6 +13,7 @@ from erpnext.hr.doctype.employee.employee import get_holiday_list_for_employee from erpnext.utilities.transaction_base import TransactionBase from frappe.utils.background_jobs import enqueue from erpnext.hr.doctype.additional_salary_component.additional_salary_component import get_additional_salary_component +from erpnext.hr.utils import get_payroll_period class SalarySlip(TransactionBase): def autoname(self): @@ -58,6 +59,10 @@ class SalarySlip(TransactionBase): amount = self.eval_condition_and_formula(struct_row, data) if amount and struct_row.statistical_component == 0: self.update_component_row(struct_row, amount, key) + if key=="deductions" and struct_row.variable_based_on_taxable_salary: + tax_row, amount = self.calculate_pro_rata_tax(struct_row.salary_component) + if tax_row and amount: + self.update_component_row(frappe._dict(tax_row), amount, key) additional_components = get_additional_salary_component(self.employee, self.start_date, self.end_date) if additional_components: @@ -464,6 +469,52 @@ class SalarySlip(TransactionBase): status = "Cancelled" return status + def calculate_pro_rata_tax(self, salary_component): + # Calculate total tax payable earnings + tax_applicable_components = [] + for earning in self._salary_structure_doc.earnings: + #all tax applicable earnings which are not flexi + if earning.is_tax_applicable and not earning.is_flexible_benefit: + tax_applicable_components.append(earning.salary_component) + total_taxable_earning = 0 + for earning in self.earnings: + if earning.salary_component in tax_applicable_components: + total_taxable_earning += earning.amount + + # Get payroll period, prorata frequency + days = date_diff(self.end_date, self.start_date) + 1 + payroll_period = get_payroll_period(self.start_date, self.end_date, self.company) + if not payroll_period: + frappe.throw(_("Start and end dates not in a valid Payroll Period")) + total_days = date_diff(payroll_period.end_date, payroll_period.start_date) + 1 + prorata_frequency = flt(total_days)/flt(days) + annual_earning = total_taxable_earning * prorata_frequency + + # Calculate total exemption declaration + exemption_amount = 0 + if frappe.db.exists("Employee Tax Exemption Declaration", {"employee": self.employee, + "payroll_period": payroll_period.parent, "docstatus": 1}): + exemption_amount = frappe.db.get_value("Employee Tax Exemption Declaration", + {"employee": self.employee, "payroll_period": "2018", "docstatus": 1}, #fix period + "total_exemption_amount") + annual_earning = annual_earning - exemption_amount + + # Get tax calc by component + component = frappe.get_doc("Salary Component", salary_component) + annual_tax = component.calculate_tax(annual_earning) + + # Calc prorata tax + pro_rata_tax = annual_tax/prorata_frequency + + # Data for update_component_row + struct_row = {} + struct_row['depends_on_lwp'] = 0 + struct_row['salary_component'] = component.name + struct_row['abbr'] = component.salary_component_abbr + struct_row['do_not_include_in_total'] = 0 + + return struct_row, pro_rata_tax + def unlink_ref_doc_from_salary_slip(ref_no): linked_ss = frappe.db.sql_list("""select name from `tabSalary Slip` where journal_entry=%s and docstatus < 2""", (ref_no)) diff --git a/erpnext/hr/doctype/taxable_salary_slab/taxable_salary_slab.json b/erpnext/hr/doctype/taxable_salary_slab/taxable_salary_slab.json index bd0ec6be31..8e6c1d86ae 100644 --- a/erpnext/hr/doctype/taxable_salary_slab/taxable_salary_slab.json +++ b/erpnext/hr/doctype/taxable_salary_slab/taxable_salary_slab.json @@ -50,7 +50,7 @@ "collapsible": 0, "columns": 0, "fieldname": "to_amount", - "fieldtype": "Data", + "fieldtype": "Currency", "hidden": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, @@ -147,7 +147,7 @@ "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2018-04-13 20:09:36.675987", + "modified": "2018-05-16 18:18:23.802576", "modified_by": "Administrator", "module": "HR", "name": "Taxable Salary Slab", diff --git a/erpnext/hr/utils.py b/erpnext/hr/utils.py index df720c4cc6..315368dbab 100644 --- a/erpnext/hr/utils.py +++ b/erpnext/hr/utils.py @@ -234,3 +234,10 @@ def get_leave_period(from_date, to_date, company): if leave_period: return leave_period + +def get_payroll_period(from_date, to_date, company): + payroll_period = frappe.db.sql("""select pd.parent, pd.start_date, pd.end_date from + `tabPayroll Period Date` pd join `tabPayroll Period` pp on + pd.parent=pp.name where pd.start_date<=%s and pd.end_date>= %s + and pp.company=%s""", (from_date, to_date, company), as_dict=1) + return payroll_period[0] if payroll_period else None From a91765707a8ddddca7a3fcf6bd10291012aa6684 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Wed, 16 May 2018 23:13:02 +0530 Subject: [PATCH 11/18] [Fix] TDS issue --- erpnext/accounts/party.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/party.py b/erpnext/accounts/party.py index 69b369f081..2222f1f431 100644 --- a/erpnext/accounts/party.py +++ b/erpnext/accounts/party.py @@ -487,7 +487,7 @@ def get_patry_tax_withholding_details(ref_doc): if tax.valid_till and date_diff(tax.valid_till, ref_doc.posting_date) > 0: tax_mapper.update({ - "rate": tax.applicable_percentage + "rate": tax.applicable_percent }) prepare_tax_withholding_details(tax_mapper, tax_withholding_details) From 44fda65b1d19497e2ee4a4f575c39662e92942fe Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Wed, 16 May 2018 23:31:09 +0530 Subject: [PATCH 12/18] [Fix] Company mandatory issue --- erpnext/accounts/report/general_ledger/general_ledger.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/erpnext/accounts/report/general_ledger/general_ledger.py b/erpnext/accounts/report/general_ledger/general_ledger.py index 2d0bd52fd0..7134b91cd0 100644 --- a/erpnext/accounts/report/general_ledger/general_ledger.py +++ b/erpnext/accounts/report/general_ledger/general_ledger.py @@ -11,6 +11,9 @@ from erpnext.accounts.utils import get_account_currency def execute(filters=None): + if not filters: + return [], [] + account_details = {} if filters and filters.get('print_in_account_currency') and \ From 2868840e6bdb2bc789c0eb56f873a196f1b6b833 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Wed, 16 May 2018 23:57:28 +0530 Subject: [PATCH 13/18] [Fix] Validation issue --- erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py | 2 +- erpnext/controllers/accounts_controller.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py index 729c101a7c..bdfcccd6c5 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -436,7 +436,7 @@ class PurchaseInvoice(BuyingController): "remarks": self.get("remarks") or _("Accounting Entry for Stock"), "credit": flt(item.rm_supp_cost) }, warehouse_account[self.supplier_warehouse]["account_currency"])) - else: + elif not item.is_fixed_asset: gl_entries.append( self.get_gl_dict({ "account": item.expense_account, diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index a16047c34e..b68f24ae3d 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -621,8 +621,8 @@ class AccountsController(TransactionBase): def validate_fixed_asset(self): for d in self.get("items"): if d.is_fixed_asset: - if d.qty > 1: - frappe.throw(_("Row #{0}: Qty must be 1, as item is a fixed asset. Please use separate row for multiple qty.").format(d.idx)) + # if d.qty > 1: +# frappe.throw(_("Row #{0}: Qty must be 1, as item is a fixed asset. Please use separate row for multiple qty.").format(d.idx)) if d.meta.get_field("asset") and d.asset: asset = frappe.get_doc("Asset", d.asset) From 585945e65d2531b47797e09fe0f8a412d0930017 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Thu, 17 May 2018 00:22:29 +0530 Subject: [PATCH 14/18] Allow to select Asset Received But Not Billed in expense account head --- .../purchase_invoice/purchase_invoice.py | 20 +++++++++---------- erpnext/controllers/queries.py | 2 +- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py index bdfcccd6c5..545967eb97 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -81,7 +81,6 @@ class PurchaseInvoice(BuyingController): self.validate_write_off_account() self.validate_multiple_billing("Purchase Receipt", "pr_detail", "amount", "items") self.validate_fixed_asset() - self.validate_fixed_asset_account() self.create_remarks() self.set_status() validate_inter_company_party(self.doctype, self.supplier, self.company, self.inter_company_invoice_reference) @@ -479,11 +478,17 @@ class PurchaseInvoice(BuyingController): asset_amount = flt(item.net_amount) + flt(item.item_tax_amount/self.conversion_rate) base_asset_amount = flt(item.base_net_amount + item.item_tax_amount) + item.expense_account = item.expense_account or asset_accounts[0] + + if (not item.expense_account or frappe.db.get_value('Account', + item.expense_account, 'account_type') != 'Asset Received But Not Billed'): + frappe.throw(_("Row {0}: Expense account must be of type Asset Received But Not Billed"). + format(item.idx)) if not self.update_stock: - asset_rbnb_currency = get_account_currency(asset_accounts[0]) + asset_rbnb_currency = get_account_currency(item.expense_account) gl_entries.append(self.get_gl_dict({ - "account": asset_accounts[0], + "account": item.expense_account, "against": self.supplier, "remarks": self.get("remarks") or _("Accounting Entry for Asset"), "debit": base_asset_amount, @@ -518,7 +523,7 @@ class PurchaseInvoice(BuyingController): })) if item.item_tax_amount and not cint(erpnext.is_perpetual_inventory_enabled(self.company)): - asset_eiiav_currency = get_account_currency(asset_accounts[0]) + asset_eiiav_currency = get_account_currency(asset_accounts[1]) gl_entries.append(self.get_gl_dict({ "account": asset_accounts[1], "against": self.supplier, @@ -751,13 +756,6 @@ class PurchaseInvoice(BuyingController): for pr in set(updated_pr): frappe.get_doc("Purchase Receipt", pr).update_billing_percentage(update_modified=update_modified) - def validate_fixed_asset_account(self): - for d in self.get('items'): - if d.is_fixed_asset: - account_type = frappe.db.get_value("Account", d.expense_account, "account_type") - if account_type != 'Fixed Asset': - frappe.throw(_("Row {0}# Account must be of type 'Fixed Asset'").format(d.idx)) - def on_recurring(self, reference_doc, auto_repeat_doc): self.due_date = None diff --git a/erpnext/controllers/queries.py b/erpnext/controllers/queries.py index 8b6dd176e1..a4e95a1bc1 100644 --- a/erpnext/controllers/queries.py +++ b/erpnext/controllers/queries.py @@ -366,7 +366,7 @@ def get_expense_account(doctype, txt, searchfield, start, page_len, filters): return frappe.db.sql("""select tabAccount.name from `tabAccount` where (tabAccount.report_type = "Profit and Loss" - or tabAccount.account_type in ("Expense Account", "Fixed Asset", "Temporary")) + or tabAccount.account_type in ("Expense Account", "Fixed Asset", "Temporary", "Asset Received But Not Billed")) and tabAccount.is_group=0 and tabAccount.docstatus!=2 and tabAccount.{key} LIKE %(txt)s From e3f7e8b10120b817e314ff9fe175ba380063ce5c Mon Sep 17 00:00:00 2001 From: Zlash65 Date: Thu, 17 May 2018 01:34:20 +0530 Subject: [PATCH 15/18] typo in frappe.throw in employee_transfer --- erpnext/hr/doctype/employee_transfer/employee_transfer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/hr/doctype/employee_transfer/employee_transfer.py b/erpnext/hr/doctype/employee_transfer/employee_transfer.py index b58d334d29..6cdd22fc21 100644 --- a/erpnext/hr/doctype/employee_transfer/employee_transfer.py +++ b/erpnext/hr/doctype/employee_transfer/employee_transfer.py @@ -14,7 +14,7 @@ class EmployeeTransfer(Document): if frappe.get_value("Employee", self.employee, "status") == "Left": frappe.throw(_("Cannot transfer Employee with status Left")) if self.new_company and self.company == self.new_company: - frappe.throw_("New Company must be different from current company") + frappe.throw(_("New Company must be different from current company")) def before_submit(self): if getdate(self.transfer_date) > getdate(): From 58363e6bbd769e145cc5a27765a56eff6a2cf76c Mon Sep 17 00:00:00 2001 From: Ranjith Date: Thu, 17 May 2018 10:00:33 +0530 Subject: [PATCH 16/18] get_payroll_period return name, fix hard coded leave period --- erpnext/hr/doctype/salary_slip/salary_slip.py | 4 ++-- erpnext/hr/utils.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/erpnext/hr/doctype/salary_slip/salary_slip.py b/erpnext/hr/doctype/salary_slip/salary_slip.py index ba8cc0235d..53e6aa437e 100644 --- a/erpnext/hr/doctype/salary_slip/salary_slip.py +++ b/erpnext/hr/doctype/salary_slip/salary_slip.py @@ -493,9 +493,9 @@ class SalarySlip(TransactionBase): # Calculate total exemption declaration exemption_amount = 0 if frappe.db.exists("Employee Tax Exemption Declaration", {"employee": self.employee, - "payroll_period": payroll_period.parent, "docstatus": 1}): + "payroll_period": payroll_period.name, "docstatus": 1}): exemption_amount = frappe.db.get_value("Employee Tax Exemption Declaration", - {"employee": self.employee, "payroll_period": "2018", "docstatus": 1}, #fix period + {"employee": self.employee, "payroll_period": payroll_period.name, "docstatus": 1}, #fix period "total_exemption_amount") annual_earning = annual_earning - exemption_amount diff --git a/erpnext/hr/utils.py b/erpnext/hr/utils.py index 315368dbab..20fe666d2b 100644 --- a/erpnext/hr/utils.py +++ b/erpnext/hr/utils.py @@ -236,7 +236,7 @@ def get_leave_period(from_date, to_date, company): return leave_period def get_payroll_period(from_date, to_date, company): - payroll_period = frappe.db.sql("""select pd.parent, pd.start_date, pd.end_date from + payroll_period = frappe.db.sql("""select pp.name, pd.start_date, pd.end_date from `tabPayroll Period Date` pd join `tabPayroll Period` pp on pd.parent=pp.name where pd.start_date<=%s and pd.end_date>= %s and pp.company=%s""", (from_date, to_date, company), as_dict=1) From 992fb34c955876c3b7b1eff0e4abb66ed4fd5cd5 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Thu, 17 May 2018 11:18:34 +0530 Subject: [PATCH 17/18] [Fix] Asset adjustment issues --- erpnext/assets/doctype/asset/asset.js | 59 ++++++++++++++++++- erpnext/assets/doctype/asset/asset.py | 14 +++++ .../asset_adjustment/asset_adjustment.js | 13 +++- .../asset_adjustment/asset_adjustment.json | 50 ++++++++++++++-- .../asset_adjustment/asset_adjustment.py | 11 ++-- erpnext/controllers/accounts_controller.py | 4 +- 6 files changed, 136 insertions(+), 15 deletions(-) diff --git a/erpnext/assets/doctype/asset/asset.js b/erpnext/assets/doctype/asset/asset.js index 88e7f78a02..658107bb18 100644 --- a/erpnext/assets/doctype/asset/asset.js +++ b/erpnext/assets/doctype/asset/asset.js @@ -82,7 +82,7 @@ frappe.ui.form.on('Asset', { } if (frm.doc.status != 'Fully Depreciated') { frm.add_custom_button(__("Asset Adjustment"), function() { - frm.trigger("create_asset_maintenance"); + frm.trigger("create_asset_adjustment"); }, __("Make")); } @@ -233,6 +233,22 @@ frappe.ui.form.on('Asset', { }) }, + create_asset_adjustment: function(frm) { + frappe.call({ + args: { + "asset": frm.doc.name, + "asset_category": frm.doc.asset_category, + "company": frm.doc.company + }, + method: "erpnext.assets.doctype.asset.asset.create_asset_adjustment", + freeze: 1, + callback: function(r) { + var doclist = frappe.model.sync(r.message); + frappe.set_route("Form", doclist[0].doctype, doclist[0].name); + } + }) + }, + calculate_depreciation: function(frm) { frappe.db.get_value("Asset Settings", {'name':"Asset Settings"}, 'schedule_based_on_fiscal_year', (data) => { if (data.schedule_based_on_fiscal_year == 1) { @@ -328,6 +344,42 @@ erpnext.asset.transfer_asset = function(frm) { }, "reqd": 1 }, + { + "label": __("Select Serial No"), + "fieldname": "serial_nos", + "fieldtype": "Link", + "options": "Serial No", + "get_query": function () { + return { + filters: { + 'asset': frm.doc.name + } + } + }, + "onchange": function() { + let val = this.get_value(); + if (val) { + let serial_nos = dialog.get_value("serial_no") || val; + if (serial_nos) { + serial_nos = serial_nos.split('\n'); + serial_nos.push(val); + + const unique_sn = serial_nos.filter(function(elem, index, self) { + return index === self.indexOf(elem); + }); + + dialog.set_value("serial_no", unique_sn.join('\n')); + dialog.set_value("serial_nos", ""); + } + } + } + }, + { + "label": __("Serial No"), + "fieldname": "serial_no", + "read_only": 1, + "fieldtype": "Small Text" + }, { "label": __("Date"), "fieldname": "transfer_date", @@ -349,8 +401,9 @@ erpnext.asset.transfer_asset = function(frm) { args: { "asset": frm.doc.name, "transaction_date": args.transfer_date, - "source_warehouse": frm.doc.location, - "target_warehouse": args.target_location, + "source_location": frm.doc.location, + "target_location": args.target_location, + "serial_no": args.serial_no, "company": frm.doc.company } }, diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py index 75e808870f..1069db636a 100644 --- a/erpnext/assets/doctype/asset/asset.py +++ b/erpnext/assets/doctype/asset/asset.py @@ -421,10 +421,24 @@ def create_asset_maintenance(asset, item_code, item_name, asset_category, compan }) return asset_maintenance +@frappe.whitelist() +def create_asset_adjustment(asset, asset_category, company): + asset_maintenance = frappe.new_doc("Asset Adjustment") + asset_maintenance.update({ + "asset": asset, + "company": company, + "asset_category": asset_category + }) + return asset_maintenance + @frappe.whitelist() def transfer_asset(args): import json args = json.loads(args) + + if args.get('serial_no'): + args['quantity'] = len(args.get('serial_no').split('\n')) + movement_entry = frappe.new_doc("Asset Movement") movement_entry.update(args) movement_entry.insert() diff --git a/erpnext/assets/doctype/asset_adjustment/asset_adjustment.js b/erpnext/assets/doctype/asset_adjustment/asset_adjustment.js index 11c02e105f..346a2f1d71 100644 --- a/erpnext/assets/doctype/asset_adjustment/asset_adjustment.js +++ b/erpnext/assets/doctype/asset_adjustment/asset_adjustment.js @@ -2,6 +2,18 @@ // For license information, please see license.txt frappe.ui.form.on('Asset Adjustment', { + setup: function(frm) { + frm.add_fetch('company', 'cost_center', 'cost_center'); + frm.set_query('cost_center', function() { + return { + filters: { + company: frm.doc.company, + is_group: 0 + } + } + }); + }, + asset: function(frm) { frm.trigger("set_current_asset_value"); }, @@ -11,7 +23,6 @@ frappe.ui.form.on('Asset Adjustment', { }, set_current_asset_value: function(frm) { - debugger if (frm.doc.finance_book && frm.doc.asset) { frm.call({ method: "erpnext.assets.doctype.asset_adjustment.asset_adjustment.get_current_asset_value", diff --git a/erpnext/assets/doctype/asset_adjustment/asset_adjustment.json b/erpnext/assets/doctype/asset_adjustment/asset_adjustment.json index faa36efe07..3f4f77c328 100644 --- a/erpnext/assets/doctype/asset_adjustment/asset_adjustment.json +++ b/erpnext/assets/doctype/asset_adjustment/asset_adjustment.json @@ -41,6 +41,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -72,6 +73,7 @@ "reqd": 1, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -103,6 +105,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -134,6 +137,7 @@ "reqd": 1, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -165,6 +169,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -194,6 +199,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -203,7 +209,7 @@ "collapsible": 0, "columns": 0, "fieldname": "date", - "fieldtype": "Datetime", + "fieldtype": "Date", "hidden": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, @@ -224,6 +230,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -254,6 +261,7 @@ "reqd": 1, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -284,6 +292,7 @@ "reqd": 1, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -314,6 +323,39 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "cost_center", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Cost Center", + "length": 0, + "no_copy": 0, + "options": "Cost Center", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 }, { @@ -344,6 +386,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 } ], @@ -357,7 +400,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2018-05-11 21:45:03.459696", + "modified": "2018-05-17 11:12:38.110774", "modified_by": "Administrator", "module": "Assets", "name": "Asset Adjustment", @@ -366,7 +409,6 @@ "permissions": [ { "amend": 1, - "apply_user_permissions": 0, "cancel": 1, "create": 1, "delete": 1, @@ -386,7 +428,6 @@ }, { "amend": 1, - "apply_user_permissions": 0, "cancel": 1, "create": 1, "delete": 1, @@ -406,7 +447,6 @@ }, { "amend": 1, - "apply_user_permissions": 0, "cancel": 1, "create": 1, "delete": 1, diff --git a/erpnext/assets/doctype/asset_adjustment/asset_adjustment.py b/erpnext/assets/doctype/asset_adjustment/asset_adjustment.py index 6b4b752e7f..af806e4a8d 100644 --- a/erpnext/assets/doctype/asset_adjustment/asset_adjustment.py +++ b/erpnext/assets/doctype/asset_adjustment/asset_adjustment.py @@ -16,12 +16,14 @@ class AssetAdjustment(Document): def on_submit(self): self.make_depreciation_entry() - self.reschedule_depreciations() + self.reschedule_depreciations(self.new_asset_value) def on_cancel(self): if self.journal_entry: frappe.throw(_("Cancel the journal entry {0} first").format(self.journal_entry)) + self.reschedule_depreciations(self.current_asset_value) + def set_difference_amount(self): self.difference_amount = flt(self.current_asset_value - self.new_asset_value) @@ -47,12 +49,13 @@ class AssetAdjustment(Document): je.append("accounts", { "account": accumulated_depreciation_account, "credit_in_account_currency": self.difference_amount, + "cost_center": depreciation_cost_center or self.cost_center }) je.append("accounts", { "account": depreciation_expense_account, "debit_in_account_currency": self.difference_amount, - "cost_center": depreciation_cost_center + "cost_center": depreciation_cost_center or self.cost_center }) je.flags.ignore_permissions = True @@ -60,11 +63,11 @@ class AssetAdjustment(Document): self.db_set("journal_entry", je.name) - def reschedule_depreciations(self): + def reschedule_depreciations(self, asset_value): asset = frappe.get_doc('Asset', self.asset) for d in asset.finance_books: - d.value_after_depreciation = self.new_asset_value + d.value_after_depreciation = asset_value if d.depreciation_method in ("Straight Line", "Manual"): end_date = max([s.schedule_date for s in asset.schedules if cint(s.finance_book_id) == d.idx]) diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index b68f24ae3d..adab972ecd 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -635,8 +635,8 @@ class AccountsController(TransactionBase): frappe.throw(_("Row #{0}: Asset {1} does not linked to Item {2}") .format(d.idx, d.asset, d.item_code)) - elif asset.docstatus != 1: - frappe.throw(_("Row #{0}: Asset {1} must be submitted").format(d.idx, d.asset)) + # elif asset.docstatus != 1: +# frappe.throw(_("Row #{0}: Asset {1} must be submitted").format(d.idx, d.asset)) elif self.doctype == "Purchase Invoice": # if asset.status != "Submitted": From b52d5b21a10216b13c7f50f059ced81eaee6c12a Mon Sep 17 00:00:00 2001 From: Valmik Jangla Date: Thu, 17 May 2018 00:02:03 -0700 Subject: [PATCH 18/18] Add UOM to Item View with Price --- erpnext/accounts/page/pos/pos.js | 1 + erpnext/public/js/pos/pos_item.html | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) mode change 100644 => 100755 erpnext/accounts/page/pos/pos.js mode change 100644 => 100755 erpnext/public/js/pos/pos_item.html diff --git a/erpnext/accounts/page/pos/pos.js b/erpnext/accounts/page/pos/pos.js old mode 100644 new mode 100755 index c07b851864..2146aced2a --- a/erpnext/accounts/page/pos/pos.js +++ b/erpnext/accounts/page/pos/pos.js @@ -1051,6 +1051,7 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({ item_name: obj.name === obj.item_name ? "" : obj.item_name, item_image: obj.image, item_stock: __('Stock Qty') + ": " + me.get_actual_qty(obj), + item_uom: obj.stock_uom, color: frappe.get_palette(obj.item_name), abbr: frappe.get_abbr(obj.item_name) })).tooltip().appendTo($wrap); diff --git a/erpnext/public/js/pos/pos_item.html b/erpnext/public/js/pos/pos_item.html old mode 100644 new mode 100755 index f6ef5a42d2..52f3cf698a --- a/erpnext/public/js/pos/pos_item.html +++ b/erpnext/public/js/pos/pos_item.html @@ -25,7 +25,7 @@ {% } %} - {{item_price}} + {{item_price}} / {{item_uom}}