Skip to content

Commit

Permalink
V0.5.2.17 (#140)
Browse files Browse the repository at this point in the history
* Balance Sheet Statement Template Bugfixes
io_context refactoring
IncomeStatementContextManager develop

* Income Statement IO Context
Income Statement HTML format improvements.
Refactoring

* income_statement.html
Income Statement IO Context Update
  • Loading branch information
elarroba committed Mar 27, 2023
1 parent 322f548 commit a5f86ba
Show file tree
Hide file tree
Showing 11 changed files with 498 additions and 218 deletions.
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.2.16'
__version__ = '0.5.2.17'
__license__ = 'GPLv3 License'

__author__ = 'Miguel Sanda'
Expand Down
4 changes: 2 additions & 2 deletions django_ledger/io/data_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
from django.utils.timezone import localtime, localdate

from django_ledger.io.roles import (INCOME_OPERATIONAL, ASSET_CA_INVENTORY, COGS, ASSET_CA_CASH, ASSET_CA_PREPAID,
LIABILITY_CL_DEFERRED_REVENUE, EXPENSE_REGULAR, EQUITY_CAPITAL,
LIABILITY_CL_DEFERRED_REVENUE, EXPENSE_OPERATIONAL, EQUITY_CAPITAL,
ASSET_CA_RECEIVABLES, LIABILITY_CL_ACC_PAYABLE)
from django_ledger.models import (EntityModel, TransactionModel, AccountModel, VendorModel, CustomerModel,
EntityUnitModel, BankAccountModel, LedgerModel, UnitOfMeasureModel, ItemModel,
Expand Down Expand Up @@ -370,7 +370,7 @@ def create_expenses(self):
entity=self.entity_model,
is_product_or_service=False,
for_inventory=False,
expense_account=choice(self.accounts_by_role[EXPENSE_REGULAR]),
expense_account=choice(self.accounts_by_role[EXPENSE_OPERATIONAL]),
) for _ in range(expense_count)
]

Expand Down
126 changes: 0 additions & 126 deletions django_ledger/io/financial_statements.py

This file was deleted.

209 changes: 204 additions & 5 deletions django_ledger/io/io_context.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
from collections import defaultdict
from itertools import groupby, chain

from django.core.exceptions import ValidationError

from django_ledger.io import roles as roles_module
from django_ledger.models.utils import LazyLoader
from django_ledger.models.utils import LazyLoader, lazy_loader

lazy_importer = LazyLoader()


class RoleManager:
class RoleContextManager:

def __init__(self,
tx_digest: dict,
Expand Down Expand Up @@ -73,7 +75,7 @@ def process_roles(self):
acc['balance'] for acc in acc_list if acc['unit_uuid'] == key[0])


class GroupManager:
class GroupContextManager:
GROUP_ACCOUNTS_KEY = 'group_account'
GROUP_BALANCE_KEY = 'group_balance'
GROUP_BALANCE_BY_UNIT_KEY = 'group_balance_by_unit'
Expand Down Expand Up @@ -146,7 +148,7 @@ def process_groups(self):
)


class ActivityManager:
class ActivityContextManager:

def __init__(self,
tx_digest: dict,
Expand Down Expand Up @@ -208,7 +210,7 @@ def process_activity(self):
acc['balance'] for acc in acc_list if acc['unit_uuid'] == key[0])


class BalanceSheetManager:
class BalanceSheetStatementContextManager:
def __init__(self, tx_digest: dict):
self.DIGEST = tx_digest

Expand Down Expand Up @@ -240,3 +242,200 @@ 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]
return self.DIGEST


class IncomeStatementContextManager:

def __init__(self, tx_digest: dict):
self.DIGEST = tx_digest

