Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CodeSpaces Development Environment #151

Open
wants to merge 3 commits into
base: v0.5.5.0
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"name": "Django Ledger Development Codespace",
"image": "python:3.11-bookworm"
}
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -113,3 +113,4 @@ data/
oauth_codes.json
http-client.private.env.json
docs/source/README.md
assets/.yarn
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,15 +89,15 @@ More details available in the [Django Ledger v0.5 Page](https://www.arrobalytics
* Hierarchical Account Model Management.
* Generate all Django Ledger Model documentation.
* ~~__0.5.3__~~: High Level EntityModel API.
* __0.5.4__: Balance Sheet Statement, Income Statement & Cash Flow Statement API & PDF report export.
* ~~__0.5.4__~~: Balance Sheet Statement, Income Statement & Cash Flow Statement API & PDF report export.
* __0.5.5__: Closing entries and snapshots.
* __0.5.6__: Chart of Accounts Import.
* __0.5.7__: Trial Balance Import.
* __0.5.8__: GraphQL API.

### Version 0.6

* IO Digest Context Manager

* Credit Line Models.
* Time tracking.
* Transaction tagging.
Expand All @@ -119,7 +119,7 @@ More details available in the [Django Ledger v0.5 Page](https://www.arrobalytics

### Version 0.9

* Enable Hierarchical Entity structures via TreeBeard.
* Enable Hierarchical Entity Structures.
* Consolidated financial statements.
* InterCompany transactions.
* Update package and code documentation.
Expand Down
2 changes: 1 addition & 1 deletion django_ledger/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
default_app_config = 'django_ledger.apps.DjangoLedgerConfig'

"""Django Ledger"""
__version__ = '0.5.4.1'
__version__ = '0.5.4.2'
__license__ = 'GPLv3 License'

__author__ = 'Miguel Sanda'
Expand Down
13 changes: 6 additions & 7 deletions django_ledger/io/data_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -730,15 +730,14 @@ def fund_entity(self):
capital_acc = choice(self.accounts_by_role[EQUITY_CAPITAL])
cash_acc = choice(self.bank_account_models).cash_account

ledger_model: LedgerModel = self.entity_model.add_equity(
user_model=self.user_model,
amount=self.capital_contribution,
self.entity_model.deposit_capital(
cash_account=cash_acc,
equity_account=capital_acc,
txs_date=self.start_date,
ledger_name='Entity Funding for Sample Data',
capital_account=capital_acc,
amount=self.capital_contribution,
je_timestamp=self.start_date,
je_posted=True,
ledger_posted=True,
je_posted=True
description='Entity Funding for Sample Data',
)

def recount_inventory(self):
Expand Down
2 changes: 1 addition & 1 deletion django_ledger/io/io_digest.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class IODigestValidationError(ValidationError):
pass


class IODigest:
class IODigestContextManager:

def __init__(self, io_data: defaultdict):
self.IO_DATA: defaultdict = io_data
Expand Down
76 changes: 39 additions & 37 deletions django_ledger/io/io_mixin.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@
from django.db.models.functions import TruncMonth
from django.http import Http404
from django.utils.dateparse import parse_date, parse_datetime
from django.utils.timezone import localdate, make_aware, is_naive
from django.utils.timezone import make_aware, is_naive, localtime

from django_ledger.exceptions import InvalidDateInputError, TransactionNotInBalanceError
from django_ledger.io import roles as roles_module
from django_ledger.io.io_context import (RoleContextManager, GroupContextManager, ActivityContextManager,
BalanceSheetStatementContextManager, IncomeStatementContextManager,
CashFlowStatementContextManager)
from django_ledger.io.io_digest import IODigest
from django_ledger.io.io_digest import IODigestContextManager
from django_ledger.io.ratios import FinancialRatioManager
from django_ledger.models.utils import lazy_loader
from django_ledger.settings import (DJANGO_LEDGER_TRANSACTION_MAX_TOLERANCE,
Expand Down Expand Up @@ -96,19 +96,21 @@ def balance_tx_data(tx_data: list, perform_correction: bool = True) -> bool:
return True


def validate_io_date(dt: Union[str, date, datetime], no_parse_localdate: bool = True) -> Union[datetime]:
def validate_io_date(dt: Union[str, date, datetime], no_parse_localdate: bool = True) -> Optional[datetime]:
if not dt:
return

if isinstance(dt, date):
dt = make_aware(datetime.combine(
dt,
datetime.min.time()
))
dt = make_aware(
value=datetime.combine(
dt,
datetime.min.time()
))
return dt

elif isinstance(dt, datetime):
if is_naive(dt):
return make_aware(dt)
return dt

elif isinstance(dt, str):
# try to parse a date object from string...
fdt = parse_date(dt)
Expand All @@ -124,7 +126,7 @@ def validate_io_date(dt: Union[str, date, datetime], no_parse_localdate: bool =
return fdt

if no_parse_localdate:
return localdate()
return localtime()


def validate_dates(
Expand Down Expand Up @@ -167,7 +169,7 @@ def digest_balance_sheet(self,
to_date: Union[date, datetime],
user_model: UserModel,
txs_queryset: Optional[QuerySet] = None,
**kwargs: Dict) -> Union[IODigest, Tuple[QuerySet, Dict]]:
**kwargs: Dict) -> Union[IODigestContextManager, Tuple[QuerySet, Dict]]:
return self.digest(
user_model=user_model,
to_date=to_date,
Expand Down Expand Up @@ -215,7 +217,7 @@ def digest_income_statement(self,
to_date: Union[date, datetime],
user_model: Optional[UserModel] = None,
txs_queryset: Optional[QuerySet] = None,
**kwargs) -> Union[IODigest, Tuple[QuerySet, Dict]]:
**kwargs) -> Union[IODigestContextManager, Tuple[QuerySet, Dict]]:
return self.digest(
user_model=user_model,
from_date=from_date,
Expand Down Expand Up @@ -265,7 +267,7 @@ def digest_cash_flow_statement(self,
to_date: Union[date, datetime],
user_model: UserModel,
txs_queryset: Optional[QuerySet] = None,
**kwargs) -> Union[IODigest, Tuple[QuerySet, Dict]]:
**kwargs) -> Union[IODigestContextManager, Tuple[QuerySet, Dict]]:
return self.digest(
user_model=user_model,
from_date=from_date,
Expand Down Expand Up @@ -609,12 +611,7 @@ def digest(self,
balance_sheet_statement: bool = False,
income_statement: bool = False,
cash_flow_statement: bool = False,
) -> Union[Tuple, IODigest]:

io_data = defaultdict(lambda: dict())
io_data['io_model'] = self
io_data['from_date'] = from_date
io_data['to_date'] = to_date
) -> Union[Tuple, IODigestContextManager]:

if balance_sheet_statement:
from_date = None
Expand All @@ -629,6 +626,11 @@ def digest(self,

from_date, to_date = validate_dates(from_date, to_date)

io_data = defaultdict(lambda: dict())
io_data['io_model'] = self
io_data['from_date'] = from_date
io_data['to_date'] = to_date

txs_qs, accounts_digest = self.python_digest(
txs_queryset=txs_queryset,
user_model=user_model,
Expand Down Expand Up @@ -702,7 +704,7 @@ def digest(self,
io_data = cfs.digest()

if as_io_digest:
return IODigest(io_data=io_data)
return IODigestContextManager(io_data=io_data)

if not digest_name:
digest_name = 'tx_digest'
Expand All @@ -714,10 +716,10 @@ def digest(self,
return txs_qs, digest_results

def commit_txs(self,
je_date: Union[str, datetime, date],
je_txs: list,
je_timestamp: Union[str, datetime, date],
je_txs: List[Dict],
je_posted: bool = False,
je_ledger=None,
je_ledger_model=None,
je_desc=None,
je_origin=None):
"""
Expand All @@ -731,36 +733,39 @@ def commit_txs(self,
'staged_tx_model': StagedTransactionModel or None
}]

:param je_date:
:param je_timestamp:
:param je_txs:
:param je_activity:
:param je_posted:
:param je_ledger:
:param je_ledger_model:
:param je_desc:
:param je_origin:
:param je_parent:
:return:
"""

# if isinstance(self, lazy_loader.get_entity_model()):

# Validates that credits/debits balance.
balance_tx_data(je_txs)

if all([
isinstance(self, lazy_loader.get_entity_model()),
not je_ledger
not je_ledger_model
]):
raise ValidationError('Must pass an instance of LedgerModel')

if not je_ledger:
je_ledger = self
if not je_ledger_model:
je_ledger_model = self

JournalEntryModel = lazy_loader.get_journal_entry_model()

je_date = validate_io_date(dt=je_date)
je_timestamp = validate_io_date(dt=je_timestamp)

je_model = JournalEntryModel(
ledger=je_ledger,
ledger=je_ledger_model,
description=je_desc,
timestamp=je_date,
timestamp=je_timestamp,
origin=je_origin,
)

Expand All @@ -770,13 +775,10 @@ def commit_txs(self,
TransactionModel = lazy_loader.get_txs_model()
txs_models = [
TransactionModel(
account_id=tx['account_id'],
tx_type=tx['tx_type'],
amount=tx['amount'],
description=tx['description'],
**txm_kwargs,
journal_entry=je_model,
stagedtransactionmodel=tx.get('staged_tx_model')
) for tx in je_txs
stagedtransactionmodel=txm_kwargs.get('staged_tx_model')
) for txm_kwargs in je_txs
]
txs_models = TransactionModel.objects.bulk_create(txs_models)

Expand Down
Loading