(20260219) Updarted APIs to now show last-in time and loc also.
This commit is contained in:
@@ -307,10 +307,22 @@ async def in_out_report_generate(
|
|||||||
"status": r.get("status"),
|
"status": r.get("status"),
|
||||||
"firstIn": cosec_notes.get("firstIn"),
|
"firstIn": cosec_notes.get("firstIn"),
|
||||||
"firstInLoc": cosec_notes.get("firstInLoc"),
|
"firstInLoc": cosec_notes.get("firstInLoc"),
|
||||||
|
"lastIn": cosec_notes.get("lastIn"),
|
||||||
|
"lastInLoc": cosec_notes.get("lastInLoc"),
|
||||||
"lastOut": cosec_notes.get("lastOut"),
|
"lastOut": cosec_notes.get("lastOut"),
|
||||||
"lastOutLoc": cosec_notes.get("lastOutLoc"),
|
"lastOutLoc": cosec_notes.get("lastOutLoc"),
|
||||||
|
"workSeconds": cosec_notes.get("workSeconds"),
|
||||||
|
"workHours": cosec_notes.get("workHours"),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
# Remove unwanted records:
|
||||||
|
from_ts = inbound_data.fromDate.timestamp()
|
||||||
|
to_ts = inbound_data.toDate.timestamp()
|
||||||
|
cumulative_register = [
|
||||||
|
cr for cr in cumulative_register
|
||||||
|
if from_ts <= cr["date"] <= to_ts
|
||||||
|
]
|
||||||
|
|
||||||
# Sort the records:
|
# Sort the records:
|
||||||
cumulative_register = sorted(cumulative_register, key = lambda x: x["date"])
|
cumulative_register = sorted(cumulative_register, key = lambda x: x["date"])
|
||||||
print(f"REGISTER ({len(cumulative_register)}):", json.to_string(cumulative_register[-10:]))
|
print(f"REGISTER ({len(cumulative_register)}):", json.to_string(cumulative_register[-10:]))
|
||||||
|
|||||||
+1
-1
File diff suppressed because one or more lines are too long
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
+18
-5
@@ -569,6 +569,11 @@ def compute_work_done(
|
|||||||
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
|
work_reports[user_id][punch_date]["first_in_loc"] = punch_loc
|
||||||
|
work_reports[user_id][punch_date]["last_in"] = punch_ts
|
||||||
|
work_reports[user_id][punch_date]["last_in_loc"] = punch_loc
|
||||||
|
else:
|
||||||
|
work_reports[user_id][punch_date]["last_in"] = punch_ts
|
||||||
|
work_reports[user_id][punch_date]["last_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":
|
||||||
@@ -589,19 +594,21 @@ 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")
|
first_in_loc = punch_info.get("first_in_loc")
|
||||||
|
last_in = punch_info.get("last_in")
|
||||||
|
last_in_loc = punch_info.get("last_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")
|
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:
|
||||||
if first_in is not None and not last_out:
|
if first_in is not None and last_out is None:
|
||||||
last_out = first_in + min_work_seconds
|
last_out = first_in + min_work_seconds
|
||||||
work_seconds = last_out - first_in
|
work_seconds = min_work_seconds
|
||||||
work_ot_seconds = 0.0
|
work_ot_seconds = 0.0
|
||||||
|
|
||||||
# When the user has neither an in-time, nor an out-time,
|
# When the user has neither an in-time, nor an out-time,
|
||||||
# we assume that he was absent the whole day:
|
# we assume that he was absent the whole day:
|
||||||
elif not first_in and not last_out:
|
elif first_in is None and last_out is None:
|
||||||
work_seconds = 0.0
|
work_seconds = 0.0
|
||||||
work_ot_seconds = 0.0
|
work_ot_seconds = 0.0
|
||||||
|
|
||||||
@@ -628,6 +635,8 @@ def compute_work_done(
|
|||||||
"work_date": punch_date,
|
"work_date": punch_date,
|
||||||
"first_in": first_in,
|
"first_in": first_in,
|
||||||
"first_in_loc": first_in_loc,
|
"first_in_loc": first_in_loc,
|
||||||
|
"last_in": last_in,
|
||||||
|
"last_in_loc": last_in_loc,
|
||||||
"last_out": last_out,
|
"last_out": last_out,
|
||||||
"last_out_loc": last_out_loc,
|
"last_out_loc": last_out_loc,
|
||||||
"work_seconds": work_seconds,
|
"work_seconds": work_seconds,
|
||||||
@@ -647,6 +656,7 @@ def compute_work_done(
|
|||||||
async def sync_attendance_to_tcaoff(
|
async def sync_attendance_to_tcaoff(
|
||||||
tcaoff_client: AsyncTheCAOffice,
|
tcaoff_client: AsyncTheCAOffice,
|
||||||
cosec_in_out_summary: dict,
|
cosec_in_out_summary: dict,
|
||||||
|
chunk_size: int = 10,
|
||||||
verbose: bool = False
|
verbose: bool = False
|
||||||
) -> Dict[str, int]:
|
) -> Dict[str, int]:
|
||||||
|
|
||||||
@@ -655,6 +665,7 @@ async def sync_attendance_to_tcaoff(
|
|||||||
:param tcaoff_client: The asynchronous client object that interfaces with TCAOFF.
|
:param tcaoff_client: The asynchronous client object that interfaces with TCAOFF.
|
||||||
:param cosec_in_out_summary: he table that contains all the work done by all the employees on the date-range that
|
:param cosec_in_out_summary: he table that contains all the work done by all the employees on the date-range that
|
||||||
was selected.
|
was selected.
|
||||||
|
:param chunk_size: The number of attendance marking requests to fire concurrently.
|
||||||
:param verbose: If True, internal debugging print will be more verbose.
|
:param verbose: If True, internal debugging print will be more verbose.
|
||||||
:return: The dict that gives you the count of the successful and failed attendance marking API calls.
|
:return: The dict that gives you the count of the successful and failed attendance marking API calls.
|
||||||
"""
|
"""
|
||||||
@@ -707,9 +718,11 @@ async def sync_attendance_to_tcaoff(
|
|||||||
json_notes = {
|
json_notes = {
|
||||||
"cosec": {
|
"cosec": {
|
||||||
"workSeconds": wr["work_seconds"],
|
"workSeconds": wr["work_seconds"],
|
||||||
"totHours": wr["work_hours"],
|
"workHours": wr["work_hours"],
|
||||||
"firstIn": wr["first_in"],
|
"firstIn": wr["first_in"],
|
||||||
"firstInLoc": wr["first_in_loc"],
|
"firstInLoc": wr["first_in_loc"],
|
||||||
|
"lastIn": wr["last_in"],
|
||||||
|
"lastInLoc": wr["last_in_loc"],
|
||||||
"lastOut": wr["last_out"],
|
"lastOut": wr["last_out"],
|
||||||
"lastOutLoc": wr["last_out_loc"],
|
"lastOutLoc": wr["last_out_loc"],
|
||||||
}
|
}
|
||||||
@@ -724,7 +737,7 @@ 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[:], size = 25):
|
for chunk in chunks(tasks[:], size = chunk_size):
|
||||||
count += 1
|
count += 1
|
||||||
printer("Task Chunk:", count)
|
printer("Task Chunk:", count)
|
||||||
_res = await asyncio.gather(*chunk)
|
_res = await asyncio.gather(*chunk)
|
||||||
|
|||||||
+8
-6
@@ -149,12 +149,13 @@ async def yesterday_cron(
|
|||||||
await common.sync_attendance_to_tcaoff(
|
await common.sync_attendance_to_tcaoff(
|
||||||
tcaoff_client = tcaoff_client,
|
tcaoff_client = tcaoff_client,
|
||||||
cosec_in_out_summary = json.from_file(common.PREV_DAY_IN_OUT_SUMMARY_CACHE_FILE),
|
cosec_in_out_summary = json.from_file(common.PREV_DAY_IN_OUT_SUMMARY_CACHE_FILE),
|
||||||
|
chunk_size = 10
|
||||||
)
|
)
|
||||||
|
|
||||||
# If something goes wrong in the COSEC step:
|
# If something goes wrong in the COSEC step:
|
||||||
except Exception as exception:
|
except Exception as exception:
|
||||||
err_printer(exception)
|
err_printer(exception)
|
||||||
if test_mode: raise
|
# if test_mode: raise
|
||||||
|
|
||||||
# Log out of TCAOFF:
|
# Log out of TCAOFF:
|
||||||
success = await tcaoff_client.logout()
|
success = await tcaoff_client.logout()
|
||||||
@@ -164,7 +165,7 @@ async def yesterday_cron(
|
|||||||
except Exception as exception:
|
except Exception as exception:
|
||||||
err_printer(exception)
|
err_printer(exception)
|
||||||
await tcaoff_client.logout()
|
await tcaoff_client.logout()
|
||||||
if test_mode: raise
|
# if test_mode: raise
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------------------------------------------------
|
||||||
@@ -246,18 +247,19 @@ async def today_cron(
|
|||||||
await common.sync_attendance_to_tcaoff(
|
await common.sync_attendance_to_tcaoff(
|
||||||
tcaoff_client = tcaoff_client,
|
tcaoff_client = tcaoff_client,
|
||||||
cosec_in_out_summary = json.from_file(common.IN_OUT_SUMMARY_CACHE_FILE),
|
cosec_in_out_summary = json.from_file(common.IN_OUT_SUMMARY_CACHE_FILE),
|
||||||
|
chunk_size = 10
|
||||||
)
|
)
|
||||||
|
|
||||||
# If something goes wrong in the COSEC step:
|
# If something goes wrong in the COSEC step:
|
||||||
except Exception as exception:
|
except Exception as exception:
|
||||||
err_printer(exception)
|
err_printer(exception)
|
||||||
if test_mode: raise
|
# if test_mode: raise
|
||||||
|
|
||||||
# If something goes wrong:
|
# If something goes wrong:
|
||||||
except Exception as exception:
|
except Exception as exception:
|
||||||
err_printer(exception)
|
err_printer(exception)
|
||||||
await tcaoff_client.logout()
|
await tcaoff_client.logout()
|
||||||
if test_mode: raise
|
# if test_mode: raise
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------------------------------------------------
|
||||||
@@ -284,12 +286,12 @@ 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),
|
||||||
tcaoff_client = tcaoff_client,
|
tcaoff_client = tcaoff_client,
|
||||||
# test_mode = test_mode
|
test_mode = test_mode
|
||||||
)
|
)
|
||||||
printer("Test Done")
|
printer("Test Done")
|
||||||
return
|
return
|
||||||
|
|||||||
+319
-204
@@ -136,7 +136,7 @@ class AsyncTheCAOffice:
|
|||||||
pool = 60.0,
|
pool = 60.0,
|
||||||
connect = 5.0,
|
connect = 5.0,
|
||||||
write = 15.0,
|
write = 15.0,
|
||||||
read = 180.0
|
read = 60.0
|
||||||
),
|
),
|
||||||
headers = None
|
headers = None
|
||||||
)
|
)
|
||||||
@@ -265,170 +265,253 @@ class AsyncTheCAOffice:
|
|||||||
# ┣┫┏┓┏┓┏┓┏┣┓┏┓┏
|
# ┣┫┏┓┏┓┏┓┏┣┓┏┓┏
|
||||||
# ┻┛┛ ┗┻┛┗┗┛┗┗ ┛
|
# ┻┛┛ ┗┻┛┗┗┛┗┗ ┛
|
||||||
|
|
||||||
async def branch_list(self) -> List[Dict[str, Any]] | None:
|
async def branch_list(
|
||||||
|
self,
|
||||||
|
raise_exception: bool = False,
|
||||||
|
) -> List[Dict[str, Any]] | None:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
List the existing branches.
|
List the existing branches.
|
||||||
|
:param raise_exception: Whether to raise any exceptions, or to suppress them.
|
||||||
:return: A list of dictionaries where each dictionary describes on branch. None if the API call fails.
|
:return: A list of dictionaries where each dictionary describes on branch. None if the API call fails.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Make the API call:
|
# Start by assuming failure:
|
||||||
response = await self._http_client.post(
|
branches = None
|
||||||
url = self.BRANCH_LIST_URL,
|
|
||||||
headers = {"X-Session-Token": self.__session_token},
|
|
||||||
json = {"idUser": self.__user_id}
|
|
||||||
)
|
|
||||||
|
|
||||||
# If the call succeeded:
|
try:
|
||||||
if response.status_code in [200]:
|
|
||||||
response_json = response.json()
|
|
||||||
branches = response_json["data"]["rs0"]
|
|
||||||
self._printer("Branches listed.")
|
|
||||||
return branches
|
|
||||||
|
|
||||||
# If the call failed:
|
# Make the API call:
|
||||||
else:
|
response = await self._http_client.post(
|
||||||
self._err_printer("Branch-list failed.")
|
url = self.BRANCH_LIST_URL,
|
||||||
return None
|
headers = {"X-Session-Token": self.__session_token},
|
||||||
|
json = {"idUser": self.__user_id}
|
||||||
|
)
|
||||||
|
|
||||||
|
# If the call succeeded:
|
||||||
|
if response.status_code in [200]:
|
||||||
|
response_json = response.json()
|
||||||
|
branches = response_json["data"]["rs0"]
|
||||||
|
self._printer("Branches listed.")
|
||||||
|
|
||||||
|
# If the call failed:
|
||||||
|
else:
|
||||||
|
self._err_printer("Branch-list failed.")
|
||||||
|
branches = None
|
||||||
|
|
||||||
|
# If something goes wrong:
|
||||||
|
except Exception as exception:
|
||||||
|
self._err_printer("Branch-list failed.", exception)
|
||||||
|
if raise_exception: raise
|
||||||
|
branches = None
|
||||||
|
|
||||||
|
# Done here:
|
||||||
|
return branches
|
||||||
|
|
||||||
async def branch_add(
|
async def branch_add(
|
||||||
self,
|
self,
|
||||||
branch_name: str
|
branch_name: str,
|
||||||
|
raise_exception: bool = False,
|
||||||
) -> bool:
|
) -> bool:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Add a new branch.
|
Add a new branch.
|
||||||
:param branch_name: The name of the branch to add.
|
:param branch_name: The name of the branch to add.
|
||||||
|
:param raise_exception: Whether to raise any exceptions, or to suppress them.
|
||||||
:return: True if logged out, else False.
|
:return: True if logged out, else False.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Make the API call:
|
# Start by assuming failure:
|
||||||
response = await self._http_client.post(
|
success = False
|
||||||
url = self.BRANCH_ADD_URL,
|
|
||||||
headers = {"X-Session-Token": self.__session_token},
|
|
||||||
json = {
|
|
||||||
"idUser": self.__user_id,
|
|
||||||
"branchName": branch_name
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
# If the call succeeded:
|
try:
|
||||||
if response.status_code in [200]:
|
|
||||||
self._printer(
|
|
||||||
"Branch added.",
|
|
||||||
branch_name
|
|
||||||
)
|
|
||||||
return True
|
|
||||||
|
|
||||||
# If the call failed:
|
# Make the API call:
|
||||||
else:
|
response = await self._http_client.post(
|
||||||
response_json = response.json()
|
url = self.BRANCH_ADD_URL,
|
||||||
self._err_printer(
|
headers = {"X-Session-Token": self.__session_token},
|
||||||
"Branch NOT added.",
|
json = {
|
||||||
branch_name,
|
"idUser": self.__user_id,
|
||||||
response_json
|
"branchName": branch_name
|
||||||
|
}
|
||||||
)
|
)
|
||||||
return False
|
|
||||||
|
# If the call succeeded:
|
||||||
|
if response.status_code in [200]:
|
||||||
|
self._printer(
|
||||||
|
"Branch added.",
|
||||||
|
branch_name
|
||||||
|
)
|
||||||
|
success = True
|
||||||
|
|
||||||
|
# If the call failed:
|
||||||
|
else:
|
||||||
|
response_json = response.json()
|
||||||
|
self._err_printer(
|
||||||
|
"Branch NOT added.",
|
||||||
|
branch_name,
|
||||||
|
response_json
|
||||||
|
)
|
||||||
|
success = False
|
||||||
|
|
||||||
|
# If something goes wrong:
|
||||||
|
except Exception as exception:
|
||||||
|
self._err_printer("Branch NOT added.", exception, branch_name)
|
||||||
|
if raise_exception: raise
|
||||||
|
success = False
|
||||||
|
|
||||||
|
# Done here:
|
||||||
|
return success
|
||||||
|
|
||||||
# ┳┓
|
# ┳┓
|
||||||
# ┃┃┏┓┏┓┏┓┏┓╋┏┳┓┏┓┏┓╋
|
# ┃┃┏┓┏┓┏┓┏┓╋┏┳┓┏┓┏┓╋
|
||||||
# ┻┛┗ ┣┛┗┻┛ ┗┛┗┗┗ ┛┗┗
|
# ┻┛┗ ┣┛┗┻┛ ┗┛┗┗┗ ┛┗┗
|
||||||
# ┛
|
# ┛
|
||||||
|
|
||||||
async def department_list(self) -> List[Dict[str, Any]] | None:
|
async def department_list(
|
||||||
|
self,
|
||||||
|
raise_exception: bool = False,
|
||||||
|
) -> List[Dict[str, Any]] | None:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
List the existing departments.
|
List the existing departments.
|
||||||
|
:param raise_exception: Whether to raise any exceptions, or to suppress them.
|
||||||
:return: A list of dictionaries where each dictionary describes one department. None if the API call fails.
|
:return: A list of dictionaries where each dictionary describes one department. None if the API call fails.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Make the API call:
|
# Start by assuming failure:
|
||||||
response = await self._http_client.post(
|
depts = None
|
||||||
url = self.DEPT_LIST_URL,
|
|
||||||
headers = {"X-Session-Token": self.__session_token},
|
|
||||||
json = {"idUser": self.__user_id}
|
|
||||||
)
|
|
||||||
|
|
||||||
# If the call succeeded:
|
try:
|
||||||
if response.status_code in [200]:
|
|
||||||
response_json = response.json()
|
|
||||||
depts = response_json["data"]["rs0"]
|
|
||||||
self._printer("Depts. listed.")
|
|
||||||
return depts
|
|
||||||
|
|
||||||
# If the call failed:
|
# Make the API call:
|
||||||
else:
|
response = await self._http_client.post(
|
||||||
self._err_printer("Dept.-list failed.")
|
url = self.DEPT_LIST_URL,
|
||||||
return None
|
headers = {"X-Session-Token": self.__session_token},
|
||||||
|
json = {"idUser": self.__user_id}
|
||||||
|
)
|
||||||
|
|
||||||
|
# If the call succeeded:
|
||||||
|
if response.status_code in [200]:
|
||||||
|
response_json = response.json()
|
||||||
|
depts = response_json["data"]["rs0"]
|
||||||
|
self._printer("Depts. listed.")
|
||||||
|
|
||||||
|
# If the call failed:
|
||||||
|
else:
|
||||||
|
self._err_printer("Dept.-list failed.")
|
||||||
|
depts = None
|
||||||
|
|
||||||
|
# If something goes wrong:
|
||||||
|
except Exception as exception:
|
||||||
|
self._err_printer("Dept.-list failed.", exception)
|
||||||
|
if raise_exception: raise
|
||||||
|
depts = None
|
||||||
|
|
||||||
|
# Done here:
|
||||||
|
return depts
|
||||||
|
|
||||||
async def department_add(
|
async def department_add(
|
||||||
self,
|
self,
|
||||||
department_name: str
|
department_name: str,
|
||||||
|
raise_exception: bool = False,
|
||||||
) -> bool:
|
) -> bool:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Add a new department.
|
Add a new department.
|
||||||
:param department_name: The name of the department to add.
|
:param department_name: The name of the department to add.
|
||||||
|
:param raise_exception: Whether to raise any exceptions, or to suppress them.
|
||||||
:return: True if logged out, else False.
|
:return: True if logged out, else False.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Make the API call:
|
# Start by assuming failure:
|
||||||
response = await self._http_client.post(
|
success = False
|
||||||
url = self.DEPT_ADD_URL,
|
|
||||||
headers = {"X-Session-Token": self.__session_token},
|
|
||||||
json = {
|
|
||||||
"idUser": self.__user_id,
|
|
||||||
"departmentName": department_name
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
# If the call succeeded:
|
try:
|
||||||
if response.status_code in [200]:
|
|
||||||
self._printer(
|
|
||||||
"Dept. added.",
|
|
||||||
department_name
|
|
||||||
)
|
|
||||||
return True
|
|
||||||
|
|
||||||
# If the call failed:
|
# Make the API call:
|
||||||
else:
|
response = await self._http_client.post(
|
||||||
response_json = response.json()
|
url = self.DEPT_ADD_URL,
|
||||||
self._err_printer(
|
headers = {"X-Session-Token": self.__session_token},
|
||||||
"Dept. NOT added.",
|
json = {
|
||||||
department_name,
|
"idUser": self.__user_id,
|
||||||
response_json
|
"departmentName": department_name
|
||||||
|
}
|
||||||
)
|
)
|
||||||
return False
|
|
||||||
|
# If the call succeeded:
|
||||||
|
if response.status_code in [200]:
|
||||||
|
self._printer(
|
||||||
|
"Dept. added.",
|
||||||
|
department_name
|
||||||
|
)
|
||||||
|
success = True
|
||||||
|
|
||||||
|
# If the call failed:
|
||||||
|
else:
|
||||||
|
response_json = response.json()
|
||||||
|
self._err_printer(
|
||||||
|
"Dept. NOT added.",
|
||||||
|
department_name,
|
||||||
|
response_json
|
||||||
|
)
|
||||||
|
success = False
|
||||||
|
|
||||||
|
# If something goes wrong:
|
||||||
|
except Exception as exception:
|
||||||
|
self._err_printer("Dept. NOT added.", exception, department_name)
|
||||||
|
if raise_exception: raise
|
||||||
|
success = False
|
||||||
|
|
||||||
|
# Done here:
|
||||||
|
return success
|
||||||
|
|
||||||
# ┏┳┓
|
# ┏┳┓
|
||||||
# ┃ ┏┓┏┓┏┳┓
|
# ┃ ┏┓┏┓┏┳┓
|
||||||
# ┻ ┗ ┗┻┛┗┗
|
# ┻ ┗ ┗┻┛┗┗
|
||||||
|
|
||||||
async def team_list(self) -> List[Dict[str, Any]] | None:
|
async def team_list(
|
||||||
|
self,
|
||||||
|
raise_exception: bool = False,
|
||||||
|
) -> List[Dict[str, Any]] | None:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
List the existing team members.
|
List the existing team members.
|
||||||
|
:param raise_exception: Whether to raise any exceptions, or to suppress them.
|
||||||
:return: A list of dictionaries where each dictionary describes one team-member. None if the API call fails.
|
:return: A list of dictionaries where each dictionary describes one team-member. None if the API call fails.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Make the API call:
|
# Start by assuming failure:
|
||||||
response = await self._http_client.post(
|
teams = None
|
||||||
url = self.TEAM_LIST_URL,
|
|
||||||
headers = {"X-Session-Token": self.__session_token},
|
|
||||||
json = {"idUser": self.__user_id}
|
|
||||||
)
|
|
||||||
|
|
||||||
# If the call succeeded:
|
try:
|
||||||
if response.status_code in [200]:
|
|
||||||
response_json = response.json()
|
|
||||||
teams = response_json["data"]["rs0"]
|
|
||||||
self._printer("Team listed.")
|
|
||||||
return teams
|
|
||||||
|
|
||||||
# If the call failed:
|
# Make the API call:
|
||||||
else:
|
response = await self._http_client.post(
|
||||||
self._err_printer("Team-list failed.")
|
url = self.TEAM_LIST_URL,
|
||||||
return None
|
headers = {"X-Session-Token": self.__session_token},
|
||||||
|
json = {"idUser": self.__user_id}
|
||||||
|
)
|
||||||
|
|
||||||
|
# If the call succeeded:
|
||||||
|
if response.status_code in [200]:
|
||||||
|
response_json = response.json()
|
||||||
|
teams = response_json["data"]["rs0"]
|
||||||
|
self._printer("Team listed.")
|
||||||
|
|
||||||
|
# If the call failed:
|
||||||
|
else:
|
||||||
|
self._err_printer("Team-list failed.")
|
||||||
|
teams = None
|
||||||
|
|
||||||
|
# If something goes wrong:
|
||||||
|
except Exception as exception:
|
||||||
|
self._err_printer("Team-list filed.", exception)
|
||||||
|
if raise_exception: raise
|
||||||
|
teams = None
|
||||||
|
|
||||||
|
# Done here:
|
||||||
|
return teams
|
||||||
|
|
||||||
async def team_add(
|
async def team_add(
|
||||||
self,
|
self,
|
||||||
@@ -441,7 +524,8 @@ class AsyncTheCAOffice:
|
|||||||
role: str,
|
role: str,
|
||||||
username: str,
|
username: str,
|
||||||
password: str,
|
password: str,
|
||||||
applicant_notes: dict | list | str = None
|
applicant_notes: dict | list | str = None,
|
||||||
|
raise_exception: bool = False,
|
||||||
) -> bool:
|
) -> bool:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
@@ -456,47 +540,62 @@ class AsyncTheCAOffice:
|
|||||||
:param username: The unique username of the team member. Cannot be the same as anyone else.
|
:param username: The unique username of the team member. Cannot be the same as anyone else.
|
||||||
:param password: The password for this team member's login.
|
:param password: The password for this team member's login.
|
||||||
:param applicant_notes: Optional notes about the team member.
|
:param applicant_notes: Optional notes about the team member.
|
||||||
|
:param raise_exception: Whether to raise any exceptions, or to suppress them.
|
||||||
:return: True if successful, else False.
|
:return: True if successful, else False.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Make the API call:
|
# Start by assuming failure:
|
||||||
response = await self._http_client.post(
|
success = False
|
||||||
url = self.TEAM_ADD_URL,
|
|
||||||
headers = {"X-Session-Token": self.__session_token},
|
|
||||||
json = {
|
|
||||||
"branchId": branch_id,
|
|
||||||
"idDepartment": dept_id,
|
|
||||||
"reportingTo": reporting_to,
|
|
||||||
"name": team_name,
|
|
||||||
"email": email,
|
|
||||||
"phoneNo": phone_no,
|
|
||||||
"role": role,
|
|
||||||
"username": username,
|
|
||||||
"password": password,
|
|
||||||
"hierarchy": 1,
|
|
||||||
"applicantNotes": applicant_notes
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
# If the call succeeded:
|
try:
|
||||||
if response.status_code in [200]:
|
|
||||||
self._printer(
|
|
||||||
"Team added.",
|
|
||||||
team_name,
|
|
||||||
username,
|
|
||||||
)
|
|
||||||
return True
|
|
||||||
|
|
||||||
# If the call failed:
|
# Make the API call:
|
||||||
else:
|
response = await self._http_client.post(
|
||||||
response_json = response.json()
|
url = self.TEAM_ADD_URL,
|
||||||
self._err_printer(
|
headers = {"X-Session-Token": self.__session_token},
|
||||||
"Team NOT added.",
|
json = {
|
||||||
team_name,
|
"branchId": branch_id,
|
||||||
username,
|
"idDepartment": dept_id,
|
||||||
response_json
|
"reportingTo": reporting_to,
|
||||||
|
"name": team_name,
|
||||||
|
"email": email,
|
||||||
|
"phoneNo": phone_no,
|
||||||
|
"role": role,
|
||||||
|
"username": username,
|
||||||
|
"password": password,
|
||||||
|
"hierarchy": 1,
|
||||||
|
"applicantNotes": applicant_notes
|
||||||
|
}
|
||||||
)
|
)
|
||||||
return False
|
|
||||||
|
# If the call succeeded:
|
||||||
|
if response.status_code in [200]:
|
||||||
|
self._printer(
|
||||||
|
"Team added.",
|
||||||
|
team_name,
|
||||||
|
username,
|
||||||
|
)
|
||||||
|
success = True
|
||||||
|
|
||||||
|
# If the call failed:
|
||||||
|
else:
|
||||||
|
response_json = response.json()
|
||||||
|
self._err_printer(
|
||||||
|
"Team NOT added.",
|
||||||
|
team_name,
|
||||||
|
username,
|
||||||
|
response_json
|
||||||
|
)
|
||||||
|
success = False
|
||||||
|
|
||||||
|
# If something goes wrong:
|
||||||
|
except Exception as exception:
|
||||||
|
self._err_printer("Team NOT added.", exception)
|
||||||
|
if raise_exception: raise
|
||||||
|
success = False
|
||||||
|
|
||||||
|
# Done here:
|
||||||
|
return success
|
||||||
|
|
||||||
# ┏┓ ┓
|
# ┏┓ ┓
|
||||||
# ┣┫╋╋┏┓┏┓┏┫┏┓┏┓┏┏┓
|
# ┣┫╋╋┏┓┏┓┏┫┏┓┏┓┏┏┓
|
||||||
@@ -508,7 +607,8 @@ class AsyncTheCAOffice:
|
|||||||
status: Literal["P", "H", "A", "OT"],
|
status: Literal["P", "H", "A", "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,
|
||||||
|
raise_exception: bool = False
|
||||||
) -> bool:
|
) -> bool:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
@@ -522,99 +622,114 @@ class AsyncTheCAOffice:
|
|||||||
: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.
|
||||||
|
:param raise_exception: Whether to raise any exceptions, or to suppress them.
|
||||||
:return: True if the attendance was marked, else False.
|
:return: True if the attendance was marked, else False.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Prepare the payload:
|
# Start by assuming failure:
|
||||||
json_payload = {
|
success = False
|
||||||
"date": (
|
|
||||||
date_time.parse_date_time(attendance_date) or
|
|
||||||
date_time.get_current_date_time()
|
|
||||||
).strftime("%Y-%m-%d"),
|
|
||||||
"idUser": user_id,
|
|
||||||
"status": status if over_time <= 0.0 else "OT",
|
|
||||||
"ot": over_time,
|
|
||||||
}
|
|
||||||
|
|
||||||
# Add JSON notes if needed:
|
try:
|
||||||
if json_notes:
|
|
||||||
json_payload["jsonNotes"] = json_notes
|
|
||||||
|
|
||||||
# Make the API call:
|
# Prepare the payload:
|
||||||
response = await self._http_client.post(
|
json_payload = {
|
||||||
url = self.ATTENDANCE_MARK_URL,
|
"date": (
|
||||||
headers = {"X-Session-Token": self.__session_token},
|
date_time.parse_date_time(attendance_date) or
|
||||||
json = json_payload
|
date_time.get_current_date_time()
|
||||||
)
|
).strftime("%Y-%m-%d"),
|
||||||
|
"idUser": user_id,
|
||||||
|
"status": status if over_time <= 0.0 else "OT",
|
||||||
|
"ot": over_time,
|
||||||
|
}
|
||||||
|
|
||||||
# Debugging:
|
# Add JSON notes if needed:
|
||||||
if response.status_code not in [200]:
|
if json_notes:
|
||||||
try:
|
json_payload["jsonNotes"] = json_notes
|
||||||
response_json = response.json()
|
|
||||||
self._printer("TCAOFF Attendance-Mark", response_json)
|
|
||||||
except Exception as e:
|
|
||||||
self._printer("TCAOFF Attendance-Mark", e, response.content)
|
|
||||||
print("Payload:", json.to_string(json_payload))
|
|
||||||
|
|
||||||
# If the call succeeded:
|
# Make the API call:
|
||||||
if response.status_code in [200]:
|
response = await self._http_client.post(
|
||||||
self._printer(
|
url = self.ATTENDANCE_MARK_URL,
|
||||||
"Attendance marked.",
|
headers = {"X-Session-Token": self.__session_token},
|
||||||
user_id,
|
json = json_payload,
|
||||||
|
timeout = httpx.Timeout(
|
||||||
|
pool = 60.0,
|
||||||
|
connect = 5.0,
|
||||||
|
write = 15.0,
|
||||||
|
read = 10.0
|
||||||
|
)
|
||||||
)
|
)
|
||||||
return True
|
|
||||||
|
|
||||||
# If the call failed:
|
# If the call succeeded:
|
||||||
else:
|
if response.status_code in [200]:
|
||||||
try: response_json = response.json()
|
self._printer("Attendance marked.", user_id, status, json_notes)
|
||||||
except Exception as e: response_json = response.content
|
success = True
|
||||||
self._err_printer(
|
|
||||||
"Attendance NOT added.",
|
# If the call failed:
|
||||||
user_id,
|
else:
|
||||||
response_json
|
try: response_json = response.json()
|
||||||
)
|
except Exception as e: response_json = response.content
|
||||||
return False
|
self._err_printer("Attendance NOT added.", user_id, response_json)
|
||||||
|
success = False
|
||||||
|
|
||||||
|
# If something goes wrong:
|
||||||
|
except Exception as exception:
|
||||||
|
self._err_printer("Attendance NOT added.", exception, user_id)
|
||||||
|
if raise_exception: raise
|
||||||
|
success = False
|
||||||
|
|
||||||
|
# Done here:
|
||||||
|
return success
|
||||||
|
|
||||||
async def attendance_register(
|
async def attendance_register(
|
||||||
self,
|
self,
|
||||||
target_month: datetime.datetime,
|
target_month: datetime.datetime,
|
||||||
|
raise_exception: bool = False,
|
||||||
) -> List[dict] | None:
|
) -> List[dict] | None:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
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 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.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Start by assuming failure:
|
# Start by assuming failure:
|
||||||
attendance_register = None
|
attendance_register = None
|
||||||
|
|
||||||
# Make the API call:
|
try:
|
||||||
json_payload = {"month": target_month.strftime("%Y-%m-%d")}
|
|
||||||
response = await self._http_client.post(
|
|
||||||
url = self.ATTENDANCE_REGISTER_URL,
|
|
||||||
headers = {"X-Session-Token": self.__session_token},
|
|
||||||
json = json_payload,
|
|
||||||
)
|
|
||||||
|
|
||||||
# If the call succeeded:
|
# Make the API call:
|
||||||
if response.status_code in [200]:
|
json_payload = {"month": target_month.strftime("%Y-%m-%d")}
|
||||||
self._printer(
|
response = await self._http_client.post(
|
||||||
"Attendance register fetched.",
|
url = self.ATTENDANCE_REGISTER_URL,
|
||||||
target_month,
|
headers = {"X-Session-Token": self.__session_token},
|
||||||
|
json = json_payload,
|
||||||
)
|
)
|
||||||
attendance_register = response.json()["data"]["rs0"]
|
|
||||||
|
|
||||||
# If the call failed:
|
# If the call succeeded:
|
||||||
else:
|
if response.status_code in [200]:
|
||||||
try: response_data = response.json()
|
self._printer(
|
||||||
except Exception as e: response_data = response.content
|
"Attendance register fetched.",
|
||||||
self._err_printer(
|
target_month,
|
||||||
"Attendance register NOT fetched.",
|
)
|
||||||
target_month,
|
attendance_register = response.json()["data"]["rs0"]
|
||||||
response_data
|
|
||||||
)
|
# If the call failed:
|
||||||
|
else:
|
||||||
|
try: response_data = response.json()
|
||||||
|
except Exception as e: response_data = response.content
|
||||||
|
self._err_printer(
|
||||||
|
"Attendance register NOT fetched.",
|
||||||
|
target_month,
|
||||||
|
response_data
|
||||||
|
)
|
||||||
|
attendance_register = None
|
||||||
|
|
||||||
|
# If something goes wrong:
|
||||||
|
except Exception as exception:
|
||||||
|
self._err_printer(exception)
|
||||||
|
if raise_exception: raise
|
||||||
attendance_register = None
|
attendance_register = None
|
||||||
|
|
||||||
# Done here:
|
# Done here:
|
||||||
|
|||||||
Reference in New Issue
Block a user