def set_dates(self): billing_date = self.invoice.due_date.replace(day=1) self.sales_order.billing_date = billing_date.strftime("%Y%m%d") due_date = self.invoice.due_date if not is_business_day(due_date): due_date = get_next_business_day(due_date) self.invoice.adjusted_due_date = due_date self.invoice.save() value_date = due_date - relativedelta(days=settings.LASKE_DUE_DATE_OFFSET_DAYS) self.sales_order.value_date = value_date.strftime("%Y%m%d")
def calculate_penalty_interest(self, calculation_date=None): from .debt_collection import InterestRate penalty_interest_data = { "interest_start_date": None, "interest_end_date": None, "outstanding_amount": self.outstanding_amount, "total_interest_amount": Decimal(0), "interest_periods": [], } if not calculation_date: calculation_date = timezone.now().date() if not self.outstanding_amount: return penalty_interest_data interest_start_date = get_next_business_day(self.due_date) interest_end_date = calculation_date penalty_interest_data["interest_start_date"] = interest_start_date penalty_interest_data["interest_end_date"] = interest_end_date years = range(interest_start_date.year, interest_end_date.year + 1) total_interest_amount = Decimal(0) for interest_rate in InterestRate.objects.filter( start_date__year__in=years).order_by("start_date"): overlap = get_range_overlap( interest_rate.start_date, interest_rate.end_date, interest_start_date, interest_end_date, ) if not overlap or not overlap[0] or not overlap[1]: continue days_between = (overlap[1] - overlap[0]).days + 1 # Inclusive # TODO: which divisor to use # divisor = 360 if calendar.isleap(interest_rate.start_date.year): divisor = 366 else: divisor = 365 interest_amount = (self.outstanding_amount * (interest_rate.penalty_rate / 100) / divisor * days_between) penalty_interest_data["interest_periods"].append({ "start_date": overlap[0], "end_date": overlap[1], "penalty_rate": interest_rate.penalty_rate, "interest_amount": interest_amount, }) total_interest_amount += interest_amount penalty_interest_data[ "total_interest_amount"] = total_interest_amount.quantize( Decimal(".01"), rounding=ROUND_HALF_UP) return penalty_interest_data
def test_get_next_business_day(the_day, expected): if inspect.isclass(expected) and issubclass(expected, Exception): with pytest.raises(expected): get_next_business_day(the_day) else: assert get_next_business_day(the_day) == expected