From a398d6bf4f9609bcfa0743ea606781bc1d158a5f Mon Sep 17 00:00:00 2001 From: Stavros Anastasiadis Date: Thu, 11 Oct 2018 13:50:30 +0300 Subject: [PATCH 01/18] Allow Same Item Multiple Items (#15657) --- erpnext/manufacturing/doctype/bom/bom.json | 35 +++++++++++++++++++++- erpnext/manufacturing/doctype/bom/bom.py | 15 +++++----- 2 files changed, 42 insertions(+), 8 deletions(-) diff --git a/erpnext/manufacturing/doctype/bom/bom.json b/erpnext/manufacturing/doctype/bom/bom.json index 77fc4989e7..a55c3c5778 100644 --- a/erpnext/manufacturing/doctype/bom/bom.json +++ b/erpnext/manufacturing/doctype/bom/bom.json @@ -1,5 +1,6 @@ { "allow_copy": 0, + "allow_events_in_timeline": 0, "allow_guest_to_view": 0, "allow_import": 1, "allow_rename": 0, @@ -472,6 +473,38 @@ "translatable": 0, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "allow_same_item_multiple_times", + "fieldtype": "Data", + "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": "Allow Same Item Multiple Times", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, { "allow_bulk_edit": 0, "allow_in_quick_entry": 0, @@ -1943,7 +1976,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2018-07-15 11:09:19.425998", + "modified": "2018-10-11 11:52:39.047935", "modified_by": "Administrator", "module": "Manufacturing", "name": "BOM", diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py index 38e6156b03..b2c3e75b8f 100644 --- a/erpnext/manufacturing/doctype/bom/bom.py +++ b/erpnext/manufacturing/doctype/bom/bom.py @@ -334,14 +334,15 @@ class BOM(WebsiteGenerator): frappe.throw(_("Quantity required for Item {0} in row {1}").format(m.item_code, m.idx)) check_list.append(m) - duplicate_items = list(get_duplicates(check_list)) - if duplicate_items: - li = [] - for i in duplicate_items: - li.append("{0} on row {1}".format(i.item_code, i.idx)) - duplicate_list = '
' + '
'.join(li) + if not self.allow_same_item_multiple_times: + duplicate_items = list(get_duplicates(check_list)) + if duplicate_items: + li = [] + for i in duplicate_items: + li.append("{0} on row {1}".format(i.item_code, i.idx)) + duplicate_list = '
' + '
'.join(li) - frappe.throw(_("Same item has been entered multiple times. {0}").format(duplicate_list)) + frappe.throw(_("Same item has been entered multiple times. {0}").format(duplicate_list)) def check_recursion(self): """ Check whether recursion occurs in any bom""" From 4833b4c27429190ca9aaddcc7a56f9e161c87629 Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Thu, 11 Oct 2018 16:27:05 +0530 Subject: [PATCH 02/18] fix: Default Series in naming series patch (#15656) --- erpnext/patches/v11_0/refactor_naming_series.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/patches/v11_0/refactor_naming_series.py b/erpnext/patches/v11_0/refactor_naming_series.py index 1e4a53c27d..428e2c386a 100644 --- a/erpnext/patches/v11_0/refactor_naming_series.py +++ b/erpnext/patches/v11_0/refactor_naming_series.py @@ -128,5 +128,6 @@ def get_series_to_preserve(doctype): return series_to_preserve def get_default_series(doctype): - default_series = (frappe.get_meta(doctype).get_field("naming_series").default or "") + field = frappe.get_meta(doctype).get_field("naming_series") + default_series = field.get('default', '') if field else '' return default_series \ No newline at end of file From e9890a3ec80bbf755c2c51b7b50f8822551b7d94 Mon Sep 17 00:00:00 2001 From: Shreya Shah Date: Thu, 11 Oct 2018 16:28:59 +0530 Subject: [PATCH 03/18] fix(patch): Check if meta object has naming_series field (#15651) --- erpnext/patches/v11_0/refactor_naming_series.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/erpnext/patches/v11_0/refactor_naming_series.py b/erpnext/patches/v11_0/refactor_naming_series.py index 428e2c386a..b85ab66f14 100644 --- a/erpnext/patches/v11_0/refactor_naming_series.py +++ b/erpnext/patches/v11_0/refactor_naming_series.py @@ -106,6 +106,8 @@ def get_series(): continue if not frappe.db.has_column(doctype, 'naming_series'): continue + if not frappe.get_meta(doctype).has_field('naming_series'): + continue series_to_preserve = list(filter(None, get_series_to_preserve(doctype))) default_series = get_default_series(doctype) From 50447b195d0d39c86dc6872b0ed2794b818cca11 Mon Sep 17 00:00:00 2001 From: Charles-Henri Decultot Date: Thu, 11 Oct 2018 13:18:38 +0200 Subject: [PATCH 04/18] Compatibility with Py2 (#15653) --- erpnext/hr/doctype/daily_work_summary/daily_work_summary.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/hr/doctype/daily_work_summary/daily_work_summary.py b/erpnext/hr/doctype/daily_work_summary/daily_work_summary.py index 4aa3bbf158..a404b5a3e3 100644 --- a/erpnext/hr/doctype/daily_work_summary/daily_work_summary.py +++ b/erpnext/hr/doctype/daily_work_summary/daily_work_summary.py @@ -9,6 +9,7 @@ from frappe import _ from email_reply_parser import EmailReplyParser from erpnext.hr.doctype.employee.employee import is_holiday from frappe.utils import global_date_format +from six import string_types class DailyWorkSummary(Document): @@ -108,7 +109,7 @@ def get_user_emails_from_group(group): :param group: Daily Work Summary Group `name`''' group_doc = group - if isinstance(group_doc, str): + if isinstance(group_doc, string_types): group_doc = frappe.get_doc('Daily Work Summary Group', group) emails = [d.email for d in group_doc.users if frappe.db.get_value("User", d.user, "enabled")] From 6c743bebf27e094c05943fe5a73a63377787ae46 Mon Sep 17 00:00:00 2001 From: Charles-Henri Decultot Date: Thu, 11 Oct 2018 13:21:29 +0200 Subject: [PATCH 05/18] Check for prefix before return EcritureNum (#15629) --- .../fichier_des_ecritures_comptables_[fec].py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/erpnext/regional/report/fichier_des_ecritures_comptables_[fec]/fichier_des_ecritures_comptables_[fec].py b/erpnext/regional/report/fichier_des_ecritures_comptables_[fec]/fichier_des_ecritures_comptables_[fec].py index a072ed031c..5fbf7007f4 100644 --- a/erpnext/regional/report/fichier_des_ecritures_comptables_[fec]/fichier_des_ecritures_comptables_[fec].py +++ b/erpnext/regional/report/fichier_des_ecritures_comptables_[fec]/fichier_des_ecritures_comptables_[fec].py @@ -105,9 +105,12 @@ def get_result_as_list(data, filters): for d in data: - JournalCode = re.split("-|/", d.get("voucher_no"))[0] + JournalCode = re.split("-|/|[0-9]", d.get("voucher_no"))[0] - EcritureNum = re.split("-|/", d.get("voucher_no"))[1] + if d.get("voucher_no").startswith("{0}-".format(JournalCode)) or d.get("voucher_no").startswith("{0}/".format(JournalCode)): + EcritureNum = re.split("-|/", d.get("voucher_no"))[1] + else: + EcritureNum = re.search("{0}(\d+)".format(JournalCode), d.get("voucher_no"), re.IGNORECASE).group(1) EcritureDate = format_datetime(d.get("GlPostDate"), "yyyyMMdd") From 64b6421fcef282ca436726eb5b5315b9f13da0f5 Mon Sep 17 00:00:00 2001 From: Charles-Henri Decultot Date: Thu, 11 Oct 2018 13:24:26 +0200 Subject: [PATCH 06/18] Add event in transaction base correction (#15631) --- erpnext/utilities/transaction_base.py | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/erpnext/utilities/transaction_base.py b/erpnext/utilities/transaction_base.py index 6ca3d5bf88..4845e0b960 100644 --- a/erpnext/utilities/transaction_base.py +++ b/erpnext/utilities/transaction_base.py @@ -37,11 +37,18 @@ class TransactionBase(StatusUpdater): self._add_calendar_event(opts) def delete_events(self): - events = frappe.db.sql_list("""select name from `tabEvent` - where ref_type=%s and ref_name=%s""", (self.doctype, self.name)) - if events: - frappe.db.sql("delete from `tabEvent` where name in ({0})" - .format(", ".join(['%s']*len(events))), tuple(events)) + participations = frappe.get_all("Event Participants", filters={"reference_doctype": self.doctype, "reference_docname": self.name, + "parenttype": "Event"}, fields=["name", "parent"]) + + if participations: + for participation in participations: + total_participants = frappe.get_all("Event Participants", filters={"parenttype": "Event", "parent": participation.parent}) + + if len(total_participants) <= 1: + frappe.db.sql("delete from `tabEvent` where name='%s'" % participation.parent) + + frappe.db.sql("delete from `tabEvent Participants` where name='%s'" % participation.name) + def _add_calendar_event(self, opts): opts = frappe._dict(opts) @@ -54,11 +61,15 @@ class TransactionBase(StatusUpdater): "description": opts.description, "starts_on": self.contact_date, "ends_on": opts.ends_on, - "event_type": "Private", - "ref_type": self.doctype, - "ref_name": self.name + "event_type": "Private" }) + event.append('event_participants', { + "reference_doctype": self.doctype, + "reference_docname": self.name + } + ) + event.insert(ignore_permissions=True) if frappe.db.exists("User", self.contact_by): From a16f0f44232e12d39ff374d9ce0d72938ba838a0 Mon Sep 17 00:00:00 2001 From: Alchez Date: Thu, 11 Oct 2018 16:56:46 +0530 Subject: [PATCH 07/18] fix(item_defaults): handle multiple item defaults for a company (#15634) --- erpnext/stock/doctype/item/item.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py index f32e959903..17cf044074 100644 --- a/erpnext/stock/doctype/item/item.py +++ b/erpnext/stock/doctype/item/item.py @@ -122,6 +122,7 @@ class Item(WebsiteGenerator): self.validate_fixed_asset() self.validate_retain_sample() self.validate_uom_conversion_factor() + self.validate_item_defaults() self.update_defaults_from_item_group() if not self.get("__islocal"): @@ -663,6 +664,12 @@ class Item(WebsiteGenerator): template_item.flags.ignore_permissions = True template_item.save() + def validate_item_defaults(self): + companies = list(set([row.company for row in self.item_defaults])) + + if len(companies) != len(self.item_defaults): + frappe.throw(_("Cannot set multiple Item Defaults for a company.")) + def update_defaults_from_item_group(self): """Get defaults from Item Group""" if self.item_group and not self.item_defaults: From 314c97cbf16394b138b4ecef274989713cb9e7fb Mon Sep 17 00:00:00 2001 From: Shreya Shah Date: Thu, 11 Oct 2018 16:59:40 +0530 Subject: [PATCH 08/18] Fix for supplier quotation (#15659) --- erpnext/controllers/buying_controller.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py index 696afb2306..dbde30410c 100644 --- a/erpnext/controllers/buying_controller.py +++ b/erpnext/controllers/buying_controller.py @@ -69,7 +69,7 @@ class BuyingController(StockController): # set contact and address details for supplier, if they are not mentioned if getattr(self, "supplier", None): self.update_if_missing(get_party_details(self.supplier, party_type="Supplier", ignore_permissions=self.flags.ignore_permissions, - doctype=self.doctype, company=self.company, party_address=self.supplier_address, shipping_address=self.shipping_address)) + doctype=self.doctype, company=self.company, party_address=self.supplier_address, shipping_address=self.get('shipping_address'))) self.set_missing_item_details(for_validate) From 8c62ab4af03866bf03d9f40fdee3980ca3869813 Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Thu, 11 Oct 2018 17:06:10 +0530 Subject: [PATCH 09/18] [Enhancement] Email birthday reminder (#15559) * Update hooks.py * modified date for reload_doc (#15027) * Single email for multiple birthdays and test --- erpnext/hr/doctype/employee/employee.py | 73 +++++++++++++++----- erpnext/hr/doctype/employee/test_employee.py | 3 +- 2 files changed, 56 insertions(+), 20 deletions(-) diff --git a/erpnext/hr/doctype/employee/employee.py b/erpnext/hr/doctype/employee/employee.py index 7285e04648..1401a4d465 100755 --- a/erpnext/hr/doctype/employee/employee.py +++ b/erpnext/hr/doctype/employee/employee.py @@ -4,7 +4,7 @@ from __future__ import unicode_literals import frappe -from frappe.utils import getdate, validate_email_add, today, add_years +from frappe.utils import getdate, validate_email_add, today, add_years, format_datetime from frappe.model.naming import set_name_by_naming_series from frappe import throw, _, scrub from frappe.permissions import add_user_permission, remove_user_permission, \ @@ -223,27 +223,63 @@ def send_birthday_reminders(): if int(frappe.db.get_single_value("HR Settings", "stop_birthday_reminders") or 0): return - from frappe.utils.user import get_enabled_system_users - users = None - birthdays = get_employees_who_are_born_today() if birthdays: - if not users: - users = [u.email_id or u.name for u in get_enabled_system_users()] + employee_list = frappe.get_all('Employee', + fields=['name','employee_name'], + filters={'status': 'Active', + 'company': birthdays[0]['company'] + } + ) + employee_emails = get_employee_emails(employee_list) + birthday_names = [name["employee_name"] for name in birthdays] + birthday_emails = [email["user_id"] or email["personal_email"] or email["company_email"] for email in birthdays] + + birthdays.append({'company_email': '','employee_name': '','personal_email': '','user_id': ''}) for e in birthdays: - frappe.sendmail(recipients=filter(lambda u: u not in (e.company_email, e.personal_email, e.user_id), users), - subject=_("Birthday Reminder for {0}").format(e.employee_name), - message=_("""Today is {0}'s birthday!""").format(e.employee_name), - reply_to=e.company_email or e.personal_email or e.user_id) + if e['company_email'] or e['personal_email'] or e['user_id']: + if len(birthday_names) == 1: + continue + recipients = e['company_email'] or e['personal_email'] or e['user_id'] + + + else: + recipients = list(set(employee_emails) - set(birthday_emails)) + + frappe.sendmail(recipients=recipients, + subject=_("Birthday Reminder"), + message=get_birthday_reminder_message(e, birthday_names), + header=['Birthday Reminder', 'green'], + ) + +def get_birthday_reminder_message(employee, employee_names): + """Get employee birthday reminder message""" + pattern = "
  • " + message = pattern.join(filter(lambda u: u not in (employee['employee_name']), employee_names)) + message = message.title() + + if pattern not in message: + message = "Today is {0}'s birthday \U0001F603".format(message) + + else: + message = "Today your colleagues are celebrating their birthdays \U0001F382
    • " + message +"
    " + + return message + def get_employees_who_are_born_today(): """Get Employee properties whose birthday is today.""" - return frappe.db.sql("""select name, personal_email, company_email, user_id, employee_name - from tabEmployee where day(date_of_birth) = day(%(date)s) - and month(date_of_birth) = month(%(date)s) - and status = 'Active'""", {"date": today()}, as_dict=True) + return frappe.db.get_values("Employee", + fieldname=["name", "personal_email", "company", "company_email", "user_id", "employee_name"], + filters={ + "date_of_birth": ("like", "%{}".format(format_datetime(getdate(), "-MM-dd"))), + "status": "Active", + }, + as_dict=True + ) + def get_holiday_list_for_employee(employee, raise_exception=True): if employee: @@ -319,10 +355,11 @@ def get_employee_emails(employee_list): for employee in employee_list: if not employee: continue - user, email = frappe.db.get_value('Employee', employee, ['user_id', 'company_email']) - if user or email: - employee_emails.append(user or email) - + user, company_email, personal_email = frappe.db.get_value('Employee', employee, + ['user_id', 'company_email', 'personal_email']) + email = user or company_email or personal_email + if email: + employee_emails.append(email) return employee_emails @frappe.whitelist() diff --git a/erpnext/hr/doctype/employee/test_employee.py b/erpnext/hr/doctype/employee/test_employee.py index 72f4c54f06..1afb8f40b4 100644 --- a/erpnext/hr/doctype/employee/test_employee.py +++ b/erpnext/hr/doctype/employee/test_employee.py @@ -30,8 +30,7 @@ class TestEmployee(unittest.TestCase): send_birthday_reminders() email_queue = frappe.db.sql("""select * from `tabEmail Queue`""", as_dict=True) - self.assertTrue("Subject: Birthday Reminder for {0}".format(employee.employee_name) \ - in email_queue[0].message) + self.assertTrue("Subject: Birthday Reminder" in email_queue[0].message) def make_employee(user): if not frappe.db.get_value("User", user): From 3362d6b948cb3204eae00a13cb1eb557cf85a4f7 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Mon, 15 Oct 2018 11:07:13 +0530 Subject: [PATCH 10/18] [Fix] Precision issue in the expense claim (#15678) --- erpnext/hr/doctype/expense_claim/expense_claim.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/erpnext/hr/doctype/expense_claim/expense_claim.py b/erpnext/hr/doctype/expense_claim/expense_claim.py index 4d1b19abdc..1eeb16a6d1 100644 --- a/erpnext/hr/doctype/expense_claim/expense_claim.py +++ b/erpnext/hr/doctype/expense_claim/expense_claim.py @@ -224,10 +224,11 @@ class ExpenseClaim(AccountsController): self.total_advance_amount += flt(d.allocated_amount) if self.total_advance_amount: - if flt(self.total_advance_amount) > flt(self.total_claimed_amount): + precision = self.precision("total_advance_amount") + if flt(self.total_advance_amount, precision) > flt(self.total_claimed_amount, precision): frappe.throw(_("Total advance amount cannot be greater than total claimed amount")) if self.total_sanctioned_amount \ - and flt(self.total_advance_amount) > flt(self.total_sanctioned_amount): + and flt(self.total_advance_amount, precision) > flt(self.total_sanctioned_amount, precision): frappe.throw(_("Total advance amount cannot be greater than total sanctioned amount")) def validate_sanctioned_amount(self): From 42510a411f7edf3f52129bf47e53e6755a0a0f16 Mon Sep 17 00:00:00 2001 From: deepeshgarg007 <42651287+deepeshgarg007@users.noreply.github.com> Date: Mon, 15 Oct 2018 11:08:04 +0530 Subject: [PATCH 11/18] [Bug-Fix]V11 Accounts Receivable print showing zero values (#15667) * Bug Fix * Print report bug fixes --- .../report/accounts_receivable/accounts_receivable.html | 2 +- .../accounts/report/accounts_receivable/accounts_receivable.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.html b/erpnext/accounts/report/accounts_receivable/accounts_receivable.html index 40ec252a24..4573a427c1 100644 --- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.html +++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.html @@ -167,7 +167,7 @@ {%= format_currency(data[i]["paid_amount"], data[i]["currency"]) %} - {%= report.report_name === "Accounts Receivable" ? format_currency(data[i]["credit_note"], data[i]["currency"]) : format_currency(data[i]["Debit Note"], data[i]["currency"]) %} + {%= report.report_name === "Accounts Receivable" ? format_currency(data[i]["credit_note"], data[i]["currency"]) : format_currency(data[i]["debit_note"], data[i]["currency"]) %} {% } %} {%= format_currency(data[i]["outstanding_amount"], data[i]["currency"]) %} diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py index f54ff48622..8b7ccaf7b7 100755 --- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py +++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py @@ -83,6 +83,7 @@ class ReceivablePayableReport(object): "{range3}-{above}".format(range3=cint(self.filters["range3"])+ 1, above=_("Above"))): columns.append({ "label": label, + "fieldname":label, "fieldtype": "Currency", "options": "currency", "width": 120 From 0d2a4c6a5903be006fc0cca299f9f4079ca068bb Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Mon, 15 Oct 2018 11:09:17 +0530 Subject: [PATCH 12/18] [Fix] TDS Payable Monthly report is not working (#15666) --- .../tds_payable_monthly/tds_payable_monthly.js | 1 + .../tds_payable_monthly/tds_payable_monthly.py | 15 +++++++++------ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.js b/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.js index 232d0537a3..344539eef6 100644 --- a/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.js +++ b/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.js @@ -8,6 +8,7 @@ frappe.query_reports["TDS Payable Monthly"] = { "fieldname":"company", "label": __("Company"), "fieldtype": "Link", + "options": "Company", "default": frappe.defaults.get_default('company') }, { diff --git a/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py b/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py index 8e5723f337..843b58f448 100644 --- a/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py +++ b/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py @@ -64,13 +64,16 @@ def get_result(filters): total_amount_credited += k.credit rate = [i.tax_withholding_rate for i in tds_doc.rates - if i.fiscal_year == gle_map[d][0].fiscal_year][0] + if i.fiscal_year == gle_map[d][0].fiscal_year] - if getdate(filters.from_date) <= gle_map[d][0].posting_date \ - and getdate(filters.to_date) >= gle_map[d][0].posting_date: - out.append([supplier.pan, supplier.name, tds_doc.name, - supplier.supplier_type, rate, total_amount_credited, tds_deducted, - gle_map[d][0].posting_date, "Purchase Invoice", d]) + if rate and len(rate) > 0: + rate = rate[0] + + if getdate(filters.from_date) <= gle_map[d][0].posting_date \ + and getdate(filters.to_date) >= gle_map[d][0].posting_date: + out.append([supplier.pan, supplier.name, tds_doc.name, + supplier.supplier_type, rate, total_amount_credited, tds_deducted, + gle_map[d][0].posting_date, "Purchase Invoice", d]) return out From 741bd29b74fbd136d4fbd3146732784ddaffae0f Mon Sep 17 00:00:00 2001 From: Ranjith Kurungadam Date: Mon, 15 Oct 2018 14:52:38 +0530 Subject: [PATCH 13/18] fix: Patient Appointment Calendar (#15684) --- .../patient_appointment.py | 4 +-- .../patient_appointment_calendar.js | 34 +------------------ 2 files changed, 3 insertions(+), 35 deletions(-) diff --git a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py index 7d948b8187..5364031fce 100755 --- a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py +++ b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py @@ -339,13 +339,13 @@ def get_events(start, end, filters=None): data = frappe.db.sql("""select name, patient, practitioner, status, duration, timestamp(appointment_date, appointment_time) as - 'appointment_date' from `tabPatient Appointment` where + 'start' from `tabPatient Appointment` where (appointment_date between %(start)s and %(end)s) and docstatus < 2 {conditions}""".format(conditions=conditions), {"start": start, "end": end}, as_dict=True, update={"allDay": 0}) for item in data: - item.appointment_datetime = item.appointment_date + datetime.timedelta(minutes = item.duration) + item.end = item.start + datetime.timedelta(minutes = item.duration) return data diff --git a/erpnext/healthcare/doctype/patient_appointment/patient_appointment_calendar.js b/erpnext/healthcare/doctype/patient_appointment/patient_appointment_calendar.js index fc674a8a3e..2249d2a205 100644 --- a/erpnext/healthcare/doctype/patient_appointment/patient_appointment_calendar.js +++ b/erpnext/healthcare/doctype/patient_appointment/patient_appointment_calendar.js @@ -10,37 +10,5 @@ frappe.views.calendar["Patient Appointment"] = { }, order_by: "appointment_date", gantt: true, - get_events_method: "erpnext.healthcare.doctype.patient_appointment.patient_appointment.get_events", - filters: [ - { - 'fieldtype': 'Link', - 'fieldname': 'practitioner', - 'options': 'Healthcare Practitioner', - 'label': __('Healthcare Practitioner') - }, - { - 'fieldtype': 'Link', - 'fieldname': 'patient', - 'options': 'Patient', - 'label': __('Patient') - }, - { - 'fieldtype': 'Link', - 'fieldname': 'appointment_type', - 'options': 'Appointment Type', - 'label': __('Appointment Type') - }, - { - 'fieldtype': 'Link', - 'fieldname': 'department', - 'options': 'Medical Department', - 'label': __('Department') - }, - { - 'fieldtype': 'Select', - 'fieldname': 'status', - 'options': 'Scheduled\nOpen\nClosed\nPending', - 'label': __('Status') - } - ] + get_events_method: "erpnext.healthcare.doctype.patient_appointment.patient_appointment.get_events" }; From 2a966f26afccae7f45f96007f09c0efb8594c5a3 Mon Sep 17 00:00:00 2001 From: Jamsheer Date: Mon, 15 Oct 2018 14:54:29 +0530 Subject: [PATCH 14/18] fix: patch - change healthcare desktop icons (#15683) --- .../v11_0/change_healthcare_desktop_icons.py | 131 ++++++++++-------- 1 file changed, 76 insertions(+), 55 deletions(-) diff --git a/erpnext/patches/v11_0/change_healthcare_desktop_icons.py b/erpnext/patches/v11_0/change_healthcare_desktop_icons.py index ab10c66bc4..b1b427559c 100644 --- a/erpnext/patches/v11_0/change_healthcare_desktop_icons.py +++ b/erpnext/patches/v11_0/change_healthcare_desktop_icons.py @@ -1,68 +1,89 @@ import frappe from frappe import _ +change_icons_map = [ + { + "module_name": "Patient", + "color": "#6BE273", + "icon": "fa fa-user", + "doctype": "Patient", + "type": "link", + "link": "List/Patient", + "label": _("Patient") + }, + { + "module_name": "Patient Encounter", + "color": "#2ecc71", + "icon": "fa fa-stethoscope", + "doctype": "Patient Encounter", + "type": "link", + "link": "List/Patient Encounter", + "label": _("Patient Encounter"), + }, + { + "module_name": "Healthcare Practitioner", + "color": "#2ecc71", + "icon": "fa fa-user-md", + "doctype": "Healthcare Practitioner", + "type": "link", + "link": "List/Healthcare Practitioner", + "label": _("Healthcare Practitioner") + }, + { + "module_name": "Patient Appointment", + "color": "#934F92", + "icon": "fa fa-calendar-plus-o", + "doctype": "Patient Appointment", + "type": "link", + "link": "List/Patient Appointment", + "label": _("Patient Appointment") + }, + { + "module_name": "Lab Test", + "color": "#7578f6", + "icon": "octicon octicon-beaker", + "doctype": "Lab Test", + "type": "link", + "link": "List/Lab Test", + "label": _("Lab Test") + } +] + def execute(): change_healthcare_desktop_icons() def change_healthcare_desktop_icons(): - change_icons_map = [ - { - "module_name": "Patient", - "color": "#6BE273", - "icon": "fa fa-user", - "doctype": "Patient", - "type": "link", - "link": "List/Patient", - "label": _("Patient") - }, - { - "module_name": "Patient Encounter", - "color": "#2ecc71", - "icon": "fa fa-stethoscope", - "doctype": "Patient Encounter", - "type": "link", - "link": "List/Patient Encounter", - "label": _("Patient Encounter"), - }, - { - "module_name": "Healthcare Practitioner", - "color": "#2ecc71", - "icon": "fa fa-user-md", - "doctype": "Healthcare Practitioner", - "type": "link", - "link": "List/Healthcare Practitioner", - "label": _("Healthcare Practitioner") - }, - { - "module_name": "Patient Appointment", - "color": "#934F92", - "icon": "fa fa-calendar-plus-o", - "doctype": "Patient Appointment", - "type": "link", - "link": "List/Patient Appointment", - "label": _("Patient Appointment") - }, - { - "module_name": "Lab Test", - "color": "#7578f6", - "icon": "octicon octicon-beaker", - "doctype": "Lab Test", - "type": "link", - "link": "List/Lab Test", - "label": _("Lab Test") - } - ] - for spec in change_icons_map: frappe.db.sql(""" - update `tabDesktop Icon` - set module_name = '{0}', color = '{1}', icon = '{2}', _doctype = '{3}', type = '{4}', - link = '{5}', label = '{6}' - where _doctype = '{7}' - """.format(spec['module_name'], spec['color'], spec['icon'], spec['doctype'], spec['type'], spec['link'], spec['label'], spec['doctype'])) + delete from `tabDesktop Icon` + where _doctype = '{0}' + """.format(spec['doctype'])) + + desktop_icon = frappe.new_doc("Desktop Icon") + desktop_icon.hidden = 1 + desktop_icon.standard = 1 + desktop_icon.icon = spec['icon'] + desktop_icon.color = spec['color'] + desktop_icon.module_name = spec['module_name'] + desktop_icon.label = spec['label'] + desktop_icon.app = "erpnext" + desktop_icon.type = spec['type'] + desktop_icon._doctype = spec['doctype'] + desktop_icon.link = spec['link'] + desktop_icon.save(ignore_permissions=True) frappe.db.sql(""" - update `tabDesktop Icon` - set color = '#FF888B', icon = 'fa fa-heartbeat' + delete from `tabDesktop Icon` where module_name = 'Healthcare' and type = 'module' """) + + desktop_icon = frappe.new_doc("Desktop Icon") + desktop_icon.hidden = 1 + desktop_icon.standard = 1 + desktop_icon.icon = "fa fa-heartbeat" + desktop_icon.color = "#FF888B" + desktop_icon.module_name = "Healthcare" + desktop_icon.label = _("Healthcare") + desktop_icon.app = "erpnext" + desktop_icon.type = 'module' + desktop_icon.save(ignore_permissions=True) From 94fcb0e9f9c640e14046eaa7e35dc7c9d18afffd Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Mon, 15 Oct 2018 14:57:46 +0530 Subject: [PATCH 15/18] [Enhance] Add user image in the employee from the user (#15680) --- erpnext/hr/doctype/employee/employee.py | 15 +++++++++++---- erpnext/patches.txt | 3 ++- .../v10_0/update_user_image_in_employee.py | 19 +++++++++++++++++++ 3 files changed, 32 insertions(+), 5 deletions(-) create mode 100644 erpnext/patches/v10_0/update_user_image_in_employee.py diff --git a/erpnext/hr/doctype/employee/employee.py b/erpnext/hr/doctype/employee/employee.py index 25d3ec4bc9..81671c21dc 100755 --- a/erpnext/hr/doctype/employee/employee.py +++ b/erpnext/hr/doctype/employee/employee.py @@ -45,14 +45,21 @@ class Employee(NestedSet): self.validate_prefered_email() if self.user_id: - self.validate_for_enabled_user_id() - self.validate_duplicate_user_id() + self.validate_user_details() else: existing_user_id = frappe.db.get_value("Employee", self.name, "user_id") if existing_user_id: frappe.permissions.remove_user_permission( "Employee", self.name, existing_user_id) + def validate_user_details(self): + data = frappe.db.get_value('User', + self.user_id, ['enabled', 'user_image'], as_dict=1) + + self.image = data.get("user_image") + self.validate_for_enabled_user_id(data.get("enabled", 0)) + self.validate_duplicate_user_id() + def update_nsm_model(self): frappe.utils.nestedset.update_nsm(self) @@ -133,10 +140,10 @@ class Employee(NestedSet): if self.status == 'Left' and not self.relieving_date: throw(_("Please enter relieving date.")) - def validate_for_enabled_user_id(self): + def validate_for_enabled_user_id(self, enabled): if not self.status == 'Active': return - enabled = frappe.db.get_value("User", self.user_id, "enabled") + if enabled is None: frappe.throw(_("User {0} does not exist").format(self.user_id)) if enabled == 0: diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 313f3789fd..6c7a252b16 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -505,4 +505,5 @@ erpnext.patches.v10_0.update_status_in_purchase_receipt erpnext.patches.v10_0.update_address_template_for_india erpnext.patches.v10_0.set_discount_amount erpnext.patches.v10_0.recalculate_gross_margin_for_project -erpnext.patches.v10_0.delete_hub_documents \ No newline at end of file +erpnext.patches.v10_0.delete_hub_documents +erpnext.patches.v10_0.update_user_image_in_employee \ No newline at end of file diff --git a/erpnext/patches/v10_0/update_user_image_in_employee.py b/erpnext/patches/v10_0/update_user_image_in_employee.py new file mode 100644 index 0000000000..72d5d2a857 --- /dev/null +++ b/erpnext/patches/v10_0/update_user_image_in_employee.py @@ -0,0 +1,19 @@ +# 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('hr', 'doctype', 'employee') + + frappe.db.sql(""" + UPDATE + `tabEmployee`, `tabUser` + SET + `tabEmployee`.image = `tabUser`.user_image + WHERE + `tabEmployee`.user_id = `tabUser`.name and + `tabEmployee`.user_id is not null and + `tabEmployee`.user_id != '' and `tabEmployee`.image is null + """) From d2c643eb0bd512fa8a2eea95cde3c7bd546e3a67 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Mon, 15 Oct 2018 16:11:25 +0600 Subject: [PATCH 16/18] bumped to version 10.1.59 --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index ae01237f54..ccd8a19cf3 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -5,7 +5,7 @@ import frappe from erpnext.hooks import regional_overrides from frappe.utils import getdate -__version__ = '10.1.58' +__version__ = '10.1.59' def get_default_company(user=None): '''Get default company for user''' From 102eb998acb7db9e7908af1cb8aa87d6b6ec4e29 Mon Sep 17 00:00:00 2001 From: Ameya Shenoy Date: Mon, 15 Oct 2018 16:05:28 +0530 Subject: [PATCH 17/18] fix(patch): reload healthacre doctypes Signed-off-by: Ameya Shenoy --- erpnext/healthcare/doctype/patient/patient.json | 2 +- erpnext/patches/v11_0/change_healthcare_desktop_icons.py | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/erpnext/healthcare/doctype/patient/patient.json b/erpnext/healthcare/doctype/patient/patient.json index 95e7bfcab3..28e5351e67 100644 --- a/erpnext/healthcare/doctype/patient/patient.json +++ b/erpnext/healthcare/doctype/patient/patient.json @@ -1391,7 +1391,7 @@ "issingle": 0, "istable": 0, "max_attachments": 50, - "modified": "2018-10-09 22:09:39.849116", + "modified": "2018-10-14 22:09:39.849116", "modified_by": "Administrator", "module": "Healthcare", "name": "Patient", diff --git a/erpnext/patches/v11_0/change_healthcare_desktop_icons.py b/erpnext/patches/v11_0/change_healthcare_desktop_icons.py index b1b427559c..ed7df503e5 100644 --- a/erpnext/patches/v11_0/change_healthcare_desktop_icons.py +++ b/erpnext/patches/v11_0/change_healthcare_desktop_icons.py @@ -53,6 +53,10 @@ def execute(): change_healthcare_desktop_icons() def change_healthcare_desktop_icons(): + doctypes = ["patient", "patient_encounter", "healthcare_practitioner", + "patient_appointment", "lab_test"] + for doctype in doctypes: + frappe.reload_doc("healthcare", "doctype", doctype) for spec in change_icons_map: frappe.db.sql(""" delete from `tabDesktop Icon` From 8d0195246d7c25705fd969f10a1627a9bb4712cb Mon Sep 17 00:00:00 2001 From: Ameya Shenoy Date: Mon, 15 Oct 2018 12:24:12 +0000 Subject: [PATCH 18/18] bumped to version 11.0.3-beta.11 --- erpnext/hooks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/hooks.py b/erpnext/hooks.py index 250c5a6d45..b980d68591 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -12,7 +12,7 @@ app_license = "GNU General Public License (v3)" source_link = "https://github.com/frappe/erpnext" develop_version = '11.x.x-develop' -staging_version = '11.0.3-beta.10' +staging_version = '11.0.3-beta.11' error_report_email = "support@erpnext.com"