def parse_date_range_arguments(options: dict, default_range: str = "last_month", tz: Any = None) -> Tuple[datetime, datetime, List[Tuple[datetime, datetime]]]: """ Parses date range from input and returns timezone-aware date range and interval list according to 'step' name argument (optional). See add_date_range_arguments() :param options: Parsed arguments passed to the command :param default_range: Default datetime range to return if no other selected :param tz: Optional timezone to use. Default is UTC. :return: begin, end, [(begin1,end1), (begin2,end2), ...] """ begin, end = get_date_range_by_name(default_range, tz=tz) for range_name in TIME_RANGE_NAMES: if options.get(range_name): begin, end = get_date_range_by_name(range_name, tz=tz) if options.get("begin"): begin = parse_datetime(options["begin"], tz) # type: ignore end = now() if options.get("end"): end = parse_datetime(options["end"], tz) # type: ignore step_type = "" for step_name in TIME_STEP_NAMES: if options.get(step_name): if step_type: raise ValueError("Cannot use --{} and --{} simultaneously".format(step_type, step_name)) step_type = step_name if step_type: steps = get_time_steps(step_type, begin, end) else: steps = [(begin, end)] return begin, end, steps
def fetch_latest_euribor_rates(commit: bool = False, verbose: bool = False) -> List[EuriborRate]: feed_url = ( "https://www.suomenpankki.fi/WebForms/ReportViewerPage.aspx?report=/tilastot/markkina-_ja_hallinnolliset_korot/euribor_korot_today_xml_en&output=xml" ) res = requests.get(feed_url) if verbose: logger.info("GET %s HTTP %s\n%s", feed_url, res.status_code, res.content) if res.status_code >= 300: raise Exception(f"Failed to load Euribor rate feed from {feed_url}") results = xml_to_dict(res.content) data = results["data"]["period_Collection"]["period"] rates: List[EuriborRate] = [] if isinstance(data, list): # Sometime get a list or single item assert len(data) > 0 data = data[len(data) - 1] # Get from newest date record_date = parse_datetime(data["@value"]).date() for rate_data in data["matrix1_Title_Collection"]["rate"]: name = rate_data["@name"] rate = dec4(rate_data["intr"]["@value"]) obj = EuriborRate(name=name, record_date=record_date, rate=rate) rates.append(obj) if commit: out: List[EuriborRate] = [] for obj in rates: out.append( EuriborRate.objects.save_unique(obj.record_date, obj.name, obj.rate)) return out return rates
def test_account(self): print("test_account") settlements = create_account_by_type(ACCOUNT_SETTLEMENTS) assert isinstance(settlements, Account) amounts = [12, "13.12", "-1.23", "20.00"] balances = [ Decimal("12.00"), Decimal("25.12"), Decimal("23.89"), Decimal("43.89") ] t = parse_datetime("2016-06-13T01:00:00") dt = timedelta(minutes=5) times = [t + dt * i for i in range(len(amounts))] for i in range(len(times)): amount = amounts[i] t = times[i] e = AccountEntry(account=settlements, amount=Decimal(amount), type=EntryType.objects.get(code=E_SETTLEMENT), timestamp=t) e.full_clean() e.save() self.assertEqual(settlements.balance, balances[i]) self.assertEqual(settlements.balance, e.balance) for i in range(len(times)): t = times[i] self.assertEqual(settlements.get_balance(t + timedelta(seconds=1)), balances[i])
def camt053_get_dt(data: Dict[str, Any], key: str, name: str = "") -> datetime: s = camt053_get_val(data, key, None, True, name) val = parse_datetime(s) if val is None: raise ValidationError( _("camt.053 field {} type {} missing or invalid").format( name, "datetime") + ": {}".format(s)) return val
def test_add_month(self): t = parse_datetime('2016-06-12T01:00:00') self.assertEqual(t.isoformat(), '2016-06-12T01:00:00+00:00') t2 = add_month(t) self.assertEqual(t2.isoformat(), '2016-07-12T01:00:00+00:00') t3 = add_month(t, 7) self.assertEqual(t3.isoformat(), '2017-01-12T01:00:00+00:00') t4 = add_month(t, -1) self.assertEqual(t4.isoformat(), '2016-05-12T01:00:00+00:00')
def parse_start_and_end_date( tz: Any, **options) -> Tuple[Optional[date], Optional[date]]: start_date = None end_date = None time_now = now().astimezone(tz if tz else pytz.utc) if options["start_date"]: if options["start_date"] == "today": start_date = time_now.date() else: start_date = parse_datetime( options["start_date"]).date() # type: ignore end_date = start_date if options["end_date"]: if options["end_date"] == "today": end_date = time_now.date() else: end_date = parse_datetime( options["end_date"]).date() # type: ignore return start_date, end_date
def test_invoice(self): print("test_invoice") settlements = create_account_by_type(ACCOUNT_SETTLEMENTS) receivables_acc = create_account_by_type(ACCOUNT_RECEIVABLES) assert isinstance(settlements, Account) # create invoices t = parse_datetime("2016-05-05") amounts = [ Decimal("120.00"), Decimal("100.00"), Decimal("50.00"), Decimal("40.00"), ] n = len(amounts) times = [add_month(t, i) for i in range(n)] invoices = [] for t, amount in zip(times, amounts): invoice = Invoice(due_date=t) invoice.full_clean() invoice.save() AccountEntry.objects.create( account=receivables_acc, source_invoice=invoice, type=EntryType.objects.get(code=E_RENT), amount=amount) invoice.update_cached_fields() self.assertEqual(invoice.unpaid_amount, amount) invoices.append(invoice) # print(invoice) unpaid_invoices = [i for i in invoices] # create payments payment_ops = [ (None, [ Decimal("120.00"), Decimal("100.00"), Decimal("50.00"), Decimal("40.00") ]), (Decimal("50.00"), [ Decimal("70.00"), Decimal("100.00"), Decimal("50.00"), Decimal("40.00") ]), (Decimal("70.50"), [ Decimal("00.00"), Decimal("100.00"), Decimal("50.00"), Decimal("40.00") ]), (Decimal("100.00"), [ Decimal("00.00"), Decimal("00.00"), Decimal("50.00"), Decimal("40.00") ]), (Decimal("100.00"), [ Decimal("00.00"), Decimal("00.00"), Decimal("00.00"), Decimal("40.00") ]), ] for j in range(len(payment_ops)): print("test_invoice: Payment op test", j) for i in range(n): inv = invoices[i] assert isinstance(inv, Invoice) paid_amount, unpaid_amounts = payment_ops[j] if paid_amount is not None: p = AccountEntry.objects.create( account=settlements, settled_invoice=unpaid_invoices[0], amount=paid_amount, type=EntryType.objects.get(code=E_MANUAL_SETTLEMENT), ) settle_assigned_invoice(receivables_acc, p, AccountEntry) if unpaid_invoices[0].is_paid: unpaid_invoices = unpaid_invoices[1:] for i in range(n): inv = invoices[i] assert isinstance(inv, Invoice) for i in range(n): paid_amount_real = invoices[i] unpaid_amount_real = invoices[i].get_unpaid_amount() unpaid_amount_ref = unpaid_amounts[i] print( "checking invoice {} payment status after payment op {} (real {}, expected {})" .format(i, j, unpaid_amount_real, unpaid_amount_ref)) self.assertEqual(unpaid_amount_real, unpaid_amount_ref, "[{}][{}]".format(j, i)) # create another acc set settlements = create_account_by_type(ACCOUNT_SETTLEMENTS) assert isinstance(settlements, Account) receivables_acc = create_account_by_type(ACCOUNT_RECEIVABLES) assert isinstance(receivables_acc, Account) # create invoices t = parse_datetime("2016-05-05") amounts = [ Decimal("120.00"), Decimal("100.00"), Decimal("50.00"), Decimal("40.00") ] n = len(amounts) times = [add_month(t, i) for i in range(n)] invoices = [] for t, amount in zip(times, amounts): invoice = Invoice(due_date=t) invoice.full_clean() invoice.save() AccountEntry.objects.create( account=receivables_acc, source_invoice=invoice, type=EntryType.objects.get(code=E_RENT), amount=amount) invoice.update_cached_fields() self.assertEqual(invoice.unpaid_amount, amount) invoices.append(invoice) print("invoice created", invoice) unpaid_invoices = [i for i in invoices] # create payments: # paid_amount, unpaid_amounts (after payment) payment_ops = [ (None, [ Decimal("120.00"), Decimal("100.00"), Decimal("50.00"), Decimal("40.00") ]), (Decimal("250.00"), [ Decimal("0.00"), Decimal("100.00"), Decimal("50.00"), Decimal("40.00") ]), ] for j in range(len(payment_ops)): paid_amount, unpaid_amounts = payment_ops[j] if paid_amount is not None and paid_amount > Decimal("0.00"): invoice = unpaid_invoices[0] print("Targeting settlement amount", paid_amount, "to invoice", invoice, "invoice.amount", invoice.amount) p = AccountEntry.objects.create( account=settlements, amount=paid_amount, settled_invoice=invoice, type=EntryType.objects.get(code=E_MANUAL_SETTLEMENT), ) settle_assigned_invoice(receivables_acc, p, AccountEntry) if invoice.is_paid: unpaid_invoices = unpaid_invoices[1:] print("invoice paid, now left", unpaid_invoices) for i in range(n): unpaid_amount_real = invoices[i].get_unpaid_amount() unpaid_amount_ref = unpaid_amounts[i] self.assertEqual(unpaid_amount_real, unpaid_amount_ref, "[{}][{}]".format(j, i)) # check that the first payment has E_RENT 120 inv = invoices[0] assert isinstance(inv, Invoice) es = inv.receivables.order_by("id") self.assertEqual(es[0].amount, Decimal("120.00")) self.assertEqual(es[1].amount, Decimal("-120.00")) self.assertIsNotNone(es[1].parent) self.assertTrue(es[1].parent.type.is_settlement) self.assertEqual(es[1].parent.amount, Decimal("250.00"))