(20260223) Manual attendance script is ready.
This commit is contained in:
@@ -0,0 +1,253 @@
|
||||
"""
|
||||
|
||||
AUTHOR:
|
||||
|
||||
Khushal P Soonderji
|
||||
|
||||
DATE:
|
||||
|
||||
CREATED: Mon, 23rd Feb, 2026
|
||||
UPDATED: Mon, 23rd Feb, 2026
|
||||
|
||||
OBJECTIVE:
|
||||
|
||||
To manually sync attendance for a specific time period.
|
||||
|
||||
REFERENCES:
|
||||
|
||||
N/A
|
||||
|
||||
DOWNLOADS:
|
||||
|
||||
N/A
|
||||
|
||||
"""
|
||||
|
||||
|
||||
# *****************************************************************************************************************
|
||||
# ***** ****
|
||||
# *** IMPORT ***
|
||||
# ***** ****
|
||||
# *****************************************************************************************************************
|
||||
|
||||
|
||||
# To make sibling directories accessible for imports:
|
||||
import sys
|
||||
sys.path.append(".")
|
||||
sys.path.append("..")
|
||||
|
||||
# For system-level activities:
|
||||
import os
|
||||
import copy
|
||||
|
||||
# To work with date and time:
|
||||
import time
|
||||
import datetime
|
||||
|
||||
# To work with tabulate data:
|
||||
import pandas as pd
|
||||
|
||||
# Cosec-related:
|
||||
from cosec_web.cosec_web import CosecWeb
|
||||
|
||||
# TCAOFF-related:
|
||||
from tcaoff.async_tcaoff import AsyncTheCAOffice
|
||||
|
||||
# My utils:
|
||||
from utils_v2.system import files
|
||||
from utils_v2.string import json
|
||||
from utils_v2.string import regex
|
||||
from utils_v2.date_time import date_time
|
||||
|
||||
# To work with datatypes:
|
||||
from typing import List, Dict, Any
|
||||
from collections import defaultdict
|
||||
|
||||
# To run a cron-like scheduler:
|
||||
from apscheduler.schedulers.asyncio import AsyncIOScheduler
|
||||
|
||||
# For async activities:
|
||||
import asyncio
|
||||
|
||||
# For debugging:
|
||||
from icecream import IceCreamDebugger
|
||||
|
||||
# Common and Shared:
|
||||
from scripts import common
|
||||
|
||||
|
||||
# *****************************************************************************************************************
|
||||
# ***** ****
|
||||
# *** MACROS / ONE-TIME INIT ***
|
||||
# ***** ****
|
||||
# *****************************************************************************************************************
|
||||
|
||||
|
||||
# Debugging:
|
||||
printer = IceCreamDebugger(prefix = "Manual | ", includeContext = True)
|
||||
err_printer = IceCreamDebugger(prefix = "[ERR] Manual | ", includeContext = True)
|
||||
|
||||
|
||||
# *****************************************************************************************************************
|
||||
# ***** ****
|
||||
# *** VARIABLES ***
|
||||
# ***** ****
|
||||
# *****************************************************************************************************************
|
||||
|
||||
|
||||
# --- Nothing Yet
|
||||
|
||||
|
||||
# *****************************************************************************************************************
|
||||
# ***** ****
|
||||
# *** CLASSES ***
|
||||
# ***** ****
|
||||
# *****************************************************************************************************************
|
||||
|
||||
|
||||
# --- Nothing Yet
|
||||
|
||||
|
||||
# *****************************************************************************************************************
|
||||
# ***** ****
|
||||
# *** FUNCTIONS ***
|
||||
# ***** ****
|
||||
# *****************************************************************************************************************
|
||||
|
||||
|
||||
async def manual_attendance(
|
||||
cosec_creds: dict,
|
||||
tcaoff_client: AsyncTheCAOffice,
|
||||
from_date: date_time.datetime = None,
|
||||
to_date: date_time.datetime = None,
|
||||
test_mode: bool = False,
|
||||
) -> None:
|
||||
|
||||
printer("MANUAL ATTENDANCE")
|
||||
|
||||
# Try the whole process once:
|
||||
try:
|
||||
|
||||
# Log in to TCAOFF:
|
||||
success = await tcaoff_client.login()
|
||||
if not success: raise RuntimeError("TCAOFF Login Failed!")
|
||||
|
||||
# Try the part that needs COSEC:
|
||||
try:
|
||||
|
||||
# Figure out the dates:
|
||||
now = date_time.get_current_ist_date_time()
|
||||
if not from_date: from_date = now - datetime.timedelta(days = 1)
|
||||
if not to_date: to_date = now
|
||||
|
||||
# Set the correct sequence for the dates:
|
||||
if from_date > to_date: from_date, to_date = to_date, from_date
|
||||
|
||||
# Get the previous day's In/Out Summary and then wait
|
||||
# for the driver's resources to get freed:
|
||||
success = common.get_in_out_summary(
|
||||
cosec_creds = cosec_creds,
|
||||
from_dt = from_date,
|
||||
to_dt = to_date,
|
||||
cache_file = common.MANUAL_SUMMARY_CACHE_FILE,
|
||||
test_mode = test_mode
|
||||
)
|
||||
|
||||
# Sync data between Cosec and TCAOFF:
|
||||
if success:
|
||||
printer("IN/OUT SUMMARY: Sync'ing with TCAOFF")
|
||||
await common.sync_attendance_to_tcaoff(
|
||||
tcaoff_client = tcaoff_client,
|
||||
cosec_in_out_summary = json.from_file(common.MANUAL_SUMMARY_CACHE_FILE),
|
||||
chunk_size = 10
|
||||
)
|
||||
|
||||
# If something goes wrong in the COSEC step:
|
||||
except Exception as exception:
|
||||
err_printer(exception)
|
||||
if test_mode: raise
|
||||
|
||||
# Log out of TCAOFF:
|
||||
success = await tcaoff_client.logout()
|
||||
if not success: raise RuntimeError("TCAOFF Logout Failed!")
|
||||
|
||||
# If something goes wrong:
|
||||
except Exception as exception:
|
||||
err_printer(exception)
|
||||
await tcaoff_client.logout()
|
||||
if test_mode: raise
|
||||
|
||||
|
||||
# *****************************************************************************************************************
|
||||
# ***** ****
|
||||
# *** MAIN PROGRAM ***
|
||||
# ***** ****
|
||||
# *****************************************************************************************************************
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
# Parse args:
|
||||
import argparse
|
||||
ap = argparse.ArgumentParser()
|
||||
ap.add_argument(
|
||||
"--test",
|
||||
action = "store_true",
|
||||
default = False,
|
||||
)
|
||||
ap.add_argument(
|
||||
"--verbose",
|
||||
action = "store_true",
|
||||
default = False,
|
||||
)
|
||||
ap.add_argument(
|
||||
"--from-date",
|
||||
help = "The date from which you want to sync attendance.",
|
||||
default = date_time.get_current_ist_date_time()
|
||||
)
|
||||
ap.add_argument(
|
||||
"--to-date",
|
||||
help = "The date till when you want to sync attendance.",
|
||||
default = date_time.get_current_ist_date_time()
|
||||
)
|
||||
args = ap.parse_args()
|
||||
|
||||
# Explicitly mention the expected file paths for other devs to maintain:
|
||||
print("PROJ. DIR. :", common.PROJ_DIR)
|
||||
print("COSEC CREDS :", common.COSEC_CREDS_FILE)
|
||||
print("TCAOFF CREDS:", common.TCAOFF_CREDS_FILE)
|
||||
|
||||
# Read required credentials:
|
||||
cosec_creds = json.from_file(common.COSEC_CREDS_FILE)
|
||||
tcaoff_creds = json.from_file(common.TCAOFF_CREDS_FILE)
|
||||
|
||||
# Date-handling:
|
||||
args.from_date = date_time.parse_date_time(args.from_date, timezone = date_time.TIMEZONE_IST)
|
||||
args.to_date = date_time.parse_date_time(args.to_date, timezone = date_time.TIMEZONE_IST)
|
||||
if args.from_date > args.to_date: args.from_date, args.to_date = args.to_date, args.from_date
|
||||
print("From Date:", args.from_date)
|
||||
print(" To Date:", args.to_date)
|
||||
# dates_list = [args.from_date]
|
||||
# while args.from_date < args.to_date:
|
||||
# args.from_date = args.from_date + datetime.timedelta(days = 1)
|
||||
# dates_list.append(args.from_date)
|
||||
# print(f"DATES ({len(dates_list)}):", dates_list)
|
||||
|
||||
# Create the clients:
|
||||
tcaoff_client = AsyncTheCAOffice(
|
||||
username = tcaoff_creds["creds"]["username"],
|
||||
password = tcaoff_creds["creds"]["password"],
|
||||
debug = True,
|
||||
debug_only_errors = False if args.verbose else True,
|
||||
)
|
||||
|
||||
# Schedule the activities:
|
||||
asyncio.run(
|
||||
manual_attendance(
|
||||
cosec_creds = cosec_creds,
|
||||
tcaoff_client = tcaoff_client,
|
||||
from_date = args.from_date,
|
||||
to_date = args.to_date,
|
||||
test_mode = args.test,
|
||||
)
|
||||
)
|
||||
Reference in New Issue
Block a user