diff --git a/erpnext/__init__.py b/erpnext/__init__.py index d102c9e9cde..9e586b53a7f 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -2,7 +2,7 @@ from __future__ import unicode_literals import frappe -__version__ = '8.0.22' +__version__ = '8.0.23' def get_default_company(user=None): '''Get default company for user''' diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py index 4d58f987ca6..530d08a62d1 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -204,7 +204,7 @@ class PurchaseInvoice(BuyingController): if frappe.db.get_value("Buying Settings", None, "po_required") == 'Yes': for d in self.get('items'): if not d.purchase_order: - throw(_("Purchse Order number required for Item {0}").format(d.item_code)) + throw(_("Purchase Order number required for Item {0}").format(d.item_code)) def pr_required(self): stock_items = self.get_stock_items() diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index b1fe0bec844..295f649d60c 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -341,13 +341,23 @@ class SalesInvoice(SellingController): super(SalesInvoice, self).validate_with_previous_doc({ "Sales Order": { "ref_dn_field": "sales_order", - "compare_fields": [["customer", "="], ["company", "="], ["project", "="], - ["currency", "="]], + "compare_fields": [["customer", "="], ["company", "="], ["project", "="], ["currency", "="]] + }, + "Sales Order Item": { + "ref_dn_field": "so_detail", + "compare_fields": [["item_code", "="], ["uom", "="], ["conversion_factor", "="]], + "is_child_table": True, + "allow_duplicate_prev_row_id": True }, "Delivery Note": { "ref_dn_field": "delivery_note", - "compare_fields": [["customer", "="], ["company", "="], ["project", "="], - ["currency", "="]], + "compare_fields": [["customer", "="], ["company", "="], ["project", "="], ["currency", "="]] + }, + "Delivery Note Item": { + "ref_dn_field": "dn_detail", + "compare_fields": [["item_code", "="], ["uom", "="], ["conversion_factor", "="]], + "is_child_table": True, + "allow_duplicate_prev_row_id": True }, }) diff --git a/erpnext/accounts/general_ledger.py b/erpnext/accounts/general_ledger.py index 4c5535d69a4..c9345f2cafc 100644 --- a/erpnext/accounts/general_ledger.py +++ b/erpnext/accounts/general_ledger.py @@ -123,10 +123,10 @@ def round_off_debit_credit(gl_map): debit_credit_diff = flt(debit_credit_diff, precision) - if gl_map[0]["voucher_type"] == "Journal Entry": + if gl_map[0]["voucher_type"] in ("Journal Entry", "Payment Entry"): allowance = 5.0 / (10**precision) else: - allowance = 1 + allowance = .5 if abs(debit_credit_diff) >= allowance: frappe.throw(_("Debit and Credit not equal for {0} #{1}. Difference is {2}.") diff --git a/erpnext/accounts/report/purchase_register/purchase_register.py b/erpnext/accounts/report/purchase_register/purchase_register.py index 47f79f17126..1a63a9d8198 100644 --- a/erpnext/accounts/report/purchase_register/purchase_register.py +++ b/erpnext/accounts/report/purchase_register/purchase_register.py @@ -20,7 +20,7 @@ def execute(filters=None): invoice_expense_map, invoice_tax_map = get_invoice_tax_map(invoice_list, invoice_expense_map, expense_accounts) invoice_po_pr_map = get_invoice_po_pr_map(invoice_list) - supplier_details = get_supplier_deatils(invoice_list) + supplier_details = get_supplier_details(invoice_list) company_currency = frappe.db.get_value("Company", filters.company, "default_currency") @@ -205,7 +205,7 @@ def get_account_details(invoice_list): return account_map -def get_supplier_deatils(invoice_list): +def get_supplier_details(invoice_list): supplier_details = {} suppliers = list(set([inv.supplier for inv in invoice_list])) for supp in frappe.db.sql("""select name, supplier_type from `tabSupplier` diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.py b/erpnext/buying/doctype/purchase_order/purchase_order.py index 88e7d20e080..e7b0d1ac8d6 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.py +++ b/erpnext/buying/doctype/purchase_order/purchase_order.py @@ -59,7 +59,8 @@ class PurchaseOrder(BuyingController): }, "Supplier Quotation Item": { "ref_dn_field": "supplier_quotation_item", - "compare_fields": [["rate", "="], ["project", "="], ["item_code", "="]], + "compare_fields": [["rate", "="], ["project", "="], ["item_code", "="], + ["uom", "="], ["conversion_factor", "="]], "is_child_table": True } }) diff --git a/erpnext/buying/doctype/supplier/supplier.json b/erpnext/buying/doctype/supplier/supplier.json index 9adb42bb071..a590f372ec1 100644 --- a/erpnext/buying/doctype/supplier/supplier.json +++ b/erpnext/buying/doctype/supplier/supplier.json @@ -15,6 +15,7 @@ "engine": "InnoDB", "fields": [ { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -45,6 +46,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -76,6 +78,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 1, "collapsible": 0, @@ -106,6 +109,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -136,6 +140,37 @@ "unique": 0 }, { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "tax_id", + "fieldtype": "Data", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Tax ID", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -165,6 +200,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -193,6 +229,7 @@ "width": "50%" }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -224,6 +261,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -254,6 +292,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 1, "collapsible": 0, @@ -284,6 +323,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 1, @@ -313,6 +353,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -342,6 +383,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -370,6 +412,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -399,6 +442,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 1, @@ -428,6 +472,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -458,6 +503,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -487,6 +533,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -518,6 +565,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -546,6 +594,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -574,6 +623,7 @@ "width": "50%" }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -602,6 +652,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 1, @@ -631,6 +682,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -662,6 +714,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 1, @@ -692,6 +745,7 @@ "width": "50%" }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -722,6 +776,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -753,6 +808,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -794,7 +850,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2017-03-14 17:04:17.785461", + "modified": "2017-05-05 04:24:03.884380", "modified_by": "Administrator", "module": "Buying", "name": "Supplier", diff --git a/erpnext/buying/page/purchase_analytics/purchase_analytics.js b/erpnext/buying/page/purchase_analytics/purchase_analytics.js index 3e6f23bedeb..10d13213986 100644 --- a/erpnext/buying/page/purchase_analytics/purchase_analytics.js +++ b/erpnext/buying/page/purchase_analytics/purchase_analytics.js @@ -35,11 +35,7 @@ erpnext.PurchaseAnalytics = frappe.views.TreeGridReport.extend({ item_key: "supplier", parent_field: "parent_supplier_type", formatter: function(item) { - // return repl('%(value)s', { - // value: item.name, - // enc_value: encodeURIComponent(item.name) - // }); - return item.name; + return item.supplier_name ? item.supplier_name + " (" + item.name + ")" : item.name; } }, "Supplier": { @@ -47,7 +43,7 @@ erpnext.PurchaseAnalytics = frappe.views.TreeGridReport.extend({ show: false, item_key: "supplier", formatter: function(item) { - return item.name; + return item.supplier_name ? item.supplier_name + " (" + item.name + ")" : item.name; } }, "Item Group": { diff --git a/erpnext/buying/utils.py b/erpnext/buying/utils.py index 9146c58d0e9..9ad1c5cf85c 100644 --- a/erpnext/buying/utils.py +++ b/erpnext/buying/utils.py @@ -64,7 +64,7 @@ def validate_for_items(doc): validate_end_of_life(d.item_code, item.end_of_life, item.disabled) # validate stock item - if item.is_stock_item==1 and d.qty and not d.warehouse and not d.delivered_by_supplier: + if item.is_stock_item==1 and d.qty and not d.warehouse and not d.get("delivered_by_supplier"): frappe.throw(_("Warehouse is mandatory for stock Item {0} in row {1}").format(d.item_code, d.idx)) items.append(cstr(d.item_code)) diff --git a/erpnext/controllers/queries.py b/erpnext/controllers/queries.py index 88600e88cc2..81c9defb46d 100644 --- a/erpnext/controllers/queries.py +++ b/erpnext/controllers/queries.py @@ -360,7 +360,8 @@ def warehouse_query(doctype, txt, searchfield, start, page_len, filters): sub_query = """ select round(`tabBin`.actual_qty, 2) from `tabBin` where `tabBin`.warehouse = `tabWarehouse`.name {bin_conditions} """.format( - bin_conditions=get_filters_cond(doctype, filter_dict.get("Bin"), bin_conditions)) + bin_conditions=get_filters_cond(doctype, filter_dict.get("Bin"), bin_conditions), + ignore_permissions=True) response = frappe.db.sql("""select `tabWarehouse`.name, CONCAT_WS(" : ", "Actual Qty", ifnull( ({sub_query}), 0) ) as actual_qty diff --git a/erpnext/controllers/selling_controller.py b/erpnext/controllers/selling_controller.py index 1cd705b8c47..10b3607df91 100644 --- a/erpnext/controllers/selling_controller.py +++ b/erpnext/controllers/selling_controller.py @@ -170,7 +170,7 @@ class SellingController(StockController): def validate_selling_price(self): def throw_message(item_name, rate, ref_rate_field): - frappe.throw(_("""Selling price for item {0} is lower than its {1}. Selling price should be atleast {2}""") + frappe.throw(_("""Selling rate for item {0} is lower than its {1}. Selling rate should be atleast {2}""") .format(item_name, ref_rate_field, rate)) if not frappe.db.get_single_value("Selling Settings", "validate_selling_price"): @@ -178,18 +178,19 @@ class SellingController(StockController): for it in self.get("items"): last_purchase_rate, is_stock_item = frappe.db.get_value("Item", it.item_code, ["last_purchase_rate", "is_stock_item"]) - - if flt(it.base_rate) < flt(last_purchase_rate): - throw_message(it.item_name, last_purchase_rate, "last purchase rate") + last_purchase_rate_in_sales_uom = last_purchase_rate / (it.conversion_factor or 1) + if flt(it.base_rate) < flt(last_purchase_rate_in_sales_uom): + throw_message(it.item_name, last_purchase_rate_in_sales_uom, "last purchase rate") last_valuation_rate = frappe.db.sql(""" SELECT valuation_rate FROM `tabStock Ledger Entry` WHERE item_code = %s AND warehouse = %s AND valuation_rate > 0 ORDER BY posting_date DESC, posting_time DESC, name DESC LIMIT 1 """, (it.item_code, it.warehouse)) - - if is_stock_item and flt(it.base_rate) < flt(last_valuation_rate): - throw_message(it.name, last_valuation_rate, "valuation rate") + if last_valuation_rate: + last_valuation_rate_in_sales_uom = last_valuation_rate[0][0] / (it.conversion_factor or 1) + if is_stock_item and flt(it.base_rate) < flt(last_valuation_rate_in_sales_uom): + throw_message(it.name, last_valuation_rate_in_sales_uom, "valuation rate") def get_item_list(self): diff --git a/erpnext/hr/doctype/salary_slip/salary_slip.py b/erpnext/hr/doctype/salary_slip/salary_slip.py index 5182c987a63..e42295810d4 100644 --- a/erpnext/hr/doctype/salary_slip/salary_slip.py +++ b/erpnext/hr/doctype/salary_slip/salary_slip.py @@ -321,9 +321,13 @@ class SalarySlip(TransactionBase): def sum_components(self, component_type, total_field): joining_date, relieving_date = frappe.db.get_value("Employee", self.employee, ["date_of_joining", "relieving_date"]) + if not relieving_date: relieving_date = getdate(self.end_date) + if not joining_date: + frappe.throw(_("Please set the Date Of Joining for employee {0}").format(frappe.bold(employee.employee))) + for d in self.get(component_type): if ((cint(d.depends_on_lwp) == 1 and not self.salary_slip_based_on_timesheet) or\ getdate(self.start_date) < joining_date or getdate(self.end_date) > relieving_date): diff --git a/erpnext/hr/doctype/salary_structure/salary_structure.py b/erpnext/hr/doctype/salary_structure/salary_structure.py index da69bccd595..dc1c04d439d 100644 --- a/erpnext/hr/doctype/salary_structure/salary_structure.py +++ b/erpnext/hr/doctype/salary_structure/salary_structure.py @@ -33,6 +33,7 @@ class SalaryStructure(Document): for employee in self.get('employees'): joining_date, relieving_date = frappe.db.get_value("Employee", employee.employee, ["date_of_joining", "relieving_date"]) + if employee.from_date and joining_date and getdate(employee.from_date) < joining_date: frappe.throw(_("From Date {0} for Employee {1} cannot be before employee's joining Date {2}") .format(employee.from_date, employee.employee, joining_date)) diff --git a/erpnext/portal/utils.py b/erpnext/portal/utils.py index 7dffd033416..8115c1fb9ba 100644 --- a/erpnext/portal/utils.py +++ b/erpnext/portal/utils.py @@ -4,14 +4,17 @@ def set_default_role(doc, method): '''Set customer, supplier, student based on email''' if frappe.flags.setting_role or frappe.flags.in_migrate: return + + roles = frappe.get_roles(doc.name) + contact_name = frappe.get_value('Contact', dict(email_id=doc.email)) if contact_name: contact = frappe.get_doc('Contact', contact_name) for link in contact.links: frappe.flags.setting_role = True - if link.link_doctype=='Customer': + if link.link_doctype=='Customer' and 'Customer' not in roles: doc.add_roles('Customer') - elif link.link_doctype=='Supplier': + elif link.link_doctype=='Supplier' and 'Supplier' not in roles: doc.add_roles('Supplier') - elif frappe.get_value('Student', dict(student_email_id=doc.email)): + elif frappe.get_value('Student', dict(student_email_id=doc.email)) and 'Student' not in roles: doc.add_roles('Student') diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js index cbedf80a14d..65395302920 100644 --- a/erpnext/public/js/controllers/transaction.js +++ b/erpnext/public/js/controllers/transaction.js @@ -500,6 +500,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ }, get_exchange_rate: function(transaction_date, from_currency, to_currency, callback) { + if (!transaction_date || !from_currency || !to_currency) return; return frappe.call({ method: "erpnext.setup.utils.get_exchange_rate", args: { @@ -563,14 +564,14 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ } }, - conversion_factor: function(doc, cdt, cdn) { + conversion_factor: function(doc, cdt, cdn, dont_fetch_price_list_rate) { if(frappe.meta.get_docfield(cdt, "stock_qty", cdn)) { var item = frappe.get_doc(cdt, cdn); frappe.model.round_floats_in(item, ["qty", "conversion_factor"]); item.stock_qty = flt(item.qty * item.conversion_factor, precision("stock_qty", item)); refresh_field("stock_qty", item.name, item.parentfield); this.toggle_conversion_factor(item); - this.apply_price_list(item, true); + if(!dont_fetch_price_list_rate) this.apply_price_list(item, true); } }, @@ -581,7 +582,8 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ }, qty: function(doc, cdt, cdn) { - this.conversion_factor(doc, cdt, cdn); + this.conversion_factor(doc, cdt, cdn, true); + this.apply_pricing_rule(frappe.get_doc(cdt, cdn), true); }, set_dynamic_labels: function() { @@ -762,7 +764,6 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ if(calculate_taxes_and_totals) me.calculate_taxes_and_totals(); return; } - return this.frm.call({ method: "erpnext.accounts.doctype.pricing_rule.pricing_rule.apply_pricing_rule", args: { args: args }, @@ -1117,4 +1118,4 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ return method }, -}); \ No newline at end of file +}); diff --git a/erpnext/schools/doctype/student_group/student_group.js b/erpnext/schools/doctype/student_group/student_group.js index c2c6912ba07..ed9469015b3 100644 --- a/erpnext/schools/doctype/student_group/student_group.js +++ b/erpnext/schools/doctype/student_group/student_group.js @@ -42,7 +42,7 @@ frappe.ui.form.on("Student Group", { }, get_students: function(frm) { - if (frm.doc.group_based_on != "Activity") { + if (frm.doc.group_based_on == "Batch" || frm.doc.group_based_on == "Course") { var student_list = []; var max_roll_no = 0; $.each(frm.doc.students, function(i,d) { diff --git a/erpnext/selling/page/sales_analytics/sales_analytics.js b/erpnext/selling/page/sales_analytics/sales_analytics.js index 73793d43390..bb47f988f49 100644 --- a/erpnext/selling/page/sales_analytics/sales_analytics.js +++ b/erpnext/selling/page/sales_analytics/sales_analytics.js @@ -34,14 +34,16 @@ erpnext.SalesAnalytics = frappe.views.TreeGridReport.extend({ show: true, item_key: "customer", parent_field: "parent_customer_group", - formatter: function(item) { return item.customer_name || item.name; } + formatter: function(item) { + return item.customer_name? item.customer_name + " (" + item.name + ")" : item.name; + } }, "Customer": { label: __("Customer"), show: false, item_key: "customer", formatter: function(item) { - return item.customer_name || item.name; + return item.customer_name? item.customer_name + " (" + item.name + ")" : item.name; } }, "Item Group": { @@ -67,7 +69,7 @@ erpnext.SalesAnalytics = frappe.views.TreeGridReport.extend({ item_key: "customer", parent_field: "parent_territory", formatter: function(item) { - return item.name; + return item.customer_name? item.customer_name + " (" + item.name + ")" : item.name; } } } diff --git a/erpnext/setup/doctype/company/company.py b/erpnext/setup/doctype/company/company.py index c09255d506d..cc5e65d8817 100644 --- a/erpnext/setup/doctype/company/company.py +++ b/erpnext/setup/doctype/company/company.py @@ -282,7 +282,7 @@ def replace_abbr(company, old, new): if len(parts) == 1 or parts[1].lower() == old.lower(): frappe.rename_doc(dt, d[0], parts[0] + " - " + new) - for dt in ["Account", "Cost Center", "Warehouse"]: + for dt in ["Warehouse", "Account", "Cost Center"]: _rename_record(dt) frappe.db.commit() diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py index a2a0115c1b1..1c730ffd08c 100644 --- a/erpnext/stock/doctype/delivery_note/delivery_note.py +++ b/erpnext/stock/doctype/delivery_note/delivery_note.py @@ -117,18 +117,31 @@ class DeliveryNote(SellingController): if not self.installation_status: self.installation_status = 'Not Installed' def validate_with_previous_doc(self): - for fn in (("Sales Order", "against_sales_order", "so_detail"), - ("Sales Invoice", "against_sales_invoice", "si_detail")): - if filter(None, [getattr(d, fn[1], None) for d in self.get("items")]): - super(DeliveryNote, self).validate_with_previous_doc({ - fn[0]: { - "ref_dn_field": fn[1], - "compare_fields": [["customer", "="], ["company", "="], ["project", "="], - ["currency", "="]], - }, - }) + super(DeliveryNote, self).validate_with_previous_doc({ + "Sales Order": { + "ref_dn_field": "against_sales_order", + "compare_fields": [["customer", "="], ["company", "="], ["project", "="], ["currency", "="]] + }, + "Sales Order Item": { + "ref_dn_field": "so_detail", + "compare_fields": [["item_code", "="], ["uom", "="], ["conversion_factor", "="]], + "is_child_table": True, + "allow_duplicate_prev_row_id": True + }, + "Sales Invoice": { + "ref_dn_field": "against_sales_invoice", + "compare_fields": [["customer", "="], ["company", "="], ["project", "="], ["currency", "="]] + }, + "Sales Invoice Item": { + "ref_dn_field": "si_detail", + "compare_fields": [["item_code", "="], ["uom", "="], ["conversion_factor", "="]], + "is_child_table": True, + "allow_duplicate_prev_row_id": True + }, + }) - if cint(frappe.db.get_single_value('Selling Settings', 'maintain_same_sales_rate')) and not self.is_return: + if cint(frappe.db.get_single_value('Selling Settings', 'maintain_same_sales_rate')) \ + and not self.is_return: self.validate_rate_with_reference_doc([["Sales Order", "against_sales_order", "so_detail"], ["Sales Invoice", "against_sales_invoice", "si_detail"]]) diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py index 4d0c3ac8816..6a9fd249005 100644 --- a/erpnext/stock/doctype/item/item.py +++ b/erpnext/stock/doctype/item/item.py @@ -142,7 +142,7 @@ class Item(WebsiteGenerator): def make_route(self): if not self.route: - return cstr(frappe.db.get_value('Item Group', self.item_group, 'route')) + '/' + self.scrub(self.item_name) + return cstr(frappe.db.get_value('Item Group', self.item_group, 'route')) + '/' + self.scrub(self.name) def get_parents(self, context): item_group, route = frappe.db.get_value('Item Group', self.item_group, ['name', 'route']) diff --git a/erpnext/translations/ro.csv b/erpnext/translations/ro.csv index cf444a3b0e7..3f8797bbe6c 100644 --- a/erpnext/translations/ro.csv +++ b/erpnext/translations/ro.csv @@ -36,7 +36,7 @@ DocType: Purchase Receipt Item,Required By,Cerute de DocType: Delivery Note,Return Against Delivery Note,Reveni Împotriva livrare Nota DocType: Purchase Order,% Billed,% Facurat apps/erpnext/erpnext/controllers/sales_and_purchase_return.py +43,Exchange Rate must be same as {0} {1} ({2}),Rata de schimb trebuie să fie aceeași ca și {0} {1} ({2}) -DocType: Sales Invoice,Customer Name,Nume client +DocType: Sales Invoice,Customer Name,Cumpărător DocType: Vehicle,Natural Gas,Gaz natural apps/erpnext/erpnext/setup/setup_wizard/setup_wizard.py +130,Bank account cannot be named as {0},Contul bancar nu poate fi numit ca {0} DocType: Account,Heads (or groups) against which Accounting Entries are made and balances are maintained.,Heads (sau grupuri) față de care înregistrările contabile sunt făcute și soldurile sunt menținute. @@ -785,7 +785,7 @@ The tax rate you define here will be the standard tax rate for all **Items**. If #### Description of Columns -1. Calculation Type: +1. Calculation Type: - This can be on **Net Total** (that is the sum of basic amount). - **On Previous Row Total / Amount** (for cumulative taxes or charges). If you select this option, the tax will be applied as a percentage of the previous row (in the tax table) amount or total. - **Actual** (as mentioned). @@ -796,19 +796,19 @@ The tax rate you define here will be the standard tax rate for all **Items**. If 6. Amount: Tax amount. 7. Total: Cumulative total to this point. 8. Enter Row: If based on ""Previous Row Total"" you can select the row number which will be taken as a base for this calculation (default is the previous row). -9. Is this Tax included in Basic Rate?: If you check this, it means that this tax will not be shown below the item table, but will be included in the Basic Rate in your main item table. This is useful where you want give a flat price (inclusive of all taxes) price to customers.","Șablon de impozitare standard, care pot fi aplicate la toate tranzacțiile de vânzare. Acest model poate conține lista de capete fiscale și, de asemenea, mai multe capete de cheltuieli / venituri, cum ar fi ""de transport"", ""asigurare"", ""manipulare"" etc. +9. Is this Tax included in Basic Rate?: If you check this, it means that this tax will not be shown below the item table, but will be included in the Basic Rate in your main item table. This is useful where you want give a flat price (inclusive of all taxes) price to customers.","Șablon de impozitare standard, care pot fi aplicate la toate tranzacțiile de vânzare. Acest model poate conține lista de capete fiscale și, de asemenea, mai multe capete de cheltuieli / venituri, cum ar fi ""de transport"", ""asigurare"", ""manipulare"" etc. - #### Notă + #### Notă vă Rata de impozitare defini aici va fi cota de impozitare standard pentru toate Articole ** **. Dacă există articole ** **, care au preturi diferite, acestea trebuie să fie adăugate în ** Impozitul Postul ** masă în ** ** postul comandantului. - #### Descrierea de coloane + #### Descrierea de coloane - 1. Calcul Tip: + 1. Calcul Tip: - Acest lucru poate fi pe ** net total ** (care este suma cuantum de bază). - ** La rândul precedent Raport / Suma ** (pentru impozite sau taxe cumulative). Dacă selectați această opțiune, impozitul va fi aplicat ca procent din rândul anterior (în tabelul de impozitare) suma totală sau. - ** ** Real (după cum sa menționat). - 2. Șeful cont: Registrul cont în care acest impozit va fi rezervat + 2. Șeful cont: Registrul cont în care acest impozit va fi rezervat 3. Cost Center: În cazul în care taxa / taxa este un venit (cum ar fi de transport maritim) sau cheltuieli trebuie să se rezervat împotriva unui centru de cost. 4. Descriere: Descriere a taxei (care vor fi tipărite în facturi / citate). 5. Notă: Rata de Profit Brut. @@ -893,7 +893,7 @@ DocType: Employee,Provide Email Address registered in company,Furnizarea Adresa DocType: Shopping Cart Settings,Enable Checkout,activaţi Checkout apps/erpnext/erpnext/config/learn.py +202,Purchase Order to Payment,Comandă de aprovizionare de plata apps/erpnext/erpnext/stock/page/stock_balance/stock_balance.js +48,Projected Qty,Proiectat Cantitate -DocType: Sales Invoice,Payment Due Date,Data scadentă de plată +DocType: Sales Invoice,Payment Due Date,Scadentă apps/erpnext/erpnext/stock/doctype/item/item.js +340,Item Variant {0} already exists with same attributes,Postul Varianta {0} există deja cu aceleași atribute apps/erpnext/erpnext/stock/report/stock_ledger/stock_ledger.py +95,'Opening',"Deschiderea" apps/erpnext/erpnext/setup/doctype/email_digest/templates/default.html +130,Open To Do,Deschideți To Do @@ -1021,7 +1021,7 @@ apps/erpnext/erpnext/accounts/doctype/c_form/c_form.py +30,"Row {0}: Invoice {1} apps/erpnext/erpnext/accounts/doctype/journal_entry/journal_entry.py +120,Row {0}: Payment against Sales/Purchase Order should always be marked as advance,Rând {0}: Plata împotriva Vânzări / Ordinului de Procurare ar trebui să fie întotdeauna marcate ca avans apps/erpnext/erpnext/setup/setup_wizard/industry_type.py +16,Chemical,Chimic DocType: Salary Component Account,Default Bank / Cash account will be automatically updated in Salary Journal Entry when this mode is selected.,Default cont bancar / numerar vor fi actualizate automat în Jurnalul de intrare a salariului când este selectat acest mod. -apps/erpnext/erpnext/schools/doctype/grading_structure/grading_structure.py +24,"The intervals for Grade Code {0} overlaps with the grade intervals for other grades. +apps/erpnext/erpnext/schools/doctype/grading_structure/grading_structure.py +24,"The intervals for Grade Code {0} overlaps with the grade intervals for other grades. Please check intervals {0} and {1} and try again",Intervalele de cod Grad {0} se suprapune cu intervalele de grad pentru alte clase. Vă rugăm să verificați intervalele de {0} și {1} și încercați din nou DocType: BOM,Raw Material Cost(Company Currency),Brut Costul materialelor (companie Moneda) apps/erpnext/erpnext/stock/doctype/stock_entry/stock_entry.py +715,All items have already been transferred for this Production Order.,Toate articolele acestei comenzi de producție au fost deja transferate. @@ -2345,7 +2345,7 @@ The tax rate you define here will be the standard tax rate for all **Items**. If #### Description of Columns -1. Calculation Type: +1. Calculation Type: - This can be on **Net Total** (that is the sum of basic amount). - **On Previous Row Total / Amount** (for cumulative taxes or charges). If you select this option, the tax will be applied as a percentage of the previous row (in the tax table) amount or total. - **Actual** (as mentioned). @@ -2357,19 +2357,19 @@ The tax rate you define here will be the standard tax rate for all **Items**. If 7. Total: Cumulative total to this point. 8. Enter Row: If based on ""Previous Row Total"" you can select the row number which will be taken as a base for this calculation (default is the previous row). 9. Consider Tax or Charge for: In this section you can specify if the tax / charge is only for valuation (not a part of total) or only for total (does not add value to the item) or for both. -10. Add or Deduct: Whether you want to add or deduct the tax.","Șablon de impozitare standard care pot fi aplicate la toate tranzacțiile de cumpărare. Acest model poate conține lista de capete fiscale și, de asemenea, mai multe capete de cheltuieli, cum ar fi ""de transport"", ""asigurare"", ""manipulare"" etc. +10. Add or Deduct: Whether you want to add or deduct the tax.","Șablon de impozitare standard care pot fi aplicate la toate tranzacțiile de cumpărare. Acest model poate conține lista de capete fiscale și, de asemenea, mai multe capete de cheltuieli, cum ar fi ""de transport"", ""asigurare"", ""manipulare"" etc. - #### Notă + #### Notă Rata de impozitare pe care o definiți aici va fi rata de impozitare standard pentru toate Articole ** **. Dacă există articole ** **, care au preturi diferite, acestea trebuie să fie adăugate în ** Impozitul Postul ** masă în ** ** postul comandantului. - #### Descrierea de coloane + #### Descrierea de coloane - 1. Calcul Tip: + 1. Calcul Tip: - Acest lucru poate fi pe ** net total ** (care este suma cuantum de bază). - ** La rândul precedent Raport / Suma ** (pentru impozite sau taxe cumulative). Dacă selectați această opțiune, impozitul va fi aplicat ca procent din rândul anterior (în tabelul de impozitare) suma totală sau. - ** ** Real (după cum sa menționat). - 2. Șeful cont: Registrul cont în care acest impozit va fi rezervat + 2. Șeful cont: Registrul cont în care acest impozit va fi rezervat 3. Cost Center: În cazul în care taxa / taxa este un venit (cum ar fi de transport maritim) sau cheltuieli trebuie să se rezervat împotriva unui centru de cost. 4. Descriere: Descriere a taxei (care vor fi tipărite în facturi / citate). 5. Notă: Rata de Profit Brut. @@ -2579,7 +2579,7 @@ Examples: 1. Ways of addressing disputes, indemnity, liability, etc. 1. Address and Contact of your Company.","Termeni și Condiții care pot fi adăugate la vânzările și achizițiile standard. - Exemple: + Exemple: 1. Perioada de valabilitate a ofertei. 1. Conditii de plata (in avans, pe credit, parte în avans etc.). @@ -2588,7 +2588,7 @@ Examples: 1. Garantie dacă este cazul. 1. Politica de Returnare. 1. Condiții de transport maritim, dacă este cazul. - 1. Modalitati de litigii de adresare, indemnizație, răspunderea, etc. + 1. Modalitati de litigii de adresare, indemnizație, răspunderea, etc. 1. Adresa și de contact ale companiei." DocType: Attendance,Leave Type,Tip Concediu DocType: Purchase Invoice,Supplier Invoice Details,Furnizor Detalii factură @@ -3641,7 +3641,7 @@ DocType: Accounts Settings,"If enabled, the system will post accounting entries apps/erpnext/erpnext/setup/setup_wizard/industry_type.py +15,Brokerage,Brokeraj apps/erpnext/erpnext/hr/doctype/leave_application/leave_application.py +232,Attendance for employee {0} is already marked for this day,Prezență pentru angajat {0} este deja marcat pentru această zi DocType: Production Order Operation,"in Minutes -Updated via 'Time Log'","în procesul-verbal +Updated via 'Time Log'","în procesul-verbal Actualizat prin ""Ora Log""" DocType: Customer,From Lead,Din Conducere apps/erpnext/erpnext/config/manufacturing.py +13,Orders released for production.,Comenzi lansat pentru producție. @@ -3743,7 +3743,7 @@ apps/erpnext/erpnext/config/learn.py +107,Newsletters,Buletine DocType: Stock Ledger Entry,Stock Ledger Entry,Stoc Ledger intrare apps/erpnext/erpnext/selling/doctype/sales_order/sales_order.py +87,Same item has been entered multiple times,Același articol a fost introdus de mai multe ori DocType: Department,Leave Block List,Lista Concedii Blocate -DocType: Sales Invoice,Tax ID,ID impozit +DocType: Sales Invoice,Tax ID,Cod inregistrare fiscala apps/erpnext/erpnext/stock/doctype/serial_no/serial_no.py +188,Item {0} is not setup for Serial Nos. Column must be blank,Articolul {0} nu este configurat pentru Numerotare Seriala. Coloana trebuie să fie vida DocType: Accounts Settings,Accounts Settings,Setări Conturi apps/erpnext/erpnext/schools/doctype/student_applicant/student_applicant.js +7,Approve,Aproba @@ -3843,7 +3843,7 @@ apps/erpnext/erpnext/controllers/recurring_document.py +136,Please find attached apps/erpnext/erpnext/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.py +34,Bank Statement balance as per General Ledger,Banca echilibru Declarație pe General Ledger DocType: Job Applicant,Applicant Name,Nume solicitant DocType: Authorization Rule,Customer / Item Name,Client / Denumire articol -DocType: Product Bundle,"Aggregate group of **Items** into another **Item**. This is useful if you are bundling a certain **Items** into a package and you maintain stock of the packed **Items** and not the aggregate **Item**. +DocType: Product Bundle,"Aggregate group of **Items** into another **Item**. This is useful if you are bundling a certain **Items** into a package and you maintain stock of the packed **Items** and not the aggregate **Item**. The package **Item** will have ""Is Stock Item"" as ""No"" and ""Is Sales Item"" as ""Yes"". @@ -4195,7 +4195,7 @@ DocType: Purchase Invoice Item,Rejected Serial No,Respins de ordine apps/erpnext/erpnext/accounts/doctype/fiscal_year/fiscal_year.py +82,Year start date or end date is overlapping with {0}. To avoid please set company,Anul Data de începere sau de încheiere este suprapunerea cu {0}. Pentru a evita vă rugăm să setați companie apps/erpnext/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.py +157,Start date should be less than end date for Item {0},Data de începere trebuie să fie mai mică decât data de sfârșit pentru postul {0} DocType: Item,"Example: ABCD.##### -If series is set and Serial No is not mentioned in transactions, then automatic serial number will be created based on this series. If you always want to explicitly mention Serial Nos for this item. leave this blank.","Exemplu:. ABCD ##### +If series is set and Serial No is not mentioned in transactions, then automatic serial number will be created based on this series. If you always want to explicitly mention Serial Nos for this item. leave this blank.","Exemplu:. ABCD ##### Dacă seria este setat și nu de serie nu este menționat în tranzacții, numărul de atunci automat de serie va fi creat pe baza acestei serii. Dacă întotdeauna doriți să se menționeze explicit Serial nr de acest articol. părăsi acest gol." DocType: Upload Attendance,Upload Attendance,Încărcați Spectatori apps/erpnext/erpnext/stock/doctype/stock_entry/stock_entry.js +302,BOM and Manufacturing Quantity are required,BOM și cantitatea de producție sunt necesare