import arrow
from decimal import Decimal
from datetime import datetime
from time import perf_counter
from sqlalchemy import select, func, distinct, cast, Date, String, literal, desc, and_, or_, case, join, alias, text
from interest_calculate import hesapla_gecikme_faizi
from Controllers.Postgres.engine import get_session_factory
from Schemas import (
BuildDecisionBookPayments,
AccountRecords,
ApiEnumDropdown,
Build,
BuildDecisionBook,
AccountDelayInterest,
BuildParts,
)
# from ServicesApi.Schemas.account.account import AccountRecords, AccountDelayInterest
# from ServicesApi.Schemas.building.decision_book import BuildDecisionBookPayments, BuildDecisionBook
# from ServicesApi.Schemas.building.build import Build, BuildParts
# from ServicesApi.Schemas.others.enums import ApiEnumDropdown
"""
BuildDuesTypes BDT-S Service fee (Service fee)
BuildDuesTypes BDT-I Information (Information)
BuildDuesTypes BDT-D Bina Aidat (Debit)
BuildDuesTypes BDT-A Bina Ek Aidat (Add Debit)
BuildDuesTypes BDT-R Bina Tadilat (Renovation)
BuildDuesTypes BDT-L Bina Yasal Harcama (Lawyer expence)
BuildDuesTypes BDT-CL Close Last Period Receipt (Close Last Period Receipt)
BuildDuesTypes BDT-OP Open New Period Receipt (Open New Period Receipt)
"""
def joined_decision_book_sql_query(build_decision_book_id: int=49):
subquery = select(
AccountRecords.build_parts_id,
BuildParts.part_code,
BuildParts.part_no,
AccountRecords.build_decision_book_id,
func.sum(AccountRecords.currency_value).label('paid')
).select_from(
AccountRecords.__table__.join(
BuildParts,
AccountRecords.build_parts_id == BuildParts.id
)
).where(
AccountRecords.build_decision_book_id == build_decision_book_id
).group_by(
AccountRecords.build_parts_id,
BuildParts.part_code,
BuildParts.part_no,
AccountRecords.build_decision_book_id
).alias('build_parts_to_account_records')
query = select(
subquery.c.build_decision_book_id,
subquery.c.build_parts_id,
subquery.c.part_code,
subquery.c.part_no,
subquery.c.paid,
func.sum(BuildDecisionBookPayments.payment_amount).label('debt'),
(func.sum(BuildDecisionBookPayments.payment_amount) + subquery.c.paid).label('total')
).select_from(
subquery.join(
BuildDecisionBookPayments,
(BuildDecisionBookPayments.build_parts_id == subquery.c.build_parts_id) &
(BuildDecisionBookPayments.build_decision_book_id == subquery.c.build_decision_book_id)
)
).group_by(
subquery.c.build_decision_book_id,
subquery.c.build_parts_id,
subquery.c.part_code,
subquery.c.part_no,
subquery.c.paid
).order_by(
subquery.c.part_no
)
return query
def print_query_result_like_dateabse_rows(results, book_id, expiry_starts, expiry_ends):
start_time = perf_counter()
print(f"\nResults for build_decision_book_id={book_id}:")
print(f"Selected decision book starts at: {expiry_starts} - ends at: {expiry_ends}")
print("-" * 80)
print(f"{'Build ID':<10} {'Parts ID':<10} {'Part Code':<15} {'Part No':<10} {'Paid (odenen)':<15} {'Debt (borc)':<15} {'Total':<15}")
print("-" * 80)
for row in results:
print(f"{row.build_decision_book_id:<10} {row.build_parts_id:<10} {row.part_code:<15} {row.part_no:<10} {row.paid:<15.2f} {row.debt:<15.2f} {row.total:<15.2f}")
print("-" * 80)
print(f"Total rows: {len(results)}")
print(f"Query execution time: {perf_counter() - start_time:.4f} seconds")
if __name__ == "__main__":
"""
Waiting for container to be ready...
Running the Python script inside the container...
Old book ID: 49
New book ID: 50
Old book starts at: 2024-07-01 - ends at: 2025-06-30
New book starts at: 2025-07-01 - ends at: 2026-06-30
Done! Check the output above.
"""
session_factory = get_session_factory()
session = session_factory()
start_time = perf_counter()
Build.set_session(session)
BuildDecisionBook.set_session(session)
build_decision_book_id, timezone = 49, "Europe/Istanbul"
selected_decision_book = BuildDecisionBook.query.filter_by(id=build_decision_book_id).first()
old_expiry_starts = arrow.get(selected_decision_book.expiry_starts).to(timezone).date()
old_expiry_ends = arrow.get(selected_decision_book.expiry_ends).to(timezone).date()
old_book_id = selected_decision_book.id
results = BuildDecisionBook.query.filter(
BuildDecisionBook.build_id == selected_decision_book.build_id,
BuildDecisionBook.expiry_ends > old_expiry_ends).order_by(BuildDecisionBook.expiry_ends.asc()
).all()
new_book = results[0] if len(results) > 0 else None
if not new_book:
raise ValueError(f"New book not found after => {build_decision_book_id}. Contant your admin for future updates")
new_expiry_starts = arrow.get(new_book.expiry_starts).to(timezone).date()
new_expiry_ends = arrow.get(new_book.expiry_ends).to(timezone).date()
new_book_id = new_book.id
joined_query = joined_decision_book_sql_query(build_decision_book_id=build_decision_book_id)
results = session.execute(joined_query).fetchall()
print_query_result_like_dateabse_rows(results=results, book_id=old_book_id, expiry_starts=old_expiry_starts, expiry_ends=old_expiry_ends)
for result in results:
if result.total > 0:
print(f'User has extra money in old book {result.total} | build part id : {result.build_parts_id} | part code : {result.part_code} | part no : {result.part_no}')
elif result.total < 0:
print(f'User has debt in new book {result.total} | build part id : {result.build_parts_id} | part code : {result.part_code} | part no : {result.part_no}')
else:
print(f'User has no debt or extra money in old book {result.total} | build part id : {result.build_parts_id} | part code : {result.part_code} | part no : {result.part_no}')
session.close()
# print(f"Old book ID: {old_book_id}")
# print(f"New book ID: {new_book_id}")
# print(f"New book starts at: {new_expiry_starts} - ends at: {new_expiry_ends}")
# old_account_records = session.query(func.sum(AccountRecords.currency_value) - func.sum(BuildDecisionBookPayments.payment_amount)).filter(
# old_expiry_starts <= cast(AccountRecords.bank_date, Date), old_expiry_ends >= cast(AccountRecords.bank_date, Date),
# AccountRecords.currency_value > 0,
# func.abs(AccountRecords.currency_value) > func.abs(BuildDecisionBookPayments.payment_amount)
# ).scalar()
# new_account_records = session.query(func.sum(AccountRecords.currency_value) - func.sum(BuildDecisionBookPayments.payment_amount)).filter(
# new_expiry_starts <= cast(AccountRecords.bank_date, Date), new_expiry_ends >= cast(AccountRecords.bank_date, Date),
# AccountRecords.currency_value > 0,
# func.abs(AccountRecords.currency_value) > func.abs(BuildDecisionBookPayments.payment_amount)
# ).scalar()
# print(f"Old account records: {old_account_records:,.2f}")
# print(f"New account records: {new_account_records:,.2f}")
# build_to_iterate = Build.query.filter_by(id=build_id).first()
# iterate_decision_books = BuildDecisionBook.query.filter_by(build_id=build_to_iterate.id).all()
# for decision_book_to_iterate in iterate_decision_books:
# joined_query = joined_decision_book_sql_query(build_decision_book_id=decision_book_to_iterate.id)
# print(f"Build Decision Book ID: {decision_book_to_iterate.id}")
# results = session.execute(joined_query).fetchall()
# print(f"\nResults for build_decision_book_id={decision_book_to_iterate.id}:")
# print("-" * 80)
# print(f"{'Build ID':<10} {'Parts ID':<10} {'Part Code':<15} {'Part No':<10} {'Paid (odenen)':<15} {'Debt (borc)':<15}")
# print("-" * 80)
# for row in results:
# print(f"{row.build_decision_book_id:<10} {row.build_parts_id:<10} {row.part_code:<15} {row.part_no:<10} {row.odenen:<15.2f} {row.borc:<15.2f}")
# print("-" * 80)
# print(f"Total rows: {len(results)}")
# print(f"Query execution time: {perf_counter() - start_time:.4f} seconds")
# print(f"\nResults for build_decision_book_id={build_decision_book_id}:")
# print(f"Selected decision book starts at: {old_expiry_starts} - ends at: {old_expiry_ends}")
# print("-" * 80)
# print(f"{'Build ID':<10} {'Parts ID':<10} {'Part Code':<15} {'Part No':<10} {'Paid (odenen)':<15} {'Debt (borc)':<15}")
# print("-" * 80)
# for row in results:
# print(f"{row.build_decision_book_id:<10} {row.build_parts_id:<10} {row.part_code:<15} {row.part_no:<10} {row.odenen:<15.2f} {row.borc:<15.2f}")
# print("-" * 80)
# print(f"Total rows: {len(results)}")
# print(f"Query execution time: {perf_counter() - start_time:.4f} seconds")