Exemple #1
0
	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
Exemple #2
0
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
Exemple #7
0
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)
Exemple #8
0
	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)
Exemple #9
0
	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)
		}
Exemple #11
0
	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)
Exemple #13
0
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
Exemple #14
0
	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"))
Exemple #16
0
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
Exemple #17
0
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)
Exemple #20
0
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")
Exemple #21
0
    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
Exemple #22
0
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")
Exemple #25
0
	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
Exemple #28
0
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)
Exemple #29
0
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
Exemple #30
0
	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()
Exemple #32
0
	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
Exemple #33
0
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)
Exemple #34
0
	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)
Exemple #35
0
 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)
Exemple #37
0
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')
Exemple #38
0
    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
Exemple #39
0
	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())
Exemple #41
0
 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()
Exemple #43
0
    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
Exemple #44
0
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'))
Exemple #45
0
    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))
Exemple #46
0
	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")
Exemple #47
0
 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)
Exemple #49
0
    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"))
Exemple #54
0
	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
Exemple #55
0
    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)
Exemple #57
0
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())
Exemple #58
0
    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)
Exemple #59
0
	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())