272 lines
14 KiB
Python
272 lines
14 KiB
Python
import uuid
|
|
from pyramid.response import Response
|
|
from pyramid.security import authenticated_userid
|
|
from pyramid.view import view_config
|
|
from sqlalchemy import func
|
|
import transaction
|
|
from brewman import groupfinder
|
|
from brewman.models import DBSession
|
|
from brewman.models.auth import User
|
|
from brewman.models.master import LedgerBase, CostCenter, DbSetting
|
|
from brewman.models.validation_exception import ValidationError, TryCatchFunction
|
|
from brewman.models.voucher import Voucher, VoucherType, Batch, Inventory
|
|
from .issue import issue_create_voucher, issue_update_voucher
|
|
from .journal import journal_update_voucher, journal_create_voucher
|
|
from .purchase import purchase_create_voucher, purchase_update_voucher
|
|
|
|
__author__ = 'tanshu'
|
|
|
|
|
|
@view_config(request_method='GET', route_name='journal_id', renderer='brewman:templates/angular_base.mako',
|
|
permission='Journal')
|
|
@view_config(request_method='GET', route_name='journal', renderer='brewman:templates/angular_base.mako',
|
|
permission='Journal')
|
|
@view_config(request_method='GET', route_name='payment_id', renderer='brewman:templates/angular_base.mako',
|
|
permission='Payment')
|
|
@view_config(request_method='GET', route_name='payment', renderer='brewman:templates/angular_base.mako',
|
|
permission='Payment')
|
|
@view_config(request_method='GET', route_name='receipt_id', renderer='brewman:templates/angular_base.mako',
|
|
permission='Receipt')
|
|
@view_config(request_method='GET', route_name='receipt', renderer='brewman:templates/angular_base.mako',
|
|
permission='Receipt')
|
|
@view_config(request_method='GET', route_name='purchase_id', renderer='brewman:templates/angular_base.mako',
|
|
permission='Purchase')
|
|
@view_config(request_method='GET', route_name='purchase', renderer='brewman:templates/angular_base.mako',
|
|
permission='Purchase')
|
|
@view_config(request_method='GET', route_name='purchase_return_id', renderer='brewman:templates/angular_base.mako',
|
|
permission='Purchase Return')
|
|
@view_config(request_method='GET', route_name='purchase_return', renderer='brewman:templates/angular_base.mako',
|
|
permission='Purchase Return')
|
|
@view_config(request_method='GET', route_name='issue_id', renderer='brewman:templates/angular_base.mako',
|
|
permission='Issue')
|
|
@view_config(request_method='GET', route_name='issue', renderer='brewman:templates/angular_base.mako',
|
|
permission='Issue')
|
|
@view_config(request_method='GET', route_name='salary_deduction_id', renderer='brewman:templates/angular_base.mako',
|
|
permission='Issue')
|
|
@view_config(request_method='GET', route_name='salary_deduction', renderer='brewman:templates/angular_base.mako',
|
|
permission='Issue')
|
|
def journal_get(request):
|
|
return {}
|
|
|
|
|
|
@view_config(request_method='POST', route_name='api_voucher_id', request_param='post', renderer='json',
|
|
permission='Post Vouchers')
|
|
@TryCatchFunction
|
|
def voucher_post(request):
|
|
user = User.by_id(uuid.UUID(authenticated_userid(request)))
|
|
voucher = Voucher.by_id(uuid.UUID(request.matchdict['id']))
|
|
lock_date = get_lock_date()
|
|
if lock_date >= voucher.date:
|
|
raise ValidationError("Vouchers upto {0} have been locked.".format(lock_date.strftime('%d-%b-%Y')))
|
|
voucher.posted = True
|
|
voucher.poster_id = user.id
|
|
transaction.commit()
|
|
return voucher_info(Voucher.by_id(voucher.id))
|
|
|
|
|
|
def check_delete_permissions(request, voucher):
|
|
user = User.by_id(uuid.UUID(authenticated_userid(request)))
|
|
permissions = groupfinder(user.id, request)
|
|
|
|
if voucher.posted and not 'Edit Posted Vouchers' in permissions:
|
|
response = Response("You are not allowed to edit posted vouchers")
|
|
response.status_int = 403
|
|
return response
|
|
elif voucher.user_id != user.id and "Edit Other User's Vouchers" not in permissions:
|
|
response = Response("You are not allowed to edit other user's vouchers")
|
|
response.status_int = 403
|
|
return response
|
|
elif VoucherType.by_id(voucher.type).name not in permissions:
|
|
response = Response("You are not allowed (0) vouchers".format(VoucherType.by_id(voucher.type).name))
|
|
response.status_int = 403
|
|
return response
|
|
lock_date = get_lock_date()
|
|
if lock_date >= voucher.date:
|
|
response = Response("Vouchers upto {0} have been locked.".format(lock_date.strftime('%d-%b-%Y')))
|
|
response.status_int = 403
|
|
return response
|
|
|
|
|
|
@view_config(request_method='DELETE', route_name='api_voucher_id', renderer='json')
|
|
@TryCatchFunction
|
|
def delete(request):
|
|
voucher = Voucher.by_id(uuid.UUID(request.matchdict['id']))
|
|
permission = check_delete_permissions(request, voucher)
|
|
if permission is not None:
|
|
return permission
|
|
json_voucher = voucher_info(voucher)
|
|
batches_to_delete = []
|
|
if voucher.type == VoucherType.by_name('Issue').id:
|
|
for item in voucher.journals:
|
|
if item.debit == 1:
|
|
destination = item.cost_center_id
|
|
else:
|
|
source = item.cost_center_id
|
|
batch_consumed = True if source == CostCenter.cost_center_purchase() else False if destination == CostCenter.cost_center_purchase() else None
|
|
if batch_consumed is None:
|
|
pass
|
|
elif batch_consumed:
|
|
for item in voucher.inventories:
|
|
item.batch.quantity_remaining += item.quantity
|
|
else:
|
|
for item in voucher.inventories:
|
|
if item.batch.quantity_remaining < item.batch.quantity_remaining:
|
|
raise ValueError(
|
|
'Quantity remaining for {0} is less than issued, hence cannot be deleted'.format(
|
|
item.product.name))
|
|
item.batch.quantity_remaining -= item.quantity
|
|
elif voucher.type == VoucherType.by_name('Purchase').id:
|
|
for item in voucher.inventories:
|
|
uses = DBSession.query(func.count(Inventory.id)) \
|
|
.filter(Inventory.batch_id == item.batch.id) \
|
|
.filter(Inventory.id != item.id).scalar()
|
|
if uses > 0:
|
|
raise ValueError('{0} has been issued and cannot be deleted'.format(item.product.name))
|
|
batches_to_delete.append(item.batch)
|
|
elif voucher.type == VoucherType.by_name('Purchase Return').id:
|
|
for item in voucher.inventories:
|
|
item.batch.quantity_remaining += item.quantity
|
|
for b in batches_to_delete:
|
|
DBSession.delete(b)
|
|
DBSession.delete(voucher)
|
|
transaction.commit()
|
|
return blank_voucher(info=json_voucher)
|
|
|
|
|
|
@view_config(request_method='GET', route_name='api_voucher_id', renderer='json')
|
|
@TryCatchFunction
|
|
def get_old(request):
|
|
id = request.matchdict.get('id', None)
|
|
return voucher_info(Voucher.by_id(uuid.UUID(id)))
|
|
|
|
|
|
def voucher_info(voucher):
|
|
json_voucher = {'VoucherID': voucher.id,
|
|
'Date': voucher.date.strftime('%d-%b-%Y'),
|
|
'Type': VoucherType.by_id(voucher.type).name,
|
|
'Posted': voucher.posted,
|
|
'Narration': voucher.narration,
|
|
'Journals': [],
|
|
'Inventories': [],
|
|
'SalaryDeductions': [],
|
|
'CreationDate': voucher.creation_date.strftime('%d-%b-%Y %H:%M'),
|
|
'LastEditDate': voucher.last_edit_date.strftime('%d-%b-%Y %H:%M'),
|
|
'User': {'UserID': voucher.user.id, 'Name': voucher.user.name},
|
|
'Poster': voucher.poster.name if voucher.posted else ''}
|
|
if voucher.reconcile_date is not None:
|
|
json_voucher['ReconcileDate'] = voucher.reconcile_date.strftime('%d-%b-%Y %H:%M')
|
|
for item in voucher.journals:
|
|
json_voucher['Journals'].append({'JournalID': item.id, 'Debit': item.debit, 'Amount': item.amount,
|
|
'Ledger': {'LedgerID': item.ledger.id, 'Name': item.ledger.name},
|
|
'CostCenter': {'CostCenterID': item.cost_center_id}})
|
|
for item in voucher.salary_deductions:
|
|
json_voucher['SalaryDeductions'].append(
|
|
{'GrossSalary': item.gross_salary,
|
|
'DaysWorked': item.days_worked,
|
|
'EsiEmployee': item.esi_ee,
|
|
'PfEmployee': item.pf_ee,
|
|
'EsiEmployer': item.esi_er,
|
|
'PfEmployer': item.pf_er,
|
|
'Journal': {'JournalID': item.journal.id,
|
|
'Ledger': {'LedgerID': item.journal.ledger.id, 'Name': item.journal.ledger.name,
|
|
'Designation': item.journal.ledger.designation,
|
|
'CostCenter': {'CostCenterID': item.journal.ledger.costcenter.id,
|
|
'Name': item.journal.ledger.costcenter.name}}}})
|
|
for item in voucher.inventories:
|
|
text = "{0} ({1}) {2:.2f}@{3:.2f} from {4}".format(item.product.name, item.product.units,
|
|
item.batch.quantity_remaining, item.batch.rate, item.batch.name.strftime('%d-%b-%Y'))
|
|
json_voucher['Inventories'].append(
|
|
{'InventoryID': item.id, 'Quantity': item.quantity, 'Rate': item.rate,
|
|
'Tax': item.tax, 'Discount': item.discount, 'Amount': item.amount,
|
|
'Product': {'ProductID': item.product.id, 'Name': item.product.full_name, 'Units': item.product.units,
|
|
'Price': item.rate},
|
|
'Batch': {'BatchID': item.batch.id, 'Name': text,
|
|
'QuantityRemaining': item.batch.quantity_remaining, 'Tax': item.batch.tax,
|
|
'Discount': item.batch.discount, 'Rate': item.batch.rate,
|
|
'Product': {'ProductID': item.batch.product.id, 'Name': item.batch.product.full_name}}})
|
|
return json_voucher
|
|
|
|
|
|
def blank_voucher(info):
|
|
if 'Type' not in info:
|
|
raise ValidationError('Voucher Type is null')
|
|
type = info['Type']
|
|
if 'Date' not in info:
|
|
raise ValidationError('Date cannot be null')
|
|
json_voucher = {'Type': type, 'Date': info['Date'], 'Posted': False, 'Narration': "", 'Journals': [], 'Inventories': []}
|
|
if type == 'Journal':
|
|
pass
|
|
elif type == 'Payment':
|
|
ledger = None
|
|
if info is not None and 'Account' in info and info['Account'] is not None:
|
|
ledger = LedgerBase.by_id(info['Account'])
|
|
if ledger is not None:
|
|
ledger = {'LedgerID': ledger.id, 'Name':ledger.name}
|
|
else:
|
|
ledger = LedgerBase.cash_in_hand()
|
|
json_voucher['Journals'].append({'Ledger': ledger, 'Amount': 0, 'Debit': -1})
|
|
elif type == 'Receipt':
|
|
ledger = None
|
|
if info is not None and 'Account' in info and info['Account'] is not None:
|
|
ledger = LedgerBase.by_id(info['Account'])
|
|
if ledger is not None:
|
|
ledger = {'LedgerID': ledger.id, 'Name':ledger.name}
|
|
else:
|
|
ledger = LedgerBase.cash_in_hand()
|
|
json_voucher['Journals'].append({'Ledger': ledger, 'Amount': 0, 'Debit': 1})
|
|
elif type == 'Purchase':
|
|
json_voucher['Journals'].append({'Ledger': LedgerBase.local_purchase(), 'Amount': 0, 'Debit': -1})
|
|
elif type == 'Purchase Return':
|
|
json_voucher['Journals'].append({'Ledger': LedgerBase.local_purchase(), 'Amount': 0, 'Debit': 1})
|
|
elif type == 'Issue':
|
|
if 'Source' in info and 'Destination' in info:
|
|
json_voucher['Journals'].append({'Ledger': {'LedgerID': LedgerBase.all_purchases()},
|
|
'Amount': 0,
|
|
'Debit': -1,
|
|
'CostCenter': {'CostCenterID': info['Source']}})
|
|
json_voucher['Journals'].append({'Ledger': {'LedgerID': LedgerBase.all_purchases()},
|
|
'Amount': 0,
|
|
'Debit': 1,
|
|
'CostCenter': {'CostCenterID': info['Destination']}})
|
|
elif 'Journals' not in info:
|
|
json_voucher['Journals'].append({'Ledger': {'LedgerID': LedgerBase.all_purchases()},
|
|
'Amount': 0,
|
|
'Debit': -1,
|
|
'CostCenter': {'CostCenterID': CostCenter.cost_center_purchase()}})
|
|
json_voucher['Journals'].append({'Ledger': {'LedgerID': LedgerBase.all_purchases()},
|
|
'Amount': 0,
|
|
'Debit': 1,
|
|
'CostCenter': {'CostCenterID': CostCenter.cost_center_kitchen()}})
|
|
else:
|
|
json_voucher['Date'] = info['Date']
|
|
for item in info['Journals']:
|
|
json_voucher['Journals'].append({'Ledger': {'LedgerID': item['Ledger']['LedgerID']},
|
|
'Amount': 0,
|
|
'Debit': item['Debit'],
|
|
'CostCenter': {'CostCenterID': item['CostCenter']['CostCenterID']}})
|
|
|
|
elif type == 'Salary Deduction':
|
|
json_voucher['SalaryDeductions'] = []
|
|
else:
|
|
raise ValidationError("Voucher of type \"{0}\" does not exist.".format(type))
|
|
return json_voucher
|
|
|
|
|
|
def get_edit_url(request, voucher):
|
|
if voucher.type == 1:
|
|
return request.route_url('journal_id', id=voucher.id)
|
|
elif voucher.type == 2:
|
|
return request.route_url('purchase_id', id=voucher.id)
|
|
elif voucher.type == 3:
|
|
return request.route_url('issue_id', id=voucher.id)
|
|
elif voucher.type == 4:
|
|
return request.route_url('payment_id', id=voucher.id)
|
|
elif voucher.type == 5:
|
|
return request.route_url('receipt_id', id=voucher.id)
|
|
elif voucher.type == 6:
|
|
return request.route_url('purchase_return_id', id=voucher.id)
|
|
elif voucher.type == 12:
|
|
return request.route_url('salary_deduction_id', id=voucher.id)
|
|
else:
|
|
return '#'
|