def get_history_records(customer_agreement): total_transaction_amount = "" history_record_dict = frappe.db.sql("""select payment_id,due_date,payment_date, monthly_rental_amount,"balance" as balance,pmt, "asso" as associate, "late" as late_days,total_transaction_amount from `tabPayments Record` where parent ='{0}' and check_box_of_submit = 1 order by idx""".format(customer_agreement),as_dict=1) # balance = frappe.db.get_value("Customer Agreement",{"name":customer_agreement},"balance") agreement = frappe.get_doc("Customer Agreement",customer_agreement) balance = "{0:.2f}".format(float(agreement.agreement_period) * float(agreement.monthly_rental_payment)) for i in history_record_dict: i['associate'] = frappe.session.user total_transaction_amount = i["total_transaction_amount"] i["total_transaction_amount"] = total_transaction_amount.split("/")[0] if total_transaction_amount else 0 i["total_calculated_payment_amount"] = total_transaction_amount.split("/")[1] if total_transaction_amount else 0 if float(balance) > float(i["monthly_rental_amount"]): i["balance"] = "{0:.2f}".format(float(balance) - float(i['monthly_rental_amount'])) balance = float(balance) - float(i['monthly_rental_amount']) if date_diff(i['payment_date'],i['due_date']) > 0: i["late_days"] = "+" + str(date_diff(i['payment_date'],i['due_date'])) elif date_diff(i['payment_date'],i['due_date']) == 0: i["late_days"] = 0 elif date_diff(i['payment_date'],i['due_date']) < 0: i["late_days"] = date_diff(i['payment_date'],i['due_date']) print history_record_dict,"history_record_dict history_record_dict","\n\n\n\n\n\n" return history_record_dict
def execute(filters=None): columns = get_columns() item_details = get_fifo_queue(filters) to_date = filters["to_date"] data = [] for item, item_dict in item_details.items(): fifo_queue = item_dict["fifo_queue"] details = item_dict["details"] if not fifo_queue: continue average_age = get_average_age(fifo_queue, to_date) earliest_age = date_diff(to_date, fifo_queue[0][1]) latest_age = date_diff(to_date, fifo_queue[-1][1]) data.append( [ item, details.item_name, details.description, details.item_group, details.brand, average_age, earliest_age, latest_age, details.stock_uom, ] ) return columns, data
def execute(filters=None): columns = get_columns(filters) items, item_map = get_item_details(filters) item_details = get_fifo_queue(filters, items) to_date = filters["to_date"] data = [] for item, item_dict in iteritems(item_details): fifo_queue = item_dict["fifo_queue"] details = item_dict["details"] if not fifo_queue: continue average_age = get_average_age(fifo_queue, to_date) earliest_age = date_diff(to_date, fifo_queue[0][1]) latest_age = date_diff(to_date, fifo_queue[-1][1]) item_detail_dict = item_map[details.name] row = [details.name, item_detail_dict["desc"]] if filters.get("show_ageing_warehouse_wise"): row.append(details.warehouse) row.extend([item_dict.get("total_qty"), average_age, earliest_age, latest_age, item_detail_dict["stock_uom"], item_detail_dict["rm"], item_detail_dict["bm"], item_detail_dict["tt"], item_detail_dict["brand"], item_detail_dict["quality"], item_detail_dict["spl"], item_detail_dict["d1"], item_detail_dict["w1"], item_detail_dict["l1"], item_detail_dict["d2"], item_detail_dict["l2"], item_detail_dict["zn"]]) data.append(row) return columns, data
def validate_service_stop_date(doc): ''' Validates service_stop_date for Purchase Invoice and Sales Invoice ''' enable_check = "enable_deferred_revenue" \ if doc.doctype=="Sales Invoice" else "enable_deferred_expense" old_stop_dates = {} old_doc = frappe.db.get_all("{0} Item".format(doc.doctype), {"parent": doc.name}, ["name", "service_stop_date"]) for d in old_doc: old_stop_dates[d.name] = d.service_stop_date or "" for item in doc.items: if not item.get(enable_check): continue if item.service_stop_date: if date_diff(item.service_stop_date, item.service_start_date) < 0: frappe.throw(_("Service Stop Date cannot be before Service Start Date")) if date_diff(item.service_stop_date, item.service_end_date) > 0: frappe.throw(_("Service Stop Date cannot be after Service End Date")) if old_stop_dates and old_stop_dates.get(item.name) and item.service_stop_date!=old_stop_dates[item.name]: frappe.throw(_("Cannot change Service Stop Date for item in row {0}".format(item.idx)))
def check_date_diff_of_first_and_second_month_due_date(self): due_date_of_next_month = datetime.strptime(self.due_date_of_next_month, '%Y-%m-%dT%H:%M:%S.%fZ') if isinstance(self.due_date_of_next_month, unicode) else getdate(self.due_date_of_next_month) diff_of_first_and_second_due_date = date_diff(due_date_of_next_month,self.date) if date_diff(due_date_of_next_month,self.date) > 44 : self.due_date_of_next_month = str(self.get_next_due_date(due_date_of_next_month,-1))+"T00:00:00.000Z" #frappe.throw("Decrease Payment Day") if date_diff(due_date_of_next_month,self.date) <= 14: self.due_date_of_next_month = str(self.get_next_due_date(due_date_of_next_month,1))+"T00:00:00.000Z"
def get_period_factor(self, period_start, period_end, start_date=None, end_date=None): payroll_days = date_diff(period_end, period_start) + 1 if start_date and end_date: salary_days = date_diff(end_date, start_date) + 1 return flt(payroll_days)/flt(salary_days) # if period configured for a year and monthly frequency return 12 to make tax calc consistent if 360 <= payroll_days <= 370 and self.payroll_frequency == "Monthly": return 12 salary_days = date_diff(self.end_date, self.start_date) + 1 return flt(payroll_days)/flt(salary_days)
def get_amount(self, sal_start_date, sal_end_date): start_date = getdate(sal_start_date) end_date = getdate(sal_end_date) total_days = date_diff(getdate(self.to_date), getdate(self.from_date)) + 1 amount_per_day = self.amount / total_days if getdate(sal_start_date) <= getdate(self.from_date): start_date = getdate(self.from_date) if getdate(sal_end_date) > getdate(self.to_date): end_date = getdate(self.to_date) no_of_days = date_diff(getdate(end_date), getdate(start_date)) + 1 return amount_per_day * no_of_days
def get_number_of_leave_days(employee, leave_type, from_date, to_date, half_day = None, half_day_date = None): number_of_days = 0 if cint(half_day) == 1: if from_date == to_date: number_of_days = 0.5 else: number_of_days = date_diff(to_date, from_date) + .5 else: number_of_days = date_diff(to_date, from_date) + 1 if not frappe.db.get_value("Leave Type", leave_type, "include_holiday"): number_of_days = flt(number_of_days) - flt(get_holidays(employee, from_date, to_date)) return number_of_days
def create_event(data): response = '' request_type="POST" url = "%s/createEvent"%get_base_url() event_data={ "event_title": data.get('event_title'), "profile_id": data.get('profile_id'), "str_event_date": data.get('event_date'), "received_from": "Desktop", "event_symptoms" : data.get('complaints'), "event_descripton": data.get('event_descripton') } event_date = datetime.datetime.strptime(event_data.get('str_event_date'), "%d/%m/%Y").strftime('%Y-%m-%d') if date_diff(event_date, nowdate()) > 0: frappe.msgprint("Event Date should be past or current") return {"exe":"Event Date should be past or current"} else: response=get_response(url, json.dumps(event_data), request_type) make_log(json.loads(response.text).get('entityid'),"Event","Create","Event Created") return json.loads(response.text)
def set_rates(self): self.net_total = 0 for d in self.items: net_rate = 0.0 for i in range(date_diff(self.to_date, self.from_date)): day = add_days(self.from_date, i) if not d.item: continue day_rate = frappe.db.sql(""" select item.rate from `tabHotel Room Pricing Item` item, `tabHotel Room Pricing` pricing where item.parent = pricing.name and item.item = %s and %s between pricing.from_date and pricing.to_date""", (d.item, day)) if day_rate: net_rate += day_rate[0][0] else: frappe.throw( _("Please set Hotel Room Rate on {}".format( frappe.format(day, dict(fieldtype="Date")))), exc=HotelRoomPricingNotSetError) d.rate = net_rate d.amount = net_rate * flt(d.qty) self.net_total += d.amount
def get_number_of_days(end_date=None, start_date=None): if start_date and end_date: num_of_days = date_diff(start_date, end_date) else: num_of_days = 0 return num_of_days
def get_leave_details(self, joining_date=None, relieving_date=None, lwp=None): if not self.fiscal_year: # if default fiscal year is not set, get from nowdate self.fiscal_year = get_fiscal_year(nowdate())[0] if not self.month: self.month = "%02d" % getdate(nowdate()).month self.set_month_dates() if not joining_date: joining_date, relieving_date = frappe.db.get_value("Employee", self.employee, ["date_of_joining", "relieving_date"]) holidays = self.get_holidays_for_employee(self.start_date, self.end_date) working_days = date_diff(self.end_date, self.start_date) + 1 if not cint(frappe.db.get_value("HR Settings", None, "include_holidays_in_total_working_days")): working_days -= len(holidays) if working_days < 0: frappe.throw(_("There are more holidays than working days this month.")) if not lwp: lwp = self.calculate_lwp(holidays, working_days) self.total_days_in_month = working_days self.leave_without_pay = lwp payment_days = flt(self.get_payment_days(joining_date, relieving_date)) - flt(lwp) self.payment_days = payment_days > 0 and payment_days or 0
def execute(filters=None): if not filters: filters = {} from_date = get_first_day(filters["month"] + '-' + filters["year"]) to_date = get_last_day(filters["month"] + '-' + filters["year"]) total_days_in_month = date_diff(to_date, from_date) +1 columns = get_columns(total_days_in_month) students = get_student_group_students(filters.get("student_group"),1) students_list = get_students_list(students) att_map = get_attendance_list(from_date, to_date, filters.get("student_group"), students_list) data = [] for stud in students: row = [stud.student, stud.student_name] student_status = frappe.db.get_value("Student", stud.student, "enabled") date = from_date total_p = total_a = 0.0 for day in range(total_days_in_month): status="None" if att_map.get(stud.student): status = att_map.get(stud.student).get(date, "None") elif not student_status: status = "Inactive" else: status = "None" status_map = {"Present": "P", "Absent": "A", "None": "", "Inactive":"-"} row.append(status_map[status]) if status == "Present": total_p += 1 elif status == "Absent": total_a += 1 date = add_days(date, 1) row += [total_p, total_a] data.append(row) return columns, data
def get_context(self, context): paid_backers = get_paid_backers(self.bounty_backer) no_of_backers = len(paid_backers) if no_of_backers == 0: no_of_backers = 'Be the first to back this bounty' elif no_of_backers == 1: no_of_backers = str(no_of_backers) + ' backer' else: no_of_backers = str(no_of_backers) + ' backers' bounty_left = self.goal - self.bounty_collected if bounty_left > (self.goal * 0.1) or bounty_left < 0: bounty_left = self.goal * 0.1 # edit permission can_edit = self.owner == frappe.session.user context.no_cache = True context.no_breadcrumbs = False context.days_to_go = date_diff(self.end_date, nowdate()) context.paid_backers = ", ".join([backer.full_name or backer.user for backer in paid_backers]) context.no_of_backers = no_of_backers context.fmt_money = fmt_money context.bounty_left = bounty_left context.comment_list = get_comment_list(self.doctype, self.name) context.can_edit = can_edit
def make_new_invoice(ref_wrapper, posting_date): from erpnext.accounts.utils import get_fiscal_year new_invoice = frappe.copy_doc(ref_wrapper) mcount = month_map[ref_wrapper.recurring_type] invoice_period_from_date = get_next_date(ref_wrapper.invoice_period_from_date, mcount) # get last day of the month to maintain period if the from date is first day of its own month # and to date is the last day of its own month if (cstr(get_first_day(ref_wrapper.invoice_period_from_date)) == \ cstr(ref_wrapper.invoice_period_from_date)) and \ (cstr(get_last_day(ref_wrapper.invoice_period_to_date)) == \ cstr(ref_wrapper.invoice_period_to_date)): invoice_period_to_date = get_last_day(get_next_date(ref_wrapper.invoice_period_to_date, mcount)) else: invoice_period_to_date = get_next_date(ref_wrapper.invoice_period_to_date, mcount) new_invoice.update({ "posting_date": posting_date, "aging_date": posting_date, "due_date": add_days(posting_date, cint(date_diff(ref_wrapper.due_date, ref_wrapper.posting_date))), "invoice_period_from_date": invoice_period_from_date, "invoice_period_to_date": invoice_period_to_date, "fiscal_year": get_fiscal_year(posting_date)[0], "owner": ref_wrapper.owner, }) new_invoice.submit() return new_invoice
def mark_employee_times(self): employee_list = get_employees_list(self.department,self.branch,self.company) #days = date_diff(self.date, self.date)+1 days = date_diff(self.date, self.date)+1 for d in range(days): dt = add_days(cstr(self.date), d) for e in employee_list: leave = frappe.db.sql(""" select t1.name from `tabAttendance` t1 where t1.docstatus < 2 and t1.employee = %s and att_date = %s """, (e, dt)) if leave: frappe.msgprint(_("Employee %s has a pre-existing attendance record for this date: %s").format(e,dt)) else: attendance = frappe.new_doc("Attendance") attendance.employee = employee['employee'] attendance.employee_name = employee['employee_name'] attendance.att_date = self.date attendance.arrival_time = self.arrival_time attendance.departure_time = self.departure_time if self.company: attendance.company = self.company else: attendance.company = frappe.db.get_value("Employee", employee['employee'], "Company") attendance.submit()
def update_event(data): response = '' request_type="POST" url="%s/createupdateevent"%get_base_url() event_data = { "entityid":data.get('entityid'), "event_complaint_list":[], "profile_owner_name": frappe.db.get_value('User', {'profile_id':data.get('profile_id')}, 'first_name'), "status": "active", "event_diseasemontoring": False, "event_symptoms" :data.get('complaints'), "event_title": data.get('event_title'), "profile_id": data.get('profile_id'), "str_event_date": data.get('event_date'), "event_descripton": data.get('event_descripton'), "visit_files": data.get('dms_file_list'), "doctor_id": data.get('doctor_id'), "doctor_name": data.get("doctor_name"), "visit_descripton": data.get('event_descripton'), "received_from": "Desktop", "str_visit_date": data.get('visit_date'), "diagnosis_desc": data.get('diagnosis_desc') } import datetime event_date = datetime.datetime.strptime(event_data.get('str_event_date'), "%d/%m/%Y").strftime('%Y-%m-%d') visit_date = datetime.datetime.strptime(event_data.get('str_visit_date'), "%d/%m/%Y").strftime('%Y-%m-%d') if date_diff(visit_date, nowdate()) > 0: frappe.msgprint("Visit Date could not be greater than current date") return {"exe":"Visit Date could not be greater than current date"} elif date_diff(visit_date, event_date) < 0: frappe.msgprint("Visit Date should not be less than Event Date") return {"exe":"Event Date should be past or current"} else: response=get_response(url, json.dumps(event_data), request_type) make_log(data.get('entityid'),"Event","Update","Event Updated") if data.get('cname'): text_msg = "%s Has Updated Event,\n\n Team Healthsnapp"%data.get('cname') email_msg = "" from phr.templates.pages.profile import notify_about_linked_phrs notify_about_linked_phrs(data.get('pid'),email_msg,text_msg,"Event",data.get('cname')) return json.loads(response.text)
def get_number_of_leave_days(employee, leave_type, from_date, to_date, half_day=None): if half_day: return 0.5 number_of_days = date_diff(to_date, from_date) + 1 if not frappe.db.get_value("Leave Type", leave_type, "include_holiday"): number_of_days = flt(number_of_days) - flt(get_holidays(employee, from_date, to_date)) return number_of_days
def get_total_leave_days(self): """Calculates total leave days based on input and holidays""" ret = {"total_leave_days": 0.5} if not self.half_day: tot_days = date_diff(self.to_date, self.from_date) + 1 holidays = self.get_holidays() ret = {"total_leave_days": flt(tot_days) - flt(holidays)} return ret
def get_average_age(fifo_queue, to_date): batch_age = age_qty = total_qty = 0.0 for batch in fifo_queue: batch_age = date_diff(to_date, batch[1]) age_qty += batch_age * batch[0] total_qty += batch[0] return (age_qty / total_qty) if total_qty else 0.0
def make_time_logs(self): """Capacity Planning. Plan time logs based on earliest availablity of workstation after Planned Start Date. Time logs will be created and remain in Draft mode and must be submitted before manufacturing entry can be made.""" if not self.operations: return time_logs = [] plan_days = frappe.db.get_single_value("Manufacturing Settings", "capacity_planning_for_days") or 30 for i, d in enumerate(self.operations): self.set_operation_start_end_time(i, d) time_log = make_time_log(self.name, d.operation, d.planned_start_time, d.planned_end_time, flt(self.qty) - flt(d.completed_qty), self.project, d.workstation, operation_id=d.name) if d.workstation: # validate operating hours if workstation [not mandatory] is specified self.check_operation_fits_in_working_hours(d) original_start_time = time_log.from_time while True: _from_time = time_log.from_time try: time_log.save() break except WorkstationHolidayError: time_log.move_to_next_day() except NotInWorkingHoursError: time_log.move_to_next_working_slot() except OverlapError: time_log.move_to_next_non_overlapping_slot() # reset end time time_log.to_time = get_datetime(time_log.from_time) + relativedelta(minutes=d.time_in_mins) if date_diff(time_log.from_time, original_start_time) > plan_days: frappe.msgprint(_("Unable to find Time Slot in the next {0} days for Operation {1}").format(plan_days, d.operation)) break # if time log needs to be moved, make sure that the from time is not the same if _from_time == time_log.from_time: frappe.throw("Capacity Planning Error") d.planned_start_time = time_log.from_time d.planned_end_time = time_log.to_time d.db_update() if time_log.name: time_logs.append(time_log.name) self.planned_end_date = self.operations[-1].planned_end_time if time_logs: frappe.local.message_log = [] frappe.msgprint(_("Time Logs created:") + "\n" + "\n".join(time_logs))
def calculate_pro_rata_tax(self, salary_component): # Calculate total tax payable earnings tax_applicable_components = [] for earning in self._salary_structure_doc.earnings: #all tax applicable earnings which are not flexi if earning.is_tax_applicable and not earning.is_flexible_benefit: tax_applicable_components.append(earning.salary_component) total_taxable_earning = 0 for earning in self.earnings: if earning.salary_component in tax_applicable_components: total_taxable_earning += earning.amount # Get payroll period, prorata frequency days = date_diff(self.end_date, self.start_date) + 1 payroll_period = get_payroll_period(self.start_date, self.end_date, self.company) if not payroll_period: frappe.throw(_("Start and end dates not in a valid Payroll Period")) total_days = date_diff(payroll_period.end_date, payroll_period.start_date) + 1 prorata_frequency = flt(total_days)/flt(days) annual_earning = total_taxable_earning * prorata_frequency # Calculate total exemption declaration exemption_amount = 0 if frappe.db.exists("Employee Tax Exemption Declaration", {"employee": self.employee, "payroll_period": payroll_period.name, "docstatus": 1}): exemption_amount = frappe.db.get_value("Employee Tax Exemption Declaration", {"employee": self.employee, "payroll_period": payroll_period.name, "docstatus": 1}, #fix period "total_exemption_amount") annual_earning = annual_earning - exemption_amount # Get tax calc by component component = frappe.get_doc("Salary Component", salary_component) annual_tax = component.calculate_tax(annual_earning) # Calc prorata tax pro_rata_tax = annual_tax/prorata_frequency # Data for update_component_row struct_row = {} struct_row['depends_on_lwp'] = 0 struct_row['salary_component'] = component.name struct_row['abbr'] = component.salary_component_abbr struct_row['do_not_include_in_total'] = 0 return struct_row, pro_rata_tax
def add_event(e, date): new_event = e.copy() enddate = add_days(date,int(date_diff(e.ends_on.split(" ")[0], e.starts_on.split(" ")[0]))) \ if (e.starts_on and e.ends_on) else date new_event.starts_on = date + " " + e.starts_on.split(" ")[1] if e.ends_on: new_event.ends_on = enddate + " " + e.ends_on.split(" ")[1] add_events.append(new_event)
def make_time_logs(self, open_new=False): """Capacity Planning. Plan time logs based on earliest availablity of workstation after Planned Start Date. Time logs will be created and remain in Draft mode and must be submitted before manufacturing entry can be made.""" if not self.operations: return timesheets = [] plan_days = frappe.db.get_single_value("Manufacturing Settings", "capacity_planning_for_days") or 30 timesheet = make_timesheet(self.name) workstation_list = [] last_workstation_idx = {} timesheet.set('time_logs', []) for i, d in enumerate(self.operations): if d.workstation and d.status != 'Completed': last_workstation_idx[d.workstation] = i # set last row index of workstation self.set_start_end_time_for_workstation(d, workstation_list, last_workstation_idx.get(d.workstation)) args = self.get_operations_data(d) add_timesheet_detail(timesheet, args) original_start_time = d.planned_start_time # validate operating hours if workstation [not mandatory] is specified try: timesheet.validate_time_logs() except OverlapError: if frappe.message_log: frappe.message_log.pop() timesheet.schedule_for_production_order(d.idx) except WorkstationHolidayError: if frappe.message_log: frappe.message_log.pop() timesheet.schedule_for_production_order(d.idx) from_time, to_time = self.get_start_end_time(timesheet, d.name) if date_diff(from_time, original_start_time) > plan_days: frappe.throw(_("Unable to find Time Slot in the next {0} days for Operation {1}").format(plan_days, d.operation)) break d.planned_start_time = from_time d.planned_end_time = to_time d.db_update() if timesheet and open_new: return timesheet if timesheet: timesheet.save() timesheets.append(timesheet.name) self.planned_end_date = self.operations[-1].planned_end_time if timesheets: frappe.local.message_log = [] frappe.msgprint(_("Timesheet created:") + "\n" + "\n".join(timesheets))
def calculate_std_hours(self): std_working_hours = frappe.get_value("Company", self.company, 'standard_working_hours') for time in self.time_logs: if time.from_time and time.to_time: if flt(std_working_hours) > 0: time.hours = flt(std_working_hours) * date_diff(time.to_time, time.from_time) else: if not time.hours: time.hours = time_diff_in_hours(time.to_time, time.from_time)
def get_period_factor(self, period_start, period_end, start_date=None, end_date=None): # TODO if both deduct checked update the factor to make tax consistent joining_date, relieving_date = frappe.db.get_value("Employee", self.employee, ["date_of_joining", "relieving_date"]) if getdate(joining_date) > getdate(period_start): period_start = joining_date if relieving_date and getdate(relieving_date) < getdate(period_end): period_end = relieving_date payroll_days = date_diff(period_end, period_start) + 1 if start_date and end_date: salary_days = date_diff(end_date, start_date) + 1 return flt(payroll_days)/flt(salary_days) # if period configured for a year and monthly frequency return 12 to make tax calc consistent if 360 <= payroll_days <= 370 and self.payroll_frequency == "Monthly": return 12 salary_days = date_diff(self.end_date, self.start_date) + 1 return flt(payroll_days)/flt(salary_days)
def get_data(filters): out = [] for room_type in frappe.get_all('Hotel Room Type'): total_booked = 0 for i in range(date_diff(filters.to_date, filters.from_date)): day = add_days(filters.from_date, i) total_booked += get_rooms_booked(room_type.name, day) out.append([room_type.name, total_booked]) return out
def validate(self): if self.starts_on and self.ends_on and self.starts_on > 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 self.starts_on and self.ends_on and int(date_diff(self.ends_on.split(" ")[0], self.starts_on.split(" ")[0])) > 0 \ and self.repeat_on == "Every Day": frappe.msgprint(frappe._("Every day events should finish on the same day."), raise_exception=True)
def send_reminder(): frappe.has_permission('GST Settings', throw=True) last_sent = frappe.db.get_single_value('GST Settings', 'gstin_email_sent_on') if last_sent and date_diff(nowdate(), last_sent) < 3: frappe.throw("Please wait 3 days before resending the reminder.") frappe.db.set_value('GST Settings', 'GST Settings', 'gstin_email_sent_on', nowdate()) # enqueue if large number of customers, suppliser frappe.enqueue('erpnext.regional.doctype.gst_settings.gst_settings.send_gstin_reminder_to_all_parties') frappe.msgprint('Email Reminders will be sent to all parties with email contacts')
def validate_due_date(posting_date, due_date, party_type, party, company): if getdate(due_date) < getdate(posting_date): frappe.throw(_("Due Date cannot be before Posting Date")) else: default_due_date = get_due_date(posting_date, party_type, party, company) if default_due_date != posting_date and getdate(due_date) > getdate(default_due_date): is_credit_controller = frappe.db.get_single_value("Accounts Settings", "credit_controller") in frappe.get_roles() if is_credit_controller: msgprint(_("Note: Due / Reference Date exceeds allowed customer credit days by {0} day(s)") .format(date_diff(due_date, default_due_date))) else: frappe.throw(_("Due / Reference Date cannot be after {0}").format(formatdate(default_due_date)))
def autocreate_leave_allocation(): auto_create = frappe.db.get_value("HR Settings", None, "sc_auto_create_leave_allocation") if auto_create == '1': yesterday = add_days(today(), -1) leave_allocations = frappe.get_list("Leave Allocation", { 'to_date': yesterday, 'docstatus': 1, 'carry_forward': True }) first_day_yes = get_first_day(yesterday) last_day_yes = get_last_day(yesterday) for leave_alloc in leave_allocations: from_date = today() to_date = today() leave_allocation = frappe.get_doc("Leave Allocation", leave_alloc['name']) new_leave_allocation = frappe.new_doc("Leave Allocation") new_leave_allocation.employee = leave_allocation.employee new_leave_allocation.employee_name = leave_allocation.employee_name new_leave_allocation.leave_type = leave_allocation.leave_type if leave_allocation.from_date == first_day_yes and leave_allocation.to_date == last_day_yes: from_date = today() to_date = get_last_day(today()) else: diff_no = date_diff(leave_allocation.to_date, leave_allocation.from_date) from_date = today() to_date = add_days(from_date, diff_no) new_leave_allocation.from_date = from_date new_leave_allocation.to_date = to_date new_leave_allocation.new_leaves_allocated = leave_allocation.new_leaves_allocated if leave_allocation.carry_forward: new_leave_allocation.carry_forward = leave_allocation.carry_forward new_leave_allocation.save(ignore_permissions=True) new_leave_allocation.submit()
def validate_house_rent_dates(doc): if not doc.rented_to_date or not doc.rented_from_date: frappe.throw(_("House rented dates required for exemption calculation")) if date_diff(doc.rented_to_date, doc.rented_from_date) < 14: frappe.throw(_("House rented dates should be atleast 15 days apart")) proofs = frappe.db.sql(""" select name from `tabEmployee Tax Exemption Proof Submission` where docstatus=1 and employee=%(employee)s and payroll_period=%(payroll_period)s and (rented_from_date between %(from_date)s and %(to_date)s or rented_to_date between %(from_date)s and %(to_date)s) """, { "employee": doc.employee, "payroll_period": doc.payroll_period, "from_date": doc.rented_from_date, "to_date": doc.rented_to_date }) if proofs: frappe.throw(_("House rent paid days overlapping with {0}").format(proofs[0][0]))
def get_leave_details(self, joining_date=None, relieving_date=None, lwp=None): if not joining_date: joining_date, relieving_date = frappe.db.get_value( "Employee", self.employee, ["date_of_joining", "relieving_date"]) holidays = self.get_holidays_for_employee(self.start_date, self.end_date) working_days = date_diff(self.end_date, self.start_date) + 1 actual_lwp = self.calculate_lwp(holidays, working_days) if not cint( frappe.db.get_value("HR Settings", None, "include_holidays_in_total_working_days")): working_days -= len(holidays) if working_days < 0: frappe.throw( _("There are more holidays than working days this month.")) if not lwp: lwp = actual_lwp elif lwp != actual_lwp: frappe.msgprint( _("Leave Without Pay does not match with approved Leave Application records" )) self.total_working_days = working_days self.leave_without_pay = lwp self.monthly_total_hours = (working_days - len(holidays)) * 8 payment_days = flt(self.get_payment_days(joining_date, relieving_date)) - flt(lwp) self.payment_days = payment_days > 0 and payment_days or 0 self.get_worked_hours() self.get_overtime_info()
def on_submit(self): company = frappe.db.get_value("Employee", self.employee, "company") date_difference = date_diff(self.work_end_date, self.work_from_date) + 1 if self.half_day: date_difference -= 0.5 leave_period = get_leave_period(self.work_from_date, self.work_end_date, company) if leave_period: leave_allocation = self.get_existing_allocation_for_period(leave_period) if leave_allocation: leave_allocation.new_leaves_allocated += date_difference leave_allocation.validate() leave_allocation.db_set("new_leaves_allocated", leave_allocation.total_leaves_allocated) leave_allocation.db_set("total_leaves_allocated", leave_allocation.total_leaves_allocated) # generate additional ledger entry for the new compensatory leaves off create_additional_leave_ledger_entry(leave_allocation, date_difference, add_days(self.work_end_date, 1)) else: leave_allocation = self.create_leave_allocation(leave_period, date_difference) self.leave_allocation=leave_allocation.name else: frappe.throw(_("There is no leave period in between {0} and {1}").format(self.work_from_date, self.work_end_date))
def reschedule_dependent_tasks(self): end_date = self.exp_end_date or self.act_end_date if end_date: for task_name in frappe.db.sql( """select name from `tabTask` as parent where parent.project = %(project)s and parent.name in \ (select parent from `tabTask Depends On` as child where child.task = %(task)s and child.project = %(project)s)""", { 'project': self.project, 'task': self.name }, as_dict=1): task = frappe.get_doc("Task", task_name.name) if task.exp_start_date and task.exp_end_date and task.exp_start_date < getdate( end_date) and task.status == "Open": task_duration = date_diff(task.exp_end_date, task.exp_start_date) task.exp_start_date = add_days(end_date, 1) task.exp_end_date = add_days(task.exp_start_date, task_duration) task.flags.ignore_recursion_check = True task.save()
def validate_availability(self): for i in range(date_diff(self.to_date, self.from_date)): day = add_days(self.from_date, i) self.rooms_booked = {} for d in self.items: if not d.item in self.rooms_booked: self.rooms_booked[d.item] = 0 room_type = frappe.db.get_value("Hotel Room Package", d.item, 'hotel_room_type') rooms_booked = get_rooms_booked(room_type, day, exclude_reservation=self.name) \ + d.qty + self.rooms_booked.get(d.item) total_rooms = self.get_total_rooms(d.item) if total_rooms < rooms_booked: frappe.throw( _("Hotel Rooms of type {0} are unavailable on {1}" ).format(d.item, frappe.format(day, dict(fieldtype="Date"))), exc=HotelRoomUnavailableError) self.rooms_booked[d.item] += rooms_booked
def validate_employee_attendance(self): employees_to_mark_attendance = [] days_in_payroll, days_holiday, days_attendance_marked = 0, 0, 0 for employee_detail in self.employees: employee_joining_date = frappe.db.get_value( "Employee", employee_detail.employee, 'date_of_joining') start_date = self.start_date if employee_joining_date > getdate(self.start_date): start_date = employee_joining_date days_holiday = self.get_count_holidays_of_employee( employee_detail.employee, start_date) days_attendance_marked = self.get_count_employee_attendance( employee_detail.employee, start_date) days_in_payroll = date_diff(self.end_date, start_date) + 1 if days_in_payroll > days_holiday + days_attendance_marked: employees_to_mark_attendance.append({ "employee": employee_detail.employee, "employee_name": employee_detail.employee_name }) return employees_to_mark_attendance
def create_job_card(self): manufacturing_settings_doc = frappe.get_doc("Manufacturing Settings") enable_capacity_planning = not cint( manufacturing_settings_doc.disable_capacity_planning) plan_days = cint( manufacturing_settings_doc.capacity_planning_for_days) or 30 for i, row in enumerate(self.operations): self.set_operation_start_end_time(i, row) if not row.workstation: frappe.throw( _("Row {0}: select the workstation against the operation {1}" ).format(row.idx, row.operation)) original_start_time = row.planned_start_time job_card_doc = create_job_card( self, row, enable_capacity_planning=enable_capacity_planning, auto_create=True) if enable_capacity_planning and job_card_doc: row.planned_start_time = job_card_doc.time_logs[0].from_time row.planned_end_time = job_card_doc.time_logs[-1].to_time if date_diff(row.planned_start_time, original_start_time) > plan_days: frappe.throw( _("Unable to find the time slot in the next {0} days for the operation {1}." ).format(plan_days, row.operation), CapacityError) row.db_update() planned_end_date = self.operations and self.operations[ -1].planned_end_time if planned_end_date: self.db_set("planned_end_date", planned_end_date)
def validate_due_date(posting_date, due_date, party_type, party, company): if getdate(due_date) < getdate(posting_date): frappe.throw(_("Due Date cannot be before Posting Date")) else: default_due_date = get_due_date(posting_date, party_type, party, company) if not default_due_date: return if default_due_date != posting_date and getdate(due_date) > getdate( default_due_date): is_credit_controller = frappe.db.get_single_value( "Accounts Settings", "credit_controller") in frappe.get_roles() if is_credit_controller: msgprint( _("Note: Due / Reference Date exceeds allowed customer credit days by {0} day(s)" ).format(date_diff(due_date, default_due_date))) else: frappe.throw( _("Due / Reference Date cannot be after {0}").format( formatdate(default_due_date)))
def validate_applicable_after(self): if self.leave_type: leave_type = frappe.get_doc("Leave Type", self.leave_type) if leave_type.applicable_after > 0: date_of_joining = frappe.db.get_value("Employee", self.employee, "date_of_joining") leave_days = get_approved_leaves_for_period( self.employee, False, date_of_joining, self.from_date) number_of_days = date_diff(getdate(self.from_date), date_of_joining) if number_of_days >= 0: holidays = 0 if not frappe.db.get_value("Leave Type", self.leave_type, "include_holiday"): holidays = get_holidays(self.employee, date_of_joining, self.from_date) number_of_days = number_of_days - leave_days - holidays if number_of_days < leave_type.applicable_after: frappe.throw( _("{0} applicable after {1} working days").format( self.leave_type, leave_type.applicable_after))
def get_payment_days(self, joining_date, relieving_date): start_date = getdate(self.start_date) if joining_date: if getdate(self.start_date) <= joining_date <= getdate(self.end_date): start_date = joining_date elif joining_date > getdate(self.end_date): return end_date = getdate(self.end_date) if relieving_date: if getdate(self.start_date) <= relieving_date <= getdate(self.end_date): end_date = relieving_date elif relieving_date < getdate(self.start_date): frappe.throw(_("Employee relieved on {0} must be set as 'Left'") .format(relieving_date)) payment_days = date_diff(end_date, start_date) + 1 if not cint(frappe.db.get_value("HR Settings", None, "include_holidays_in_total_working_days")): holidays = self.get_holidays_for_employee(start_date, end_date) payment_days -= len(holidays) return payment_days
def test_loan_interest_accural(self): pledges = [] pledges.append({ "loan_security": "Test Security 1", "qty": 4000.00, "haircut": 50, "loan_security_price": 500.00 }) loan_security_pledge = create_loan_security_pledge( self.applicant, pledges) loan = create_demand_loan(self.applicant, "Demand Loan", loan_security_pledge.name, posting_date=get_first_day(nowdate())) loan.submit() first_date = '2019-10-01' last_date = '2019-10-30' no_of_days = date_diff(last_date, first_date) + 1 accrued_interest_amount = (loan.loan_amount * loan.rate_of_interest * no_of_days) \ / (days_in_year(get_datetime(first_date).year) * 100) make_loan_disbursement_entry(loan.name, loan.loan_amount, disbursement_date=first_date) process_loan_interest_accrual(posting_date=last_date) loan_interest_accural = frappe.get_doc("Loan Interest Accrual", {'loan': loan.name}) self.assertEquals(flt(loan_interest_accural.interest_amount, 2), flt(accrued_interest_amount, 2))
def test_regular_loan_repayment(self): pledges = [] pledges.append({ "loan_security": "Test Security 1", "qty": 4000.00, "haircut": 50 }) loan_security_pledge = create_loan_security_pledge(self.applicant2, pledges) loan = create_demand_loan(self.applicant2, "Demand Loan", loan_security_pledge.name, posting_date=get_first_day(nowdate())) loan.submit() self.assertEquals(loan.loan_amount, 1000000) first_date = '2019-10-01' last_date = '2019-10-30' no_of_days = date_diff(last_date, first_date) + 1 accrued_interest_amount = (loan.loan_amount * loan.rate_of_interest * no_of_days) \ / (days_in_year(get_datetime(first_date).year) * 100) make_loan_disbursement_entry(loan.name, loan.loan_amount, disbursement_date=first_date) process_loan_interest_accrual(posting_date = last_date) repayment_entry = create_repayment_entry(loan.name, self.applicant2, add_days(last_date, 10), "Regular Payment", 111118.68) repayment_entry.save() penalty_amount = (accrued_interest_amount * 5 * 25) / (100 * days_in_year(get_datetime(first_date).year)) self.assertEquals(flt(repayment_entry.interest_payable, 2), flt(accrued_interest_amount, 2)) self.assertEquals(flt(repayment_entry.penalty_amount, 2), flt(penalty_amount, 2)) repayment_entry.submit()
def get_payment_days(self, joining_date, relieving_date): start_date = getdate(self.start_date) if joining_date: if getdate(self.start_date) <= joining_date <= getdate( self.end_date): start_date = joining_date elif joining_date > getdate(self.end_date): return end_date = getdate(self.end_date) if relieving_date: if getdate(self.start_date) <= relieving_date <= getdate( self.end_date): end_date = relieving_date elif relieving_date < getdate(self.start_date): frappe.throw( _("Employee relieved on {0} must be set as 'Left'").format( relieving_date)) payment_days = date_diff(end_date, start_date) + 1 #vin code start if ((self.get_holiday_setting_from_salary_stucture() < 2) and (self.get_holiday_setting_from_salary_stucture() == 0)): #frappe.msgprint(_("0:"+str(holidays)+","+ str(working_days))); holidays = self.get_holidays_for_employee(start_date, end_date) payment_days -= len(holidays) elif ((self.get_holiday_setting_from_salary_stucture() < 2) and (self.get_holiday_setting_from_salary_stucture() == 1)): #frappe.msgprint(_("1:"+str(holidays)+","+ str(working_days))); pass #if not cint(frappe.db.get_value("HR Settings", None, "include_holidays_in_total_working_days")): #vin code end return payment_days
def get_overdue(loan_period): # check for overdue articles today = nowdate() overdue_by_member = {} articles_transacted = [] for d in frappe.db.sql("""select name, article, article_name, library_member, member_name from `tabLibrary Transaction` order by transaction_date desc, modified desc""", as_dict=1): if d.article in articles_transacted: continue if d.transaction_type=="Issue" and \ date_diff(today, d.transaction_date) > loan_period: overdue_by_member.setdefault(d.library_member, []) overdue_by_member[d.library_member].append(d) articles_transacted.append(d.article) return overdue_by_member
def check_due_date(self): if self.cheque_date: for d in self.get("accounts"): if d.party_type and d.party and d.get( "credit" if d.party_type == "Customer" else "debit") > 0: due_date = None if d.against_invoice: due_date = frappe.db.get_value("Sales Invoice", d.against_invoice, "due_date") elif d.against_voucher: due_date = frappe.db.get_value("Purchase Invoice", d.against_voucher, "due_date") if due_date and getdate( self.cheque_date) > getdate(due_date): diff = date_diff(self.cheque_date, due_date) if diff > 0: msgprint( _("Note: Reference Date exceeds invoice due date by {0} days for {1} {2}" ).format(diff, d.party_type, d.party))
def test_loan_topup(self): pledge = [{ "loan_security": "Test Security 1", "qty": 4000.00 }] loan_application = create_loan_application('_Test Company', self.applicant, 'Demand Loan', pledge) create_pledge(loan_application) loan = create_demand_loan(self.applicant, "Demand Loan", loan_application, posting_date=get_first_day(nowdate())) loan.submit() first_date = get_first_day(nowdate()) last_date = get_last_day(nowdate()) no_of_days = date_diff(last_date, first_date) + 1 accrued_interest_amount = (loan.loan_amount * loan.rate_of_interest * no_of_days) \ / (days_in_year(get_datetime().year) * 100) make_loan_disbursement_entry(loan.name, loan.loan_amount, disbursement_date=first_date) process_loan_interest_accrual_for_demand_loans(posting_date=add_days(last_date, 1)) # Should not be able to create loan disbursement entry before repayment self.assertRaises(frappe.ValidationError, make_loan_disbursement_entry, loan.name, 500000, first_date) repayment_entry = create_repayment_entry(loan.name, self.applicant, add_days(get_last_day(nowdate()), 5), "Regular Payment", 611095.89) repayment_entry.submit() loan.reload() # After repayment loan disbursement entry should go through make_loan_disbursement_entry(loan.name, 500000, disbursement_date=add_days(last_date, 16))
def passport_validate_check(): from frappe.core.doctype.communication.email import make frappe.flags.sent_mail = None emp = frappe.db.sql( "select name,valid_upto,user_id,passport_notification from `tabEmployee`" ) for i in emp: if i[1] and i[3]: date_difference = date_diff(i[1], getdate(nowdate())) if date_difference <= 30 and date_difference > 0: content_msg_emp = "Your Passport validity will end after {0} days".format( date_difference) prefered_email = frappe.get_value("Employee", filters={"name": i[0]}, fieldname="prefered_email") if prefered_email: try: sent = 0 make(subject="Passport Validity Notification", content=content_msg_emp, recipients=prefered_email, send_email=True, sender="*****@*****.**") sent = 1 print('send email for ' + prefered_email) except: frappe.msgprint("could not send") print(content_msg_emp) print( '----------------------------------------------------------------' )
def get_payroll_period_days(start_date, end_date, employee, company=None): if not company: company = frappe.db.get_value("Employee", employee, "company") payroll_period = frappe.db.sql(""" select name, start_date, end_date from `tabPayroll Period` where company=%(company)s and %(start_date)s between start_date and end_date and %(end_date)s between start_date and end_date """, { 'company': company, 'start_date': start_date, 'end_date': end_date }) if len(payroll_period) > 0: actual_no_of_days = date_diff(getdate(payroll_period[0][2]), getdate(payroll_period[0][1])) + 1 working_days = actual_no_of_days if not cint(frappe.db.get_value("HR Settings", None, "include_holidays_in_total_working_days")): holidays = get_holidays_for_employee(employee, getdate(payroll_period[0][1]), getdate(payroll_period[0][2])) working_days -= len(holidays) return payroll_period[0][0], working_days, actual_no_of_days return False, False, False
def get_leave_details(self, joining_date=None, relieving_date=None, lwp=None): if not self.fiscal_year: # if default fiscal year is not set, get from nowdate self.fiscal_year = get_fiscal_year(nowdate())[0] if not self.month: self.month = "%02d" % getdate(nowdate()).month self.set_month_dates() if not joining_date: joining_date, relieving_date = frappe.db.get_value( "Employee", self.employee, ["date_of_joining", "relieving_date"]) holidays = self.get_holidays_for_employee(self.start_date, self.end_date) working_days = date_diff(self.end_date, self.start_date) + 1 if not cint( frappe.db.get_value("HR Settings", None, "include_holidays_in_total_working_days")): working_days -= len(holidays) if working_days < 0: frappe.throw( _("There are more holidays than working days this month.")) if not lwp: lwp = self.calculate_lwp(holidays, working_days) self.total_days_in_month = working_days self.leave_without_pay = lwp payment_days = flt(self.get_payment_days(joining_date, relieving_date)) - flt(lwp) self.payment_days = payment_days > 0 and payment_days or 0
def on_submit(self): if self.approver != frappe.session.user: frappe.throw(_("Only Leave Approver can submit this document")) if self.status == "Open": frappe.throw( _("Only Applications with status 'Approved' and 'Rejected' can be submitted")) elif self.status == "Approved": request_days = date_diff(self.to_date, self.from_date) + 1 for number in range(request_days): attendance_date = add_days(self.from_date, number) skip_attendance = validate_if_attendance_not_applicable( self.employee, attendance_date) if not skip_attendance: att = frappe.db.exists( "Attendance", {"employee": self.employee, "attendance_date": attendance_date}) if att: attendance = frappe.get_doc("Attendance", att) attendance.update({ "status": "Present", "onduty_status": "On Duty" # "on_duty_application": doc.name }) attendance.db_update() frappe.db.commit() else: attendance = frappe.new_doc("Attendance") attendance.employee = self.employee attendance.employee_name = self.employee_name attendance.status = "Present" attendance.attendance_date = attendance_date attendance.in_time = "" attendance.out_time = "" attendance.onduty_status = "On Duty" attendance.company = self.company attendance.save(ignore_permissions=True) attendance.submit()
def on_cancel(self): if self.leave_allocation: date_difference = date_diff(self.work_end_date, self.work_from_date) + 1 if self.half_day: date_difference -= 0.5 leave_allocation = frappe.get_doc("Leave Allocation", self.leave_allocation) if leave_allocation: leave_allocation.new_leaves_allocated -= date_difference if leave_allocation.new_leaves_allocated - date_difference <= 0: leave_allocation.new_leaves_allocated = 0 leave_allocation.validate() leave_allocation.db_set( "new_leaves_allocated", leave_allocation.total_leaves_allocated) leave_allocation.db_set( "total_leaves_allocated", leave_allocation.total_leaves_allocated) # create reverse entry on cancelation create_additional_leave_ledger_entry( leave_allocation, date_difference * -1, add_days(self.work_end_date, 1))
def create_event(data): response = '' request_type="POST" url = "%s/createEvent"%get_base_url() event_data={ "event_title": data.get('event_title'), "profile_id": data.get('profile_id'), "str_event_date": data.get('event_date'), "received_from": "Desktop", "event_symptoms" : data.get('complaints'), "event_descripton": data.get('event_descripton') } event_date = datetime.datetime.strptime(event_data.get('str_event_date'), "%d/%m/%Y").strftime('%Y-%m-%d') if date_diff(event_date, nowdate()) > 0: frappe.msgprint("Event Date should be past or current",raise_exception=1) else: response=get_response(url, json.dumps(event_data), request_type) make_log(json.loads(response.text).get('entityid'),"Event","Create","Event Created") return json.loads(response.text)
def get_max_benefits_remaining(employee, on_date, payroll_period): max_benefits = get_max_benefits(employee, on_date) if max_benefits and max_benefits > 0: have_depends_on_payment_days = False per_day_amount_total = 0 payroll_period_days = get_payroll_period_days(on_date, on_date, employee)[0] payroll_period_obj = frappe.get_doc("Payroll Period", payroll_period) # Get all salary slip flexi amount in the payroll period prev_sal_slip_flexi_total = get_sal_slip_total_benefit_given(employee, payroll_period_obj) if prev_sal_slip_flexi_total > 0: # Check salary structure hold depends_on_payment_days component # If yes then find the amount per day of each component and find the sum sal_struct_name = get_assigned_salary_structure(employee, on_date) if sal_struct_name: sal_struct = frappe.get_doc("Salary Structure", sal_struct_name) for sal_struct_row in sal_struct.get("earnings"): salary_component = frappe.get_doc("Salary Component", sal_struct_row.salary_component) if salary_component.depends_on_payment_days == 1 and salary_component.pay_against_benefit_claim != 1: have_depends_on_payment_days = True benefit_amount = get_benefit_amount_based_on_pro_rata(sal_struct, salary_component.max_benefit_amount) amount_per_day = benefit_amount / payroll_period_days per_day_amount_total += amount_per_day # Then the sum multiply with the no of lwp in that period # Include that amount to the prev_sal_slip_flexi_total to get the actual if have_depends_on_payment_days and per_day_amount_total > 0: holidays = get_holidays_for_employee(employee, payroll_period_obj.start_date, on_date) working_days = date_diff(on_date, payroll_period_obj.start_date) + 1 leave_days = calculate_lwp(employee, payroll_period_obj.start_date, holidays, working_days) leave_days_amount = leave_days * per_day_amount_total prev_sal_slip_flexi_total += leave_days_amount return max_benefits - prev_sal_slip_flexi_total return max_benefits
def pretty_date(iso_datetime, ref_date=None): """ Extends frappe.utils.data.pretty_date """ days = date_diff(iso_datetime, ref_date or datetime.date.today()) if days < 0: return frappe.utils.pretty_date(iso_datetime) if days < 1: return _('today') if days == 1: return _('tomorrow') if days < 7: return _('in {} days'.format(cint(days))) if days < 12: return _('in a week') if days < 31: return _('in {} weeks'.format(cint(days / 7.0))) if days < 46: return _('in a month') if days < 365: return _('in {} months'.format(cint(days / 30.0))) if days < 550: return _('in a year') return _('in {} years'.format(cint(days / 365.0)))
def get_depreciation_amount_prorata_temporis(self, depreciable_value, row, start_date=None, end_date=None): if start_date and end_date: prorata_temporis = min( abs(flt(date_diff(str(end_date), str(start_date)))) / flt( frappe.db.get_value("Asset Settings", None, "number_of_days_in_fiscal_year")), 1) else: prorata_temporis = 1 if row.depreciation_method in ("Straight Line", "Manual"): depreciation_amount = ( flt(row.value_after_depreciation) - flt(row.expected_value_after_useful_life) ) / (cint(row.total_number_of_depreciations) - cint(self.number_of_depreciations_booked)) * prorata_temporis else: depreciation_amount = self.get_depreciation_amount( depreciable_value, row) return depreciation_amount
def set_follow_up(appointment_doc, method): filters = { "name": ["!=", appointment_doc.name], "insurance_subscription": appointment_doc.insurance_subscription, "department": appointment_doc.department, "status": "Closed", } appointment = get_previous_appointment(appointment_doc.patient, filters) if appointment and appointment_doc.appointment_date: diff = date_diff(appointment_doc.appointment_date, appointment.appointment_date) valid_days = int( frappe.get_value("Healthcare Settings", "Healthcare Settings", "valid_days")) if diff <= valid_days: appointment_doc.follow_up = 1 if (appointment_doc.follow_up and appointment_doc.insurance_subscription and not appointment_doc.authorization_number): return appointment_doc.invoiced = 1 # frappe.msgprint(_("Previous appointment found valid for free follow-up.<br>Skipping invoice for this appointment!"), alert=True) else: appointment_doc.follow_up = 0
def test_loan_interest_accural(self): pledge = [{ "loan_security": "Test Security 1", "qty": 4000.00 }] loan_application = create_loan_application('_Test Company', self.applicant, 'Demand Loan', pledge) create_pledge(loan_application) loan = create_demand_loan(self.applicant, "Demand Loan", loan_application, posting_date=get_first_day(nowdate())) loan.submit() first_date = '2019-10-01' last_date = '2019-10-30' no_of_days = date_diff(last_date, first_date) + 1 accrued_interest_amount = (loan.loan_amount * loan.rate_of_interest * no_of_days) \ / (days_in_year(get_datetime(first_date).year) * 100) make_loan_disbursement_entry(loan.name, loan.loan_amount, disbursement_date=first_date) process_loan_interest_accrual_for_demand_loans(posting_date=last_date) loan_interest_accural = frappe.get_doc("Loan Interest Accrual", {'loan': loan.name}) self.assertEquals(flt(loan_interest_accural.interest_amount, 0), flt(accrued_interest_amount, 0))
def get_events(start, end, user=None, for_reminder=False): if not user: user = frappe.session.user roles = frappe.get_roles(user) events = frappe.db.sql("""select name, subject, description, starts_on, ends_on, owner, all_day, event_type, repeat_this_event, repeat_on,repeat_till, monday, tuesday, wednesday, thursday, friday, saturday, sunday from tabEvent where (( (date(starts_on) between date(%(start)s) and date(%(end)s)) or (date(ends_on) between date(%(start)s) and date(%(end)s)) or (date(starts_on) <= date(%(start)s) and date(ends_on) >= date(%(end)s)) ) or ( date(starts_on) <= date(%(start)s) and repeat_this_event=1 and ifnull(repeat_till, "3000-01-01") > date(%(start)s) )) {reminder_condition} and (event_type='Public' or owner=%(user)s or exists(select name from `tabDocShare` where tabDocShare.share_doctype="Event" and `tabDocShare`.share_name=tabEvent.name and tabDocShare.user=%(user)s) or exists(select * from `tabEvent Role` where `tabEvent Role`.parent=tabEvent.name and `tabEvent Role`.role in ({roles}))) order by starts_on""".format( reminder_condition="and ifnull(send_reminder,0)=1" if for_reminder else "", roles=", ".join('"{}"'.format(frappe.db.escape(r)) for r in roles) ), { "start": start, "end": end, "user": user, }, as_dict=1) # process recurring events start = start.split(" ")[0] end = end.split(" ")[0] add_events = [] remove_events = [] def add_event(e, date): new_event = e.copy() enddate = add_days(date,int(date_diff(e.ends_on.split(" ")[0], e.starts_on.split(" ")[0]))) \ if (e.starts_on and e.ends_on) else date new_event.starts_on = date + " " + e.starts_on.split(" ")[1] if e.ends_on: new_event.ends_on = enddate + " " + e.ends_on.split(" ")[1] add_events.append(new_event) for e in events: if e.repeat_this_event: e.starts_on = get_datetime_str(e.starts_on) if e.ends_on: e.ends_on = get_datetime_str(e.ends_on) event_start, time_str = get_datetime_str(e.starts_on).split(" ") if cstr(e.repeat_till) == "": repeat = "3000-01-01" else: repeat = e.repeat_till if e.repeat_on=="Every Year": start_year = cint(start.split("-")[0]) end_year = cint(end.split("-")[0]) event_start = "-".join(event_start.split("-")[1:]) # repeat for all years in period for year in range(start_year, end_year+1): date = str(year) + "-" + event_start if getdate(date) >= getdate(start) and getdate(date) <= getdate(end) and getdate(date) <= getdate(repeat): add_event(e, date) remove_events.append(e) if e.repeat_on=="Every Month": date = start.split("-")[0] + "-" + start.split("-")[1] + "-" + event_start.split("-")[2] # last day of month issue, start from prev month! try: getdate(date) except ValueError: date = date.split("-") date = date[0] + "-" + str(cint(date[1]) - 1) + "-" + date[2] start_from = date for i in xrange(int(date_diff(end, start) / 30) + 3): if getdate(date) >= getdate(start) and getdate(date) <= getdate(end) \ and getdate(date) <= getdate(repeat) and getdate(date) >= getdate(event_start): add_event(e, date) date = add_months(start_from, i+1) remove_events.append(e) if e.repeat_on=="Every Week": weekday = getdate(event_start).weekday() # monday is 0 start_weekday = getdate(start).weekday() # start from nearest weeday after last monday date = add_days(start, weekday - start_weekday) for cnt in xrange(int(date_diff(end, start) / 7) + 3): if getdate(date) >= getdate(start) and getdate(date) <= getdate(end) \ and getdate(date) <= getdate(repeat) and getdate(date) >= getdate(event_start): add_event(e, date) date = add_days(date, 7) remove_events.append(e) if e.repeat_on=="Every Day": for cnt in xrange(date_diff(end, start) + 1): date = add_days(start, cnt) if getdate(date) >= getdate(event_start) and getdate(date) <= getdate(end) \ and getdate(date) <= getdate(repeat) and e[weekdays[getdate(date).weekday()]]: add_event(e, date) remove_events.append(e) for e in remove_events: events.remove(e) events = events + add_events for e in events: # remove weekday properties (to reduce message size) for w in weekdays: del e[w] return events
def make_time_logs(self): """Capacity Planning. Plan time logs based on earliest availablity of workstation after Planned Start Date. Time logs will be created and remain in Draft mode and must be submitted before manufacturing entry can be made.""" if not self.operations: return time_logs = [] plan_days = frappe.db.get_single_value( "Manufacturing Settings", "capacity_planning_for_days") or 30 for i, d in enumerate(self.operations): self.set_operation_start_end_time(i, d) time_log = make_time_log(self.name, d.operation, d.planned_start_time, d.planned_end_time, flt(self.qty) - flt(d.completed_qty), self.project_name, d.workstation, operation_id=d.name) if d.workstation: # validate operating hours if workstation [not mandatory] is specified self.check_operation_fits_in_working_hours(d) original_start_time = time_log.from_time while True: _from_time = time_log.from_time try: time_log.save() break except WorkstationHolidayError: time_log.move_to_next_day() except NotInWorkingHoursError: time_log.move_to_next_working_slot() except OverlapError: time_log.move_to_next_non_overlapping_slot() # reset end time time_log.to_time = get_datetime( time_log.from_time) + relativedelta(minutes=d.time_in_mins) if date_diff(time_log.from_time, original_start_time) > plan_days: frappe.msgprint( _("Unable to find Time Slot in the next {0} days for Operation {1}" ).format(plan_days, d.operation)) break if _from_time == time_log.from_time: frappe.throw("Capacity Planning Error") d.planned_start_time = time_log.from_time d.planned_end_time = time_log.to_time d.db_update() if time_log.name: time_logs.append(time_log.name) self.planned_end_date = self.operations[-1].planned_end_time if time_logs: frappe.local.message_log = [] frappe.msgprint( _("Time Logs created:") + "\n" + "\n".join(time_logs))