Merge branch 'hotfix'
diff --git a/erpnext/__init__.py b/erpnext/__init__.py
index 4940522..75e7361 100644
--- a/erpnext/__init__.py
+++ b/erpnext/__init__.py
@@ -5,7 +5,7 @@
from erpnext.hooks import regional_overrides
from frappe.utils import getdate
-__version__ = '10.1.40'
+__version__ = '10.1.41'
def get_default_company(user=None):
'''Get default company for user'''
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.js b/erpnext/accounts/doctype/payment_entry/payment_entry.js
index c353e5e..940a709 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.js
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.js
@@ -819,28 +819,30 @@
reference_name: function(frm, cdt, cdn) {
var row = locals[cdt][cdn];
- return frappe.call({
- method: "erpnext.accounts.doctype.payment_entry.payment_entry.get_reference_details",
- args: {
- reference_doctype: row.reference_doctype,
- reference_name: row.reference_name,
- party_account_currency: frm.doc.payment_type=="Receive" ?
- frm.doc.paid_from_account_currency : frm.doc.paid_to_account_currency
- },
- callback: function(r, rt) {
- if(r.message) {
- $.each(r.message, function(field, value) {
- frappe.model.set_value(cdt, cdn, field, value);
- })
+ if (row.reference_name && row.reference_doctype) {
+ return frappe.call({
+ method: "erpnext.accounts.doctype.payment_entry.payment_entry.get_reference_details",
+ args: {
+ reference_doctype: row.reference_doctype,
+ reference_name: row.reference_name,
+ party_account_currency: frm.doc.payment_type=="Receive" ?
+ frm.doc.paid_from_account_currency : frm.doc.paid_to_account_currency
+ },
+ callback: function(r, rt) {
+ if(r.message) {
+ $.each(r.message, function(field, value) {
+ frappe.model.set_value(cdt, cdn, field, value);
+ })
- let allocated_amount = frm.doc.unallocated_amount > row.outstanding_amount ?
- row.outstanding_amount : frm.doc.unallocated_amount;
+ let allocated_amount = frm.doc.unallocated_amount > row.outstanding_amount ?
+ row.outstanding_amount : frm.doc.unallocated_amount;
- frappe.model.set_value(cdt, cdn, 'allocated_amount', allocated_amount);
- frm.refresh_fields();
+ frappe.model.set_value(cdt, cdn, 'allocated_amount', allocated_amount);
+ frm.refresh_fields();
+ }
}
- }
- })
+ })
+ }
},
allocated_amount: function(frm) {
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
index b940a6a..a73d607 100755
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
@@ -1239,7 +1239,7 @@
"unique": 0
},
{
- "allow_bulk_edit": 0,
+ "allow_bulk_edit": 1,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -3973,7 +3973,7 @@
"istable": 0,
"max_attachments": 0,
"menu_index": 0,
- "modified": "2018-05-28 02:38:40.310899",
+ "modified": "2018-07-06 02:38:40.310899",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Invoice",
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
index a033bb0..75792f8 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
@@ -1459,7 +1459,7 @@
"unique": 0
},
{
- "allow_bulk_edit": 0,
+ "allow_bulk_edit": 1,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -4713,7 +4713,7 @@
"istable": 0,
"max_attachments": 0,
"menu_index": 0,
- "modified": "2018-05-28 04:47:29.879475",
+ "modified": "2018-07-06 12:09:02.039783",
"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 b174d9b..56767c2 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -318,6 +318,7 @@
if not for_validate and not self.customer:
self.customer = pos.customer
+ self.ignore_pricing_rule = pos.ignore_pricing_rule
if pos.get('account_for_change_amount'):
self.account_for_change_amount = pos.get('account_for_change_amount')
diff --git a/erpnext/accounts/report/budget_variance_report/budget_variance_report.js b/erpnext/accounts/report/budget_variance_report/budget_variance_report.js
index 1315b25..cf8d549 100644
--- a/erpnext/accounts/report/budget_variance_report/budget_variance_report.js
+++ b/erpnext/accounts/report/budget_variance_report/budget_variance_report.js
@@ -39,6 +39,12 @@
options: ["Cost Center", "Project"],
default: "Cost Center",
reqd: 1
- }
+ },
+ {
+ fieldname: "cost_center",
+ label: __("Cost Center"),
+ fieldtype: "Link",
+ options: "Cost Center"
+ },
]
}
diff --git a/erpnext/accounts/report/budget_variance_report/budget_variance_report.py b/erpnext/accounts/report/budget_variance_report/budget_variance_report.py
index bc457aa..c9f913a 100644
--- a/erpnext/accounts/report/budget_variance_report/budget_variance_report.py
+++ b/erpnext/accounts/report/budget_variance_report/budget_variance_report.py
@@ -10,9 +10,13 @@
def execute(filters=None):
if not filters: filters = {}
-
+ validate_filters(filters)
columns = get_columns(filters)
- cost_centers = get_cost_centers(filters)
+ if filters.get("cost_center"):
+ cost_centers = [filters.get("cost_center")]
+ else:
+ cost_centers = get_cost_centers(filters)
+
period_month_ranges = get_period_month_ranges(filters["period"], filters["fiscal_year"])
cam_map = get_cost_center_account_month_map(filters)
@@ -39,6 +43,10 @@
return columns, data
+def validate_filters(filters):
+ if filters.get("budget_against")=="Project" and filters.get("cost_center"):
+ frappe.throw(_("Filter based on Cost Center is only applicable if Budget Against is selected as Cost Center"))
+
def get_columns(filters):
columns = [_(filters.get("budget_against")) + ":Link/%s:120"%(filters.get("budget_against")), _("Account") + ":Link/Account:120"]
@@ -66,12 +74,16 @@
#Get cost center & target details
def get_cost_center_target_details(filters):
+ cond = ""
+ if filters.get("cost_center"):
+ cond += " and b.cost_center='%s'" % frappe.db.escape(filters.get("cost_center"))
+
return frappe.db.sql("""
select b.{budget_against} as budget_against, b.monthly_distribution, ba.account, ba.budget_amount
from `tabBudget` b, `tabBudget Account` ba
where b.name=ba.parent and b.docstatus = 1 and b.fiscal_year=%s
- and b.budget_against = %s and b.company=%s
- """.format(budget_against=filters.get("budget_against").replace(" ", "_").lower()),
+ and b.budget_against = %s and b.company=%s {cond}
+ """.format(budget_against=filters.get("budget_against").replace(" ", "_").lower(), cond=cond),
(filters.fiscal_year, filters.budget_against, filters.company), as_dict=True)
#Get target distribution details of accounts of cost center
diff --git a/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py b/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py
index ac9f4ce..e6216b5 100644
--- a/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py
+++ b/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py
@@ -53,7 +53,7 @@
delivery_note, d.income_account, d.cost_center, d.stock_qty, d.stock_uom
]
- row += [d.base_net_rate/d.stock_qty, d.base_net_amount] \
+ row += [(d.base_net_rate * d.qty)/d.stock_qty, d.base_net_amount] \
if d.stock_uom != d.uom else [d.base_net_rate, d.base_net_amount]
total_tax = 0
@@ -133,7 +133,7 @@
`tabSales Invoice Item`.stock_uom, `tabSales Invoice Item`.base_net_rate,
`tabSales Invoice Item`.base_net_amount, `tabSales Invoice`.customer_name,
`tabSales Invoice`.customer_group, `tabSales Invoice Item`.so_detail,
- `tabSales Invoice`.update_stock, `tabSales Invoice Item`.uom {0}
+ `tabSales Invoice`.update_stock, `tabSales Invoice Item`.uom, `tabSales Invoice Item`.qty {0}
from `tabSales Invoice`, `tabSales Invoice Item`
where `tabSales Invoice`.name = `tabSales Invoice Item`.parent
and `tabSales Invoice`.docstatus = 1 %s %s
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.json b/erpnext/buying/doctype/purchase_order/purchase_order.json
index 95aca6b..baf3b23 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.json
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.json
@@ -1207,7 +1207,7 @@
"unique": 0
},
{
- "allow_bulk_edit": 0,
+ "allow_bulk_edit": 1,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -3355,7 +3355,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
- "modified": "2018-02-17 11:00:05.037716",
+ "modified": "2018-07-06 11:00:05.037716",
"modified_by": "Administrator",
"module": "Buying",
"name": "Purchase Order",
diff --git a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json
index ad47d52..bee6553 100644
--- a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json
+++ b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json
@@ -781,7 +781,7 @@
"unique": 0
},
{
- "allow_bulk_edit": 0,
+ "allow_bulk_edit": 1,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -2549,7 +2549,7 @@
"istable": 0,
"max_attachments": 0,
"menu_index": 0,
- "modified": "2018-05-28 02:45:48.616334",
+ "modified": "2018-07-06 02:45:48.616334",
"modified_by": "Administrator",
"module": "Buying",
"name": "Supplier Quotation",
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index 58073bc..22ddf1f 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -131,6 +131,8 @@
self.meta.get_label(date_field), self)
def validate_due_date(self):
+ if self.get('is_pos'): return
+
from erpnext.accounts.party import validate_due_date
if self.doctype == "Sales Invoice":
if not self.due_date:
diff --git a/erpnext/controllers/item_variant.py b/erpnext/controllers/item_variant.py
index bf8c88c..5e7ddbb 100644
--- a/erpnext/controllers/item_variant.py
+++ b/erpnext/controllers/item_variant.py
@@ -176,6 +176,14 @@
@frappe.whitelist()
def enqueue_multiple_variant_creation(item, args):
# There can be innumerable attribute combinations, enqueue
+ if isinstance(args, basestring):
+ variants = json.loads(args)
+ total_variants = 1
+ for key in variants:
+ total_variants *= len(variants[key])
+ if total_variants >= 600:
+ frappe.msgprint("Please do not create more than 500 items at a time", raise_exception=1)
+ return
frappe.enqueue("erpnext.controllers.item_variant.create_multiple_variants",
item=item, args=args, now=frappe.flags.in_test);
diff --git a/erpnext/hr/doctype/appraisal/appraisal.js b/erpnext/hr/doctype/appraisal/appraisal.js
index 64d6f40..30317d9 100644
--- a/erpnext/hr/doctype/appraisal/appraisal.js
+++ b/erpnext/hr/doctype/appraisal/appraisal.js
@@ -24,6 +24,7 @@
}
cur_frm.cscript.kra_template = function(doc, dt, dn) {
+ doc.goals = [];
erpnext.utils.map_current_doc({
method: "erpnext.hr.doctype.appraisal.appraisal.fetch_appraisal_template",
source_name: cur_frm.doc.kra_template,
diff --git a/erpnext/hr/doctype/leave_application/leave_application.py b/erpnext/hr/doctype/leave_application/leave_application.py
index 8d6db5c..dd7d19b 100755
--- a/erpnext/hr/doctype/leave_application/leave_application.py
+++ b/erpnext/hr/doctype/leave_application/leave_application.py
@@ -355,7 +355,7 @@
@frappe.whitelist()
def get_number_of_leave_days(employee, leave_type, from_date, to_date, half_day = None, half_day_date = None):
number_of_days = 0
- if half_day == 1:
+ if cint(half_day) == 1:
if from_date == to_date:
number_of_days = 0.5
else:
diff --git a/erpnext/manufacturing/doctype/bom_update_tool/bom_update_tool.js b/erpnext/manufacturing/doctype/bom_update_tool/bom_update_tool.js
index a4b48af..e4b8a20 100644
--- a/erpnext/manufacturing/doctype/bom_update_tool/bom_update_tool.js
+++ b/erpnext/manufacturing/doctype/bom_update_tool/bom_update_tool.js
@@ -22,6 +22,21 @@
frm.disable_save();
},
+ replace: function(frm) {
+ if (frm.doc.current_bom && frm.doc.new_bom) {
+ frappe.call({
+ method: "erpnext.manufacturing.doctype.bom_update_tool.bom_update_tool.enqueue_replace_bom",
+ freeze: true,
+ args: {
+ args: {
+ "current_bom": frm.doc.current_bom,
+ "new_bom": frm.doc.new_bom
+ }
+ }
+ });
+ }
+ },
+
update_latest_price_in_all_boms: function() {
frappe.call({
method: "erpnext.manufacturing.doctype.bom_update_tool.bom_update_tool.enqueue_update_cost",
diff --git a/erpnext/manufacturing/doctype/bom_update_tool/bom_update_tool.json b/erpnext/manufacturing/doctype/bom_update_tool/bom_update_tool.json
index ab63c0b..b348bb7 100644
--- a/erpnext/manufacturing/doctype/bom_update_tool/bom_update_tool.json
+++ b/erpnext/manufacturing/doctype/bom_update_tool/bom_update_tool.json
@@ -123,7 +123,7 @@
"label": "Replace",
"length": 0,
"no_copy": 0,
- "options": "replace_bom",
+ "options": "",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
@@ -208,7 +208,7 @@
"issingle": 1,
"istable": 0,
"max_attachments": 0,
- "modified": "2017-07-31 18:08:05.919276",
+ "modified": "2018-07-02 16:17:09.014102",
"modified_by": "Administrator",
"module": "Manufacturing",
"name": "BOM Update Tool",
diff --git a/erpnext/manufacturing/doctype/bom_update_tool/bom_update_tool.py b/erpnext/manufacturing/doctype/bom_update_tool/bom_update_tool.py
index ec948eb..04f9717 100644
--- a/erpnext/manufacturing/doctype/bom_update_tool/bom_update_tool.py
+++ b/erpnext/manufacturing/doctype/bom_update_tool/bom_update_tool.py
@@ -3,9 +3,10 @@
# For license information, please see license.txt
from __future__ import unicode_literals
-import frappe
+import frappe, json
from frappe.utils import cstr, flt
from frappe import _
+from six import string_types
from erpnext.manufacturing.doctype.bom.bom import get_boms_in_bottom_up_order
from frappe.model.document import Document
@@ -17,12 +18,14 @@
updated_bom = []
for bom in bom_list:
bom_obj = frappe.get_doc("BOM", bom)
+ bom_obj.get_doc_before_save()
updated_bom = bom_obj.update_cost_and_exploded_items(updated_bom)
bom_obj.calculate_cost()
bom_obj.update_parent_cost()
bom_obj.db_update()
-
- frappe.msgprint(_("BOM replaced"))
+ if (getattr(bom_obj.meta, 'track_changes', False)
+ and bom_obj._doc_before_save and not bom_obj.flags.ignore_version):
+ bom_obj.save_version()
def validate_bom(self):
if cstr(self.current_bom) == cstr(self.new_bom):
@@ -55,6 +58,14 @@
return bom_list
@frappe.whitelist()
+def enqueue_replace_bom(args):
+ if isinstance(args, string_types):
+ args = json.loads(args)
+
+ frappe.enqueue("erpnext.manufacturing.doctype.bom_update_tool.bom_update_tool.replace_bom", args=args)
+ frappe.msgprint(_("Queued for replacing the BOM. It may take a few minutes."))
+
+@frappe.whitelist()
def enqueue_update_cost():
frappe.enqueue("erpnext.manufacturing.doctype.bom_update_tool.bom_update_tool.update_cost")
frappe.msgprint(_("Queued for updating latest price in all Bill of Materials. It may take a few minutes."))
@@ -63,6 +74,14 @@
if frappe.db.get_single_value("Manufacturing Settings", "update_bom_costs_automatically"):
update_cost()
+def replace_bom(args):
+ args = frappe._dict(args)
+
+ doc = frappe.get_doc("BOM Update Tool")
+ doc.current_bom = args.current_bom
+ doc.new_bom = args.new_bom
+ doc.replace_bom()
+
def update_cost():
bom_list = get_boms_in_bottom_up_order()
for bom in bom_list:
diff --git a/erpnext/non_profit/doctype/membership/membership.json b/erpnext/non_profit/doctype/membership/membership.json
index 42e084d..694a4fa 100644
--- a/erpnext/non_profit/doctype/membership/membership.json
+++ b/erpnext/non_profit/doctype/membership/membership.json
@@ -15,6 +15,7 @@
"fields": [
{
"allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -42,10 +43,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
+ "translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -73,10 +76,12 @@
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
+ "translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -102,10 +107,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
+ "translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -133,15 +140,17 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
+ "translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
- "fieldname": "membership_validaty_section",
+ "fieldname": "membership_validity_section",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
@@ -150,7 +159,7 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
- "label": "membership validaty section",
+ "label": "Validity",
"length": 0,
"no_copy": 0,
"permlevel": 0,
@@ -163,10 +172,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
+ "translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -193,10 +204,12 @@
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
+ "translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -223,10 +236,12 @@
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
+ "translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -252,10 +267,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
+ "translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -282,10 +299,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
+ "translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -312,10 +331,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
+ "translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -342,10 +363,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
+ "translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -373,10 +396,12 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
+ "translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -403,6 +428,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
+ "translatable": 0,
"unique": 0
}
],
@@ -416,7 +442,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
- "modified": "2017-12-05 07:02:56.859408",
+ "modified": "2018-06-26 19:23:17.911121",
"modified_by": "Administrator",
"module": "Non Profit",
"name": "Membership",
@@ -425,7 +451,6 @@
"permissions": [
{
"amend": 0,
- "apply_user_permissions": 0,
"cancel": 0,
"create": 1,
"delete": 1,
@@ -445,7 +470,6 @@
},
{
"amend": 0,
- "apply_user_permissions": 0,
"cancel": 0,
"create": 1,
"delete": 1,
@@ -472,5 +496,6 @@
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1,
- "track_seen": 0
-}
\ No newline at end of file
+ "track_seen": 0,
+ "track_views": 0
+}
diff --git a/erpnext/projects/doctype/project/project.py b/erpnext/projects/doctype/project/project.py
index 44b0c00..1f4bd00 100644
--- a/erpnext/projects/doctype/project/project.py
+++ b/erpnext/projects/doctype/project/project.py
@@ -4,7 +4,7 @@
from __future__ import unicode_literals
import frappe
-from frappe.utils import flt, getdate, get_url
+from frappe.utils import flt, getdate, get_url, now
from frappe import _
from frappe.model.document import Document
@@ -60,6 +60,7 @@
self.validate_weights()
self.sync_tasks()
self.tasks = []
+ self.load_tasks()
self.send_welcome_email()
def validate_project_name(self):
@@ -83,36 +84,68 @@
"""sync tasks and remove table"""
if self.flags.dont_sync_tasks: return
task_names = []
+
+ existing_task_data = {}
+ for d in frappe.get_all('Project Task',
+ fields = ["title", "status", "start_date", "end_date", "description", "task_weight", "task_id"],
+ filters = {'parent': self.name}):
+ existing_task_data.setdefault(d.task_id, d)
+
for t in self.tasks:
if t.task_id:
task = frappe.get_doc("Task", t.task_id)
else:
task = frappe.new_doc("Task")
task.project = self.name
- task.update({
- "subject": t.title,
- "status": t.status,
- "exp_start_date": t.start_date,
- "exp_end_date": t.end_date,
- "description": t.description,
- "task_weight": t.task_weight
- })
- self.map_custom_fields(t, task)
+ if not t.task_id or self.is_row_updated(t, existing_task_data):
+ task.update({
+ "subject": t.title,
+ "status": t.status,
+ "exp_start_date": t.start_date,
+ "exp_end_date": t.end_date,
+ "description": t.description,
+ "task_weight": t.task_weight
+ })
- task.flags.ignore_links = True
- task.flags.from_project = True
- task.flags.ignore_feed = True
- task.save(ignore_permissions = True)
- task_names.append(task.name)
+ self.map_custom_fields(t, task)
+
+ task.flags.ignore_links = True
+ task.flags.from_project = True
+ task.flags.ignore_feed = True
+
+ if t.task_id:
+ task.update({
+ "modified_by": frappe.session.user,
+ "modified": now()
+ })
+
+ task.validate()
+ task.db_update()
+ else:
+ task.save(ignore_permissions = True)
+ task_names.append(task.name)
+ else:
+ task_names.append(task.name)
# delete
for t in frappe.get_all("Task", ["name"], {"project": self.name, "name": ("not in", task_names)}):
frappe.delete_doc("Task", t.name)
+ def update_costing_and_percentage_complete(self):
self.update_percent_complete()
self.update_costing()
+ def is_row_updated(self, row, existing_task_data):
+ if self.get("__islocal") or not existing_task_data: return True
+
+ d = existing_task_data.get(row.task_id)
+
+ if (d and (row.title != d.title or row.status != d.status
+ or getdate(row.start_date) != getdate(d.start_date) or getdate(row.end_date) != getdate(d.end_date)
+ or row.description != d.description or row.task_weight != d.task_weight)):
+ return True
+
def map_custom_fields(self, source, target):
project_task_custom_fields = frappe.get_all("Custom Field", {"dt": "Project Task"}, "fieldname")
@@ -207,6 +240,9 @@
self.total_billed_amount = total_billed_amount and total_billed_amount[0][0] or 0
+ def after_rename(self, old_name, new_name, merge=False):
+ if old_name == self.copied_from:
+ frappe.db.set_value('Project', new_name, 'copied_from', new_name)
def send_welcome_email(self):
url = get_url("/project/?name={0}".format(self.name))
@@ -227,8 +263,7 @@
user.welcome_email_sent=1
def on_update(self):
- self.load_tasks()
- self.sync_tasks()
+ self.update_costing_and_percentage_complete()
self.update_dependencies_on_duplicated_project()
def update_dependencies_on_duplicated_project(self):
@@ -251,9 +286,7 @@
continue
name = _task.name
- depends_on_tasks = _task.depends_on_tasks
- depends_on_tasks = [x for x in depends_on_tasks.split(',') if x]
dependency_map[task.title] = [ x['subject'] for x in frappe.get_list(
'Task Depends On', {"parent": name}, ['subject'])]
@@ -264,7 +297,8 @@
for dt in value:
dt_name = frappe.db.get_value('Task', {"subject": dt, "project": self.name })
task_doc.append('depends_on', {"task": dt_name})
- task_doc.save()
+
+ task_doc.update_db()
def get_timeline_data(doctype, name):
'''Return timeline for attendance'''
diff --git a/erpnext/projects/doctype/project_task/project_task.json b/erpnext/projects/doctype/project_task/project_task.json
index 79790e5..d215d63 100644
--- a/erpnext/projects/doctype/project_task/project_task.json
+++ b/erpnext/projects/doctype/project_task/project_task.json
@@ -61,7 +61,7 @@
"label": "Status",
"length": 0,
"no_copy": 1,
- "options": "Open\nWorking\nPending Review\nClosed\nCancelled",
+ "options": "Open\nWorking\nPending Review\nOverdue\nClosed\nCancelled",
"permlevel": 0,
"precision": "",
"print_hide": 0,
@@ -371,7 +371,7 @@
"remember_last_selected_value": 1,
"report_hide": 0,
"reqd": 0,
- "search_index": 0,
+ "search_index": 1,
"set_only_once": 0,
"unique": 0
}
@@ -386,7 +386,7 @@
"issingle": 0,
"istable": 1,
"max_attachments": 0,
- "modified": "2017-12-19 14:49:15.886339",
+ "modified": "2018-07-05 19:34:31.204454",
"modified_by": "Administrator",
"module": "Projects",
"name": "Project Task",
diff --git a/erpnext/projects/doctype/task/task.json b/erpnext/projects/doctype/task/task.json
index 8e72d03..cf524da 100644
--- a/erpnext/projects/doctype/task/task.json
+++ b/erpnext/projects/doctype/task/task.json
@@ -38,7 +38,7 @@
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
- "search_index": 0,
+ "search_index": 1,
"set_only_once": 0,
"unique": 0
},
@@ -70,7 +70,7 @@
"remember_last_selected_value": 1,
"report_hide": 0,
"reqd": 0,
- "search_index": 0,
+ "search_index": 1,
"set_only_once": 0,
"unique": 0
},
@@ -1214,7 +1214,7 @@
"istable": 0,
"max_attachments": 5,
"menu_index": 0,
- "modified": "2017-11-10 18:37:19.660293",
+ "modified": "2018-06-26 11:46:06.678115",
"modified_by": "Administrator",
"module": "Projects",
"name": "Task",
diff --git a/erpnext/regional/united_arab_emirates/setup.py b/erpnext/regional/united_arab_emirates/setup.py
index aa27d61..3c8328b 100644
--- a/erpnext/regional/united_arab_emirates/setup.py
+++ b/erpnext/regional/united_arab_emirates/setup.py
@@ -17,7 +17,7 @@
def make_custom_fields():
invoice_fields = [
dict(fieldname='vat_section', label='VAT Details', fieldtype='Section Break',
- insert_after='select_print_heading', print_hide=1, collapsible=1),
+ insert_after='group_same_items', print_hide=1, collapsible=1),
dict(fieldname='permit_no', label='Permit Number',
fieldtype='Data', insert_after='vat_section', print_hide=1),
dict(fieldname='reverse_charge_applicable', label='Reverse Charge Applicable',
diff --git a/erpnext/selling/doctype/quotation/quotation.js b/erpnext/selling/doctype/quotation/quotation.js
index 081d4db..695a410 100644
--- a/erpnext/selling/doctype/quotation/quotation.js
+++ b/erpnext/selling/doctype/quotation/quotation.js
@@ -186,7 +186,7 @@
return cur_frm.call({
method: "declare_order_lost",
doc: cur_frm.doc,
- args: args.reason,
+ args: args,
callback: function(r) {
if(r.exc) {
frappe.msgprint(__("There were errors."));
diff --git a/erpnext/selling/doctype/quotation/quotation.json b/erpnext/selling/doctype/quotation/quotation.json
index 61973d6..f38156c 100644
--- a/erpnext/selling/doctype/quotation/quotation.json
+++ b/erpnext/selling/doctype/quotation/quotation.json
@@ -1076,7 +1076,7 @@
"unique": 0
},
{
- "allow_bulk_edit": 0,
+ "allow_bulk_edit": 1,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -2911,7 +2911,7 @@
"istable": 0,
"max_attachments": 1,
"menu_index": 0,
- "modified": "2018-05-28 03:23:15.354674",
+ "modified": "2018-07-06 03:23:15.354674",
"modified_by": "Administrator",
"module": "Selling",
"name": "Quotation",
diff --git a/erpnext/selling/doctype/quotation/quotation.py b/erpnext/selling/doctype/quotation/quotation.py
index ad06bd2..709c069 100644
--- a/erpnext/selling/doctype/quotation/quotation.py
+++ b/erpnext/selling/doctype/quotation/quotation.py
@@ -70,10 +70,10 @@
opp.status = None
opp.set_status(update=True)
- def declare_order_lost(self, arg):
+ def declare_order_lost(self, reason):
if not self.has_sales_order():
frappe.db.set(self, 'status', 'Lost')
- frappe.db.set(self, 'order_lost_reason', arg)
+ frappe.db.set(self, 'order_lost_reason', reason)
self.update_opportunity()
self.update_lead()
else:
diff --git a/erpnext/selling/doctype/sales_order/sales_order.json b/erpnext/selling/doctype/sales_order/sales_order.json
index f302c1c..b0437e3 100644
--- a/erpnext/selling/doctype/sales_order/sales_order.json
+++ b/erpnext/selling/doctype/sales_order/sales_order.json
@@ -1131,7 +1131,7 @@
"unique": 0
},
{
- "allow_bulk_edit": 0,
+ "allow_bulk_edit": 1,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -3529,7 +3529,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
- "modified": "2018-01-12 15:56:12.483019",
+ "modified": "2018-07-06 15:56:12.483019",
"modified_by": "Administrator",
"module": "Selling",
"name": "Sales Order",
diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.json b/erpnext/stock/doctype/delivery_note/delivery_note.json
index e377783..325b234 100644
--- a/erpnext/stock/doctype/delivery_note/delivery_note.json
+++ b/erpnext/stock/doctype/delivery_note/delivery_note.json
@@ -1253,7 +1253,7 @@
"unique": 0
},
{
- "allow_bulk_edit": 0,
+ "allow_bulk_edit": 1,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -3731,7 +3731,7 @@
"istable": 0,
"max_attachments": 0,
"menu_index": 0,
- "modified": "2018-05-28 03:03:35.035396",
+ "modified": "2018-07-06 03:03:35.035396",
"modified_by": "Administrator",
"module": "Stock",
"name": "Delivery Note",
diff --git a/erpnext/stock/doctype/material_request/material_request.json b/erpnext/stock/doctype/material_request/material_request.json
index ba37345..7ba139c 100644
--- a/erpnext/stock/doctype/material_request/material_request.json
+++ b/erpnext/stock/doctype/material_request/material_request.json
@@ -294,7 +294,7 @@
"unique": 0
},
{
- "allow_bulk_edit": 0,
+ "allow_bulk_edit": 1,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -716,7 +716,7 @@
"istable": 0,
"max_attachments": 0,
"menu_index": 0,
- "modified": "2017-10-05 18:24:17.148782",
+ "modified": "2018-07-06 18:24:17.148782",
"modified_by": "Administrator",
"module": "Stock",
"name": "Material Request",
diff --git a/erpnext/stock/doctype/material_request_item/material_request_item.py b/erpnext/stock/doctype/material_request_item/material_request_item.py
index 16f007f..6c6ecfe 100644
--- a/erpnext/stock/doctype/material_request_item/material_request_item.py
+++ b/erpnext/stock/doctype/material_request_item/material_request_item.py
@@ -6,10 +6,12 @@
from __future__ import unicode_literals
import frappe
+from erpnext.controllers.print_settings import print_settings_for_item_table
from frappe.model.document import Document
class MaterialRequestItem(Document):
- pass
+ def __setup__(self):
+ print_settings_for_item_table(self)
def on_doctype_update():
frappe.db.add_index("Material Request Item", ["item_code", "warehouse"])
\ No newline at end of file
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json
index 3f4337f..15372c1 100755
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json
@@ -1038,7 +1038,7 @@
"unique": 0
},
{
- "allow_bulk_edit": 0,
+ "allow_bulk_edit": 1,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -3301,7 +3301,7 @@
"istable": 0,
"max_attachments": 0,
"menu_index": 0,
- "modified": "2018-05-28 02:59:59.609643",
+ "modified": "2018-07-06 02:59:59.609643",
"modified_by": "Administrator",
"module": "Stock",
"name": "Purchase Receipt",
diff --git a/erpnext/templates/pages/order.html b/erpnext/templates/pages/order.html
index 3a6d225..7980189 100644
--- a/erpnext/templates/pages/order.html
+++ b/erpnext/templates/pages/order.html
@@ -20,7 +20,7 @@
<div class="row transaction-subheading">
<div class="col-xs-6">
<span class="indicator {{ doc.indicator_color or ("blue" if doc.docstatus==1 else "darkgrey") }}">
- {{ _(doc.indicator_title) or _(doc.status) or _("Submitted") }}
+ {{ _(doc.get("status")) or _(doc.get("indicator_title")) or _("Submitted") }}
</span>
</div>
<div class="col-xs-6 text-muted text-right small">