(20260216) Attendance mark is now truly async.
This commit is contained in:
@@ -461,7 +461,7 @@ class AsyncTheCAOffice:
|
|||||||
# applicant_notes = json.to_string(applicant_notes, no_space = True)
|
# applicant_notes = json.to_string(applicant_notes, no_space = True)
|
||||||
|
|
||||||
# Make the API call:
|
# Make the API call:
|
||||||
response = requests.post(
|
response = await self._http_client.post(
|
||||||
url = self.TEAM_ADD_URL,
|
url = self.TEAM_ADD_URL,
|
||||||
headers = {"X-Session-Token": self.__session_token},
|
headers = {"X-Session-Token": self.__session_token},
|
||||||
json = {
|
json = {
|
||||||
@@ -526,6 +526,8 @@ class AsyncTheCAOffice:
|
|||||||
:return: True if the attendance was marked, else False.
|
:return: True if the attendance was marked, else False.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
start_time = time.time()
|
||||||
|
|
||||||
# Prepare the payload:
|
# Prepare the payload:
|
||||||
json_payload = {
|
json_payload = {
|
||||||
"date": (
|
"date": (
|
||||||
@@ -542,7 +544,7 @@ class AsyncTheCAOffice:
|
|||||||
json_payload["jsonNotes"] = json_notes
|
json_payload["jsonNotes"] = json_notes
|
||||||
|
|
||||||
# Make the API call:
|
# Make the API call:
|
||||||
response = requests.post(
|
response = await self._http_client.post(
|
||||||
url = self.ATTENDANCE_MARK_URL,
|
url = self.ATTENDANCE_MARK_URL,
|
||||||
headers = {"X-Session-Token": self.__session_token},
|
headers = {"X-Session-Token": self.__session_token},
|
||||||
json = json_payload
|
json = json_payload
|
||||||
@@ -564,6 +566,7 @@ class AsyncTheCAOffice:
|
|||||||
"Attendance marked.",
|
"Attendance marked.",
|
||||||
user_id,
|
user_id,
|
||||||
)
|
)
|
||||||
|
print("ONE TIME TAKEN:", time.time() - start_time)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
# If the call failed:
|
# If the call failed:
|
||||||
@@ -575,6 +578,7 @@ class AsyncTheCAOffice:
|
|||||||
user_id,
|
user_id,
|
||||||
response_json
|
response_json
|
||||||
)
|
)
|
||||||
|
print("ONE TIME TAKEN:", time.time() - start_time)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+14
-2
@@ -164,6 +164,7 @@ def get_muster_roll(
|
|||||||
|
|
||||||
# Start by assuming failure:
|
# Start by assuming failure:
|
||||||
success = False
|
success = False
|
||||||
|
report_path = None
|
||||||
|
|
||||||
# If test mode:
|
# If test mode:
|
||||||
if test_mode:
|
if test_mode:
|
||||||
@@ -232,7 +233,7 @@ def get_muster_roll(
|
|||||||
# Sort by hierarchy (BFS):
|
# Sort by hierarchy (BFS):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
print(f"MUSTER ROLL ({len(report_data)}):", json.to_string(report_data))
|
# print(f"MUSTER ROLL ({len(report_data)}):", json.to_string(report_data))
|
||||||
|
|
||||||
# Save the data to a JSON file:
|
# Save the data to a JSON file:
|
||||||
json.to_file(
|
json.to_file(
|
||||||
@@ -428,6 +429,7 @@ def get_in_out_summary(
|
|||||||
|
|
||||||
# Start by assuming failure:
|
# Start by assuming failure:
|
||||||
success = False
|
success = False
|
||||||
|
report_path = None
|
||||||
|
|
||||||
# If test mode:
|
# If test mode:
|
||||||
if test_mode:
|
if test_mode:
|
||||||
@@ -546,16 +548,19 @@ def compute_work_done(
|
|||||||
punch_dt = date_time.parse_date_time(row["Punch Time"], timezone = date_time.TIMEZONE_IST)
|
punch_dt = date_time.parse_date_time(row["Punch Time"], timezone = date_time.TIMEZONE_IST)
|
||||||
punch_date = punch_dt.strftime("%Y-%m-%d")
|
punch_date = punch_dt.strftime("%Y-%m-%d")
|
||||||
punch_ts = punch_dt.timestamp()
|
punch_ts = punch_dt.timestamp()
|
||||||
|
punch_loc = row[" Device/Source Detail"]
|
||||||
|
|
||||||
# Handle the first in time:
|
# Handle the first in time:
|
||||||
if row["I/O Type"] == "In":
|
if row["I/O Type"] == "In":
|
||||||
if work_reports[user_id][punch_date].get("first_in") is None:
|
if work_reports[user_id][punch_date].get("first_in") is None:
|
||||||
work_reports[user_id][punch_date]["first_in"] = punch_ts
|
work_reports[user_id][punch_date]["first_in"] = punch_ts
|
||||||
|
work_reports[user_id][punch_date]["first_in_loc"] = punch_loc
|
||||||
|
|
||||||
# Handle the last out time:
|
# Handle the last out time:
|
||||||
if row["I/O Type"] == "Out":
|
if row["I/O Type"] == "Out":
|
||||||
if work_reports[user_id][punch_date].get("first_in") is not None:
|
if work_reports[user_id][punch_date].get("first_in") is not None:
|
||||||
work_reports[user_id][punch_date]["last_out"] = punch_ts
|
work_reports[user_id][punch_date]["last_out"] = punch_ts
|
||||||
|
work_reports[user_id][punch_date]["last_out_loc"] = punch_loc
|
||||||
|
|
||||||
# Now use the first_in and last out times of each record to figure out the amount of work done:
|
# Now use the first_in and last out times of each record to figure out the amount of work done:
|
||||||
for user_id, user_reports in work_reports.items():
|
for user_id, user_reports in work_reports.items():
|
||||||
@@ -569,7 +574,9 @@ def compute_work_done(
|
|||||||
|
|
||||||
# Extract, clean and compute punch timing:
|
# Extract, clean and compute punch timing:
|
||||||
first_in = punch_info.get("first_in")
|
first_in = punch_info.get("first_in")
|
||||||
|
first_in_loc = punch_info.get("first_in_loc")
|
||||||
last_out = punch_info.get("last_out")
|
last_out = punch_info.get("last_out")
|
||||||
|
last_out_loc = punch_info.get("last_out_loc")
|
||||||
|
|
||||||
# When the user has a valid in-time, but no known out time,
|
# When the user has a valid in-time, but no known out time,
|
||||||
# we assume that he worked a full day:
|
# we assume that he worked a full day:
|
||||||
@@ -606,7 +613,9 @@ def compute_work_done(
|
|||||||
"user_id": user_id,
|
"user_id": user_id,
|
||||||
"work_date": punch_date,
|
"work_date": punch_date,
|
||||||
"first_in": first_in,
|
"first_in": first_in,
|
||||||
|
"first_in_loc": first_in_loc,
|
||||||
"last_out": last_out,
|
"last_out": last_out,
|
||||||
|
"last_out_loc": last_out_loc,
|
||||||
"work_seconds": work_seconds,
|
"work_seconds": work_seconds,
|
||||||
"work_hours": work_hours,
|
"work_hours": work_hours,
|
||||||
"work_ot_seconds": work_ot_seconds,
|
"work_ot_seconds": work_ot_seconds,
|
||||||
@@ -695,7 +704,8 @@ async def sync_attendance_to_tcaoff(
|
|||||||
yield lst[i:i + size]
|
yield lst[i:i + size]
|
||||||
|
|
||||||
count = 0
|
count = 0
|
||||||
for chunk in chunks(tasks[:]):
|
for chunk in chunks(tasks[:30]):
|
||||||
|
start_time = time.time()
|
||||||
count += 1
|
count += 1
|
||||||
printer("Task Chunk:", count)
|
printer("Task Chunk:", count)
|
||||||
_res = await asyncio.gather(*chunk)
|
_res = await asyncio.gather(*chunk)
|
||||||
@@ -704,6 +714,8 @@ async def sync_attendance_to_tcaoff(
|
|||||||
results["success"] += success
|
results["success"] += success
|
||||||
results["failure"] += failure
|
results["failure"] += failure
|
||||||
results["total"] += len(_res)
|
results["total"] += len(_res)
|
||||||
|
print("BATCH TIME TAKEN:", time.time() - start_time)
|
||||||
|
print("\n\n---\n\n")
|
||||||
|
|
||||||
# Done here:
|
# Done here:
|
||||||
printer(results)
|
printer(results)
|
||||||
|
|||||||
+44
-22
@@ -137,7 +137,7 @@ async def yesterday_cron(
|
|||||||
# for the driver's resources to get freed:
|
# for the driver's resources to get freed:
|
||||||
success = common.get_in_out_summary(
|
success = common.get_in_out_summary(
|
||||||
cosec_creds = cosec_creds,
|
cosec_creds = cosec_creds,
|
||||||
from_dt = date_time.get_current_ist_date_time() - datetime.timedelta(days = 7),
|
from_dt = date_time.get_current_ist_date_time() - datetime.timedelta(days = 2),
|
||||||
to_dt = date_time.get_current_ist_date_time(),
|
to_dt = date_time.get_current_ist_date_time(),
|
||||||
cache_file = common.PREV_DAY_IN_OUT_SUMMARY_CACHE_FILE,
|
cache_file = common.PREV_DAY_IN_OUT_SUMMARY_CACHE_FILE,
|
||||||
test_mode = test_mode
|
test_mode = test_mode
|
||||||
@@ -196,34 +196,56 @@ async def today_cron(
|
|||||||
# Try the part that needs COSEC:
|
# Try the part that needs COSEC:
|
||||||
try:
|
try:
|
||||||
|
|
||||||
# Get the Muster Roll and then wait
|
# # MUSTER-ROLL:
|
||||||
|
#
|
||||||
|
# # Get the Muster Roll and then wait
|
||||||
|
# # for the driver's resources to get freed:
|
||||||
|
# success = common.get_muster_roll(
|
||||||
|
# cosec_creds = cosec_creds,
|
||||||
|
# on_date = date_time.get_current_ist_date_time().replace(
|
||||||
|
# hour = 0,
|
||||||
|
# minute = 0,
|
||||||
|
# second = 0
|
||||||
|
# ),
|
||||||
|
# cache_file = common.PREV_DAY_IN_OUT_SUMMARY_CACHE_FILE,
|
||||||
|
# test_mode = test_mode
|
||||||
|
# )
|
||||||
|
#
|
||||||
|
# # Sync data between Cosec and TCAOFF:
|
||||||
|
# if success:
|
||||||
|
# print("MUSTER ROLL: Sync'ing with TCAOFF")
|
||||||
|
# cosec_muster_roll = json.from_file(common.MUSTER_ROLL_CACHE_FILE)
|
||||||
|
# await common.sync_branches_to_tcaoff(
|
||||||
|
# tcaoff_client = tcaoff_client,
|
||||||
|
# cosec_muster_roll = cosec_muster_roll,
|
||||||
|
# )
|
||||||
|
# await common.sync_departments_to_tcaoff(
|
||||||
|
# tcaoff_client = tcaoff_client,
|
||||||
|
# cosec_muster_roll = cosec_muster_roll,
|
||||||
|
# )
|
||||||
|
# await common.sync_teams_to_tcaoff(
|
||||||
|
# tcaoff_client = tcaoff_client,
|
||||||
|
# cosec_muster_roll = cosec_muster_roll,
|
||||||
|
# )
|
||||||
|
|
||||||
|
# IN-OUT SUMMARY:
|
||||||
|
|
||||||
|
# Get the previous day's In/Out Summary and then wait
|
||||||
# for the driver's resources to get freed:
|
# for the driver's resources to get freed:
|
||||||
success = common.get_muster_roll(
|
success = common.get_in_out_summary(
|
||||||
cosec_creds = cosec_creds,
|
cosec_creds = cosec_creds,
|
||||||
on_date = date_time.get_current_ist_date_time().replace(
|
from_dt = date_time.get_current_ist_date_time().replace(hour = 0, minute = 0, second = 0, microsecond = 0),
|
||||||
hour = 0,
|
to_dt = date_time.get_current_ist_date_time(),
|
||||||
minute = 0,
|
cache_file = common.IN_OUT_SUMMARY_CACHE_FILE,
|
||||||
second = 0
|
|
||||||
),
|
|
||||||
cache_file = common.PREV_DAY_IN_OUT_SUMMARY_CACHE_FILE,
|
|
||||||
test_mode = test_mode
|
test_mode = test_mode
|
||||||
)
|
)
|
||||||
|
|
||||||
# Sync data between Cosec and TCAOFF:
|
# Sync data between Cosec and TCAOFF:
|
||||||
if success:
|
if success:
|
||||||
print("MUSTER ROLL: Sync'ing with TCAOFF")
|
printer("IN/OUT SUMMARY: Sync'ing with TCAOFF")
|
||||||
cosec_muster_roll = json.from_file(common.MUSTER_ROLL_CACHE_FILE)
|
await common.sync_attendance_to_tcaoff(
|
||||||
await common.sync_branches_to_tcaoff(
|
|
||||||
tcaoff_client = tcaoff_client,
|
tcaoff_client = tcaoff_client,
|
||||||
cosec_muster_roll = cosec_muster_roll,
|
cosec_in_out_summary = json.from_file(common.IN_OUT_SUMMARY_CACHE_FILE),
|
||||||
)
|
|
||||||
await common.sync_departments_to_tcaoff(
|
|
||||||
tcaoff_client = tcaoff_client,
|
|
||||||
cosec_muster_roll = cosec_muster_roll,
|
|
||||||
)
|
|
||||||
await common.sync_teams_to_tcaoff(
|
|
||||||
tcaoff_client = tcaoff_client,
|
|
||||||
cosec_muster_roll = cosec_muster_roll,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# If something goes wrong in the COSEC step:
|
# If something goes wrong in the COSEC step:
|
||||||
@@ -262,7 +284,7 @@ async def set_scheduler(
|
|||||||
# await yesterday_cron(
|
# await yesterday_cron(
|
||||||
# cosec_creds = copy.deepcopy(cosec_creds),
|
# cosec_creds = copy.deepcopy(cosec_creds),
|
||||||
# tcaoff_client = tcaoff_client,
|
# tcaoff_client = tcaoff_client,
|
||||||
# test_mode = test_mode
|
# # test_mode = test_mode
|
||||||
# )
|
# )
|
||||||
await today_cron(
|
await today_cron(
|
||||||
cosec_creds = copy.deepcopy(cosec_creds),
|
cosec_creds = copy.deepcopy(cosec_creds),
|
||||||
|
|||||||
Reference in New Issue
Block a user