|
|
|
|
@ -1,10 +1,10 @@
|
|
|
|
|
import datetime
|
|
|
|
|
from sqlalchemy.sql.expression import func
|
|
|
|
|
from sqlalchemy.sql.expression import func, desc
|
|
|
|
|
|
|
|
|
|
from pyramid.view import view_config
|
|
|
|
|
|
|
|
|
|
from brewman.models import DBSession
|
|
|
|
|
from brewman.models.master import CostCenter, Ledger, LedgerType
|
|
|
|
|
from brewman.models.master import CostCenter, LedgerType, LedgerBase
|
|
|
|
|
|
|
|
|
|
from brewman.models.voucher import Voucher, Journal, VoucherType, Inventory
|
|
|
|
|
from brewman.views.services.session import services_session_period_start, services_session_period_finish
|
|
|
|
|
@ -17,210 +17,143 @@ def get_html(request):
|
|
|
|
|
|
|
|
|
|
@view_config(request_method='GET', route_name='profit_loss', renderer='json', xhr=True)
|
|
|
|
|
def get_profit_loss(request):
|
|
|
|
|
print('profit loss')
|
|
|
|
|
start_date = request.GET.get('StartDate', None)
|
|
|
|
|
finish_date = request.GET.get('FinishDate', None)
|
|
|
|
|
if start_date and finish_date:
|
|
|
|
|
report = {'StartDate': start_date, 'FinishDate': finish_date, 'Body': [], 'Footer': []}
|
|
|
|
|
report = {'StartDate': start_date, 'FinishDate': finish_date}
|
|
|
|
|
start_date = datetime.datetime.strptime(start_date, '%d-%b-%Y')
|
|
|
|
|
finish_date = datetime.datetime.strptime(finish_date, '%d-%b-%Y')
|
|
|
|
|
net_profit, opening_stock, closing_stock = build_profit_loss(request, report, start_date, finish_date)
|
|
|
|
|
report['Body'].append([{}, {}, {}])
|
|
|
|
|
report['Footer'].append([{}, {}, {}])
|
|
|
|
|
build_balance_sheet(request, report, net_profit, opening_stock, closing_stock, start_date, finish_date)
|
|
|
|
|
|
|
|
|
|
net_profit, opening_stock, closing_stock,\
|
|
|
|
|
report['ProfitLossBody'], report['ProfitLossFooter'] = build_profit_loss(request, start_date, finish_date)
|
|
|
|
|
report['BalanceSheetBody'], report['BalanceSheetFooter'] = build_balance_sheet(request, net_profit,
|
|
|
|
|
opening_stock, closing_stock, start_date, finish_date)
|
|
|
|
|
return report
|
|
|
|
|
else:
|
|
|
|
|
return {'StartDate': services_session_period_start(request),
|
|
|
|
|
'FinishDate': services_session_period_finish(request), 'Body': [], 'Footer': {}}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def build_profit_loss(request, report, start_date, finish_date):
|
|
|
|
|
def build_profit_loss(request, start_date, finish_date):
|
|
|
|
|
report = []
|
|
|
|
|
groups = dict()
|
|
|
|
|
type_list = []
|
|
|
|
|
for item in LedgerType.list():
|
|
|
|
|
if not item.balance_sheet:
|
|
|
|
|
type_list.append(item.id)
|
|
|
|
|
|
|
|
|
|
query = DBSession.query(Ledger, func.sum(Journal.amount * Journal.debit))\
|
|
|
|
|
amount_sum = func.sum(Journal.amount * Journal.debit)
|
|
|
|
|
query = DBSession.query(LedgerBase, amount_sum)\
|
|
|
|
|
.join(Journal.voucher).join(Journal.ledger)\
|
|
|
|
|
.filter(Voucher.date >= start_date)\
|
|
|
|
|
.filter(Voucher.date <= finish_date)\
|
|
|
|
|
.filter(Voucher.type != VoucherType.by_name('Issue').id)\
|
|
|
|
|
.filter(Ledger.type.in_(type_list))\
|
|
|
|
|
.group_by(Ledger)\
|
|
|
|
|
.order_by(Ledger.type)\
|
|
|
|
|
.all()
|
|
|
|
|
.filter(LedgerBase.type.in_(type_list))\
|
|
|
|
|
.group_by(LedgerBase).order_by(LedgerBase.type).order_by(desc(func.abs(amount_sum))).all()
|
|
|
|
|
|
|
|
|
|
# Get opening / closing stock
|
|
|
|
|
opening_stock, closing_stock = get_stocks(start_date, finish_date)
|
|
|
|
|
total_debit = opening_stock
|
|
|
|
|
total_credit = closing_stock
|
|
|
|
|
report['Body'].append({'Name': 'Opening / Closing Stock', 'Class': 'sub_heading unposted',
|
|
|
|
|
'Expense': "\u20B9 {0:,.2f}".format(total_debit),
|
|
|
|
|
'Income': "\u20B9 {0:,.2f}".format(total_credit)})
|
|
|
|
|
|
|
|
|
|
last_type = LedgerType(id=0, name="")
|
|
|
|
|
type_debit = 0
|
|
|
|
|
type_credit = 0
|
|
|
|
|
opening_stock = 0 if opening_stock is None else opening_stock
|
|
|
|
|
closing_stock = 0 if closing_stock is None else closing_stock
|
|
|
|
|
total_amount = (opening_stock - closing_stock) * -1
|
|
|
|
|
report.append(
|
|
|
|
|
{'Name': 'Opening Stock', 'SubAmount': "\u20B9 {0:,.2f}".format(opening_stock * -1), 'Order': 20.0001})
|
|
|
|
|
report.append({'Name': 'Closing Stock', 'SubAmount': "\u20B9 {0:,.2f}".format(closing_stock), 'Order': 29})
|
|
|
|
|
purchase_group = LedgerType.by_id(2)
|
|
|
|
|
groups[purchase_group.id] = {'Group': purchase_group.name, 'Amount': total_amount, 'Order': purchase_group.order}
|
|
|
|
|
counter = 0
|
|
|
|
|
for ledger, amount in query:
|
|
|
|
|
# Add Subtotals
|
|
|
|
|
ledger_type = LedgerType.by_id(ledger.type)
|
|
|
|
|
if last_type.id != ledger_type.id:
|
|
|
|
|
if last_type.id != 0:
|
|
|
|
|
if last_type.debit:
|
|
|
|
|
type_debit = "\u20B9 {0:,.2f}".format(type_debit)
|
|
|
|
|
type_credit = ""
|
|
|
|
|
else:
|
|
|
|
|
type_credit = "\u20B9 {0:,.2f}".format(type_credit)
|
|
|
|
|
type_debit = ""
|
|
|
|
|
|
|
|
|
|
report['Body'].append({'Name': last_type.name, 'Class': 'sub_heading unposted', 'Expense': type_debit,
|
|
|
|
|
'Income': type_credit})
|
|
|
|
|
|
|
|
|
|
type_debit = 0
|
|
|
|
|
type_credit = 0
|
|
|
|
|
last_type = ledger_type
|
|
|
|
|
# Add Items
|
|
|
|
|
if ledger_type.debit:
|
|
|
|
|
debit = "\u20B9 {0:,.2f}".format(amount)
|
|
|
|
|
credit = ""
|
|
|
|
|
type_debit += amount
|
|
|
|
|
total_debit += amount
|
|
|
|
|
else:
|
|
|
|
|
credit = "\u20B9 {0:,.2f}".format(amount * -1)
|
|
|
|
|
debit = ""
|
|
|
|
|
type_credit += (amount * -1)
|
|
|
|
|
total_credit += (amount * -1)
|
|
|
|
|
ledger_type = LedgerType.by_id(ledger.type)
|
|
|
|
|
amount = amount * -1
|
|
|
|
|
total_amount += amount
|
|
|
|
|
if amount != 0:
|
|
|
|
|
report['Body'].append({'Name': ledger.name, 'Expense': debit, 'Income': credit})
|
|
|
|
|
# Add Last Subtotal
|
|
|
|
|
if last_type.debit:
|
|
|
|
|
type_debit = "\u20B9 {0:,.2f}".format(type_debit)
|
|
|
|
|
type_credit = ""
|
|
|
|
|
counter += .001
|
|
|
|
|
report.append(
|
|
|
|
|
{'Name': ledger.name, 'SubAmount': "\u20B9 {0:,.2f}".format(amount),
|
|
|
|
|
'Order': ledger_type.order + counter})
|
|
|
|
|
if ledger_type.id in groups:
|
|
|
|
|
groups[ledger_type.id]['Amount'] += amount
|
|
|
|
|
else:
|
|
|
|
|
type_credit = "\u20B9 {0:,.2f}".format(type_credit)
|
|
|
|
|
type_debit = ""
|
|
|
|
|
groups[ledger_type.id] = {'Group': ledger_type.name, 'Amount': amount, 'Order': ledger_type.order}
|
|
|
|
|
|
|
|
|
|
report['Body'].append(
|
|
|
|
|
{'Name': last_type.name, 'Class': 'sub_heading unposted', 'Expense': type_debit, 'Income': type_credit})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Add Totals
|
|
|
|
|
report['Footer'].append({'Name': 'Total', 'Expense': type_debit, 'Income': type_credit})
|
|
|
|
|
# Add Subtotals
|
|
|
|
|
for item in groups.values():
|
|
|
|
|
item['Amount'] = "\u20B9 {0:,.2f}".format(item['Amount'])
|
|
|
|
|
report.append(item)
|
|
|
|
|
|
|
|
|
|
footer = []
|
|
|
|
|
# Add Net
|
|
|
|
|
net_profit = total_credit - total_debit
|
|
|
|
|
if total_debit > total_credit:
|
|
|
|
|
total_credit = "\u20B9 {0:,.2f}".format(total_debit - total_credit)
|
|
|
|
|
total_debit = ""
|
|
|
|
|
net_name = "Net Loss"
|
|
|
|
|
if total_amount > 0:
|
|
|
|
|
footer.append({'Name': 'Net Profit', 'Amount': "\u20B9 {0:,.2f}".format(total_amount), 'Order': 100})
|
|
|
|
|
else:
|
|
|
|
|
total_debit = "\u20B9 {0:,.2f}".format(total_credit - total_debit)
|
|
|
|
|
total_credit = ""
|
|
|
|
|
net_name = "Net Profit"
|
|
|
|
|
footer.append({'Name': 'Net Loss', 'Amount': "\u20B9 {0:,.2f}".format(total_amount), 'Order': 100})
|
|
|
|
|
|
|
|
|
|
report['Footer'].append({'Name': net_name, 'Expense': total_debit, 'Income': total_credit})
|
|
|
|
|
|
|
|
|
|
return net_profit, opening_stock, closing_stock
|
|
|
|
|
return total_amount, opening_stock, closing_stock, sorted(report, key=lambda d: d['Order']), footer
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def build_balance_sheet(request, report, net_profit, opening_stock, closing_stock, start_date, finish_date):
|
|
|
|
|
def build_balance_sheet(request, net_profit, opening_stock, closing_stock, start_date, finish_date):
|
|
|
|
|
report = []
|
|
|
|
|
groups = dict()
|
|
|
|
|
# Add Net Profit / Loss
|
|
|
|
|
if net_profit < 0:
|
|
|
|
|
debit = "\u20B9 {0:,.2f}".format(net_profit * -1)
|
|
|
|
|
credit = ""
|
|
|
|
|
name = "Net Loss"
|
|
|
|
|
total_debit = net_profit * -1
|
|
|
|
|
total_credit = 0
|
|
|
|
|
else:
|
|
|
|
|
credit = "\u20B9 {0:,.2f}".format(net_profit)
|
|
|
|
|
debit = ""
|
|
|
|
|
name = "Net Profit"
|
|
|
|
|
total_credit = net_profit
|
|
|
|
|
total_debit = 0
|
|
|
|
|
|
|
|
|
|
report['Body'].append({'Name': name, 'Liability': credit, 'Asset': debit})
|
|
|
|
|
|
|
|
|
|
net_profit *= -1
|
|
|
|
|
total_amount = net_profit
|
|
|
|
|
report.append({'Name': 'Net Loss' if net_profit >= 0 else 'Net Profit',
|
|
|
|
|
'SubAmount': "\u20B9 {0:,.2f}".format(net_profit), 'Order': 79})
|
|
|
|
|
|
|
|
|
|
# Add Accumulated Profit / Loss
|
|
|
|
|
accumulated_profit = get_accumulated_profit(opening_stock, start_date, finish_date)
|
|
|
|
|
if accumulated_profit < 0:
|
|
|
|
|
debit = "\u20B9 {0:,.2f}".format(accumulated_profit * -1)
|
|
|
|
|
credit = ""
|
|
|
|
|
name = "Accumulated Loss"
|
|
|
|
|
total_debit += accumulated_profit * -1
|
|
|
|
|
else:
|
|
|
|
|
credit = "\u20B9 {0:,.2f}".format(accumulated_profit)
|
|
|
|
|
debit = ""
|
|
|
|
|
name = "Accumulated Profit"
|
|
|
|
|
total_credit += accumulated_profit
|
|
|
|
|
accumulated_profit = get_accumulated_profit(opening_stock, start_date)
|
|
|
|
|
report.append({'Name': 'Accumulated Loss' if accumulated_profit >= 0 else 'Accumulated Profit',
|
|
|
|
|
'SubAmount': "\u20B9 {0:,.2f}".format(accumulated_profit), 'Order': 78})
|
|
|
|
|
total_amount += accumulated_profit
|
|
|
|
|
|
|
|
|
|
report['Body'].append({'Name': name, 'Liability': credit, 'Asset': debit})
|
|
|
|
|
capital_group = LedgerType.by_id(5)
|
|
|
|
|
groups[capital_group.id] = {'Group': capital_group.name, 'Amount': total_amount, 'Order': capital_group.order}
|
|
|
|
|
|
|
|
|
|
# Add Closing Stock
|
|
|
|
|
if closing_stock > 0:
|
|
|
|
|
total_debit += closing_stock
|
|
|
|
|
report['Body'].append({'Name': 'Closing Stock', 'Asset': "\u20B9 {0:,.2f}".format(closing_stock)})
|
|
|
|
|
total_amount += closing_stock
|
|
|
|
|
report.append({'Name': 'Closing Stock', 'SubAmount': "\u20B9 {0:,.2f}".format(closing_stock), 'Order': 20.001})
|
|
|
|
|
|
|
|
|
|
asset_group = LedgerType.by_id(4)
|
|
|
|
|
groups[asset_group.id] = {'Group': asset_group.name, 'Amount': closing_stock, 'Order': asset_group.order}
|
|
|
|
|
|
|
|
|
|
type_list = []
|
|
|
|
|
for item in LedgerType.list():
|
|
|
|
|
if item.balance_sheet:
|
|
|
|
|
type_list.append(item.id)
|
|
|
|
|
|
|
|
|
|
query = DBSession.query(Ledger, func.sum(Journal.amount * Journal.debit))\
|
|
|
|
|
amount_sum = func.sum(Journal.amount * Journal.debit)
|
|
|
|
|
query = DBSession.query(LedgerBase, amount_sum)\
|
|
|
|
|
.join(Journal.voucher).join(Journal.ledger)\
|
|
|
|
|
.filter(Voucher.date <= finish_date)\
|
|
|
|
|
.filter(Voucher.type != VoucherType.by_name('Issue').id)\
|
|
|
|
|
.filter(Ledger.type.in_(type_list))\
|
|
|
|
|
.group_by(Ledger)\
|
|
|
|
|
.order_by(Ledger.type)\
|
|
|
|
|
.all()
|
|
|
|
|
.filter(LedgerBase.type.in_(type_list))\
|
|
|
|
|
.group_by(LedgerBase).order_by(LedgerBase.type).order_by(desc(func.abs(amount_sum))).all()
|
|
|
|
|
|
|
|
|
|
last_type = LedgerType(id=0, name="")
|
|
|
|
|
type_debit = 0
|
|
|
|
|
type_credit = 0
|
|
|
|
|
counter = 0
|
|
|
|
|
sss = 0
|
|
|
|
|
for ledger, amount in query:
|
|
|
|
|
# Add Subtotals
|
|
|
|
|
ledger_type = LedgerType.by_id(ledger.type)
|
|
|
|
|
if last_type.id != ledger_type.id:
|
|
|
|
|
if last_type.id != 0:
|
|
|
|
|
if last_type.debit:
|
|
|
|
|
type_debit = "\u20B9 {0:,.2f}".format(type_debit)
|
|
|
|
|
type_credit = ""
|
|
|
|
|
else:
|
|
|
|
|
type_credit = "\u20B9 {0:,.2f}".format(type_credit)
|
|
|
|
|
type_debit = ""
|
|
|
|
|
|
|
|
|
|
report['Body'].append({'Name': last_type.name, 'Liability': type_credit, 'Asset': type_debit})
|
|
|
|
|
type_debit = 0
|
|
|
|
|
type_credit = 0
|
|
|
|
|
last_type = ledger_type
|
|
|
|
|
# Add Items
|
|
|
|
|
if ledger_type.debit:
|
|
|
|
|
debit = "\u20B9 {0:,.2f}".format(amount)
|
|
|
|
|
credit = ""
|
|
|
|
|
type_debit += amount
|
|
|
|
|
total_debit += amount
|
|
|
|
|
else:
|
|
|
|
|
credit = "\u20B9 {0:,.2f}".format(amount * -1)
|
|
|
|
|
debit = ""
|
|
|
|
|
type_credit += (amount * -1)
|
|
|
|
|
total_credit += (amount * -1)
|
|
|
|
|
ledger_type = LedgerType.by_id(ledger.type)
|
|
|
|
|
sss += amount
|
|
|
|
|
total_amount += amount
|
|
|
|
|
if amount != 0:
|
|
|
|
|
report['Body'].append({'Name': ledger.name, 'Liability': credit, 'Asset': debit})
|
|
|
|
|
|
|
|
|
|
# Add Last Subtotal
|
|
|
|
|
if last_type.debit:
|
|
|
|
|
type_debit = "\u20B9 {0:,.2f}".format(type_debit)
|
|
|
|
|
type_credit = ""
|
|
|
|
|
counter += .001
|
|
|
|
|
report.append(
|
|
|
|
|
{'Name': ledger.name, 'SubAmount': "\u20B9 {0:,.2f}".format(amount),
|
|
|
|
|
'Order': ledger_type.order + counter})
|
|
|
|
|
if ledger_type.id in groups:
|
|
|
|
|
groups[ledger_type.id]['Amount'] += amount
|
|
|
|
|
else:
|
|
|
|
|
type_credit = "\u20B9 {0:,.2f}".format(type_credit)
|
|
|
|
|
type_debit = ""
|
|
|
|
|
groups[ledger_type.id] = {'Group': ledger_type.name, 'Amount': amount, 'Order': ledger_type.order}
|
|
|
|
|
|
|
|
|
|
report['Body'].append(
|
|
|
|
|
{'Name': last_type.name, 'Liability': type_credit, 'Asset': type_debit, 'class': 'sub_heading unposted'})
|
|
|
|
|
# Add Subtotals
|
|
|
|
|
for item in groups.values():
|
|
|
|
|
item['Amount'] = "\u20B9 {0:,.2f}".format(item['Amount'])
|
|
|
|
|
report.append(item)
|
|
|
|
|
|
|
|
|
|
report['Footer'].append({'Name': 'Total', 'Liability': "\u20B9 {0:,.2f}".format(total_credit),
|
|
|
|
|
'Asset': "\u20B9 {0:,.2f}".format(total_debit)})
|
|
|
|
|
footer = [{'Name': 'Total', 'Amount': "\u20B9 {0:,.2f}".format(total_amount), 'Order': 100}]
|
|
|
|
|
|
|
|
|
|
return sorted(report, key=lambda d: d['Order']), footer
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_stocks(startDate, finishDate):
|
|
|
|
|
@ -239,7 +172,7 @@ def get_stocks(startDate, finishDate):
|
|
|
|
|
return opening_stock, closing_stock
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_accumulated_profit(opening_stock, startDate, finishDate):
|
|
|
|
|
def get_accumulated_profit(opening_stock, start_date):
|
|
|
|
|
type_list = []
|
|
|
|
|
for item in LedgerType.list():
|
|
|
|
|
if not item.balance_sheet:
|
|
|
|
|
@ -247,10 +180,10 @@ def get_accumulated_profit(opening_stock, startDate, finishDate):
|
|
|
|
|
|
|
|
|
|
accumulated_profit = DBSession.query(func.sum(Journal.amount * Journal.debit))\
|
|
|
|
|
.join(Journal.voucher).join(Journal.ledger)\
|
|
|
|
|
.filter(Voucher.date < startDate)\
|
|
|
|
|
.filter(Voucher.date < start_date)\
|
|
|
|
|
.filter(Voucher.type != VoucherType.by_name('Issue').id)\
|
|
|
|
|
.filter(Ledger.type.in_(type_list))\
|
|
|
|
|
.filter(LedgerBase.type.in_(type_list))\
|
|
|
|
|
.scalar()
|
|
|
|
|
if accumulated_profit is None:
|
|
|
|
|
accumulated_profit = 0
|
|
|
|
|
return (accumulated_profit * -1) + opening_stock
|
|
|
|
|
return accumulated_profit - opening_stock
|
|
|
|
|
|