Merge branch 'develop' into maintainance-ux-fix
diff --git a/erpnext/__init__.py b/erpnext/__init__.py
index 686d549..d031bc5 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__ = '12.1.6'
+__version__ = '12.1.8'
def get_default_company(user=None):
'''Get default company for user'''
diff --git a/erpnext/accounts/dashboard_chart_source/account_balance_timeline/account_balance_timeline.py b/erpnext/accounts/dashboard_chart_source/account_balance_timeline/account_balance_timeline.py
index bc07b6d..d098d84 100644
--- a/erpnext/accounts/dashboard_chart_source/account_balance_timeline/account_balance_timeline.py
+++ b/erpnext/accounts/dashboard_chart_source/account_balance_timeline/account_balance_timeline.py
@@ -3,6 +3,7 @@
from __future__ import unicode_literals
import frappe, json
+from frappe import _
from frappe.utils import add_to_date, date_diff, getdate, nowdate, get_last_day, formatdate
from erpnext.accounts.report.general_ledger.general_ledger import execute
from frappe.core.page.dashboard.dashboard import cache_source, get_from_date_from_timespan
@@ -24,6 +25,9 @@
account = filters.get("account")
company = filters.get("company")
+ if not account and chart:
+ frappe.throw(_("Account is not set for the dashboard chart {0}").format(chart))
+
if not to_date:
to_date = nowdate()
if not from_date:
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.js b/erpnext/accounts/doctype/payment_entry/payment_entry.js
index 172d537..1e0b1bc 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.js
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.js
@@ -308,7 +308,7 @@
() => {
frm.set_party_account_based_on_party = false;
if (r.message.bank_account) {
- frm.set_value("bank_account", r.message.bank_account);
+ frm.set_value("party_bank_account", r.message.bank_account);
}
}
]);
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 146c10c..8d65ac8 100644
--- a/erpnext/accounts/report/budget_variance_report/budget_variance_report.py
+++ b/erpnext/accounts/report/budget_variance_report/budget_variance_report.py
@@ -69,7 +69,7 @@
for year in fiscal_year:
for from_date, to_date in get_period_date_ranges(filters["period"], year[0]):
if filters["period"] == "Yearly":
- labels = [_("Budget") + " " + str(year[0]), _("Actual ") + " " + str(year[0]), _("Varaiance ") + " " + str(year[0])]
+ labels = [_("Budget") + " " + str(year[0]), _("Actual ") + " " + str(year[0]), _("Variance ") + " " + str(year[0])]
for label in labels:
columns.append(label+":Float:150")
else:
diff --git a/erpnext/erpnext_integrations/doctype/shopify_log/shopify_log.py b/erpnext/erpnext_integrations/doctype/shopify_log/shopify_log.py
index 7d3f572..a2b6af9 100644
--- a/erpnext/erpnext_integrations/doctype/shopify_log/shopify_log.py
+++ b/erpnext/erpnext_integrations/doctype/shopify_log/shopify_log.py
@@ -39,7 +39,7 @@
if hasattr(exception, 'message'):
message = exception.message
elif hasattr(exception, '__str__'):
- message = e.__str__()
+ message = exception.__str__()
else:
message = "Something went wrong while syncing"
return message
diff --git a/erpnext/erpnext_integrations/doctype/shopify_settings/shopify_settings.py b/erpnext/erpnext_integrations/doctype/shopify_settings/shopify_settings.py
index a4332b1..0cad0cc 100644
--- a/erpnext/erpnext_integrations/doctype/shopify_settings/shopify_settings.py
+++ b/erpnext/erpnext_integrations/doctype/shopify_settings/shopify_settings.py
@@ -43,7 +43,7 @@
d.raise_for_status()
self.update_webhook_table(method, d.json())
except Exception as e:
- make_shopify_log(status="Warning", message=e, exception=False)
+ make_shopify_log(status="Warning", exception=e, rollback=True)
def unregister_webhooks(self):
session = get_request_session()
diff --git a/erpnext/hr/doctype/expense_claim/expense_claim_list.js b/erpnext/hr/doctype/expense_claim/expense_claim_list.js
index 0e25e66..6195ad4 100644
--- a/erpnext/hr/doctype/expense_claim/expense_claim_list.js
+++ b/erpnext/hr/doctype/expense_claim/expense_claim_list.js
@@ -2,11 +2,11 @@
add_fields: ["total_claimed_amount", "docstatus"],
get_indicator: function(doc) {
if(doc.status == "Paid") {
- return [__("Paid"), "green", "status,=,'Paid'"];
+ return [__("Paid"), "green", "status,=,Paid"];
}else if(doc.status == "Unpaid") {
- return [__("Unpaid"), "orange"];
+ return [__("Unpaid"), "orange", "status,=,Unpaid"];
} else if(doc.status == "Rejected") {
- return [__("Rejected"), "grey"];
+ return [__("Rejected"), "grey", "status,=,Rejected"];
}
}
};
diff --git a/erpnext/hr/doctype/leave_application/leave_application.py b/erpnext/hr/doctype/leave_application/leave_application.py
index 97de40f..b73028e 100755
--- a/erpnext/hr/doctype/leave_application/leave_application.py
+++ b/erpnext/hr/doctype/leave_application/leave_application.py
@@ -503,14 +503,17 @@
def get_pending_leaves_for_period(employee, leave_type, from_date, to_date):
''' Returns leaves that are pending approval '''
- return frappe.db.get_value("Leave Application",
+ leaves = frappe.get_all("Leave Application",
filters={
"employee": employee,
"leave_type": leave_type,
- "from_date": ("<=", from_date),
- "to_date": (">=", to_date),
"status": "Open"
- }, fieldname=['SUM(total_leave_days)']) or flt(0)
+ },
+ or_filters={
+ "from_date": ["between", (from_date, to_date)],
+ "to_date": ["between", (from_date, to_date)]
+ }, fields=['SUM(total_leave_days) as leaves'])[0]
+ return leaves['leaves'] if leaves['leaves'] else 0.0
def get_remaining_leaves(allocation, leaves_taken, date, expiry):
''' Returns minimum leaves remaining after comparing with remaining days for allocation expiry '''
diff --git a/erpnext/hr/doctype/salary_slip/salary_slip.py b/erpnext/hr/doctype/salary_slip/salary_slip.py
index 27a51c3..46be4fe 100644
--- a/erpnext/hr/doctype/salary_slip/salary_slip.py
+++ b/erpnext/hr/doctype/salary_slip/salary_slip.py
@@ -5,7 +5,7 @@
import frappe, erpnext
import datetime, math
-from frappe.utils import add_days, cint, cstr, flt, getdate, rounded, date_diff, money_in_words, getdate
+from frappe.utils import add_days, cint, cstr, flt, getdate, rounded, date_diff, money_in_words
from frappe.model.naming import make_autoname
from frappe import msgprint, _
diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py
index 225ae29..c849f5b 100644
--- a/erpnext/manufacturing/doctype/bom/bom.py
+++ b/erpnext/manufacturing/doctype/bom/bom.py
@@ -39,9 +39,11 @@
names = [d[-1][1:] for d in filter(lambda x: len(x) > 1 and x[-1], names)]
# split by (-) if cancelled
- names = [cint(name.split('-')[-1]) for name in names]
-
- idx = max(names) + 1
+ if names:
+ names = [cint(name.split('-')[-1]) for name in names]
+ idx = max(names) + 1
+ else:
+ idx = 1
else:
idx = 1
@@ -290,7 +292,8 @@
return valuation_rate
def manage_default_bom(self):
- """ Uncheck others if current one is selected as default,
+ """ Uncheck others if current one is selected as default or
+ check the current one as default if it the only bom for the selected item,
update default bom in item master
"""
if self.is_default and self.is_active:
@@ -299,6 +302,9 @@
item = frappe.get_doc("Item", self.item)
if item.default_bom != self.name:
frappe.db.set_value('Item', self.item, 'default_bom', self.name)
+ elif not frappe.db.exists(dict(doctype='BOM', docstatus=1, item=self.item, is_default=1)) \
+ and self.is_active:
+ frappe.db.set(self, "is_default", 1)
else:
frappe.db.set(self, "is_default", 0)
item = frappe.get_doc("Item", self.item)
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index 9f98099..ee6bdff 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -640,3 +640,4 @@
erpnext.patches.v12_0.set_produced_qty_field_in_sales_order_for_work_order
erpnext.patches.v12_0.generate_leave_ledger_entries
erpnext.patches.v12_0.set_default_shopify_app_type
+erpnext.patches.v12_0.replace_accounting_with_accounts_in_home_settings
diff --git a/erpnext/patches/v12_0/replace_accounting_with_accounts_in_home_settings.py b/erpnext/patches/v12_0/replace_accounting_with_accounts_in_home_settings.py
new file mode 100644
index 0000000..09fc4c1
--- /dev/null
+++ b/erpnext/patches/v12_0/replace_accounting_with_accounts_in_home_settings.py
@@ -0,0 +1,5 @@
+import frappe
+
+def execute():
+ frappe.db.sql("""UPDATE `tabUser` SET `home_settings` = REPLACE(`home_settings`, 'Accounting', 'Accounts')""")
+ frappe.cache().delete_key('home_settings')
\ No newline at end of file
diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py
index af78ab2..c4c3c0f 100755
--- a/erpnext/selling/doctype/sales_order/sales_order.py
+++ b/erpnext/selling/doctype/sales_order/sales_order.py
@@ -205,7 +205,7 @@
if self.coupon_code:
from erpnext.accounts.doctype.pricing_rule.utils import update_coupon_code_count
update_coupon_code_count(self.coupon_code,'cancelled')
-
+
def update_project(self):
if frappe.db.get_single_value('Selling Settings', 'sales_update_frequency') != "Each Transaction":
return
@@ -661,12 +661,15 @@
if source_parent.project:
target.cost_center = frappe.db.get_value("Project", source_parent.project, "cost_center")
- if not target.cost_center and target.item_code:
+ if target.item_code:
item = get_item_defaults(target.item_code, source_parent.company)
item_group = get_item_group_defaults(target.item_code, source_parent.company)
- target.cost_center = item.get("selling_cost_center") \
+ cost_center = item.get("selling_cost_center") \
or item_group.get("selling_cost_center")
+ if cost_center:
+ target.cost_center = cost_center
+
doclist = get_mapped_doc("Sales Order", source_name, {
"Sales Order": {
"doctype": "Sales Invoice",
diff --git a/erpnext/setup/doctype/company/company.py b/erpnext/setup/doctype/company/company.py
index e69a6aad..8b42b19 100644
--- a/erpnext/setup/doctype/company/company.py
+++ b/erpnext/setup/doctype/company/company.py
@@ -33,6 +33,10 @@
return exists
def validate(self):
+ self.update_default_account = False
+ if self.is_new():
+ self.update_default_account = True
+
self.validate_abbr()
self.validate_default_accounts()
self.validate_currency()
@@ -203,8 +207,8 @@
"default_expense_account": "Cost of Goods Sold"
})
- for default_account in default_accounts:
- if self.is_new() or frappe.flags.in_test or frappe.flags.in_demo:
+ if self.update_default_account or frappe.flags.in_test:
+ for default_account in default_accounts:
self._set_default_account(default_account, default_accounts.get(default_account))
if not self.default_income_account:
diff --git a/erpnext/shopping_cart/cart.py b/erpnext/shopping_cart/cart.py
index f850bc1..a4c10cf 100644
--- a/erpnext/shopping_cart/cart.py
+++ b/erpnext/shopping_cart/cart.py
@@ -66,7 +66,7 @@
from erpnext.selling.doctype.quotation.quotation import _make_sales_order
sales_order = frappe.get_doc(_make_sales_order(quotation.name, ignore_permissions=True))
- if not cart_settings.allow_items_not_in_stock:
+ if not cint(cart_settings.allow_items_not_in_stock):
for item in sales_order.get("items"):
item.reserved_warehouse, is_stock_item = frappe.db.get_value("Item",
item.item_code, ["website_warehouse", "is_stock_item"])
diff --git a/erpnext/stock/doctype/delivery_note/delivery_note_list.js b/erpnext/stock/doctype/delivery_note/delivery_note_list.js
index 6fc51ec..0ae7c37 100644
--- a/erpnext/stock/doctype/delivery_note/delivery_note_list.js
+++ b/erpnext/stock/doctype/delivery_note/delivery_note_list.js
@@ -6,9 +6,9 @@
return [__("Return"), "darkgrey", "is_return,=,Yes"];
} else if (doc.status === "Closed") {
return [__("Closed"), "green", "status,=,Closed"];
- } else if (doc.grand_total !== 0 && flt(doc.per_billed, 2) < 100) {
+ } else if (flt(doc.per_billed, 2) < 100) {
return [__("To Bill"), "orange", "per_billed,<,100"];
- } else if (doc.grand_total === 0 || flt(doc.per_billed, 2) == 100) {
+ } else if (flt(doc.per_billed, 2) == 100) {
return [__("Completed"), "green", "per_billed,=,100"];
}
},
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py
index 7fa7d3b..55e02a4 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.py
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.py
@@ -241,7 +241,9 @@
for d in self.get("items"):
if not d.expense_account:
- frappe.throw(_("Please enter Difference Account"))
+ frappe.throw(_("Please enter <b>Difference Account</b> or set default <b>Stock Adjustment Account</b> for company {0}")
+ .format(frappe.bold(self.company)))
+
elif self.is_opening == "Yes" and frappe.db.get_value("Account", d.expense_account, "report_type") == "Profit and Loss":
frappe.throw(_("Difference Account must be a Asset/Liability type account, since this Stock Entry is an Opening Entry"), OpeningEntryAccountError)
diff --git a/erpnext/support/doctype/issue/issue.py b/erpnext/support/doctype/issue/issue.py
index cdf5fed..b748e3f 100644
--- a/erpnext/support/doctype/issue/issue.py
+++ b/erpnext/support/doctype/issue/issue.py
@@ -22,7 +22,6 @@
return "{0}: {1}".format(_(self.status), self.subject)
def validate(self):
- self.flags.ignore_disabled = 1
if self.is_new() and self.via_customer_portal:
self.flags.create_communication = True