Skip to content

Commit e46c0e9

Browse files
committed
v0.5.4.2
Make Payments Method IODatabaseMixIn Optimization
1 parent 44c344f commit e46c0e9

File tree

15 files changed

+391
-164
lines changed

15 files changed

+391
-164
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,3 +113,4 @@ data/
113113
oauth_codes.json
114114
http-client.private.env.json
115115
docs/source/README.md
116+
assets/.yarn

django_ledger/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
default_app_config = 'django_ledger.apps.DjangoLedgerConfig'
1010

1111
"""Django Ledger"""
12-
__version__ = '0.5.4.1'
12+
__version__ = '0.5.4.2'
1313
__license__ = 'GPLv3 License'
1414

1515
__author__ = 'Miguel Sanda'

django_ledger/io/data_generator.py

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -730,15 +730,14 @@ def fund_entity(self):
730730
capital_acc = choice(self.accounts_by_role[EQUITY_CAPITAL])
731731
cash_acc = choice(self.bank_account_models).cash_account
732732

733-
ledger_model: LedgerModel = self.entity_model.add_equity(
734-
user_model=self.user_model,
735-
amount=self.capital_contribution,
733+
self.entity_model.deposit_capital(
736734
cash_account=cash_acc,
737-
equity_account=capital_acc,
738-
txs_date=self.start_date,
739-
ledger_name='Entity Funding for Sample Data',
735+
capital_account=capital_acc,
736+
amount=self.capital_contribution,
737+
je_timestamp=self.start_date,
738+
je_posted=True,
740739
ledger_posted=True,
741-
je_posted=True
740+
description='Entity Funding for Sample Data',
742741
)
743742

744743
def recount_inventory(self):

django_ledger/io/io_mixin.py

Lines changed: 33 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
from django.db.models.functions import TruncMonth
2020
from django.http import Http404
2121
from django.utils.dateparse import parse_date, parse_datetime
22-
from django.utils.timezone import localdate, make_aware, is_naive
22+
from django.utils.timezone import make_aware, is_naive, localtime
2323

2424
from django_ledger.exceptions import InvalidDateInputError, TransactionNotInBalanceError
2525
from django_ledger.io import roles as roles_module
@@ -96,19 +96,21 @@ def balance_tx_data(tx_data: list, perform_correction: bool = True) -> bool:
9696
return True
9797

9898

99-
def validate_io_date(dt: Union[str, date, datetime], no_parse_localdate: bool = True) -> Union[datetime]:
99+
def validate_io_date(dt: Union[str, date, datetime], no_parse_localdate: bool = True) -> Optional[datetime]:
100+
if not dt:
101+
return
102+
100103
if isinstance(dt, date):
101-
dt = make_aware(datetime.combine(
102-
dt,
103-
datetime.min.time()
104-
))
104+
dt = make_aware(
105+
value=datetime.combine(
106+
dt,
107+
datetime.min.time()
108+
))
105109
return dt
106-
107110
elif isinstance(dt, datetime):
108111
if is_naive(dt):
109112
return make_aware(dt)
110113
return dt
111-
112114
elif isinstance(dt, str):
113115
# try to parse a date object from string...
114116
fdt = parse_date(dt)
@@ -124,7 +126,7 @@ def validate_io_date(dt: Union[str, date, datetime], no_parse_localdate: bool =
124126
return fdt
125127

126128
if no_parse_localdate:
127-
return localdate()
129+
return localtime()
128130

129131

130132
def validate_dates(
@@ -611,11 +613,6 @@ def digest(self,
611613
cash_flow_statement: bool = False,
612614
) -> Union[Tuple, IODigest]:
613615

614-
io_data = defaultdict(lambda: dict())
615-
io_data['io_model'] = self
616-
io_data['from_date'] = from_date
617-
io_data['to_date'] = to_date
618-
619616
if balance_sheet_statement:
620617
from_date = None
621618

@@ -629,6 +626,11 @@ def digest(self,
629626

630627
from_date, to_date = validate_dates(from_date, to_date)
631628

629+
io_data = defaultdict(lambda: dict())
630+
io_data['io_model'] = self
631+
io_data['from_date'] = from_date
632+
io_data['to_date'] = to_date
633+
632634
txs_qs, accounts_digest = self.python_digest(
633635
txs_queryset=txs_queryset,
634636
user_model=user_model,
@@ -714,10 +716,10 @@ def digest(self,
714716
return txs_qs, digest_results
715717

716718
def commit_txs(self,
717-
je_date: Union[str, datetime, date],
718-
je_txs: list,
719+
je_timestamp: Union[str, datetime, date],
720+
je_txs: List[Dict],
719721
je_posted: bool = False,
720-
je_ledger=None,
722+
je_ledger_model=None,
721723
je_desc=None,
722724
je_origin=None):
723725
"""
@@ -731,36 +733,39 @@ def commit_txs(self,
731733
'staged_tx_model': StagedTransactionModel or None
732734
}]
733735
734-
:param je_date:
736+
:param je_timestamp:
735737
:param je_txs:
736738
:param je_activity:
737739
:param je_posted:
738-
:param je_ledger:
740+
:param je_ledger_model:
739741
:param je_desc:
740742
:param je_origin:
741743
:param je_parent:
742744
:return:
743745
"""
746+
747+
# if isinstance(self, lazy_loader.get_entity_model()):
748+
744749
# Validates that credits/debits balance.
745750
balance_tx_data(je_txs)
746751

747752
if all([
748753
isinstance(self, lazy_loader.get_entity_model()),
749-
not je_ledger
754+
not je_ledger_model
750755
]):
751756
raise ValidationError('Must pass an instance of LedgerModel')
752757

753-
if not je_ledger:
754-
je_ledger = self
758+
if not je_ledger_model:
759+
je_ledger_model = self
755760

756761
JournalEntryModel = lazy_loader.get_journal_entry_model()
757762

758-
je_date = validate_io_date(dt=je_date)
763+
je_timestamp = validate_io_date(dt=je_timestamp)
759764

760765
je_model = JournalEntryModel(
761-
ledger=je_ledger,
766+
ledger=je_ledger_model,
762767
description=je_desc,
763-
timestamp=je_date,
768+
timestamp=je_timestamp,
764769
origin=je_origin,
765770
)
766771

@@ -770,13 +775,10 @@ def commit_txs(self,
770775
TransactionModel = lazy_loader.get_txs_model()
771776
txs_models = [
772777
TransactionModel(
773-
account_id=tx['account_id'],
774-
tx_type=tx['tx_type'],
775-
amount=tx['amount'],
776-
description=tx['description'],
778+
**txm_kwargs,
777779
journal_entry=je_model,
778-
stagedtransactionmodel=tx.get('staged_tx_model')
779-
) for tx in je_txs
780+
stagedtransactionmodel=txm_kwargs.get('staged_tx_model')
781+
) for txm_kwargs in je_txs
780782
]
781783
txs_models = TransactionModel.objects.bulk_create(txs_models)
782784

django_ledger/models/bill.py

Lines changed: 94 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
>>> bill_model.save()
2020
"""
2121

22-
from datetime import date
22+
from datetime import date, datetime
2323
from decimal import Decimal
2424
from typing import Union, Optional, Tuple, Dict, List
2525
from uuid import uuid4
@@ -31,7 +31,7 @@
3131
from django.db.models.signals import post_delete, pre_save
3232
from django.shortcuts import get_object_or_404
3333
from django.urls import reverse
34-
from django.utils.timezone import localdate
34+
from django.utils.timezone import localdate, localtime
3535
from django.utils.translation import gettext_lazy as _
3636

3737
from django_ledger.models.entity import EntityModel
@@ -906,16 +906,88 @@ def can_generate_bill_number(self) -> bool:
906906
self.is_configured()
907907
])
908908

909-
# --> URLs <---
910-
def get_absolute_url(self):
911-
return reverse('django_ledger:bill-detail',
912-
kwargs={
913-
'entity_slug': self.ledger.entity.slug,
914-
'bill_pk': self.uuid
915-
})
909+
# ACTIONS ---
910+
911+
def can_make_payment(self) -> bool:
912+
"""
913+
Checks if the BillModel can accept a payment.
914+
915+
916+
Returns
917+
_______
918+
919+
bool
920+
True if can bind provided PurchaseOderModel, else False.
921+
"""
922+
return self.is_approved()
916923

917-
# --> ACTIONS <---
918-
def action_bind_estimate(self, estimate_model, commit: bool = False, raise_exception: bool = True):
924+
def make_payment(self,
925+
payment_amount: Union[Decimal, float, int],
926+
payment_date: Optional[Union[datetime, date]] = None,
927+
commit: bool = False,
928+
raise_exception: bool = True):
929+
"""
930+
Makes a payment to the BillModel.
931+
932+
933+
Parameters
934+
__________
935+
936+
payment_amount: Decimal ot float
937+
The payment amount to process.
938+
939+
payment_date: datetime or date.
940+
Date or timestamp of the payment being applied.
941+
942+
commit: bool
943+
If True, commits the transaction into the DB. Defaults to False.
944+
945+
raise_exception: bool
946+
If True, raises BillModelValidationError if payment exceeds amount due, else False.
947+
948+
Returns
949+
_______
950+
951+
bool
952+
True if can make payment, else False.
953+
"""
954+
955+
if isinstance(payment_amount, float):
956+
payment_amount = Decimal.from_float(payment_amount)
957+
elif isinstance(payment_amount, int):
958+
payment_amount = Decimal.from_float(float(payment_amount))
959+
self.amount_paid += payment_amount
960+
961+
if self.amount_paid > self.amount_due:
962+
if raise_exception:
963+
raise BillModelValidationError(
964+
f'Amount paid: {self.amount_paid} exceed amount due: {self.amount_due}.'
965+
)
966+
return
967+
968+
self.get_state(commit=True)
969+
self.clean()
970+
971+
if not payment_date:
972+
payment_date = localtime()
973+
974+
if commit:
975+
self.migrate_state(
976+
user_model=None,
977+
entity_slug=self.ledger.entity.slug,
978+
je_timestamp=payment_date,
979+
raise_exception=True
980+
)
981+
self.save(
982+
update_fields=[
983+
'amount_paid',
984+
'amount_earned',
985+
'amount_unearned',
986+
'amount_receivable',
987+
'updated'
988+
])
989+
990+
def bind_estimate(self, estimate_model, commit: bool = False, raise_exception: bool = True):
919991
"""
920992
Binds BillModel to a given EstimateModel. Raises ValueError if EstimateModel cannot be bound.
921993
@@ -1168,7 +1240,7 @@ def mark_as_approved(self,
11681240
self.migrate_state(
11691241
entity_slug=entity_slug,
11701242
user_model=user_model,
1171-
je_date=date_approved,
1243+
je_timestamp=date_approved,
11721244
force_migrate=self.accrue
11731245
)
11741246
self.ledger.post(commit=commit)
@@ -1226,6 +1298,7 @@ def mark_as_paid(self,
12261298
itemtxs_qs: Optional[ItemTransactionModelQuerySet] = None,
12271299
commit: bool = False,
12281300
**kwargs):
1301+
12291302
"""
12301303
Marks BillModel as Paid.
12311304
@@ -1290,7 +1363,7 @@ def mark_as_paid(self,
12901363
user_model=user_model,
12911364
entity_slug=entity_slug,
12921365
itemtxs_qs=itemtxs_qs,
1293-
je_date=date_paid,
1366+
je_timestamp=date_paid,
12941367
force_migrate=True
12951368
)
12961369
self.lock_ledger(commit=True)
@@ -1725,6 +1798,14 @@ def generate_bill_number(self, commit: bool = False) -> str:
17251798
def generate_descriptive_title(self) -> str:
17261799
return f'Bill {self.bill_number} | {self.get_bill_status_display()} {self.get_status_action_date()} | {self.vendor.vendor_name}'
17271800

1801+
# --> URLs <---
1802+
def get_absolute_url(self):
1803+
return reverse('django_ledger:bill-detail',
1804+
kwargs={
1805+
'entity_slug': self.ledger.entity.slug,
1806+
'bill_pk': self.uuid
1807+
})
1808+
17281809
def clean(self, commit: bool = True):
17291810
"""
17301811
Clean method for BillModel. Results in a DB query if bill number has not been generated and the BillModel is

0 commit comments

Comments
 (0)