Skip to content

Commit

Permalink
V0.5.5.4 (#172)
Browse files Browse the repository at this point in the history
* IO Bugfixes from prior version.

* v0.5.5.4
IO BugFixes
  • Loading branch information
elarroba committed Nov 14, 2023
1 parent 5ff920a commit 11d5cfc
Show file tree
Hide file tree
Showing 6 changed files with 1,072 additions and 286 deletions.
124 changes: 62 additions & 62 deletions django_ledger/io/io_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,18 +211,20 @@ def process_activity(self):


class BalanceSheetStatementContextManager:
BS_DIGEST_KEY = 'balance_sheet'

def __init__(self, io_data: dict):
self.DIGEST = io_data
self.IO_DATA = io_data

def digest(self):
if 'group_account' in self.DIGEST:
if 'group_account' in self.IO_DATA:
gb_bs = {
bsr: list(l) for bsr, l in groupby(
chain.from_iterable(
[
self.DIGEST['group_account']['GROUP_ASSETS'],
self.DIGEST['group_account']['GROUP_LIABILITIES'],
self.DIGEST['group_account']['GROUP_CAPITAL'],
self.IO_DATA['group_account']['GROUP_ASSETS'],
self.IO_DATA['group_account']['GROUP_LIABILITIES'],
self.IO_DATA['group_account']['GROUP_CAPITAL'],
]
),
key=lambda acc: acc['role_bs'])
Expand All @@ -245,119 +247,116 @@ def digest(self):
role_data['total_balance'] = sum(a['balance'] for a in role_data['accounts'])
role_data['role_name'] = roles_module.ACCOUNT_LIST_ROLE_VERBOSE[acc_role]

bs_context['equity_balance'] = self.DIGEST['group_balance']['GROUP_EQUITY']
bs_context['retained_earnings_balance'] = self.DIGEST['group_balance']['GROUP_EARNINGS']
bs_context['liabilities_equity_balance'] = self.DIGEST['group_balance']['GROUP_LIABILITIES_EQUITY']
bs_context['equity_balance'] = self.IO_DATA['group_balance']['GROUP_EQUITY']
bs_context['retained_earnings_balance'] = self.IO_DATA['group_balance']['GROUP_EARNINGS']
bs_context['liabilities_equity_balance'] = self.IO_DATA['group_balance']['GROUP_LIABILITIES_EQUITY']

self.DIGEST['balance_sheet'] = bs_context
self.IO_DATA[self.BS_DIGEST_KEY] = bs_context

return self.DIGEST
return self.IO_DATA


class IncomeStatementContextManager:
IC_DIGEST_KEY = 'income_statement'

def __init__(self, io_data: dict):
self.DIGEST = io_data
self.IO_DATA = io_data

def digest(self):
if 'group_account' in self.DIGEST:
self.DIGEST['income_statement'] = {
if 'group_account' in self.IO_DATA:
self.IO_DATA[self.IC_DIGEST_KEY] = {
'operating': {
'revenues': [
acc for acc in self.DIGEST['group_account']['GROUP_INCOME'] if
acc for acc in self.IO_DATA['group_account']['GROUP_INCOME'] if
acc['role'] in roles_module.GROUP_IC_OPERATING_REVENUES
],
'cogs': [
acc for acc in self.DIGEST['group_account']['GROUP_COGS'] if
acc for acc in self.IO_DATA['group_account']['GROUP_COGS'] if
acc['role'] in roles_module.GROUP_IC_OPERATING_COGS
],
'expenses': [
acc for acc in self.DIGEST['group_account']['GROUP_EXPENSES'] if
acc for acc in self.IO_DATA['group_account']['GROUP_EXPENSES'] if
acc['role'] in roles_module.GROUP_IC_OPERATING_EXPENSES
]
},
'other': {
'revenues': [acc for acc in self.DIGEST['group_account']['GROUP_INCOME'] if
'revenues': [acc for acc in self.IO_DATA['group_account']['GROUP_INCOME'] if
acc['role'] in roles_module.GROUP_IC_OTHER_REVENUES],
'expenses': [acc for acc in self.DIGEST['group_account']['GROUP_EXPENSES'] if
'expenses': [acc for acc in self.IO_DATA['group_account']['GROUP_EXPENSES'] if
acc['role'] in roles_module.GROUP_IC_OTHER_EXPENSES],
}
}

for activity, ic_section in self.DIGEST['income_statement'].items():
for activity, ic_section in self.IO_DATA[self.IC_DIGEST_KEY].items():
for section, acc_list in ic_section.items():
for acc in acc_list:
acc['role_name'] = roles_module.ACCOUNT_LIST_ROLE_VERBOSE[acc['role']]

# OPERATING INCOME...
self.DIGEST['income_statement']['operating']['gross_profit'] = sum(
self.IO_DATA[self.IC_DIGEST_KEY]['operating']['gross_profit'] = sum(
acc['balance'] for acc in chain.from_iterable(
[
self.DIGEST['income_statement']['operating']['revenues'],
self.DIGEST['income_statement']['operating']['cogs']
self.IO_DATA[self.IC_DIGEST_KEY]['operating']['revenues'],
self.IO_DATA[self.IC_DIGEST_KEY]['operating']['cogs']
]
))
self.DIGEST['income_statement']['operating']['net_operating_income'] = sum(
self.IO_DATA[self.IC_DIGEST_KEY]['operating']['net_operating_income'] = sum(
acc['balance'] for acc in chain.from_iterable(
[
self.DIGEST['income_statement']['operating']['revenues'],
self.DIGEST['income_statement']['operating']['cogs'],
self.DIGEST['income_statement']['operating']['expenses'],
self.IO_DATA[self.IC_DIGEST_KEY]['operating']['revenues'],
self.IO_DATA[self.IC_DIGEST_KEY]['operating']['cogs'],
self.IO_DATA[self.IC_DIGEST_KEY]['operating']['expenses'],
]
))
self.DIGEST['income_statement']['operating']['net_operating_revenue'] = sum(
acc['balance'] for acc in self.DIGEST['income_statement']['operating']['revenues']
self.IO_DATA[self.IC_DIGEST_KEY]['operating']['net_operating_revenue'] = sum(
acc['balance'] for acc in self.IO_DATA[self.IC_DIGEST_KEY]['operating']['revenues']
)
self.DIGEST['income_statement']['operating']['net_cogs'] = sum(
acc['balance'] for acc in self.DIGEST['income_statement']['operating']['cogs']
self.IO_DATA[self.IC_DIGEST_KEY]['operating']['net_cogs'] = sum(
acc['balance'] for acc in self.IO_DATA[self.IC_DIGEST_KEY]['operating']['cogs']
)
self.DIGEST['income_statement']['operating']['net_operating_expenses'] = sum(
acc['balance'] for acc in self.DIGEST['income_statement']['operating']['expenses']
self.IO_DATA[self.IC_DIGEST_KEY]['operating']['net_operating_expenses'] = sum(
acc['balance'] for acc in self.IO_DATA[self.IC_DIGEST_KEY]['operating']['expenses']
)

# OTHER INCOME....
self.DIGEST['income_statement']['other']['net_other_revenues'] = sum(
acc['balance'] for acc in self.DIGEST['income_statement']['other']['revenues']
self.IO_DATA[self.IC_DIGEST_KEY]['other']['net_other_revenues'] = sum(
acc['balance'] for acc in self.IO_DATA[self.IC_DIGEST_KEY]['other']['revenues']
)
self.DIGEST['income_statement']['other']['net_other_expenses'] = sum(
acc['balance'] for acc in self.DIGEST['income_statement']['other']['expenses']
self.IO_DATA[self.IC_DIGEST_KEY]['other']['net_other_expenses'] = sum(
acc['balance'] for acc in self.IO_DATA[self.IC_DIGEST_KEY]['other']['expenses']
)
self.DIGEST['income_statement']['other']['net_other_income'] = sum(
self.IO_DATA[self.IC_DIGEST_KEY]['other']['net_other_income'] = sum(
acc['balance'] for acc in chain.from_iterable(
[
self.DIGEST['income_statement']['other']['revenues'],
self.DIGEST['income_statement']['other']['expenses']
self.IO_DATA[self.IC_DIGEST_KEY]['other']['revenues'],
self.IO_DATA[self.IC_DIGEST_KEY]['other']['expenses']
]
))

# NET INCOME...
self.DIGEST['income_statement']['net_income'] = self.DIGEST['income_statement']['operating'][
self.IO_DATA[self.IC_DIGEST_KEY]['net_income'] = self.IO_DATA[self.IC_DIGEST_KEY]['operating'][
'net_operating_income']
self.DIGEST['income_statement']['net_income'] += self.DIGEST['income_statement']['other'][
self.IO_DATA[self.IC_DIGEST_KEY]['net_income'] += self.IO_DATA[self.IC_DIGEST_KEY]['other'][
'net_other_income']
return self.DIGEST
return self.IO_DATA


class CashFlowStatementContextManager:
CFS_DIGEST_KEY = 'cash_flow_statement'

# todo: implement by period and by unit...
def __init__(self,
io_data: dict,
by_period: bool = False,
by_unit: bool = False):
self.IO_DIGEST = io_data
self.CASH_ACCOUNTS = [a for a in self.IO_DIGEST['accounts'] if a['role'] == roles_module.ASSET_CA_CASH]
def __init__(self, io_data: dict):
self.IO_DATA = io_data
self.CASH_ACCOUNTS = [a for a in self.IO_DATA['accounts'] if a['role'] == roles_module.ASSET_CA_CASH]
self.JE_MODEL = lazy_loader.get_journal_entry_model()

def check_io_digest(self):
if GroupContextManager.GROUP_BALANCE_KEY not in self.IO_DIGEST:
if GroupContextManager.GROUP_BALANCE_KEY not in self.IO_DATA:
raise ValidationError(
'IO Digest must have groups for Cash Flow Statement'
)

def operating(self):
group_balances = self.IO_DIGEST[GroupContextManager.GROUP_BALANCE_KEY]
group_balances = self.IO_DATA[GroupContextManager.GROUP_BALANCE_KEY]
operating_activities = dict()
operating_activities['GROUP_CFS_NET_INCOME'] = {
'description': 'Net Income',
Expand Down Expand Up @@ -394,13 +393,13 @@ def operating(self):
}

net_cash_by_op_activities = sum(i['balance'] for g, i in operating_activities.items())
self.IO_DIGEST[self.CFS_DIGEST_KEY]['operating'] = operating_activities
self.IO_DIGEST[self.CFS_DIGEST_KEY]['net_cash_by_activity'] = dict(
self.IO_DATA[self.CFS_DIGEST_KEY]['operating'] = operating_activities
self.IO_DATA[self.CFS_DIGEST_KEY]['net_cash_by_activity'] = dict(
OPERATING=net_cash_by_op_activities
)

def financing(self):
group_balances = self.IO_DIGEST[GroupContextManager.GROUP_BALANCE_KEY]
# group_balances = self.IO_DIGEST[GroupContextManager.GROUP_BALANCE_KEY]
financing_activities = dict()
financing_activities['GROUP_CFS_FIN_ISSUING_EQUITY'] = {
'description': 'Common Stock, Preferred Stock and Capital Raised',
Expand All @@ -421,11 +420,11 @@ def financing(self):
}

net_cash = sum(i['balance'] for g, i in financing_activities.items())
self.IO_DIGEST[self.CFS_DIGEST_KEY]['financing'] = financing_activities
self.IO_DIGEST[self.CFS_DIGEST_KEY]['net_cash_by_activity']['FINANCING'] = net_cash
self.IO_DATA[self.CFS_DIGEST_KEY]['financing'] = financing_activities
self.IO_DATA[self.CFS_DIGEST_KEY]['net_cash_by_activity']['FINANCING'] = net_cash

def investing(self):
group_balances = self.IO_DIGEST[GroupContextManager.GROUP_BALANCE_KEY]
group_balances = self.IO_DATA[GroupContextManager.GROUP_BALANCE_KEY]
investing_activities = dict()
investing_activities['GROUP_CFS_INVESTING_SECURITIES'] = {
'description': 'Purchase, Maturity and Sales of Investments & Securities',
Expand All @@ -439,18 +438,19 @@ def investing(self):
}

net_cash = sum(i['balance'] for g, i in investing_activities.items())
self.IO_DIGEST[self.CFS_DIGEST_KEY]['investing'] = investing_activities
self.IO_DIGEST[self.CFS_DIGEST_KEY]['net_cash_by_activity']['INVESTING'] = net_cash
self.IO_DATA[self.CFS_DIGEST_KEY]['investing'] = investing_activities
self.IO_DATA[self.CFS_DIGEST_KEY]['net_cash_by_activity']['INVESTING'] = net_cash

def net_cash(self):
self.IO_DIGEST[self.CFS_DIGEST_KEY]['net_cash'] = sum([
bal for act, bal in self.IO_DIGEST[self.CFS_DIGEST_KEY]['net_cash_by_activity'].items()
self.IO_DATA[self.CFS_DIGEST_KEY]['net_cash'] = sum([
bal for act, bal in self.IO_DATA[self.CFS_DIGEST_KEY]['net_cash_by_activity'].items()
])

def digest(self):
self.IO_DATA[self.CFS_DIGEST_KEY] = dict()
self.check_io_digest()
self.operating()
self.financing()
self.investing()
self.net_cash()
return self.IO_DIGEST
return self.IO_DATA
2 changes: 1 addition & 1 deletion django_ledger/io/io_digest.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class IODigestContextManager:
def __init__(self, io_state: defaultdict):
self.IO_DATA: Dict = io_state
self.IO_RESULT = io_state['io_result']
self.IO_MODEL = self.IO_RESULT.txs_queryset
self.IO_MODEL = io_state['io_model']
self.TXS_QS = io_state['io_result']
self.STRFTIME_FORMAT = '%B %d, %Y'

Expand Down
10 changes: 2 additions & 8 deletions django_ledger/io/io_mixin.py
Original file line number Diff line number Diff line change
Expand Up @@ -235,8 +235,8 @@ def database_digest(self,
accounts: Optional[Union[str, List[str], Set[str]]] = None,
posted: bool = True,
exclude_zero_bal: bool = True,
force_closing_entry_use: bool = False
) -> IOResult:
force_closing_entry_use: bool = False,
**kwargs) -> IOResult:
"""
Performs the appropriate database aggregation query for a given request.
Expand Down Expand Up @@ -852,14 +852,12 @@ def get_balance_sheet_statement(self,
filepath: Optional[Path] = None,
filename: Optional[str] = None,
user_model: Optional[UserModel] = None,
txs_queryset: Optional[QuerySet] = None,
save_pdf: bool = False,
**kwargs
):
io_digest = self.digest_balance_sheet(
to_date=to_date,
user_model=user_model,
txs_queryset=txs_queryset,
**kwargs
)

Expand Down Expand Up @@ -952,15 +950,13 @@ def get_cash_flow_statement(self,
filepath: Optional[Path] = None,
filename: Optional[str] = None,
user_model: Optional[UserModel] = None,
txs_queryset: Optional[QuerySet] = None,
save_pdf: bool = False,
**kwargs):

io_digest = self.digest_cash_flow_statement(
from_date=from_date,
to_date=to_date,
user_model=user_model,
txs_queryset=txs_queryset,
**kwargs
)

Expand All @@ -985,7 +981,6 @@ def get_financial_statements(self,
to_date: Union[date, datetime],
dt_strfmt: str = '%Y%m%d',
user_model: Optional[UserModel] = None,
txs_queryset: Optional[QuerySet] = None,
save_pdf: bool = False,
filepath: Optional[Path] = None,
**kwargs) -> ReportTuple:
Expand All @@ -994,7 +989,6 @@ def get_financial_statements(self,
from_date=from_date,
to_date=to_date,
user_model=user_model,
txs_queryset=txs_queryset,
balance_sheet_statement=True,
income_statement=True,
cash_flow_statement=True,
Expand Down
2 changes: 1 addition & 1 deletion django_ledger/models/entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -2684,7 +2684,7 @@ def populate_random_data(self, start_date: date, days_forward=180, tx_quantity:
data_generator = EntityDataGenerator(
user_model=self.admin,
days_forward=days_forward,
start_date=start_date,
start_dttm=start_date,
entity_model=self,
capital_contribution=Decimal.from_float(50000.00),
tx_quantity=tx_quantity
Expand Down
16 changes: 12 additions & 4 deletions docs/source/quickstart_notebook.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
import os
from datetime import date, datetime
from random import randint, choices, random
from zoneinfo import ZoneInfo

import django

# for easier visualization it is recommended to use pandas to render data...
# if pandas is not installed, you may install it with this command: pip install -U pandas
# pandas is not a dependecy of django_ledger...
Expand All @@ -28,6 +28,7 @@ from django_ledger.models.bill import BillModel
from django_ledger.models.estimate import EstimateModel
from django.contrib.auth import get_user_model
from django_ledger.io import roles

```

# Get Your Entity Administrator UserModel
Expand All @@ -42,7 +43,14 @@ UserModel = get_user_model()
try:
user_model = UserModel.objects.get(username__exact=MY_USERNAME)
except:
user_model = UserModel.objects.create(username=MY_USERNAME, password=MY_PASSWORD)
user_model = UserModel(username=MY_USERNAME)
user_model.set_password(MY_PASSWORD)
user_model.save()
```


```python
entity_model = EntityModel.objects.get(name__exact='My Good Looking LLC')
```

# Create an Entity Model
Expand Down Expand Up @@ -91,12 +99,12 @@ default_coa_model


```python
START_DATE = date(year=2022, month=10, day=1)
START_DTTM = datetime(year=2022, month=10, day=1, tzinfo=ZoneInfo('UTC'))
```


```python
entity_model.populate_random_data(start_date=START_DATE)
entity_model.populate_random_data(start_date=START_DTTM)
```

### EntityModel has now a Default Chart of Accounts
Expand Down

0 comments on commit 11d5cfc

Please sign in to comment.