import datetime from decimal import Decimal import uuid from pyramid.security import authenticated_userid from pyramid.view import view_config from sqlalchemy import func, and_ from sqlalchemy.orm import aliased import transaction from brewman.models import DBSession from brewman.models.master import LedgerBase, CostCenter, Product, LedgerType from brewman.models.validation_exception import TryCatchFunction from brewman.models.voucher import Journal, Voucher, VoucherType, Batch, Inventory, SalaryDeduction, Fingerprint, Attendance __author__ = 'tanshu' @view_config(request_method='POST', route_name='api_rebase', renderer='json', permission='Rebase') @TryCatchFunction def rebase(request): date = request.matchdict.get('date', None) date = datetime.datetime.strptime(date, '%d-%b-%Y') user_id = uuid.UUID(authenticated_userid(request)) voucher_l = opening_ledgers(date, user_id) voucher_b, batches = opening_batches(date, user_id) delete_data(date, batches) DBSession.add(voucher_l) for j in voucher_l.journals: DBSession.add(j) DBSession.add(voucher_b) for j in voucher_b.journals: DBSession.add(j) for i in voucher_b.inventories: DBSession.add(i) transaction.commit() return {} def opening_ledgers(date, user_id): running_total = 0 sum_func = func.sum(Journal.signed_amount) query = DBSession.query(LedgerBase, sum_func) \ .join(Journal, Voucher.journals).join(LedgerBase, Journal.ledger) \ .filter(Voucher.date < date).filter(Voucher.type != VoucherType.by_name('Issue').id) \ .having(sum_func != 0) \ .group_by(LedgerBase).all() dt = date - datetime.timedelta(days=1) voucher = Voucher(date=dt, narration='Opening Ledgers', user_id=user_id, posted=True, type=VoucherType.by_name('Opening Ledgers')) for ledger, amount in query: amount = round(Decimal(amount), 2) if not ledger.type_object().balance_sheet: pass if amount != 0: running_total += amount journal = Journal(amount=abs(amount), debit=-1 if amount < 0 else 1, ledger_id=ledger.id, cost_center_id=ledger.costcenter_id) voucher.journals.append(journal) if running_total != 0: journal = Journal(amount=abs(amount), debit=-1 if amount * -1 < 0 else 1, ledger_id=LedgerBase.suspense(), cost_center_id=CostCenter.cost_center_overall()) voucher.journals.append(journal) return voucher def opening_batches(date, user_id): total = 0 batches = [] sum_func = func.sum(Journal.debit * Inventory.quantity) query = DBSession.query(Batch, sum_func) \ .join(Journal, Voucher.journals).join(Inventory, Voucher.inventories).join(Batch, Inventory.batch) \ .filter(Voucher.date < date) \ .filter(Journal.cost_center_id == CostCenter.cost_center_purchase()) \ .having(sum_func != 0) \ .group_by(Batch).all() dt = date - datetime.timedelta(days=1) voucher = Voucher(date=dt, narration='Opening Batches', user_id=user_id, posted=True, type=VoucherType.by_name('Opening Batches')) for batch, quantity in query: quantity = round(Decimal(quantity), 2) if quantity != 0: total += quantity * batch.rate * (1 + batch.tax) * (1 - batch.discount) inventory = Inventory(product_id=batch.product_id, batch=batch, quantity=quantity, rate=batch.rate, tax=batch.tax, discount=batch.discount) voucher.inventories.append(inventory) batches.append(batch.id) voucher.journals.append(Journal(amount=abs(total), debit=-1, ledger_id=LedgerBase.all_purchases(), cost_center_id=CostCenter.cost_center_overall())) voucher.journals.append(Journal(amount=abs(total), debit=1, ledger_id=LedgerBase.all_purchases(), cost_center_id=CostCenter.cost_center_purchase())) return voucher, batches def delete_data(date, batches): sub_voucher = aliased(Voucher) sub_query = DBSession.query(sub_voucher.id).filter(sub_voucher.date < date).subquery() Inventory.__table__.delete(Inventory.voucher_id.in_(sub_query)).execute() SalaryDeduction.__table__.delete(SalaryDeduction.voucher_id.in_(sub_query)).execute() Journal.__table__.delete(Journal.voucher_id.in_(sub_query)).execute() Voucher.__table__.delete(Voucher.date < date).execute() Batch.__table__.delete(and_(~Batch.inventories.any(), ~Batch.id.in_(batches))).execute() Fingerprint.__table__.delete(Fingerprint.date < date).execute() Attendance.__table__.delete(Attendance.date < date).execute()