189 lines
8.4 KiB
Python
189 lines
8.4 KiB
Python
import datetime
|
|
import pkg_resources
|
|
from sqlalchemy import func
|
|
import transaction
|
|
import uuid
|
|
|
|
from pyramid.response import Response, FileResponse
|
|
from pyramid.view import view_config
|
|
from sqlalchemy.orm import joinedload_all
|
|
|
|
from brewman.models.master import CostCentre, Ledger, LedgerType, LedgerBase
|
|
from brewman.models.validation_exception import ValidationError
|
|
from brewman.models.voucher import Voucher, Journal, VoucherType
|
|
|
|
|
|
@view_config(route_name='account_list', permission='Accounts')
|
|
@view_config(request_method='GET', route_name='account_id', permission='Accounts')
|
|
@view_config(request_method='GET', route_name='account', permission='Accounts')
|
|
def html(request):
|
|
package, resource = 'brewman:static/index.html'.split(':', 1)
|
|
file = pkg_resources.resource_filename(package, resource)
|
|
return FileResponse(file, request=request)
|
|
|
|
|
|
@view_config(request_method='POST', route_name='api_account', renderer='json', permission='Accounts', trans=True)
|
|
def save(request):
|
|
item = Ledger(code=0, name=request.json_body['Name'], type=int(request.json_body['Type']),
|
|
is_active=request.json_body['IsActive'], is_reconcilable=request.json_body['IsReconcilable'],
|
|
cost_centre_id=uuid.UUID(request.json_body['CostCentre']['CostCentreID'])).create(request.dbsession)
|
|
transaction.commit()
|
|
return account_info(item.id, request.dbsession)
|
|
|
|
|
|
@view_config(request_method='POST', route_name='api_account_id', renderer='json', permission='Accounts', trans=True)
|
|
def update(request):
|
|
item = request.dbsession.query(Ledger).filter(Ledger.id == uuid.UUID(request.matchdict['id'])).first()
|
|
if item.is_fixture:
|
|
raise ValidationError("{0} is a fixture and cannot be edited or deleted.".format(item.name))
|
|
new_type = int(request.json_body['Type'])
|
|
if not item.type == new_type:
|
|
item.code = Ledger.get_code(new_type, request.dbsession)
|
|
item.type = new_type
|
|
item.name = request.json_body['Name']
|
|
item.is_active = request.json_body['IsActive']
|
|
item.is_reconcilable = request.json_body['IsReconcilable']
|
|
item.cost_centre_id = uuid.UUID(request.json_body['CostCentre']['CostCentreID'])
|
|
transaction.commit()
|
|
return account_info(item.id, request.dbsession)
|
|
|
|
|
|
@view_config(request_method='DELETE', route_name='api_account_id', renderer='json', permission='Accounts')
|
|
def delete(request):
|
|
account = request.dbsession.query(Ledger).filter(Ledger.id == uuid.UUID(request.matchdict['id'])).first()
|
|
can_delete, reason = account.can_delete(request.has_permission('Advanced Delete'))
|
|
if can_delete:
|
|
delete_with_data(account, request.dbsession)
|
|
transaction.commit()
|
|
return account_info(None, request.dbsession)
|
|
else:
|
|
transaction.abort()
|
|
response = Response("Cannot delete account because {0}".format(reason))
|
|
response.status_int = 500
|
|
return response
|
|
|
|
|
|
@view_config(request_method='GET', route_name='api_account_id', renderer='json', request_param='b',
|
|
permission='Authenticated')
|
|
def show_balance(request):
|
|
date = request.GET.get('d', None)
|
|
date = None if date is None or date == '' else datetime.datetime.strptime(date, '%d-%b-%Y')
|
|
id = uuid.UUID(request.matchdict['id'])
|
|
return {'Date': balance(id, date, request.dbsession), 'Total': balance(id, None, request.dbsession)}
|
|
|
|
|
|
def balance(id_, date, dbsession):
|
|
account = dbsession.query(LedgerBase).filter(LedgerBase.id == id_).first()
|
|
if not account.type_object.balance_sheet:
|
|
return 0
|
|
|
|
bal = dbsession.query(func.sum(Journal.amount * Journal.debit)).join(Journal.voucher)
|
|
if date is not None:
|
|
bal = bal.filter(Voucher.date <= date)
|
|
|
|
bal = bal.filter(Voucher.type != VoucherType.by_name('Issue').id) \
|
|
.filter(Journal.ledger_id == id_) \
|
|
.scalar()
|
|
return 0 if bal is None else bal
|
|
|
|
|
|
@view_config(request_method='GET', route_name='api_account_id', renderer='json', permission='Accounts')
|
|
def show_id(request):
|
|
return account_info(uuid.UUID(request.matchdict.get('id', None)), request.dbsession)
|
|
|
|
|
|
@view_config(request_method='GET', route_name='api_account', renderer='json', permission='Accounts')
|
|
def show_blank(request):
|
|
return account_info(None, request.dbsession)
|
|
|
|
|
|
@view_config(request_method='GET', route_name='api_account', renderer='json', request_param='list',
|
|
permission='Authenticated')
|
|
def show_list(request):
|
|
list = request.dbsession.query(Ledger).order_by(Ledger.type).order_by(Ledger.name).order_by(Ledger.code).all()
|
|
ledgers = []
|
|
for item in list:
|
|
ledgers.append({'Name': item.name, 'Type': item.type_object.name, 'IsActive': 'Yes' if item.is_active else 'No',
|
|
'IsReconcilable': 'Yes' if item.is_reconcilable else '', 'CostCentre': item.cost_centre.name,
|
|
'IsFixture': item.is_fixture, 'Url': request.route_url('account_id', id=item.id)})
|
|
return ledgers
|
|
|
|
|
|
@view_config(request_method='GET', route_name='api_account', renderer='json', request_param='term',
|
|
permission='Authenticated')
|
|
def show_term(request):
|
|
type = request.GET.get('type', None)
|
|
type = int(type) if type is not None else None
|
|
filter = request.GET.get('term', None)
|
|
filter = filter if filter is not None and filter is not '' else None
|
|
reconcilable = request.GET.get('r', None)
|
|
reconcilable = reconcilable if reconcilable is not None else None
|
|
active = request.GET.get('a', None)
|
|
active = active if active is not None else None
|
|
count = request.GET.get('count', None)
|
|
count = None if count is None or count == '' else int(count)
|
|
|
|
list = []
|
|
for index, item in enumerate(LedgerBase.list(type, filter, reconcilable, active, request.dbsession)):
|
|
list.append({'LedgerID': item.id, 'Name': item.name})
|
|
if count is not None and index == count - 1:
|
|
break
|
|
return list
|
|
|
|
|
|
@view_config(request_method='GET', route_name='api_account_type_list', renderer='json', permission='Authenticated')
|
|
def account_type_list(request):
|
|
account_types = []
|
|
for item in LedgerType.list():
|
|
account_types.append({'AccountTypeID': item.id, 'Name': item.name})
|
|
return account_types
|
|
|
|
|
|
def account_info(id, dbsession):
|
|
if id is None:
|
|
account = {'Code': '(Auto)', 'Type': LedgerType.by_name('Creditors').id, 'IsActive': True,
|
|
'IsReconcilable': False, 'CostCentre': CostCentre.overall()}
|
|
else:
|
|
account = dbsession.query(Ledger).filter(Ledger.id == id).first()
|
|
account = {'LedgerID': account.id, 'Code': account.code, 'Name': account.name, 'Type': account.type,
|
|
'IsActive': account.is_active, 'IsReconcilable': account.is_reconcilable,
|
|
'IsFixture': account.is_fixture,
|
|
'CostCentre': {'CostCentreID': account.cost_centre_id, 'Name': account.cost_centre.name}}
|
|
return account
|
|
|
|
|
|
def delete_with_data(account, dbsession):
|
|
suspense_ledger = dbsession.query(Ledger).filter(Ledger.id == Ledger.suspense()).first()
|
|
query = dbsession.query(Voucher).options(joinedload_all(Voucher.journals, Journal.ledger, innerjoin=True)) \
|
|
.filter(Voucher.journals.any(Journal.ledger_id == account.id)) \
|
|
.all()
|
|
|
|
for voucher in query:
|
|
others, sus_jnl, acc_jnl = False, None, None
|
|
for journal in voucher.journals:
|
|
if journal.ledger_id == account.id:
|
|
acc_jnl = journal
|
|
elif journal.ledger_id == Ledger.suspense():
|
|
sus_jnl = journal
|
|
else:
|
|
others = True
|
|
if not others:
|
|
dbsession.delete(voucher)
|
|
else:
|
|
if sus_jnl is None:
|
|
acc_jnl.ledger = suspense_ledger
|
|
voucher.narration += '\nSuspense \u20B9{0:,.2f} is {1}'.format(acc_jnl.amount, account.name)
|
|
else:
|
|
amount = (sus_jnl.debit * sus_jnl.amount) + (acc_jnl.debit * acc_jnl.amount)
|
|
dbsession.delete(acc_jnl)
|
|
if amount == 0:
|
|
dbsession.delete(sus_jnl)
|
|
else:
|
|
sus_jnl.amount = abs(amount)
|
|
sus_jnl.debit = -1 if amount < 0 else 1
|
|
voucher.narration += '\nDeleted \u20B9{0:,.2f} of {1}'.format(acc_jnl.amount * acc_jnl.debit,
|
|
account.name)
|
|
if voucher.type in (VoucherType.by_name('Payment').id, VoucherType.by_name('Receipt').id):
|
|
voucher.type = VoucherType.by_name('Journal')
|
|
dbsession.delete(account)
|