(20260309) Added new 'mode' for formatting the muster roll'.
This commit is contained in:
@@ -187,7 +187,8 @@ async def muster_roll_report_generate(
|
|||||||
success = False
|
success = False
|
||||||
report_data = None
|
report_data = None
|
||||||
|
|
||||||
# Figure out the paths:
|
# Figure out the paths,
|
||||||
|
# and read the records:
|
||||||
proj_dir = files.get_parent_directory(
|
proj_dir = files.get_parent_directory(
|
||||||
files.get_file_directory(include_filename = False),
|
files.get_file_directory(include_filename = False),
|
||||||
depth = 4
|
depth = 4
|
||||||
@@ -201,6 +202,16 @@ async def muster_roll_report_generate(
|
|||||||
# Note down the status of success or failure:
|
# Note down the status of success or failure:
|
||||||
success = True if report_data else False
|
success = True if report_data else False
|
||||||
|
|
||||||
|
# format the report as required:
|
||||||
|
if success:
|
||||||
|
if inbound_data.mode == "array":
|
||||||
|
pass # ... already an array
|
||||||
|
elif inbound_data.mode == "map":
|
||||||
|
report_data["report"] = {
|
||||||
|
r["UserID"]: {k: v for k,v in r.items if k != "User ID"}
|
||||||
|
for r in report_data["report"]
|
||||||
|
}
|
||||||
|
|
||||||
# ┳┓
|
# ┳┓
|
||||||
# ┣┫┏┓┏┏┓┏┓┏┓┏┏┓
|
# ┣┫┏┓┏┏┓┏┓┏┓┏┏┓
|
||||||
# ┛┗┗ ┛┣┛┗┛┛┗┛┗
|
# ┛┗┗ ┛┣┛┗┛┛┗┛┗
|
||||||
|
|||||||
@@ -84,6 +84,11 @@ class CosecMusterRollReportRequestData(BaseModel):
|
|||||||
frozen = True,
|
frozen = True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
mode: Literal["array", "map"] = Field(
|
||||||
|
description = "The format in which the response is desired.",
|
||||||
|
frozen = True,
|
||||||
|
)
|
||||||
|
|
||||||
# ┏┓ ┏•
|
# ┏┓ ┏•
|
||||||
# ┃ ┏┓┏┓╋┓┏┓
|
# ┃ ┏┓┏┓╋┓┏┓
|
||||||
# ┗┛┗┛┛┗┛┗┗┫
|
# ┗┛┗┛┛┗┛┗┗┫
|
||||||
|
|||||||
Vendored
+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
@@ -0,0 +1,54 @@
|
|||||||
|
from utils_v2.string import json
|
||||||
|
from scripts import common
|
||||||
|
from tcaoff.async_tcaoff import AsyncTheCAOffice
|
||||||
|
import asyncio
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
# 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)
|
||||||
|
|
||||||
|
# Create the clients:
|
||||||
|
tcaoff_client = AsyncTheCAOffice(
|
||||||
|
username = tcaoff_creds["creds"]["username"],
|
||||||
|
password = tcaoff_creds["creds"]["password"],
|
||||||
|
debug = True,
|
||||||
|
debug_only_errors = False,
|
||||||
|
)
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
|
||||||
|
# Ensure login:
|
||||||
|
if not await tcaoff_client.login():
|
||||||
|
return
|
||||||
|
|
||||||
|
# Get the data:
|
||||||
|
raw_records = await tcaoff_client.attendance_register(
|
||||||
|
target_month = datetime.datetime.now(),
|
||||||
|
raise_exception = True
|
||||||
|
)
|
||||||
|
|
||||||
|
# Format the data for preview:
|
||||||
|
formatted_records = []
|
||||||
|
for r in raw_records:
|
||||||
|
cosec_data = json.from_string(r.get("json_notes", "{}")).get("cosec", {})
|
||||||
|
if cosec_data:
|
||||||
|
cosec_data.update({
|
||||||
|
"cosecId": r["pseudonym"],
|
||||||
|
"tcaoffId": r["user_id"],
|
||||||
|
})
|
||||||
|
formatted_records.append(cosec_data)
|
||||||
|
|
||||||
|
# Show the formatted data for debugging:
|
||||||
|
print(f"RECORDS ({len(formatted_records)}):", json.to_string(formatted_records))
|
||||||
|
print(f"Found {len(formatted_records)} record(s).")
|
||||||
|
|
||||||
|
# Log out:
|
||||||
|
await tcaoff_client.logout()
|
||||||
|
|
||||||
|
asyncio.run(main())
|
||||||
+7
-5
@@ -620,14 +620,16 @@ def compute_work_done(
|
|||||||
work_ot_seconds = max(0.0, work_seconds - min_work_seconds)
|
work_ot_seconds = max(0.0, work_seconds - min_work_seconds)
|
||||||
|
|
||||||
# Finally, compute the work status.
|
# Finally, compute the work status.
|
||||||
# 'A' --> Absent
|
# 'A' ----> Absent
|
||||||
# 'H' --> Half Day
|
# 'H' ----> Holiday
|
||||||
# 'P' --> Present (Full Day)
|
# 'HD1' --> Half Day (1st Half)
|
||||||
# 'OT' -> Overtime
|
# 'HD2' --> Half Day (2nd Half)
|
||||||
|
# 'P' ----> Present (Full Day)
|
||||||
|
# 'OT' ---> Overtime
|
||||||
work_hours = work_seconds / (60 * 60)
|
work_hours = work_seconds / (60 * 60)
|
||||||
if work_hours > 10.0: work_status = "OT"
|
if work_hours > 10.0: work_status = "OT"
|
||||||
elif 7.5 < work_hours <= 10.0: work_status = "P"
|
elif 7.5 < work_hours <= 10.0: work_status = "P"
|
||||||
elif 4.5 < work_hours <= 7.5: work_status = "H"
|
elif 4.5 < work_hours <= 7.5: work_status = "HD1"
|
||||||
else: work_status = "A"
|
else: work_status = "A"
|
||||||
|
|
||||||
# Save the data:
|
# Save the data:
|
||||||
|
|||||||
+1
-1
@@ -351,7 +351,7 @@ if __name__ == "__main__":
|
|||||||
import argparse
|
import argparse
|
||||||
ap = argparse.ArgumentParser()
|
ap = argparse.ArgumentParser()
|
||||||
ap.add_argument(
|
ap.add_argument(
|
||||||
"--test",
|
"--test", "--test-mode",
|
||||||
action = "store_true",
|
action = "store_true",
|
||||||
default = False,
|
default = False,
|
||||||
)
|
)
|
||||||
|
|||||||
+13
-7
@@ -604,7 +604,7 @@ class AsyncTheCAOffice:
|
|||||||
async def attendance_mark(
|
async def attendance_mark(
|
||||||
self,
|
self,
|
||||||
user_id: int,
|
user_id: int,
|
||||||
status: Literal["P", "H", "A", "OT"],
|
status: Literal["A", "H", "HD1", "HD2", "P", "OT"],
|
||||||
over_time: int | float,
|
over_time: int | float,
|
||||||
attendance_date: datetime.datetime | None = None,
|
attendance_date: datetime.datetime | None = None,
|
||||||
json_notes: dict = None,
|
json_notes: dict = None,
|
||||||
@@ -615,10 +615,12 @@ class AsyncTheCAOffice:
|
|||||||
Add a new department.
|
Add a new department.
|
||||||
:param user_id: The id of the user whose attendance is being marked.
|
:param user_id: The id of the user whose attendance is being marked.
|
||||||
:param status: The status of the attendance.
|
:param status: The status of the attendance.
|
||||||
1. "P" for present,
|
1. "A" for absent,
|
||||||
2. "H" for half-day,
|
2. "H" for holiday,
|
||||||
3. "A" for absent,
|
3. "HD1" for half-day (1st half),
|
||||||
4. "OT" for over-time.
|
4. "HD2" for half-day (2nd half),
|
||||||
|
5. "P" for present,
|
||||||
|
6. "OT" for over-time.
|
||||||
:param over_time: The amount of over-time work in hours.
|
:param over_time: The amount of over-time work in hours.
|
||||||
:param attendance_date: The date of the attendance. If not given, today's date will be used.
|
:param attendance_date: The date of the attendance. If not given, today's date will be used.
|
||||||
:param json_notes: Optional notes about the attendance.
|
:param json_notes: Optional notes about the attendance.
|
||||||
@@ -683,6 +685,7 @@ class AsyncTheCAOffice:
|
|||||||
async def attendance_register(
|
async def attendance_register(
|
||||||
self,
|
self,
|
||||||
target_month: datetime.datetime,
|
target_month: datetime.datetime,
|
||||||
|
mode: Literal["month", "date"] = "month",
|
||||||
raise_exception: bool = False,
|
raise_exception: bool = False,
|
||||||
) -> List[dict] | None:
|
) -> List[dict] | None:
|
||||||
|
|
||||||
@@ -690,6 +693,7 @@ class AsyncTheCAOffice:
|
|||||||
To get the whole attendance register for a month for all the employees of an entity.
|
To get the whole attendance register for a month for all the employees of an entity.
|
||||||
:param target_month: The datetime which indicates the year and month in which the attendance needs to be
|
:param target_month: The datetime which indicates the year and month in which the attendance needs to be
|
||||||
checked.
|
checked.
|
||||||
|
:param mode: The mode of the attendance filtering.
|
||||||
:param raise_exception: Whether to raise any exceptions, or to suppress them.
|
:param raise_exception: Whether to raise any exceptions, or to suppress them.
|
||||||
:return: The attendance register records if successful, else None.
|
:return: The attendance register records if successful, else None.
|
||||||
"""
|
"""
|
||||||
@@ -700,11 +704,13 @@ class AsyncTheCAOffice:
|
|||||||
try:
|
try:
|
||||||
|
|
||||||
# Make the API call:
|
# Make the API call:
|
||||||
json_payload = {"month": target_month.strftime("%Y-%m-%d")}
|
|
||||||
response = await self._http_client.post(
|
response = await self._http_client.post(
|
||||||
url = self.ATTENDANCE_REGISTER_URL,
|
url = self.ATTENDANCE_REGISTER_URL,
|
||||||
headers = {"X-Session-Token": self.__session_token},
|
headers = {"X-Session-Token": self.__session_token},
|
||||||
json = json_payload,
|
json = {
|
||||||
|
"month": target_month.strftime("%Y-%m-%d"),
|
||||||
|
"mode": mode
|
||||||
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
# If the call succeeded:
|
# If the call succeeded:
|
||||||
|
|||||||
Reference in New Issue
Block a user