diff --git a/erpnext/__init__.py b/erpnext/__init__.py index e9bdbf94a3b..a81cc856255 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''' diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.html b/erpnext/accounts/report/accounts_receivable/accounts_receivable.html index 40ec252a24b..4573a427c1b 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 f54ff486229..8b7ccaf7b7e 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 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 232d0537a32..344539eef6d 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 8e5723f3371..843b58f4486 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 diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py index 7d83d5cbf11..79ed56b79dd 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) diff --git a/erpnext/healthcare/doctype/patient/patient.json b/erpnext/healthcare/doctype/patient/patient.json index 95e7bfcab34..28e5351e67e 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/healthcare/doctype/patient_appointment/patient_appointment.py b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py index 7d948b8187b..5364031fce1 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 fc674a8a3e1..2249d2a2059 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" }; diff --git a/erpnext/hooks.py b/erpnext/hooks.py index b0ff5a9b5fb..fa3e9dbdfdd 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 = '12.x.x-develop' -staging_version = '11.0.3-beta.10' +staging_version = '11.0.3-beta.11' error_report_email = "support@erpnext.com" 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 4aa3bbf1587..a404b5a3e30 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")] diff --git a/erpnext/hr/doctype/employee/employee.py b/erpnext/hr/doctype/employee/employee.py index 7285e046480..cb4c1908fb3 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, \ @@ -49,8 +49,7 @@ class Employee(NestedSet): self.validate_onboarding_process() 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: @@ -60,6 +59,14 @@ class Employee(NestedSet): def set_employee_name(self): self.employee_name = ' '.join(filter(lambda x: x, [self.first_name, self.middle_name, self.last_name])) + 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) @@ -143,10 +150,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: @@ -223,27 +230,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
    " + + 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 +362,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 72f4c54f06f..1afb8f40b47 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): diff --git a/erpnext/hr/doctype/expense_claim/expense_claim.py b/erpnext/hr/doctype/expense_claim/expense_claim.py index ca092ad05e0..d6b0eca70ee 100644 --- a/erpnext/hr/doctype/expense_claim/expense_claim.py +++ b/erpnext/hr/doctype/expense_claim/expense_claim.py @@ -215,10 +215,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): diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 26c33061a98..9c569488c96 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -571,3 +571,4 @@ erpnext.patches.v11_0.add_sales_stages erpnext.patches.v11_0.ewaybill_fields_gst_india erpnext.patches.v11_0.drop_column_max_days_allowed erpnext.patches.v11_0.change_healthcare_desktop_icons +erpnext.patches.v10_0.update_user_image_in_employee 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 00000000000..72d5d2a857b --- /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 + """) diff --git a/erpnext/patches/v11_0/change_healthcare_desktop_icons.py b/erpnext/patches/v11_0/change_healthcare_desktop_icons.py index ab10c66bc4b..ed7df503e51 100644 --- a/erpnext/patches/v11_0/change_healthcare_desktop_icons.py +++ b/erpnext/patches/v11_0/change_healthcare_desktop_icons.py @@ -1,68 +1,93 @@ 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") - } - ] - + 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(""" - 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) diff --git a/erpnext/patches/v11_0/refactor_naming_series.py b/erpnext/patches/v11_0/refactor_naming_series.py index 1e4a53c27da..b85ab66f148 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) @@ -128,5 +130,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 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 a072ed031cb..5fbf7007f4c 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") diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py index 73fd30e37b7..f56c5f5a039 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: diff --git a/erpnext/utilities/transaction_base.py b/erpnext/utilities/transaction_base.py index 6ca3d5bf889..4845e0b960e 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):