diff --git a/erpnext/__init__.py b/erpnext/__init__.py index 8c387dd887..32c971969b 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -2,7 +2,7 @@ from __future__ import unicode_literals import frappe -__version__ = '8.1.7' +__version__ = '8.2.0' def get_default_company(user=None): diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js index ad5ecc160d..ac5f5dd321 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js @@ -224,9 +224,9 @@ cur_frm.fields_dict.cash_bank_account.get_query = function(doc) { return { filters: [ ["Account", "account_type", "in", ["Cash", "Bank"]], - ["Account", "root_type", "=", "Asset"], ["Account", "is_group", "=",0], - ["Account", "company", "=", doc.company] + ["Account", "company", "=", doc.company], + ["Account", "report_type", "=", "Balance Sheet"] ] } } diff --git a/erpnext/buying/doctype/supplier/supplier_list.js b/erpnext/buying/doctype/supplier/supplier_list.js index dd98c434f1..ab25d2c8fc 100644 --- a/erpnext/buying/doctype/supplier/supplier_list.js +++ b/erpnext/buying/doctype/supplier/supplier_list.js @@ -1,3 +1,3 @@ frappe.listview_settings['Supplier'] = { - add_fields: ["supplier_name", "supplier_type"], + add_fields: ["supplier_name", "supplier_type", "image"], }; diff --git a/erpnext/config/support.py b/erpnext/config/support.py index c1f56f0516..b85c430899 100644 --- a/erpnext/config/support.py +++ b/erpnext/config/support.py @@ -49,6 +49,12 @@ def get_data(): "doctype": "Issue", "is_query_report": True }, + { + "type": "report", + "name": "Support Hours", + "doctype": "Issue", + "is_query_report": True + }, ] }, ] diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py index 553c7b345a..9ccf7f4de1 100644 --- a/erpnext/controllers/buying_controller.py +++ b/erpnext/controllers/buying_controller.py @@ -255,7 +255,7 @@ class BuyingController(StockController): def get_items_from_bom(self, item_code, bom): bom_items = frappe.db.sql("""select t2.item_code, - t2.qty / ifnull(t1.quantity, 1) as qty_consumed_per_unit, + t2.stock_qty / ifnull(t1.quantity, 1) as qty_consumed_per_unit, t2.rate, t2.stock_uom, t2.name, t2.description from `tabBOM` t1, `tabBOM Item` t2, tabItem t3 where t2.parent = t1.name and t1.item = %s diff --git a/erpnext/docs/assets/img/support/support_hours.png b/erpnext/docs/assets/img/support/support_hours.png new file mode 100644 index 0000000000..44cfbbbdaa Binary files /dev/null and b/erpnext/docs/assets/img/support/support_hours.png differ diff --git a/erpnext/docs/user/manual/en/support/support_reports.md b/erpnext/docs/user/manual/en/support/support_reports.md new file mode 100644 index 0000000000..2be72e10ef --- /dev/null +++ b/erpnext/docs/user/manual/en/support/support_reports.md @@ -0,0 +1,8 @@ + + +### Support Hours +This report provide the information about the time slot along with the count of issues has been reported during the slot daywise. + +> Support > Reports > Support Hours + +Maintenance Visit diff --git a/erpnext/manufacturing/doctype/bom/bom.js b/erpnext/manufacturing/doctype/bom/bom.js index 83e0950f6e..87dd565599 100644 --- a/erpnext/manufacturing/doctype/bom/bom.js +++ b/erpnext/manufacturing/doctype/bom/bom.js @@ -5,7 +5,7 @@ frappe.provide("erpnext.bom"); frappe.ui.form.on("BOM", { setup: function(frm) { - frm.add_fetch('buying_price_list', 'currency', 'currency') + frm.add_fetch('buying_price_list', 'currency', 'currency'); frm.fields_dict["items"].grid.get_field("bom_no").get_query = function(doc, cdt, cdn){ return { filters: {'currency': frm.doc.currency} @@ -74,6 +74,15 @@ erpnext.bom.BomController = erpnext.TransactionController.extend({ get_bom_material_detail(doc, cdt, cdn, scrap_items); }, + conversion_factor: function(doc, cdt, cdn, dont_fetch_price_list_rate) { + if(frappe.meta.get_docfield(cdt, "stock_qty", cdn)) { + var item = frappe.get_doc(cdt, cdn); + frappe.model.round_floats_in(item, ["qty", "conversion_factor"]); + item.stock_qty = flt(item.qty * item.conversion_factor, precision("stock_qty", item)); + refresh_field("stock_qty", item.name, item.parentfield); + this.toggle_conversion_factor(item); + } + }, }) $.extend(cur_frm.cscript, new erpnext.bom.BomController({frm: cur_frm})); @@ -300,6 +309,13 @@ frappe.ui.form.on("BOM Operation", "workstation", function(frm, cdt, cdn) { }) }); +frappe.ui.form.on("BOM Item", "qty", function(frm, cdt, cdn) { + var d = locals[cdt][cdn]; + d.stock_qty = d.qty * d.conversion_factor; + refresh_field("items"); +}); + + 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 bbfdc9a337..41eec8d933 100644 --- a/erpnext/manufacturing/doctype/bom/bom.py +++ b/erpnext/manufacturing/doctype/bom/bom.py @@ -7,6 +7,7 @@ from frappe.utils import cint, cstr, flt from frappe import _ from erpnext.setup.utils import get_exchange_rate from frappe.website.website_generator import WebsiteGenerator +from erpnext.stock.get_item_details import get_conversion_factor from operator import itemgetter @@ -48,7 +49,7 @@ class BOM(WebsiteGenerator): self.set_conversion_rate() from erpnext.utilities.transaction_base import validate_uom_is_integer - validate_uom_is_integer(self, "stock_uom", "qty", "BOM Item") + validate_uom_is_integer(self, "stock_uom", "stock_qty", "BOM Item") self.validate_materials() self.set_bom_material_details() @@ -60,6 +61,7 @@ class BOM(WebsiteGenerator): def on_update(self): self.check_recursion() + self.update_stock_qty() self.update_exploded_items() def on_submit(self): @@ -94,7 +96,7 @@ class BOM(WebsiteGenerator): def set_bom_material_details(self): for item in self.get("items"): ret = self.get_bom_material_detail({"item_code": item.item_code, "item_name": item.item_name, "bom_no": item.bom_no, - "qty": item.qty}) + "stock_qty": item.stock_qty}) for r in ret: if not item.get(r): item.set(r, ret[r]) @@ -122,8 +124,11 @@ class BOM(WebsiteGenerator): 'description' : item and args['description'] or '', 'image' : item and args['image'] or '', 'stock_uom' : item and args['stock_uom'] or '', + 'uom' : item and args['stock_uom'] or '', + 'conversion_factor' : 1, 'bom_no' : args['bom_no'], 'rate' : rate, + 'stock_qty' : args.get("qty") or args.get("stock_qty") or 1, 'base_rate' : rate if self.company_currency() == self.currency else rate * self.conversion_rate } return ret_item @@ -160,7 +165,7 @@ class BOM(WebsiteGenerator): for d in self.get("items"): rate = self.get_bom_material_detail({'item_code': d.item_code, 'bom_no': d.bom_no, - 'qty': d.qty})["rate"] + 'stock_qty': d.stock_qty})["rate"] if rate: d.rate = rate @@ -240,6 +245,19 @@ class BOM(WebsiteGenerator): frappe.db.get_value('Price List', self.buying_price_list, 'currency') != self.currency: frappe.throw(_("Currency of the price list {0} is not similar with the selected currency {1}").format(self.buying_price_list, self.currency)) + + def update_stock_qty(self): + for m in self.get('items'): + + if not m.conversion_factor: + m.conversion_factor = flt(get_conversion_factor(m.item_code, m.uom)['conversion_factor']) + if m.uom and m.qty: + m.stock_qty = flt(m.conversion_factor)*flt(m.qty) + if not m.uom and m.stock_uom: + m.uom = m.stock_uom + m.qty = m.stock_qty + + def set_conversion_rate(self): self.conversion_rate = get_exchange_rate(self.currency, self.company_currency()) @@ -259,7 +277,7 @@ class BOM(WebsiteGenerator): for m in self.get('items'): if m.bom_no: validate_bom_no(m.item_code, m.bom_no) - if flt(m.qty) <= 0: + if flt(m.stock_qty) <= 0: frappe.throw(_("Quantity required for Item {0} in row {1}").format(m.item_code, m.idx)) check_list.append(m) @@ -351,9 +369,9 @@ class BOM(WebsiteGenerator): d.rate = self.get_bom_unitcost(d.bom_no) d.base_rate = flt(d.rate) * flt(self.conversion_rate) - d.amount = flt(d.rate, self.precision("rate", d)) * flt(d.qty, self.precision("qty", d)) + d.amount = flt(d.rate, self.precision("rate", d)) * flt(d.stock_qty, self.precision("stock_qty", d)) d.base_amount = d.amount * flt(self.conversion_rate) - d.qty_consumed_per_unit = flt(d.qty, self.precision("qty", d)) / flt(self.quantity, self.precision("quantity")) + d.qty_consumed_per_unit = flt(d.stock_qty, self.precision("stock_qty", d)) / flt(self.quantity, self.precision("quantity")) total_rm_cost += d.amount base_total_rm_cost += d.base_amount @@ -367,7 +385,7 @@ class BOM(WebsiteGenerator): for d in self.get('scrap_items'): d.base_rate = d.rate * self.conversion_rate - d.amount = flt(d.rate, self.precision("rate", d)) * flt(d.qty, self.precision("qty", d)) + d.amount = flt(d.rate, self.precision("rate", d)) * flt(d.stock_qty, self.precision("stock_qty", d)) d.base_amount = d.amount * self.conversion_rate total_sm_cost += d.amount base_total_sm_cost += d.base_amount @@ -385,7 +403,7 @@ class BOM(WebsiteGenerator): self.cur_exploded_items = {} for d in self.get('items'): if d.bom_no: - self.get_child_exploded_items(d.bom_no, d.qty) + self.get_child_exploded_items(d.bom_no, d.stock_qty) else: self.add_to_cur_exploded_items(frappe._dict({ 'item_code' : d.item_code, @@ -393,7 +411,7 @@ class BOM(WebsiteGenerator): 'description' : d.description, 'image' : d.image, 'stock_uom' : d.stock_uom, - 'qty' : flt(d.qty), + 'stock_qty' : flt(d.stock_qty), 'rate' : d.base_rate, })) @@ -402,16 +420,16 @@ class BOM(WebsiteGenerator): def add_to_cur_exploded_items(self, args): if self.cur_exploded_items.get(args.item_code): - self.cur_exploded_items[args.item_code]["qty"] += args.qty + self.cur_exploded_items[args.item_code]["stock_qty"] += args.stock_qty else: self.cur_exploded_items[args.item_code] = args - def get_child_exploded_items(self, bom_no, qty): + def get_child_exploded_items(self, bom_no, stock_qty): """ Add all items from Flat BOM of child BOM""" # Did not use qty_consumed_per_unit in the query, as it leads to rounding loss child_fb_items = frappe.db.sql("""select bom_item.item_code, bom_item.item_name, bom_item.description, - bom_item.stock_uom, bom_item.qty, bom_item.rate, - bom_item.qty / ifnull(bom.quantity, 1) as qty_consumed_per_unit + bom_item.stock_uom, bom_item.stock_qty, bom_item.rate, + bom_item.stock_qty / ifnull(bom.quantity, 1) as qty_consumed_per_unit from `tabBOM Explosion Item` bom_item, tabBOM bom where bom_item.parent = bom.name and bom.name = %s and bom.docstatus = 1""", bom_no, as_dict = 1) @@ -421,7 +439,7 @@ class BOM(WebsiteGenerator): 'item_name' : d['item_name'], 'description' : d['description'], 'stock_uom' : d['stock_uom'], - 'qty' : d['qty_consumed_per_unit']*qty, + 'stock_qty' : d['qty_consumed_per_unit']*stock_qty, 'rate' : flt(d['rate']), })) @@ -433,8 +451,8 @@ class BOM(WebsiteGenerator): ch = self.append('exploded_items', {}) for i in self.cur_exploded_items[d].keys(): ch.set(i, self.cur_exploded_items[d][i]) - ch.amount = flt(ch.qty) * flt(ch.rate) - ch.qty_consumed_per_unit = flt(ch.qty) / flt(self.quantity) + ch.amount = flt(ch.stock_qty) * flt(ch.rate) + ch.qty_consumed_per_unit = flt(ch.stock_qty) / flt(self.quantity) ch.docstatus = self.docstatus ch.db_insert() @@ -468,7 +486,7 @@ def get_bom_items_as_dict(bom, company, qty=1, fetch_exploded=1, fetch_scrap_ite query = """select bom_item.item_code, item.item_name, - sum(bom_item.qty/ifnull(bom.quantity, 1)) * %(qty)s as qty, + sum(bom_item.stock_qty/ifnull(bom.quantity, 1)) * %(qty)s as qty, item.description, item.image, item.stock_uom, @@ -478,13 +496,13 @@ def get_bom_items_as_dict(bom, company, qty=1, fetch_exploded=1, fetch_scrap_ite from `tab{table}` bom_item, `tabBOM` bom, `tabItem` item where - bom_item.parent = bom.name - and bom_item.docstatus < 2 - and bom_item.parent = %(bom)s + bom_item.docstatus < 2 + and bom.name = %(bom)s + and bom_item.parent = bom.name and item.name = bom_item.item_code and is_stock_item = 1 {conditions} - group by item_code, stock_uom""" + group by item_code, stock_uom""" if fetch_exploded: query = query.format(table="BOM Explosion Item", @@ -536,7 +554,7 @@ def get_children(): return frappe.db.sql("""select bom_item.item_code, bom_item.bom_no as value, - bom_item.qty, + bom_item.stock_qty, if(ifnull(bom_item.bom_no, "")!="", 1, 0) as expandable, item.image, item.description diff --git a/erpnext/manufacturing/doctype/bom/test_records.json b/erpnext/manufacturing/doctype/bom/test_records.json index 5baa0cbf1d..0f1143ef7d 100644 --- a/erpnext/manufacturing/doctype/bom/test_records.json +++ b/erpnext/manufacturing/doctype/bom/test_records.json @@ -6,7 +6,7 @@ "doctype": "BOM Item", "item_code": "_Test Serialized Item With Series", "parentfield": "items", - "qty": 1.0, + "stock_qty": 1.0, "rate": 5000.0, "stock_uom": "_Test UOM" }, @@ -15,7 +15,7 @@ "doctype": "BOM Item", "item_code": "_Test Item 2", "parentfield": "items", - "qty": 2.0, + "stock_qty": 2.0, "rate": 1000.0, "stock_uom": "_Test UOM" } @@ -35,7 +35,7 @@ "doctype": "BOM Item", "item_code": "_Test Item Home Desktop 100", "parentfield": "items", - "qty": 1.0, + "stock_qty": 1.0, "rate": 2000.0, "stock_uom": "_Test UOM" } @@ -46,7 +46,7 @@ "doctype": "BOM Item", "item_code": "_Test Item", "parentfield": "items", - "qty": 1.0, + "stock_qty": 1.0, "rate": 5000.0, "stock_uom": "_Test UOM" }, @@ -55,7 +55,7 @@ "doctype": "BOM Item", "item_code": "_Test Item Home Desktop 100", "parentfield": "items", - "qty": 2.0, + "stock_qty": 2.0, "rate": 1000.0, "stock_uom": "_Test UOM" } @@ -84,7 +84,7 @@ "doctype": "BOM Item", "item_code": "_Test Item", "parentfield": "items", - "qty": 1.0, + "stock_qty": 1.0, "rate": 5000.0, "stock_uom": "_Test UOM" }, @@ -94,7 +94,7 @@ "doctype": "BOM Item", "item_code": "_Test Item Home Desktop Manufactured", "parentfield": "items", - "qty": 3.0, + "stock_qty": 3.0, "rate": 1000.0, "stock_uom": "_Test UOM" } @@ -124,7 +124,7 @@ "doctype": "BOM Item", "item_code": "_Test Item", "parentfield": "items", - "qty": 2.0, + "stock_qty": 2.0, "rate": 3000.0, "stock_uom": "_Test UOM" } 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 f075840806..e1a3d4da53 100644 --- a/erpnext/manufacturing/doctype/bom_explosion_item/bom_explosion_item.json +++ b/erpnext/manufacturing/doctype/bom_explosion_item/bom_explosion_item.json @@ -1,5 +1,6 @@ { "allow_copy": 0, + "allow_guest_to_view": 0, "allow_import": 0, "allow_rename": 0, "autoname": "hash", @@ -13,6 +14,7 @@ "engine": "InnoDB", "fields": [ { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -44,6 +46,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -72,6 +75,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -101,6 +105,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -129,6 +134,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -161,6 +167,7 @@ "width": "300px" }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -189,6 +196,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -218,6 +226,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -248,6 +257,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -276,11 +286,12 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, "columns": 0, - "fieldname": "qty", + "fieldname": "stock_qty", "fieldtype": "Float", "hidden": 0, "ignore_user_permissions": 0, @@ -289,7 +300,7 @@ "in_global_search": 0, "in_list_view": 1, "in_standard_filter": 0, - "label": "Qty", + "label": "Stock Qty", "length": 0, "no_copy": 0, "oldfieldname": "qty", @@ -306,6 +317,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -337,6 +349,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -365,6 +378,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -393,6 +407,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -424,6 +439,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -455,17 +471,17 @@ "unique": 0 } ], + "has_web_view": 0, "hide_heading": 0, "hide_toolbar": 0, "idx": 1, "image_view": 0, "in_create": 0, - "in_dialog": 0, "is_submittable": 0, "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2017-02-17 17:27:43.757983", + "modified": "2017-06-02 19:29:34.498719", "modified_by": "Administrator", "module": "Manufacturing", "name": "BOM Explosion Item", diff --git a/erpnext/manufacturing/doctype/bom_item/bom_item.json b/erpnext/manufacturing/doctype/bom_item/bom_item.json index 2fc29a883b..966b89bd4c 100644 --- a/erpnext/manufacturing/doctype/bom_item/bom_item.json +++ b/erpnext/manufacturing/doctype/bom_item/bom_item.json @@ -1,5 +1,6 @@ { "allow_copy": 0, + "allow_guest_to_view": 0, "allow_import": 0, "allow_rename": 0, "beta": 0, @@ -11,6 +12,7 @@ "editable_grid": 1, "fields": [ { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -20,7 +22,8 @@ "hidden": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, - "in_filter": 1, + "in_filter": 0, + "in_global_search": 0, "in_list_view": 1, "in_standard_filter": 0, "label": "Item Code", @@ -41,6 +44,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -51,6 +55,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Item Name", @@ -69,6 +74,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -79,6 +85,7 @@ "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, @@ -96,6 +103,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -105,7 +113,8 @@ "hidden": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, - "in_filter": 1, + "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "BOM No", @@ -128,6 +137,7 @@ "width": "150px" }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -138,6 +148,7 @@ "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, @@ -155,6 +166,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -165,6 +177,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Item Description", @@ -186,6 +199,7 @@ "width": "250px" }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -196,6 +210,7 @@ "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, @@ -212,6 +227,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -222,6 +238,7 @@ "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", @@ -240,6 +257,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -250,6 +268,7 @@ "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", @@ -269,6 +288,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -279,6 +299,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Quantity and Rate", @@ -296,6 +317,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -306,6 +328,7 @@ "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", @@ -319,16 +342,170 @@ "read_only": 0, "remember_last_selected_value": 0, "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 1, + "fieldname": "uom", + "fieldtype": "Link", + "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": "UOM", + "length": 0, + "no_copy": 0, + "options": "UOM", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "col_break2", + "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, + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "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": 0, + "in_standard_filter": 0, + "label": "Stock Qty", + "length": 0, + "no_copy": 0, + "oldfieldname": "stock_qty", + "oldfieldtype": "Currency", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 1, + "remember_last_selected_value": 0, + "report_hide": 0, "reqd": 1, "search_index": 0, "set_only_once": 0, "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, - "columns": 2, + "columns": 0, + "fieldname": "conversion_factor", + "fieldtype": "Float", + "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": "Conversion Factor", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "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": "Data", + "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": 1, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, "description": "See \"Rate Of Materials Based On\" in Costing Section", "fieldname": "rate", "fieldtype": "Currency", @@ -336,7 +513,8 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, - "in_list_view": 1, + "in_global_search": 0, + "in_list_view": 0, "in_standard_filter": 0, "label": "Rate", "length": 0, @@ -354,6 +532,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -364,6 +543,7 @@ "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", @@ -386,62 +566,7 @@ "width": "150px" }, { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "col_break2", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_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_list_view": 0, - "in_standard_filter": 0, - "label": "Stock UOM", - "length": 0, - "no_copy": 0, - "oldfieldname": "stock_uom", - "oldfieldtype": "Data", - "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": 1, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -452,6 +577,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Basic Rate (Company Currency)", @@ -471,6 +597,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -481,6 +608,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Amount (Company Currency)", @@ -500,6 +628,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -510,6 +639,7 @@ "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, @@ -527,6 +657,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -537,6 +668,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 1, "in_standard_filter": 0, "label": "Scrap %", @@ -556,6 +688,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -566,6 +699,7 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Qty Consumed Per Unit", @@ -585,18 +719,18 @@ "unique": 0 } ], + "has_web_view": 0, "hide_heading": 0, "hide_toolbar": 0, "idx": 1, "image_view": 0, "in_create": 0, - "in_dialog": 0, "is_submittable": 0, "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2016-12-20 12:54:34.859076", - "modified_by": "rmehta@gmail.com", + "modified": "2017-05-23 15:59:37.946963", + "modified_by": "Administrator", "module": "Manufacturing", "name": "BOM Item", "owner": "Administrator", @@ -604,7 +738,9 @@ "quick_entry": 0, "read_only": 0, "read_only_onload": 0, + "show_name_in_global_search": 0, "sort_field": "modified", "sort_order": "DESC", + "track_changes": 0, "track_seen": 0 } \ No newline at end of file diff --git a/erpnext/manufacturing/doctype/bom_replace_tool/bom_replace_tool.py b/erpnext/manufacturing/doctype/bom_replace_tool/bom_replace_tool.py index d4d5329ace..f0a834c37b 100644 --- a/erpnext/manufacturing/doctype/bom_replace_tool/bom_replace_tool.py +++ b/erpnext/manufacturing/doctype/bom_replace_tool/bom_replace_tool.py @@ -33,7 +33,7 @@ class BOMReplaceTool(Document): from `tabBOM` where name = %s""", self.current_bom) current_bom_unitcost = current_bom_unitcost and flt(current_bom_unitcost[0][0]) or 0 frappe.db.sql("""update `tabBOM Item` set bom_no=%s, - rate=%s, amount=qty*%s where bom_no = %s and docstatus < 2""", + rate=%s, amount=stock_qty*%s where bom_no = %s and docstatus < 2""", (self.new_bom, current_bom_unitcost, current_bom_unitcost, self.current_bom)) def get_parent_boms(self): diff --git a/erpnext/manufacturing/doctype/bom_scrap_item/bom_scrap_item.json b/erpnext/manufacturing/doctype/bom_scrap_item/bom_scrap_item.json index fe81592769..e9aebfe39c 100644 --- a/erpnext/manufacturing/doctype/bom_scrap_item/bom_scrap_item.json +++ b/erpnext/manufacturing/doctype/bom_scrap_item/bom_scrap_item.json @@ -1,5 +1,6 @@ { "allow_copy": 0, + "allow_guest_to_view": 0, "allow_import": 0, "allow_rename": 0, "beta": 0, @@ -11,6 +12,7 @@ "editable_grid": 1, "fields": [ { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -21,7 +23,9 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 1, + "in_standard_filter": 0, "label": "Item Code", "length": 0, "no_copy": 0, @@ -31,6 +35,7 @@ "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 0, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 1, "search_index": 0, @@ -38,6 +43,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -48,7 +54,9 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 1, + "in_standard_filter": 0, "label": "Item Name", "length": 0, "no_copy": 0, @@ -57,6 +65,7 @@ "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, @@ -64,6 +73,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -74,7 +84,9 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Quantity and Rate", "length": 0, "no_copy": 0, @@ -83,6 +95,7 @@ "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, @@ -90,17 +103,20 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, "columns": 0, - "fieldname": "qty", + "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": "Qty", "length": 0, "no_copy": 0, @@ -109,6 +125,7 @@ "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 0, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 1, "search_index": 0, @@ -116,6 +133,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -126,7 +144,9 @@ "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, @@ -136,6 +156,7 @@ "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, @@ -143,6 +164,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -153,7 +175,9 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Amount", "length": 0, "no_copy": 0, @@ -163,6 +187,7 @@ "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, @@ -170,6 +195,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -180,7 +206,9 @@ "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, @@ -188,6 +216,7 @@ "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, @@ -195,6 +224,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -205,7 +235,9 @@ "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, @@ -215,6 +247,7 @@ "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, @@ -222,6 +255,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -232,7 +266,9 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Basic Rate (Company Currency)", "length": 0, "no_copy": 0, @@ -242,6 +278,7 @@ "print_hide": 1, "print_hide_if_no_value": 0, "read_only": 1, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, "search_index": 0, @@ -249,6 +286,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -259,7 +297,9 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Basic Amount (Company Currency)", "length": 0, "no_copy": 0, @@ -269,6 +309,7 @@ "print_hide": 1, "print_hide_if_no_value": 0, "read_only": 1, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, "search_index": 0, @@ -276,17 +317,17 @@ "unique": 0 } ], + "has_web_view": 0, "hide_heading": 0, "hide_toolbar": 0, "idx": 0, "image_view": 0, "in_create": 0, - "in_dialog": 0, "is_submittable": 0, "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2016-10-25 00:27:53.712140", + "modified": "2017-05-23 16:04:32.442287", "modified_by": "Administrator", "module": "Manufacturing", "name": "BOM Scrap Item", @@ -296,7 +337,9 @@ "quick_entry": 1, "read_only": 0, "read_only_onload": 0, + "show_name_in_global_search": 0, "sort_field": "modified", "sort_order": "DESC", + "track_changes": 1, "track_seen": 0 } \ No newline at end of file diff --git a/erpnext/manufacturing/doctype/production_order/test_production_order.py b/erpnext/manufacturing/doctype/production_order/test_production_order.py index 40e839323c..cdadba4825 100644 --- a/erpnext/manufacturing/doctype/production_order/test_production_order.py +++ b/erpnext/manufacturing/doctype/production_order/test_production_order.py @@ -266,9 +266,9 @@ class TestProductionOrder(unittest.TestCase): def get_scrap_item_details(bom_no): scrap_items = {} - for item in frappe.db.sql("""select item_code, qty from `tabBOM Scrap Item` + for item in frappe.db.sql("""select item_code, stock_qty from `tabBOM Scrap Item` where parent = %s""", bom_no, as_dict=1): - scrap_items[item.item_code] = item.qty + scrap_items[item.item_code] = item.stock_qty return scrap_items @@ -287,8 +287,7 @@ def make_prod_order_test_record(**args): pro_order.stock_uom = args.stock_uom or "_Test UOM" pro_order.use_multi_level_bom=0 pro_order.set_production_order_operations() - - + if args.source_warehouse: pro_order.source_warehouse = args.source_warehouse @@ -297,6 +296,7 @@ def make_prod_order_test_record(**args): if not args.do_not_save: pro_order.insert() + if not args.do_not_submit: pro_order.submit() return pro_order diff --git a/erpnext/manufacturing/doctype/production_planning_tool/production_planning_tool.py b/erpnext/manufacturing/doctype/production_planning_tool/production_planning_tool.py index dd4b2b69ab..050c3c1c33 100644 --- a/erpnext/manufacturing/doctype/production_planning_tool/production_planning_tool.py +++ b/erpnext/manufacturing/doctype/production_planning_tool/production_planning_tool.py @@ -321,7 +321,7 @@ class ProductionPlanningTool(Document): # get all raw materials with sub assembly childs # Did not use qty_consumed_per_unit in the query, as it leads to rounding loss for d in frappe.db.sql("""select fb.item_code, - ifnull(sum(fb.qty/ifnull(bom.quantity, 1)), 0) as qty, + ifnull(sum(fb.stock_qty/ifnull(bom.quantity, 1)), 0) as qty, fb.description, fb.stock_uom, item.min_order_qty from `tabBOM Explosion Item` fb, `tabBOM` bom, `tabItem` item where bom.name = fb.parent and item.name = fb.item_code @@ -348,7 +348,7 @@ class ProductionPlanningTool(Document): SELECT bom_item.item_code, default_material_request_type, - ifnull(%(parent_qty)s * sum(bom_item.qty/ifnull(bom.quantity, 1)), 0) as qty, + ifnull(%(parent_qty)s * sum(bom_item.stock_qty/ifnull(bom.quantity, 1)), 0) as qty, item.is_sub_contracted_item as is_sub_contracted, item.default_bom as default_bom, bom_item.description as description, diff --git a/erpnext/manufacturing/doctype/production_planning_tool/test_production_planning_tool.py b/erpnext/manufacturing/doctype/production_planning_tool/test_production_planning_tool.py index ea4da0cb94..4f80b6a626 100644 --- a/erpnext/manufacturing/doctype/production_planning_tool/test_production_planning_tool.py +++ b/erpnext/manufacturing/doctype/production_planning_tool/test_production_planning_tool.py @@ -235,9 +235,9 @@ def create_test_records(): "is_active": 1, "is_default": 1, "docstatus": 1, - "with_operations": 0}, [{"item_code": "_Test PPT Item Raw B", "doctype":"BOM Item", "qty":1, + "with_operations": 0}, [{"item_code": "_Test PPT Item Raw B", "doctype":"BOM Item", "stock_qty":1, "rate":100, "amount": 100, "stock_uom": "_Test UOM"}, - {"item_code": "_Test PPT Item Raw C", "doctype":"BOM Item", "qty":4, "rate":100, + {"item_code": "_Test PPT Item Raw C", "doctype":"BOM Item", "stock_qty":4, "rate":100, "amount": 400,"stock_uom": "_Test UOM"}]) bom_subC = make_bom("BOM-_Test PPT Item Sub C-001",{"quantity":1, @@ -247,9 +247,9 @@ def create_test_records(): "docstatus": 1, "with_operations": 0}, [ {"item_code": "_Test PPT Item Raw A","item_name": "_Test PPT Item Raw A", - "doctype":"BOM Item", "qty":6, "rate":100, "amount": 600}, + "doctype":"BOM Item", "stock_qty":6, "rate":100, "amount": 600}, {"item_code": "_Test PPT Item Sub B","item_name": "_Test PPT Item Sub B", - "bom_no":"BOM-_Test PPT Item Sub B-001", "doctype":"BOM Item", "qty":2, + "bom_no":"BOM-_Test PPT Item Sub B-001", "doctype":"BOM Item", "stock_qty":2, "rate":100, "amount": 200}]) bom_sCA = make_bom("BOM-_Test PPT Item SC A-001",{"quantity":1, @@ -259,7 +259,7 @@ def create_test_records(): "docstatus": 1, "with_operations": 0}, [ {"item_code": "_Test PPT Item Raw D","item_name": "_Test PPT Item Raw D", - "doctype":"BOM Item", "qty":1, "rate":100, "amount": 100}]) + "doctype":"BOM Item", "stock_qty":1, "rate":100, "amount": 100}]) bom_sCB = make_bom("BOM-_Test PPT Item SC B-001",{"quantity":1, "item": "_Test PPT Item SC B", @@ -268,9 +268,9 @@ def create_test_records(): "docstatus": 1, "with_operations": 0}, [ {"item_code": "_Test PPT Item Raw B","item_name": "_Test PPT Item Raw B", - "doctype":"BOM Item", "qty":1, "rate":100, "amount": 100}, + "doctype":"BOM Item", "stock_qty":1, "rate":100, "amount": 100}, {"item_code": "_Test PPT Item Raw C","item_name": "_Test PPT Item Raw C", - "doctype":"BOM Item", "qty":4, "rate":100, "amount": 400}]) + "doctype":"BOM Item", "stock_qty":4, "rate":100, "amount": 400}]) bom_subA = make_bom("BOM-_Test PPT Item Sub A-001",{"quantity":1, "item": "_Test PPT Item Sub A", @@ -278,11 +278,11 @@ def create_test_records(): "is_default": 1, "docstatus": 1, "with_operations": 0}, [ - {"item_code": "_Test PPT Item Sub C","item_name": "_Test PPT Item Sub C", + {"item_code": "_Test PPT Item Sub C","item_name": "_Test PPT Item Sub C", "bom_no":"BOM-_Test PPT Item Sub C-001", "doctype":"BOM Item", - "qty":1, "rate":100, "amount": 100}, + "stock_qty":1, "rate":100, "amount": 100}, {"item_code": "_Test PPT Item SC B","item_name": "_Test PPT Item SC B", - "bom_no":"BOM-_Test PPT Item SC B-001", "doctype":"BOM Item", "qty":2, + "bom_no":"BOM-_Test PPT Item SC B-001", "doctype":"BOM Item", "stock_qty":2, "rate":100, "amount": 200}]) bom_master = make_bom("BOM-_Test PPT Item Master-001",{"quantity":1, @@ -293,16 +293,16 @@ def create_test_records(): "with_operations": 0}, [ {"item_code": "_Test PPT Item Sub A","item_name": "_Test PPT Item Sub A", "bom_no":"BOM-_Test PPT Item Sub A-001", - "doctype":"BOM Item", "qty":2, "rate":100, "amount": 200}, + "doctype":"BOM Item", "stock_qty":2, "rate":100, "amount": 200}, {"item_code": "_Test PPT Item Sub B","item_name": "_Test PPT Item Sub B", "bom_no":"BOM-_Test PPT Item Sub B-001", - "doctype":"BOM Item", "qty":1, "rate":100, "amount": 100}, + "doctype":"BOM Item", "stock_qty":1, "rate":100, "amount": 100}, {"item_code": "_Test PPT Item Raw A","item_name": "_Test PPT Item Raw A", - "doctype":"BOM Item", "qty":2, "rate":100, + "doctype":"BOM Item", "stock_qty":2, "rate":100, "amount": 200}, {"item_code": "_Test PPT Item SC A","item_name": "_Test PPT Item SC A", "bom_no":"BOM-_Test PPT Item SC A-001", - "doctype":"BOM Item", "qty":1, "rate":100, "amount": 100} + "doctype":"BOM Item", "stock_qty":1, "rate":100, "amount": 100} ]) @@ -388,4 +388,4 @@ def get_requested_types(item_code): where item.item_code = %(item_code)s and item.parent = mat_req.name""", {"item_code":item_code}, as_dict=1): types.append(d.type) return types - \ No newline at end of file + diff --git a/erpnext/manufacturing/report/production_order_stock_report/production_order_stock_report.py b/erpnext/manufacturing/report/production_order_stock_report/production_order_stock_report.py index 6d586ddb22..bb79a49159 100644 --- a/erpnext/manufacturing/report/production_order_stock_report/production_order_stock_report.py +++ b/erpnext/manufacturing/report/production_order_stock_report/production_order_stock_report.py @@ -23,7 +23,7 @@ def get_item_list(prod_list, filters): item_list = frappe.db.sql("""SELECT bom_item.item_code as item_code, - ifnull(ledger.actual_qty*bom.quantity/bom_item.qty,0) as build_qty + ifnull(ledger.actual_qty*bom.quantity/bom_item.stock_qty,0) as build_qty FROM `tabBOM` as bom, `tabBOM Item` AS bom_item LEFT JOIN `tabBin` AS ledger diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 706638a20f..130554fe64 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -403,6 +403,7 @@ erpnext.patches.v8_0.rename_items_in_status_field_of_material_request erpnext.patches.v8_0.delete_bin_indexes erpnext.patches.v8_0.move_account_head_from_account_to_warehouse_for_inventory erpnext.patches.v8_0.change_in_words_varchar_length +erpnext.patches.v8_0.update_stock_qty_value_in_bom_item erpnext.patches.v8_0.create_domain_docs #16-05-2017 erpnext.patches.v8_0.update_sales_cost_in_project erpnext.patches.v8_0.save_system_settings diff --git a/erpnext/patches/v7_2/contact_address_links.py b/erpnext/patches/v7_2/contact_address_links.py index 07d9341f24..cf23e88798 100644 --- a/erpnext/patches/v7_2/contact_address_links.py +++ b/erpnext/patches/v7_2/contact_address_links.py @@ -4,8 +4,8 @@ from frappe.utils import update_progress_bar def execute(): frappe.reload_doc('core', 'doctype', 'dynamic_link') - frappe.reload_doc('email', 'doctype', 'contact') - frappe.reload_doc('contact', 'doctype', 'address') + frappe.reload_doc('contacts', 'doctype', 'contact') + frappe.reload_doc('contacts', 'doctype', 'address') map_fields = ( ('Customer', 'customer'), ('Supplier', 'supplier'), diff --git a/erpnext/patches/v8_0/update_stock_qty_value_in_bom_item.py b/erpnext/patches/v8_0/update_stock_qty_value_in_bom_item.py new file mode 100644 index 0000000000..9e95eb0c23 --- /dev/null +++ b/erpnext/patches/v8_0/update_stock_qty_value_in_bom_item.py @@ -0,0 +1,13 @@ +# Copyright (c) 2017, Frappe and Contributors +# License: GNU General Public License v3. See license.txt + +from __future__ import unicode_literals +import frappe + +def execute(): + frappe.reload_doc('manufacturing', 'doctype', 'bom_item') + frappe.reload_doc('manufacturing', 'doctype', 'bom_explosion_item') + frappe.reload_doc('manufacturing', 'doctype', 'bom_scrap_item') + frappe.db.sql("update `tabBOM Item` set stock_qty = qty, uom = stock_uom, conversion_factor = 1") + frappe.db.sql("update `tabBOM Explosion Item` set stock_qty = qty") + frappe.db.sql("update `tabBOM Scrap Item` set stock_qty = qty") \ No newline at end of file diff --git a/erpnext/patches/v8_1/delete_deprecated_reports.py b/erpnext/patches/v8_1/delete_deprecated_reports.py index 7e861319bf..9047d84fc8 100644 --- a/erpnext/patches/v8_1/delete_deprecated_reports.py +++ b/erpnext/patches/v8_1/delete_deprecated_reports.py @@ -15,17 +15,40 @@ def execute(): for report in reports: if frappe.db.exists("Report", report): check_and_update_desktop_icon_for_report(report) + check_and_update_auto_email_report(report) + frappe.db.commit() + frappe.delete_doc("Report", report, ignore_permissions=True) def check_and_update_desktop_icon_for_report(report): - """ delete desktop icon for deprecated desktop icon and update the _report for Addresses And Contacts""" + """ delete or update desktop icon""" + desktop_icons = frappe.db.sql_list("""select name from `tabDesktop Icon` + where _report='{0}'""".format(report)) + + if not desktop_icons: + return if report == "Monthly Salary Register": - frappe.delete_doc("Desktop Icon", report) + for icon in desktop_icons: + frappe.delete_doc("Desktop Icon", icon) elif report in ["Customer Addresses And Contacts", "Supplier Addresses And Contacts"]: - name = frappe.db.get_value("Desktop Icon", {"_report": report}) - if name: - frappe.db.set_value("Desktop Icon", name, "_report", "Addresses And Contacts") + frappe.db.sql("""update `tabDesktop Icon` set _report='{value}' + where name in ({docnames})""".format( + value=report, + docnames=",".join(["'%s'"%icon for icon in desktop_icons]) + ) + ) - frappe.db.commit() +def check_and_update_auto_email_report(report): + """ delete or update auto email report for deprecated report """ + + auto_email_report = frappe.db.get_value("Auto Email Report", {"report": report}) + if not auto_email_report: + return + + if report == "Monthly Salary Register": + frappe.delete_doc("Auto Email Report", auto_email_report) + + elif report in ["Customer Addresses And Contacts", "Supplier Addresses And Contacts"]: + frapppe.db.set_value("Auto Email Report", auto_email_report, "report", report) \ No newline at end of file diff --git a/erpnext/patches/v8_1/setup_gst_india.py b/erpnext/patches/v8_1/setup_gst_india.py index 374c738f13..1b319f9680 100644 --- a/erpnext/patches/v8_1/setup_gst_india.py +++ b/erpnext/patches/v8_1/setup_gst_india.py @@ -18,7 +18,7 @@ def execute(): def delete_custom_field_tax_id_if_exists(): for field in frappe.db.sql_list("""select name from `tabCustom Field` where fieldname='tax_id' - and dt in ('Sales Order', 'Salse Invoice', 'Delivery Note')"""): + and dt in ('Sales Order', 'Sales Invoice', 'Delivery Note')"""): frappe.delete_doc("Custom Field", field, ignore_permissions=True) frappe.db.commit() diff --git a/erpnext/public/images/erpnext-logo.jpg b/erpnext/public/images/erpnext-logo.jpg new file mode 100644 index 0000000000..811eca833e Binary files /dev/null and b/erpnext/public/images/erpnext-logo.jpg differ diff --git a/erpnext/regional/doctype/gst_settings/gst_settings.py b/erpnext/regional/doctype/gst_settings/gst_settings.py index 5edb172336..45c565d193 100644 --- a/erpnext/regional/doctype/gst_settings/gst_settings.py +++ b/erpnext/regional/doctype/gst_settings/gst_settings.py @@ -83,7 +83,7 @@ def _send_gstin_reminder(party_type, party, default_email_id=None, sent_to=None)

Please help us send you GST Ready Invoices.

- Click on the here to update your GSTIN Number in our system + Click here to update your GSTIN Number in our system

diff --git a/erpnext/regional/india/utils.py b/erpnext/regional/india/utils.py index 26c579448d..4d37498114 100644 --- a/erpnext/regional/india/utils.py +++ b/erpnext/regional/india/utils.py @@ -7,9 +7,10 @@ def validate_gstin_for_india(doc, method): return if doc.gstin: - p = re.compile("[0-9]{2}[a-zA-Z]{5}[0-9]{4}[a-zA-Z]{1}[1-9A-Za-z]{1}[Z]{1}[0-9a-zA-Z]{1}") - if not p.match(doc.gstin): - frappe.throw(_("Invalid GSTIN")) + if doc.gstin != "NA": + p = re.compile("[0-9]{2}[a-zA-Z]{5}[0-9]{4}[a-zA-Z]{1}[1-9A-Za-z]{1}[Z]{1}[0-9a-zA-Z]{1}") + if not p.match(doc.gstin): + frappe.throw(_("Invalid GSTIN or Enter NA for Unregistered")) if not doc.gst_state: if doc.state in states: diff --git a/erpnext/schools/doctype/program_enrollment/program_enrollment.js b/erpnext/schools/doctype/program_enrollment/program_enrollment.js index dcdaabc83d..d1b703b8ca 100644 --- a/erpnext/schools/doctype/program_enrollment/program_enrollment.js +++ b/erpnext/schools/doctype/program_enrollment/program_enrollment.js @@ -30,6 +30,16 @@ frappe.ui.form.on("Program Enrollment", { } }); } + + frm.set_query("student", function() { + return{ + query: "erpnext.schools.doctype.program_enrollment.program_enrollment.get_students", + filters: { + 'academic_year': frm.doc.academic_year, + 'academic_term': frm.doc.academic_term + } + } + }); }, program: function(frm) { diff --git a/erpnext/schools/doctype/program_enrollment/program_enrollment.py b/erpnext/schools/doctype/program_enrollment/program_enrollment.py index feb4c2f60e..4e679082c6 100644 --- a/erpnext/schools/doctype/program_enrollment/program_enrollment.py +++ b/erpnext/schools/doctype/program_enrollment/program_enrollment.py @@ -77,3 +77,34 @@ def get_program_courses(doctype, txt, searchfield, start, page_len, filters): "_txt": txt.replace('%', ''), "program": filters['program'] }) + + +@frappe.whitelist() +def get_students(doctype, txt, searchfield, start, page_len, filters): + if not filters.get("academic_term"): + filters["academic_term"] = frappe.defaults.get_defaults().academic_term + + if not filters.get("academic_year"): + filters["academic_year"] = frappe.defaults.get_defaults().academic_year + + enrolled_students = frappe.get_list("Program Enrollment", filters={ + "academic_term": filters.get('academic_term'), + "academic_year": filters.get('academic_year') + }, fields=["student"]) + + students = [d.student for d in enrolled_students] if enrolled_students else [""] + + return frappe.db.sql("""select + name, title from tabStudent + where + name not in (%s) + and + `%s` LIKE %s + order by + idx desc, name + limit %s, %s"""%( + ", ".join(['%s']*len(students)), searchfield, "%s", "%s", "%s"), + tuple(students + ["%%%s%%" % txt, start, page_len] + ) + ) + diff --git a/erpnext/schools/doctype/school_settings/school_settings.json b/erpnext/schools/doctype/school_settings/school_settings.json index 8607a76569..8d4d4f530d 100644 --- a/erpnext/schools/doctype/school_settings/school_settings.json +++ b/erpnext/schools/doctype/school_settings/school_settings.json @@ -139,8 +139,8 @@ "bold": 0, "collapsible": 0, "columns": 0, - "default": "1", - "fieldname": "validation_from_pe", + "description": "For Batch based Student Group, the Student Batch will be validated for every Student from the Program Enrollment.", + "fieldname": "validate_batch", "fieldtype": "Check", "hidden": 0, "ignore_user_permissions": 0, @@ -149,7 +149,38 @@ "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, - "label": "Validate the Student Group from Program Enrollment", + "label": "Validate Batch for Students in Student Group", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "description": "For Course based Student Group, the Course will be validated for every Student from the enrolled Courses in Program Enrollment.", + "fieldname": "validate_course", + "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": "Validate Enrolled Course for Students in Student Group", "length": 0, "no_copy": 0, "permlevel": 0, @@ -175,7 +206,7 @@ "issingle": 1, "istable": 0, "max_attachments": 0, - "modified": "2017-04-27 15:37:00.159072", + "modified": "2017-06-26 14:07:36.542314", "modified_by": "Administrator", "module": "Schools", "name": "School Settings", diff --git a/erpnext/schools/doctype/school_settings/school_settings.py b/erpnext/schools/doctype/school_settings/school_settings.py index 6d8efb4279..999014ad80 100644 --- a/erpnext/schools/doctype/school_settings/school_settings.py +++ b/erpnext/schools/doctype/school_settings/school_settings.py @@ -11,7 +11,8 @@ school_keydict = { # "key in defaults": "key in Global Defaults" "academic_year": "current_academic_year", "academic_term": "current_academic_term", - "student_validation_setting": "validation_from_pe", + "validate_batch": "validate_batch", + "validate_course": "validate_course" } class SchoolSettings(Document): diff --git a/erpnext/schools/doctype/student_attendance/student_attendance.py b/erpnext/schools/doctype/student_attendance/student_attendance.py index 2688123f97..696029680f 100644 --- a/erpnext/schools/doctype/student_attendance/student_attendance.py +++ b/erpnext/schools/doctype/student_attendance/student_attendance.py @@ -35,9 +35,7 @@ class StudentAttendance(Document): student_group = frappe.db.get_value("Course Schedule", self.course_schedule, "student_group") else: student_group = self.student_group - student_group_students = [] - for d in get_student_group_students(student_group): - student_group_students.append(d.student) + student_group_students = [d.student for d in get_student_group_students(student_group)] if student_group and self.student not in student_group_students: frappe.throw(_('''Student {0}: {1} does not belong to Student Group {2}'''.format(self.student, self.student_name, student_group))) diff --git a/erpnext/schools/doctype/student_group/student_group.js b/erpnext/schools/doctype/student_group/student_group.js index 83fe0945cc..80355a8b94 100644 --- a/erpnext/schools/doctype/student_group/student_group.js +++ b/erpnext/schools/doctype/student_group/student_group.js @@ -9,6 +9,22 @@ frappe.ui.form.on("Student Group", { } }; }); + if (!frm.__islocal) { + frm.set_query("student", "students", function() { + return{ + query: "erpnext.schools.doctype.student_group.student_group.fetch_students", + filters: { + 'academic_year': frm.doc.academic_year, + 'group_based_on': frm.doc.group_based_on, + 'academic_term': frm.doc.academic_term, + 'program': frm.doc.program, + 'batch': frm.doc.batch, + 'course': frm.doc.course, + 'student_group': frm.doc.name + } + } + }); + } }, refresh: function(frm) { diff --git a/erpnext/schools/doctype/student_group/student_group.py b/erpnext/schools/doctype/student_group/student_group.py index 9cdf9c7f01..55f1b66d29 100644 --- a/erpnext/schools/doctype/student_group/student_group.py +++ b/erpnext/schools/doctype/student_group/student_group.py @@ -12,8 +12,7 @@ class StudentGroup(Document): def validate(self): self.validate_mandatory_fields() self.validate_strength() - if frappe.defaults.get_defaults().student_validation_setting: - self.validate_students() + self.validate_students() self.validate_and_set_child_table_fields() validate_duplicate_student(self.students) @@ -31,12 +30,14 @@ class StudentGroup(Document): def validate_students(self): program_enrollment = get_program_enrollment(self.academic_year, self.academic_term, self.program, self.batch, self.course) - students = [d.student for d in program_enrollment] if program_enrollment else None + students = [d.student for d in program_enrollment] if program_enrollment else [] for d in self.students: - if self.group_based_on != "Activity" and students and d.student not in students and d.active == 1: - frappe.throw(_("{0} - {1} is not enrolled in the given {2}".format(d.group_roll_number, d.student_name, self.group_based_on))) if not frappe.db.get_value("Student", d.student, "enabled") and d.active: frappe.throw(_("{0} - {1} is inactive student".format(d.group_roll_number, d.student_name))) + if self.group_based_on == "Batch" and d.student not in students and frappe.defaults.get_defaults().validate_batch: + frappe.throw(_("{0} - {1} is not enrolled in the Batch {2}".format(d.group_roll_number, d.student_name, self.batch))) + if self.group_based_on == "Course" and d.student not in students and frappe.defaults.get_defaults().validate_course: + frappe.throw(_("{0} - {1} is not enrolled in the Course {2}".format(d.group_roll_number, d.student_name, self.course))) def validate_and_set_child_table_fields(self): roll_numbers = [d.group_roll_number for d in self.students if d.group_roll_number] @@ -95,3 +96,25 @@ def get_program_enrollment(academic_year, academic_term=None, program=None, batc '''.format(condition1=condition1, condition2=condition2), ({"academic_year": academic_year, "academic_term":academic_term, "program": program, "batch": batch, "course": course}), as_dict=1) + +@frappe.whitelist() +def fetch_students(doctype, txt, searchfield, start, page_len, filters): + if filters.get("group_based_on") != "Activity": + enrolled_students = get_program_enrollment(filters.get('academic_year'), filters.get('academic_term'), + filters.get('program'), filters.get('batch')) + student_group_student = frappe.db.sql_list('''select student from `tabStudent Group Student` where parent=%s''', + (filters.get('student_group'))) + students = ([d.student for d in enrolled_students if d.student not in student_group_student] + if enrolled_students else [""]) or [""] + return frappe.db.sql("""select name, title from tabStudent + where name in ({0}) and `{1}` LIKE %s + order by idx desc, name + limit %s, %s""".format(", ".join(['%s']*len(students)), searchfield), + tuple(students + ["%%%s%%" % txt, start, page_len])) + else: + return frappe.db.sql("""select name, title from tabStudent + where `{0}` LIKE %s + order by idx desc, name + limit %s, %s""".format(searchfield), + tuple(["%%%s%%" % txt, start, page_len])) + diff --git a/erpnext/support/report/support_hours/__init__.py b/erpnext/support/report/support_hours/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/support/report/support_hours/support_hours.js b/erpnext/support/report/support_hours/support_hours.js new file mode 100644 index 0000000000..439b7678ee --- /dev/null +++ b/erpnext/support/report/support_hours/support_hours.js @@ -0,0 +1,39 @@ +// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt +/* eslint-disable */ + +frappe.query_reports["Support Hours"] = { + "filters": [ + { + 'lable': __("From Date"), + 'fieldname': 'from_date', + 'fieldtype': 'Date', + 'default': frappe.datetime.nowdate(), + 'reqd': 1 + }, + { + 'lable': __("To Date"), + 'fieldname': 'to_date', + 'fieldtype': 'Date', + 'default': frappe.datetime.nowdate(), + 'reqd': 1 + } + ], + get_chart_data: function(columns, result) { + return { + data: { + x: 'Date', + columns: [ + ['Date'].concat($.map(result, function(d) { return d.date; })), + [columns[3].label].concat($.map(result, function(d) { return d[columns[3].label]; })), + [columns[4].label].concat($.map(result, function(d) { return d[columns[4].label]; })), + [columns[5].label].concat($.map(result, function(d) { return d[columns[5].label]; })), + [columns[6].label].concat($.map(result, function(d) { return d[columns[6].label]; })), + [columns[7].label].concat($.map(result, function(d) { return d[columns[7].label]; })) + ] + }, + chart_type: 'bar', + + } + } +} diff --git a/erpnext/support/report/support_hours/support_hours.json b/erpnext/support/report/support_hours/support_hours.json new file mode 100644 index 0000000000..01e4bb44cb --- /dev/null +++ b/erpnext/support/report/support_hours/support_hours.json @@ -0,0 +1,27 @@ +{ + "add_total_row": 0, + "apply_user_permissions": 1, + "creation": "2017-06-23 14:21:37.558691", + "disabled": 0, + "docstatus": 0, + "doctype": "Report", + "idx": 0, + "is_standard": "Yes", + "letter_head": "", + "modified": "2017-06-23 16:33:31.211390", + "modified_by": "Administrator", + "module": "Support", + "name": "Support Hours", + "owner": "Administrator", + "ref_doctype": "Issue", + "report_name": "Support Hours", + "report_type": "Script Report", + "roles": [ + { + "role": "Support Team" + }, + { + "role": "System Manager" + } + ] +} \ No newline at end of file diff --git a/erpnext/support/report/support_hours/support_hours.py b/erpnext/support/report/support_hours/support_hours.py new file mode 100644 index 0000000000..f1606cd646 --- /dev/null +++ b/erpnext/support/report/support_hours/support_hours.py @@ -0,0 +1,73 @@ +# 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 _ +from frappe.utils import add_to_date, getdate, get_datetime + +time_slots = { + '12AM - 3AM': '00:00:00-03:00:00', + '3AM - 6AM': '03:00:00-06:00:00', + '6AM - 9AM': '06:00:00-09:00:00', + '9AM - 12PM': '09:00:00-12:00:00', + '12PM - 3PM': '12:00:00-15:00:00', + '3PM - 6PM': '15:00:00-18:00:00', + '6PM - 9PM': '18:00:00-21:00:00', + '9PM - 12AM': '21:00:00-23:00:00' +} + +def execute(filters=None): + columns, data = [], [] + if not filters.get('periodicity'): + filters['periodicity'] = 'Daily' + + columns = get_columns() + data = get_data(filters) + return columns, data + +def get_data(filters): + start_date = getdate(filters.from_date) + data = [] + while(start_date <= getdate(filters.to_date)): + hours_count = {'date': start_date} + for key, value in time_slots.items(): + start_time, end_time = value.split('-') + start_time = get_datetime("{0} {1}".format(start_date.strftime("%Y-%m-%d"), start_time)) + end_time = get_datetime("{0} {1}".format(start_date.strftime("%Y-%m-%d"), end_time)) + hours_count[key] = get_hours_count(start_time, end_time) + + if hours_count: + data.append(hours_count) + + start_date = add_to_date(start_date, days=1) + + return data + +def get_hours_count(start_time, end_time): + data = frappe.db.sql(""" select count(*) from `tabIssue` where creation + between %(start_time)s and %(end_time)s""", { + 'start_time': start_time, + 'end_time': end_time + }, as_list=1) or [] + + return data[0][0] if len(data) > 0 else 0 + +def get_columns(): + columns = [{ + "fieldname": "date", + "label": _("Date"), + "fieldtype": "Date", + "width": 100 + }] + + for label in ['12AM - 3AM', '3AM - 6AM', '6AM - 9AM', + '9AM - 12PM', '12PM - 3PM', '3PM - 6PM', '6PM - 9PM', '9PM - 12AM']: + columns.append({ + "fieldname": label, + "label": _(label), + "fieldtype": "Data", + "width": 120 + }) + + return columns \ No newline at end of file diff --git a/erpnext/templates/pages/regional/india/update_gstin.py b/erpnext/templates/pages/regional/india/update_gstin.py index 643aafe83c..8dcd48e5fc 100644 --- a/erpnext/templates/pages/regional/india/update_gstin.py +++ b/erpnext/templates/pages/regional/india/update_gstin.py @@ -33,7 +33,7 @@ def update_gstin(context): address_name = frappe.get_value('Address', key) if address_name: address = frappe.get_doc('Address', address_name) - address.gstin = value + address.gstin = value.upper() address.save(ignore_permissions=True) dirty = True