payment updated

This commit is contained in:
Berkay 2025-07-19 22:22:21 +03:00
parent 2fe8375be2
commit 479104a04f
11 changed files with 1085 additions and 266 deletions

3
.gitignore vendored
View File

@ -162,3 +162,6 @@ yarn-error.log*
# typescript
*.tsbuildinfo
next-env.d.ts
# Project specific
ServicesBank/Zemberek/

View File

@ -13,3 +13,7 @@
Todo:
Text from bank iban dan build_id bulup | build_id den managment_room[living_space_id] bulup idisine
account records default id haline getirelecek
read_url_content(Url="https://github.com/username/repository")
read_resource(url="https://github.com/username/repository")
search_web(query="specific GitHub repository or topic", domain="github.com")

View File

@ -9,7 +9,7 @@ from Validations.response.pagination import PaginateOnly
from Extensions.Middlewares.token_provider import TokenProvider
living_space_endpoint_route = APIRouter(prefix="/living-space", tags=["Living Space Cluster"])
living_space_endpoint_route = APIRouter(prefix="/living/spaces", tags=["Living Spaces Cluster"])
living_space_list = "LivingSpaceList"

View File

@ -14,7 +14,7 @@ from Schemas import (
Build,
BuildParts,
ApiEnumDropdown,
BuildTypes,
# BuildTypes,
BuildParts,
AccountRecords,
)

View File

