def test_get_periods_billing_date_as_month_end(self): '''Test get_periods for billing dates falling in end of the month''' actual = get_periods(31, '2018-01-14', 5) expected = [ { 'start_date': getdate('2017-09-30'), 'end_date': getdate('2017-10-30'), 'as_text': '2017-09-30 - 2017-10-30' }, { 'start_date': getdate('2017-10-31'), 'end_date': getdate('2017-11-29'), 'as_text': '2017-10-31 - 2017-11-29' }, { 'start_date': getdate('2017-11-30'), 'end_date': getdate('2017-12-30'), 'as_text': '2017-11-30 - 2017-12-30' }, { 'start_date': getdate('2017-12-31'), 'end_date': getdate('2018-01-30'), 'as_text': '2017-12-31 - 2018-01-30' }, { 'start_date': getdate('2018-01-31'), 'end_date': getdate('2018-02-27'), 'as_text': '2018-01-31 - 2018-02-27' }, ] self.assertEqual(actual, expected)
def get_off_days(from_date, to_date, company): off_days = 0 year = getdate(from_date).strftime("%Y") holiday_lists = frappe.db.sql( """SELECT `year`, `public_holiday_list` FROM `tabPublic Holiday List` WHERE `year` = '{year}' AND `company` = '{company}' LIMIT 1""" .format(year=year, company=company), as_dict=True) if len(holiday_lists) > 0: holiday_list = holiday_lists[0].public_holiday_list _holiday_list_entries = frappe.db.sql( """SELECT `holiday_date` FROM `tabHoliday` WHERE `parent` = '{holiday_list}'""" .format(holiday_list=holiday_list), as_list=True) holiday_list_entries = [] for entry in _holiday_list_entries: holiday_list_entries.append(entry[0]) start_date = getdate(from_date) end_date = getdate(to_date) delta = timedelta(days=1) while start_date <= end_date: if start_date in holiday_list_entries: off_days += 1 start_date += delta return off_days
def add_busse(mitglied, busse, datum, beschreibung=None, training=None, spiel=None, betrag=None): if busse == "Eigene": mitglied = frappe.get_doc("TeamPlaner Mitglied", mitglied) row = mitglied.append('bussen', {}) row.training = training row.spiel = spiel row.bemerkung = beschreibung + " - " + getdate(datum).strftime( "%d.%m.%Y") row.betrag = betrag mitglied.save() else: mitglied = frappe.get_doc("TeamPlaner Mitglied", mitglied) busse = frappe.db.sql( """SELECT `training`, `spiel`, `betrag`, `beschreibung` FROM `tabTeamPlaner Bussenkatalog` WHERE `beschreibung` = '{beschreibung}'""" .format(beschreibung=busse), as_dict=True)[0] row = mitglied.append('bussen', {}) row.training = busse.training row.spiel = busse.spiel row.bemerkung = busse.beschreibung + " - " + getdate(datum).strftime( "%d.%m.%Y") row.betrag = busse.betrag mitglied.save() return "OK"
def handle_timesheet(user, doctype, reference, time, bemerkung='', date=nowdate()): _date = getdate(date) latest_date = getdate(add_days(nowdate(), -7)) if _date < latest_date: frappe.throw( "Sie können maximal 7 Tage in die Vergangenheit buchungen vornehmen." ) user = frappe.db.sql( """SELECT `name` FROM `tabEmployee` WHERE `user_id` = '{user}'""". format(user=user), as_list=True) if not user: frappe.throw("Es wurde kein Mitarbeiterstamm gefunden!") else: user = user[0][0] if not time: time = 0.000 else: time = float(time) ts = check_if_timesheet_exist(user, date) if ts == 'gebucht': frappe.throw("Das Timesheet vom {datum} ist bereits verbucht.".format( date=date)) elif ts == 'neuanlage': create_timesheet(user, doctype, reference, time, bemerkung, date) else: update_timesheet(ts, time, doctype, reference, user, bemerkung, date)
def _generate_items(renting): """ Create items for succeeding dates :param renting: :return: """ def make_item(invoice_date): return { "invoice_date": getdate(invoice_date), "description": "Rent Due", "is_invoice_created": 0, } items = [] if _get_invoice_on_start_date(): items.append(make_item(renting.start_invoice_date)) end_date = getdate(renting.contract_end_date) next_date = _get_next_date(getdate(renting.start_invoice_date), renting.rental_frequency) while next_date < end_date: items.append(make_item(next_date)) next_date = _get_next_date(next_date, renting.rental_frequency) return items
def validate_eligibility(doc): if isinstance(doc, six.string_types): doc = json.loads(doc) invalid_doctype = doc.get('doctype') != 'Sales Invoice' if invalid_doctype: return False einvoicing_enabled = cint(frappe.db.get_single_value('E Invoice Settings', 'enable')) if not einvoicing_enabled: return False einvoicing_eligible_from = frappe.db.get_single_value('E Invoice Settings', 'applicable_from') or '2021-04-01' if getdate(doc.get('posting_date')) < getdate(einvoicing_eligible_from): return False invalid_company = not frappe.db.get_value('E Invoice User', { 'company': doc.get('company') }) invalid_supply_type = doc.get('gst_category') not in ['Registered Regular', 'SEZ', 'Overseas', 'Deemed Export'] company_transaction = doc.get('billing_address_gstin') == doc.get('company_gstin') # if export invoice, then taxes can be empty # invoice can only be ineligible if no taxes applied and is not an export invoice no_taxes_applied = not doc.get('taxes') and not doc.get('gst_category') == 'Overseas' has_non_gst_item = any(d for d in doc.get('items', []) if d.get('is_non_gst')) if invalid_company or invalid_supply_type or company_transaction or no_taxes_applied or has_non_gst_item: return False return True
def is_current_invoice_generated(self): invoice = self.get_current_invoice() if invoice and getdate(self.current_invoice_start) <= getdate(invoice.posting_date) <= getdate(self.current_invoice_end): return True return False
def validate_eligibility(doc): if isinstance(doc, six.string_types): doc = json.loads(doc) invalid_doctype = doc.get('doctype') != 'Sales Invoice' if invalid_doctype: return False einvoicing_enabled = cint(frappe.db.get_single_value('E Invoice Settings', 'enable')) if not einvoicing_enabled: return False einvoicing_eligible_from = frappe.db.get_single_value('E Invoice Settings', 'applicable_from') or '2021-04-01' if getdate(doc.get('posting_date')) < getdate(einvoicing_eligible_from): return False invalid_company = not frappe.db.get_value('E Invoice User', { 'company': doc.get('company') }) invalid_supply_type = doc.get('gst_category') not in ['Registered Regular', 'SEZ', 'Overseas', 'Deemed Export'] company_transaction = doc.get('billing_address_gstin') == doc.get('company_gstin') no_taxes_applied = not doc.get('taxes') if invalid_company or invalid_supply_type or company_transaction or no_taxes_applied: return False return True
def hourly(): """ Expires unused points of the customers s after specified time""" customers=frappe.get_all("Customer",fields=["customer_id"]) for customer in customers: customer_id=customer.get("customer_id") doc=frappe.get_doc("Customer",customer_id) if doc.get("points_table")!=None: for raw in doc.get("points_table"): startdate=data.getdate(raw.purchase_date) enddate=data.getdate(datetime.datetime.now()) print data.date_diff(enddate,startdate) rule_engine=frappe.get_all("Rule Engine",fields=['rule_type','points_expiry_duration'], filters={"status":"Active","docstatus":1}) for rule in rule_engine: if rule.get('points_expiry_duration')=="1 Year": if data.date_diff(enddate,startdate)==365 or data.date_diff(enddate,startdate)>365: raw.status="Expired" print raw.status doc.save() if rule.get('points_expiry_duration')=="3 Months": if data.date_diff(enddate,startdate)==90 or data.date_diff(enddate,startdate)>90: raw.status="Expired" print raw.status doc.save() if rule.get('points_expiry_duration')=="6 Months": if data.date_diff(enddate,startdate)==180 or data.date_diff(enddate,startdate)>180: raw.status="Expired" print raw.status doc.save()
def process_for_past_due_date(self): """ Called by `process` if the status of the `Subscription` is 'Past Due Date'. The possible outcomes of this method are: 1. Change the `Subscription` status to 'Active' 2. Change the `Subscription` status to 'Cancelled' 3. Change the `Subscription` status to 'Unpaid' """ current_invoice = self.get_current_invoice() if not current_invoice: frappe.throw( _("Current invoice {0} is missing").format( current_invoice.invoice)) else: if not self.has_outstanding_invoice(): self.status = "Active" else: self.set_status_grace_period() # Generate invoices periodically even if current invoice are unpaid if (self.generate_new_invoices_past_due_date and not self.is_current_invoice_generated( self.current_invoice_start, self.current_invoice_end) and (self.is_postpaid_to_invoice() or self.is_prepaid_to_invoice())): prorate = frappe.db.get_single_value("Subscription Settings", "prorate") self.generate_invoice(prorate) if getdate() > getdate(self.current_invoice_end): self.update_subscription_period( add_days(self.current_invoice_end, 1))
def process_for_active(self): """ Called by `process` if the status of the `Subscription` is 'Active'. The possible outcomes of this method are: 1. Generate a new invoice 2. Change the `Subscription` status to 'Past Due Date' 3. Change the `Subscription` status to 'Cancelled' """ if not self.is_current_invoice_generated( self.current_invoice_start, self.current_invoice_end) and ( self.is_postpaid_to_invoice() or self.is_prepaid_to_invoice()): prorate = frappe.db.get_single_value("Subscription Settings", "prorate") self.generate_invoice(prorate) if getdate() > getdate( self.current_invoice_end) and self.is_prepaid_to_invoice(): self.update_subscription_period( add_days(self.current_invoice_end, 1)) if self.cancel_at_period_end and getdate() > getdate( self.current_invoice_end): self.cancel_subscription_at_period_end()
def test_get_periods(self): '''Test get_periods correct returns''' actual = get_periods(5, '2017-12-12') expected = [ { 'start_date': getdate('2017-09-05'), 'end_date': getdate('2017-10-04'), 'as_text': '2017-09-05 - 2017-10-04' }, { 'start_date': getdate('2017-10-05'), 'end_date': getdate('2017-11-04'), 'as_text': '2017-10-05 - 2017-11-04' }, { 'start_date': getdate('2017-11-05'), 'end_date': getdate('2017-12-04'), 'as_text': '2017-11-05 - 2017-12-04' }, { 'start_date': getdate('2017-12-05'), 'end_date': getdate('2018-01-04'), 'as_text': '2017-12-05 - 2018-01-04' }, { 'start_date': getdate('2018-01-05'), 'end_date': getdate('2018-02-04'), 'as_text': '2018-01-05 - 2018-02-04' }, ] self.assertEqual(actual, expected)
def current_invoice_is_past_due(self, current_invoice=None): if not current_invoice: current_invoice = self.get_current_invoice() if not current_invoice: return False else: return getdate(nowdate()) > getdate(current_invoice.due_date)
def set_plan_details_status(self): for plan in self.plans: if getdate(plan.from_date or "1900-01-01") <= getdate( nowdate()) and getdate( plan.to_date or "3000-12-31") >= getdate(nowdate()): plan.status = "Active" else: plan.status = "Inactive"
def validate_end_date(self): billing_cycle_info = self.get_billing_cycle_data() end_date = add_to_date(self.start_date, **billing_cycle_info) if self.end_date and getdate(self.end_date) <= getdate(end_date): frappe.throw( _("Subscription End Date must be after {0} as per the subscription plan" ).format(end_date))
def is_prepaid_to_invoice(self): if not self.generate_invoice_at_period_start: return False if self.is_new_subscription(): return True # Check invoice dates and make sure it doesn't have outstanding invoices return getdate(nowdate()) >= getdate(self.current_invoice_start) and not self.has_outstanding_invoice()
def berechnung_anzahl_mo_bis_fr(von, bis): anzahl_mo_bis_fr = 0 _von = getdate(von) _bis = getdate(bis) while _von <= _bis: if _von.weekday() < 5: anzahl_mo_bis_fr += 1 _von = add_days(_von, 1) return anzahl_mo_bis_fr
def is_current_invoice_paid(self): if self.is_new_subscription(): return False last_invoice = frappe.get_doc('Sales Invoice', self.invoices[-1].invoice) if getdate(last_invoice.posting_date) == getdate(self.current_invoice_start) and last_invoice.status == 'Paid': return True return False
def validate_subscription_period(self): if self.trial_period_start and getdate( self.trial_period_end) >= getdate( self.current_invoice_end) and not self.is_trial(): self.update_subscription_period(add_days(self.trial_period_end, 1)) elif self.is_new_subscription(): self.update_subscription_period(self.start) elif self.has_invoice_for_period(): self.update_subscription_period(self.current_invoice_start)
def validate(self): effective_date = frappe.get_value('Loan Plan', self.loan_plan, 'date_effective_from') if effective_date and \ getdate(effective_date) > getdate(self.posting_date): return None if self.stipulated_recovery_amount > self.loan_principal: frappe.throw("Recovery Amount cannot exceed Principal.") date_of_retirement, net_salary_amount = frappe.get_value( 'Loanee Details', {'customer': self.customer}, ['date_of_retirement', 'net_salary_amount']) force_duration, income_multiple, max_duration = frappe.get_value( 'Loan Plan', self.loan_plan, ['force_duration', 'income_multiple', 'max_duration']) check = calculate_principal_and_duration( income=net_salary_amount, loan_plan={ 'force_duration': force_duration, 'income_multiple': income_multiple, 'max_duration': max_duration, 'billing_day': getdate(self.billing_date).day, 'rate_of_interest': self.rate_of_interest, }, end_date=date_of_retirement, execution_date=self.posting_date) if self.loan_principal > flt(check.get('principal')): frappe.throw("Requested principal cannot exceed {}.".format( self.fmt_money(check.get('principal')))) if self.stipulated_recovery_amount < \ self.loan_principal / check.get('duration'): frappe.throw("Recovery Amount can be less than {}.".format( self.fmt_money(self.loan_principal / check.get('duration')))) # possible heavy db queries ahead so check for outstanding is # positioned last outstanding_principal = reduce( (lambda a, x: a + get_outstanding_principal( x.name, self.posting_date)), frappe.get_all('Loan', filters={ 'customer': self.customer, 'docstatus': 1, 'recovery_status': ('in', 'Not Started, In Progress'), }), 0) if self.loan_principal + outstanding_principal > \ flt(check.get('principal')): frappe.throw(""" Customer has existing loans of outstanding {}. Total principal should not exceed allowable principal {}. """.format(self.fmt_money(outstanding_principal), self.fmt_money(check.get('principal')))) self.expected_end_date = check.get('expected_eta')
def get_data(filters): data = [] from_date = getdate(filters.from_date) to_date = getdate(filters.to_date) # get net revenue sum_net_base_total = frappe.db.sql("""SELECT SUM(`tabSales Invoice`.`base_net_total`) AS `base_net_total` FROM `tabSales Invoice` LEFT JOIN `tabSales Team` ON `tabSales Invoice`.`name` = `tabSales Team`.`parent` WHERE `tabSales Team`.`sales_person` = '{sales_person}' AND `tabSales Invoice`.`docstatus` = '1' AND `tabSales Invoice`.`posting_date` BETWEEN '{from_date}' AND '{to_date}' """.format(sales_person=filters.sales_person, from_date=from_date, to_date=to_date), as_dict=True) net_revenue = sum_net_base_total[0]['base_net_total'] or 0 data.append({ 'platzhalter': _("Nettoumsatz Total"), 'net_amount': net_revenue }) # get transport deduction deduction = frappe.db.sql("""SELECT SUM(`debit`) AS `debit` FROM `tabGL Entry` WHERE `account` = '7300 - Transporte durch Dritte - HOH' AND `tabGL Entry`.`posting_date` BETWEEN '{from_date}' AND '{to_date}' """.format(from_date=from_date, to_date=to_date), as_dict=True) deductions = (-1) * (deduction[0]['debit'] or 0) data.append({ 'platzhalter': _("Transportkosten Total"), 'net_amount': deductions }) # get transport deduction deduction2 = frappe.db.sql("""SELECT SUM(`debit`) AS `debit` FROM `tabGL Entry` WHERE `account` LIKE '7790%' AND `tabGL Entry`.`posting_date` BETWEEN '{from_date}' AND '{to_date}' """.format(from_date=from_date, to_date=to_date), as_dict=True) deductions2 = (-1) * (deduction2[0]['debit'] or 0) data.append({'platzhalter': _("Bankgebühren"), 'net_amount': deductions2}) # intermediate sum intermediate = net_revenue + deductions + deductions2 data.append({ 'platzhalter': _("Zwischensumme"), 'net_amount': intermediate }) # commission commission = 0.03 * intermediate data.append({'platzhalter': _("Kommission"), 'net_amount': commission}) return data
def cancel_subscription_at_period_end(self): """ Called when `Subscription.cancel_at_period_end` is truthy """ if self.end_date and getdate() < getdate(self.end_date): return self.status = "Cancelled" if not self.cancelation_date: self.cancelation_date = nowdate()
def period_has_passed(end_date): """ Returns true if the given `end_date` has passed """ # todo: test for illegal time if not end_date: return True end_date = getdate(end_date) return getdate(nowdate()) > getdate(end_date)
def validate_trial_period(self): """ Runs sanity checks on trial period dates for the `Subscription` """ if self.trial_period_start and self.trial_period_end: if getdate(self.trial_period_end) < getdate(self.trial_period_start): frappe.throw(_('Trial Period End Date Cannot be before Trial Period Start Date')) elif self.trial_period_start or self.trial_period_end: frappe.throw(_('Both Trial Period Start Date and Trial Period End Date must be set'))
def validate_reading(doc): for cur in doc.get('current_reading'): cur.total=( int(cur.get('reading') or 0) + int(cur.get('reading_2') or 0)) if doc.get('last_readings'): for lst in doc.get('last_readings'): lst.total=( int(lst.get('reading') or 0) + int(lst.get('reading_2') or 0)) if int(lst.total)>int(cur.total): frappe.throw("Current Reading Must be Greater than Last Reading") if getdate(lst.date)>getdate(cur.date): frappe.throw("Current Reading <b>Date</b> Must be Greater than Last Reading")
def process_for_active(self): """ Called by `process` if the status of the `Subscription` is 'Active'. The possible outcomes of this method are: 1. Generate a new invoice 2. Change the `Subscription` status to 'Past Due Date' 3. Change the `Subscription` status to 'Cancelled' """ if getdate(nowdate()) > getdate(self.current_invoice_end) or ( getdate(nowdate()) >= getdate(self.current_invoice_end) and getdate(self.current_invoice_end) == getdate( self.current_invoice_start) ) and not self.has_outstanding_invoice(): self.generate_invoice() if self.current_invoice_is_past_due(): self.status = 'Past Due Date' if self.current_invoice_is_past_due() and getdate(nowdate()) > getdate( self.current_invoice_end): self.status = 'Past Due Date' if self.cancel_at_period_end and getdate( nowdate()) > self.current_invoice_end: self.cancel_subscription_at_period_end()
def current_invoice_is_past_due(self, current_invoice=None): """ Returns `True` if the current generated invoice is overdue """ if not current_invoice: current_invoice = self.get_current_invoice() if not current_invoice: return False else: return getdate(nowdate()) > getdate(current_invoice.due_date)
def get_friday_qty(filters): qty = 0 start_date = getdate(filters.from_date) end_date = getdate(filters.to_date) delta = timedelta(days=1) while start_date <= end_date: week_day_no = start_date.weekday() if week_day_no == 4: qty += 1 start_date += delta return qty
def validate_trial_period(self): if self.trial_period_start and self.trial_period_end: if getdate(self.trial_period_end) < getdate( self.trial_period_start): frappe.throw( _('Trial Period End Date Cannot be before Trial Period Start Date' )) elif self.trial_period_start and not self.trial_period_end: frappe.throw( _('Both Trial Period Start Date and Trial Period End Date must be set' ))
def set_current_invoice_end(self): if self.trial_period_start and getdate( self.trial_period_end) > getdate(self.current_invoice_start): self.current_invoice_end = self.trial_period_end else: billing_cycle_info = self.get_billing_cycle_data() if billing_cycle_info: self.current_invoice_end = add_to_date( self.current_invoice_start, **billing_cycle_info) else: self.current_invoice_end = get_last_day( self.current_invoice_start)
def generate_interest_receivable(posting_date): loans = frappe.get_list('Loan', ['name', 'billing_date'], filters={ 'docstatus': 1, 'recovery_status': ("in", "In Progress, Not Started"), }) for loan_dict in loans: if getdate(loan_dict.get('billing_date')).day == \ getdate(posting_date).day: loan = frappe.get_doc('Loan', loan_dict.get('name')) loan.convert_interest_to_principal(posting_date)
def _create_fiscal_years(self): try: # Assumes that exactly one fiscal year has been created so far # Creates fiscal years till oldest ledger entry date is covered from frappe.utils.data import add_years, getdate from itertools import chain smallest_ledger_entry_date = getdate(min(entry["date"] for entry in chain(*self.gl_entries.values()) if entry["date"])) oldest_fiscal_year = frappe.get_all("Fiscal Year", fields=["year_start_date", "year_end_date"], order_by="year_start_date" )[0] # Keep on creating fiscal years # until smallest_ledger_entry_date is no longer smaller than the oldest fiscal year's start date while smallest_ledger_entry_date < oldest_fiscal_year.year_start_date: new_fiscal_year = frappe.get_doc({"doctype": "Fiscal Year"}) new_fiscal_year.year_start_date = add_years(oldest_fiscal_year.year_start_date, -1) new_fiscal_year.year_end_date = add_years(oldest_fiscal_year.year_end_date, -1) if new_fiscal_year.year_start_date.year == new_fiscal_year.year_end_date.year: new_fiscal_year.year = new_fiscal_year.year_start_date.year else: new_fiscal_year.year = "{}-{}".format(new_fiscal_year.year_start_date.year, new_fiscal_year.year_end_date.year) new_fiscal_year.save() oldest_fiscal_year = new_fiscal_year frappe.db.commit() except Exception as e: self._log_error(e)
def process_for_active(self): """ Called by `process` if the status of the `Subscription` is 'Active'. The possible outcomes of this method are: 1. Generate a new invoice 2. Change the `Subscription` status to 'Past Due Date' 3. Change the `Subscription` status to 'Cancelled' """ if self.is_postpaid_to_invoice or self.is_prepaid_to_invoice: self.generate_invoice() if self.current_invoice_is_past_due(): self.status = 'Past Due Date' if self.current_invoice_is_past_due() and getdate(nowdate()) > getdate(self.current_invoice_end): self.status = 'Past Due Date' if self.cancel_at_period_end and getdate(nowdate()) > getdate(self.current_invoice_end): self.cancel_subscription_at_period_end()
def is_past_grace_period(self): """ Returns `True` if the grace period for the `Subscription` has passed """ current_invoice = self.get_current_invoice() if self.current_invoice_is_past_due(current_invoice): subscription_settings = frappe.get_single('Subscription Settings') grace_period = cint(subscription_settings.grace_period) return getdate(nowdate()) > add_days(current_invoice.due_date, grace_period)
def is_postpaid_to_invoice(self): return getdate(nowdate()) > getdate(self.current_invoice_end) or \ (getdate(nowdate()) >= getdate(self.current_invoice_end) and getdate(self.current_invoice_end) == getdate(self.current_invoice_start)) and \ not self.has_outstanding_invoice()