From e7b87ad071ddeb68cef5238271dd902e18dbf5fe Mon Sep 17 00:00:00 2001 From: mbauskar Date: Thu, 16 Feb 2017 13:12:29 +0530 Subject: [PATCH 1/6] [minor] timestamp fixes for heatmap --- erpnext/accounts/party.py | 15 ++++++++++++--- erpnext/stock/doctype/item/item.py | 11 +++++++++-- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/erpnext/accounts/party.py b/erpnext/accounts/party.py index c65a845deb..e8070554bb 100644 --- a/erpnext/accounts/party.py +++ b/erpnext/accounts/party.py @@ -7,7 +7,7 @@ import frappe import datetime from frappe import _, msgprint, scrub from frappe.defaults import get_user_permissions -from frappe.utils import add_days, getdate, formatdate, get_first_day, date_diff, add_years +from frappe.utils import add_days, getdate, formatdate, get_first_day, date_diff, add_years, get_timestamp from erpnext.utilities.doctype.address.address import get_address_display from erpnext.utilities.doctype.contact.contact import get_contact_details from erpnext.exceptions import PartyFrozen, InvalidCurrency, PartyDisabled, InvalidAccountCurrency @@ -351,8 +351,17 @@ def validate_party_frozen_disabled(party_type, party_name): def get_timeline_data(doctype, name): '''returns timeline data for the past one year''' from frappe.desk.form.load import get_communication_data + + out = {} data = get_communication_data(doctype, name, - fields = 'unix_timestamp(date(creation)), count(name)', + fields = 'date(creation), count(name)', after = add_years(None, -1).strftime('%Y-%m-%d'), group_by='group by date(creation)', as_dict=False) - return dict(data) \ No newline at end of file + + timeline_items = dict(data) + + for date, count in timeline_items.iteritems(): + timestamp = get_timestamp(date) + out.update({ timestamp: count }) + + return out \ No newline at end of file diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py index d20ba49763..f9938ab9cc 100644 --- a/erpnext/stock/doctype/item/item.py +++ b/erpnext/stock/doctype/item/item.py @@ -7,7 +7,7 @@ import erpnext import json import itertools from frappe import msgprint, _ -from frappe.utils import cstr, flt, cint, getdate, now_datetime, formatdate, strip +from frappe.utils import cstr, flt, cint, getdate, now_datetime, formatdate, strip, get_timestamp from frappe.website.website_generator import WebsiteGenerator from erpnext.setup.doctype.item_group.item_group import invalidate_cache_for, get_parent_item_groups from frappe.website.render import clear_cache @@ -667,10 +667,17 @@ class Item(WebsiteGenerator): def get_timeline_data(doctype, name): '''returns timeline data based on stock ledger entry''' - return dict(frappe.db.sql('''select unix_timestamp(posting_date), count(*) + out = {} + items = dict(frappe.db.sql('''select posting_date, count(*) from `tabStock Ledger Entry` where item_code=%s and posting_date > date_sub(curdate(), interval 1 year) group by posting_date''', name)) + + for date, count in items.iteritems(): + timestamp = get_timestamp(date) + out.update({ timestamp: count }) + + return out def validate_end_of_life(item_code, end_of_life=None, disabled=None, verbose=1): if (not end_of_life) or (disabled is None): From 4b9d2f27336caffab98966b333a268dee408dcba Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Thu, 16 Feb 2017 15:53:40 +0530 Subject: [PATCH 2/6] [Fix] Cleanup supplied items if supply raw material is set as No --- erpnext/controllers/buying_controller.py | 3 +++ erpnext/patches.txt | 3 ++- .../empty_supplied_items_for_non_subcontracted.py | 14 ++++++++++++++ 3 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 erpnext/patches/v7_2/empty_supplied_items_for_non_subcontracted.py diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py index c4ba9e7b1d..1d1b4e2198 100644 --- a/erpnext/controllers/buying_controller.py +++ b/erpnext/controllers/buying_controller.py @@ -178,6 +178,9 @@ class BuyingController(StockController): for item in self.get("items"): item.rm_supp_cost = 0.0 + if self.is_subcontracted == "No" and self.get("supplied_items"): + self.set('supplied_items', []) + def update_raw_materials_supplied(self, item, raw_material_table): bom_items = self.get_items_from_bom(item.item_code, item.bom) raw_materials_cost = 0 diff --git a/erpnext/patches.txt b/erpnext/patches.txt index b997dfc13b..6563dfb3ee 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -363,4 +363,5 @@ erpnext.patches.v7_2.update_website_for_variant erpnext.patches.v7_2.update_doctype_status erpnext.patches.v7_2.update_salary_slips erpnext.patches.v7_2.set_null_value_to_fields -erpnext.patches.v7_2.update_abbr_in_salary_slips \ No newline at end of file +erpnext.patches.v7_2.update_abbr_in_salary_slips +erpnext.patches.v7_2.empty_supplied_items_for_non_subcontracted \ No newline at end of file diff --git a/erpnext/patches/v7_2/empty_supplied_items_for_non_subcontracted.py b/erpnext/patches/v7_2/empty_supplied_items_for_non_subcontracted.py new file mode 100644 index 0000000000..ec6f8afc3a --- /dev/null +++ b/erpnext/patches/v7_2/empty_supplied_items_for_non_subcontracted.py @@ -0,0 +1,14 @@ +# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors +# License: GNU General Public License v3. See license.txt + +from __future__ import unicode_literals +import frappe + +def execute(): + for doctype in ["Purchase Order", "Purchase Invoice", "Purchase Receipt"]: + child_table = 'Purchase Receipt Item Supplied' if doctype != 'Purchase Order' else 'Purchase Order Item Supplied' + for data in frappe.db.sql(""" select distinct `tab{doctype}`.name from `tab{doctype}` , `tab{child_table}` + where `tab{doctype}`.name = `tab{child_table}`.parent and `tab{doctype}`.docstatus != 2 + and `tab{doctype}`.is_subcontracted = 'No' """.format(doctype = doctype, child_table = child_table), as_dict=1): + frappe.db.sql(""" delete from `tab{child_table}` + where parent = %s and parenttype = %s""".format(child_table= child_table), (data.name, doctype)) \ No newline at end of file From 9e5b3dad296bf3c598f87f65b5307dcee1c015e9 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Fri, 17 Feb 2017 11:03:30 +0530 Subject: [PATCH 3/6] Minor fix in assesment --- erpnext/schools/doctype/assessment/assessment.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/schools/doctype/assessment/assessment.py b/erpnext/schools/doctype/assessment/assessment.py index 003b4276e7..50883364cd 100644 --- a/erpnext/schools/doctype/assessment/assessment.py +++ b/erpnext/schools/doctype/assessment/assessment.py @@ -34,7 +34,7 @@ class Assessment(Document): validate_overlap_for(self, "Assessment", "student_group") validate_overlap_for(self, "Assessment", "room") - validate_overlap_for(self, "Assessment", "supervisor", self.instructor) + validate_overlap_for(self, "Assessment", "supervisor", self.supervisor) def get_assessment_list(doctype, txt, filters, limit_start, limit_page_length=20): From 6af7dd4e1b98118c876decc42fb4d414b7117805 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Fri, 17 Feb 2017 14:47:25 +0530 Subject: [PATCH 4/6] Set fiscal year start and end date based on country --- erpnext/public/js/setup_wizard.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/erpnext/public/js/setup_wizard.js b/erpnext/public/js/setup_wizard.js index 30323ecd6b..c2a15950d8 100644 --- a/erpnext/public/js/setup_wizard.js +++ b/erpnext/public/js/setup_wizard.js @@ -100,7 +100,12 @@ function load_erpnext_slides() { fy = ["01-01", "12-31"]; next_year = current_year; } - + + var year_start_date = current_year + "-" + fy[0]; + if(year_start_date > get_today()) { + next_year = current_year + current_year -= 1; + } slide.get_field("fy_start_date").set_input(current_year + "-" + fy[0]); slide.get_field("fy_end_date").set_input(next_year + "-" + fy[1]); } From 0c5375d0fa6f1ce8e37649e3d2010b01d18522d5 Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Fri, 17 Feb 2017 14:57:31 +0530 Subject: [PATCH 5/6] [minor] item name not mandatory and item price with quick edit --- erpnext/stock/doctype/item/item.js | 53 ++++--- erpnext/stock/doctype/item/item.json | 8 +- erpnext/stock/doctype/item/item.py | 9 +- .../stock/doctype/item_price/item_price.json | 142 +++++++----------- 4 files changed, 99 insertions(+), 113 deletions(-) diff --git a/erpnext/stock/doctype/item/item.js b/erpnext/stock/doctype/item/item.js index 1f793d11e8..985bd4f950 100644 --- a/erpnext/stock/doctype/item/item.js +++ b/erpnext/stock/doctype/item/item.js @@ -4,6 +4,13 @@ frappe.provide("erpnext.item"); frappe.ui.form.on("Item", { + setup: function(frm) { + frm.add_fetch('attribute', 'numeric_values', 'numeric_values'); + frm.add_fetch('attribute', 'from_range', 'from_range'); + frm.add_fetch('attribute', 'to_range', 'to_range'); + frm.add_fetch('attribute', 'increment', 'increment'); + frm.add_fetch('tax_type', 'tax_rate', 'tax_rate'); + }, onload: function(frm) { erpnext.item.setup_queries(frm); if (frm.doc.variant_of){ @@ -16,7 +23,6 @@ frappe.ui.form.on("Item", { }, refresh: function(frm) { - if(frm.doc.is_stock_item) { frm.add_custom_button(__("Balance"), function() { frappe.route_options = { @@ -54,9 +60,9 @@ frappe.ui.form.on("Item", { }, __("View")); frm.add_custom_button(__("Variant"), function() { - erpnext.item.make_variant() + erpnext.item.make_variant(frm); }, __("Make")); - cur_frm.page.set_inner_btn_group_as_primary(__("Make")); + frm.page.set_inner_btn_group_as_primary(__("Make")); } if (frm.doc.variant_of) { frm.set_intro(__("This Item is a Variant of {0} (Template). Attributes will be copied over from the template unless 'No Copy' is set", [frm.doc.variant_of]), true); @@ -79,6 +85,17 @@ frappe.ui.form.on("Item", { frm.toggle_enable("is_fixed_asset", (frm.doc.__islocal || (!frm.doc.is_stock_item && ((frm.doc.__onload && frm.doc.__onload.asset_exists) ? false : true)))); + + frm.add_custom_button(__('Duplicate'), function() { + var new_item = frappe.model.copy_doc(frm.doc); + if(new_item.item_name===new_item.item_code) { + new_item.item_name = null; + } + if(new_item.description===new_item.description) { + new_item.description = null; + } + frappe.set_route('Form', 'Item', new_item.name); + }); }, validate: function(frm){ @@ -88,13 +105,13 @@ frappe.ui.form.on("Item", { image: function(frm) { refresh_field("image_view"); }, - + is_fixed_asset: function(frm) { if (frm.doc.is_fixed_asset) { frm.set_value("is_stock_item", 0); } }, - + page_name: frappe.utils.warn_page_name_change, item_code: function(frm) { @@ -191,15 +208,15 @@ $.extend(erpnext.item, { frm.fields_dict.reorder_levels.grid.get_field("warehouse").get_query = function(doc, cdt, cdn) { var d = locals[cdt][cdn]; - + var filters = { "is_group": 0 } - + if (d.parent_warehouse) { filters.extend({"parent_warehouse": d.warehouse_group}) } - + return { filters: filters } @@ -212,7 +229,8 @@ $.extend(erpnext.item, { return; frappe.require('assets/js/item-dashboard.min.js', function() { - var section = frm.dashboard.add_section('
Stock Levels
'); + var section = frm.dashboard.add_section('
\ + Stock Levels
'); erpnext.item.item_dashboard = new erpnext.stock.ItemDashboard({ parent: section, item_code: frm.doc.name @@ -234,12 +252,12 @@ $.extend(erpnext.item, { } }, - make_variant: function(doc) { + make_variant: function(frm) { var fields = [] - for(var i=0;i< cur_frm.doc.attributes.length;i++){ + for(var i=0;i< frm.doc.attributes.length;i++){ var fieldtype, desc; - var row = cur_frm.doc.attributes[i]; + var row = frm.doc.attributes[i]; if (row.numeric_values){ fieldtype = "Float"; desc = "Min Value: "+ row.from_range +" , Max Value: "+ row.to_range +", in Increments of: "+ row.increment @@ -268,7 +286,7 @@ $.extend(erpnext.item, { frappe.call({ method:"erpnext.controllers.item_variant.get_variant", args: { - "template": cur_frm.doc.name, + "template": frm.doc.name, "args": d.get_values() }, callback: function(r) { @@ -290,7 +308,7 @@ $.extend(erpnext.item, { frappe.call({ method:"erpnext.controllers.item_variant.create_variant", args: { - "item": cur_frm.doc.name, + "item": frm.doc.name, "args": d.get_values() }, callback: function(r) { @@ -358,10 +376,3 @@ $.extend(erpnext.item, { frm.fields_dict.attributes.grid.toggle_enable("attribute_value", !frm.doc.variant_of); } }); - - -cur_frm.add_fetch('attribute', 'numeric_values', 'numeric_values'); -cur_frm.add_fetch('attribute', 'from_range', 'from_range'); -cur_frm.add_fetch('attribute', 'to_range', 'to_range'); -cur_frm.add_fetch('attribute', 'increment', 'increment'); -cur_frm.add_fetch('tax_type', 'tax_rate', 'tax_rate'); diff --git a/erpnext/stock/doctype/item/item.json b/erpnext/stock/doctype/item/item.json index 6dfe76e379..60f6fdf371 100644 --- a/erpnext/stock/doctype/item/item.json +++ b/erpnext/stock/doctype/item/item.json @@ -87,7 +87,7 @@ "in_standard_filter": 0, "label": "Item Code", "length": 0, - "no_copy": 1, + "no_copy": 0, "oldfieldname": "item_code", "oldfieldtype": "Data", "permlevel": 0, @@ -134,7 +134,7 @@ }, { "allow_on_submit": 0, - "bold": 0, + "bold": 1, "collapsible": 0, "columns": 0, "fieldname": "item_name", @@ -156,7 +156,7 @@ "read_only": 0, "remember_last_selected_value": 0, "report_hide": 0, - "reqd": 1, + "reqd": 0, "search_index": 1, "set_only_once": 0, "unique": 0 @@ -2713,7 +2713,7 @@ "issingle": 0, "istable": 0, "max_attachments": 1, - "modified": "2017-01-18 17:43:20.262925", + "modified": "2017-02-17 04:00:38.825621", "modified_by": "Administrator", "module": "Stock", "name": "Item", diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py index d20ba49763..f54744be72 100644 --- a/erpnext/stock/doctype/item/item.py +++ b/erpnext/stock/doctype/item/item.py @@ -63,6 +63,9 @@ class Item(WebsiteGenerator): def validate(self): super(Item, self).validate() + if not self.item_name: + self.item_name = self.item_code + if not self.description: self.description = self.item_name @@ -470,12 +473,12 @@ class Item(WebsiteGenerator): def check_if_linked_document_exists(self, key): linked_doctypes = ["Delivery Note Item", "Sales Invoice Item", "Purchase Receipt Item", "Purchase Invoice Item", "Stock Entry Detail", "Stock Reconciliation Item"] - - # For "Is Stock Item", following doctypes is important + + # For "Is Stock Item", following doctypes is important # because reserved_qty, ordered_qty and requested_qty updated from these doctypes if key == "is_stock_item": linked_doctypes += ["Sales Order Item", "Purchase Order Item", "Material Request Item"] - + for doctype in linked_doctypes: if frappe.db.get_value(doctype, filters={"item_code": self.name, "docstatus": 1}) or \ frappe.db.get_value("Production Order", diff --git a/erpnext/stock/doctype/item_price/item_price.json b/erpnext/stock/doctype/item_price/item_price.json index 5f0826248d..0685c80438 100644 --- a/erpnext/stock/doctype/item_price/item_price.json +++ b/erpnext/stock/doctype/item_price/item_price.json @@ -69,6 +69,33 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "column_break_3", + "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, + "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_on_submit": 0, "bold": 0, @@ -151,6 +178,34 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_on_submit": 0, + "bold": 1, + "collapsible": 0, + "columns": 0, + "fieldname": "currency", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 1, + "in_standard_filter": 0, + "label": "Currency", + "length": 0, + "no_copy": 0, + "options": "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, + "unique": 0 + }, { "allow_on_submit": 0, "bold": 0, @@ -211,34 +266,6 @@ "set_only_once": 0, "unique": 0 }, - { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "currency", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Currency", - "length": 0, - "no_copy": 0, - "options": "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, - "unique": 0 - }, { "allow_on_submit": 0, "bold": 0, @@ -318,61 +345,6 @@ "search_index": 0, "set_only_once": 0, "unique": 0 - }, - { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "section_break_12", - "fieldtype": "Section 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, - "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_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "bulk_import_help", - "fieldtype": "HTML", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Bulk Import Help", - "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 } ], "hide_heading": 0, @@ -386,7 +358,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2016-12-15 14:52:09.842544", + "modified": "2017-02-17 04:24:30.453863", "modified_by": "Administrator", "module": "Stock", "name": "Item Price", @@ -435,7 +407,7 @@ "write": 1 } ], - "quick_entry": 0, + "quick_entry": 1, "read_only": 0, "read_only_onload": 0, "sort_order": "ASC", From 66b373033a632e7325f382cf015f7b6793ff0464 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Mon, 20 Feb 2017 15:22:01 +0600 Subject: [PATCH 6/6] bumped to version 7.2.22 --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index 4f53d0daba..e9be38a791 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -2,7 +2,7 @@ from __future__ import unicode_literals import frappe -__version__ = '7.2.21' +__version__ = '7.2.22' def get_default_company(user=None): '''Get default company for user'''