@ -12,7 +12,7 @@ from Validations.response import (
from Validations.defaults.validations import CommonHeaders
from Schemas import (
Addresses,
BuildTypes,
# BuildTypes,
Build,
BuildSites,
BuildParts,

View File

@ -17,7 +17,7 @@ if __name__ == "__main__":
with get_db() as db_session:
if set_alembic:
generate_alembic(session=db_session)
exit()
try:
create_one_address(db_session=db_session)
except Exception as e:
@ -26,6 +26,7 @@ if __name__ == "__main__":
init_api_enums_build_types(db_session=db_session)
except Exception as e:
print(f"Error creating enums: {e}")
exit()
try:
create_application_defaults(db_session=db_session)
except Exception as e:

View File

@ -153,12 +153,32 @@ def init_api_enums_build_types(db_session):
{
"enum_class": "BuildDuesTypes",
"type_code": "BDT-CL",
"type_name": "Close Last Period Receipt",
"type_name": "Close Last Period Debit Receipt",
},
{
"enum_class": "BuildDuesTypes",
"type_code": "BDT-OP",
"type_name": "Open New Period Receipt",
"type_name": "Open New Period Debit Receipt",
},
{
"enum_class": "BuildDuesTypes",
"type_code": "BDT-OPR",
"type_name": "Open New Period Renewal Receipt",
},
{
"enum_class": "BuildDuesTypes",
"type_code": "BDT-CLR",
"type_name": "Close Last Period Renewal Receipt",
},
{
"enum_class": "BuildDuesTypes",
"type_code": "BDT-CLL",
"type_name": "Close Last Period Lawyer Receipt",
},
{
"enum_class": "BuildDuesTypes",
"type_code": "BDT-OPR",
"type_name": "Open New Period Lawyer Receipt",
},
{
"enum_class": "BuildDuesTypes",

View File

@ -203,176 +203,6 @@ def get_read_payment_type(payment_result_type_uu_id):
return None
# Debt pay debt that is paid in same month early bird
def pay_debt_that_is_paid_in_same_month_early_bird(session, payment_type_list, date_from):
# Create aliases for tables
ar = AccountRecords.__table__.alias('ar')
bdp = BuildDecisionBookPayments.__table__.alias('bdp')
# Calculate day difference expression
day_diff = (func.cast(func.to_char(ar.c.bank_date, 'YYYYMMDD'), Integer) -
func.cast(func.to_char(bdp.c.process_date, 'YYYYMMDD'), Integer)).label('day_df')
# Calculate absolute difference between fund and payment
amount_diff = func.abs((ar.c.currency_value + ar.c.remainder_balance) - func.abs(bdp.c.debt_to_pay)).label('diff')
# Calculate fund amount
fund_amount = (ar.c.currency_value + ar.c.remainder_balance).label('fund')
# Payment correctness check
payment_correct = (ar.c.payment_result_type == bdp.c.payment_types_id).label('payment_correct')
# func.to_char(ar.c.bank_date, 'YYYY-MM') == func.to_char(bdp.c.process_date, 'YYYY-MM'),
# Build the query using SQLAlchemy
query = session.query(
ar.c.id.label('account_record_id'),
bdp.c.id.label('build_decision_book_payment_id'),
ar.c.living_space_id.label('living'),
amount_diff,
day_diff,
ar.c.process_comment,
func.cast(ar.c.bank_date, Date).label('bank_date'),
func.cast(bdp.c.process_date, Date).label('process_date'),
fund_amount,
bdp.c.debt_to_pay.label('debt'),
payment_correct
).join(
bdp,
and_(
ar.c.build_parts_id == bdp.c.build_parts_id,
func.to_char(ar.c.bank_date, 'YYYY-MM') == func.to_char(bdp.c.process_date, 'YYYY-MM'),
ar.c.payment_result_type == bdp.c.payment_types_id,
(ar.c.currency_value + ar.c.remainder_balance) == func.abs(bdp.c.debt_to_pay),
)
).filter(
ar.c.currency_value > 0,
bdp.c.build_decision_book_id == ar.c.build_decision_book_id,
bdp.c.is_closed.is_(False),
bdp.c.account_is_debit.is_(True),
func.cast(ar.c.bank_date, Date) <= datetime.now(),
func.cast(bdp.c.process_date, Date) <= datetime.now(),
func.cast(ar.c.bank_date, Date) > date_from,
func.cast(bdp.c.process_date, Date) > date_from
).order_by(ar.c.living_space_id.asc(), day_diff.asc(), amount_diff.asc(), ar.c.bank_date.desc(), bdp.c.process_date.desc())
return query.all()
# Debt pay debt that pay date in between thirty one day
def pay_debt_that_pay_date_in_between_thirty_one_day(session, payment_type_list, date_from):
# Create aliases for tables
ar = AccountRecords.__table__.alias('ar')
bdp = BuildDecisionBookPayments.__table__.alias('bdp')
# Calculate day difference expression
day_diff = (func.cast(func.to_char(ar.c.bank_date, 'YYYYMMDD'), Integer) -
func.cast(func.to_char(bdp.c.process_date, 'YYYYMMDD'), Integer)).label('day_df')
# Calculate absolute difference between fund and payment
amount_diff = func.abs((ar.c.currency_value + ar.c.remainder_balance) -
func.abs(bdp.c.debt_to_pay)).label('diff')
# Calculate fund amount
fund_amount = (ar.c.currency_value + ar.c.remainder_balance).label('fund')
# Payment correctness check
payment_correct = (ar.c.payment_result_type == bdp.c.payment_types_id).label('payment_correct')
# func.to_char(ar.c.bank_date, 'YYYY-MM') == func.to_char(bdp.c.process_date, 'YYYY-MM'),
# Build the query using SQLAlchemy
query = session.query(
ar.c.id.label('account_record_id'),
bdp.c.id.label('build_decision_book_payment_id'),
ar.c.living_space_id.label('living'),
amount_diff,
day_diff,
ar.c.process_comment,
func.cast(ar.c.bank_date, Date).label('bank_date'),
func.cast(bdp.c.process_date, Date).label('process_date'),
fund_amount,
bdp.c.debt_to_pay.label('debt'),
payment_correct
).join(
bdp,
and_(
ar.c.build_parts_id == bdp.c.build_parts_id,
ar.c.payment_result_type == bdp.c.payment_types_id,
(ar.c.currency_value + ar.c.remainder_balance) == func.abs(bdp.c.debt_to_pay),
func.abs(func.cast(ar.c.bank_date, Date) - func.cast(bdp.c.process_date, Date)) < 32,
)
).filter(
bdp.c.is_closed.is_(False),
ar.c.currency_value > 0,
bdp.c.account_is_debit.is_(True),
bdp.c.build_decision_book_id == ar.c.build_decision_book_id,
func.cast(ar.c.bank_date, Date) < datetime.now(),
func.cast(bdp.c.process_date, Date) < datetime.now(),
func.cast(ar.c.bank_date, Date) > date_from,
func.cast(bdp.c.process_date, Date) > date_from
).order_by(ar.c.living_space_id.asc(), day_diff.asc(), amount_diff.asc(), ar.c.bank_date.desc(), bdp.c.process_date.desc())
return query.all()
# Debt pay debt that has sent to do many rows
def pay_debt_that_has_sent_to_do_many_rows(session, payment_type_list, date_from):
# Create aliases for tables
ar = AccountRecords.__table__.alias('ar')
bdp = BuildDecisionBookPayments.__table__.alias('bdp')
# Calculate day difference expression
day_diff = (func.cast(func.to_char(ar.c.bank_date, 'YYYYMMDD'), Integer) -
func.cast(func.to_char(bdp.c.process_date, 'YYYYMMDD'), Integer)).label('day_df')
# Calculate absolute difference between fund and payment
amount_diff = func.abs((ar.c.currency_value + ar.c.remainder_balance) -
func.abs(bdp.c.debt_to_pay)).label('diff')
# Calculate fund amount
fund_amount = (ar.c.currency_value + ar.c.remainder_balance).label('fund')
# Payment correctness check
payment_correct = (ar.c.payment_result_type == bdp.c.payment_types_id).label('payment_correct')
# func.to_char(ar.c.bank_date, 'YYYY-MM') == func.to_char(bdp.c.process_date, 'YYYY-MM'),
# Build the query using SQLAlchemy
query = session.query(
ar.c.id.label('account_record_id'),
bdp.c.id.label('build_decision_book_payment_id'),
ar.c.living_space_id.label('living'),
amount_diff,
day_diff,
ar.c.process_comment,
func.cast(ar.c.bank_date, Date).label('bank_date'),
func.cast(bdp.c.process_date, Date).label('process_date'),
fund_amount,
bdp.c.debt_to_pay.label('debt'),
payment_correct
).join(
bdp,
and_(
ar.c.build_parts_id == bdp.c.build_parts_id,
ar.c.build_decision_book_id == bdp.c.build_decision_book_id,
func.abs(func.cast(ar.c.bank_date, Date) - func.cast(bdp.c.process_date, Date)) < 32,
ar.c.payment_result_type == bdp.c.payment_types_id,
(ar.c.currency_value + ar.c.remainder_balance) >= func.abs(bdp.c.debt_to_pay),
bdp.c.is_closed.is_(False),
)
).filter(
ar.c.currency_value > 0,
ar.c.build_decision_book_id == bdp.c.build_decision_book_id,
bdp.c.account_is_debit.is_(True),
func.cast(ar.c.bank_date, Date) < datetime.now(),
func.cast(bdp.c.process_date, Date) < datetime.now(),
func.cast(ar.c.bank_date, Date) > date_from,
func.cast(bdp.c.process_date, Date) > date_from
).order_by(
ar.c.living_space_id.asc(),
day_diff.asc(),
amount_diff.asc(),
ar.c.bank_date.desc(),
bdp.c.process_date.desc()
)
return query.all()
if __name__ == "__main__":
# import sys
@ -384,56 +214,70 @@ if __name__ == "__main__":
session = session_factory()
payment_type_list = get_enums_from_database()
date_from = '2022-01-01'
early_bird_results = pay_debt_that_is_paid_in_same_month_early_bird(session=session, payment_type_list=payment_type_list, date_from=date_from)
for early_bird_result in early_bird_results:
results = session.query(distinct(AccountRecords.build_parts_id)).filter(
AccountRecords.active == True, func.abs(AccountRecords.currency_value) - func.abs(AccountRecords.remainder_balance) > 0,
AccountRecords.bank_date >= date_from, AccountRecords.bank_date <= datetime.now(), AccountRecords.currency_value > 0
).order_by(AccountRecords.build_parts_id.asc()).all()
build_parts_ids = [result[0] for result in results]
build_parts_ids.remove(1)
for build_parts_id in build_parts_ids:
AccountRecords.set_session(session)
BuildDecisionBookPayments.set_session(session)
all_account_records_of_selected_build_parts = session.query(AccountRecords).filter(
AccountRecords.active == True, func.abs(AccountRecords.currency_value) - func.abs(AccountRecords.remainder_balance) > 0,
AccountRecords.bank_date >= date_from, AccountRecords.bank_date <= datetime.now(), AccountRecords.currency_value > 0,
AccountRecords.build_parts_id == build_parts_id
).order_by(AccountRecords.bank_date.desc()).limit(10).offset(0).all()
for account_record in all_account_records_of_selected_build_parts:
AccountRecords.set_session(session)
BuildDecisionBookPayments.set_session(session)
print(ExactMatch(*early_bird_result).to_dict())
account_record = AccountRecords.query.filter_by(id=early_bird_result.account_record_id).first()
book_payment = BuildDecisionBookPayments.query.filter_by(id=early_bird_result.build_decision_book_payment_id).first()
fund = account_record.currency_value + account_record.remainder_balance
if fund < abs(book_payment.debt_to_pay):
print("Fund is less than debt to pay", "-" * 500)
continue
if book_payment.is_closed:
print("Payment is closed", "-" * 500)
continue
close_payment_book(account_record=account_record, payment_row_book=book_payment, session=session, value=book_payment.debt_to_pay, is_commission_applicable=False)
count_row += 1
late_bird_results = pay_debt_that_pay_date_in_between_thirty_one_day(session=session, payment_type_list=payment_type_list, date_from=date_from)
for late_bird_result in late_bird_results:
AccountRecords.set_session(session)
BuildDecisionBookPayments.set_session(session)
print(ExactMatch(*late_bird_result).to_dict())
account_record = AccountRecords.query.filter_by(id=late_bird_result.account_record_id).first()
book_payment = BuildDecisionBookPayments.query.filter_by(id=late_bird_result.build_decision_book_payment_id).first()
fund = account_record.currency_value + account_record.remainder_balance
if fund < abs(book_payment.debt_to_pay):
print("Fund is less than debt to pay", "-" * 500)
continue
if book_payment.is_closed:
print("Payment is closed", "-" * 500)
continue
close_payment_book(account_record=account_record, payment_row_book=book_payment, session=session, value=book_payment.debt_to_pay, is_commission_applicable=False)
count_row += 1
selected_bank_date = account_record.bank_date
selected_bank_date_month = selected_bank_date.month
selected_bank_date_year = selected_bank_date.year
year_month = f"{selected_bank_date_year}-{selected_bank_date_month:02d}"
print(f"Build decision book id: {account_record.build_decision_book_id}")
total_amount_collected_this_month = session.query(func.sum(AccountRecords.currency_value)).filter(
AccountRecords.currency_value > 0,
AccountRecords.build_decision_book_id == account_record.build_decision_book_id,
func.abs(AccountRecords.currency_value) - func.abs(AccountRecords.remainder_balance) > 0,
func.extract('month', AccountRecords.bank_date) == selected_bank_date_month,
func.extract('year', AccountRecords.bank_date) == selected_bank_date_year,
AccountRecords.build_parts_id == build_parts_id
).scalar() or 0
total_amount_of_debt_of_this_month = session.query(func.sum(BuildDecisionBookPayments.debt_to_pay)).filter(
BuildDecisionBookPayments.account_is_debit == True,
BuildDecisionBookPayments.build_decision_book_id == account_record.build_decision_book_id,
func.extract('month', BuildDecisionBookPayments.process_date) == selected_bank_date_month,
func.extract('year', BuildDecisionBookPayments.process_date) == selected_bank_date_year,
BuildDecisionBookPayments.process_date <= datetime.now()
).scalar() or 0
print(f"{year_month} total amount of debt in this month : ", f"{total_amount_of_debt_of_this_month:,.2f}")
print(f"{year_month} total amount collected this month : ", f"{total_amount_collected_this_month:,.2f}")
thirty_three_days = pay_debt_that_has_sent_to_do_many_rows(session=session, payment_type_list=payment_type_list, date_from=date_from)
for thirty_three_day in thirty_three_days:
AccountRecords.set_session(session)
BuildDecisionBookPayments.set_session(session)
print(ExactMatch(*thirty_three_day).to_dict())
account_record = AccountRecords.query.filter_by(id=thirty_three_day.account_record_id).first()
book_payment = BuildDecisionBookPayments.query.filter_by(id=thirty_three_day.build_decision_book_payment_id).first()
fund = account_record.currency_value + account_record.remainder_balance
if fund < abs(book_payment.debt_to_pay):
print("Fund is less than debt to pay", "-" * 500)
continue
if book_payment.is_closed:
print("Payment is closed", "-" * 500)
continue
close_payment_book(account_record=account_record, payment_row_book=book_payment, session=session, value=book_payment.debt_to_pay, is_commission_applicable=False)
count_row += 1
avaliable_fund = abs(account_record.currency_value) - abs(account_record.remainder_balance)
total_debt_to_pay_of_this_month = session.query(func.sum(BuildDecisionBookPayments.debt_to_pay)).filter(
BuildDecisionBookPayments.account_is_debit == True,
BuildDecisionBookPayments.build_decision_book_id == account_record.build_decision_book_id,
func.extract('month', BuildDecisionBookPayments.process_date) == selected_bank_date_month,
func.extract('year', BuildDecisionBookPayments.process_date) == selected_bank_date_year,
BuildDecisionBookPayments.process_date <= datetime.now()
).scalar() or 0
exact_match_with_account_fund_and_debt_to_pay = BuildDecisionBookPayments.query.filter(
BuildDecisionBookPayments.account_is_debit == True,
BuildDecisionBookPayments.build_decision_book_id == account_record.build_decision_book_id,
func.extract('month', BuildDecisionBookPayments.process_date) == selected_bank_date_month,
func.extract('year', BuildDecisionBookPayments.process_date) == selected_bank_date_year,
BuildDecisionBookPayments.process_date <= datetime.now(),
BuildDecisionBookPayments.debt_to_pay == avaliable_fund
).first()
is_fund_available_is_completely_closes_all_debts = avaliable_fund >= total_debt_to_pay_of_this_month
is_one_of_the_debt_to_pay_exactly_matches = avaliable_fund == exact_match_with_account_fund_and_debt_to_pay.debt_to_pay if exact_match_with_account_fund_and_debt_to_pay else False
print(f"account record id: {account_record.id} | bank date: {account_record.bank_date.date()} | total debt to pay: {total_debt_to_pay_of_this_month:,.2f}")
print(f"avaliable fund: {avaliable_fund:,.2f} | exact match: {is_one_of_the_debt_to_pay_exactly_matches}")
print(f"Build part processed: {build_parts_id}")
session.close()
print(f"Processed {count_row} rows")
# Parse command line arguments

View File

@ -0,0 +1,445 @@
import arrow
import calendar
from time import perf_counter
from decimal import Decimal
from datetime import datetime, timedelta
from Schemas import BuildDecisionBookPayments, AccountRecords, AccountDelayInterest, ApiEnumDropdown, Build, BuildDecisionBook
from sqlalchemy import select,text, Integer, Float, func, distinct, cast, Date, String, literal, desc, and_, or_, case
from sqlalchemy.sql.expression import literal
from Controllers.Postgres.engine import get_session_factory
def find_last_day_of_month(date_value):
today = date_value.date()
_, last_day = calendar.monthrange(today.year, today.month)
return datetime(today.year, today.month, last_day, 23, 59, 59)
def find_first_day_of_month(date_value):
today = date_value.date()
return datetime(today.year, today.month, 1)
def add_month_to_date(date_value):
month_to_process = date_value.month
year_to_process = date_value.year
if date_value.month == 12:
month_to_process = 1
year_to_process += 1
else:
month_to_process += 1
_, last_day = calendar.monthrange(year_to_process, month_to_process)
return datetime(year_to_process, month_to_process, 1), datetime(year_to_process, month_to_process, last_day)
class BuildDuesTypes:
def __init__(self):
self.debit: ApiEnumDropdownShallowCopy = None
self.add_debit: ApiEnumDropdownShallowCopy = None
self.renovation: ApiEnumDropdownShallowCopy = None
self.lawyer_expence: ApiEnumDropdownShallowCopy = None
self.service_fee: ApiEnumDropdownShallowCopy = None
self.information: ApiEnumDropdownShallowCopy = None
class ApiEnumDropdownShallowCopy:
id: int
uuid: str
enum_class: str
key: str
value: str
def __init__(self, id: int, uuid: str, enum_class: str, key: str, value: str):
self.id = id
self.uuid = uuid
self.enum_class = enum_class
self.key = key
self.value = value
class ExactMatch:
def __init__(self,
account_record_id, build_decision_book_payment_id, living, diff, day_df, process_comment,
bank_date, process_date, fund, debt, payment_correct):
self.account_record_id = account_record_id
self.build_decision_book_payment_id = build_decision_book_payment_id
self.living = living
self.diff = diff
self.day_df = day_df
self.process_comment = process_comment
self.bank_date = str(bank_date)
self.process_date = str(process_date)
self.fund = fund
self.debt = debt
self.payment_correct = payment_correct
def to_dict(self):
return {
'account_record_id': self.account_record_id,
'build_decision_book_payment_id': self.build_decision_book_payment_id,
# 'process_comment': self.process_comment,
'living': self.living,
'diff': self.diff,
'day_df': self.day_df,
'bank_date': self.bank_date,
'process_date': self.process_date,
'fund': self.fund,
'debt': self.debt,
'payment_correct': self.payment_correct
}
def close_payment_book(payment_row_book, account_record, value, session, is_commission_applicable: bool = False):
"""Create a credit entry in BuildDecisionBookPayments to close a debt.
Args:
payment_row_book: The debit entry to be paid
account_record: The account record containing the funds
value: The amount to pay
session: Database session
Returns:
The newly created payment record
"""
BuildDecisionBookPayments.set_session(session)
# account_record_remainder_balance = retrieve_remainder_balance_set_if_needed(account_record_id=account_record.id, session=session)
# print(f'NOT Updated remainder balance: {account_record_remainder_balance} | Account record id: {account_record.id}')
# Create a new credit entry (payment)
new_row = BuildDecisionBookPayments.create(
ref_id=str(payment_row_book.uu_id),
payment_plan_time_periods=payment_row_book.payment_plan_time_periods,
period_time=payment_row_book.period_time,
currency=payment_row_book.currency,
account_records_id=account_record.id,
account_records_uu_id=str(account_record.uu_id),
build_parts_id=payment_row_book.build_parts_id,
build_parts_uu_id=str(payment_row_book.build_parts_uu_id),
payment_amount=abs(value), # Negative for credit entries
payment_types_id=payment_row_book.payment_types_id,
payment_types_uu_id=str(payment_row_book.payment_types_uu_id),
process_date_m=payment_row_book.process_date.month,
process_date_y=payment_row_book.process_date.year,
process_date=payment_row_book.process_date,
build_decision_book_item_id=payment_row_book.build_decision_book_item_id if payment_row_book.build_decision_book_item_id else None,
build_decision_book_item_uu_id=str(payment_row_book.build_decision_book_item_uu_id) if payment_row_book.build_decision_book_item_uu_id else None,
decision_book_project_id=payment_row_book.decision_book_project_id if payment_row_book.decision_book_project_id else None,
decision_book_project_uu_id=str(payment_row_book.decision_book_project_uu_id) if payment_row_book.decision_book_project_uu_id else None,
build_decision_book_id=payment_row_book.build_decision_book_id if payment_row_book.build_decision_book_id else None,
build_decision_book_uu_id=str(payment_row_book.build_decision_book_uu_id) if payment_row_book.build_decision_book_uu_id else None,
is_confirmed=True,
account_is_debit=False,
)
# Save the new payment record
saved_row = new_row.save()
session.commit()
session.refresh(saved_row)
if is_commission_applicable:
AccountDelayInterest.set_session(session)
new_row_interest = AccountDelayInterest.create(
account_record_bank_date=account_record.bank_date,
book_payment_process_date=payment_row_book.process_date,
debt=abs(value),
account_records_id=account_record.id,
account_records_uu_id=str(account_record.uu_id),
build_decision_book_payment_id=saved_row.id,
build_decision_book_payment_uu_id=str(saved_row.uu_id),
replication_id=99, # Triggers for trigger_account_delay_interest calculation [active trigger]
bank_resp_company_id=1, # Evyos interest rates will be applied when id is given
bank_resp_company_uu_id="CMP",
)
new_row_interest.save()
session.commit()
session.refresh(new_row_interest)
print(f'Commission applicable: amount : {value} bank date: {account_record.bank_date} process date: {payment_row_book.process_date}')
# account_record_remainder_balance = retrieve_remainder_balance_set_if_needed(account_record_id=account_record.id, session=session)
# print(f'Updated remainder balance: {account_record_remainder_balance} | Account record id: {account_record.id}')
# check_current_debt_to_pay_from_database_is_closed(ref_id=new_row.ref_id, session=session)
return None
def get_enums_from_database():
build_dues_types = BuildDuesTypes()
with ApiEnumDropdown.new_session() as session:
ApiEnumDropdown.set_session(session)
debit_enum_shallow = ApiEnumDropdown.query.filter_by(enum_class="BuildDuesTypes", key="BDT-D").first() # Debit
add_debit_enum_shallow = ApiEnumDropdown.query.filter_by(enum_class="BuildDuesTypes", key="BDT-A").first() # Add Debit
renovation_enum_shallow = ApiEnumDropdown.query.filter_by(enum_class="BuildDuesTypes", key="BDT-R").first() # Renovation
late_payment_enum_shallow = ApiEnumDropdown.query.filter_by(enum_class="BuildDuesTypes", key="BDT-L").first() # Lawyer expence
service_fee_enum_shallow = ApiEnumDropdown.query.filter_by(enum_class="BuildDuesTypes", key="BDT-S").first() # Service fee
information_enum_shallow = ApiEnumDropdown.query.filter_by(enum_class="BuildDuesTypes", key="BDT-I").first() # Information
build_dues_types.debit = ApiEnumDropdownShallowCopy(
debit_enum_shallow.id, str(debit_enum_shallow.uu_id), debit_enum_shallow.enum_class, debit_enum_shallow.key, debit_enum_shallow.value
)
build_dues_types.add_debit = ApiEnumDropdownShallowCopy(
add_debit_enum_shallow.id, str(add_debit_enum_shallow.uu_id), add_debit_enum_shallow.enum_class, add_debit_enum_shallow.key, add_debit_enum_shallow.value
)
build_dues_types.renovation = ApiEnumDropdownShallowCopy(
renovation_enum_shallow.id, str(renovation_enum_shallow.uu_id), renovation_enum_shallow.enum_class, renovation_enum_shallow.key, renovation_enum_shallow.value
)
build_dues_types.lawyer_expence = ApiEnumDropdownShallowCopy(
late_payment_enum_shallow.id, str(late_payment_enum_shallow.uu_id), late_payment_enum_shallow.enum_class, late_payment_enum_shallow.key, late_payment_enum_shallow.value
)
build_dues_types.service_fee = ApiEnumDropdownShallowCopy(
service_fee_enum_shallow.id, str(service_fee_enum_shallow.uu_id), service_fee_enum_shallow.enum_class, service_fee_enum_shallow.key, service_fee_enum_shallow.value
)
build_dues_types.information = ApiEnumDropdownShallowCopy(
information_enum_shallow.id, str(information_enum_shallow.uu_id), information_enum_shallow.enum_class, information_enum_shallow.key, information_enum_shallow.value
)
return [build_dues_types.debit, build_dues_types.lawyer_expence, build_dues_types.add_debit, build_dues_types.renovation, build_dues_types.service_fee, build_dues_types.information]
def get_read_payment_type(payment_result_type_uu_id):
payment_type_list = get_enums_from_database()
for payment_type in payment_type_list:
if payment_type.uuid == payment_result_type_uu_id:
return payment_type.key
return None
# Debt pay debt that is paid in same month early bird
def pay_debt_that_is_paid_in_same_month_early_bird(session, payment_type_list, date_from):
# Create aliases for tables
ar = AccountRecords.__table__.alias('ar')
bdp = BuildDecisionBookPayments.__table__.alias('bdp')
# Calculate day difference expression
day_diff = (func.cast(func.to_char(ar.c.bank_date, 'YYYYMMDD'), Integer) -
func.cast(func.to_char(bdp.c.process_date, 'YYYYMMDD'), Integer)).label('day_df')
# Calculate absolute difference between fund and payment
amount_diff = func.abs((ar.c.currency_value + ar.c.remainder_balance) - func.abs(bdp.c.debt_to_pay)).label('diff')
# Calculate fund amount
fund_amount = (ar.c.currency_value + ar.c.remainder_balance).label('fund')
# Payment correctness check
payment_correct = (ar.c.payment_result_type == bdp.c.payment_types_id).label('payment_correct')
# func.to_char(ar.c.bank_date, 'YYYY-MM') == func.to_char(bdp.c.process_date, 'YYYY-MM'),
# Build the query using SQLAlchemy
query = session.query(
ar.c.id.label('account_record_id'),
bdp.c.id.label('build_decision_book_payment_id'),
ar.c.living_space_id.label('living'),
amount_diff,
day_diff,
ar.c.process_comment,
func.cast(ar.c.bank_date, Date).label('bank_date'),
func.cast(bdp.c.process_date, Date).label('process_date'),
fund_amount,
bdp.c.debt_to_pay.label('debt'),
payment_correct
).join(
bdp,
and_(
ar.c.build_parts_id == bdp.c.build_parts_id,
func.to_char(ar.c.bank_date, 'YYYY-MM') == func.to_char(bdp.c.process_date, 'YYYY-MM'),
ar.c.payment_result_type == bdp.c.payment_types_id,
(ar.c.currency_value + ar.c.remainder_balance) == func.abs(bdp.c.debt_to_pay),
)
).filter(
ar.c.currency_value > 0,
bdp.c.build_decision_book_id == ar.c.build_decision_book_id,
bdp.c.is_closed.is_(False),
bdp.c.account_is_debit.is_(True),
func.cast(ar.c.bank_date, Date) <= datetime.now(),
func.cast(bdp.c.process_date, Date) <= datetime.now(),
func.cast(ar.c.bank_date, Date) > date_from,
func.cast(bdp.c.process_date, Date) > date_from
).order_by(ar.c.living_space_id.asc(), day_diff.asc(), amount_diff.asc(), ar.c.bank_date.desc(), bdp.c.process_date.desc())
return query.all()
# Debt pay debt that pay date in between thirty one day
def pay_debt_that_pay_date_in_between_thirty_one_day(session, payment_type_list, date_from):
# Create aliases for tables
ar = AccountRecords.__table__.alias('ar')
bdp = BuildDecisionBookPayments.__table__.alias('bdp')
# Calculate day difference expression
day_diff = (func.cast(func.to_char(ar.c.bank_date, 'YYYYMMDD'), Integer) -
func.cast(func.to_char(bdp.c.process_date, 'YYYYMMDD'), Integer)).label('day_df')
# Calculate absolute difference between fund and payment
amount_diff = func.abs((ar.c.currency_value + ar.c.remainder_balance) -
func.abs(bdp.c.debt_to_pay)).label('diff')
# Calculate fund amount
fund_amount = (ar.c.currency_value + ar.c.remainder_balance).label('fund')
# Payment correctness check
payment_correct = (ar.c.payment_result_type == bdp.c.payment_types_id).label('payment_correct')
# func.to_char(ar.c.bank_date, 'YYYY-MM') == func.to_char(bdp.c.process_date, 'YYYY-MM'),
# Build the query using SQLAlchemy
query = session.query(
ar.c.id.label('account_record_id'),
bdp.c.id.label('build_decision_book_payment_id'),
ar.c.living_space_id.label('living'),
amount_diff,
day_diff,
ar.c.process_comment,
func.cast(ar.c.bank_date, Date).label('bank_date'),
func.cast(bdp.c.process_date, Date).label('process_date'),
fund_amount,
bdp.c.debt_to_pay.label('debt'),
payment_correct
).join(
bdp,
and_(
ar.c.build_parts_id == bdp.c.build_parts_id,
ar.c.payment_result_type == bdp.c.payment_types_id,
(ar.c.currency_value + ar.c.remainder_balance) == func.abs(bdp.c.debt_to_pay),
func.abs(func.cast(ar.c.bank_date, Date) - func.cast(bdp.c.process_date, Date)) < 32,
)
).filter(
bdp.c.is_closed.is_(False),
ar.c.currency_value > 0,
bdp.c.account_is_debit.is_(True),
bdp.c.build_decision_book_id == ar.c.build_decision_book_id,
func.cast(ar.c.bank_date, Date) < datetime.now(),
func.cast(bdp.c.process_date, Date) < datetime.now(),
func.cast(ar.c.bank_date, Date) > date_from,
func.cast(bdp.c.process_date, Date) > date_from
).order_by(ar.c.living_space_id.asc(), day_diff.asc(), amount_diff.asc(), ar.c.bank_date.desc(), bdp.c.process_date.desc())
return query.all()
# Debt pay debt that has sent to do many rows
def pay_debt_that_has_sent_to_do_many_rows(session, payment_type_list, date_from):
# Create aliases for tables
ar = AccountRecords.__table__.alias('ar')
bdp = BuildDecisionBookPayments.__table__.alias('bdp')
# Calculate day difference expression
day_diff = (func.cast(func.to_char(ar.c.bank_date, 'YYYYMMDD'), Integer) -
func.cast(func.to_char(bdp.c.process_date, 'YYYYMMDD'), Integer)).label('day_df')
# Calculate absolute difference between fund and payment
amount_diff = func.abs((ar.c.currency_value + ar.c.remainder_balance) -
func.abs(bdp.c.debt_to_pay)).label('diff')
# Calculate fund amount
fund_amount = (ar.c.currency_value + ar.c.remainder_balance).label('fund')
# Payment correctness check
payment_correct = (ar.c.payment_result_type == bdp.c.payment_types_id).label('payment_correct')
# func.to_char(ar.c.bank_date, 'YYYY-MM') == func.to_char(bdp.c.process_date, 'YYYY-MM'),
# Build the query using SQLAlchemy
query = session.query(
ar.c.id.label('account_record_id'),
bdp.c.id.label('build_decision_book_payment_id'),
ar.c.living_space_id.label('living'),
amount_diff,
day_diff,
ar.c.process_comment,
func.cast(ar.c.bank_date, Date).label('bank_date'),
func.cast(bdp.c.process_date, Date).label('process_date'),
fund_amount,
bdp.c.debt_to_pay.label('debt'),
payment_correct
).join(
bdp,
and_(
ar.c.build_parts_id == bdp.c.build_parts_id,
ar.c.build_decision_book_id == bdp.c.build_decision_book_id,
func.abs(func.cast(ar.c.bank_date, Date) - func.cast(bdp.c.process_date, Date)) < 32,
ar.c.payment_result_type == bdp.c.payment_types_id,
(ar.c.currency_value + ar.c.remainder_balance) >= func.abs(bdp.c.debt_to_pay),
bdp.c.is_closed.is_(False),
)
).filter(
ar.c.currency_value > 0,
ar.c.build_decision_book_id == bdp.c.build_decision_book_id,
bdp.c.account_is_debit.is_(True),
func.cast(ar.c.bank_date, Date) < datetime.now(),
func.cast(bdp.c.process_date, Date) < datetime.now(),
func.cast(ar.c.bank_date, Date) > date_from,
func.cast(bdp.c.process_date, Date) > date_from
).order_by(
ar.c.living_space_id.asc(),
day_diff.asc(),
amount_diff.asc(),
ar.c.bank_date.desc(),
bdp.c.process_date.desc()
)
return query.all()
if __name__ == "__main__":
# import sys
# Default values
# id_given = 1
count_row = 0
session_factory = get_session_factory()
session = session_factory()
payment_type_list = get_enums_from_database()
date_from = '2022-01-01'
early_bird_results = pay_debt_that_is_paid_in_same_month_early_bird(session=session, payment_type_list=payment_type_list, date_from=date_from)
for early_bird_result in early_bird_results:
AccountRecords.set_session(session)
BuildDecisionBookPayments.set_session(session)
print(ExactMatch(*early_bird_result).to_dict())
account_record = AccountRecords.query.filter_by(id=early_bird_result.account_record_id).first()
book_payment = BuildDecisionBookPayments.query.filter_by(id=early_bird_result.build_decision_book_payment_id).first()
fund = account_record.currency_value + account_record.remainder_balance
if fund < abs(book_payment.debt_to_pay):
print("Fund is less than debt to pay", "-" * 500)
continue
if book_payment.is_closed:
print("Payment is closed", "-" * 500)
continue
close_payment_book(account_record=account_record, payment_row_book=book_payment, session=session, value=book_payment.debt_to_pay, is_commission_applicable=False)
count_row += 1
late_bird_results = pay_debt_that_pay_date_in_between_thirty_one_day(session=session, payment_type_list=payment_type_list, date_from=date_from)
for late_bird_result in late_bird_results:
AccountRecords.set_session(session)
BuildDecisionBookPayments.set_session(session)
print(ExactMatch(*late_bird_result).to_dict())
account_record = AccountRecords.query.filter_by(id=late_bird_result.account_record_id).first()
book_payment = BuildDecisionBookPayments.query.filter_by(id=late_bird_result.build_decision_book_payment_id).first()
fund = account_record.currency_value + account_record.remainder_balance
if fund < abs(book_payment.debt_to_pay):
print("Fund is less than debt to pay", "-" * 500)
continue
if book_payment.is_closed:
print("Payment is closed", "-" * 500)
continue
close_payment_book(account_record=account_record, payment_row_book=book_payment, session=session, value=book_payment.debt_to_pay, is_commission_applicable=False)
count_row += 1
thirty_three_days = pay_debt_that_has_sent_to_do_many_rows(session=session, payment_type_list=payment_type_list, date_from=date_from)
for thirty_three_day in thirty_three_days:
AccountRecords.set_session(session)
BuildDecisionBookPayments.set_session(session)
print(ExactMatch(*thirty_three_day).to_dict())
account_record = AccountRecords.query.filter_by(id=thirty_three_day.account_record_id).first()
book_payment = BuildDecisionBookPayments.query.filter_by(id=thirty_three_day.build_decision_book_payment_id).first()
fund = account_record.currency_value + account_record.remainder_balance
if fund < abs(book_payment.debt_to_pay):
print("Fund is less than debt to pay", "-" * 500)
continue
if book_payment.is_closed:
print("Payment is closed", "-" * 500)
continue
close_payment_book(account_record=account_record, payment_row_book=book_payment, session=session, value=book_payment.debt_to_pay, is_commission_applicable=False)
count_row += 1
session.close()
print(f"Processed {count_row} rows")
# Parse command line arguments
# if len(sys.argv) > 1:
# try:
# id_given = int(sys.argv[1])
# except ValueError:
# print(f"Error: Invalid limit value '{sys.argv[1]}'. Using default limit={limit}")

View File

@ -0,0 +1,493 @@
import arrow
import calendar
from time import perf_counter
from decimal import Decimal
from datetime import datetime, timedelta
from Schemas import BuildDecisionBookPayments, AccountRecords, AccountDelayInterest, ApiEnumDropdown, Build, BuildDecisionBook
from sqlalchemy import select,text, Integer, Float, func, distinct, cast, Date, String, literal, desc, and_, or_, case
from sqlalchemy.sql.expression import literal
from Controllers.Postgres.engine import get_session_factory
def find_last_day_of_month(date_value):
today = date_value.date()
_, last_day = calendar.monthrange(today.year, today.month)
return datetime(today.year, today.month, last_day, 23, 59, 59)
def find_first_day_of_month(date_value):
today = date_value.date()
return datetime(today.year, today.month, 1)
def add_month_to_date(date_value):
month_to_process = date_value.month
year_to_process = date_value.year
if date_value.month == 12:
month_to_process = 1
year_to_process += 1
else:
month_to_process += 1
_, last_day = calendar.monthrange(year_to_process, month_to_process)
return datetime(year_to_process, month_to_process, 1), datetime(year_to_process, month_to_process, last_day)
class BuildDuesTypes:
def __init__(self):
self.debit: ApiEnumDropdownShallowCopy = None
self.add_debit: ApiEnumDropdownShallowCopy = None
self.renovation: ApiEnumDropdownShallowCopy = None
self.lawyer_expence: ApiEnumDropdownShallowCopy = None
self.service_fee: ApiEnumDropdownShallowCopy = None
self.information: ApiEnumDropdownShallowCopy = None
class ApiEnumDropdownShallowCopy:
id: int
uuid: str
enum_class: str
key: str
value: str
def __init__(self, id: int, uuid: str, enum_class: str, key: str, value: str):
self.id = id
self.uuid = uuid
self.enum_class = enum_class
self.key = key
self.value = value
def get_enums_from_database():
build_dues_types = BuildDuesTypes()
with ApiEnumDropdown.new_session() as session:
ApiEnumDropdown.set_session(session)
debit_enum_shallow = ApiEnumDropdown.query.filter_by(enum_class="BuildDuesTypes", key="BDT-D").first() # Debit
add_debit_enum_shallow = ApiEnumDropdown.query.filter_by(enum_class="BuildDuesTypes", key="BDT-A").first() # Add Debit
renovation_enum_shallow = ApiEnumDropdown.query.filter_by(enum_class="BuildDuesTypes", key="BDT-R").first() # Renovation
late_payment_enum_shallow = ApiEnumDropdown.query.filter_by(enum_class="BuildDuesTypes", key="BDT-L").first() # Lawyer expence
service_fee_enum_shallow = ApiEnumDropdown.query.filter_by(enum_class="BuildDuesTypes", key="BDT-S").first() # Service fee
information_enum_shallow = ApiEnumDropdown.query.filter_by(enum_class="BuildDuesTypes", key="BDT-I").first() # Information
build_dues_types.debit = ApiEnumDropdownShallowCopy(
debit_enum_shallow.id, str(debit_enum_shallow.uu_id), debit_enum_shallow.enum_class, debit_enum_shallow.key, debit_enum_shallow.value
)
build_dues_types.add_debit = ApiEnumDropdownShallowCopy(
add_debit_enum_shallow.id, str(add_debit_enum_shallow.uu_id), add_debit_enum_shallow.enum_class, add_debit_enum_shallow.key, add_debit_enum_shallow.value
)
build_dues_types.renovation = ApiEnumDropdownShallowCopy(
renovation_enum_shallow.id, str(renovation_enum_shallow.uu_id), renovation_enum_shallow.enum_class, renovation_enum_shallow.key, renovation_enum_shallow.value
)
build_dues_types.lawyer_expence = ApiEnumDropdownShallowCopy(
late_payment_enum_shallow.id, str(late_payment_enum_shallow.uu_id), late_payment_enum_shallow.enum_class, late_payment_enum_shallow.key, late_payment_enum_shallow.value
)
build_dues_types.service_fee = ApiEnumDropdownShallowCopy(
service_fee_enum_shallow.id, str(service_fee_enum_shallow.uu_id), service_fee_enum_shallow.enum_class, service_fee_enum_shallow.key, service_fee_enum_shallow.value
)
build_dues_types.information = ApiEnumDropdownShallowCopy(
information_enum_shallow.id, str(information_enum_shallow.uu_id), information_enum_shallow.enum_class, information_enum_shallow.key, information_enum_shallow.value
)
return [build_dues_types.debit, build_dues_types.lawyer_expence, build_dues_types.add_debit, build_dues_types.renovation, build_dues_types.service_fee, build_dues_types.information]
def read_all_account_records(session, date_from, list_payment_type = None):
if list_payment_type:
return session.query(AccountRecords).filter(
func.abs(AccountRecords.currency_value) - func.abs(AccountRecords.remainder_balance) > 0,
cast(AccountRecords.bank_date, Date) >= date_from,
cast(AccountRecords.bank_date, Date) <= datetime.now().date(),
AccountRecords.currency_value > 0,
AccountRecords.build_parts_id > 1,
AccountRecords.payment_result_type == list_payment_type.id,
).order_by(AccountRecords.build_parts_id.asc(), AccountRecords.bank_date.asc()).all()
return session.query(AccountRecords).filter(
func.abs(AccountRecords.currency_value) - func.abs(AccountRecords.remainder_balance) > 0,
cast(AccountRecords.bank_date, Date) >= date_from,
cast(AccountRecords.bank_date, Date) <= datetime.now().date(),
AccountRecords.currency_value > 0,
AccountRecords.build_parts_id > 1,
).order_by(AccountRecords.build_parts_id.asc(), AccountRecords.bank_date.asc()).all()
def calculate_debts_for_this_month(session, date_from, list_payment_type, bank_date, build_decision_book_id, build_parts_id):
selected_bank_date_month = bank_date.month
selected_bank_date_year = bank_date.year
return session.query(func.sum(BuildDecisionBookPayments.debt_to_pay)).filter(
BuildDecisionBookPayments.build_decision_book_id == build_decision_book_id,
func.extract('month', BuildDecisionBookPayments.process_date) == int(selected_bank_date_month),
func.extract('year', BuildDecisionBookPayments.process_date) == int(selected_bank_date_year),
BuildDecisionBookPayments.payment_types_id == list_payment_type.id,
BuildDecisionBookPayments.account_is_debit == True,
BuildDecisionBookPayments.is_closed == False,
BuildDecisionBookPayments.build_parts_id == build_parts_id,
).scalar()
def calculate_debts_for_previous_month(session, date_from, list_payment_type, bank_date, build_decision_book_id, build_parts_id):
return session.query(func.sum(BuildDecisionBookPayments.debt_to_pay)).filter(
BuildDecisionBookPayments.build_decision_book_id == build_decision_book_id,
cast(BuildDecisionBookPayments.process_date, Date) <= bank_date.date(),
BuildDecisionBookPayments.payment_types_id == list_payment_type.id,
BuildDecisionBookPayments.account_is_debit == True,
BuildDecisionBookPayments.is_closed == False,
BuildDecisionBookPayments.build_parts_id == build_parts_id,
).scalar()
def calculate_debts_for_previous_month_without_payment_type(session, date_from, bank_date, build_decision_book_id, build_parts_id):
return session.query(func.sum(BuildDecisionBookPayments.debt_to_pay)).filter(
BuildDecisionBookPayments.build_decision_book_id == build_decision_book_id,
# cast(BuildDecisionBookPayments.process_date, Date) <= bank_date.date(),
BuildDecisionBookPayments.account_is_debit == True,
BuildDecisionBookPayments.is_closed == False,
BuildDecisionBookPayments.build_parts_id == build_parts_id,
).scalar()
def get_rows_of_debt_for_this_month(session, date_from, list_payment_type, bank_date, build_decision_book_id, build_parts_id):
selected_bank_date_month = bank_date.month
selected_bank_date_year = bank_date.year
return session.query(BuildDecisionBookPayments).filter(
BuildDecisionBookPayments.build_decision_book_id == build_decision_book_id,
func.extract('month', BuildDecisionBookPayments.process_date) == int(selected_bank_date_month),
func.extract('year', BuildDecisionBookPayments.process_date) == int(selected_bank_date_year),
BuildDecisionBookPayments.payment_types_id == list_payment_type.id,
BuildDecisionBookPayments.account_is_debit == True,
BuildDecisionBookPayments.is_closed == False,
BuildDecisionBookPayments.build_parts_id == build_parts_id,
).order_by(BuildDecisionBookPayments.debt_to_pay.desc()).all()
def get_rows_of_debt_for_previous_month(session, date_from, list_payment_type, bank_date, build_decision_book_id, build_parts_id):
return session.query(BuildDecisionBookPayments).filter(
BuildDecisionBookPayments.build_decision_book_id == build_decision_book_id,
cast(BuildDecisionBookPayments.process_date, Date) <= bank_date.date(),
BuildDecisionBookPayments.payment_types_id == list_payment_type.id,
BuildDecisionBookPayments.account_is_debit == True,
BuildDecisionBookPayments.is_closed == False,
BuildDecisionBookPayments.build_parts_id == build_parts_id,
).order_by(BuildDecisionBookPayments.debt_to_pay.desc(), BuildDecisionBookPayments.process_date.desc()).all()
def get_rows_of_debt_for_previous_month_without_payment_type(session, date_from, bank_date, build_decision_book_id, build_parts_id):
return session.query(BuildDecisionBookPayments).filter(
BuildDecisionBookPayments.build_decision_book_id == build_decision_book_id,
# cast(BuildDecisionBookPayments.process_date, Date) <= bank_date.date(),
BuildDecisionBookPayments.account_is_debit == True,
BuildDecisionBookPayments.is_closed == False,
BuildDecisionBookPayments.build_parts_id == build_parts_id,
).order_by(BuildDecisionBookPayments.debt_to_pay.desc(), BuildDecisionBookPayments.process_date.desc()).all()
def close_payment_book(payment_row_book, account_record, value, session, is_commission_applicable: bool = False):
"""Create a credit entry in BuildDecisionBookPayments to close a debt.
Args:
payment_row_book: The debit entry to be paid
account_record: The account record containing the funds
value: The amount to pay
session: Database session
Returns:
The newly created payment record
"""
BuildDecisionBookPayments.set_session(session)
# account_record_remainder_balance = retrieve_remainder_balance_set_if_needed(account_record_id=account_record.id, session=session)
# print(f'NOT Updated remainder balance: {account_record_remainder_balance} | Account record id: {account_record.id}')
# Create a new credit entry (payment)
new_row = BuildDecisionBookPayments.create(
ref_id=str(payment_row_book.uu_id),
payment_plan_time_periods=payment_row_book.payment_plan_time_periods,
period_time=payment_row_book.period_time,
currency=payment_row_book.currency,
account_records_id=account_record.id,
account_records_uu_id=str(account_record.uu_id),
build_parts_id=payment_row_book.build_parts_id,
build_parts_uu_id=str(payment_row_book.build_parts_uu_id),
payment_amount=abs(value), # Negative for credit entries
payment_types_id=payment_row_book.payment_types_id,
payment_types_uu_id=str(payment_row_book.payment_types_uu_id),
process_date_m=payment_row_book.process_date.month,
process_date_y=payment_row_book.process_date.year,
process_date=payment_row_book.process_date,
build_decision_book_item_id=payment_row_book.build_decision_book_item_id if payment_row_book.build_decision_book_item_id else None,
build_decision_book_item_uu_id=str(payment_row_book.build_decision_book_item_uu_id) if payment_row_book.build_decision_book_item_uu_id else None,
decision_book_project_id=payment_row_book.decision_book_project_id if payment_row_book.decision_book_project_id else None,
decision_book_project_uu_id=str(payment_row_book.decision_book_project_uu_id) if payment_row_book.decision_book_project_uu_id else None,
build_decision_book_id=payment_row_book.build_decision_book_id if payment_row_book.build_decision_book_id else None,
build_decision_book_uu_id=str(payment_row_book.build_decision_book_uu_id) if payment_row_book.build_decision_book_uu_id else None,
is_confirmed=True,
account_is_debit=False,
)
# Save the new payment record
saved_row = new_row.save()
session.commit()
session.refresh(saved_row)
if is_commission_applicable:
AccountDelayInterest.set_session(session)
debt_to_pay_with_commission_applied = payment_row_book.debt_to_pay - value
if debt_to_pay_with_commission_applied < 0:
return None
new_row_interest = AccountDelayInterest.create(
account_record_bank_date=account_record.bank_date,
book_payment_process_date=payment_row_book.process_date,
debt=abs(debt_to_pay_with_commission_applied),
account_records_id=account_record.id,
account_records_uu_id=str(account_record.uu_id),
build_decision_book_payment_id=payment_row_book.id,
build_decision_book_payment_uu_id=str(payment_row_book.uu_id),
replication_id=99, # Triggers for trigger_account_delay_interest calculation [active trigger]
bank_resp_company_id=1, # Evyos interest rates will be applied when id is given
bank_resp_company_uu_id="CMP",
)
new_row_interest.save()
session.commit()
session.refresh(new_row_interest)
print(f"Applying commission : {payment_row_book.build_parts_id}")
print(f"Account record id : {account_record.id} - {account_record.bank_date.date()}")
print(f"Commission applied : {debt_to_pay_with_commission_applied} | {payment_row_book.debt_to_pay}")
print(f"Build Decision Book id : {payment_row_book.build_decision_book_id} - {payment_row_book.process_date.date()}")
# account_record_remainder_balance = retrieve_remainder_balance_set_if_needed(account_record_id=account_record.id, session=session)
# print(f'Updated remainder balance: {account_record_remainder_balance} | Account record id: {account_record.id}')
# check_current_debt_to_pay_from_database_is_closed(ref_id=new_row.ref_id, session=session)
return None
def get_available_account_records_fund(session, account_record_id):
return session.query(func.abs(AccountRecords.currency_value) - func.abs(AccountRecords.remainder_balance)).filter(
AccountRecords.id == account_record_id,
).scalar()
def set_account_and_payments_with_this_month_debts(session, date_from, list_payment_types):
# Function 1: Read only matching month and year of account records and close debts for each payment type [Commission Applicable if insufficient funds]
print('Function 1: Read only matching month and year of account records and close debts for each payment type [Commission Applicable if insufficient funds]')
print('---' * 200)
AccountRecords.set_session(session)
BuildDecisionBookPayments.set_session(session)
BuildDecisionBook.set_session(session)
for list_payment_type in list_payment_types:
result_all_account_records = read_all_account_records(session, date_from, list_payment_type)
print('list_payment_type', list_payment_type.id, '---' * 50)
for result_all_account_record in result_all_account_records:
AccountRecords.set_session(session)
BuildDecisionBookPayments.set_session(session)
selected_bank_date = result_all_account_record.bank_date
selected_bank_date_month = selected_bank_date.month
selected_bank_date_year = selected_bank_date.year
avaliable_fund = get_available_account_records_fund(session, result_all_account_record.id)
# print(f'iterating account records id : ', result_all_account_record.id)
# print(f'iterating account records bank_date : ', result_all_account_record.bank_date.date())
# print(f'iterating account records currency_value : ', result_all_account_record.currency_value)
# print(f'iterating account records remainder_balance : ', result_all_account_record.remainder_balance)
# print(f'iterating account records process comment : ', result_all_account_record.process_comment)
# print(f'iterating account records build_parts_id : ', result_all_account_record.build_parts_id)
# print(f'iterating account records decision_book_id : ', result_all_account_record.build_decision_book_id)
# print(f'iterating account records avaliable_fund : {avaliable_fund:,.2f}')
get_payments_dict = dict(
session=session, date_from=date_from, list_payment_type=list_payment_type, bank_date=selected_bank_date,
build_decision_book_id=result_all_account_record.build_decision_book_id, build_parts_id=result_all_account_record.build_parts_id
)
debts_for_this_month = calculate_debts_for_this_month(**get_payments_dict) or 0
print_variable_of_debt = f"{debts_for_this_month:,.2f}" if debts_for_this_month else "No debts found"
# print(f'{selected_bank_date_year}-{selected_bank_date_month:02d}: {print_variable_of_debt}')
if debts_for_this_month > 0 and avaliable_fund > 0:
this_month_debts = get_rows_of_debt_for_this_month(**get_payments_dict)
for this_month_debt in this_month_debts:
if this_month_debt.debt_to_pay <= avaliable_fund:
# print(f"debt process date : {this_month_debt.process_date.date()}")
# print(f"debt amount : {this_month_debt.debt_to_pay:,.2f}")
# print(f"money paid : {this_month_debt.debt_to_pay:,.2f}")
close_payment_book(
payment_row_book=this_month_debt, account_record=result_all_account_record, value=this_month_debt.debt_to_pay, session=session, is_commission_applicable=False
)
avaliable_fund = get_available_account_records_fund(session, result_all_account_record.id)
# print(f"Remaind Balance : {avaliable_fund:,.2f}")
if avaliable_fund <= 0:
break
# else:
# close_payment_book(
# payment_row_book=this_month_debt, account_record=result_all_account_record, value=avaliable_fund, session=session, is_commission_applicable=True
# )
# print(f"Insufficient fund for debt :( : {this_month_debt.debt_to_pay:,.2f}")
# print(f"Fund available :( : {avaliable_fund:,.2f}")
else:
pass
# print(f"No debts found for or fund found for {selected_bank_date_year}-{selected_bank_date_month:02d} debt: {debts_for_this_month:,.2f} fund: {avaliable_fund:,.2f}")
# Function 1: Read only matching month and year of account records and close debts for each payment type [Commission Applicable if insufficient funds]
def set_account_and_payments_with_previous_month_debts(session, date_from, list_payment_types):
# Function 2: Read only bank date < decision book payment process date and close debts for each payment type [Commission Applicable if insufficient funds]
print('Function 2: Read only bank date < decision book payment process date and close debts for each payment type [Commission Applicable if insufficient funds]')
print('---' * 200)
for list_payment_type in list_payment_types:
result_all_account_records = read_all_account_records(session, date_from, list_payment_type)
for result_all_account_record in result_all_account_records:
AccountRecords.set_session(session)
BuildDecisionBookPayments.set_session(session)
selected_bank_date = result_all_account_record.bank_date
selected_bank_date_month = selected_bank_date.month
selected_bank_date_year = selected_bank_date.year
avaliable_fund = get_available_account_records_fund(session, result_all_account_record.id)
print(f'iterating account records id : ', result_all_account_record.id)
print(f'iterating account records bank_date : ', result_all_account_record.bank_date.date())
print(f'iterating account records currency_value : ', result_all_account_record.currency_value)
print(f'iterating account records remainder_balance : ', result_all_account_record.remainder_balance)
print(f'iterating account records process comment : ', result_all_account_record.process_comment)
print(f'iterating account records build_parts_id : ', result_all_account_record.build_parts_id)
print(f'iterating account records decision_book_id : ', result_all_account_record.build_decision_book_id)
print(f'iterating account records payment type : ', list_payment_type.value, 'id: ', list_payment_type.id)
print(f'iterating account records avaliable_fund : {avaliable_fund:,.2f}')
get_payments_dict = dict(
session=session, date_from=date_from, list_payment_type=list_payment_type, bank_date=selected_bank_date,
build_decision_book_id=result_all_account_record.build_decision_book_id, build_parts_id=result_all_account_record.build_parts_id
)
debts_for_this_month = calculate_debts_for_previous_month(**get_payments_dict) or 0
print_variable_of_debt = f"{debts_for_this_month:,.2f}" if debts_for_this_month else "No debts found"
print(f'{selected_bank_date_year}-{selected_bank_date_month:02d}: {print_variable_of_debt}')
if debts_for_this_month > 0 and avaliable_fund > 0:
this_month_debts = get_rows_of_debt_for_previous_month(**get_payments_dict)
for this_month_debt in this_month_debts:
if this_month_debt.debt_to_pay <= avaliable_fund:
print(f"debt process date : {this_month_debt.process_date.date()}")
print(f"debt amount : {this_month_debt.debt_to_pay:,.2f}")
print(f"money paid : {this_month_debt.debt_to_pay:,.2f}")
print(f"Payment id : {this_month_debt.id}")
close_payment_book(
payment_row_book=this_month_debt,
account_record=result_all_account_record,
value=this_month_debt.debt_to_pay,
session=session,
is_commission_applicable=True
)
avaliable_fund = get_available_account_records_fund(session, result_all_account_record.id)
print(f"Remaind Balance : {avaliable_fund:,.2f}")
if avaliable_fund <= 0:
break
# else:
# # close_payment_book(
# # payment_row_book=this_month_debt,
# # account_record=result_all_account_record,
# # value=avaliable_fund,
# # session=session,
# # is_commission_applicable=True
# # )
# print(f"Insufficient fund for debt : {this_month_debt.debt_to_pay:,.2f}")
# print(f"Debt process date : {this_month_debt.process_date.date()}")
# print(f"Debt id : {this_month_debt.id}")
# print(f"Fund available : {avaliable_fund:,.2f}")
# print(f"Payment id : {this_month_debt.id}")
else:
print(f"No debts found for or fund found for {selected_bank_date_year}-{selected_bank_date_month:02d} debt: {debts_for_this_month:,.2f} fund: {avaliable_fund:,.2f}")
def set_account_and_payments_with_previous_month_debts_without_payment_type(session, date_from):
# Function 3: Read only bank date < decision book payment process date and close debts for without payment type [Commission Applicable if insufficient funds]
print('Function 3: Read only bank date < decision book payment process date and close debts for without payment type [Commission Applicable if insufficient funds]')
print('---' * 200)
result_all_account_records = read_all_account_records(session, date_from)
for result_all_account_record in result_all_account_records:
AccountRecords.set_session(session)
BuildDecisionBookPayments.set_session(session)
selected_bank_date = result_all_account_record.bank_date
selected_bank_date_month = selected_bank_date.month
selected_bank_date_year = selected_bank_date.year
avaliable_fund = get_available_account_records_fund(session, result_all_account_record.id)
print(f'iterating account records id : ', result_all_account_record.id)
print(f'iterating account records bank_date : ', result_all_account_record.bank_date.date())
print(f'iterating account records currency_value : ', result_all_account_record.currency_value)
print(f'iterating account records remainder_balance : ', result_all_account_record.remainder_balance)
print(f'iterating account records process comment : ', result_all_account_record.process_comment)
print(f'iterating account records build_parts_id : ', result_all_account_record.build_parts_id)
print(f'iterating account records decision_book_id : ', result_all_account_record.build_decision_book_id)
print(f'iterating account records payment type : ', result_all_account_record.payment_result_type)
print(f'iterating account records avaliable_fund : {avaliable_fund:,.2f}')
get_payments_dict = dict(
session=session, date_from=date_from, bank_date=selected_bank_date,
build_decision_book_id=result_all_account_record.build_decision_book_id, build_parts_id=result_all_account_record.build_parts_id
)
debts_for_this_month = calculate_debts_for_previous_month_without_payment_type(**get_payments_dict) or 0
print_variable_of_debt = f"{debts_for_this_month:,.2f}" if debts_for_this_month else "No debts found"
print(f'{selected_bank_date_year}-{selected_bank_date_month:02d}: {print_variable_of_debt}')
if debts_for_this_month > 0 and avaliable_fund > 0:
this_month_debts = get_rows_of_debt_for_previous_month_without_payment_type(**get_payments_dict)
for this_month_debt in this_month_debts:
if this_month_debt.debt_to_pay <= avaliable_fund:
print(f"debt process date : {this_month_debt.process_date.date()}")
print(f"debt amount : {this_month_debt.debt_to_pay:,.2f}")
print(f"money paid : {this_month_debt.debt_to_pay:,.2f}")
print(f"Payment id : {this_month_debt.id}")
print(f"Payment type : {this_month_debt.payment_types_id}")
close_payment_book(
payment_row_book=this_month_debt,
account_record=result_all_account_record,
value=this_month_debt.debt_to_pay,
session=session,
is_commission_applicable=True
)
avaliable_fund = get_available_account_records_fund(session, result_all_account_record.id)
print(f"Remaind Balance : {avaliable_fund:,.2f}")
if avaliable_fund <= 0:
break
# else:
# close_payment_book(
# payment_row_book=this_month_debt,
# account_record=result_all_account_record,
# value=avaliable_fund,
# session=session,
# is_commission_applicable=True
# )
# print(f"Insufficient fund for debt : {this_month_debt.debt_to_pay:,.2f}")
# print(f"Debt process date : {this_month_debt.process_date.date()}")
# print(f"Debt id : {this_month_debt.id}")
# print(f"Fund available : {avaliable_fund:,.2f}")
# print(f"Payment id : {this_month_debt.id}")
else:
print(f"No debts found for or fund found for {selected_bank_date_year}-{selected_bank_date_month:02d} debt: {debts_for_this_month:,.2f} fund: {avaliable_fund:,.2f}")
if __name__ == "__main__":
# import sys
# Default values
# id_given = 1
count_row = 0
session_factory = get_session_factory()
session = session_factory()
list_payment_types = get_enums_from_database()
date_from = '2023-06-30'
AccountRecords.set_session(session)
BuildDecisionBookPayments.set_session(session)
BuildDecisionBook.set_session(session)
set_account_and_payments_with_this_month_debts(session, date_from, list_payment_types)
session.commit()
session.flush()
set_account_and_payments_with_previous_month_debts(session, date_from, list_payment_types)
session.commit()
session.flush()
set_account_and_payments_with_previous_month_debts_without_payment_type(session, date_from)
session.commit()
session.flush()
session.close()

View File

@ -189,50 +189,59 @@ services:
- "8003:8003"
# restart: unless-stopped python3 app_accounts.py
# finder_build_from_iban_service:
# container_name: finder_build_from_iban_service
# env_file:
# - api_env.env
# build:
# context: .
# dockerfile: ServicesBank/Finder/BuildFromIban/Dockerfile
# networks:
# - wag-services
# logging:
# driver: "json-file"
# options:
# max-size: "10m"
# max-file: "3"
finder_build_from_iban_service:
container_name: finder_build_from_iban_service
env_file:
- api_env.env
build:
context: .
dockerfile: ServicesBank/Finder/BuildFromIban/Dockerfile
networks:
- wag-services
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
# finder_build_living_space_service:
# container_name: finder_build_living_space_service
# env_file:
# - api_env.env
# build:
# context: .
# dockerfile: ServicesBank/Finder/BuildLivingSpace/Dockerfile
# networks:
# - wag-services
# logging:
# driver: "json-file"
# options:
# max-size: "10m"
# max-file: "3"
finder_build_living_space_service:
container_name: finder_build_living_space_service
env_file:
- api_env.env
build:
context: .
dockerfile: ServicesBank/Finder/BuildLivingSpace/Dockerfile
networks:
- wag-services
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
# finder_decision_book_service:
# container_name: finder_decision_book_service
# env_file:
# - api_env.env
# build:
# context: .
# dockerfile: ServicesBank/Finder/DecisionBook/Dockerfile
# networks:
# - wag-services
# logging:
# driver: "json-file"
# options:
# max-size: "10m"
# max-file: "3"
finder_decision_book_service:
container_name: finder_decision_book_service
env_file:
- api_env.env
build:
context: .
dockerfile: ServicesBank/Finder/DecisionBook/Dockerfile
networks:
- wag-services
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
zemberek-api:
build:
context: .
dockerfile: ServicesBank/Zemberek/Dockerfile
container_name: zemberek-api
ports:
- "8111:8111"
restart: unless-stopped
finder_payment_service:
container_name: finder_payment_service
@ -345,7 +354,7 @@ services:
context: .
dockerfile: ServicesApi/Builds/Initial/Dockerfile
environment:
- SET_ALEMBIC=1
- SET_ALEMBIC=0
networks:
- wag-services
env_file: