Journal, Purchase and Purchase Return vouchers done!! Changed the column type of "date" columns from "datetime" to better fit the data.
283 lines
9.1 KiB
Python
283 lines
9.1 KiB
Python
import datetime
|
|
import uuid
|
|
from decimal import Decimal
|
|
from sqlalchemy import func, and_, distinct
|
|
from sqlalchemy.orm import aliased, joinedload_all
|
|
|
|
from brewman.models.master import AccountBase, CostCentre, Account, Employee
|
|
from brewman.models.voucher import (
|
|
Journal,
|
|
Voucher,
|
|
VoucherType,
|
|
Batch,
|
|
Inventory,
|
|
EmployeeBenefit,
|
|
Fingerprint,
|
|
Attendance,
|
|
DbImage,
|
|
Incentive,
|
|
)
|
|
|
|
|
|
@router.post("/api/rebase/{date}") # "Rebase"
|
|
def rebase(request):
|
|
# request.dbsession.execute('SET statement_timeout TO 300000;') # 5 minutes
|
|
date = request.matchdict.get("date", None)
|
|
date = datetime.datetime.strptime(date, "%d-%b-%Y")
|
|
user_id = uuid.UUID(request.authenticated_userid)
|
|
voucher_l = opening_accounts(date, user_id, request.dbsession)
|
|
voucher_b = opening_batches(date, user_id, request.dbsession)
|
|
starred_vouchers = save_starred(date, request.dbsession)
|
|
request.dbsession.flush()
|
|
delete_data(date, starred_vouchers, request.dbsession)
|
|
request.dbsession.add(voucher_l)
|
|
for j in voucher_l.journals:
|
|
request.dbsession.add(j)
|
|
request.dbsession.add(voucher_b)
|
|
for j in voucher_b.journals:
|
|
request.dbsession.add(j)
|
|
for i in voucher_b.inventories:
|
|
request.dbsession.add(i)
|
|
request.dbsession.flush()
|
|
cleanup_lint(date, request.dbsession)
|
|
# request.dbsession.execute('RESET statement_timeout;')
|
|
transaction.commit()
|
|
return {}
|
|
|
|
|
|
def save_starred(date, dbsession):
|
|
accounts = [
|
|
i.id
|
|
for i in dbsession.query(AccountBase.id)
|
|
.filter(AccountBase.is_starred == True)
|
|
.all()
|
|
]
|
|
vouchers = []
|
|
query = (
|
|
dbsession.query(Voucher)
|
|
.options(joinedload_all(Voucher.journals, Journal.account, innerjoin=True))
|
|
.filter(Voucher.date < date)
|
|
.filter(Voucher.journals.any(Journal.account_id.in_(accounts)))
|
|
.all()
|
|
)
|
|
|
|
for voucher in query:
|
|
vouchers.append(voucher.id)
|
|
others = [
|
|
journal
|
|
for journal in voucher.journals
|
|
if journal.account_id not in accounts
|
|
]
|
|
if len(others) == 0:
|
|
continue
|
|
amount = round(Decimal(sum(o.signed_amount for o in others)), 2)
|
|
if amount != 0:
|
|
journal = Journal(
|
|
amount=abs(amount),
|
|
debit=-1 if amount < 0 else 1,
|
|
account_id=AccountBase.suspense(),
|
|
cost_centre_id=CostCentre.cost_centre_overall(),
|
|
)
|
|
voucher.journals.append(journal)
|
|
dbsession.add(journal)
|
|
|
|
for other in others:
|
|
if voucher.type != VoucherType.by_name("Opening Accounts").id:
|
|
voucher.narration += "\nSuspense \u20B9{0:,.2f} is {1}".format(
|
|
other.amount, other.account.name
|
|
)
|
|
dbsession.delete(other)
|
|
voucher.type = VoucherType.by_name("Journal")
|
|
if len(voucher.narration) >= 1000:
|
|
voucher.narration = voucher.narration[:1000]
|
|
return vouchers
|
|
|
|
|
|
def opening_accounts(date, user_id, dbsession):
|
|
running_total = 0
|
|
sum_func = func.sum(Journal.signed_amount)
|
|
query = (
|
|
dbsession.query(AccountBase, sum_func)
|
|
.join(Journal, Voucher.journals)
|
|
.join(AccountBase, Journal.account)
|
|
.filter(AccountBase.is_starred == False)
|
|
.filter(AccountBase.id != AccountBase.suspense())
|
|
.filter(Voucher.date < date)
|
|
.filter(Voucher.type != VoucherType.by_name("Issue").id)
|
|
.having(sum_func != 0)
|
|
.group_by(AccountBase)
|
|
.all()
|
|
)
|
|
|
|
dt = date - datetime.timedelta(days=1)
|
|
voucher = Voucher(
|
|
date=dt,
|
|
narration="Opening Accounts",
|
|
user_id=user_id,
|
|
posted=True,
|
|
type=VoucherType.by_name("Opening Accounts"),
|
|
)
|
|
for account, amount in query:
|
|
amount = round(Decimal(amount), 2)
|
|
if account.type_object.balance_sheet and amount != 0:
|
|
running_total += amount
|
|
journal = Journal(
|
|
amount=abs(amount),
|
|
debit=-1 if amount < 0 else 1,
|
|
account_id=account.id,
|
|
cost_centre_id=account.cost_centre_id,
|
|
)
|
|
voucher.journals.append(journal)
|
|
if running_total != 0:
|
|
journal = Journal(
|
|
amount=abs(amount),
|
|
debit=-1 if amount * -1 < 0 else 1,
|
|
account_id=AccountBase.suspense(),
|
|
cost_centre_id=CostCentre.cost_centre_overall(),
|
|
)
|
|
voucher.journals.append(journal)
|
|
return voucher
|
|
|
|
|
|
def opening_batches(date, user_id, dbsession):
|
|
total = 0
|
|
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_centre_id == CostCentre.cost_centre_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)
|
|
voucher.journals.append(
|
|
Journal(
|
|
amount=abs(total),
|
|
debit=-1,
|
|
account_id=AccountBase.all_purchases(),
|
|
cost_centre_id=CostCentre.cost_centre_overall(),
|
|
)
|
|
)
|
|
voucher.journals.append(
|
|
Journal(
|
|
amount=abs(total),
|
|
debit=1,
|
|
account_id=AccountBase.all_purchases(),
|
|
cost_centre_id=CostCentre.cost_centre_purchase(),
|
|
)
|
|
)
|
|
return voucher
|
|
|
|
|
|
def delete_data(date, vouchers, dbsession):
|
|
sub_voucher = aliased(Voucher)
|
|
sub_query = (
|
|
dbsession.query(sub_voucher.id).filter(sub_voucher.date < date).subquery()
|
|
)
|
|
|
|
dbsession.execute(Inventory.__table__.delete(Inventory.voucher_id.in_(sub_query)))
|
|
dbsession.execute(
|
|
EmployeeBenefit.__table__.delete(EmployeeBenefit.voucher_id.in_(sub_query))
|
|
)
|
|
dbsession.execute(
|
|
Incentive.__table__.delete(Incentive.voucher_id.in_(sub_query))
|
|
)
|
|
dbsession.execute(
|
|
Journal.__table__.delete(
|
|
and_(Journal.voucher_id.in_(sub_query), ~Journal.voucher_id.in_(vouchers))
|
|
)
|
|
)
|
|
dbsession.execute(
|
|
DbImage.__table__.delete(
|
|
and_(
|
|
DbImage.resource_type == "voucher",
|
|
DbImage.resource_id.in_(sub_query),
|
|
~DbImage.resource_id.in_(vouchers),
|
|
)
|
|
)
|
|
)
|
|
dbsession.execute(
|
|
Voucher.__table__.delete(and_(Voucher.date < date, ~Voucher.id.in_(vouchers)))
|
|
)
|
|
|
|
|
|
def cleanup_lint(date, dbsession):
|
|
# Insert executes on the end so keep list of batches and journals
|
|
dbsession.execute(
|
|
Batch.__table__.delete(
|
|
~Batch.id.in_(dbsession.query(distinct(Inventory.batch_id)).subquery())
|
|
)
|
|
)
|
|
dbsession.execute(Fingerprint.__table__.delete(Fingerprint.date < date))
|
|
dbsession.execute(Attendance.__table__.delete(Attendance.date < date))
|
|
dbsession.execute(
|
|
Employee.__table__.delete(
|
|
and_(
|
|
~Employee.id.in_(
|
|
dbsession.query(distinct(Journal.account_id)).subquery()
|
|
),
|
|
~Employee.id.in_(
|
|
dbsession.query(distinct(Fingerprint.employee_id)).subquery()
|
|
),
|
|
~Employee.id.in_(
|
|
dbsession.query(distinct(Attendance.employee_id)).subquery()
|
|
),
|
|
Employee.id.in_(
|
|
dbsession.query(AccountBase.id)
|
|
.filter(AccountBase.is_fixture == False)
|
|
.filter(AccountBase.is_active == False)
|
|
.filter(AccountBase.is_starred == False)
|
|
.subquery()
|
|
),
|
|
Employee.leaving_date < date,
|
|
)
|
|
)
|
|
)
|
|
dbsession.execute(
|
|
AccountBase.__table__.delete(
|
|
and_(
|
|
~AccountBase.id.in_(dbsession.query(Employee.id).subquery()),
|
|
AccountBase.account_type
|
|
== Employee.__mapper_args__["polymorphic_identity"],
|
|
)
|
|
)
|
|
)
|
|
dbsession.execute(
|
|
Account.__table__.delete(
|
|
and_(
|
|
~Account.id.in_(
|
|
dbsession.query(distinct(Journal.account_id)).subquery()
|
|
),
|
|
Account.is_fixture == False,
|
|
Account.is_starred == False,
|
|
Account.account_type == Account.__mapper_args__["polymorphic_identity"],
|
|
)
|
|
)
|
|
)
|