def find_parent_based_on_subject_and_sender(self, communication, email): '''Find parent document based on subject and sender match''' parent = None if self.append_to and self.sender_field: if self.subject_field: # try and match by subject and sender # if sent by same sender with same subject, # append it to old coversation subject = strip(re.sub("(^\s*(Fw|FW|fwd)[^:]*:|\s*(Re|RE)[^:]*:\s*)*", "", email.subject)) parent = frappe.db.get_all(self.append_to, filters={ self.sender_field: email.from_email, self.subject_field: ("like", "%{0}%".format(subject)), "creation": (">", (get_datetime() - relativedelta(days=10)).strftime(DATE_FORMAT)) }, fields="name") # match only subject field # when the from_email is of a user in the system # and subject is atleast 10 chars long if not parent and len(subject) > 10 and is_system_user(email.from_email): parent = frappe.db.get_all(self.append_to, filters={ self.subject_field: ("like", "%{0}%".format(subject)), "creation": (">", (get_datetime() - relativedelta(days=10)).strftime(DATE_FORMAT)) }, fields="name") if parent: parent = frappe.get_doc(self.append_to, parent[0].name) return parent
def daily_notifications(): """ sent notifications to user if 1 : ticket is open for more than 24 hrs 2 : ticket is assigned but not Closed in 24 hrs """ tickets = frappe.db.get_all("Ticket Escalation History", filters=[["status", "!=", "Closed"], ["status", "!=", "Deleted"]], fields=["*"]) for ticket in tickets: # ticket is raised but not yet assigned issue_doc = frappe.get_doc("Issue", ticket.ticket_id) args = { "user": get_fullname(issue_doc.raised_by) or "User", "email": issue_doc.raised_by, "action": "user_issue_notification", "issue": issue_doc } if ticket.raised_email_notification and not ticket.assigned_email_notification: raised_time = ticket.raised_email_notification_datetime if time_diff_in_hours(get_datetime().now(), raised_time) >= 24: # send user notification mail msg = "Your support ticket {ticket_id} is pending our representative will \ check the issue as soon as possible".format(ticket_id=ticket.ticket_id) args.update({"msg":msg}) send_mail(args, "[HelpDesk] Daily Notifications") elif ticket.assigned_email_notification and not ticket.status_closed_email_notification: assigned_time = ticket.assigned_email_notification_datetime if time_diff_in_hours(get_datetime().now(), assigned_time) >= 24: # send the user notification mail msg = "Your support ticket {ticket_id} is assigned to our support representative \ and issue will be solved as soon as possble".format(ticket_id=ticket.ticket_id) args.update({"msg":msg}) send_mail(args, "[HelpDesk] Daily Notifications")
def validate_return_against(doc): filters = {"doctype": doc.doctype, "docstatus": 1, "company": doc.company} if doc.meta.get_field("customer") and doc.customer: filters["customer"] = doc.customer elif doc.meta.get_field("supplier") and doc.supplier: filters["supplier"] = doc.supplier if not frappe.db.exists(filters): frappe.throw(_("Invalid {0}: {1}") .format(doc.meta.get_label("return_against"), doc.return_against)) else: ref_doc = frappe.get_doc(doc.doctype, doc.return_against) # validate posting date time return_posting_datetime = "%s %s" % (doc.posting_date, doc.get("posting_time") or "00:00:00") ref_posting_datetime = "%s %s" % (ref_doc.posting_date, ref_doc.get("posting_time") or "00:00:00") if get_datetime(return_posting_datetime) < get_datetime(ref_posting_datetime): frappe.throw(_("Posting timestamp must be after {0}").format(format_datetime(ref_posting_datetime))) # validate same exchange rate if doc.conversion_rate != ref_doc.conversion_rate: frappe.throw(_("Exchange Rate must be same as {0} {1} ({2})") .format(doc.doctype, doc.return_against, ref_doc.conversion_rate)) # validate update stock if doc.doctype == "Sales Invoice" and doc.update_stock and not ref_doc.update_stock: frappe.throw(_("'Update Stock' can not be checked because items are not delivered via {0}") .format(doc.return_against))
def test_make_time_log(self): prod_order = make_prod_order_test_record(item="_Test FG Item 2", planned_start_date="2014-11-25 00:00:00", qty=1, do_not_save=True) prod_order.set_production_order_operations() prod_order.insert() prod_order.submit() d = prod_order.operations[0] d.completed_qty = flt(d.completed_qty) time_log = make_time_log(prod_order.name, d.operation, \ d.planned_start_time, d.planned_end_time, prod_order.qty - d.completed_qty, operation_id=d.name) self.assertEqual(prod_order.name, time_log.production_order) self.assertEqual((prod_order.qty - d.completed_qty), time_log.completed_qty) self.assertEqual(time_diff_in_hours(d.planned_end_time, d.planned_start_time),time_log.hours) time_log.save() time_log.submit() manufacturing_settings = frappe.get_doc({ "doctype": "Manufacturing Settings", "allow_production_on_holidays": 0 }) manufacturing_settings.save() prod_order.load_from_db() self.assertEqual(prod_order.operations[0].status, "Completed") self.assertEqual(prod_order.operations[0].completed_qty, prod_order.qty) self.assertEqual(get_datetime(prod_order.operations[0].actual_start_time), get_datetime(time_log.from_time)) self.assertEqual(get_datetime(prod_order.operations[0].actual_end_time), get_datetime(time_log.to_time)) self.assertEqual(prod_order.operations[0].actual_operation_time, 60) self.assertEqual(prod_order.operations[0].actual_operating_cost, 100) time_log.cancel() prod_order.load_from_db() self.assertEqual(prod_order.operations[0].status, "Pending") self.assertEqual(flt(prod_order.operations[0].completed_qty), 0) self.assertEqual(flt(prod_order.operations[0].actual_operation_time), 0) self.assertEqual(flt(prod_order.operations[0].actual_operating_cost), 0) time_log2 = frappe.copy_doc(time_log) time_log2.update({ "completed_qty": 10, "from_time": "2014-11-26 00:00:00", "to_time": "2014-11-26 00:00:00", "docstatus": 0 }) self.assertRaises(OverProductionLoggedError, time_log2.save)
def get_last_login_diff(user): """ Returns difference between todays date and last login date """ last_login = frappe.db.get_value("User", user, ["last_login"]) for x in xrange(1,10): print((get_datetime() - get_datetime(last_login)).days, user) return (get_datetime() - get_datetime(last_login)).days
def make_course_schedule(self, date): course_schedule = frappe.new_doc("Course Schedule") course_schedule.student_group = self.student_group course_schedule.course = self.course course_schedule.instructor = self.instructor course_schedule.instructor_name = self.instructor_name course_schedule.room = self.room course_schedule.from_time= get_datetime(date + " " + self.from_time) course_schedule.to_time= get_datetime(date + " " + self.to_time) return course_schedule
def is_within_operating_hours(workstation, operation, from_datetime, to_datetime): operation_length = time_diff_in_seconds(to_datetime, from_datetime) workstation = frappe.get_doc("Workstation", workstation) for working_hour in workstation.working_hours: slot_length = (get_datetime(working_hour.end_time) - get_datetime(working_hour.start_time)).total_seconds() if slot_length >= operation_length: return frappe.throw(_("Operation {0} longer than any available working hours in workstation {1}, break down the operation into multiple operations").format(operation, workstation.name), NotInWorkingHoursError)
def validate(self): if self.starts_on and self.ends_on and get_datetime(self.starts_on) > get_datetime(self.ends_on): frappe.msgprint(frappe._("Event end must be after start"), raise_exception=True) if self.starts_on == self.ends_on: # this scenario doesn't make sense i.e. it starts and ends at the same second! self.ends_on = None if getdate(self.starts_on) == getdate(self.ends_on) and self.repeat_on == "Every Day": frappe.msgprint(frappe._("Every day events should finish on the same day."), raise_exception=True)
def validate_dates(self): if self.end_date: if self.start_date and get_datetime(self.end_date) < get_datetime(self.start_date): frappe.throw(_("End Date cannot be before Start Date!")) # If the current date is past end date, and # web page is published, empty the end date if self.published and now() > self.end_date: self.end_date = None frappe.msgprint(_("Clearing end date, as it cannot be in the past for published pages."))
def get_operations_data(self, data): return { 'from_time': get_datetime(data.planned_start_time), 'hours': data.time_in_mins / 60.0, 'to_time': get_datetime(data.planned_end_time), 'project': self.project, 'operation': data.operation, 'operation_id': data.name, 'workstation': data.workstation, 'completed_qty': flt(self.qty) - flt(data.completed_qty) }
def Sethoras_Quarto(self): if self.hora_diaria_noite == "Noite": self.hora_saida= get_datetime(self.hora_entrada) + timedelta(hours=12) elif self.hora_diaria_noite == "Diaria": self.hora_saida= get_datetime(self.hora_entrada) + timedelta(days=self.horas) elif self.hora_diaria_noite == "Hora": self.hora_saida = get_datetime(self.hora_entrada) + timedelta(hours=self.horas) print "DEPOIS DE CALCULAR" print self.hora_saida
def create_update_escalation_history(issue_doc=None, issue_name=None, esc_name=None): if not issue_doc: issue_doc = frappe.get_doc("Issue", issue_name) esc = None is_new = True args = { "user": "******", "email": issue_doc.raised_by, "action": "user_issue_notification", "issue": issue_doc } if not esc_name: # ticket does not exist create new esc = frappe.new_doc("Ticket Escalation History") else: # ticket already exist update escalation history esc = frappe.get_doc("Ticket Escalation History", esc_name) is_new = False esc.ticket_id = issue_doc.name esc.status = issue_doc.status esc.opening_date = issue_doc.opening_date esc.opening_time = issue_doc.opening_time if is_new: datetime_str = "{date} {time}".format(date=issue_doc.opening_date, time=issue_doc.opening_time) esc.assigned_on = get_datetime(datetime_str) esc.current_owner = "Administrator" esc.current_role = "Administrator" args.update({ "msg": "A Support Ticket {name} has been created successfully in \ the HelpDesk System, please check the Support Ticket details".format(name=issue_doc.name) }) send_mail(args, "[HelpDesk][Issue Raised] HelpDesk Notifications") print args.get("email") esc.raised_email_notification = 1 esc.raised_email_notification_datetime = get_datetime().now() # mail notification to email if issue status is closed elif issue_doc.status == "Closed" and not esc.status_closed_email_notification: args.update({ "msg": "A Support Ticket {name}'s status has been changed to Closed, \ please check the Support Ticket details".format(name=issue_doc.name) }) send_mail(args, "[HelpDesk][Ticket Closed] HelpDesk Notifications") esc.status_closed_email_notification = 1 esc.status_closed_email_notification_datetime = get_datetime().now() esc.save(ignore_permissions=True)
def get_last_tried_login_data(user, get_last_login=False): locked_account_time = frappe.cache().hget('locked_account_time', user) if get_last_login and locked_account_time: return locked_account_time last_login_tried = frappe.cache().hget('last_login_tried', user) if not last_login_tried or last_login_tried < get_datetime(): last_login_tried = get_datetime() + datetime.timedelta(seconds=60) frappe.cache().hset('last_login_tried', user, last_login_tried) return last_login_tried
def make_course_schedule(self, date): """Makes a new Course Schedule. :param date: Date on which Course Schedule will be created.""" course_schedule = frappe.new_doc("Course Schedule") course_schedule.student_group = self.student_group course_schedule.course = self.course course_schedule.instructor = self.instructor course_schedule.instructor_name = self.instructor_name course_schedule.room = self.room course_schedule.from_time= get_datetime(date + " " + self.from_time) course_schedule.to_time= get_datetime(date + " " + self.to_time) return course_schedule
def set_start_end_time_for_workstation(self, data, index): """Set start and end time for given operation. If first operation, set start as `planned_start_date`, else add time diff to end time of earlier operation.""" if index == 0: data.planned_start_time = self.planned_start_date else: data.planned_start_time = get_datetime(self.operations[index-1].planned_end_time)\ + get_mins_between_operations() data.planned_end_time = get_datetime(data.planned_start_time) + relativedelta(minutes = data.time_in_mins) if data.planned_start_time == data.planned_end_time: frappe.throw(_("Capacity Planning Error"))
def check_frequency_hit(from_date, to_date, frequency): '''Return True if current date matches frequency''' from_dt = get_datetime(from_date) to_dt = get_datetime(to_date) from dateutil import relativedelta rd = relativedelta.relativedelta(to_dt, from_dt) months = rd.months if frequency == "Quarterly": if not months % 3: return True elif frequency == "Yearly": if not months % 12: return True return False
def check_consecutive_login_attempts(user, doc): login_failed_count = get_login_failed_count(user) last_login_tried = (get_last_tried_login_data(user, True) + datetime.timedelta(seconds=doc.allow_login_after_fail)) if login_failed_count >= cint(doc.allow_consecutive_login_attempts): locked_account_time = frappe.cache().hget('locked_account_time', user) if not locked_account_time: frappe.cache().hset('locked_account_time', user, get_datetime()) if last_login_tried > get_datetime(): frappe.throw(_("Your account has been locked and will resume after {0} seconds") .format(doc.allow_login_after_fail), frappe.SecurityException) else: delete_login_failed_cache(user)
def set_operation_start_end_time(self, i, d): """Set start and end time for given operation. If first operation, set start as `planned_start_date`, else add time diff to end time of earlier operation.""" if self.planned_start_date: if i==0: # first operation at planned_start date d.planned_start_time = self.planned_start_date else: d.planned_start_time = get_datetime(self.operations[i-1].planned_end_time)\ + get_mins_between_operations() d.planned_end_time = get_datetime(d.planned_start_time) + relativedelta(minutes = d.time_in_mins) if d.planned_start_time == d.planned_end_time: frappe.throw(_("Capacity Planning Error"))
def create_update_escalation_record(todo=None, todo_name=None, esc_name=None): if not todo: todo = frappe.get_doc("ToDo", todo_name) esc = frappe.get_doc("Ticket Escalation History", esc_name) rec_id = frappe.db.get_value("Escalation Record",{"parent":esc_name, "todo":todo.name},"name") entry = None if not rec_id: # child entry not found create new entry entry = esc.append('items', {}) entry.todo = todo.name else: # update child table record and update moodified date of the Ticket Escalation History items = esc.items entry = [ch for ch in items if ch.get("name") == rec_id][0] entry.assigned_by = todo.assigned_by entry.assigned_to = todo.owner entry.todo_status = todo.status entry.due_date = todo.date esc.is_assigned = 1 # esc.assigned_on = get_datetime("{date} {time}".format(date=todo.date, time=todo.due_time)) esc.assigned_on = get_datetime() esc.current_owner = todo.owner esc.current_role = todo.assigned_to_role esc.save(ignore_permissions=True)
def datetime_in_user_format(date_time): if not date_time: return "" if isinstance(date_time, basestring): date_time = get_datetime(date_time) from frappe.utils import formatdate return formatdate(date_time.date()) + " " + date_time.strftime("%H:%M")
def cast(self, val, df): if df.fieldtype in ("Currency", "Float", "Percent"): val = flt(val) elif df.fieldtype in ("Int", "Check"): val = cint(val) elif df.fieldtype in ( "Data", "Text", "Small Text", "Long Text", "Text Editor", "Select", "Link", "Dynamic Link", ): val = cstr(val) elif df.fieldtype == "Date": val = getdate(val) elif df.fieldtype == "Datetime": val = get_datetime(val) elif df.fieldtype == "Time": val = to_timedelta(val) return val
def get_day_wise_records(resultSet): day_wise_record = {} for r in resultSet: label = "Pending" if r.get("status") not in ("Open", "Closed") else r.get("status") date = get_datetime(r.get("resolution_date")).date() if r.get("status") == "Closed" else getdate(r.get("opening_date")) date = str(date) record = day_wise_record.get(date) if not record: day_wise_record.update({ date:{ label:[r] } }) else: lebel_wise_record = record.get(label) if not lebel_wise_record: record.update({ label:[r] }) else: lebel_wise_record.append(r) record.update({ label: lebel_wise_record }) return day_wise_record
def create_show_property_contact_entry(user_data, response): if not frappe.db.get_value("Show Contact Property", {"user_id":user_data.get("user_id"), "property_id":response.get("property_id")}, "name"): doc = frappe.new_doc("Show Contact Property") doc.user_id = user_data.get("user_id") doc.property_id = response.get("property_id") doc.property_title = response.get("property_title") doc.property_type = response.get("property_type") doc.property_subtype = response.get("property_subtype") doc.visiting_date = get_datetime() doc.save(ignore_permissions=True) return True else: scp = frappe.get_doc("Show Contact Property", {"user_id":user_data.get("user_id"), "property_id":response.get("property_id")} ) scp.visiting_date = get_datetime() scp.save(ignore_permissions=True) return False
def deactivate_relieved_employees(): employees = frappe.db.sql("""select name,employee_name,relieving_date from `tabEmployee` where relieving_date IS NOT NULL and status <> %(status)s""", {"status": "Left"}, as_dict=1) for emp in employees: from datetime import datetime currentDay = datetime.now().day currentMonth = datetime.now().month currentYear = datetime.now().year relieving_date = get_datetime(emp.relieving_date) relieving_day = relieving_date.day relieving_month = relieving_date.month relieving_year = relieving_date.year if relieving_year < currentYear: # frappe.errprint("change to left - year different") frappe.db.begin() frappe.db.set_value('Employee', emp.name, 'status', 'Left') frappe.db.commit() elif relieving_year == currentYear: if relieving_month < currentMonth: # frappe.errprint("change to left - year same") frappe.db.begin() frappe.db.set_value('Employee', emp.name, 'status', 'Left') frappe.db.commit() # else: # frappe.errprint("no change-relieving month same or greater")
def move_to_next_non_overlapping_slot(self, data): overlapping = self.get_overlap_for("workstation", data, data.workstation) if overlapping: time_sheet = self.get_last_working_slot(overlapping.name, data.workstation) data.from_time = get_datetime(time_sheet.to_time) + get_mins_between_operations() data.to_time = self.get_to_time(data) self.check_workstation_working_day(data)
def create_update_escalation_history(issue_doc=None, issue_name=None, esc_name=None): if not issue_doc: issue_doc = frappe.get_doc("Issue", issue_name) esc = None is_new = True if not esc_name: # ticket does not exist create new esc = frappe.new_doc("Ticket Escalation History") else: # ticket already exist update escalation history esc = frappe.get_doc("Ticket Escalation History", esc_name) is_new = False esc.ticket_id = issue_doc.name esc.status = issue_doc.status esc.opening_date = issue_doc.opening_date esc.opening_time = issue_doc.opening_time if is_new: datetime_str = "{date} {time}".format(date=issue_doc.opening_date, time=issue_doc.opening_time) esc.assigned_on = get_datetime(datetime_str) esc.current_owner = "Administrator" esc.current_role = "Administrator" esc.save(ignore_permissions=True)
def make_course_schedule_test_record(**args): args = frappe._dict(args) course_schedule = frappe.new_doc("Course Schedule") course_schedule.student_group = args.student_group or "_Test Student Group" course_schedule.course = args.course or "_Test Course" course_schedule.instructor = args.instructor or "_T-Instructor-00001" course_schedule.room = args.room or "RM0001" course_schedule.from_time = args.from_time or (get_datetime(now()) + datetime.timedelta(minutes=10)) course_schedule.to_time = args.to_time or course_schedule.from_time + datetime.timedelta(hours= 1) if not args.do_not_save: if args.simulate: while True: try: course_schedule.save() break except OverlapError: course_schedule.from_time = course_schedule.from_time + datetime.timedelta(minutes=10) course_schedule.to_time = course_schedule.from_time + datetime.timedelta(hours= 1) else: course_schedule.save() return course_schedule
def apply_action(action, doctype, docname, current_state, user=None, last_modified=None): if not verify_request(): return doc = frappe.get_doc(doctype, docname) doc_workflow_state = get_doc_workflow_state(doc) if doc_workflow_state == current_state: action_link = get_confirm_workflow_action_url(doc, action, user) if not last_modified or get_datetime(doc.modified) == get_datetime(last_modified): return_action_confirmation_page(doc, action, action_link) else: return_action_confirmation_page(doc, action, action_link, alert_doc_change=True) else: return_link_expired_page(doc, doc_workflow_state)
def get_between_date_filter(value): ''' return the formattted date as per the given example [u'2017-11-01', u'2017-11-03'] => '2017-11-01 00:00:00.000000' AND '2017-11-04 00:00:00.000000' ''' from_date = None to_date = None if value and isinstance(value, (list, tuple)): if len(value) >= 1: from_date = value[0] if len(value) >= 2: to_date = value[1] data = "'%s' AND '%s'" % ( get_datetime(from_date).strftime("%Y-%m-%d %H:%M:%S.%f"), add_to_date(get_datetime(to_date),days=1).strftime("%Y-%m-%d %H:%M:%S.%f")) return data
def update_invalid_login(self, user): last_login_tried = get_last_tried_login_data(user) failed_count = 0 if last_login_tried > get_datetime(): failed_count = get_login_failed_count(user) frappe.cache().hset('login_failed_count', user, failed_count + 1)
def create_checkin(self): emp = frappe.get_doc("Employee", self.employee) if not emp.default_shift: frappe.throw(_("""Employee should to have Default Shift""")) shift = frappe.get_doc("Shift Type", emp.default_shift) if self.is_manual: ec = frappe.get_doc(frappe._dict({ "doctype": "Employee Checkin", "employee": self.employee, "log_type": "IN", "time": get_datetime(formatdate(self.date,'YYYY-mm-dd')+' '+format_time(self.from_time)), "employee_checkin_request": self.name })) ec.insert() ec = frappe.get_doc(frappe._dict({ "doctype": "Employee Checkin", "employee": self.employee, "log_type": "OUT", "time": get_datetime(formatdate(self.date,'YYYY-mm-dd')+' '+format_time(self.to_time)), "employee_checkin_request": self.name })) ec.insert() elif self.enable_two_period_in_ecr==1: if self.period_type=='First': if self.log_type=='ALL': ec = frappe.get_doc(frappe._dict({ "doctype": "Employee Checkin", "employee": self.employee, "log_type": "IN", "time": get_datetime(formatdate(self.date,'YYYY-mm-dd')+' '+format_time(shift.start_time)), "employee_checkin_request": self.name })) ec.insert() ec = frappe.get_doc(frappe._dict({ "doctype": "Employee Checkin", "employee": self.employee, "log_type": "OUT", "time": get_datetime(formatdate(self.date,'YYYY-mm-dd')+' '+format_time(shift.end_first_period)), "employee_checkin_request": self.name })) ec.insert() else: ec = frappe.get_doc(frappe._dict({ "doctype": "Employee Checkin", "employee": self.employee, "log_type": self.log_type, "time": get_datetime(formatdate(self.date,'YYYY-mm-dd')+' '+format_time(shift.start_time if self.log_type=='IN' else shift.end_first_period)), "employee_checkin_request": self.name })) ec.insert() elif self.period_type=='Second': if self.log_type=='ALL': ec = frappe.get_doc(frappe._dict({ "doctype": "Employee Checkin", "employee": self.employee, "log_type": "IN", "time": get_datetime(formatdate(self.date,'YYYY-mm-dd')+' '+format_time(shift.start_second_period)), "employee_checkin_request": self.name })) ec.insert() ec = frappe.get_doc(frappe._dict({ "doctype": "Employee Checkin", "employee": self.employee, "log_type": "OUT", "time": get_datetime(formatdate(self.date,'YYYY-mm-dd')+' '+format_time(shift.end_time)), "employee_checkin_request": self.name })) ec.insert() else: ec = frappe.get_doc(frappe._dict({ "doctype": "Employee Checkin", "employee": self.employee, "log_type": self.log_type, "time": get_datetime(formatdate(self.date,'YYYY-mm-dd')+' '+format_time(shift.start_second_period if self.log_type=='IN' else shift.end_time)), "employee_checkin_request": self.name })) ec.insert() elif self.period_type=='ALL': if self.log_type=='ALL': ec = frappe.get_doc(frappe._dict({ "doctype": "Employee Checkin", "employee": self.employee, "log_type": "IN", "time": get_datetime(formatdate(self.date,'YYYY-mm-dd')+' '+format_time(shift.start_time)), "employee_checkin_request": self.name })) ec.insert() ec = frappe.get_doc(frappe._dict({ "doctype": "Employee Checkin", "employee": self.employee, "log_type": "OUT", "time": get_datetime(formatdate(self.date,'YYYY-mm-dd')+' '+format_time(shift.end_first_period)), "employee_checkin_request": self.name })) ec.insert() ec = frappe.get_doc(frappe._dict({ "doctype": "Employee Checkin", "employee": self.employee, "log_type": "IN", "time": get_datetime(formatdate(self.date,'YYYY-mm-dd')+' '+format_time(shift.start_second_period)), "employee_checkin_request": self.name })) ec.insert() ec = frappe.get_doc(frappe._dict({ "doctype": "Employee Checkin", "employee": self.employee, "log_type": "OUT", "time": get_datetime(formatdate(self.date,'YYYY-mm-dd')+' '+format_time(shift.end_time)), "employee_checkin_request": self.name })) ec.insert() else: frappe.throw(_("""If the Period Type equal ALL, the Log Type should to be ALL""")) else: if self.log_type=='ALL': ec = frappe.get_doc(frappe._dict({ "doctype": "Employee Checkin", "employee": self.employee, "log_type": "IN", "time": get_datetime(formatdate(self.date,'YYYY-mm-dd')+' '+format_time(shift.start_time)), "employee_checkin_request": self.name })) ec.insert() ec = frappe.get_doc(frappe._dict({ "doctype": "Employee Checkin", "employee": self.employee, "log_type": "OUT", "time": get_datetime(formatdate(self.date,'YYYY-mm-dd')+' '+format_time(shift.end_time)), "employee_checkin_request": self.name })) ec.insert() else: ec = frappe.get_doc(frappe._dict({ "doctype": "Employee Checkin", "employee": self.employee, "log_type": self.log_type, "time": get_datetime(formatdate(self.date,'YYYY-mm-dd')+' '+format_time(shift.start_time if self.log_type=='IN' else shift.end_time)), "employee_checkin_request": self.name })) ec.insert()
def get_last_created(self, doctype): last_record = self.get_all(doctype, ('creation'), limit=1, order_by='creation desc') if last_record: return get_datetime(last_record[0].creation) else: return None
def set_first_response_time(communication, method): if communication.get('reference_doctype') == "Issue": issue = get_parent_doc(communication) if is_first_response(issue) and issue.service_level_agreement: first_response_time = calculate_first_response_time(issue, get_datetime(issue.first_responded_on)) issue.db_set("first_response_time", first_response_time)
def validate_timings(self): if self.to_time and self.from_time and get_datetime(self.to_time) <= get_datetime(self.from_time): frappe.throw(_("To Time must be greater than From Time"), NegativeHoursError)
def test_get_functions(self): # Test round-trip through getdate, get_datetime and get_time self.assertEqual(test_date_obj, get_datetime(test_datetime)) self.assertEqual(test_date_obj.date(), getdate(test_date)) self.assertEqual(test_date_obj.time(), get_time(test_time))
def get_to_time(self, data): return get_datetime(data.from_time) + timedelta(hours=data.hours)
def complete_test(data): """Endpoint para calcular los resultados BIG5, los resultados se guardan en `Big Five Results` y buscar que perfil de personalidad se adecua a los resultados""" try: res = json.loads(data) # DEBUG: # with open('respuestas.json', 'w') as f: # f.write(json.dumps(res, indent=2)) # Debe ser 100 total_questions = len(res.get('extraversion')) + len(res.get('agreeableness')) + len(res.get('conscientiousness')) + \ len(res.get('neuroticism')) + len(res.get('openness')) # Deben completarse las 100 preguntar para completar el proceso if total_questions != 100: return False, f'{total_questions} {_("de")} 100 {_("fueron respondidas, por favor responda todas las preguntas y presione completar")}' results = { 'total_extraversion': sum(x['value'] for x in res.get('extraversion')), # extraversión 'total_agreeableness': sum(x['value'] for x in res.get('agreeableness')), # simpatía 'total_conscientiousness': sum(x['value'] for x in res.get('conscientiousness')), # concienciación 'total_neuroticism': sum(x['value'] for x in res.get('neuroticism')), # neuroticismo 'total_openness': sum(x['value'] for x in res.get('openness')), # apertura 'user': frappe.db.get_value('User', {'name': frappe.session.user}, 'full_name'), 'datetimetest': str(get_datetime()) } # DATOS PRUEBA # results = { # 'total_extraversion': 62, # extraversión # 'total_agreeableness': 56, # simpatía # 'total_conscientiousness': 63, # concienciación # 'total_neuroticism': 57, # neuroticismo # 'total_openness': 63, # apertura # 'user': frappe.db.get_value('User', {'name': frappe.session.user}, 'full_name'), # 'datetimetest': str(get_datetime()) # } # Los resultados se asignan a variables, para no repetir el acceso al dict origen res_extraversion = cint(res.get('total_extraversion')) res_agreeableness = cint(res.get('total_agreeableness')) res_conscientiousness = cint(res.get('total_conscientiousness')) res_neuroticism = cint(res.get('total_neuroticism')) res_openness = cint(res.get('total_openness')) # Los resultados se comparan con los perfiles de personalidad ya establecidos en ERP para obtener el que mejor # que se adapte a la persona. NOTA: pueden ser varios estos se guardaran en una tabla hija de `Big Five Results` query_str = f"""SELECT PF.name AS profile FROM `tabPersonality Profile` AS PF WHERE ({res_openness} >= PF.minimum_result_for_openness AND {res_openness} <= PF.maximun_result_for_openness) AND ({res_neuroticism} >= PF.minimum_result_for_neuroticism AND {res_neuroticism} <= PF.maximun_result_for_neuroticism) AND ({res_agreeableness} >= PF.minimum_result_for_agreeableness AND {res_agreeableness} <= PF.maximun_result_for_agreeableness) AND ({res_conscientiousness} >= PF.minimum_result_for_conscientiousness AND {res_conscientiousness} <= PF.maximun_result_for_conscientiousness) AND ({res_extraversion} >= PF.minimum_result_for_extraversion AND {res_extraversion} <= PF.maximum_result_for_extraversion);""" ok_profiles = frappe.db.sql(query_str, as_dict=True) # DEBUG: # with open('ok_profiles_b5.json', 'w') as f: # f.write(json.dumps(ok_profiles, indent=2)) # Se registran los resultados doc = frappe.get_doc({ 'doctype': 'Big Five Results', 'completed_from': 'ERP', 'completed_by': frappe.session.user, 'date_time': results.get('datetimetest'), 'results': [ { 'category': 'EXTRAVERSION', 'score': results.get('total_extraversion') }, { 'category': 'AGREEABLENESS', 'score': results.get('total_agreeableness') }, { 'category': 'CONSCIENTIOUSNESS', 'score': results.get('total_conscientiousness') }, { 'category': 'NEUROTICISM', 'score': results.get('total_neuroticism') }, { 'category': 'OPENNESS', 'score': results.get('total_openness') }, ], 'recommended_profiles': ok_profiles, 'docstatus': 1 }) doc.insert(ignore_permissions=True) return True, results except: frappe.msgprint(msg=_( f'Calculo no pudo ser completado, si la falla persiste copie o tome una captura de pantalla completo de todo este mensaje, \ y reportelo con soporte. \n <hr> <code>{frappe.get_traceback()}</code>' ), title=_('Process not completed'), indicator='red')
def prepare_filter_condition(self, f): """Returns a filter condition in the format: ifnull(`tabDocType`.`fieldname`, fallback) operator "value" """ f = get_filter(self.doctype, f) tname = ('`tab' + f.doctype + '`') if not tname in self.tables: self.append_table(tname) if 'ifnull(' in f.fieldname: column_name = f.fieldname else: column_name = '{tname}.{fname}'.format(tname=tname, fname=f.fieldname) can_be_null = True # prepare in condition if f.operator.lower() in ('ancestors of', 'descendants of', 'not ancestors of', 'not descendants of', 'subtree of', 'not subtree of'): values = f.value or '' # TODO: handle list and tuple # if not isinstance(values, (list, tuple)): # values = values.split(",") ref_doctype = f.doctype if frappe.get_meta(f.doctype).get_field(f.fieldname) is not None: ref_doctype = frappe.get_meta(f.doctype).get_field( f.fieldname).options result = [] lft, rgt = frappe.db.get_value(ref_doctype, f.value, ["lft", "rgt"]) lt_op, gt_op = ("<=", ">=") if f.operator.lower() in ( 'subtree of', 'not subtree of') else ("<", ">") # Get descendants elements of a DocType with a tree structure if f.operator.lower() in ('descendants of', 'not descendants of', 'subtree of', 'not subtree of'): result = frappe.db.sql_list( """select name from `tab{0}` where lft{1}%s and rgt{2}%s order by lft asc""".format( ref_doctype, lt_op, gt_op), (lft, rgt)) else: # Get ancestor elements of a DocType with a tree structure result = frappe.db.sql_list( """select name from `tab{0}` where lft{1}%s and rgt{2}%s order by lft desc""".format( ref_doctype, lt_op, gt_op), (lft, rgt)) fallback = "''" value = (frappe.db.escape((v or '').strip(), percent=False) for v in result) value = '("{0}")'.format('", "'.join(value)) # changing operator to IN as the above code fetches all the parent / child values and convert into tuple # which can be directly used with IN operator to query. f.operator = 'not in' if f.operator.lower() in ( 'not ancestors of', 'not descendants of') else 'in' elif f.operator.lower() in ('in', 'not in'): values = f.value or '' if isinstance(values, frappe.string_types): values = values.split(",") fallback = "''" value = (frappe.db.escape((v or '').strip(), percent=False) for v in values) value = '("{0}")'.format('", "'.join(value)) else: df = frappe.get_meta(f.doctype).get("fields", {"fieldname": f.fieldname}) df = df[0] if df else None if df and df.fieldtype in ("Check", "Float", "Int", "Currency", "Percent"): can_be_null = False if f.operator.lower() == 'between' and \ (f.fieldname in ('creation', 'modified') or (df and (df.fieldtype=="Date" or df.fieldtype=="Datetime"))): value = get_between_date_filter(f.value, df) fallback = "'0000-00-00 00:00:00'" elif df and df.fieldtype == "Date": value = getdate(f.value).strftime("%Y-%m-%d") fallback = "'0000-00-00'" elif (df and df.fieldtype == "Datetime") or isinstance( f.value, datetime): value = get_datetime(f.value).strftime("%Y-%m-%d %H:%M:%S.%f") fallback = "'0000-00-00 00:00:00'" elif df and df.fieldtype == "Time": value = get_time(f.value).strftime("%H:%M:%S.%f") fallback = "'00:00:00'" elif f.operator.lower() == "is": if f.value == 'set': f.operator = '!=' elif f.value == 'not set': f.operator = '=' value = "" fallback = '""' can_be_null = True if 'ifnull' not in column_name: column_name = 'ifnull({}, {})'.format( column_name, fallback) elif f.operator.lower() in ("like", "not like") or ( isinstance(f.value, string_types) and (not df or df.fieldtype not in ["Float", "Int", "Currency", "Percent", "Check"])): value = "" if f.value == None else f.value fallback = '""' if f.operator.lower() in ("like", "not like") and isinstance( value, string_types): # because "like" uses backslash (\) for escaping value = value.replace("\\", "\\\\").replace("%", "%%") else: value = flt(f.value) fallback = 0 # put it inside double quotes if isinstance( value, string_types) and not f.operator.lower() == 'between': value = '"{0}"'.format(frappe.db.escape(value, percent=False)) if (self.ignore_ifnull or not can_be_null or (f.value and f.operator.lower() in ('=', 'like')) or 'ifnull(' in column_name.lower()): condition = '{column_name} {operator} {value}'.format( column_name=column_name, operator=f.operator, value=value) else: condition = 'ifnull({column_name}, {fallback}) {operator} {value}'.format( column_name=column_name, fallback=fallback, operator=f.operator, value=value) return condition
def test_is_dormant(self): self.assertTrue(is_dormant(check_time=get_datetime("2100-01-01 00:00:00"))) self.assertTrue(is_dormant(check_time=add_days(frappe.db.get_last_created("Activity Log"), 5))) self.assertFalse(is_dormant(check_time=frappe.db.get_last_created("Activity Log")))
def onload(self): self.set_onload('update_time', get_datetime())
def validate_overlap_for_workstation(self, args, row): # get the last record based on the to time from the job card data = self.get_overlap_for(args, check_next_available_slot=True) if data: row.planned_start_time = get_datetime( data.to_time + get_mins_between_operations())
def create_process_loan_security_shortfall(): if check_for_secured_loans(): process = frappe.new_doc("Process Loan Security Shortfall") process.update_time = get_datetime() process.submit()
def set_thread(self, communication, email): """Appends communication to parent based on thread ID. Will extract parent communication and will link the communication to the reference of that communication. Also set the status of parent transaction to Open or Replied. If no thread id is found and `append_to` is set for the email account, it will create a new parent transaction (e.g. Issue)""" in_reply_to = (email.mail.get("In-Reply-To") or "").strip(" <>") parent = None if self.append_to: # set subject_field and sender_field meta_module = frappe.get_meta_module(self.append_to) meta = frappe.get_meta(self.append_to) subject_field = getattr(meta_module, "subject_field", "subject") if not meta.get_field(subject_field): subject_field = None sender_field = getattr(meta_module, "sender_field", "sender") if not meta.get_field(sender_field): sender_field = None if in_reply_to: if "@{0}".format(frappe.local.site) in in_reply_to: # reply to a communication sent from the system in_reply_to, domain = in_reply_to.split("@", 1) if frappe.db.exists("Communication", in_reply_to): parent = frappe.get_doc("Communication", in_reply_to) if parent.reference_name: parent = frappe.get_doc(parent.reference_doctype, parent.reference_name) if not parent and self.append_to and sender_field: if subject_field: # try and match by subject and sender # if sent by same sender with same subject, # append it to old coversation subject = strip( re.sub("^\s*(Re|RE)[^:]*:\s*", "", email.subject)) parent = frappe.db.get_all( self.append_to, filters={ sender_field: email.from_email, subject_field: ("like", "%{0}%".format(subject)), "creation": (">", (get_datetime() - relativedelta(days=10)).strftime(DATE_FORMAT)) }, fields="name") # match only subject field # when the from_email is of a user in the system # and subject is atleast 10 chars long if not parent and len(subject) > 10 and is_system_user( email.from_email): parent = frappe.db.get_all( self.append_to, filters={ subject_field: ("like", "%{0}%".format(subject)), "creation": (">", (get_datetime() - relativedelta(days=10)).strftime(DATE_FORMAT)) }, fields="name") if parent: parent = frappe.get_doc(self.append_to, parent[0].name) if not parent and self.append_to: # no parent found, but must be tagged # insert parent type doc parent = frappe.new_doc(self.append_to) if subject_field: parent.set(subject_field, email.subject) if sender_field: parent.set(sender_field, email.from_email) parent.flags.ignore_mandatory = True try: parent.insert(ignore_permissions=True) except frappe.DuplicateEntryError: # try and find matching parent parent_name = frappe.db.get_value( self.append_to, {sender_field: email.from_email}) if parent_name: parent.name = parent_name else: parent = None # NOTE if parent isn't found and there's no subject match, it is likely that it is a new conversation thread and hence is_first = True communication.is_first = True if parent: communication.reference_doctype = parent.doctype communication.reference_name = parent.name
def _validate_appointment_times(doc): practitioner_schedules = get_practitioner_schedules( doc.physician, doc.appointment_date) appointment_time = get_datetime(doc.appointment_time).strftime('%H:%M') if appointment_time not in practitioner_schedules: frappe.throw(_('Selected appointment time is not available'))
def check_workstation_time(self, row): workstation_doc = frappe.get_cached_doc("Workstation", self.workstation) if (not workstation_doc.working_hours or cint( frappe.db.get_single_value("Manufacturing Settings", "allow_overtime"))): if get_datetime(row.planned_end_time) < get_datetime( row.planned_start_time): row.planned_end_time = add_to_date(row.planned_start_time, minutes=row.time_in_mins) row.remaining_time_in_mins = 0.0 else: row.remaining_time_in_mins -= time_diff_in_minutes( row.planned_end_time, row.planned_start_time) self.update_time_logs(row) return start_date = getdate(row.planned_start_time) start_time = get_time(row.planned_start_time) new_start_date = workstation_doc.validate_workstation_holiday( start_date) if new_start_date != start_date: row.planned_start_time = datetime.datetime.combine( new_start_date, start_time) start_date = new_start_date total_idx = len(workstation_doc.working_hours) for i, time_slot in enumerate(workstation_doc.working_hours): workstation_start_time = datetime.datetime.combine( start_date, get_time(time_slot.start_time)) workstation_end_time = datetime.datetime.combine( start_date, get_time(time_slot.end_time)) if (get_datetime(row.planned_start_time) >= workstation_start_time and get_datetime( row.planned_start_time) <= workstation_end_time): time_in_mins = time_diff_in_minutes(workstation_end_time, row.planned_start_time) # If remaining time fit in workstation time logs else split hours as per workstation time if time_in_mins > row.remaining_time_in_mins: row.planned_end_time = add_to_date( row.planned_start_time, minutes=row.remaining_time_in_mins) row.remaining_time_in_mins = 0 else: row.planned_end_time = add_to_date(row.planned_start_time, minutes=time_in_mins) row.remaining_time_in_mins -= time_in_mins self.update_time_logs(row) if total_idx != (i + 1) and row.remaining_time_in_mins > 0: row.planned_start_time = datetime.datetime.combine( start_date, get_time(workstation_doc.working_hours[i + 1].start_time)) if row.remaining_time_in_mins > 0: start_date = add_days(start_date, 1) row.planned_start_time = datetime.datetime.combine( start_date, get_time(workstation_doc.working_hours[0].start_time))
def test_response_time_and_resolution_time_based_on_different_sla(self): creation = get_datetime("2019-03-04 12:00") # make issue with customer specific SLA customer = create_customer("_Test Customer", "__Test SLA Customer Group", "__Test SLA Territory") issue = make_issue(creation, "_Test Customer", 1) self.assertEqual(issue.response_by, get_datetime("2019-03-04 14:00")) self.assertEqual(issue.resolution_by, get_datetime("2019-03-04 15:00")) # make issue with customer_group specific SLA customer = create_customer("__Test Customer", "_Test SLA Customer Group", "__Test SLA Territory") issue = make_issue(creation, "__Test Customer", 2) self.assertEqual(issue.response_by, get_datetime("2019-03-04 14:00")) self.assertEqual(issue.resolution_by, get_datetime("2019-03-04 15:00")) # make issue with territory specific SLA customer = create_customer( "___Test Customer", "__Test SLA Customer Group", "_Test SLA Territory" ) issue = make_issue(creation, "___Test Customer", 3) self.assertEqual(issue.response_by, get_datetime("2019-03-04 14:00")) self.assertEqual(issue.resolution_by, get_datetime("2019-03-04 15:00")) # make issue with default SLA issue = make_issue(creation=creation, index=4) self.assertEqual(issue.response_by, get_datetime("2019-03-04 16:00")) self.assertEqual(issue.resolution_by, get_datetime("2019-03-04 18:00")) # make issue with default SLA before working hours creation = get_datetime("2019-03-04 7:00") issue = make_issue(creation=creation, index=5) self.assertEqual(issue.response_by, get_datetime("2019-03-04 14:00")) self.assertEqual(issue.resolution_by, get_datetime("2019-03-04 16:00")) # make issue with default SLA after working hours creation = get_datetime("2019-03-04 20:00") issue = make_issue(creation, index=6) self.assertEqual(issue.response_by, get_datetime("2019-03-06 14:00")) self.assertEqual(issue.resolution_by, get_datetime("2019-03-06 16:00")) # make issue with default SLA next day creation = get_datetime("2019-03-04 14:00") issue = make_issue(creation=creation, index=7) self.assertEqual(issue.response_by, get_datetime("2019-03-04 18:00")) self.assertEqual(issue.resolution_by, get_datetime("2019-03-06 12:00")) frappe.flags.current_time = get_datetime("2019-03-04 15:00") issue.status = "Closed" issue.save() self.assertEqual(issue.agreement_status, "Fulfilled")
def validate(self): if not self.time: self.time = get_datetime()
def move_to_next_non_overlapping_slot(self): """If in overlap, set start as the end point of the overlapping time log""" overlapping = self.get_overlap_for("workstation") if overlapping: self.from_time = get_datetime( overlapping.to_time) + relativedelta(minutes=10)
def process_route(self, optimize): """ Estimate the arrival times for each stop in the Delivery Trip. If `optimize` is True, the stops will be re-arranged, based on the optimized order, before estimating the arrival times. Args: optimize (bool): True if route needs to be optimized, else False """ departure_datetime = get_datetime(self.departure_time) route_list = self.form_route_list(optimize) # For locks, maintain idx count while looping through route list idx = 0 for route in route_list: directions = self.get_directions(route, optimize) if directions: if optimize and len(directions.get("waypoint_order")) > 1: self.rearrange_stops(directions.get("waypoint_order"), start=idx) # Avoid estimating last leg back to the home address legs = directions.get( "legs" )[:-1] if route == route_list[-1] else directions.get("legs") # Google Maps returns the legs in the optimized order for leg in legs: delivery_stop = self.delivery_stops[idx] delivery_stop.lat, delivery_stop.lng = leg.get( "end_location", {}).values() delivery_stop.uom = self.default_distance_uom distance = leg.get("distance", {}).get("value", 0.0) # in meters delivery_stop.distance = distance * self.uom_conversion_factor duration = leg.get("duration", {}).get("value", 0) estimated_arrival = departure_datetime + datetime.timedelta( seconds=duration) delivery_stop.estimated_arrival = estimated_arrival stop_delay = frappe.db.get_single_value( "Delivery Settings", "stop_delay") departure_datetime = estimated_arrival + datetime.timedelta( minutes=cint(stop_delay)) idx += 1 # Include last leg in the final distance calculation self.uom = self.default_distance_uom total_distance = sum([ leg.get("distance", {}).get("value", 0.0) for leg in directions.get("legs") ]) # in meters self.total_distance = total_distance * self.uom_conversion_factor else: idx += len(route) - 1 self.save()
def approve(self): if self.status == "Approved" and not self.unpledge_time: self.update_loan_status() self.db_set('unpledge_time', get_datetime())
def _destruct_datetime(dt): _dt = get_datetime(dt) return {"posting_date": _dt.date(), "posting_time": _dt.time()}
def validate_unpledge_qty(self): from erpnext.loan_management.doctype.loan_security_shortfall.loan_security_shortfall import ( get_ltv_ratio, ) pledge_qty_map = get_pledged_security_qty(self.loan) ltv_ratio_map = frappe._dict( frappe.get_all("Loan Security Type", fields=["name", "loan_to_value_ratio"], as_list=1)) loan_security_price_map = frappe._dict( frappe.get_all("Loan Security Price", fields=["loan_security", "loan_security_price"], filters={ "valid_from": ("<=", get_datetime()), "valid_upto": (">=", get_datetime()) }, as_list=1)) loan_details = frappe.get_value( "Loan", self.loan, [ 'total_payment', 'total_principal_paid', 'total_interest_payable', 'written_off_amount', 'disbursed_amount', 'status' ], as_dict=1) if loan_details.status == 'Disbursed': pending_principal_amount = flt(loan_details.total_payment) - flt(loan_details.total_interest_payable) \ - flt(loan_details.total_principal_paid) - flt(loan_details.written_off_amount) else: pending_principal_amount = flt(loan_details.disbursed_amount) - flt(loan_details.total_interest_payable) \ - flt(loan_details.total_principal_paid) - flt(loan_details.written_off_amount) security_value = 0 unpledge_qty_map = {} ltv_ratio = 0 for security in self.securities: pledged_qty = pledge_qty_map.get(security.loan_security, 0) if security.qty > pledged_qty: msg = _("Row {0}: {1} {2} of {3} is pledged against Loan {4}." ).format(security.idx, pledged_qty, security.uom, frappe.bold(security.loan_security), frappe.bold(self.loan)) msg += "<br>" msg += _("You are trying to unpledge more.") frappe.throw(msg, title=_("Loan Security Unpledge Error")) unpledge_qty_map.setdefault(security.loan_security, 0) unpledge_qty_map[security.loan_security] += security.qty for security in pledge_qty_map: if not ltv_ratio: ltv_ratio = get_ltv_ratio(security) qty_after_unpledge = pledge_qty_map.get( security, 0) - unpledge_qty_map.get(security, 0) current_price = loan_security_price_map.get(security) security_value += qty_after_unpledge * current_price if not security_value and flt(pending_principal_amount, 2) > 0: self._throw(security_value, pending_principal_amount, ltv_ratio) if security_value and flt( pending_principal_amount / security_value) * 100 > ltv_ratio: self._throw(security_value, pending_principal_amount, ltv_ratio)
def validate_timings(self): if self.to_time and self.from_time and get_datetime( self.to_time) < get_datetime(self.from_time): frappe.throw(_("From Time cannot be greater than To Time"))
def prepare_filter_condition(self, f): """Returns a filter condition in the format: ifnull(`tabDocType`.`fieldname`, fallback) operator "value" """ f = get_filter(self.doctype, f) tname = ('`tab' + f.doctype + '`') if not tname in self.tables: self.append_table(tname) if 'ifnull(' in f.fieldname: column_name = f.fieldname else: column_name = '{tname}.{fname}'.format(tname=tname, fname=f.fieldname) can_be_null = True # prepare in condition if f.operator.lower() in ('in', 'not in'): values = f.value or '' if not isinstance(values, (list, tuple)): values = values.split(",") fallback = "''" value = (frappe.db.escape((v or '').strip(), percent=False) for v in values) value = '("{0}")'.format('", "'.join(value)) else: df = frappe.get_meta(f.doctype).get("fields", {"fieldname": f.fieldname}) df = df[0] if df else None if df and df.fieldtype in ("Check", "Float", "Int", "Currency", "Percent"): can_be_null = False if f.operator.lower() == 'between' and \ (f.fieldname in ('creation', 'modified') or (df and (df.fieldtype=="Date" or df.fieldtype=="Datetime"))): value = get_between_date_filter(f.value, df) fallback = "'0000-00-00 00:00:00'" elif df and df.fieldtype=="Date": value = getdate(f.value).strftime("%Y-%m-%d") fallback = "'0000-00-00'" elif (df and df.fieldtype=="Datetime") or isinstance(f.value, datetime): value = get_datetime(f.value).strftime("%Y-%m-%d %H:%M:%S.%f") fallback = "'0000-00-00 00:00:00'" elif df and df.fieldtype=="Time": value = get_time(f.value).strftime("%H:%M:%S.%f") fallback = "'00:00:00'" elif f.operator.lower() in ("like", "not like") or (isinstance(f.value, string_types) and (not df or df.fieldtype not in ["Float", "Int", "Currency", "Percent", "Check"])): value = "" if f.value==None else f.value fallback = '""' if f.operator.lower() in ("like", "not like") and isinstance(value, string_types): # because "like" uses backslash (\) for escaping value = value.replace("\\", "\\\\").replace("%", "%%") else: value = flt(f.value) fallback = 0 # put it inside double quotes if isinstance(value, string_types) and not f.operator.lower() == 'between': value = '"{0}"'.format(frappe.db.escape(value, percent=False)) if (self.ignore_ifnull or not can_be_null or (f.value and f.operator.lower() in ('=', 'like')) or 'ifnull(' in column_name.lower()): condition = '{column_name} {operator} {value}'.format( column_name=column_name, operator=f.operator, value=value) else: condition = 'ifnull({column_name}, {fallback}) {operator} {value}'.format( column_name=column_name, fallback=fallback, operator=f.operator, value=value) return condition
def prepare_filter_condition(self, f): """Returns a filter condition in the format: ifnull(`tabDocType`.`fieldname`, fallback) operator "value" """ f = self.get_filter(f) tname = ('`tab' + f.doctype + '`') if not tname in self.tables: self.append_table(tname) # prepare in condition if f.operator in ('in', 'not in'): values = f.value if not isinstance(values, (list, tuple)): values = values.split(",") values = (frappe.db.escape(v.strip(), percent=False) for v in values) values = '("{0}")'.format('", "'.join(values)) condition = 'ifnull({tname}.{fname}, "") {operator} {value}'.format( tname=tname, fname=f.fieldname, operator=f.operator, value=values) else: df = frappe.get_meta(f.doctype).get("fields", {"fieldname": f.fieldname}) df = df[0] if df else None if df and df.fieldtype == "Date": value = getdate(f.value).strftime("%Y-%m-%d") fallback = "'0000-00-00'" elif df and df.fieldtype == "Datetime": value = get_datetime(f.value).strftime("%Y-%m-%d %H:%M:%S.%f") fallback = "'0000-00-00 00:00:00'" elif df and df.fieldtype == "Time": value = get_time(f.value).strftime("%H:%M:%S.%f") fallback = "'00:00:00'" elif f.operator in ("like", "not like") or ( isinstance(f.value, basestring) and (not df or df.fieldtype not in ["Float", "Int", "Currency", "Percent", "Check"])): value = "" if f.value == None else f.value fallback = '""' if f.operator in ("like", "not like") and isinstance( value, basestring): # because "like" uses backslash (\) for escaping value = value.replace("\\", "\\\\").replace("%", "%%") else: value = flt(f.value) fallback = 0 # put it inside double quotes if isinstance(value, basestring): value = '"{0}"'.format(frappe.db.escape(value, percent=False)) condition = 'ifnull({tname}.{fname}, {fallback}) {operator} {value}'.format( tname=tname, fname=f.fieldname, fallback=fallback, operator=f.operator, value=value) return condition
def move_to_next_day(self): """Move start and end time one day forward""" self.from_time = get_datetime(self.from_time) + relativedelta(day=1)
def create_recurring_profile(token, payerid): try: custom_redirect_to = None updating = False data, params, url = get_paypal_and_transaction_details(token) addons = data.get("addons") subscription_details = data.get("subscription_details") if data.get('subscription_id') and addons: updating = True manage_recurring_payment_profile_status(data['subscription_id'], 'Cancel', params, url) params.update({ "METHOD": "CreateRecurringPaymentsProfile", "PAYERID": payerid, "TOKEN": token, "DESC": data.get("description"), "BILLINGPERIOD": subscription_details.get("billing_period"), "BILLINGFREQUENCY": subscription_details.get("billing_frequency"), "AMT": data.get("amount") if data.get("subscription_amount") == data.get("amount") else data.get("subscription_amount"), "CURRENCYCODE": data.get("currency").upper(), "INITAMT": data.get("upfront_amount") }) status_changed_to = 'Completed' if data.get( "starting_immediately") or updating else 'Verified' starts_at = get_datetime(subscription_details.get( "start_date")) or frappe.utils.now_datetime() starts_at = starts_at.replace( tzinfo=pytz.timezone(frappe.utils.get_time_zone())).astimezone( pytz.utc) #"PROFILESTARTDATE": datetime.utcfromtimestamp(get_timestamp(starts_at)).isoformat() params.update({"PROFILESTARTDATE": starts_at.isoformat()}) response = make_post_request(url, data=params) if response.get("ACK")[0] == "Success": update_integration_request_status( token, { "profile_id": response.get("PROFILEID")[0], }, "Completed") if data.get("reference_doctype") and data.get("reference_docname"): data['subscription_id'] = response.get("PROFILEID")[0] frappe.flags.data = data custom_redirect_to = frappe.get_doc( data.get("reference_doctype"), data.get("reference_docname")).run_method( "on_payment_authorized", status_changed_to) frappe.db.commit() redirect_url = '/integrations/payment-success?doctype={0}&docname={1}'.format( data.get("reference_doctype"), data.get("reference_docname")) else: redirect_url = "/integrations/payment-failed" setup_redirect(data, redirect_url, custom_redirect_to) except Exception: frappe.log_error(frappe.get_traceback())
def handle_hold_time(self, status): if self.service_level_agreement: # set response and resolution variance as None as the issue is on Hold pause_sla_on = frappe.db.get_all( "Pause SLA On Status", fields=["status"], filters={"parent": self.service_level_agreement}) hold_statuses = [entry.status for entry in pause_sla_on] update_values = {} if hold_statuses: if self.status in hold_statuses and status not in hold_statuses: update_values[ 'on_hold_since'] = frappe.flags.current_time or now_datetime( ) if not self.first_responded_on: update_values['response_by'] = None update_values['response_by_variance'] = 0 update_values['resolution_by'] = None update_values['resolution_by_variance'] = 0 # calculate hold time when status is changed from any hold status to any non-hold status if self.status not in hold_statuses and status in hold_statuses: hold_time = self.total_hold_time if self.total_hold_time else 0 now_time = frappe.flags.current_time or now_datetime() last_hold_time = 0 if self.on_hold_since: # last_hold_time will be added to the sla variables last_hold_time = time_diff_in_seconds( now_time, self.on_hold_since) update_values['total_hold_time'] = hold_time + \ last_hold_time # re-calculate SLA variables after issue changes from any hold status to any non-hold status # add hold time to SLA variables start_date_time = get_datetime( self.service_level_agreement_creation) priority = get_priority(self) now_time = frappe.flags.current_time or now_datetime() if not self.first_responded_on: response_by = get_expected_time_for( parameter="response", service_level=priority, start_date_time=start_date_time) response_by = add_to_date( response_by, seconds=round(last_hold_time)) response_by_variance = round( time_diff_in_seconds(response_by, now_time)) update_values['response_by'] = response_by update_values['response_by_variance'] = response_by_variance + \ last_hold_time resolution_by = get_expected_time_for( parameter="resolution", service_level=priority, start_date_time=start_date_time) resolution_by = add_to_date(resolution_by, seconds=round(last_hold_time)) resolution_by_variance = round( time_diff_in_seconds(resolution_by, now_time)) update_values['resolution_by'] = resolution_by update_values['resolution_by_variance'] = resolution_by_variance + \ last_hold_time update_values['on_hold_since'] = None self.db_set(update_values)
def get_doc(start_idx): if doctypes: doc = {} for idx in range(start_idx, len(rows)): if (not doc) or main_doc_empty(rows[idx]): for dt, parentfield in doctypes: d = {} for column_idx in column_idx_to_fieldname[(dt, parentfield)]: try: fieldname = column_idx_to_fieldname[(dt, parentfield)][column_idx] fieldtype = column_idx_to_fieldtype[(dt, parentfield)][column_idx] d[fieldname] = rows[idx][column_idx] if fieldtype in ("Int", "Check"): d[fieldname] = cint(d[fieldname]) elif fieldtype in ("Float", "Currency", "Percent"): d[fieldname] = flt(d[fieldname]) elif fieldtype == "Date": if d[fieldname] and isinstance(d[fieldname], basestring): d[fieldname] = getdate(parse_date(d[fieldname])) elif fieldtype == "Datetime": if d[fieldname]: if " " in d[fieldname]: _date, _time = d[fieldname].split() else: _date, _time = d[fieldname], '00:00:00' _date = parse_date(d[fieldname]) d[fieldname] = get_datetime(_date + " " + _time) else: d[fieldname] = None elif fieldtype in ("Image", "Attach Image", "Attach"): # added file to attachments list attachments.append(d[fieldname]) elif fieldtype in ("Link", "Dynamic Link") and d[fieldname]: # as fields can be saved in the number format(long type) in data import template d[fieldname] = cstr(d[fieldname]) except IndexError: pass # scrub quotes from name and modified if d.get("name") and d["name"].startswith('"'): d["name"] = d["name"][1:-1] if sum([0 if not val else 1 for val in d.values()]): d['doctype'] = dt if dt == doctype: doc.update(d) else: if not overwrite: d['parent'] = doc["name"] d['parenttype'] = doctype d['parentfield'] = parentfield doc.setdefault(d['parentfield'], []).append(d) else: break return doc else: doc = frappe._dict(zip(columns, rows[start_idx][1:])) doc['doctype'] = doctype return doc
def onload(self): self.set_onload("update_time", get_datetime())