Merge branch 'develop' into print-uom-after-quantity-patch
diff --git a/erpnext/accounts/desk_page/accounting/accounting.json b/erpnext/accounts/desk_page/accounting/accounting.json
index 3f23ba9..045d8fb 100644
--- a/erpnext/accounts/desk_page/accounting/accounting.json
+++ b/erpnext/accounts/desk_page/accounting/accounting.json
@@ -53,7 +53,7 @@
{
"hidden": 0,
"label": "Goods and Services Tax (GST India)",
- "links": "[\n {\n \"label\": \"GST Settings\",\n \"name\": \"GST Settings\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"GST HSN Code\",\n \"name\": \"GST HSN Code\",\n \"type\": \"doctype\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"GSTR-1\",\n \"name\": \"GSTR-1\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"GSTR-2\",\n \"name\": \"GSTR-2\",\n \"type\": \"report\"\n },\n {\n \"label\": \"GSTR 3B Report\",\n \"name\": \"GSTR 3B Report\",\n \"type\": \"doctype\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"GST Sales Register\",\n \"name\": \"GST Sales Register\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"GST Purchase Register\",\n \"name\": \"GST Purchase Register\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"GST Itemised Sales Register\",\n \"name\": \"GST Itemised Sales Register\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"GST Itemised Purchase Register\",\n \"name\": \"GST Itemised Purchase Register\",\n \"type\": \"report\"\n },\n {\n \"country\": \"India\",\n \"description\": \"C-Form records\",\n \"label\": \"C-Form\",\n \"name\": \"C-Form\",\n \"type\": \"doctype\"\n }\n]"
+ "links": "[\n {\n \"label\": \"GST Settings\",\n \"name\": \"GST Settings\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"GST HSN Code\",\n \"name\": \"GST HSN Code\",\n \"type\": \"doctype\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"GSTR-1\",\n \"name\": \"GSTR-1\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"GSTR-2\",\n \"name\": \"GSTR-2\",\n \"type\": \"report\"\n },\n {\n \"label\": \"GSTR 3B Report\",\n \"name\": \"GSTR 3B Report\",\n \"type\": \"doctype\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"GST Sales Register\",\n \"name\": \"GST Sales Register\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"GST Purchase Register\",\n \"name\": \"GST Purchase Register\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"GST Itemised Sales Register\",\n \"name\": \"GST Itemised Sales Register\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"GST Itemised Purchase Register\",\n \"name\": \"GST Itemised Purchase Register\",\n \"type\": \"report\"\n },\n {\n \"country\": \"India\",\n \"description\": \"C-Form records\",\n \"label\": \"C-Form\",\n \"name\": \"C-Form\",\n \"type\": \"doctype\"\n },\n {\n \"country\": \"India\",\n \"label\": \"Lower Deduction Certificate\",\n \"name\": \"Lower Deduction Certificate\",\n \"type\": \"doctype\"\n }\n]"
},
{
"hidden": 0,
@@ -98,7 +98,7 @@
"idx": 0,
"is_standard": 1,
"label": "Accounting",
- "modified": "2020-09-09 11:45:33.766400",
+ "modified": "2020-10-08 20:31:46.022470",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Accounting",
diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py
index 34c262e..d839478 100644
--- a/erpnext/accounts/doctype/journal_entry/journal_entry.py
+++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py
@@ -22,8 +22,12 @@
return self.voucher_type
def validate(self):
+ if self.voucher_type == 'Opening Entry':
+ self.is_opening = 'Yes'
+
if not self.is_opening:
self.is_opening='No'
+
self.clearance_date = None
self.validate_party()
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry_list.js b/erpnext/accounts/doctype/payment_entry/payment_entry_list.js
index 7ea60bb..e6d83b9 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry_list.js
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry_list.js
@@ -1,12 +1,14 @@
frappe.listview_settings['Payment Entry'] = {
onload: function(listview) {
- listview.page.fields_dict.party_type.get_query = function() {
- return {
- "filters": {
- "name": ["in", Object.keys(frappe.boot.party_account_types)],
- }
+ if (listview.page.fields_dict.party_type) {
+ listview.page.fields_dict.party_type.get_query = function() {
+ return {
+ "filters": {
+ "name": ["in", Object.keys(frappe.boot.party_account_types)],
+ }
+ };
};
- };
+ }
}
};
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/pos_profile/pos_profile.js b/erpnext/accounts/doctype/pos_profile/pos_profile.js
index 8ec6a53..558e21c 100755
--- a/erpnext/accounts/doctype/pos_profile/pos_profile.js
+++ b/erpnext/accounts/doctype/pos_profile/pos_profile.js
@@ -15,15 +15,6 @@
erpnext.queries.setup_queries(frm, "Warehouse", function() {
return erpnext.queries.warehouse(frm.doc);
});
-
- frm.call({
- method: "erpnext.accounts.doctype.pos_profile.pos_profile.get_series",
- callback: function(r) {
- if(!r.exc) {
- set_field_options("naming_series", r.message);
- }
- }
- });
});
frappe.ui.form.on('POS Profile', {
diff --git a/erpnext/accounts/doctype/pos_profile/pos_profile.json b/erpnext/accounts/doctype/pos_profile/pos_profile.json
index d4c1791..999da75 100644
--- a/erpnext/accounts/doctype/pos_profile/pos_profile.json
+++ b/erpnext/accounts/doctype/pos_profile/pos_profile.json
@@ -8,7 +8,6 @@
"field_order": [
"disabled",
"section_break_2",
- "naming_series",
"customer",
"company",
"country",
@@ -60,17 +59,6 @@
"fieldtype": "Section Break"
},
{
- "fieldname": "naming_series",
- "fieldtype": "Select",
- "in_list_view": 1,
- "label": "Series",
- "no_copy": 1,
- "oldfieldname": "naming_series",
- "oldfieldtype": "Select",
- "options": "[Select]",
- "reqd": 1
- },
- {
"fieldname": "customer",
"fieldtype": "Link",
"label": "Customer",
@@ -323,7 +311,7 @@
"icon": "icon-cog",
"idx": 1,
"links": [],
- "modified": "2020-06-29 12:20:30.977272",
+ "modified": "2020-10-01 17:29:27.759088",
"modified_by": "Administrator",
"module": "Accounts",
"name": "POS Profile",
@@ -350,4 +338,4 @@
],
"sort_field": "modified",
"sort_order": "DESC"
-}
+}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/pos_profile/pos_profile.py b/erpnext/accounts/doctype/pos_profile/pos_profile.py
index 1386b70..1d160a5 100644
--- a/erpnext/accounts/doctype/pos_profile/pos_profile.py
+++ b/erpnext/accounts/doctype/pos_profile/pos_profile.py
@@ -110,10 +110,6 @@
lft >= {lft} and rgt <= {rgt} order by lft""".format(tab=group_type, lft=lft, rgt=rgt), as_dict=1)
@frappe.whitelist()
-def get_series():
- return frappe.get_meta("POS Invoice").get_field("naming_series").options or "s"
-
-@frappe.whitelist()
@frappe.validate_and_sanitize_search_inputs
def pos_profile_query(doctype, txt, searchfield, start, page_len, filters):
user = frappe.session['user']
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
index 079f599..c5260a1 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -711,7 +711,8 @@
item.item_tax_amount / self.conversion_rate)
}, item=item))
else:
- cwip_account = get_asset_account("capital_work_in_progress_account", company = self.company)
+ cwip_account = get_asset_account("capital_work_in_progress_account",
+ asset_category=item.asset_category,company=self.company)
cwip_account_currency = get_account_currency(cwip_account)
gl_entries.append(self.get_gl_dict({
diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
index 9a666bf..2e5a714 100644
--- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
@@ -1002,7 +1002,8 @@
"cost_center": args.cost_center or "_Test Cost Center - _TC",
"project": args.project,
"rejected_warehouse": args.rejected_warehouse or "",
- "rejected_serial_no": args.rejected_serial_no or ""
+ "rejected_serial_no": args.rejected_serial_no or "",
+ "asset_location": args.location or ""
})
if args.get_taxes_and_charges:
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
index 2397b7d..c7d791e 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
@@ -1825,7 +1825,7 @@
"fieldtype": "Table",
"hide_days": 1,
"hide_seconds": 1,
- "label": "Sales Team1",
+ "label": "Sales Contributions and Incentives",
"oldfieldname": "sales_team",
"oldfieldtype": "Table",
"options": "Sales Team",
@@ -1926,6 +1926,7 @@
},
{
"default": "0",
+ "depends_on": "eval:(doc.is_pos && doc.is_consolidated)",
"fieldname": "is_consolidated",
"fieldtype": "Check",
"label": "Is Consolidated",
@@ -1946,7 +1947,7 @@
"idx": 181,
"is_submittable": 1,
"links": [],
- "modified": "2020-08-27 01:56:28.532140",
+ "modified": "2020-10-09 15:59:57.544736",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Invoice",
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index 92e49d5..206340b 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -428,7 +428,7 @@
if pos.get('account_for_change_amount'):
self.account_for_change_amount = pos.get('account_for_change_amount')
- for fieldname in ('naming_series', 'currency', 'letter_head', 'tc_name',
+ for fieldname in ('currency', 'letter_head', 'tc_name',
'company', 'select_print_heading', 'write_off_account', 'taxes_and_charges',
'write_off_cost_center', 'apply_discount_on', 'cost_center'):
if (not for_validate) or (for_validate and not self.get(fieldname)):
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice_dashboard.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice_dashboard.py
index 2980213..f106928 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice_dashboard.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice_dashboard.py
@@ -13,8 +13,7 @@
'Auto Repeat': 'reference_document',
},
'internal_links': {
- 'Sales Order': ['items', 'sales_order'],
- 'Delivery Note': ['items', 'delivery_note']
+ 'Sales Order': ['items', 'sales_order']
},
'transactions': [
{
diff --git a/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py b/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py
index 83d7967..8b5e68b 100644
--- a/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py
+++ b/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py
@@ -106,6 +106,7 @@
from `tabGL Entry`
where company = %s and
party in %s and fiscal_year=%s and credit > 0
+ and is_opening = 'No'
""", (company, tuple(suppliers), fiscal_year), as_dict=1)
vouchers = [d.voucher_no for d in entries]
@@ -192,6 +193,7 @@
select distinct voucher_no
from `tabGL Entry`
where party in %s and %s and debit > 0
+ and is_opening = 'No'
""", (tuple(suppliers), condition)) or []
def get_debit_note_amount(suppliers, year_start_date, year_end_date, company=None):
diff --git a/erpnext/accounts/report/pos_register/__init__.py b/erpnext/accounts/report/pos_register/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/accounts/report/pos_register/__init__.py
diff --git a/erpnext/accounts/report/pos_register/pos_register.js b/erpnext/accounts/report/pos_register/pos_register.js
new file mode 100644
index 0000000..b8d48d9
--- /dev/null
+++ b/erpnext/accounts/report/pos_register/pos_register.js
@@ -0,0 +1,76 @@
+// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+/* eslint-disable */
+
+frappe.query_reports["POS Register"] = {
+ "filters": [
+ {
+ "fieldname":"company",
+ "label": __("Company"),
+ "fieldtype": "Link",
+ "options": "Company",
+ "default": frappe.defaults.get_user_default("Company"),
+ "reqd": 1
+ },
+ {
+ "fieldname":"from_date",
+ "label": __("From Date"),
+ "fieldtype": "Date",
+ "default": frappe.datetime.add_months(frappe.datetime.get_today(), -1),
+ "reqd": 1,
+ "width": "60px"
+ },
+ {
+ "fieldname":"to_date",
+ "label": __("To Date"),
+ "fieldtype": "Date",
+ "default": frappe.datetime.get_today(),
+ "reqd": 1,
+ "width": "60px"
+ },
+ {
+ "fieldname":"pos_profile",
+ "label": __("POS Profile"),
+ "fieldtype": "Link",
+ "options": "POS Profile"
+ },
+ {
+ "fieldname":"cashier",
+ "label": __("Cashier"),
+ "fieldtype": "Link",
+ "options": "User"
+ },
+ {
+ "fieldname":"customer",
+ "label": __("Customer"),
+ "fieldtype": "Link",
+ "options": "Customer"
+ },
+ {
+ "fieldname":"mode_of_payment",
+ "label": __("Payment Method"),
+ "fieldtype": "Link",
+ "options": "Mode of Payment"
+ },
+ {
+ "fieldname":"group_by",
+ "label": __("Group by"),
+ "fieldtype": "Select",
+ "options": ["", "POS Profile", "Cashier", "Payment Method", "Customer"],
+ "default": "POS Profile"
+ },
+ {
+ "fieldname":"is_return",
+ "label": __("Is Return"),
+ "fieldtype": "Check"
+ },
+ ],
+ "formatter": function(value, row, column, data, default_formatter) {
+ value = default_formatter(value, row, column, data);
+ if (data && data.bold) {
+ value = value.bold();
+
+ }
+ return value;
+ }
+};
diff --git a/erpnext/accounts/report/pos_register/pos_register.json b/erpnext/accounts/report/pos_register/pos_register.json
new file mode 100644
index 0000000..2398b10
--- /dev/null
+++ b/erpnext/accounts/report/pos_register/pos_register.json
@@ -0,0 +1,30 @@
+{
+ "add_total_row": 0,
+ "columns": [],
+ "creation": "2020-09-10 19:25:03.766871",
+ "disable_prepared_report": 0,
+ "disabled": 0,
+ "docstatus": 0,
+ "doctype": "Report",
+ "filters": [],
+ "idx": 0,
+ "is_standard": "Yes",
+ "json": "{}",
+ "modified": "2020-09-10 19:25:15.851331",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "POS Register",
+ "owner": "Administrator",
+ "prepared_report": 0,
+ "ref_doctype": "POS Invoice",
+ "report_name": "POS Register",
+ "report_type": "Script Report",
+ "roles": [
+ {
+ "role": "Accounts Manager"
+ },
+ {
+ "role": "Accounts User"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/erpnext/accounts/report/pos_register/pos_register.py b/erpnext/accounts/report/pos_register/pos_register.py
new file mode 100644
index 0000000..0bcde64
--- /dev/null
+++ b/erpnext/accounts/report/pos_register/pos_register.py
@@ -0,0 +1,222 @@
+# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe import _, _dict
+from erpnext import get_company_currency, get_default_company
+from erpnext.accounts.report.sales_register.sales_register import get_mode_of_payments
+
+def execute(filters=None):
+ if not filters:
+ return [], []
+
+ validate_filters(filters)
+
+ columns = get_columns(filters)
+
+ group_by_field = get_group_by_field(filters.get("group_by"))
+
+ pos_entries = get_pos_entries(filters, group_by_field)
+ if group_by_field != "mode_of_payment":
+ concat_mode_of_payments(pos_entries)
+
+ # return only entries if group by is unselected
+ if not group_by_field:
+ return columns, pos_entries
+
+ # handle grouping
+ invoice_map, grouped_data = {}, []
+ for d in pos_entries:
+ invoice_map.setdefault(d[group_by_field], []).append(d)
+
+ for key in invoice_map:
+ invoices = invoice_map[key]
+ grouped_data += invoices
+ add_subtotal_row(grouped_data, invoices, group_by_field, key)
+
+ # move group by column to first position
+ column_index = next((index for (index, d) in enumerate(columns) if d["fieldname"] == group_by_field), None)
+ columns.insert(0, columns.pop(column_index))
+
+ return columns, grouped_data
+
+def get_pos_entries(filters, group_by_field):
+ conditions = get_conditions(filters)
+ order_by = "p.posting_date"
+ select_mop_field, from_sales_invoice_payment, group_by_mop_condition = "", "", ""
+ if group_by_field == "mode_of_payment":
+ select_mop_field = ", sip.mode_of_payment"
+ from_sales_invoice_payment = ", `tabSales Invoice Payment` sip"
+ group_by_mop_condition = "sip.parent = p.name AND ifnull(sip.base_amount, 0) != 0 AND"
+ order_by += ", sip.mode_of_payment"
+
+ elif group_by_field:
+ order_by += ", p.{}".format(group_by_field)
+
+ return frappe.db.sql(
+ """
+ SELECT
+ p.posting_date, p.name as pos_invoice, p.pos_profile,
+ p.owner, p.base_grand_total as grand_total, p.base_paid_amount as paid_amount,
+ p.customer, p.is_return {select_mop_field}
+ FROM
+ `tabPOS Invoice` p {from_sales_invoice_payment}
+ WHERE
+ {group_by_mop_condition}
+ {conditions}
+ ORDER BY
+ {order_by}
+ """.format(
+ select_mop_field=select_mop_field,
+ from_sales_invoice_payment=from_sales_invoice_payment,
+ group_by_mop_condition=group_by_mop_condition,
+ conditions=conditions,
+ order_by=order_by
+ ), filters, as_dict=1)
+
+def concat_mode_of_payments(pos_entries):
+ mode_of_payments = get_mode_of_payments(set([d.pos_invoice for d in pos_entries]))
+ for entry in pos_entries:
+ if mode_of_payments.get(entry.pos_invoice):
+ entry.mode_of_payment = ", ".join(mode_of_payments.get(entry.pos_invoice, []))
+
+def add_subtotal_row(data, group_invoices, group_by_field, group_by_value):
+ grand_total = sum([d.grand_total for d in group_invoices])
+ paid_amount = sum([d.paid_amount for d in group_invoices])
+ data.append({
+ group_by_field: group_by_value,
+ "grand_total": grand_total,
+ "paid_amount": paid_amount,
+ "bold": 1
+ })
+ data.append({})
+
+def validate_filters(filters):
+ if not filters.get("company"):
+ frappe.throw(_("{0} is mandatory").format(_("Company")))
+
+ if not filters.get("from_date") and not filters.get("to_date"):
+ frappe.throw(_("{0} and {1} are mandatory").format(frappe.bold(_("From Date")), frappe.bold(_("To Date"))))
+
+ if filters.from_date > filters.to_date:
+ frappe.throw(_("From Date must be before To Date"))
+
+ if (filters.get("pos_profile") and filters.get("group_by") == _('POS Profile')):
+ frappe.throw(_("Can not filter based on POS Profile, if grouped by POS Profile"))
+
+ if (filters.get("customer") and filters.get("group_by") == _('Customer')):
+ frappe.throw(_("Can not filter based on Customer, if grouped by Customer"))
+
+ if (filters.get("owner") and filters.get("group_by") == _('Cashier')):
+ frappe.throw(_("Can not filter based on Cashier, if grouped by Cashier"))
+
+ if (filters.get("mode_of_payment") and filters.get("group_by") == _('Payment Method')):
+ frappe.throw(_("Can not filter based on Payment Method, if grouped by Payment Method"))
+
+def get_conditions(filters):
+ conditions = "company = %(company)s AND posting_date >= %(from_date)s AND posting_date <= %(to_date)s".format(
+ company=filters.get("company"),
+ from_date=filters.get("from_date"),
+ to_date=filters.get("to_date"))
+
+ if filters.get("pos_profile"):
+ conditions += " AND pos_profile = %(pos_profile)s".format(pos_profile=filters.get("pos_profile"))
+
+ if filters.get("owner"):
+ conditions += " AND owner = %(owner)s".format(owner=filters.get("owner"))
+
+ if filters.get("customer"):
+ conditions += " AND customer = %(customer)s".format(customer=filters.get("customer"))
+
+ if filters.get("is_return"):
+ conditions += " AND is_return = %(is_return)s".format(is_return=filters.get("is_return"))
+
+ if filters.get("mode_of_payment"):
+ conditions += """
+ AND EXISTS(
+ SELECT name FROM `tabSales Invoice Payment` sip
+ WHERE parent=p.name AND ifnull(sip.mode_of_payment, '') = %(mode_of_payment)s
+ )"""
+
+ return conditions
+
+def get_group_by_field(group_by):
+ group_by_field = ""
+
+ if group_by == "POS Profile":
+ group_by_field = "pos_profile"
+ elif group_by == "Cashier":
+ group_by_field = "owner"
+ elif group_by == "Customer":
+ group_by_field = "customer"
+ elif group_by == "Payment Method":
+ group_by_field = "mode_of_payment"
+
+ return group_by_field
+
+def get_columns(filters):
+ columns = [
+ {
+ "label": _("Posting Date"),
+ "fieldname": "posting_date",
+ "fieldtype": "Date",
+ "width": 90
+ },
+ {
+ "label": _("POS Invoice"),
+ "fieldname": "pos_invoice",
+ "fieldtype": "Link",
+ "options": "POS Invoice",
+ "width": 120
+ },
+ {
+ "label": _("Customer"),
+ "fieldname": "customer",
+ "fieldtype": "Link",
+ "options": "Customer",
+ "width": 120
+ },
+ {
+ "label": _("POS Profile"),
+ "fieldname": "pos_profile",
+ "fieldtype": "Link",
+ "options": "POS Profile",
+ "width": 160
+ },
+ {
+ "label": _("Cashier"),
+ "fieldname": "owner",
+ "fieldtype": "Link",
+ "options": "User",
+ "width": 140
+ },
+ {
+ "label": _("Grand Total"),
+ "fieldname": "grand_total",
+ "fieldtype": "Currency",
+ "options": "company:currency",
+ "width": 120
+ },
+ {
+ "label": _("Paid Amount"),
+ "fieldname": "paid_amount",
+ "fieldtype": "Currency",
+ "options": "company:currency",
+ "width": 120
+ },
+ {
+ "label": _("Payment Method"),
+ "fieldname": "mode_of_payment",
+ "fieldtype": "Data",
+ "width": 150
+ },
+ {
+ "label": _("Is Return"),
+ "fieldname": "is_return",
+ "fieldtype": "Data",
+ "width": 80
+ },
+ ]
+
+ return columns
\ No newline at end of file
diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py
index efdbdb1..30abc66 100644
--- a/erpnext/assets/doctype/asset/asset.py
+++ b/erpnext/assets/doctype/asset/asset.py
@@ -131,7 +131,7 @@
def validate_gross_and_purchase_amount(self):
if self.is_existing_asset: return
-
+
if self.gross_purchase_amount and self.gross_purchase_amount != self.purchase_receipt_amount:
frappe.throw(_("Gross Purchase Amount should be {} to purchase amount of one single Asset. {}\
Please do not book expense of multiple assets against one single Asset.")
@@ -466,50 +466,63 @@
def validate_make_gl_entry(self):
purchase_document = self.get_purchase_document()
- asset_bought_with_invoice = purchase_document == self.purchase_invoice
- fixed_asset_account, cwip_account = self.get_asset_accounts()
- cwip_enabled = is_cwip_accounting_enabled(self.asset_category)
- # check if expense already has been booked in case of cwip was enabled after purchasing asset
- expense_booked = False
- cwip_booked = False
-
- if asset_bought_with_invoice:
- expense_booked = frappe.db.sql("""SELECT name FROM `tabGL Entry` WHERE voucher_no = %s and account = %s""",
- (purchase_document, fixed_asset_account), as_dict=1)
- else:
- cwip_booked = frappe.db.sql("""SELECT name FROM `tabGL Entry` WHERE voucher_no = %s and account = %s""",
- (purchase_document, cwip_account), as_dict=1)
-
- if cwip_enabled and (expense_booked or not cwip_booked):
- # if expense has already booked from invoice or cwip is booked from receipt
+ if not purchase_document:
return False
- elif not cwip_enabled and (not expense_booked or cwip_booked):
- # if cwip is disabled but expense hasn't been booked yet
- return True
- elif cwip_enabled:
- # default condition
- return True
+
+ asset_bought_with_invoice = (purchase_document == self.purchase_invoice)
+ fixed_asset_account = self.get_fixed_asset_account()
+
+ cwip_enabled = is_cwip_accounting_enabled(self.asset_category)
+ cwip_account = self.get_cwip_account(cwip_enabled=cwip_enabled)
+
+ query = """SELECT name FROM `tabGL Entry` WHERE voucher_no = %s and account = %s"""
+ if asset_bought_with_invoice:
+ # with invoice purchase either expense or cwip has been booked
+ expense_booked = frappe.db.sql(query, (purchase_document, fixed_asset_account), as_dict=1)
+ if expense_booked:
+ # if expense is already booked from invoice then do not make gl entries regardless of cwip enabled/disabled
+ return False
+
+ cwip_booked = frappe.db.sql(query, (purchase_document, cwip_account), as_dict=1)
+ if cwip_booked:
+ # if cwip is booked from invoice then make gl entries regardless of cwip enabled/disabled
+ return True
+ else:
+ # with receipt purchase either cwip has been booked or no entries have been made
+ if not cwip_account:
+ # if cwip account isn't available do not make gl entries
+ return False
+
+ cwip_booked = frappe.db.sql(query, (purchase_document, cwip_account), as_dict=1)
+ # if cwip is not booked from receipt then do not make gl entries
+ # if cwip is booked from receipt then make gl entries
+ return cwip_booked
def get_purchase_document(self):
asset_bought_with_invoice = self.purchase_invoice and frappe.db.get_value('Purchase Invoice', self.purchase_invoice, 'update_stock')
purchase_document = self.purchase_invoice if asset_bought_with_invoice else self.purchase_receipt
return purchase_document
+
+ def get_fixed_asset_account(self):
+ return get_asset_category_account('fixed_asset_account', None, self.name, None, self.asset_category, self.company)
+
+ def get_cwip_account(self, cwip_enabled=False):
+ cwip_account = None
+ try:
+ cwip_account = get_asset_account("capital_work_in_progress_account", self.name, self.asset_category, self.company)
+ except:
+ # if no cwip account found in category or company and "cwip is enabled" then raise else silently pass
+ if cwip_enabled:
+ raise
- def get_asset_accounts(self):
- fixed_asset_account = get_asset_category_account('fixed_asset_account', asset=self.name,
- asset_category = self.asset_category, company = self.company)
-
- cwip_account = get_asset_account("capital_work_in_progress_account",
- self.name, self.asset_category, self.company)
-
- return fixed_asset_account, cwip_account
+ return cwip_account
def make_gl_entries(self):
gl_entries = []
purchase_document = self.get_purchase_document()
- fixed_asset_account, cwip_account = self.get_asset_accounts()
+ fixed_asset_account, cwip_account = self.get_fixed_asset_account(), self.get_cwip_account()
if (purchase_document and self.purchase_receipt_amount and self.available_for_use_date <= nowdate()):
@@ -561,14 +574,18 @@
return 100 * (1 - flt(depreciation_rate, float_precision))
def update_maintenance_status():
- assets = frappe.get_all('Asset', filters = {'docstatus': 1, 'maintenance_required': 1})
+ assets = frappe.get_all(
+ "Asset", filters={"docstatus": 1, "maintenance_required": 1}
+ )
for asset in assets:
asset = frappe.get_doc("Asset", asset.name)
- if frappe.db.exists('Asset Maintenance Task', {'parent': asset.name, 'next_due_date': today()}):
- asset.set_status('In Maintenance')
- if frappe.db.exists('Asset Repair', {'asset_name': asset.name, 'repair_status': 'Pending'}):
- asset.set_status('Out of Order')
+ if frappe.db.exists("Asset Repair", {"asset_name": asset.name, "repair_status": "Pending"}):
+ asset.set_status("Out of Order")
+ elif frappe.db.exists("Asset Maintenance Task", {"parent": asset.name, "next_due_date": today()}):
+ asset.set_status("In Maintenance")
+ else:
+ asset.set_status()
def make_post_gl_entry():
diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py
index 52039c1..a0d7603 100644
--- a/erpnext/assets/doctype/asset/test_asset.py
+++ b/erpnext/assets/doctype/asset/test_asset.py
@@ -9,6 +9,7 @@
from erpnext.assets.doctype.asset.depreciation import post_depreciation_entries, scrap_asset, restore_asset
from erpnext.assets.doctype.asset.asset import make_sales_invoice
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt
+from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice
from erpnext.stock.doctype.purchase_receipt.purchase_receipt import make_purchase_invoice as make_invoice
class TestAsset(unittest.TestCase):
@@ -558,81 +559,6 @@
self.assertEqual(gle, expected_gle)
- def test_gle_with_cwip_toggling(self):
- # TEST: purchase an asset with cwip enabled and then disable cwip and try submitting the asset
- frappe.db.set_value("Asset Category", "Computers", "enable_cwip_accounting", 1)
-
- pr = make_purchase_receipt(item_code="Macbook Pro",
- qty=1, rate=5000, do_not_submit=True, location="Test Location")
- pr.set('taxes', [{
- 'category': 'Total',
- 'add_deduct_tax': 'Add',
- 'charge_type': 'On Net Total',
- 'account_head': '_Test Account Service Tax - _TC',
- 'description': '_Test Account Service Tax',
- 'cost_center': 'Main - _TC',
- 'rate': 5.0
- }, {
- 'category': 'Valuation and Total',
- 'add_deduct_tax': 'Add',
- 'charge_type': 'On Net Total',
- 'account_head': '_Test Account Shipping Charges - _TC',
- 'description': '_Test Account Shipping Charges',
- 'cost_center': 'Main - _TC',
- 'rate': 5.0
- }])
- pr.submit()
- expected_gle = (
- ("Asset Received But Not Billed - _TC", 0.0, 5250.0),
- ("CWIP Account - _TC", 5250.0, 0.0)
- )
- pr_gle = frappe.db.sql("""select account, debit, credit from `tabGL Entry`
- where voucher_type='Purchase Receipt' and voucher_no = %s
- order by account""", pr.name)
- self.assertEqual(pr_gle, expected_gle)
-
- pi = make_invoice(pr.name)
- pi.submit()
- expected_gle = (
- ("_Test Account Service Tax - _TC", 250.0, 0.0),
- ("_Test Account Shipping Charges - _TC", 250.0, 0.0),
- ("Asset Received But Not Billed - _TC", 5250.0, 0.0),
- ("Creditors - _TC", 0.0, 5500.0),
- ("Expenses Included In Asset Valuation - _TC", 0.0, 250.0),
- )
- pi_gle = frappe.db.sql("""select account, debit, credit from `tabGL Entry`
- where voucher_type='Purchase Invoice' and voucher_no = %s
- order by account""", pi.name)
- self.assertEqual(pi_gle, expected_gle)
-
- asset = frappe.db.get_value('Asset', {'purchase_receipt': pr.name, 'docstatus': 0}, 'name')
- asset_doc = frappe.get_doc('Asset', asset)
- month_end_date = get_last_day(nowdate())
- asset_doc.available_for_use_date = nowdate() if nowdate() != month_end_date else add_days(nowdate(), -15)
- self.assertEqual(asset_doc.gross_purchase_amount, 5250.0)
- asset_doc.append("finance_books", {
- "expected_value_after_useful_life": 200,
- "depreciation_method": "Straight Line",
- "total_number_of_depreciations": 3,
- "frequency_of_depreciation": 10,
- "depreciation_start_date": month_end_date
- })
-
- # disable cwip and try submitting
- frappe.db.set_value("Asset Category", "Computers", "enable_cwip_accounting", 0)
- asset_doc.submit()
- # asset should have gl entries even if cwip is disabled
- expected_gle = (
- ("_Test Fixed Asset - _TC", 5250.0, 0.0),
- ("CWIP Account - _TC", 0.0, 5250.0)
- )
- gle = frappe.db.sql("""select account, debit, credit from `tabGL Entry`
- where voucher_type='Asset' and voucher_no = %s
- order by account""", asset_doc.name)
- self.assertEqual(gle, expected_gle)
-
- frappe.db.set_value("Asset Category", "Computers", "enable_cwip_accounting", 1)
-
def test_expense_head(self):
pr = make_purchase_receipt(item_code="Macbook Pro",
qty=2, rate=200000.0, location="Test Location")
@@ -640,6 +566,74 @@
doc = make_invoice(pr.name)
self.assertEquals('Asset Received But Not Billed - _TC', doc.items[0].expense_account)
+
+ def test_asset_cwip_toggling_cases(self):
+ cwip = frappe.db.get_value("Asset Category", "Computers", "enable_cwip_accounting")
+ name = frappe.db.get_value("Asset Category Account", filters={"parent": "Computers"}, fieldname=["name"])
+ cwip_acc = "CWIP Account - _TC"
+
+ frappe.db.set_value("Asset Category", "Computers", "enable_cwip_accounting", 0)
+ frappe.db.set_value("Asset Category Account", name, "capital_work_in_progress_account", "")
+ frappe.db.get_value("Company", "_Test Company", "capital_work_in_progress_account", "")
+
+ # case 0 -- PI with cwip disable, Asset with cwip disabled, No cwip account set
+ pi = make_purchase_invoice(item_code="Macbook Pro", qty=1, rate=200000.0, location="Test Location", update_stock=1)
+ asset = frappe.db.get_value('Asset', {'purchase_invoice': pi.name, 'docstatus': 0}, 'name')
+ asset_doc = frappe.get_doc('Asset', asset)
+ asset_doc.available_for_use_date = nowdate()
+ asset_doc.calculate_depreciation = 0
+ asset_doc.submit()
+ gle = frappe.db.sql("""select name from `tabGL Entry` where voucher_type='Asset' and voucher_no = %s""", asset_doc.name)
+ self.assertFalse(gle)
+
+ # case 1 -- PR with cwip disabled, Asset with cwip enabled
+ pr = make_purchase_receipt(item_code="Macbook Pro", qty=1, rate=200000.0, location="Test Location")
+ frappe.db.set_value("Asset Category", "Computers", "enable_cwip_accounting", 1)
+ frappe.db.set_value("Asset Category Account", name, "capital_work_in_progress_account", cwip_acc)
+ asset = frappe.db.get_value('Asset', {'purchase_receipt': pr.name, 'docstatus': 0}, 'name')
+ asset_doc = frappe.get_doc('Asset', asset)
+ asset_doc.available_for_use_date = nowdate()
+ asset_doc.calculate_depreciation = 0
+ asset_doc.submit()
+ gle = frappe.db.sql("""select name from `tabGL Entry` where voucher_type='Asset' and voucher_no = %s""", asset_doc.name)
+ self.assertFalse(gle)
+
+ # case 2 -- PR with cwip enabled, Asset with cwip disabled
+ pr = make_purchase_receipt(item_code="Macbook Pro", qty=1, rate=200000.0, location="Test Location")
+ frappe.db.set_value("Asset Category", "Computers", "enable_cwip_accounting", 0)
+ asset = frappe.db.get_value('Asset', {'purchase_receipt': pr.name, 'docstatus': 0}, 'name')
+ asset_doc = frappe.get_doc('Asset', asset)
+ asset_doc.available_for_use_date = nowdate()
+ asset_doc.calculate_depreciation = 0
+ asset_doc.submit()
+ gle = frappe.db.sql("""select name from `tabGL Entry` where voucher_type='Asset' and voucher_no = %s""", asset_doc.name)
+ self.assertTrue(gle)
+
+ # case 3 -- PI with cwip disabled, Asset with cwip enabled
+ pi = make_purchase_invoice(item_code="Macbook Pro", qty=1, rate=200000.0, location="Test Location", update_stock=1)
+ frappe.db.set_value("Asset Category", "Computers", "enable_cwip_accounting", 1)
+ asset = frappe.db.get_value('Asset', {'purchase_invoice': pi.name, 'docstatus': 0}, 'name')
+ asset_doc = frappe.get_doc('Asset', asset)
+ asset_doc.available_for_use_date = nowdate()
+ asset_doc.calculate_depreciation = 0
+ asset_doc.submit()
+ gle = frappe.db.sql("""select name from `tabGL Entry` where voucher_type='Asset' and voucher_no = %s""", asset_doc.name)
+ self.assertFalse(gle)
+
+ # case 4 -- PI with cwip enabled, Asset with cwip disabled
+ pi = make_purchase_invoice(item_code="Macbook Pro", qty=1, rate=200000.0, location="Test Location", update_stock=1)
+ frappe.db.set_value("Asset Category", "Computers", "enable_cwip_accounting", 0)
+ asset = frappe.db.get_value('Asset', {'purchase_invoice': pi.name, 'docstatus': 0}, 'name')
+ asset_doc = frappe.get_doc('Asset', asset)
+ asset_doc.available_for_use_date = nowdate()
+ asset_doc.calculate_depreciation = 0
+ asset_doc.submit()
+ gle = frappe.db.sql("""select name from `tabGL Entry` where voucher_type='Asset' and voucher_no = %s""", asset_doc.name)
+ self.assertTrue(gle)
+
+ frappe.db.set_value("Asset Category", "Computers", "enable_cwip_accounting", cwip)
+ frappe.db.set_value("Asset Category Account", name, "capital_work_in_progress_account", cwip_acc)
+ frappe.db.get_value("Company", "_Test Company", "capital_work_in_progress_account", cwip_acc)
def create_asset_data():
if not frappe.db.exists("Asset Category", "Computers"):
diff --git a/erpnext/assets/doctype/asset_category/asset_category.py b/erpnext/assets/doctype/asset_category/asset_category.py
index 9a33fc1..46620d5 100644
--- a/erpnext/assets/doctype/asset_category/asset_category.py
+++ b/erpnext/assets/doctype/asset_category/asset_category.py
@@ -5,7 +5,7 @@
from __future__ import unicode_literals
import frappe
from frappe import _
-from frappe.utils import cint
+from frappe.utils import cint, get_link_to_form
from frappe.model.document import Document
class AssetCategory(Document):
@@ -13,6 +13,7 @@
self.validate_finance_books()
self.validate_account_types()
self.validate_account_currency()
+ self.valide_cwip_account()
def validate_finance_books(self):
for d in self.finance_books:
@@ -58,6 +59,21 @@
frappe.throw(_("Row #{}: {} of {} should be {}. Please modify the account or select a different account.")
.format(d.idx, frappe.unscrub(key_to_match), frappe.bold(selected_account), frappe.bold(expected_key_type)),
title=_("Invalid Account"))
+
+ def valide_cwip_account(self):
+ if self.enable_cwip_accounting:
+ missing_cwip_accounts_for_company = []
+ for d in self.accounts:
+ if (not d.capital_work_in_progress_account and
+ not frappe.db.get_value("Company", d.company_name, "capital_work_in_progress_account")):
+ missing_cwip_accounts_for_company.append(get_link_to_form("Company", d.company_name))
+
+ if missing_cwip_accounts_for_company:
+ msg = _("""To enable Capital Work in Progress Accounting, """)
+ msg += _("""you must select Capital Work in Progress Account in accounts table""")
+ msg += "<br><br>"
+ msg += _("You can also set default CWIP account in Company {}").format(", ".join(missing_cwip_accounts_for_company))
+ frappe.throw(msg, title=_("Missing Account"))
@frappe.whitelist()
diff --git a/erpnext/assets/doctype/asset_category/test_asset_category.py b/erpnext/assets/doctype/asset_category/test_asset_category.py
index b32f9b5..39b79d6 100644
--- a/erpnext/assets/doctype/asset_category/test_asset_category.py
+++ b/erpnext/assets/doctype/asset_category/test_asset_category.py
@@ -26,4 +26,22 @@
asset_category.insert()
except frappe.DuplicateEntryError:
pass
-
\ No newline at end of file
+
+ def test_cwip_accounting(self):
+ company_cwip_acc = frappe.db.get_value("Company", "_Test Company", "capital_work_in_progress_account")
+ frappe.db.set_value("Company", "_Test Company", "capital_work_in_progress_account", "")
+
+ asset_category = frappe.new_doc("Asset Category")
+ asset_category.asset_category_name = "Computers"
+ asset_category.enable_cwip_accounting = 1
+
+ asset_category.total_number_of_depreciations = 3
+ asset_category.frequency_of_depreciation = 3
+ asset_category.append("accounts", {
+ "company_name": "_Test Company",
+ "fixed_asset_account": "_Test Fixed Asset - _TC",
+ "accumulated_depreciation_account": "_Test Accumulated Depreciations - _TC",
+ "depreciation_expense_account": "_Test Depreciations - _TC"
+ })
+
+ self.assertRaises(frappe.ValidationError, asset_category.insert)
\ No newline at end of file
diff --git a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js
index 4a937f7..cf5d7cd 100644
--- a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js
+++ b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js
@@ -179,7 +179,7 @@
dialog.hide();
return frappe.call({
type: "GET",
- method: "erpnext.buying.doctype.request_for_quotation.request_for_quotation.make_supplier_quotation",
+ method: "erpnext.buying.doctype.request_for_quotation.request_for_quotation.make_supplier_quotation_from_rfq",
args: {
"source_name": doc.name,
"for_supplier": args.supplier
diff --git a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py
index b54a585..361ccdf 100644
--- a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py
+++ b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py
@@ -214,14 +214,14 @@
and `tabDynamic Link`.link_name like %(txt)s) and `tabContact`.name = `tabDynamic Link`.parent
limit %(start)s, %(page_len)s""", {"start": start, "page_len":page_len, "txt": "%%%s%%" % txt, "name": filters.get('supplier')})
-# This method is used to make supplier quotation from material request form.
@frappe.whitelist()
-def make_supplier_quotation(source_name, for_supplier, target_doc=None):
+def make_supplier_quotation_from_rfq(source_name, target_doc=None, for_supplier=None):
def postprocess(source, target_doc):
- target_doc.supplier = for_supplier
- args = get_party_details(for_supplier, party_type="Supplier", ignore_permissions=True)
- target_doc.currency = args.currency or get_party_account_currency('Supplier', for_supplier, source.company)
- target_doc.buying_price_list = args.buying_price_list or frappe.db.get_value('Buying Settings', None, 'buying_price_list')
+ if for_supplier:
+ target_doc.supplier = for_supplier
+ args = get_party_details(for_supplier, party_type="Supplier", ignore_permissions=True)
+ target_doc.currency = args.currency or get_party_account_currency('Supplier', for_supplier, source.company)
+ target_doc.buying_price_list = args.buying_price_list or frappe.db.get_value('Buying Settings', None, 'buying_price_list')
set_missing_values(source, target_doc)
doclist = get_mapped_doc("Request for Quotation", source_name, {
@@ -354,3 +354,32 @@
frappe.cache().hset("Supplier", "Tags", tags)
return frappe.cache().hget("Supplier", "Tags")
+
+@frappe.whitelist()
+@frappe.validate_and_sanitize_search_inputs
+def get_rfq_containing_supplier(doctype, txt, searchfield, start, page_len, filters):
+ conditions = ""
+ if txt:
+ conditions += "and rfq.name like '%%"+txt+"%%' "
+
+ if filters.get("transaction_date"):
+ conditions += "and rfq.transaction_date = '{0}'".format(filters.get("transaction_date"))
+
+ rfq_data = frappe.db.sql("""
+ select
+ distinct rfq.name, rfq.transaction_date,
+ rfq.company
+ from
+ `tabRequest for Quotation` rfq, `tabRequest for Quotation Supplier` rfq_supplier
+ where
+ rfq.name = rfq_supplier.parent
+ and rfq_supplier.supplier = '{0}'
+ and rfq.docstatus = 1
+ and rfq.company = '{1}'
+ {2}
+ order by rfq.transaction_date ASC
+ limit %(page_len)s offset %(start)s """ \
+ .format(filters.get("supplier"), filters.get("company"), conditions),
+ {"page_len": page_len, "start": start}, as_dict=1)
+
+ return rfq_data
\ No newline at end of file
diff --git a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.js b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.js
index 1b8b404..3376e82 100644
--- a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.js
+++ b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.js
@@ -8,8 +8,7 @@
setup: function() {
this.frm.custom_make_buttons = {
'Purchase Order': 'Purchase Order',
- 'Quotation': 'Quotation',
- 'Subscription': 'Subscription'
+ 'Quotation': 'Quotation'
}
this._super();
@@ -28,12 +27,6 @@
cur_frm.page.set_inner_btn_group_as_primary(__('Create'));
cur_frm.add_custom_button(__("Quotation"), this.make_quotation,
__('Create'));
-
- if(!this.frm.doc.auto_repeat) {
- cur_frm.add_custom_button(__('Subscription'), function() {
- erpnext.utils.make_subscription(me.frm.doc.doctype, me.frm.doc.name)
- }, __('Create'))
- }
}
else if (this.frm.doc.docstatus===0) {
@@ -54,6 +47,27 @@
}
})
}, __("Get items from"));
+
+ this.frm.add_custom_button(__("Request for Quotation"),
+ function() {
+ if (!me.frm.doc.supplier) {
+ frappe.throw({message:__("Please select a Supplier"), title:__("Mandatory")})
+ }
+ erpnext.utils.map_current_doc({
+ method: "erpnext.buying.doctype.request_for_quotation.request_for_quotation.make_supplier_quotation_from_rfq",
+ source_doctype: "Request for Quotation",
+ target: me.frm,
+ setters: {
+ company: me.frm.doc.company,
+ transaction_date: null
+ },
+ get_query_filters: {
+ supplier: me.frm.doc.supplier
+ },
+ get_query_method: "erpnext.buying.doctype.request_for_quotation.request_for_quotation.get_rfq_containing_supplier"
+
+ })
+ }, __("Get items from"));
}
},
diff --git a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json
index 660dcff..9a092ca 100644
--- a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json
+++ b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json
@@ -159,6 +159,7 @@
"default": "Today",
"fieldname": "transaction_date",
"fieldtype": "Date",
+ "in_list_view": 1,
"label": "Date",
"oldfieldname": "transaction_date",
"oldfieldtype": "Date",
@@ -798,6 +799,7 @@
{
"fieldname": "valid_till",
"fieldtype": "Date",
+ "in_list_view": 1,
"label": "Valid Till"
}
],
@@ -805,7 +807,7 @@
"idx": 29,
"is_submittable": 1,
"links": [],
- "modified": "2020-07-18 05:10:45.556792",
+ "modified": "2020-10-01 20:56:17.932007",
"modified_by": "Administrator",
"module": "Buying",
"name": "Supplier Quotation",
diff --git a/erpnext/buying/doctype/supplier_quotation_item/supplier_quotation_item.json b/erpnext/buying/doctype/supplier_quotation_item/supplier_quotation_item.json
index b50e834..7d62435 100644
--- a/erpnext/buying/doctype/supplier_quotation_item/supplier_quotation_item.json
+++ b/erpnext/buying/doctype/supplier_quotation_item/supplier_quotation_item.json
@@ -12,6 +12,8 @@
"item_name",
"column_break_3",
"lead_time_days",
+ "expected_delivery_date",
+ "is_free_item",
"section_break_5",
"description",
"item_group",
@@ -19,20 +21,18 @@
"col_break1",
"image",
"image_view",
- "manufacture_details",
- "manufacturer",
- "column_break_15",
- "manufacturer_part_no",
"quantity_and_rate",
"qty",
"stock_uom",
- "price_list_rate",
- "discount_percentage",
- "discount_amount",
"col_break2",
"uom",
"conversion_factor",
"stock_qty",
+ "sec_break_price_list",
+ "price_list_rate",
+ "discount_percentage",
+ "discount_amount",
+ "col_break_price_list",
"base_price_list_rate",
"sec_break1",
"rate",
@@ -42,7 +42,6 @@
"base_rate",
"base_amount",
"pricing_rules",
- "is_free_item",
"section_break_24",
"net_rate",
"net_amount",
@@ -56,7 +55,6 @@
"weight_uom",
"warehouse_and_reference",
"warehouse",
- "project",
"prevdoc_doctype",
"material_request",
"sales_order",
@@ -65,13 +63,19 @@
"material_request_item",
"request_for_quotation_item",
"item_tax_rate",
+ "manufacture_details",
+ "manufacturer",
+ "column_break_15",
+ "manufacturer_part_no",
+ "ad_sec_break",
+ "project",
"section_break_44",
"page_break"
],
"fields": [
{
"bold": 1,
- "columns": 4,
+ "columns": 2,
"fieldname": "item_code",
"fieldtype": "Link",
"in_list_view": 1,
@@ -107,7 +111,7 @@
{
"fieldname": "lead_time_days",
"fieldtype": "Int",
- "label": "Lead Time in days"
+ "label": "Supplier Lead Time (days)"
},
{
"collapsible": 1,
@@ -162,7 +166,6 @@
{
"fieldname": "stock_uom",
"fieldtype": "Link",
- "in_list_view": 1,
"label": "Stock UOM",
"options": "UOM",
"print_hide": 1,
@@ -196,6 +199,7 @@
{
"fieldname": "uom",
"fieldtype": "Link",
+ "in_list_view": 1,
"label": "UOM",
"options": "UOM",
"print_hide": 1,
@@ -290,14 +294,6 @@
"read_only": 1
},
{
- "default": "0",
- "fieldname": "is_free_item",
- "fieldtype": "Check",
- "label": "Is Free Item",
- "print_hide": 1,
- "read_only": 1
- },
- {
"fieldname": "section_break_24",
"fieldtype": "Section Break"
},
@@ -528,12 +524,43 @@
{
"fieldname": "column_break_15",
"fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "sec_break_price_list",
+ "fieldtype": "Section Break"
+ },
+ {
+ "fieldname": "col_break_price_list",
+ "fieldtype": "Column Break"
+ },
+ {
+ "collapsible": 1,
+ "fieldname": "ad_sec_break",
+ "fieldtype": "Section Break",
+ "label": "Accounting Dimensions"
+ },
+ {
+ "default": "0",
+ "depends_on": "is_free_item",
+ "fieldname": "is_free_item",
+ "fieldtype": "Check",
+ "label": "Is Free Item",
+ "print_hide": 1,
+ "read_only": 1
+ },
+ {
+ "allow_on_submit": 1,
+ "bold": 1,
+ "fieldname": "expected_delivery_date",
+ "fieldtype": "Date",
+ "label": "Expected Delivery Date"
}
],
"idx": 1,
+ "index_web_pages_for_search": 1,
"istable": 1,
"links": [],
- "modified": "2020-04-07 18:35:51.175947",
+ "modified": "2020-10-01 16:34:39.703033",
"modified_by": "Administrator",
"module": "Buying",
"name": "Supplier Quotation Item",
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index bb288c5..1665649 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -1319,24 +1319,26 @@
validate_quantity(child_item, d)
child_item.qty = flt(d.get("qty"))
- precision = child_item.precision("rate") or 2
+ rate_precision = child_item.precision("rate") or 2
+ conv_fac_precision = child_item.precision("conversion_factor") or 2
+ qty_precision = child_item.precision("qty") or 2
- if flt(child_item.billed_amt, precision) > flt(flt(d.get("rate")) * flt(d.get("qty")), precision):
+ if flt(child_item.billed_amt, rate_precision) > flt(flt(d.get("rate"), rate_precision) * flt(d.get("qty"), qty_precision), rate_precision):
frappe.throw(_("Row #{0}: Cannot set Rate if amount is greater than billed amount for Item {1}.")
.format(child_item.idx, child_item.item_code))
else:
- child_item.rate = flt(d.get("rate"))
+ child_item.rate = flt(d.get("rate"), rate_precision)
if d.get("conversion_factor"):
if child_item.stock_uom == child_item.uom:
child_item.conversion_factor = 1
else:
- child_item.conversion_factor = flt(d.get('conversion_factor'))
+ child_item.conversion_factor = flt(d.get('conversion_factor'), conv_fac_precision)
if d.get("uom"):
child_item.uom = d.get("uom")
conversion_factor = flt(get_conversion_factor(child_item.item_code, child_item.uom).get("conversion_factor"))
- child_item.conversion_factor = flt(d.get('conversion_factor')) or conversion_factor
+ child_item.conversion_factor = flt(d.get('conversion_factor'), conv_fac_precision) or conversion_factor
if d.get("delivery_date") and parent_doctype == 'Sales Order':
child_item.delivery_date = d.get('delivery_date')
diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py
index ac567b7..e05c70e 100644
--- a/erpnext/controllers/buying_controller.py
+++ b/erpnext/controllers/buying_controller.py
@@ -847,6 +847,7 @@
where
t2.parent = t1.name and t1.item = %s
and t1.docstatus = 1 and t1.is_active = 1 and t1.name = %s
+ and t2.sourced_by_supplier = 0
and t2.item_code = t3.name""".format(doctype),
(item_code, bom), as_dict=1)
diff --git a/erpnext/hr/doctype/employee/employee.json b/erpnext/hr/doctype/employee/employee.json
index 8c02e4f..da78919 100644
--- a/erpnext/hr/doctype/employee/employee.json
+++ b/erpnext/hr/doctype/employee/employee.json
@@ -109,7 +109,6 @@
"encashment_date",
"exit_interview_details",
"held_on",
- "reason_for_resignation",
"new_workplace",
"feedback",
"lft",
@@ -682,7 +681,7 @@
},
{
"fieldname": "reason_for_leaving",
- "fieldtype": "Data",
+ "fieldtype": "Small Text",
"label": "Reason for Leaving",
"oldfieldname": "reason_for_leaving",
"oldfieldtype": "Data"
@@ -696,6 +695,7 @@
"options": "\nYes\nNo"
},
{
+ "depends_on": "eval:doc.leave_encashed ==\"Yes\"",
"fieldname": "encashment_date",
"fieldtype": "Date",
"label": "Encashment Date",
@@ -705,7 +705,6 @@
{
"fieldname": "exit_interview_details",
"fieldtype": "Column Break",
- "label": "Exit Interview Details",
"oldfieldname": "col_brk6",
"oldfieldtype": "Column Break",
"width": "50%"
@@ -713,19 +712,11 @@
{
"fieldname": "held_on",
"fieldtype": "Date",
- "label": "Held On",
+ "label": "Exit Interview Held On",
"oldfieldname": "held_on",
"oldfieldtype": "Date"
},
{
- "fieldname": "reason_for_resignation",
- "fieldtype": "Select",
- "label": "Reason for Resignation",
- "oldfieldname": "reason_for_resignation",
- "oldfieldtype": "Select",
- "options": "\nBetter Prospects\nHealth Concerns"
- },
- {
"fieldname": "new_workplace",
"fieldtype": "Data",
"label": "New Workplace",
@@ -809,37 +800,29 @@
"fieldname": "expense_approver",
"fieldtype": "Link",
"label": "Expense Approver",
- "options": "User",
- "show_days": 1,
- "show_seconds": 1
+ "options": "User"
},
{
"fieldname": "approvers_section",
"fieldtype": "Section Break",
- "label": "Approvers",
- "show_days": 1,
- "show_seconds": 1
+ "label": "Approvers"
},
{
"fieldname": "column_break_45",
- "fieldtype": "Column Break",
- "show_days": 1,
- "show_seconds": 1
+ "fieldtype": "Column Break"
},
{
"fieldname": "shift_request_approver",
"fieldtype": "Link",
"label": "Shift Request Approver",
- "options": "User",
- "show_days": 1,
- "show_seconds": 1
+ "options": "User"
}
],
"icon": "fa fa-user",
"idx": 24,
"image_field": "image",
"links": [],
- "modified": "2020-07-28 01:36:04.109189",
+ "modified": "2020-10-06 15:58:23.805489",
"modified_by": "Administrator",
"module": "HR",
"name": "Employee",
diff --git a/erpnext/manufacturing/doctype/bom/bom.js b/erpnext/manufacturing/doctype/bom/bom.js
index 47b4207..1c4b7a1 100644
--- a/erpnext/manufacturing/doctype/bom/bom.js
+++ b/erpnext/manufacturing/doctype/bom/bom.js
@@ -434,7 +434,8 @@
"include_item_in_manufacturing": d.include_item_in_manufacturing,
"uom": d.uom,
"stock_uom": d.stock_uom,
- "conversion_factor": d.conversion_factor
+ "conversion_factor": d.conversion_factor,
+ "sourced_by_supplier": d.sourced_by_supplier
},
callback: function(r) {
d = locals[cdt][cdn];
@@ -616,6 +617,22 @@
refresh_field("allow_alternative_item", d.name, d.parentfield);
});
+frappe.ui.form.on("BOM Item", "sourced_by_supplier", function(frm, cdt, cdn) {
+ var d = locals[cdt][cdn];
+ if (d.sourced_by_supplier) {
+ d.rate = 0;
+ refresh_field("rate", d.name, d.parentfield);
+ }
+});
+
+frappe.ui.form.on("BOM Item", "rate", function(frm, cdt, cdn) {
+ var d = locals[cdt][cdn];
+ if (d.sourced_by_supplier) {
+ d.rate = 0;
+ refresh_field("rate", d.name, d.parentfield);
+ }
+});
+
frappe.ui.form.on("BOM Operation", "operations_remove", function(frm) {
erpnext.bom.calculate_op_cost(frm.doc);
erpnext.bom.calculate_total(frm.doc);
diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py
index 3189433..71d49a9 100644
--- a/erpnext/manufacturing/doctype/bom/bom.py
+++ b/erpnext/manufacturing/doctype/bom/bom.py
@@ -137,7 +137,8 @@
"qty": item.qty,
"uom": item.uom,
"stock_uom": item.stock_uom,
- "conversion_factor": item.conversion_factor
+ "conversion_factor": item.conversion_factor,
+ "sourced_by_supplier": item.sourced_by_supplier
})
for r in ret:
if not item.get(r):
@@ -172,7 +173,8 @@
'qty' : args.get("qty") or args.get("stock_qty") or 1,
'stock_qty' : args.get("qty") or args.get("stock_qty") or 1,
'base_rate' : flt(rate) * (flt(self.conversion_rate) or 1),
- 'include_item_in_manufacturing': cint(args['transfer_for_manufacture']) or 0
+ 'include_item_in_manufacturing': cint(args['transfer_for_manufacture']) or 0,
+ 'sourced_by_supplier' : args['sourced_by_supplier'] or 0
}
return ret_item
@@ -191,8 +193,8 @@
if arg.get('scrap_items'):
rate = get_valuation_rate(arg)
elif arg:
- #Customer Provided parts will have zero rate
- if not frappe.db.get_value('Item', arg["item_code"], 'is_customer_provided_item'):
+ #Customer Provided parts and Supplier sourced parts will have zero rate
+ if not frappe.db.get_value('Item', arg["item_code"], 'is_customer_provided_item') and not arg.get('sourced_by_supplier'):
if arg.get('bom_no') and self.set_rate_of_sub_assembly_item_based_on_bom:
rate = flt(self.get_bom_unitcost(arg['bom_no'])) * (arg.get("conversion_factor") or 1)
else:
@@ -205,7 +207,6 @@
else:
frappe.msgprint(_("{0} not found for item {1}")
.format(self.rm_cost_as_per, arg["item_code"]), alert=True)
-
return flt(rate) * flt(self.plc_conversion_rate or 1) / (self.conversion_rate or 1)
def update_cost(self, update_parent=True, from_child_bom=False, save=True):
@@ -221,7 +222,8 @@
"qty": d.qty,
"uom": d.uom,
"stock_uom": d.stock_uom,
- "conversion_factor": d.conversion_factor
+ "conversion_factor": d.conversion_factor,
+ "sourced_by_supplier": d.sourced_by_supplier
})
if rate:
@@ -495,7 +497,8 @@
'stock_uom' : d.stock_uom,
'stock_qty' : flt(d.stock_qty),
'rate' : flt(d.base_rate) / (flt(d.conversion_factor) or 1.0),
- 'include_item_in_manufacturing': d.include_item_in_manufacturing
+ 'include_item_in_manufacturing': d.include_item_in_manufacturing,
+ 'sourced_by_supplier': d.sourced_by_supplier
}))
def company_currency(self):
@@ -521,6 +524,7 @@
bom_item.stock_qty,
bom_item.rate,
bom_item.include_item_in_manufacturing,
+ bom_item.sourced_by_supplier,
bom_item.stock_qty / ifnull(bom.quantity, 1) AS qty_consumed_per_unit
FROM `tabBOM Explosion Item` bom_item, tabBOM bom
WHERE
@@ -539,7 +543,8 @@
'stock_uom' : d['stock_uom'],
'stock_qty' : d['qty_consumed_per_unit'] * stock_qty,
'rate' : flt(d['rate']),
- 'include_item_in_manufacturing': d.get('include_item_in_manufacturing', 0)
+ 'include_item_in_manufacturing': d.get('include_item_in_manufacturing', 0),
+ 'sourced_by_supplier': d.get('sourced_by_supplier', 0)
}))
def add_exploded_items(self):
@@ -679,7 +684,7 @@
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, bom_item.description, bom_item.rate,
+ bom_item.include_item_in_manufacturing, bom_item.description, bom_item.rate, bom_item.sourced_by_supplier,
(Select idx from `tabBOM Item` where item_code = bom_item.item_code and parent = %(parent)s limit 1) as idx""")
items = frappe.db.sql(query, { "parent": bom, "qty": qty, "bom": bom, "company": company }, as_dict=True)
@@ -692,7 +697,7 @@
query = query.format(table="BOM Item", where_conditions="", is_stock_item=is_stock_item,
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,
+ bom_item.idx, bom_item.operation, bom_item.include_item_in_manufacturing, bom_item.sourced_by_supplier,
bom_item.description, bom_item.base_rate as rate """)
items = frappe.db.sql(query, { "qty": qty, "bom": bom, "company": company }, as_dict=True)
diff --git a/erpnext/manufacturing/doctype/bom/test_bom.py b/erpnext/manufacturing/doctype/bom/test_bom.py
index 3dfd03b..eface4d 100644
--- a/erpnext/manufacturing/doctype/bom/test_bom.py
+++ b/erpnext/manufacturing/doctype/bom/test_bom.py
@@ -10,6 +10,8 @@
from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation import create_stock_reconciliation
from erpnext.manufacturing.doctype.bom_update_tool.bom_update_tool import update_cost
from six import string_types
+from erpnext.stock.doctype.item.test_item import make_item
+from erpnext.buying.doctype.purchase_order.test_purchase_order import create_purchase_order
test_records = frappe.get_test_records('BOM')
@@ -138,6 +140,74 @@
self.assertEqual(bom.items[0].rate, 20)
+ def test_subcontractor_sourced_item(self):
+ item_code = "_Test Subcontracted FG Item 1"
+
+ if not frappe.db.exists('Item', item_code):
+ make_item(item_code, {
+ 'is_stock_item': 1,
+ 'is_sub_contracted_item': 1,
+ 'stock_uom': 'Nos'
+ })
+
+ if not frappe.db.exists('Item', "Test Extra Item 1"):
+ make_item("Test Extra Item 1", {
+ 'is_stock_item': 1,
+ 'stock_uom': 'Nos'
+ })
+
+ if not frappe.db.exists('Item', "Test Extra Item 2"):
+ make_item("Test Extra Item 2", {
+ 'is_stock_item': 1,
+ 'stock_uom': 'Nos'
+ })
+
+ if not frappe.db.exists('Item', "Test Extra Item 3"):
+ make_item("Test Extra Item 3", {
+ 'is_stock_item': 1,
+ 'stock_uom': 'Nos'
+ })
+ bom = frappe.get_doc({
+ 'doctype': 'BOM',
+ 'is_default': 1,
+ 'item': item_code,
+ 'currency': 'USD',
+ 'quantity': 1,
+ 'company': '_Test Company'
+ })
+
+ for item in ["Test Extra Item 1", "Test Extra Item 2"]:
+ item_doc = frappe.get_doc('Item', item)
+
+ bom.append('items', {
+ 'item_code': item,
+ 'qty': 1,
+ 'uom': item_doc.stock_uom,
+ 'stock_uom': item_doc.stock_uom,
+ 'rate': item_doc.valuation_rate
+ })
+
+ bom.append('items', {
+ 'item_code': "Test Extra Item 3",
+ 'qty': 1,
+ 'uom': item_doc.stock_uom,
+ 'stock_uom': item_doc.stock_uom,
+ 'rate': 0,
+ 'sourced_by_supplier': 1
+ })
+ bom.insert(ignore_permissions=True)
+ bom.update_cost()
+ bom.submit()
+ # test that sourced_by_supplier rate is zero even after updating cost
+ self.assertEqual(bom.items[2].rate, 0)
+ # test in Purchase Order sourced_by_supplier is not added to Supplied Item
+ po = create_purchase_order(item_code=item_code, qty=1,
+ is_subcontracted="Yes", supplier_warehouse="_Test Warehouse 1 - _TC")
+ bom_items = sorted([d.item_code for d in bom.items if d.sourced_by_supplier != 1])
+ supplied_items = sorted([d.rm_item_code for d in po.supplied_items])
+ self.assertEquals(bom_items, supplied_items)
+
+
def get_default_bom(item_code="_Test FG Item 2"):
return frappe.db.get_value("BOM", {"item": item_code, "is_active": 1, "is_default": 1})
diff --git a/erpnext/manufacturing/doctype/bom_explosion_item/bom_explosion_item.json b/erpnext/manufacturing/doctype/bom_explosion_item/bom_explosion_item.json
index 9fadbef..f01d856 100644
--- a/erpnext/manufacturing/doctype/bom_explosion_item/bom_explosion_item.json
+++ b/erpnext/manufacturing/doctype/bom_explosion_item/bom_explosion_item.json
@@ -1,626 +1,181 @@
{
- "allow_copy": 0,
- "allow_events_in_timeline": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "autoname": "hash",
- "beta": 0,
- "creation": "2013-03-07 11:42:57",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "Setup",
- "editable_grid": 1,
- "engine": "InnoDB",
+ "actions": [],
+ "autoname": "hash",
+ "creation": "2013-03-07 11:42:57",
+ "doctype": "DocType",
+ "document_type": "Setup",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "item_code",
+ "item_name",
+ "cb",
+ "source_warehouse",
+ "operation",
+ "section_break_3",
+ "description",
+ "column_break_2",
+ "image",
+ "image_view",
+ "section_break_4",
+ "stock_qty",
+ "rate",
+ "qty_consumed_per_unit",
+ "column_break_8",
+ "stock_uom",
+ "amount",
+ "include_item_in_manufacturing",
+ "sourced_by_supplier"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "item_code",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 1,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Item Code",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "item_code",
- "oldfieldtype": "Link",
- "options": "Item",
- "permlevel": 0,
- "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
- },
+ "fieldname": "item_code",
+ "fieldtype": "Link",
+ "in_global_search": 1,
+ "in_list_view": 1,
+ "label": "Item Code",
+ "oldfieldname": "item_code",
+ "oldfieldtype": "Link",
+ "options": "Item",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "item_name",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 1,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Item Name",
- "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
- },
+ "fieldname": "item_name",
+ "fieldtype": "Data",
+ "in_global_search": 1,
+ "in_list_view": 1,
+ "label": "Item Name",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "cb",
- "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
- },
+ "fieldname": "cb",
+ "fieldtype": "Column Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "source_warehouse",
- "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": "Source Warehouse",
- "length": 0,
- "no_copy": 0,
- "options": "Warehouse",
- "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
- },
+ "fieldname": "source_warehouse",
+ "fieldtype": "Link",
+ "label": "Source Warehouse",
+ "options": "Warehouse",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "operation",
- "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": "Operation",
- "length": 0,
- "no_copy": 0,
- "options": "Operation",
- "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
- },
+ "fieldname": "operation",
+ "fieldtype": "Link",
+ "label": "Operation",
+ "options": "Operation",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "section_break_3",
- "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,
- "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
- },
+ "fieldname": "section_break_3",
+ "fieldtype": "Section Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "description",
- "fieldtype": "Text Editor",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Description",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "description",
- "oldfieldtype": "Text",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "print_width": "300px",
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0,
+ "fieldname": "description",
+ "fieldtype": "Text Editor",
+ "in_list_view": 1,
+ "label": "Description",
+ "oldfieldname": "description",
+ "oldfieldtype": "Text",
+ "print_width": "300px",
+ "read_only": 1,
"width": "300px"
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break_2",
- "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
- },
+ "fieldname": "column_break_2",
+ "fieldtype": "Column Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "image",
- "fieldtype": "Attach",
- "hidden": 1,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Image",
- "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
- },
+ "fieldname": "image",
+ "fieldtype": "Attach",
+ "hidden": 1,
+ "label": "Image",
+ "print_hide": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "image_view",
- "fieldtype": "Image",
- "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": "Image View",
- "length": 0,
- "no_copy": 0,
- "options": "image",
- "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
- },
+ "fieldname": "image_view",
+ "fieldtype": "Image",
+ "label": "Image View",
+ "options": "image"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "section_break_4",
- "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,
- "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
- },
+ "fieldname": "section_break_4",
+ "fieldtype": "Section Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "stock_qty",
- "fieldtype": "Float",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Stock Qty",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "qty",
- "oldfieldtype": "Currency",
- "permlevel": 0,
- "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
- },
+ "fieldname": "stock_qty",
+ "fieldtype": "Float",
+ "in_list_view": 1,
+ "label": "Stock Qty",
+ "oldfieldname": "qty",
+ "oldfieldtype": "Currency",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "rate",
- "fieldtype": "Currency",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Rate",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "standard_rate",
- "oldfieldtype": "Currency",
- "options": "Company:company:default_currency",
- "permlevel": 0,
- "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
- },
+ "fieldname": "rate",
+ "fieldtype": "Currency",
+ "in_list_view": 1,
+ "label": "Rate",
+ "oldfieldname": "standard_rate",
+ "oldfieldtype": "Currency",
+ "options": "Company:company:default_currency",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "qty_consumed_per_unit",
- "fieldtype": "Float",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Qty Consumed Per Unit",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "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
- },
+ "fieldname": "qty_consumed_per_unit",
+ "fieldtype": "Float",
+ "in_list_view": 1,
+ "label": "Qty Consumed Per Unit",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break_8",
- "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
- },
+ "fieldname": "column_break_8",
+ "fieldtype": "Column Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "stock_uom",
- "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": "Stock UOM",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "stock_uom",
- "oldfieldtype": "Link",
- "options": "UOM",
- "permlevel": 0,
- "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
- },
+ "fieldname": "stock_uom",
+ "fieldtype": "Link",
+ "label": "Stock UOM",
+ "oldfieldname": "stock_uom",
+ "oldfieldtype": "Link",
+ "options": "UOM",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "amount",
- "fieldtype": "Currency",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Amount",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "amount_as_per_sr",
- "oldfieldtype": "Currency",
- "options": "Company:company:default_currency",
- "permlevel": 0,
- "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
- },
+ "fieldname": "amount",
+ "fieldtype": "Currency",
+ "in_list_view": 1,
+ "label": "Amount",
+ "oldfieldname": "amount_as_per_sr",
+ "oldfieldtype": "Currency",
+ "options": "Company:company:default_currency",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "include_item_in_manufacturing",
- "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": "Include Item In Manufacturing",
- "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
+ "default": "0",
+ "fieldname": "include_item_in_manufacturing",
+ "fieldtype": "Check",
+ "label": "Include Item In Manufacturing",
+ "read_only": 1
+ },
+ {
+ "default": "0",
+ "fieldname": "sourced_by_supplier",
+ "fieldtype": "Check",
+ "label": "Sourced by Supplier",
+ "read_only": 1
}
- ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 1,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 1,
- "max_attachments": 0,
- "modified": "2018-11-20 19:04:59.813773",
- "modified_by": "Administrator",
- "module": "Manufacturing",
- "name": "BOM Explosion Item",
- "owner": "Administrator",
- "permissions": [],
- "quick_entry": 0,
- "read_only": 0,
- "read_only_onload": 0,
- "show_name_in_global_search": 0,
- "track_changes": 1,
- "track_seen": 0,
- "track_views": 0
+ ],
+ "idx": 1,
+ "index_web_pages_for_search": 1,
+ "istable": 1,
+ "links": [],
+ "modified": "2020-10-08 16:21:29.386212",
+ "modified_by": "Administrator",
+ "module": "Manufacturing",
+ "name": "BOM Explosion Item",
+ "owner": "Administrator",
+ "permissions": [],
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
}
\ No newline at end of file
diff --git a/erpnext/manufacturing/doctype/bom_item/bom_item.json b/erpnext/manufacturing/doctype/bom_item/bom_item.json
index e34be61..4c9877f 100644
--- a/erpnext/manufacturing/doctype/bom_item/bom_item.json
+++ b/erpnext/manufacturing/doctype/bom_item/bom_item.json
@@ -37,7 +37,9 @@
"section_break_27",
"has_variants",
"include_item_in_manufacturing",
- "original_item"
+ "original_item",
+ "column_break_33",
+ "sourced_by_supplier"
],
"fields": [
{
@@ -272,12 +274,23 @@
"no_copy": 1,
"print_hide": 1,
"read_only": 1
+ },
+ {
+ "fieldname": "column_break_33",
+ "fieldtype": "Column Break"
+ },
+ {
+ "default": "0",
+ "fieldname": "sourced_by_supplier",
+ "fieldtype": "Check",
+ "label": "Sourced by Supplier"
}
],
"idx": 1,
+ "index_web_pages_for_search": 1,
"istable": 1,
"links": [],
- "modified": "2020-04-09 14:30:26.535546",
+ "modified": "2020-10-08 14:19:37.563300",
"modified_by": "Administrator",
"module": "Manufacturing",
"name": "BOM Item",
diff --git a/erpnext/manufacturing/doctype/production_plan/production_plan.py b/erpnext/manufacturing/doctype/production_plan/production_plan.py
index c889237..5b14d05 100644
--- a/erpnext/manufacturing/doctype/production_plan/production_plan.py
+++ b/erpnext/manufacturing/doctype/production_plan/production_plan.py
@@ -381,7 +381,6 @@
"transaction_date": nowdate(),
"status": "Draft",
"company": self.company,
- "requested_by": frappe.session.user,
'material_request_type': material_request_type,
'customer': item_doc.customer or ''
})
diff --git a/erpnext/manufacturing/doctype/work_order/work_order.py b/erpnext/manufacturing/doctype/work_order/work_order.py
index b7d968e..3173b6c 100644
--- a/erpnext/manufacturing/doctype/work_order/work_order.py
+++ b/erpnext/manufacturing/doctype/work_order/work_order.py
@@ -434,7 +434,7 @@
elif flt(d.completed_qty) <= max_allowed_qty_for_wo:
d.status = "Completed"
else:
- frappe.throw(_("Completed Qty can not be greater than 'Qty to Manufacture'"))
+ frappe.throw(_("Completed Qty cannot be greater than 'Qty to Manufacture'"))
def set_actual_dates(self):
if self.get("operations"):
diff --git a/erpnext/payroll/doctype/salary_component/salary_component.json b/erpnext/payroll/doctype/salary_component/salary_component.json
index 225b048..c97e45c 100644
--- a/erpnext/payroll/doctype/salary_component/salary_component.json
+++ b/erpnext/payroll/doctype/salary_component/salary_component.json
@@ -217,7 +217,7 @@
"fieldname": "help",
"fieldtype": "HTML",
"label": "Help",
- "options": "<h3>Help</h3>\n\n<p>Notes:</p>\n\n<ol>\n<li>Use field <code>base</code> for using base salary of the Employee</li>\n<li>Use Salary Component abbreviations in conditions and formulas. <code>BS = Basic Salary</code></li>\n<li>Use field name for employee details in conditions and formulas. <code>Employment Type = employment_type</code><code>Branch = branch</code></li>\n<li>Use field name from Salary Slip in conditions and formulas. <code>Payment Days = payment_days</code><code>Leave without pay = leave_without_pay</code></li>\n<li>Direct Amount can also be entered based on Condtion. See example 3</li></ol>\n\n<h4>Examples</h4>\n<ol>\n<li>Calculating Basic Salary based on <code>base</code>\n<pre><code>Condition: base < 10000</code></pre>\n<pre><code>Formula: base * .2</code></pre></li>\n<li>Calculating HRA based on Basic Salary<code>BS</code> \n<pre><code>Condition: BS > 2000</code></pre>\n<pre><code>Formula: BS * .1</code></pre></li>\n<li>Calculating TDS based on Employment Type<code>employment_type</code> \n<pre><code>Condition: employment_type==\"Intern\"</code></pre>\n<pre><code>Amount: 1000</code></pre></li>\n</ol>"
+ "options": "<h3>Help</h3>\n\n<p>Notes:</p>\n\n<ol>\n<li>Use field <code>base</code> for using base salary of the Employee</li>\n<li>Use Salary Component abbreviations in conditions and formulas. <code>BS = Basic Salary</code></li>\n<li>Use field name for employee details in conditions and formulas. <code>Employment Type = employment_type</code><code>Branch = branch</code></li>\n<li>Use field name from Salary Slip in conditions and formulas. <code>Payment Days = payment_days</code><code>Leave without pay = leave_without_pay</code></li>\n<li>Direct Amount can also be entered based on Condition. See example 3</li></ol>\n\n<h4>Examples</h4>\n<ol>\n<li>Calculating Basic Salary based on <code>base</code>\n<pre><code>Condition: base < 10000</code></pre>\n<pre><code>Formula: base * .2</code></pre></li>\n<li>Calculating HRA based on Basic Salary<code>BS</code> \n<pre><code>Condition: BS > 2000</code></pre>\n<pre><code>Formula: BS * .1</code></pre></li>\n<li>Calculating TDS based on Employment Type<code>employment_type</code> \n<pre><code>Condition: employment_type==\"Intern\"</code></pre>\n<pre><code>Amount: 1000</code></pre></li>\n</ol>"
},
{
"default": "0",
@@ -238,14 +238,13 @@
"depends_on": "eval:doc.type == \"Deduction\"",
"fieldname": "is_income_tax_component",
"fieldtype": "Check",
- "label": "Is Income Tax Component",
- "show_days": 1,
- "show_seconds": 1
+ "label": "Is Income Tax Component"
}
],
"icon": "fa fa-flag",
+ "index_web_pages_for_search": 1,
"links": [],
- "modified": "2020-06-22 15:39:20.826565",
+ "modified": "2020-10-07 20:38:33.795853",
"modified_by": "Administrator",
"module": "Payroll",
"name": "Salary Component",
diff --git a/erpnext/payroll/doctype/salary_detail/salary_detail.json b/erpnext/payroll/doctype/salary_detail/salary_detail.json
index cc87cae..eedb56e 100644
--- a/erpnext/payroll/doctype/salary_detail/salary_detail.json
+++ b/erpnext/payroll/doctype/salary_detail/salary_detail.json
@@ -117,7 +117,7 @@
"depends_on": "eval:doc.is_flexible_benefit != 1",
"fieldname": "section_break_2",
"fieldtype": "Section Break",
- "label": "Condtion and formula"
+ "label": "Condition and formula"
},
{
"allow_on_submit": 1,
@@ -206,38 +206,28 @@
"collapsible": 1,
"fieldname": "section_break_5",
"fieldtype": "Section Break",
- "label": "Component properties and references ",
- "show_days": 1,
- "show_seconds": 1
+ "label": "Component properties and references "
},
{
"fieldname": "column_break_11",
- "fieldtype": "Column Break",
- "show_days": 1,
- "show_seconds": 1
+ "fieldtype": "Column Break"
},
{
"fieldname": "section_break_19",
- "fieldtype": "Section Break",
- "show_days": 1,
- "show_seconds": 1
+ "fieldtype": "Section Break"
},
{
"fieldname": "column_break_18",
- "fieldtype": "Column Break",
- "show_days": 1,
- "show_seconds": 1
+ "fieldtype": "Column Break"
},
{
"fieldname": "column_break_24",
- "fieldtype": "Column Break",
- "show_days": 1,
- "show_seconds": 1
+ "fieldtype": "Column Break"
}
],
"istable": 1,
"links": [],
- "modified": "2020-07-01 12:13:41.956495",
+ "modified": "2020-10-07 20:39:41.619283",
"modified_by": "Administrator",
"module": "Payroll",
"name": "Salary Detail",
diff --git a/erpnext/public/js/utils.js b/erpnext/public/js/utils.js
index 9ed5009..6d73418 100755
--- a/erpnext/public/js/utils.js
+++ b/erpnext/public/js/utils.js
@@ -452,6 +452,9 @@
const frm = opts.frm;
const cannot_add_row = (typeof opts.cannot_add_row === 'undefined') ? true : opts.cannot_add_row;
const child_docname = (typeof opts.cannot_add_row === 'undefined') ? "items" : opts.child_docname;
+ const child_meta = frappe.get_meta(`${frm.doc.doctype} Item`);
+ const get_precision = (fieldname) => child_meta.fields.find(f => f.fieldname == fieldname).precision;
+
this.data = [];
const fields = [{
fieldtype:'Data',
@@ -499,14 +502,16 @@
default: 0,
read_only: 0,
in_list_view: 1,
- label: __('Qty')
+ label: __('Qty'),
+ precision: get_precision("qty")
}, {
fieldtype:'Currency',
fieldname:"rate",
default: 0,
read_only: 0,
in_list_view: 1,
- label: __('Rate')
+ label: __('Rate'),
+ precision: get_precision("rate")
}];
if (frm.doc.doctype == 'Sales Order' || frm.doc.doctype == 'Purchase Order' ) {
@@ -521,7 +526,8 @@
fieldtype: 'Float',
fieldname: "conversion_factor",
in_list_view: 1,
- label: __("Conversion Factor")
+ label: __("Conversion Factor"),
+ precision: get_precision('conversion_factor')
})
}
diff --git a/erpnext/selling/doctype/customer/customer.py b/erpnext/selling/doctype/customer/customer.py
index 1f955fc..0172d9c 100644
--- a/erpnext/selling/doctype/customer/customer.py
+++ b/erpnext/selling/doctype/customer/customer.py
@@ -132,7 +132,7 @@
address = frappe.get_doc('Address', address_name.get('name'))
if not address.has_link('Customer', self.name):
address.append('links', dict(link_doctype='Customer', link_name=self.name))
- address.save()
+ address.save(ignore_permissions=self.flags.ignore_permissions)
lead = frappe.db.get_value("Lead", self.lead_name, ["organization_lead", "lead_name", "email_id", "phone", "mobile_no", "gender", "salutation"], as_dict=True)
@@ -150,7 +150,7 @@
contact = frappe.get_doc('Contact', contact_name.get('name'))
if not contact.has_link('Customer', self.name):
contact.append('links', dict(link_doctype='Customer', link_name=self.name))
- contact.save()
+ contact.save(ignore_permissions=self.flags.ignore_permissions)
else:
lead.lead_name = lead.lead_name.lstrip().split(" ")
diff --git a/erpnext/selling/doctype/quotation/tests/test_quotation.js b/erpnext/selling/doctype/quotation/tests/test_quotation.js
index d69d799..ad942fe 100644
--- a/erpnext/selling/doctype/quotation/tests/test_quotation.js
+++ b/erpnext/selling/doctype/quotation/tests/test_quotation.js
@@ -46,7 +46,7 @@
assert.ok(cur_frm.doc.items[0].rate == 200, "Price Changed Manually");
assert.equal(cur_frm.doc.total, 1000, "New Total Calculated");
- // Check Terms and Condtions
+ // Check Terms and Conditions
assert.ok(cur_frm.doc.tc_name == "Test Term 1", "Terms and Conditions Checked");
assert.ok(cur_frm.doc.payment_terms_template, "Payment Terms Template is correct");
diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py
index f882898..62a5d4e 100755
--- a/erpnext/selling/doctype/sales_order/sales_order.py
+++ b/erpnext/selling/doctype/sales_order/sales_order.py
@@ -989,7 +989,6 @@
doctype = 'Material Request',
transaction_date = nowdate(),
company = company,
- requested_by = frappe.session.user,
material_request_type = 'Purchase'
))
for item in raw_materials:
diff --git a/erpnext/selling/doctype/sales_order/test_sales_order.py b/erpnext/selling/doctype/sales_order/test_sales_order.py
index 5aef096..1ce36dd 100644
--- a/erpnext/selling/doctype/sales_order/test_sales_order.py
+++ b/erpnext/selling/doctype/sales_order/test_sales_order.py
@@ -403,6 +403,22 @@
trans_item = json.dumps([{'item_code' : '_Test Item', 'rate' : 200, 'qty' : 2, 'docname': so.items[0].name}])
self.assertRaises(frappe.ValidationError, update_child_qty_rate,'Sales Order', trans_item, so.name)
+
+ def test_update_child_with_precision(self):
+ from frappe.model.meta import get_field_precision
+ from frappe.custom.doctype.property_setter.property_setter import make_property_setter
+
+ precision = get_field_precision(frappe.get_meta("Sales Order Item").get_field("rate"))
+
+ make_property_setter("Sales Order Item", "rate", "precision", 7, "Currency")
+ so = make_sales_order(item_code= "_Test Item", qty=4, rate=200.34664)
+
+ trans_item = json.dumps([{'item_code' : '_Test Item', 'rate' : 200.34669, 'qty' : 4, 'docname': so.items[0].name}])
+ update_child_qty_rate('Sales Order', trans_item, so.name)
+
+ so.reload()
+ self.assertEqual(so.items[0].rate, 200.34669)
+ make_property_setter("Sales Order Item", "rate", "precision", precision, "Currency")
def test_update_child_perm(self):
so = make_sales_order(item_code= "_Test Item", qty=4)
diff --git a/erpnext/setup/doctype/company/company.py b/erpnext/setup/doctype/company/company.py
index 8e707fe..4a438f7 100644
--- a/erpnext/setup/doctype/company/company.py
+++ b/erpnext/setup/doctype/company/company.py
@@ -442,7 +442,7 @@
module_name = "erpnext.regional.{0}.setup.setup".format(frappe.scrub(company_doc.country))
frappe.get_attr(module_name)(company_doc, False)
except Exception as e:
- frappe.log_error(str(e), frappe.get_traceback())
+ frappe.log_error()
frappe.throw(_("Failed to setup defaults for country {0}. Please contact support@erpnext.com").format(frappe.bold(company_doc.country)))
diff --git a/erpnext/stock/desk_page/stock/stock.json b/erpnext/stock/desk_page/stock/stock.json
index 2fba5fa..390fcd9 100644
--- a/erpnext/stock/desk_page/stock/stock.json
+++ b/erpnext/stock/desk_page/stock/stock.json
@@ -3,7 +3,7 @@
{
"hidden": 0,
"label": "Items and Pricing",
- "links": "[\n {\n \"label\": \"Item\",\n \"name\": \"Item\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"icon\": \"fa fa-sitemap\",\n \"label\": \"Item Group\",\n \"link\": \"Tree/Item Group\",\n \"name\": \"Item Group\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Product Bundle\",\n \"name\": \"Product Bundle\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Price List\",\n \"name\": \"Price List\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Item Price\",\n \"name\": \"Item Price\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Shipping Rule\",\n \"name\": \"Shipping Rule\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Pricing Rule\",\n \"name\": \"Pricing Rule\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Item Alternative\",\n \"name\": \"Item Alternative\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Item Manufacturer\",\n \"name\": \"Item Manufacturer\",\n \"type\": \"doctype\"\n }\n]"
+ "links": "[\n {\n \"label\": \"Item\",\n \"name\": \"Item\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"icon\": \"fa fa-sitemap\",\n \"label\": \"Item Group\",\n \"link\": \"Tree/Item Group\",\n \"name\": \"Item Group\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Product Bundle\",\n \"name\": \"Product Bundle\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Price List\",\n \"name\": \"Price List\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Item Price\",\n \"name\": \"Item Price\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Shipping Rule\",\n \"name\": \"Shipping Rule\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Pricing Rule\",\n \"name\": \"Pricing Rule\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Item Alternative\",\n \"name\": \"Item Alternative\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Item Manufacturer\",\n \"name\": \"Item Manufacturer\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Customs Tariff Number\",\n \"name\": \"Customs Tariff Number\",\n \"type\": \"doctype\"\n }\n]"
},
{
"hidden": 0,
@@ -18,7 +18,7 @@
{
"hidden": 0,
"label": "Settings",
- "links": "[\n {\n \"label\": \"Stock Settings\",\n \"name\": \"Stock Settings\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Warehouse\",\n \"name\": \"Warehouse\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Unit of Measure (UOM)\",\n \"name\": \"UOM\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Item Variant Settings\",\n \"name\": \"Item Variant Settings\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Brand\",\n \"name\": \"Brand\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Item Attribute\",\n \"name\": \"Item Attribute\",\n \"type\": \"doctype\"\n }\n]"
+ "links": "[\n {\n \"label\": \"Stock Settings\",\n \"name\": \"Stock Settings\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Warehouse\",\n \"name\": \"Warehouse\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Unit of Measure (UOM)\",\n \"name\": \"UOM\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Item Variant Settings\",\n \"name\": \"Item Variant Settings\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Brand\",\n \"name\": \"Brand\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Item Attribute\",\n \"name\": \"Item Attribute\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"UOM Conversion Factor\",\n \"name\": \"UOM Conversion Factor\",\n \"type\": \"doctype\"\n }\n]"
},
{
"hidden": 0,
@@ -58,7 +58,7 @@
"idx": 0,
"is_standard": 1,
"label": "Stock",
- "modified": "2020-08-11 17:29:32.626067",
+ "modified": "2020-10-07 18:40:17.130207",
"modified_by": "Administrator",
"module": "Stock",
"name": "Stock",
diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py
index d22fda8..bfdddbb 100644
--- a/erpnext/stock/doctype/item/item.py
+++ b/erpnext/stock/doctype/item/item.py
@@ -984,9 +984,7 @@
if self.stock_ledger_created():
return True
- elif frappe.db.get_value(doctype, filters={"item_code": self.name, "docstatus": 1}) or \
- frappe.db.get_value("Production Order",
- filters={"production_item": self.name, "docstatus": 1}):
+ elif frappe.db.get_value(doctype, filters={"item_code": self.name, "docstatus": 1}):
return True
def validate_auto_reorder_enabled_in_stock_settings(self):
diff --git a/erpnext/stock/doctype/item_attribute/item_attribute.py b/erpnext/stock/doctype/item_attribute/item_attribute.py
index 7f00201..3764738 100644
--- a/erpnext/stock/doctype/item_attribute/item_attribute.py
+++ b/erpnext/stock/doctype/item_attribute/item_attribute.py
@@ -29,9 +29,18 @@
'''Validate that if there are existing items with attributes, they are valid'''
attributes_list = [d.attribute_value for d in self.item_attribute_values]
- for item in frappe.db.sql('''select i.name, iva.attribute_value as value
- from `tabItem Variant Attribute` iva, `tabItem` i where iva.attribute = %s
- and iva.parent = i.name and i.has_variants = 0''', self.name, as_dict=1):
+ # Get Item Variant Attribute details of variant items
+ items = frappe.db.sql("""
+ select
+ i.name, iva.attribute_value as value
+ from
+ `tabItem Variant Attribute` iva, `tabItem` i
+ where
+ iva.attribute = %(attribute)s
+ and iva.parent = i.name and
+ i.variant_of is not null and i.variant_of != ''""", {"attribute" : self.name}, as_dict=1)
+
+ for item in items:
if self.numeric_values:
validate_is_incremental(self, self.name, item.value, item.name)
else:
diff --git a/erpnext/stock/doctype/item_price/item_price.py b/erpnext/stock/doctype/item_price/item_price.py
index 8e39eb5..51b47c5 100644
--- a/erpnext/stock/doctype/item_price/item_price.py
+++ b/erpnext/stock/doctype/item_price/item_price.py
@@ -50,16 +50,18 @@
def check_duplicates(self):
conditions = "where item_code=%(item_code)s and price_list=%(price_list)s and name != %(name)s"
+ condition_data_dict = dict(item_code=self.item_code, price_list=self.price_list, name=self.name)
for field in ['uom', 'valid_from',
'valid_upto', 'packing_unit', 'customer', 'supplier']:
if self.get(field):
conditions += " and {0} = %({1})s".format(field, field)
+ condition_data_dict[field] = self.get(field)
price_list_rate = frappe.db.sql("""
SELECT price_list_rate
FROM `tabItem Price`
- {conditions} """.format(conditions=conditions), self.as_dict())
+ {conditions} """.format(conditions=conditions), condition_data_dict)
if price_list_rate :
frappe.throw(_("Item Price appears multiple times based on Price List, Supplier/Customer, Currency, Item, UOM, Qty and Dates."), ItemPriceDuplicateItem)
diff --git a/erpnext/stock/doctype/material_request/material_request.js b/erpnext/stock/doctype/material_request/material_request.js
index 3c4e353..8c47098 100644
--- a/erpnext/stock/doctype/material_request/material_request.js
+++ b/erpnext/stock/doctype/material_request/material_request.js
@@ -280,7 +280,8 @@
fieldname:'default_supplier',
fieldtype: 'Link',
options: 'Supplier',
- description: __('Select a Supplier from the Default Supplier List of the items below.'),
+ description: __('Select a Supplier from the Default Suppliers of the items below. \
+ On selection, a Purchase Order will be made against items belonging to the selected Supplier only.'),
get_query: () => {
return{
query: "erpnext.stock.doctype.material_request.material_request.get_default_supplier_query",
diff --git a/erpnext/stock/doctype/material_request/material_request.json b/erpnext/stock/doctype/material_request/material_request.json
index 44503d2..d73349d 100644
--- a/erpnext/stock/doctype/material_request/material_request.json
+++ b/erpnext/stock/doctype/material_request/material_request.json
@@ -13,7 +13,9 @@
"material_request_type",
"transfer_status",
"customer",
+ "status",
"column_break_2",
+ "transaction_date",
"schedule_date",
"company",
"amended_from",
@@ -25,11 +27,8 @@
"scan_barcode",
"items",
"more_info",
- "requested_by",
- "transaction_date",
- "column_break2",
- "status",
"per_ordered",
+ "column_break2",
"per_received",
"printing_details",
"letter_head",
@@ -82,7 +81,8 @@
"fieldname": "customer",
"fieldtype": "Link",
"label": "Customer",
- "options": "Customer"
+ "options": "Customer",
+ "print_hide": 1
},
{
"fieldname": "column_break_2",
@@ -92,12 +92,12 @@
"allow_on_submit": 1,
"fieldname": "schedule_date",
"fieldtype": "Date",
+ "in_list_view": 1,
"label": "Required By"
},
{
"fieldname": "company",
"fieldtype": "Link",
- "in_list_view": 1,
"in_standard_filter": 1,
"label": "Company",
"oldfieldname": "company",
@@ -154,17 +154,9 @@
"options": "fa fa-file-text"
},
{
- "fieldname": "requested_by",
- "fieldtype": "Data",
- "in_standard_filter": 1,
- "label": "Requested For",
- "options": "Email"
- },
- {
"default": "Today",
"fieldname": "transaction_date",
"fieldtype": "Date",
- "in_list_view": 1,
"label": "Transaction Date",
"no_copy": 1,
"oldfieldname": "transaction_date",
@@ -197,7 +189,7 @@
"width": "100px"
},
{
- "depends_on": "eval:doc.docstatus==1",
+ "depends_on": "eval:doc.per_ordered > 0",
"fieldname": "per_ordered",
"fieldtype": "Percent",
"label": "% Ordered",
@@ -208,7 +200,7 @@
"read_only": 1
},
{
- "depends_on": "eval:doc.docstatus==1",
+ "depends_on": "eval:doc.per_received > 0",
"fieldname": "per_received",
"fieldtype": "Percent",
"label": "% Received",
@@ -282,13 +274,15 @@
},
{
"fieldname": "warehouse_section",
- "fieldtype": "Section Break"
+ "fieldtype": "Section Break",
+ "label": "Warehouse"
},
{
- "description": "Sets 'For Warehouse' in each row of the Items table.",
+ "description": "Sets 'Target Warehouse' in each row of the Items table.",
"fieldname": "set_warehouse",
"fieldtype": "Link",
- "label": "Set Warehouse",
+ "in_list_view": 1,
+ "label": "Set Target Warehouse",
"options": "Warehouse"
},
{
@@ -300,9 +294,10 @@
},
{
"depends_on": "eval:doc.material_request_type == 'Material Transfer'",
+ "description": "Sets 'Source Warehouse' in each row of the Items table.",
"fieldname": "set_from_warehouse",
"fieldtype": "Link",
- "label": "Set From Warehouse",
+ "label": "Set Source Warehouse",
"options": "Warehouse"
},
{
@@ -319,7 +314,7 @@
"idx": 70,
"is_submittable": 1,
"links": [],
- "modified": "2020-08-10 13:27:54.891058",
+ "modified": "2020-09-19 01:04:09.285862",
"modified_by": "Administrator",
"module": "Stock",
"name": "Material Request",
diff --git a/erpnext/stock/doctype/material_request/material_request_dashboard.py b/erpnext/stock/doctype/material_request/material_request_dashboard.py
index 0e4fb7a..f3e5e5d 100644
--- a/erpnext/stock/doctype/material_request/material_request_dashboard.py
+++ b/erpnext/stock/doctype/material_request/material_request_dashboard.py
@@ -7,7 +7,7 @@
'fieldname': 'material_request',
'transactions': [
{
- 'label': _('Related'),
+ 'label': _('Reference'),
'items': ['Request for Quotation', 'Supplier Quotation', 'Purchase Order']
},
{
diff --git a/erpnext/stock/doctype/material_request_item/material_request_item.json b/erpnext/stock/doctype/material_request_item/material_request_item.json
index 32bd4a0..25bbbbd 100644
--- a/erpnext/stock/doctype/material_request_item/material_request_item.json
+++ b/erpnext/stock/doctype/material_request_item/material_request_item.json
@@ -13,12 +13,10 @@
"schedule_date",
"section_break_4",
"description",
+ "column_break_12",
"item_group",
"brand",
- "image_section",
"image",
- "column_break_12",
- "manufacturer_part_no",
"quantity_and_warehouse",
"qty",
"stock_uom",
@@ -28,12 +26,26 @@
"uom",
"conversion_factor",
"stock_qty",
+ "qty_info_sec_break",
+ "min_order_qty",
+ "projected_qty",
+ "qty_info_col_break",
+ "actual_qty",
+ "ordered_qty",
+ "received_qty",
"rate_and_amount_section_break",
"rate",
"col_break3",
"amount",
"manufacture_details",
"manufacturer",
+ "manufacturer_part_no",
+ "col_break_mfg",
+ "bom_no",
+ "accounting_dimensions_section",
+ "project",
+ "dimension_col_break",
+ "cost_center",
"more_info",
"lead_time_date",
"sales_order",
@@ -41,19 +53,7 @@
"production_plan",
"material_request_plan_item",
"col_break4",
- "min_order_qty",
- "projected_qty",
- "actual_qty",
- "ordered_qty",
- "received_qty",
- "accounting_details",
"expense_account",
- "accounting_dimensions_section",
- "project",
- "dimension_col_break",
- "cost_center",
- "section_break_37",
- "bom_no",
"section_break_46",
"page_break"
],
@@ -164,7 +164,7 @@
"fieldname": "warehouse",
"fieldtype": "Link",
"in_list_view": 1,
- "label": "For Warehouse",
+ "label": "Target Warehouse",
"oldfieldname": "warehouse",
"oldfieldtype": "Link",
"options": "Warehouse",
@@ -191,12 +191,14 @@
{
"fieldname": "rate",
"fieldtype": "Currency",
- "label": "Rate"
+ "label": "Rate",
+ "print_hide": 1
},
{
"fieldname": "amount",
"fieldtype": "Currency",
"label": "Amount",
+ "print_hide": 1,
"read_only": 1
},
{
@@ -326,6 +328,7 @@
"report_hide": 1
},
{
+ "depends_on": "eval:doc.docstatus==1",
"fieldname": "ordered_qty",
"fieldtype": "Float",
"label": "Completed Qty",
@@ -336,12 +339,6 @@
"read_only": 1
},
{
- "collapsible": 1,
- "fieldname": "accounting_details",
- "fieldtype": "Section Break",
- "label": "Accounting Details"
- },
- {
"fieldname": "expense_account",
"fieldtype": "Link",
"label": "Expense Account",
@@ -367,21 +364,10 @@
"print_hide": 1
},
{
- "collapsible": 1,
- "fieldname": "image_section",
- "fieldtype": "Section Break",
- "label": "Image"
- },
- {
- "depends_on": "eval:parent.material_request_type == \"Manufacture\"",
- "fieldname": "section_break_37",
- "fieldtype": "Section Break",
- "label": "Manufacturing"
- },
- {
+ "depends_on": "eval:doc.docstatus==1",
"fieldname": "received_qty",
"fieldtype": "Float",
- "label": "Received Quantity",
+ "label": "Received Qty",
"no_copy": 1,
"print_hide": 1,
"read_only": 1
@@ -398,6 +384,7 @@
},
{
"collapsible": 1,
+ "depends_on": "eval:in_list([\"Manufacture\", \"Purchase\"], parent.material_request_type)",
"fieldname": "manufacture_details",
"fieldtype": "Section Break",
"label": "Manufacture"
@@ -430,10 +417,11 @@
"depends_on": "eval:parent.material_request_type == \"Material Transfer\"",
"fieldname": "from_warehouse",
"fieldtype": "Link",
- "label": "Source Warehouse (Material Transfer)",
+ "label": "Source Warehouse",
"options": "Warehouse"
},
{
+ "allow_on_submit": 1,
"fieldname": "bom_no",
"fieldtype": "Link",
"label": "BOM No",
@@ -444,12 +432,25 @@
{
"fieldname": "section_break_46",
"fieldtype": "Section Break"
+ },
+ {
+ "fieldname": "col_break_mfg",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "qty_info_sec_break",
+ "fieldtype": "Section Break"
+ },
+ {
+ "fieldname": "qty_info_col_break",
+ "fieldtype": "Column Break"
}
],
"idx": 1,
+ "index_web_pages_for_search": 1,
"istable": 1,
"links": [],
- "modified": "2020-05-15 09:00:00.992835",
+ "modified": "2020-10-02 11:44:36.553064",
"modified_by": "Administrator",
"module": "Stock",
"name": "Material Request Item",
diff --git a/erpnext/stock/report/item_prices/item_prices.py b/erpnext/stock/report/item_prices/item_prices.py
index aa3ed92..12f3297 100644
--- a/erpnext/stock/report/item_prices/item_prices.py
+++ b/erpnext/stock/report/item_prices/item_prices.py
@@ -77,38 +77,33 @@
return item_rate_map
def get_last_purchase_rate():
-
item_last_purchase_rate_map = {}
- query = """select * from (select
- result.item_code,
- result.base_rate
- from (
- (select
- po_item.item_code,
- po_item.item_name,
- po.transaction_date as posting_date,
- po_item.base_price_list_rate,
- po_item.discount_percentage,
- po_item.base_rate
- from `tabPurchase Order` po, `tabPurchase Order Item` po_item
- where po.name = po_item.parent and po.docstatus = 1)
- union
- (select
- pr_item.item_code,
- pr_item.item_name,
- pr.posting_date,
- pr_item.base_price_list_rate,
- pr_item.discount_percentage,
- pr_item.base_rate
- from `tabPurchase Receipt` pr, `tabPurchase Receipt Item` pr_item
- where pr.name = pr_item.parent and pr.docstatus = 1)
- ) result
- order by result.item_code asc, result.posting_date desc) result_wrapper
- group by item_code"""
+ query = """select * from (
+ (select
+ po_item.item_code,
+ po.transaction_date as posting_date,
+ po_item.base_rate
+ from `tabPurchase Order` po, `tabPurchase Order Item` po_item
+ where po.name = po_item.parent and po.docstatus = 1)
+ union
+ (select
+ pr_item.item_code,
+ pr.posting_date,
+ pr_item.base_rate
+ from `tabPurchase Receipt` pr, `tabPurchase Receipt Item` pr_item
+ where pr.name = pr_item.parent and pr.docstatus = 1)
+ union
+ (select
+ pi_item.item_code,
+ pi.posting_date,
+ pi_item.base_rate
+ from `tabPurchase Invoice` pi, `tabPurchase Invoice Item` pi_item
+ where pi.name = pi_item.parent and pi.docstatus = 1 and pi.update_stock = 1)
+ ) result order by result.item_code asc, result.posting_date asc"""
for d in frappe.db.sql(query, as_dict=1):
- item_last_purchase_rate_map.setdefault(d.item_code, d.base_rate)
+ item_last_purchase_rate_map[d.item_code] = d.base_rate
return item_last_purchase_rate_map
diff --git a/erpnext/utilities/transaction_base.py b/erpnext/utilities/transaction_base.py
index c8e3330..298e111 100644
--- a/erpnext/utilities/transaction_base.py
+++ b/erpnext/utilities/transaction_base.py
@@ -5,7 +5,7 @@
import frappe
import frappe.share
from frappe import _
-from frappe.utils import cstr, now_datetime, cint, flt, get_time, get_datetime, get_link_to_form
+from frappe.utils import cstr, now_datetime, cint, flt, get_time, get_datetime, get_link_to_form, date_diff, nowdate
from erpnext.controllers.status_updater import StatusUpdater
from erpnext.accounts.utils import get_fiscal_year
@@ -29,7 +29,27 @@
except ValueError:
frappe.throw(_('Invalid Posting Time'))
+ self.validate_future_posting()
self.validate_with_last_transaction_posting_time()
+
+ def is_stock_transaction(self):
+ if self.doctype not in ["Sales Invoice", "Purchase Invoice", "Stock Entry", "Stock Reconciliation",
+ "Delivery Note", "Purchase Receipt", "Fees"]:
+ return False
+
+ if self.doctype in ["Sales Invoice", "Purchase Invoice"]:
+ if not (self.get("update_stock") or self.get("is_pos")):
+ return False
+
+ return True
+
+ def validate_future_posting(self):
+ if not self.is_stock_transaction():
+ return
+
+ if getattr(self, 'set_posting_time', None) and date_diff(self.posting_date, nowdate()) > 0:
+ msg = _("Posting future transactions are not allowed due to Immutable Ledger")
+ frappe.throw(msg, title=_("Future Posting Not Allowed"))
def add_calendar_event(self, opts, force=False):
if cstr(self.contact_by) != cstr(self._prev.contact_by) or \
@@ -162,13 +182,8 @@
def validate_with_last_transaction_posting_time(self):
- if self.doctype not in ["Sales Invoice", "Purchase Invoice", "Stock Entry", "Stock Reconciliation",
- "Delivery Note", "Purchase Receipt", "Fees"]:
- return
-
- if self.doctype in ["Sales Invoice", "Purchase Invoice"]:
- if not (self.get("update_stock") or self.get("is_pos")):
- return
+ if not self.is_stock_transaction():
+ return
for item in self.get('items'):
last_transaction_time = frappe.db.sql("""