def digest(self):
if 'group_account' in self.DIGEST:
self.DIGEST['income_statement'] = {
'operating': {
'revenues': [
acc for acc in self.DIGEST['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['role'] in roles_module.GROUP_IC_OPERATING_COGS
],
'expenses': [
acc for acc in self.DIGEST['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
acc['role'] in roles_module.GROUP_IC_OTHER_REVENUES],
'expenses': [acc for acc in self.DIGEST['group_account']['GROUP_INCOME'] if
acc['role'] in roles_module.GROUP_IC_OTHER_EXPENSES],
}
}

# OPERATING INCOME...
self.DIGEST['income_statement']['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.DIGEST['income_statement']['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.DIGEST['income_statement']['operating']['net_operating_revenue'] = sum(
acc['balance'] for acc in self.DIGEST['income_statement']['operating']['revenues']
)
self.DIGEST['income_statement']['operating']['net_cogs'] = sum(
acc['balance'] for acc in self.DIGEST['income_statement']['operating']['cogs']
)
self.DIGEST['income_statement']['operating']['net_operating_expenses'] = sum(
acc['balance'] for acc in self.DIGEST['income_statement']['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.DIGEST['income_statement']['other']['net_other_expenses'] = sum(
acc['balance'] for acc in self.DIGEST['income_statement']['other']['expenses']
)
self.DIGEST['income_statement']['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']
]
))

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


class CashFlowStatementContextManager:
CFS_DIGEST_KEY = 'cash_flow_statement'

def __init__(self,
io_digest: dict,
by_period: bool = False,
by_unit: bool = False):
self.IO_DIGEST = io_digest
self.CASH_ACCOUNTS = [a for a in self.IO_DIGEST['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:
raise ValidationError(
'IO Digest must have groups for Cash Flow Statement'
)

def operating(self):
group_balances = self.IO_DIGEST[GroupContextManager.GROUP_BALANCE_KEY]
operating_activities = dict()
operating_activities['GROUP_CFS_NET_INCOME'] = {
'description': 'Net Income',
'balance': group_balances['GROUP_CFS_NET_INCOME']
}
operating_activities['GROUP_CFS_OP_DEPRECIATION_AMORTIZATION'] = {
'description': 'Depreciation & Amortization of Assets',
'balance': -group_balances['GROUP_CFS_OP_DEPRECIATION_AMORTIZATION']
}
operating_activities['GROUP_CFS_OP_INVESTMENT_GAINS'] = {
'description': 'Gain/Loss Sale of Assets',
'balance': group_balances['GROUP_CFS_OP_INVESTMENT_GAINS']
}
operating_activities['GROUP_CFS_OP_ACCOUNTS_RECEIVABLE'] = {
'description': 'Accounts Receivable',
'balance': -group_balances['GROUP_CFS_OP_ACCOUNTS_RECEIVABLE']
}
operating_activities['GROUP_CFS_OP_INVENTORY'] = {
'description': 'Inventories',
'balance': -group_balances['GROUP_CFS_OP_INVENTORY']
}

operating_activities['GROUP_CFS_OP_ACCOUNTS_PAYABLE'] = {
'description': 'Accounts Payable',
'balance': group_balances['GROUP_CFS_OP_ACCOUNTS_PAYABLE']
}
operating_activities['GROUP_CFS_OP_OTHER_CURRENT_ASSETS_ADJUSTMENT'] = {
'description': 'Other Current Assets',
'balance': -group_balances['GROUP_CFS_OP_OTHER_CURRENT_ASSETS_ADJUSTMENT']
}
operating_activities['GROUP_CFS_OP_OTHER_CURRENT_LIABILITIES_ADJUSTMENT'] = {
'description': 'Other Current Liabilities',
'balance': group_balances['GROUP_CFS_OP_OTHER_CURRENT_LIABILITIES_ADJUSTMENT']
}

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(
OPERATING=net_cash_by_op_activities
)

def financing(self):
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',
'balance': sum(a['balance'] for a in self.CASH_ACCOUNTS if a['activity'] == self.JE_MODEL.FINANCING_EQUITY)
}
financing_activities['GROUP_CFS_FIN_DIVIDENDS'] = {
'description': 'Dividends Payed Out to Shareholders',
'balance': sum(
a['balance'] for a in self.CASH_ACCOUNTS if a['activity'] == self.JE_MODEL.FINANCING_DIVIDENDS)
}
financing_activities['GROUP_CFS_FIN_ST_DEBT_PAYMENTS'] = {
'description': 'Increase/Reduction of Short-Term Debt Principal',
'balance': sum(a['balance'] for a in self.CASH_ACCOUNTS if a['activity'] == self.JE_MODEL.FINANCING_STD)
}
financing_activities['GROUP_CFS_FIN_LT_DEBT_PAYMENTS'] = {
'description': 'Increase/Reduction of Long-Term Debt Principal',
'balance': sum(a['balance'] for a in self.CASH_ACCOUNTS if a['activity'] == self.JE_MODEL.FINANCING_LTD)
}

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

def investing(self):
group_balances = self.IO_DIGEST[GroupContextManager.GROUP_BALANCE_KEY]
investing_activities = dict()
investing_activities['GROUP_CFS_INVESTING_SECURITIES'] = {
'description': 'Purchase, Maturity and Sales of Investments & Securities',
'balance': sum(
a['balance'] for a in self.CASH_ACCOUNTS if a['activity'] == self.JE_MODEL.INVESTING_SECURITIES)
}
investing_activities['GROUP_CFS_INVESTING_PPE'] = {
'description': 'Addition and Disposition of Property, Plant & Equipment',
'balance': sum(
a['balance'] for a in self.CASH_ACCOUNTS if a['activity'] == self.JE_MODEL.INVESTING_PPE)
}

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

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()
])

def digest(self):
self.check_io_digest()
self.operating()
self.financing()
self.investing()
self.net_cash()
return self.IO_DIGEST
Loading

0 comments on commit a5f86ba

Please sign in to comment.