import sys import arrow if "/service_account_records" not in list(sys.path): sys.path.append("/service_account_records") from decimal import Decimal from pydantic import BaseModel from typing import Optional, Union from sqlalchemy import func, cast, Date from Schemas import AccountRecords, BuildIbans, BuildDecisionBook, Build, BuildLivingSpace, People, OccupantTypes, BuildParts, BuildDecisionBookPayments, ApiEnumDropdown from account_record_parser import parse_comment_with_name, parse_comment_with_name_iban_description # from ServicesApi.Schemas.account.account import AccountRecords # from ServicesApi.Schemas.building.build import BuildIbans, BuildDecisionBook, BuildParts, BuildLivingSpace, Build # from ServicesApi.Schemas.identity.identity import People, OccupantTypes # from ServicesApi.Schemas.others.enums import ApiEnumDropdown # from ServicesApi.Schemas.building.decision_book import BuildDecisionBookPayments # AccountRecords.approved_record = False def account_find_build_from_iban(session): created_ibans = [] AccountRecords.set_session(session) BuildIbans.set_session(session) account_records_ibans = AccountRecords.query.filter(AccountRecords.build_id == None, AccountRecords.approved_record == False).distinct(AccountRecords.iban).all() for account_records_iban in account_records_ibans: found_iban: BuildIbans = BuildIbans.query.filter(BuildIbans.iban == account_records_iban.iban).first() if not found_iban: create_build_ibans = BuildIbans.create(iban=account_records_iban.iban, start_date=str(arrow.now().shift(days=-1))) create_build_ibans.save() created_ibans.append(account_records_iban.iban) else: update_dict = {"build_id": found_iban.build_id, "build_uu_id": str(found_iban.build_uu_id)} session.query(AccountRecords).filter(AccountRecords.iban == account_records_iban.iban).update(update_dict, synchronize_session=False) session.commit() def account_records_find_decision_book(session): AccountRecords.set_session(session) BuildIbans.set_session(session) BuildDecisionBook.set_session(session) created_ibans, iban_build_dict = [], {} account_records_list: list[AccountRecords] = AccountRecords.query.filter(AccountRecords.build_id != None, AccountRecords.build_decision_book_id == None).order_by(AccountRecords.bank_date.desc()).all() for account_record in account_records_list: if found_iban := BuildIbans.query.filter(BuildIbans.iban == account_record.iban).first(): if found_decision_book := BuildDecisionBook.query.filter( BuildDecisionBook.build_id == found_iban.build_id, cast(BuildDecisionBook.expiry_starts, Date) <= cast(account_record.bank_date, Date), cast(BuildDecisionBook.expiry_ends, Date) >= cast(account_record.bank_date, Date), ).first(): account_record.build_decision_book_id = found_decision_book.id account_record.build_decision_book_uu_id = str(found_decision_book.uu_id) account_record.save() def account_get_people_and_living_space_info_via_iban() -> dict: build_living_space_dict = {} AccountRecords.set_session(session) OccupantTypes.set_session(session) BuildParts.set_session(session) BuildLivingSpace.set_session(session) People.set_session(session) account_records_ibans = AccountRecords.query.filter(AccountRecords.build_decision_book_id != None).distinct(AccountRecords.iban).all() flat_resident = OccupantTypes.query.filter_by(occupant_category_type="FL", occupant_code="FL-RES").first() flat_owner = OccupantTypes.query.filter_by(occupant_category_type="FL", occupant_code="FL-OWN").first() flat_tenant = OccupantTypes.query.filter_by(occupant_category_type="FL", occupant_code="FL-TEN").first() flat_represent = OccupantTypes.query.filter_by(occupant_category_type="FL", occupant_code="FL-REP").first() for account_records_iban in account_records_ibans: if account_records_iban.iban not in build_living_space_dict: build_parts = BuildParts.query.filter_by(build_id=account_records_iban.build_id, human_livable=True).all() living_spaces = BuildLivingSpace.query.filter( BuildLivingSpace.build_parts_id.in_([build_parts.id for build_parts in build_parts]), BuildLivingSpace.occupant_type_id.in_([flat_resident.id, flat_owner.id, flat_tenant.id, flat_represent.id]), ).all() living_spaces_people = [living_space.person_id for living_space in living_spaces if living_space.person_id] people_list = People.query.filter(People.id.in_(living_spaces_people)).all() people_list_dict = [] for people in people_list: people_list_dict.append({"id": people.id, "uu_id": str(people.uu_id), "firstname": people.firstname, "surname": people.surname, "middle_name": people.middle_name}) living_spaces_dict = [] for living_space in living_spaces: living_spaces_dict.append({"id": living_space.id, "uu_id": str(living_space.uu_id), "person_id": living_space.person_id, "person_uu_id": str(living_space.person_uu_id)}) build_parts_dict = [] for build_parts in build_parts: build_parts_dict.append({"id": build_parts.id, "uu_id": str(build_parts.uu_id)}) build_living_space_dict[str(account_records_iban.iban)] = {"people": list(people_list_dict), "living_space": list(living_spaces_dict), "build_parts": list(build_parts_dict)} return build_living_space_dict def account_records_search(): build_living_space_dict = account_get_people_and_living_space_info_via_iban() found_list = [] with AccountRecords.new_session() as session: AccountRecords.set_session(session) account_records_list: list[AccountRecords] = AccountRecords.query.filter(AccountRecords.build_decision_book_id != None).all() for account_record in account_records_list: account_record_dict = account_record.get_dict() similarity_result = parse_comment_with_name(account_record=account_record_dict, living_space_dict=build_living_space_dict) fs, ac = float(similarity_result.get("similarity", 0)), float(account_record_dict.get("similarity", 0)) if fs >= 0.8 and fs >= ac: print("similarity_result positive", similarity_result) found_list.append(similarity_result) account_save_search_result(account_record=account_record_dict, similarity_result=similarity_result) else: similarity_result = parse_comment_with_name_iban_description(account_record=account_record_dict) fs, ac = float(similarity_result.get("similarity", 0)), float(account_record_dict.get("similarity", 0)) if fs >= 0.8 and fs > ac: print("similarity_result negative", similarity_result) found_list.append(similarity_result) account_save_search_result(account_record=account_record_dict, similarity_result=similarity_result) print("Account Records Search : ", len(found_list), "/", len(account_records_list)) return def account_save_search_result(account_record, similarity_result): BuildParts.set_session(session) Build.set_session(session) BuildLivingSpace.set_session(session) found_company = similarity_result.get("company", None) found_customer, part, build = (similarity_result.get("living_space", None), None, None) if found_customer: found_living_space = BuildLivingSpace.query.filter_by(id=int(found_customer.get("id"))).first() part = BuildParts.query.filter_by(id=found_living_space.build_parts_id, human_livable=True).first() if part: build = Build.query.filter_by(id=part.build_id).first() account_record_dict = { "similarity": similarity_result.get("similarity", 0.00), "found_from": similarity_result.get("found_from", None), "company_id": getattr(found_company, "id", None), "company_uu_id": str(getattr(found_company, "uu_id", None)) if getattr(found_company, "uu_id", None) else None, "build_parts_id": getattr(part, "id", None) if getattr(part, "id", None) else None, "build_parts_uu_id": str(getattr(part, "uu_id", None)) if getattr(part, "uu_id", None) else None, "living_space_id": getattr(found_customer, "id", None), "living_space_uu_id": str(getattr(found_customer, "uu_id", None)) if getattr(found_customer, "uu_id", None) else None, } if not account_record.get("build_id") and build: account_record_dict.update({"build_id": getattr(build, "id", None), "build_uu_id": str(getattr(build, "uu_id", None)) if getattr(build, "uu_id", None) else None}) AccountRecords.query.filter_by(uu_id=str(account_record.get("uu_id"))).update(account_record_dict) session.commit() def pay_the_registration(account_record, receive_enum, debit_enum, is_old_record: bool = False): with AccountRecords.new_session() as session: AccountRecords.set_session(session) BuildDecisionBookPayments.set_session(session) current_currency_value = float(Decimal(account_record.currency_value)) - float(Decimal(account_record.remainder_balance)) if not current_currency_value > 0: return current_currency_value process_date = arrow.get(account_record.bank_date) account_bank_date_year, account_bank_date_month = (process_date.date().year, process_date.date().month) payment_arguments_debit = [ BuildDecisionBookPayments.build_parts_id == account_record.build_parts_id, BuildDecisionBookPayments.payment_types_id == debit_enum.id, BuildDecisionBookPayments.account_records_id == None, ] if not is_old_record: payment_arguments_debit.extend([BuildDecisionBookPayments.process_date_y == int(account_bank_date_year), BuildDecisionBookPayments.process_date_m == int(account_bank_date_month)]) payments = BuildDecisionBookPayments.query.filter(*payment_arguments_debit).order_by(BuildDecisionBookPayments.process_date.asc()).all() for payment in payments: if not current_currency_value > 0: return current_currency_value payment_arguments_receive = [ BuildDecisionBookPayments.build_parts_id == account_record.build_parts_id, BuildDecisionBookPayments.payment_plan_time_periods == payment.payment_plan_time_periods, BuildDecisionBookPayments.payment_types_id == receive_enum.id, BuildDecisionBookPayments.build_decision_book_item_id == payment.build_decision_book_item_id, BuildDecisionBookPayments.decision_book_project_id == payment.decision_book_project_id, BuildDecisionBookPayments.process_date == payment.process_date, ] if not is_old_record: payment_arguments_receive.extend([BuildDecisionBookPayments.process_date_y == int(account_bank_date_year), BuildDecisionBookPayments.process_date_m == int(account_bank_date_month)]) payment_received = BuildDecisionBookPayments.query.filter(*payment_arguments_receive).all() sum_of_payment_received = sum([abs(payment.payment_amount) for payment in payment_received]) net_amount = float(abs(Decimal(payment.payment_amount))) - float(abs(Decimal(sum_of_payment_received))) if not net_amount > 0: continue if float(abs(current_currency_value)) < float(abs(net_amount)): net_amount = float(current_currency_value) process_date = arrow.get(payment.process_date) try: found_payment = BuildDecisionBookPayments.query.filter_by( build_parts_id=payment.build_parts_id, payment_plan_time_periods=payment.payment_plan_time_periods, payment_types_id=receive_enum.id, build_decision_book_item_id=payment.build_decision_book_item_id, decision_book_project_id=payment.decision_book_project_id, process_date=str(process_date), ).first() if found_payment: continue created_book_payment = BuildDecisionBookPayments.create( payment_plan_time_periods=payment.payment_plan_time_periods, payment_amount=float(abs(net_amount)), payment_types_id=receive_enum.id, payment_types_uu_id=str(receive_enum.uu_id), process_date=str(process_date), process_date_m=process_date.date().month, process_date_y=process_date.date().year, period_time=f"{process_date.year}-{str(process_date.month).zfill(2)}", build_parts_id=payment.build_parts_id, build_parts_uu_id=str(payment.build_parts_uu_id), account_records_id=account_record.id, account_records_uu_id=str(account_record.uu_id), build_decision_book_item_id=payment.build_decision_book_item_id, build_decision_book_item_uu_id=str(payment.build_decision_book_item_uu_id), decision_book_project_id=payment.decision_book_project_id, decision_book_project_uu_id=str(payment.decision_book_project_uu_id), ) created_book_payment.save_and_confirm() created_payment_amount = float(Decimal(created_book_payment.payment_amount)) remainder_balance = float(Decimal(account_record.remainder_balance)) + float(abs(created_payment_amount)) account_record.update(remainder_balance=remainder_balance) account_record.save() if current_currency_value >= abs(net_amount): current_currency_value -= abs(net_amount) except Exception as e: print("Exception of decision payment ln:300", e) return current_currency_value def send_accounts_to_decision_payment(): with ApiEnumDropdown.new_session() as session: ApiEnumDropdown.set_session(session) AccountRecords.set_session(session) receive_enum = ApiEnumDropdown.query.filter_by(enum_class="DebitTypes", key="DT-R").first() debit_enum = ApiEnumDropdown.query.filter_by(enum_class="DebitTypes", key="DT-D").first() account_records_list: list[AccountRecords] = AccountRecords.query.filter( AccountRecords.remainder_balance < AccountRecords.currency_value, AccountRecords.approved_record == True, AccountRecords.receive_debit == receive_enum.id, ).order_by(AccountRecords.bank_date.desc()).limit(1000).offset(0).all() for account_record in account_records_list: current_currency_value = pay_the_registration(account_record, receive_enum, debit_enum) if current_currency_value > 0: pay_the_registration(account_record, receive_enum, debit_enum, True) if abs(float(Decimal(account_record.remainder_balance))) == abs(float(Decimal(account_record.currency_value))): account_record.update(status_id=97) account_record.save() # # # todo If the payment is more than the amount, then create a new account record with the remaining amount return def account_records_service() -> None: print("Account Records Service is running...") account_find_build_from_iban(session=session) account_records_find_decision_book(session=session) account_records_search(session=session) send_accounts_to_decision_payment(session=session) print("Account Records Service is finished...") if __name__ == "__main__": account_records_service()