diff --git a/erpnext/__init__.py b/erpnext/__init__.py index 8fbdb54234a..e510e38c090 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -5,7 +5,7 @@ import frappe from erpnext.hooks import regional_overrides from frappe.utils import getdate -__version__ = '11.1.16' +__version__ = '11.1.17' def get_default_company(user=None): '''Get default company for user''' diff --git a/erpnext/accounts/doctype/account/account.py b/erpnext/accounts/doctype/account/account.py index 427f3dba20d..ac74b4516a7 100644 --- a/erpnext/accounts/doctype/account/account.py +++ b/erpnext/accounts/doctype/account/account.py @@ -98,6 +98,8 @@ class Account(NestedSet): ancestors = get_root_company(self.company) if ancestors: + if frappe.get_value("Company", self.company, "allow_account_creation_against_child_company"): + return frappe.throw(_("Please add the account to root level Company - %s" % ancestors[0])) else: descendants = get_descendants_of('Company', self.company) diff --git a/erpnext/accounts/doctype/account/account_tree.js b/erpnext/accounts/doctype/account/account_tree.js index df0486cc271..27f5349e2b7 100644 --- a/erpnext/accounts/doctype/account/account_tree.js +++ b/erpnext/accounts/doctype/account/account_tree.js @@ -23,6 +23,10 @@ frappe.treeview_settings["Account"] = { if(r.message) { let root_company = r.message.length ? r.message[0] : ""; me.page.fields_dict.root_company.set_value(root_company); + + frappe.db.get_value("Company", {"name": company}, "allow_account_creation_against_child_company", (r) => { + frappe.flags.ignore_root_company_validation = r.allow_account_creation_against_child_company; + }); } } }); @@ -133,9 +137,10 @@ frappe.treeview_settings["Account"] = { { label:__("Add Child"), condition: function(node) { - return frappe.boot.user.can_create.indexOf("Account") !== -1 && - !frappe.treeview_settings['Account'].treeview.page.fields_dict.root_company.get_value() && - node.expandable && !node.hide_add; + return frappe.boot.user.can_create.indexOf("Account") !== -1 + && (!frappe.treeview_settings['Account'].treeview.page.fields_dict.root_company.get_value() + || frappe.flags.ignore_root_company_validation) + && node.expandable && !node.hide_add; }, click: function() { var me = frappe.treeview_settings['Account'].treeview; diff --git a/erpnext/accounts/doctype/bank_reconciliation/bank_reconciliation.py b/erpnext/accounts/doctype/bank_reconciliation/bank_reconciliation.py index 917276293d2..dafa330b540 100644 --- a/erpnext/accounts/doctype/bank_reconciliation/bank_reconciliation.py +++ b/erpnext/accounts/doctype/bank_reconciliation/bank_reconciliation.py @@ -79,8 +79,12 @@ class BankReconciliation(Document): for d in entries: row = self.append('payment_entries', {}) - amount = d.debit if d.debit else d.credit - d.amount = fmt_money(amount, 2, d.account_currency) + " " + (_("Dr") if d.debit else _("Cr")) + + amount = d.get('debit', 0) - d.get('credit', 0) + + formatted_amount = fmt_money(abs(amount), 2, d.account_currency) + d.amount = formatted_amount + " " + (_("Dr") if amount > 0 else _("Cr")) + d.pop("credit") d.pop("debit") d.pop("account_currency") diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py index 7c48b5c4f89..92342f4d7c8 100644 --- a/erpnext/accounts/doctype/journal_entry/journal_entry.py +++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py @@ -52,11 +52,6 @@ class JournalEntry(AccountsController): self.update_loan() self.update_inter_company_jv() - def before_print(self): - self.gl_entries = frappe.get_list("GL Entry",filters={"voucher_type": "Journal Entry", - "voucher_no": self.name} , - fields=["account", "party_type", "party", "debit", "credit", "remarks"] - ) def get_title(self): return self.pay_to_recd_from or self.accounts[0].account diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py index f356ef8c8fe..91004104af0 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py @@ -70,11 +70,6 @@ class PaymentEntry(AccountsController): self.update_advance_paid() self.update_expense_claim() - def before_print(self): - self.gl_entries = frappe.get_list("GL Entry",filters={"voucher_type": "Payment Entry", - "voucher_no": self.name} , - fields=["account", "party_type", "party", "debit", "credit", "remarks"] - ) def on_cancel(self): self.setup_party_account_field() diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py index 53eb73191d0..450f2d0eb7b 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -55,11 +55,6 @@ class PurchaseInvoice(BuyingController): if not self.on_hold: self.release_date = '' - def before_print(self): - self.gl_entries = frappe.get_list("GL Entry",filters={"voucher_type": "Purchase Invoice", - "voucher_no": self.name} , - fields=["account", "party_type", "party", "debit", "credit"] - ) def invoice_is_blocked(self): return self.on_hold and (not self.release_date or self.release_date > getdate(nowdate())) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index 61e12245965..489343c00c8 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -205,11 +205,6 @@ class SalesInvoice(SellingController): def before_cancel(self): self.update_time_sheet(None) - def before_print(self): - self.gl_entries = frappe.get_list("GL Entry",filters={"voucher_type": "Sales Invoice", - "voucher_no": self.name} , - fields=["account", "party_type", "party", "debit", "credit"] - ) def on_cancel(self): self.check_close_sales_order("sales_order") diff --git a/erpnext/accounts/page/pos/pos.js b/erpnext/accounts/page/pos/pos.js index c3274b9fb5b..4550dedba94 100755 --- a/erpnext/accounts/page/pos/pos.js +++ b/erpnext/accounts/page/pos/pos.js @@ -333,6 +333,7 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({ var me = this; this.frm = {} this.load_data(true); + this.frm.doc.offline_pos_name = ''; this.setup(); this.set_default_customer() }, @@ -345,7 +346,6 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({ if (load_doc) { this.frm.doc = JSON.parse(localStorage.getItem('doc')); - this.frm.doc.offline_pos_name = null; } $.each(this.meta, function (i, data) { @@ -641,7 +641,7 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({ me.list_customers_btn.toggleClass("view_customer"); me.pos_bill.show(); me.list_customers_btn.show(); - me.frm.doc.offline_pos_name = $(this).parents().attr('invoice-name') + me.frm.doc.offline_pos_name = $(this).parents().attr('invoice-name'); me.edit_record(); }) @@ -984,7 +984,7 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({ } if(!this.customer_doc.fields_dict.customer_pos_id.value) { - this.customer_doc.set_value("customer_pos_id", $.now()) + this.customer_doc.set_value("customer_pos_id", frappe.datetime.now_datetime()) } }, @@ -1686,10 +1686,18 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({ create_invoice: function () { var me = this; + var existing_pos_list = []; var invoice_data = {}; this.si_docs = this.get_doc_from_localstorage(); - if (this.frm.doc.offline_pos_name) { + if(this.si_docs) { + this.si_docs.forEach((row) => { + existing_pos_list.push(Object.keys(row)); + }); + } + + if (this.frm.doc.offline_pos_name + && in_list(existing_pos_list, this.frm.doc.offline_pos_name)) { this.update_invoice() //to retrieve and set the default payment invoice_data[this.frm.doc.offline_pos_name] = this.frm.doc; @@ -1698,8 +1706,8 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({ this.frm.doc.paid_amount = this.frm.doc.net_total this.frm.doc.outstanding_amount = 0 - } else { - this.frm.doc.offline_pos_name = $.now(); + } else if(!this.frm.doc.offline_pos_name) { + this.frm.doc.offline_pos_name = frappe.datetime.now_datetime(); this.frm.doc.posting_date = frappe.datetime.get_today(); this.frm.doc.posting_time = frappe.datetime.now_time(); this.frm.doc.pos_total_qty = this.frm.doc.qty_total; diff --git a/erpnext/accounts/party.py b/erpnext/accounts/party.py index 70e48007845..67bd0bd8c70 100644 --- a/erpnext/accounts/party.py +++ b/erpnext/accounts/party.py @@ -573,13 +573,17 @@ def get_party_shipping_address(doctype, name): else: return '' -def get_partywise_advanced_payment_amount(party_type="Customer"): +def get_partywise_advanced_payment_amount(party_type, posting_date = None): + cond = "1=1" + if posting_date: + cond = "posting_date <= '{0}'".format(posting_date) + data = frappe.db.sql(""" SELECT party, sum({0}) as amount FROM `tabGL Entry` WHERE party_type = %s and against_voucher is null - GROUP BY party""" - .format(("credit") if party_type == "Customer" else "debit") , party_type) + and {1} GROUP BY party""" + .format(("credit") if party_type == "Customer" else "debit", cond) , party_type) if data: return frappe._dict(data) \ No newline at end of file diff --git a/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py b/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py index 8cb5ac1090f..ffd19948ce9 100644 --- a/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py +++ b/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py @@ -136,7 +136,8 @@ class AccountsReceivableSummary(ReceivablePayableReport): partywise_total = self.get_partywise_total(party_naming_by, args) - partywise_advance_amount = get_partywise_advanced_payment_amount(args.get("party_type")) or {} + partywise_advance_amount = get_partywise_advanced_payment_amount(args.get("party_type"), + self.filters.get("report_date")) or {} for party, party_dict in iteritems(partywise_total): row = [party] @@ -144,7 +145,9 @@ class AccountsReceivableSummary(ReceivablePayableReport): row += [self.get_party_name(args.get("party_type"), party)] row += [partywise_advance_amount.get(party, 0)] - paid_amt = flt(party_dict.paid_amt - partywise_advance_amount.get(party, 0)) + + if party_dict.paid_amt > 0: + paid_amt = flt(party_dict.paid_amt - partywise_advance_amount.get(party, 0)) row += [ party_dict.invoiced_amt, paid_amt, party_dict.credit_amt, party_dict.outstanding_amt, diff --git a/erpnext/accounts/report/profitability_analysis/profitability_analysis.py b/erpnext/accounts/report/profitability_analysis/profitability_analysis.py index 39706acde0f..a0d8c5f0e4e 100644 --- a/erpnext/accounts/report/profitability_analysis/profitability_analysis.py +++ b/erpnext/accounts/report/profitability_analysis/profitability_analysis.py @@ -133,6 +133,13 @@ def get_columns(filters): "options": filters.get("based_on"), "width": 300 }, + { + "fieldname": "currency", + "label": _("Currency"), + "fieldtype": "Link", + "options": "Currency", + "hidden": 1 + }, { "fieldname": "income", "label": _("Income"), @@ -153,13 +160,6 @@ def get_columns(filters): "fieldtype": "Currency", "options": "currency", "width": 120 - }, - { - "fieldname": "currency", - "label": _("Currency"), - "fieldtype": "Link", - "options": "Currency", - "hidden": 1 } ] @@ -191,4 +191,4 @@ def set_gl_entries_by_account(company, from_date, to_date, based_on, gl_entries_ for entry in gl_entries: gl_entries_by_account.setdefault(entry.based_on, []).append(entry) - return gl_entries_by_account \ No newline at end of file + return gl_entries_by_account diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index 34bbe7b9994..86b1ab6ece8 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -116,6 +116,12 @@ class AccountsController(TransactionBase): self.validate_non_invoice_documents_schedule() def before_print(self): + if self.doctype in ['Journal Entry', 'Payment Entry', 'Sales Invoice', 'Purchase Invoice']: + self.gl_entries = frappe.get_list("GL Entry", filters={ + "voucher_type": self.doctype, + "voucher_no": self.name + }, fields=["account", "party_type", "party", "debit", "credit", "remarks"]) + if self.doctype in ['Purchase Order', 'Sales Order', 'Sales Invoice', 'Purchase Invoice', 'Supplier Quotation', 'Purchase Receipt', 'Delivery Note', 'Quotation']: if self.get("group_same_items"): diff --git a/erpnext/hr/doctype/leave_application/leave_application.py b/erpnext/hr/doctype/leave_application/leave_application.py index 692db8e1a54..b73d0e5b3fb 100755 --- a/erpnext/hr/doctype/leave_application/leave_application.py +++ b/erpnext/hr/doctype/leave_application/leave_application.py @@ -399,6 +399,19 @@ def get_leave_balance_on(employee, leave_type, date, allocation_records=None, do return flt(allocation.total_leaves_allocated) - (flt(leaves_taken) + flt(leaves_encashed)) +def get_total_allocated_leaves(employee, leave_type, date): + filters= { + 'from_date': ['<=', date], + 'to_date': ['>=', date], + 'docstatus': 1, + 'leave_type': leave_type, + 'employee': employee + } + + leave_allocation_records = frappe.db.get_all('Leave Allocation', filters=filters, fields=['total_leaves_allocated']) + + return flt(leave_allocation_records[0]['total_leaves_allocated']) if leave_allocation_records else flt(0) + def get_leaves_for_period(employee, leave_type, from_date, to_date, status, docname=None): leave_applications = frappe.db.sql(""" select name, employee, leave_type, from_date, to_date, total_leave_days diff --git a/erpnext/hr/report/employee_leave_balance/employee_leave_balance.py b/erpnext/hr/report/employee_leave_balance/employee_leave_balance.py index ed44d639f52..95cb30b7918 100644 --- a/erpnext/hr/report/employee_leave_balance/employee_leave_balance.py +++ b/erpnext/hr/report/employee_leave_balance/employee_leave_balance.py @@ -5,21 +5,21 @@ from __future__ import unicode_literals import frappe from frappe import _ from erpnext.hr.doctype.leave_application.leave_application \ - import get_leave_allocation_records, get_leave_balance_on, get_approved_leaves_for_period + import get_leave_allocation_records, get_leave_balance_on, get_approved_leaves_for_period, get_total_allocated_leaves def execute(filters=None): leave_types = frappe.db.sql_list("select name from `tabLeave Type` order by name asc") - + columns = get_columns(leave_types) data = get_data(filters, leave_types) - + return columns, data - + def get_columns(leave_types): columns = [ - _("Employee") + ":Link/Employee:150", - _("Employee Name") + "::200", + _("Employee") + ":Link/Employee:150", + _("Employee Name") + "::200", _("Department") +"::150" ] @@ -27,18 +27,18 @@ def get_columns(leave_types): columns.append(_(leave_type) + " " + _("Opening") + ":Float:160") columns.append(_(leave_type) + " " + _("Taken") + ":Float:160") columns.append(_(leave_type) + " " + _("Balance") + ":Float:160") - + return columns - + def get_data(filters, leave_types): user = frappe.session.user allocation_records_based_on_to_date = get_leave_allocation_records(filters.to_date) allocation_records_based_on_from_date = get_leave_allocation_records(filters.from_date) - active_employees = frappe.get_all("Employee", - filters = { "status": "Active", "company": filters.company}, + active_employees = frappe.get_all("Employee", + filters = { "status": "Active", "company": filters.company}, fields = ["name", "employee_name", "department", "user_id"]) - + data = [] for employee in active_employees: leave_approvers = get_approvers(employee.department) @@ -51,8 +51,7 @@ def get_data(filters, leave_types): filters.from_date, filters.to_date) # opening balance - opening = get_leave_balance_on(employee.name, leave_type, filters.from_date, - allocation_records_based_on_from_date.get(employee.name, frappe._dict())) + opening = get_total_allocated_leaves(employee.name, leave_type, filters.to_date) # closing balance closing = get_leave_balance_on(employee.name, leave_type, filters.to_date, @@ -61,7 +60,7 @@ def get_data(filters, leave_types): row += [opening, leaves_taken, closing] data.append(row) - + return data def get_approvers(department): diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py index ea6b7ede924..db94350d670 100644 --- a/erpnext/manufacturing/doctype/bom/bom.py +++ b/erpnext/manufacturing/doctype/bom/bom.py @@ -580,7 +580,7 @@ def get_list_context(context): context.title = _("Bill of Materials") # context.introduction = _('Boms') -def get_bom_items_as_dict(bom, company, qty=1, fetch_exploded=1, fetch_scrap_items=0, include_non_stock_items=False): +def get_bom_items_as_dict(bom, company, qty=1, fetch_exploded=1, fetch_scrap_items=0, include_non_stock_items=False, fetch_qty_in_stock_uom=True): item_dict = {} # Did not use qty_consumed_per_unit in the query, as it leads to rounding loss @@ -588,7 +588,7 @@ def get_bom_items_as_dict(bom, company, qty=1, fetch_exploded=1, fetch_scrap_ite bom_item.item_code, bom_item.idx, item.item_name, - sum(bom_item.stock_qty/ifnull(bom.quantity, 1)) * %(qty)s as qty, + sum(bom_item.{qty_field}/ifnull(bom.quantity, 1)) * %(qty)s as qty, item.description, item.image, item.stock_uom, @@ -616,16 +616,18 @@ def get_bom_items_as_dict(bom, company, qty=1, fetch_exploded=1, fetch_scrap_ite query = query.format(table="BOM Explosion Item", where_conditions="", is_stock_item=is_stock_item, + qty_field="stock_qty", select_columns = """, bom_item.source_warehouse, bom_item.operation, bom_item.include_item_in_manufacturing, (Select idx from `tabBOM Item` where item_code = bom_item.item_code and parent = %(parent)s ) as idx""") items = frappe.db.sql(query, { "parent": bom, "qty": qty, "bom": bom, "company": company }, as_dict=True) elif fetch_scrap_items: - query = query.format(table="BOM Scrap Item", where_conditions="", select_columns=", bom_item.idx", is_stock_item=is_stock_item) + query = query.format(table="BOM Scrap Item", where_conditions="", select_columns=", bom_item.idx", is_stock_item=is_stock_item, qty_field="stock_qty") items = frappe.db.sql(query, { "qty": qty, "bom": bom, "company": company }, as_dict=True) else: query = query.format(table="BOM Item", where_conditions="", is_stock_item=is_stock_item, - select_columns = ", bom_item.source_warehouse, bom_item.idx, bom_item.operation, bom_item.include_item_in_manufacturing") + qty_field="stock_qty" if fetch_qty_in_stock_uom else "qty", + select_columns = ", bom_item.uom, bom_item.conversion_factor, bom_item.source_warehouse, bom_item.idx, bom_item.operation, bom_item.include_item_in_manufacturing") items = frappe.db.sql(query, { "qty": qty, "bom": bom, "company": company }, as_dict=True) for item in items: diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 7d49ad5fe36..9d1e7b14539 100755 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -587,5 +587,5 @@ erpnext.patches.v11_1.setup_guardian_role execute:frappe.delete_doc('DocType', 'Notification Control') erpnext.patches.v11_0.remove_barcodes_field_from_copy_fields_to_variants erpnext.patches.v10_0.item_barcode_childtable_migrate # 16-02-2019 -erpnext.patches.v11_0.make_italian_localization_fields # 01-03-2019 -erpnext.patches.v11_1.make_job_card_time_logs \ No newline at end of file +erpnext.patches.v11_0.make_italian_localization_fields # 26-03-2019 +erpnext.patches.v11_1.make_job_card_time_logs diff --git a/erpnext/patches/v11_0/make_italian_localization_fields.py b/erpnext/patches/v11_0/make_italian_localization_fields.py index 44a281f86f4..79958b9189c 100644 --- a/erpnext/patches/v11_0/make_italian_localization_fields.py +++ b/erpnext/patches/v11_0/make_italian_localization_fields.py @@ -6,7 +6,6 @@ from erpnext.regional.italy.setup import make_custom_fields, setup_report from erpnext.regional.italy import state_codes import frappe - def execute(): company = frappe.get_all('Company', filters = {'country': 'Italy'}) if not company: @@ -27,4 +26,12 @@ def execute(): frappe.db.sql(""" UPDATE tabAddress set {condition} country_code = UPPER(ifnull((select code from `tabCountry` where name = `tabAddress`.country), '')) + where country_code is null and state_code is null """.format(condition=condition)) + + frappe.db.sql(""" + UPDATE `tabSales Invoice Item` si, `tabSales Order` so + set si.customer_po_no = so.po_no, si.customer_po_date = so.po_date + WHERE + si.sales_order = so.name and so.po_no is not null + """) diff --git a/erpnext/projects/doctype/timesheet/timesheet.js b/erpnext/projects/doctype/timesheet/timesheet.js index 8811ab95438..8ffc10ee972 100644 --- a/erpnext/projects/doctype/timesheet/timesheet.js +++ b/erpnext/projects/doctype/timesheet/timesheet.js @@ -10,8 +10,8 @@ frappe.ui.form.on("Timesheet", { filters:{ 'status': 'Active' } - } - } + }; + }; frm.fields_dict['time_logs'].grid.get_field('task').get_query = function(frm, cdt, cdn) { var child = locals[cdt][cdn]; @@ -20,33 +20,37 @@ frappe.ui.form.on("Timesheet", { 'project': child.project, 'status': ["!=", "Cancelled"] } - } - } + }; + }; frm.fields_dict['time_logs'].grid.get_field('project').get_query = function() { return{ filters: { 'company': frm.doc.company } - } - } + }; + }; }, onload: function(frm){ if (frm.doc.__islocal && frm.doc.time_logs) { calculate_time_and_amount(frm); } + + if (frm.is_new()) { + set_employee_and_company(frm); + } }, refresh: function(frm) { if(frm.doc.docstatus==1) { if(frm.doc.per_billed < 100 && frm.doc.total_billable_hours && frm.doc.total_billable_hours > frm.doc.total_billed_hours){ - frm.add_custom_button(__("Make Sales Invoice"), function() { frm.trigger("make_invoice") }, + frm.add_custom_button(__("Make Sales Invoice"), function() { frm.trigger("make_invoice"); }, "fa fa-file-alt"); } if(!frm.doc.salary_slip && frm.doc.employee){ - frm.add_custom_button(__("Make Salary Slip"), function() { frm.trigger("make_salary_slip") }, + frm.add_custom_button(__("Make Salary Slip"), function() { frm.trigger("make_salary_slip"); }, "fa fa-file-alt"); } } @@ -58,7 +62,7 @@ frappe.ui.form.on("Timesheet", { if ((row.from_time <= frappe.datetime.now_datetime()) && !row.completed) { button = 'Resume Timer'; } - }) + }); frm.add_custom_button(__(button), function() { var flag = true; @@ -77,7 +81,7 @@ frappe.ui.form.on("Timesheet", { erpnext.timesheet.timer(frm, row, timestamp); flag = false; } - }) + }); // If no activities found to start a timer, create new if (flag) { erpnext.timesheet.timer(frm); @@ -94,7 +98,7 @@ frappe.ui.form.on("Timesheet", { frappe.db.get_value('Company', { 'company_name' : frm.doc.company }, 'standard_working_hours') .then(({ message }) => { (frappe.working_hours = message.standard_working_hours || 0); - }); + }); }, make_invoice: function(frm) { @@ -125,8 +129,8 @@ frappe.ui.form.on("Timesheet", { frappe.set_route("Form", r.message.doctype, r.message.name); } } - }) - }) + }); + }); dialog.show(); }, @@ -136,7 +140,7 @@ frappe.ui.form.on("Timesheet", { frm: frm }); }, -}) +}); frappe.ui.form.on("Timesheet Detail", { time_logs_remove: function(frm) { @@ -171,22 +175,22 @@ frappe.ui.form.on("Timesheet Detail", { .find('[data-fieldname="timer"]') .append(frappe.render_template("timesheet")); frm.trigger("control_timer"); - }) + }); }, hours: function(frm, cdt, cdn) { - calculate_end_time(frm, cdt, cdn) + calculate_end_time(frm, cdt, cdn); }, billing_hours: function(frm, cdt, cdn) { - calculate_billing_costing_amount(frm, cdt, cdn) + calculate_billing_costing_amount(frm, cdt, cdn); }, billing_rate: function(frm, cdt, cdn) { - calculate_billing_costing_amount(frm, cdt, cdn) + calculate_billing_costing_amount(frm, cdt, cdn); }, costing_rate: function(frm, cdt, cdn) { - calculate_billing_costing_amount(frm, cdt, cdn) + calculate_billing_costing_amount(frm, cdt, cdn); }, billable: function(frm, cdt, cdn) { @@ -212,7 +216,7 @@ frappe.ui.form.on("Timesheet Detail", { calculate_billing_costing_amount(frm, cdt, cdn); } } - }) + }); } }); @@ -240,23 +244,23 @@ var calculate_end_time = function(frm, cdt, cdn) { frm._setting_hours = true; frappe.model.set_value(cdt, cdn, "to_time", d.format(frappe.defaultDatetimeFormat)).then(() => { - frm._setting_hours = false; - }); + frm._setting_hours = false; + }); } } -} +}; var update_billing_hours = function(frm, cdt, cdn){ var child = locals[cdt][cdn]; if(!child.billable) frappe.model.set_value(cdt, cdn, 'billing_hours', 0.0); -} +}; var update_time_rates = function(frm, cdt, cdn){ var child = locals[cdt][cdn]; if(!child.billable){ frappe.model.set_value(cdt, cdn, 'billing_rate', 0.0); } -} +}; var calculate_billing_costing_amount = function(frm, cdt, cdn){ var child = locals[cdt][cdn]; @@ -270,7 +274,7 @@ var calculate_billing_costing_amount = function(frm, cdt, cdn){ frappe.model.set_value(cdt, cdn, 'billing_amount', billing_amount); frappe.model.set_value(cdt, cdn, 'costing_amount', costing_amount); calculate_time_and_amount(frm); -} +}; var calculate_time_and_amount = function(frm) { var tl = frm.doc.time_logs || []; @@ -294,4 +298,17 @@ var calculate_time_and_amount = function(frm) { frm.set_value("total_hours", total_working_hr); frm.set_value("total_billable_amount", total_billable_amount); frm.set_value("total_costing_amount", total_costing_amount); -} \ No newline at end of file +}; + +// set employee (and company) to the one that's currently logged in +const set_employee_and_company = function(frm) { + const options = { user_id: frappe.session.user }; + const fields = ['name', 'company']; + frappe.db.get_value('Employee', options, fields).then(({ message }) => { + if (message) { + // there is an employee with the currently logged in user_id + frm.set_value("employee", message.name); + frm.set_value("company", message.company); + } + }); +}; diff --git a/erpnext/regional/italy/e-invoice.xml b/erpnext/regional/italy/e-invoice.xml index c886ee9aa8e..935077b7bea 100644 --- a/erpnext/regional/italy/e-invoice.xml +++ b/erpnext/regional/italy/e-invoice.xml @@ -95,13 +95,12 @@ {{ doc.customer_data.last_name }} {%- else %} - {%- if doc.customer_data.is_public_administration %} - {{ doc.customer_data.fiscal_code }} - {%- else %} {{ doc.customer_address_data.country_code }} {{ doc.tax_id | replace("IT","") }} + {%- if doc.customer_data.fiscal_code %} + {{ doc.customer_data.fiscal_code }} {%- endif %} {{ doc.customer_name }} @@ -128,22 +127,42 @@ {{ format_float(doc.stamp_duty) }} {%- endif %} - {{ format_float(doc.grand_total) }} + {%- if doc.discount_amount %} + + {%- if doc.discount_amount > 0.0 %} + SC + {%- else %} + MG + {%- endif %} + {%- if doc.additional_discount_percentage > 0.0 %} + {{ format_float(doc.additional_discount_percentage) }} + {%- endif %} + {{ format_float(doc.discount_amount) }} + + {%- endif %} + {{ format_float(doc.rounded_total or doc.grand_total) }} VENDITA - {%- if doc.po_no %} - - {{ doc.po_no }} - {%- if doc.po_date %} - {{ doc.po_date }} - {%- endif %} - - {%- endif %} + {%- for po_no, po_date in doc.customer_po_data.items() %} + + {{ po_no }} + {{ po_date }} + + {%- endfor %} {%- if doc.is_return and doc.return_against_unamended %} {{ doc.return_against_unamended }} {%- endif %} + {%- for row in doc.e_invoice_items %} + {%- if row.delivery_note %} + + {{ row.delivery_note }} + {{ frappe.db.get_value('Delivery Note', row.delivery_note, 'posting_date') }} + {{ row.idx }} + + {%- endif %} + {%- endfor %} {%- if doc.shipping_address_data %} @@ -165,7 +184,11 @@ {{ item.stock_uom }} {{ format_float(item.price_list_rate or item.rate) }} {{ render_discount_or_margin(item) }} - {{ format_float(item.amount) }} + {%- if (item.discount_amount or item.rate_with_margin) %} + {{ format_float(item.net_amount) }} + {%- else %} + {{ format_float(item.amount) }} + {%- endif %} {{ format_float(item.tax_rate) }} {%- if item.tax_exemption_reason %} {{ item.tax_exemption_reason.split("-")[0] }} @@ -199,7 +222,9 @@ {{ payment_term.mode_of_payment_code.split("-")[0] }} {{ payment_term.due_date }} {{ format_float(payment_term.payment_amount) }} - {{ payment_term.bank_account_name }} + {%- if payment_term.bank_account_name %} + {{ payment_term.bank_account_name }} + {%- endif %} {%- if payment_term.bank_account_iban %} {{ payment_term.bank_account_iban }} {{ payment_term.bank_account_iban[5:10] }} diff --git a/erpnext/regional/italy/sales_invoice.js b/erpnext/regional/italy/sales_invoice.js index 3457f7161ed..586a52937b5 100644 --- a/erpnext/regional/italy/sales_invoice.js +++ b/erpnext/regional/italy/sales_invoice.js @@ -3,15 +3,26 @@ erpnext.setup_e_invoice_button = (doctype) => { refresh: (frm) => { if(frm.doc.docstatus == 1) { frm.add_custom_button('Generate E-Invoice', () => { - var w = window.open( - frappe.urllib.get_full_url( - "/api/method/erpnext.regional.italy.utils.generate_single_invoice?" - + "docname=" + frm.doc.name - ) - ) - if (!w) { - frappe.msgprint(__("Please enable pop-ups")); return; - } + frm.call({ + method: "erpnext.regional.italy.utils.generate_single_invoice", + args: { + docname: frm.doc.name + }, + callback: function(r) { + frm.reload_doc(); + if(r.message) { + var w = window.open( + frappe.urllib.get_full_url( + "/api/method/erpnext.regional.italy.utils.download_e_invoice_file?" + + "file_name=" + r.message + ) + ) + if (!w) { + frappe.msgprint(__("Please enable pop-ups")); return; + } + } + } + }); }); } } diff --git a/erpnext/regional/italy/setup.py b/erpnext/regional/italy/setup.py index 2b6e3af52ab..1526d6f62f0 100644 --- a/erpnext/regional/italy/setup.py +++ b/erpnext/regional/italy/setup.py @@ -26,6 +26,22 @@ def make_custom_fields(update=True): print_hide=1, hidden=1, read_only=1, options="currency") ] + customer_po_fields = [ + dict(fieldname='customer_po_details', label='Customer PO', + fieldtype='Section Break', insert_after='image'), + dict(fieldname='customer_po_no', label='Customer PO No', + fieldtype='Data', insert_after='customer_po_details', + fetch_from = 'sales_order.po_no', + print_hide=1, allow_on_submit=1, fetch_if_empty= 1, read_only=1, no_copy=1), + dict(fieldname='customer_po_clm_brk', label='', + fieldtype='Column Break', insert_after='customer_po_no', + print_hide=1, read_only=1), + dict(fieldname='customer_po_date', label='Customer PO Date', + fieldtype='Date', insert_after='customer_po_clm_brk', + fetch_from = 'sales_order.po_date', + print_hide=1, allow_on_submit=1, fetch_if_empty= 1, read_only=1, no_copy=1) + ] + custom_fields = { 'Company': [ dict(fieldname='sb_e_invoicing', label='E-Invoicing', @@ -128,7 +144,7 @@ def make_custom_fields(update=True): 'Purchase Invoice Item': invoice_item_fields, 'Sales Order Item': invoice_item_fields, 'Delivery Note Item': invoice_item_fields, - 'Sales Invoice Item': invoice_item_fields, + 'Sales Invoice Item': invoice_item_fields + customer_po_fields, 'Quotation Item': invoice_item_fields, 'Purchase Order Item': invoice_item_fields, 'Purchase Receipt Item': invoice_item_fields, diff --git a/erpnext/regional/italy/utils.py b/erpnext/regional/italy/utils.py index f39b144cdc0..435faea4c97 100644 --- a/erpnext/regional/italy/utils.py +++ b/erpnext/regional/italy/utils.py @@ -82,6 +82,14 @@ def prepare_invoice(invoice, progressive_number): if item.tax_rate == 0.0 and item.tax_amount == 0.0: item.tax_exemption_reason = tax_data["0.0"]["tax_exemption_reason"] + customer_po_data = {} + for d in invoice.e_invoice_items: + if (d.customer_po_no and d.customer_po_date + and d.customer_po_no not in customer_po_data): + customer_po_data[d.customer_po_no] = d.customer_po_date + + invoice.customer_po_data = customer_po_data + return invoice def get_conditions(filters): @@ -134,6 +142,7 @@ def get_invoice_summary(items, taxes): idx=len(items)+1, item_code=reference_row.description, item_name=reference_row.description, + description=reference_row.description, rate=reference_row.tax_amount, qty=1.0, amount=reference_row.tax_amount, @@ -198,19 +207,25 @@ def sales_invoice_validate(doc): else: doc.company_fiscal_regime = company_fiscal_regime + doc.company_tax_id = frappe.get_cached_value("Company", doc.company, 'tax_id') + doc.company_fiscal_code = frappe.get_cached_value("Company", doc.company, 'fiscal_code') if not doc.company_tax_id and not doc.company_fiscal_code: frappe.throw(_("Please set either the Tax ID or Fiscal Code on Company '%s'" % doc.company), title=_("E-Invoicing Information Missing")) #Validate customer details - customer_type, is_public_administration = frappe.db.get_value("Customer", doc.customer, ["customer_type", "is_public_administration"]) - if customer_type == _("Individual"): + customer = frappe.get_doc("Customer", doc.customer) + + if customer.customer_type == _("Individual"): + doc.customer_fiscal_code = customer.fiscal_code if not doc.customer_fiscal_code: frappe.throw(_("Please set Fiscal Code for the customer '%s'" % doc.customer), title=_("E-Invoicing Information Missing")) else: - if is_public_administration: + if customer.is_public_administration: + doc.customer_fiscal_code = customer.fiscal_code if not doc.customer_fiscal_code: frappe.throw(_("Please set Fiscal Code for the public administration '%s'" % doc.customer), title=_("E-Invoicing Information Missing")) else: + doc.tax_id = customer.tax_id if not doc.tax_id: frappe.throw(_("Please set Tax ID for the customer '%s'" % doc.customer), title=_("E-Invoicing Information Missing")) @@ -266,13 +281,18 @@ def prepare_and_attach_invoice(doc, replace=False): def generate_single_invoice(docname): doc = frappe.get_doc("Sales Invoice", docname) + e_invoice = prepare_and_attach_invoice(doc, True) + return e_invoice.file_name + +@frappe.whitelist() +def download_e_invoice_file(file_name): content = None - with open(frappe.get_site_path('private', 'files', e_invoice.file_name), "r") as f: + with open(frappe.get_site_path('private', 'files', file_name), "r") as f: content = f.read() - frappe.local.response.filename = e_invoice.file_name + frappe.local.response.filename = file_name frappe.local.response.filecontent = content frappe.local.response.type = "download" diff --git a/erpnext/setup/doctype/company/company.json b/erpnext/setup/doctype/company/company.json index 77c371e0cdd..dbd7c4149f3 100644 --- a/erpnext/setup/doctype/company/company.json +++ b/erpnext/setup/doctype/company/company.json @@ -22,6 +22,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "details", "fieldtype": "Section Break", "hidden": 0, @@ -54,6 +55,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "company_name", "fieldtype": "Data", "hidden": 0, @@ -88,6 +90,7 @@ "collapsible": 0, "columns": 0, "description": "", + "fetch_if_empty": 0, "fieldname": "abbr", "fieldtype": "Data", "hidden": 0, @@ -122,6 +125,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval:!doc.__islocal && in_list(frappe.user_roles, \"System Manager\")", + "fetch_if_empty": 0, "fieldname": "change_abbr", "fieldtype": "Button", "hidden": 0, @@ -153,6 +157,7 @@ "bold": 1, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "is_group", "fieldtype": "Check", "hidden": 0, @@ -185,6 +190,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "default_finance_book", "fieldtype": "Link", "hidden": 0, @@ -218,6 +224,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "cb0", "fieldtype": "Column Break", "hidden": 0, @@ -248,6 +255,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "domain", "fieldtype": "Link", "hidden": 0, @@ -280,6 +288,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "parent_company", "fieldtype": "Link", "hidden": 0, @@ -313,6 +322,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "sb_about", "fieldtype": "Section Break", "hidden": 0, @@ -345,6 +355,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "company_logo", "fieldtype": "Attach Image", "hidden": 0, @@ -377,6 +388,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "company_description", "fieldtype": "Text Editor", "hidden": 0, @@ -409,6 +421,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "sales_settings", "fieldtype": "Section Break", "hidden": 0, @@ -441,6 +454,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "sales_monthly_history", "fieldtype": "Small Text", "hidden": 1, @@ -473,6 +487,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "transactions_annual_history", "fieldtype": "Code", "hidden": 1, @@ -505,6 +520,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "monthly_sales_target", "fieldtype": "Currency", "hidden": 0, @@ -538,6 +554,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break_goals", "fieldtype": "Column Break", "hidden": 0, @@ -569,6 +586,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "total_monthly_sales", "fieldtype": "Currency", "hidden": 0, @@ -602,6 +620,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "charts_section", "fieldtype": "Section Break", "hidden": 0, @@ -633,6 +652,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "default_currency", "fieldtype": "Link", "hidden": 0, @@ -665,6 +685,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "default_letter_head", "fieldtype": "Link", "hidden": 0, @@ -698,6 +719,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "default_holiday_list", "fieldtype": "Link", "hidden": 0, @@ -731,6 +753,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "standard_working_hours", "fieldtype": "Float", "hidden": 0, @@ -763,6 +786,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "default_terms", "fieldtype": "Link", "hidden": 0, @@ -795,6 +819,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break_10", "fieldtype": "Column Break", "hidden": 0, @@ -826,6 +851,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "country", "fieldtype": "Link", "hidden": 0, @@ -858,6 +884,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "create_chart_of_accounts_based_on", "fieldtype": "Select", "hidden": 0, @@ -892,6 +919,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval:doc.create_chart_of_accounts_based_on===\"Standard Template\"", + "fetch_if_empty": 0, "fieldname": "chart_of_accounts", "fieldtype": "Select", "hidden": 0, @@ -926,6 +954,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval:doc.create_chart_of_accounts_based_on===\"Existing Company\"", + "fetch_if_empty": 0, "fieldname": "existing_company", "fieldtype": "Link", "hidden": 0, @@ -959,6 +988,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "tax_id", "fieldtype": "Data", "hidden": 0, @@ -991,6 +1021,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "date_of_establishment", "fieldtype": "Date", "hidden": 0, @@ -1023,6 +1054,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "default_settings", "fieldtype": "Section Break", "hidden": 0, @@ -1056,6 +1088,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval:!doc.__islocal", + "fetch_if_empty": 0, "fieldname": "default_bank_account", "fieldtype": "Link", "hidden": 0, @@ -1091,6 +1124,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval:!doc.__islocal", + "fetch_if_empty": 0, "fieldname": "default_cash_account", "fieldtype": "Link", "hidden": 0, @@ -1124,6 +1158,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval:!doc.__islocal", + "fetch_if_empty": 0, "fieldname": "default_receivable_account", "fieldtype": "Link", "hidden": 0, @@ -1158,6 +1193,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "round_off_account", "fieldtype": "Link", "hidden": 0, @@ -1191,6 +1227,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "round_off_cost_center", "fieldtype": "Link", "hidden": 0, @@ -1224,6 +1261,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "write_off_account", "fieldtype": "Link", "hidden": 0, @@ -1257,6 +1295,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "discount_allowed_account", "fieldtype": "Link", "hidden": 0, @@ -1290,6 +1329,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "discount_received_account", "fieldtype": "Link", "hidden": 0, @@ -1323,6 +1363,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "exchange_gain_loss_account", "fieldtype": "Link", "hidden": 0, @@ -1356,6 +1397,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "unrealized_exchange_gain_loss_account", "fieldtype": "Link", "hidden": 0, @@ -1389,6 +1431,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break0", "fieldtype": "Column Break", "hidden": 0, @@ -1414,6 +1457,40 @@ "unique": 0, "width": "50%" }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "eval:doc.parent_company", + "fetch_if_empty": 0, + "fieldname": "allow_account_creation_against_child_company", + "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": "Allow Account Creation Against Child Company", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, { "allow_bulk_edit": 0, "allow_in_quick_entry": 0, @@ -1422,6 +1499,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval:!doc.__islocal", + "fetch_if_empty": 0, "fieldname": "default_payable_account", "fieldtype": "Link", "hidden": 0, @@ -1456,6 +1534,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "default_employee_advance_account", "fieldtype": "Link", "hidden": 0, @@ -1490,6 +1569,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval:!doc.__islocal", + "fetch_if_empty": 0, "fieldname": "default_expense_account", "fieldtype": "Link", "hidden": 0, @@ -1523,6 +1603,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval:!doc.__islocal", + "fetch_if_empty": 0, "fieldname": "default_income_account", "fieldtype": "Link", "hidden": 0, @@ -1556,6 +1637,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval:!doc.__islocal", + "fetch_if_empty": 0, "fieldname": "default_deferred_revenue_account", "fieldtype": "Link", "hidden": 0, @@ -1590,6 +1672,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval:!doc.__islocal", + "fetch_if_empty": 0, "fieldname": "default_deferred_expense_account", "fieldtype": "Link", "hidden": 0, @@ -1624,6 +1707,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval:!doc.__islocal", + "fetch_if_empty": 0, "fieldname": "default_payroll_payable_account", "fieldtype": "Link", "hidden": 0, @@ -1658,6 +1742,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval:!doc.__islocal", + "fetch_if_empty": 0, "fieldname": "default_expense_claim_payable_account", "fieldtype": "Link", "hidden": 0, @@ -1691,6 +1776,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "section_break_22", "fieldtype": "Section Break", "hidden": 0, @@ -1723,6 +1809,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval:!doc.__islocal", + "fetch_if_empty": 0, "fieldname": "cost_center", "fieldtype": "Link", "hidden": 0, @@ -1755,6 +1842,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break_26", "fieldtype": "Column Break", "hidden": 0, @@ -1787,6 +1875,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval:!doc.__islocal", + "fetch_if_empty": 0, "fieldname": "credit_limit", "fieldtype": "Currency", "hidden": 0, @@ -1822,6 +1911,7 @@ "collapsible": 0, "columns": 0, "depends_on": "", + "fetch_if_empty": 0, "fieldname": "payment_terms", "fieldtype": "Link", "hidden": 0, @@ -1856,6 +1946,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval:!doc.__islocal", + "fetch_if_empty": 0, "fieldname": "auto_accounting_for_stock_settings", "fieldtype": "Section Break", "hidden": 0, @@ -1888,6 +1979,7 @@ "collapsible": 0, "columns": 0, "default": "1", + "fetch_if_empty": 0, "fieldname": "enable_perpetual_inventory", "fieldtype": "Check", "hidden": 0, @@ -1920,6 +2012,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "default_inventory_account", "fieldtype": "Link", "hidden": 0, @@ -1953,6 +2046,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "stock_adjustment_account", "fieldtype": "Link", "hidden": 0, @@ -1985,6 +2079,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break_32", "fieldtype": "Column Break", "hidden": 0, @@ -2016,6 +2111,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "stock_received_but_not_billed", "fieldtype": "Link", "hidden": 0, @@ -2048,6 +2144,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "expenses_included_in_valuation", "fieldtype": "Link", "hidden": 0, @@ -2080,6 +2177,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "fixed_asset_depreciation_settings", "fieldtype": "Section Break", "hidden": 0, @@ -2112,6 +2210,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "accumulated_depreciation_account", "fieldtype": "Link", "hidden": 0, @@ -2145,6 +2244,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "depreciation_expense_account", "fieldtype": "Link", "hidden": 0, @@ -2178,6 +2278,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "series_for_depreciation_entry", "fieldtype": "Data", "hidden": 0, @@ -2210,6 +2311,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "expenses_included_in_asset_valuation", "fieldtype": "Link", "hidden": 0, @@ -2243,6 +2345,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break_40", "fieldtype": "Column Break", "hidden": 0, @@ -2274,6 +2377,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "disposal_account", "fieldtype": "Link", "hidden": 0, @@ -2307,6 +2411,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "depreciation_cost_center", "fieldtype": "Link", "hidden": 0, @@ -2340,6 +2445,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "capital_work_in_progress_account", "fieldtype": "Link", "hidden": 0, @@ -2373,6 +2479,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "asset_received_but_not_billed", "fieldtype": "Link", "hidden": 0, @@ -2406,6 +2513,7 @@ "bold": 0, "collapsible": 1, "columns": 0, + "fetch_if_empty": 0, "fieldname": "budget_detail", "fieldtype": "Section Break", "hidden": 0, @@ -2438,6 +2546,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "exception_budget_approver_role", "fieldtype": "Link", "hidden": 0, @@ -2472,6 +2581,7 @@ "collapsible": 0, "columns": 0, "description": "For reference only.", + "fetch_if_empty": 0, "fieldname": "company_info", "fieldtype": "Section Break", "hidden": 0, @@ -2503,6 +2613,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "date_of_incorporation", "fieldtype": "Date", "hidden": 0, @@ -2535,6 +2646,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "address_html", "fieldtype": "HTML", "hidden": 0, @@ -2566,6 +2678,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "column_break1", "fieldtype": "Column Break", "hidden": 0, @@ -2599,6 +2712,7 @@ "collapsible": 0, "columns": 0, "depends_on": "eval:doc.date_of_incorporation", + "fetch_if_empty": 0, "fieldname": "date_of_commencement", "fieldtype": "Date", "hidden": 0, @@ -2631,6 +2745,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "phone_no", "fieldtype": "Data", "hidden": 0, @@ -2665,6 +2780,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "fax", "fieldtype": "Data", "hidden": 0, @@ -2699,6 +2815,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "email", "fieldtype": "Data", "hidden": 0, @@ -2733,6 +2850,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "website", "fieldtype": "Data", "hidden": 0, @@ -2767,6 +2885,7 @@ "collapsible": 0, "columns": 0, "description": "", + "fetch_if_empty": 0, "fieldname": "registration_info", "fieldtype": "Section Break", "hidden": 0, @@ -2801,6 +2920,7 @@ "collapsible": 0, "columns": 0, "description": "Company registration numbers for your reference. Tax numbers etc.", + "fetch_if_empty": 0, "fieldname": "registration_details", "fieldtype": "Code", "hidden": 0, @@ -2834,6 +2954,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "delete_company_transactions", "fieldtype": "Button", "hidden": 0, @@ -2866,6 +2987,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "lft", "fieldtype": "Int", "hidden": 1, @@ -2898,6 +3020,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "rgt", "fieldtype": "Int", "hidden": 1, @@ -2930,6 +3053,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "old_parent", "fieldtype": "Data", "hidden": 1, @@ -2969,7 +3093,7 @@ "istable": 0, "max_attachments": 0, "menu_index": 0, - "modified": "2019-01-15 13:29:54.510379", + "modified": "2019-03-26 17:15:50.390548", "modified_by": "Administrator", "module": "Setup", "name": "Company", diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index 3a5253019af..dc9c4fc3fe8 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -802,7 +802,7 @@ class StockEntry(StockController): # item dict = { item_code: {qty, description, stock_uom} } item_dict = get_bom_items_as_dict(self.bom_no, self.company, qty=qty, - fetch_exploded = self.use_multi_level_bom) + fetch_exploded = self.use_multi_level_bom, fetch_qty_in_stock_uom=False) used_alternative_items = get_used_alternative_items(work_order = self.work_order) for item in itervalues(item_dict): @@ -1031,7 +1031,7 @@ class StockEntry(StockController): se_child.item_code = item_dict[d].get('item_code') or cstr(d) se_child.item_name = item_dict[d]["item_name"] se_child.description = item_dict[d]["description"] - se_child.uom = stock_uom + se_child.uom = item_dict[d]["uom"] if item_dict[d].get("uom") else stock_uom se_child.stock_uom = stock_uom se_child.qty = flt(item_dict[d]["qty"], se_child.precision("qty")) se_child.expense_account = item_dict[d].get("expense_account") or expense_account @@ -1049,8 +1049,9 @@ class StockEntry(StockController): se_child.t_warehouse = self.to_warehouse # in stock uom - se_child.transfer_qty = flt(item_dict[d]["qty"], se_child.precision("qty")) - se_child.conversion_factor = 1.00 + se_child.conversion_factor = flt(item_dict[d].get("conversion_factor")) or 1 + se_child.transfer_qty = flt(item_dict[d]["qty"]*se_child.conversion_factor, se_child.precision("qty")) + # to be assigned for finished item se_child.bom_no = bom_no