diff --git a/erpnext/accounts/doctype/pos_invoice/pos_invoice.py b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py index 91c07ade7f..d782cc295c 100644 --- a/erpnext/accounts/doctype/pos_invoice/pos_invoice.py +++ b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py @@ -485,16 +485,15 @@ class POSInvoice(SalesInvoice): "payment_account": pay.account, }, ["name"]) - args = { - 'doctype': 'Payment Request', + filters = { 'reference_doctype': 'POS Invoice', 'reference_name': self.name, 'payment_gateway_account': payment_gateway_account, 'email_to': self.contact_mobile } - pr = frappe.db.exists(args) + pr = frappe.db.get_value('Payment Request', filters=filters) if pr: - return frappe.get_doc('Payment Request', pr[0][0]) + return frappe.get_doc('Payment Request', pr) @frappe.whitelist() def get_stock_availability(item_code, warehouse): diff --git a/erpnext/crm/doctype/appointment/appointment.py b/erpnext/crm/doctype/appointment/appointment.py index 20fb987c60..88a9c10131 100644 --- a/erpnext/crm/doctype/appointment/appointment.py +++ b/erpnext/crm/doctype/appointment/appointment.py @@ -225,9 +225,7 @@ def _check_agent_availability(agent_email, scheduled_time): def _get_employee_from_user(user): - employee_docname = frappe.db.exists( - {'doctype': 'Employee', 'user_id': user}) + employee_docname = frappe.db.get_value('Employee', {'user_id': user}) if employee_docname: - # frappe.db.exists returns a tuple of a tuple - return frappe.get_doc('Employee', employee_docname[0][0]) + return frappe.get_doc('Employee', employee_docname) return None diff --git a/erpnext/crm/doctype/appointment/test_appointment.py b/erpnext/crm/doctype/appointment/test_appointment.py index f4086dc37c..776e604333 100644 --- a/erpnext/crm/doctype/appointment/test_appointment.py +++ b/erpnext/crm/doctype/appointment/test_appointment.py @@ -8,50 +8,44 @@ import frappe def create_test_lead(): - test_lead = frappe.db.exists({'doctype': 'Lead', 'email_id':'test@example.com'}) - if test_lead: - return frappe.get_doc('Lead', test_lead[0][0]) - test_lead = frappe.get_doc({ - 'doctype': 'Lead', - 'lead_name': 'Test Lead', - 'email_id': 'test@example.com' - }) - test_lead.insert(ignore_permissions=True) - return test_lead + test_lead = frappe.db.get_value("Lead", {"email_id": "test@example.com"}) + if test_lead: + return frappe.get_doc("Lead", test_lead) + test_lead = frappe.get_doc( + {"doctype": "Lead", "lead_name": "Test Lead", "email_id": "test@example.com"} + ) + test_lead.insert(ignore_permissions=True) + return test_lead def create_test_appointments(): - test_appointment = frappe.db.exists( - {'doctype': 'Appointment', 'scheduled_time':datetime.datetime.now(),'email':'test@example.com'}) - if test_appointment: - return frappe.get_doc('Appointment', test_appointment[0][0]) - test_appointment = frappe.get_doc({ - 'doctype': 'Appointment', - 'email': 'test@example.com', - 'status': 'Open', - 'customer_name': 'Test Lead', - 'customer_phone_number': '666', - 'customer_skype': 'test', - 'customer_email': 'test@example.com', - 'scheduled_time': datetime.datetime.now() - }) - test_appointment.insert() - return test_appointment + test_appointment = frappe.get_doc( + { + "doctype": "Appointment", + "email": "test@example.com", + "status": "Open", + "customer_name": "Test Lead", + "customer_phone_number": "666", + "customer_skype": "test", + "customer_email": "test@example.com", + "scheduled_time": datetime.datetime.now(), + } + ) + test_appointment.insert() + return test_appointment class TestAppointment(unittest.TestCase): - test_appointment = test_lead = None + test_appointment = test_lead = None - def setUp(self): - self.test_lead = create_test_lead() - self.test_appointment = create_test_appointments() + def setUp(self): + self.test_lead = create_test_lead() + self.test_appointment = create_test_appointments() - def test_calendar_event_created(self): - cal_event = frappe.get_doc( - 'Event', self.test_appointment.calendar_event) - self.assertEqual(cal_event.starts_on, - self.test_appointment.scheduled_time) + def test_calendar_event_created(self): + cal_event = frappe.get_doc("Event", self.test_appointment.calendar_event) + self.assertEqual(cal_event.starts_on, self.test_appointment.scheduled_time) - def test_lead_linked(self): - lead = frappe.get_doc('Lead', self.test_lead.name) - self.assertIsNotNone(lead) + def test_lead_linked(self): + lead = frappe.get_doc("Lead", self.test_lead.name) + self.assertIsNotNone(lead) diff --git a/erpnext/e_commerce/product_ui/views.js b/erpnext/e_commerce/product_ui/views.js index 6dce79dd72..fb63b21a08 100644 --- a/erpnext/e_commerce/product_ui/views.js +++ b/erpnext/e_commerce/product_ui/views.js @@ -418,6 +418,22 @@ erpnext.ProductView = class { me.change_route_with_filters(); }); + + // bind filter lookup input box + $('.filter-lookup-input').on('keydown', frappe.utils.debounce((e) => { + const $input = $(e.target); + const keyword = ($input.val() || '').toLowerCase(); + const $filter_options = $input.next('.filter-options'); + + $filter_options.find('.filter-lookup-wrapper').show(); + $filter_options.find('.filter-lookup-wrapper').each((i, el) => { + const $el = $(el); + const value = $el.data('value').toLowerCase(); + if (!value.includes(keyword)) { + $el.hide(); + } + }); + }, 300)); } change_route_with_filters() { diff --git a/erpnext/education/setup.py b/erpnext/education/setup.py index b716926176..663f1cab4f 100644 --- a/erpnext/education/setup.py +++ b/erpnext/education/setup.py @@ -3,7 +3,6 @@ import frappe -from erpnext.setup.utils import insert_record def setup_education(): @@ -13,6 +12,21 @@ def setup_education(): return create_academic_sessions() + +def insert_record(records): + for r in records: + doc = frappe.new_doc(r.get("doctype")) + doc.update(r) + try: + doc.insert(ignore_permissions=True) + except frappe.DuplicateEntryError as e: + # pass DuplicateEntryError and continue + if e.args and e.args[0]==doc.doctype and e.args[1]==doc.name: + # make sure DuplicateEntryError is for the exact same doc and not a related doc + pass + else: + raise + def create_academic_sessions(): data = [ {"doctype": "Academic Year", "academic_year_name": "2015-16"}, diff --git a/erpnext/hr/doctype/leave_application/test_leave_application.py b/erpnext/hr/doctype/leave_application/test_leave_application.py index 7d32fd8865..3a30990268 100644 --- a/erpnext/hr/doctype/leave_application/test_leave_application.py +++ b/erpnext/hr/doctype/leave_application/test_leave_application.py @@ -25,6 +25,7 @@ from erpnext.hr.doctype.leave_application.leave_application import ( LeaveDayBlockedError, NotAnOptionalHoliday, OverlapError, + get_leave_allocation_records, get_leave_balance_on, get_leave_details, ) @@ -882,6 +883,27 @@ class TestLeaveApplication(unittest.TestCase): self.assertEqual(leave_allocation['leaves_pending_approval'], 1) self.assertEqual(leave_allocation['remaining_leaves'], 26) + @set_holiday_list('Salary Slip Test Holiday List', '_Test Company') + def test_get_leave_allocation_records(self): + employee = get_employee() + leave_type = create_leave_type( + leave_type_name="_Test_CF_leave_expiry", + is_carry_forward=1, + expire_carry_forwarded_leaves_after_days=90) + leave_type.insert() + + leave_alloc = create_carry_forwarded_allocation(employee, leave_type) + details = get_leave_allocation_records(employee.name, getdate(), leave_type.name) + expected_data = { + "from_date": getdate(leave_alloc.from_date), + "to_date": getdate(leave_alloc.to_date), + "total_leaves_allocated": 30.0, + "unused_leaves": 15.0, + "new_leaves_allocated": 15.0, + "leave_type": leave_type.name + } + self.assertEqual(details.get(leave_type.name), expected_data) + def create_carry_forwarded_allocation(employee, leave_type): # initial leave allocation @@ -903,6 +925,8 @@ def create_carry_forwarded_allocation(employee, leave_type): carry_forward=1) leave_allocation.submit() + return leave_allocation + def make_allocation_record(employee=None, leave_type=None, from_date=None, to_date=None, carry_forward=False, leaves=None): allocation = frappe.get_doc({ "doctype": "Leave Allocation", @@ -931,12 +955,9 @@ def set_leave_approver(): dept_doc.save(ignore_permissions=True) def get_leave_period(): - leave_period_name = frappe.db.exists({ - "doctype": "Leave Period", - "company": "_Test Company" - }) + leave_period_name = frappe.db.get_value("Leave Period", {"company": "_Test Company"}) if leave_period_name: - return frappe.get_doc("Leave Period", leave_period_name[0][0]) + return frappe.get_doc("Leave Period", leave_period_name) else: return frappe.get_doc(dict( name = 'Test Leave Period', diff --git a/erpnext/public/scss/shopping_cart.scss b/erpnext/public/scss/shopping_cart.scss index 019496d295..6ae464d2c2 100644 --- a/erpnext/public/scss/shopping_cart.scss +++ b/erpnext/public/scss/shopping_cart.scss @@ -264,6 +264,15 @@ body.product-page { font-size: 13px; } + .filter-lookup-input { + background-color: white; + border: 1px solid var(--gray-300); + + &:focus { + border: 1px solid var(--primary); + } + } + .filter-label { font-size: 11px; font-weight: 600; diff --git a/erpnext/setup/install.py b/erpnext/setup/install.py index 1d7bad2686..1d95ddb203 100644 --- a/erpnext/setup/install.py +++ b/erpnext/setup/install.py @@ -21,9 +21,7 @@ default_mail_footer = """
\nThis is a notification for a task that is due today, and a sample Notification. In ERPNext you can setup notifications on anything, Invoices, Orders, Leads, Opportunities, so you never miss a thing.\n
To edit this, and setup other alerts, just type Notification in the search bar.