MEGAINFRA-WEBAPP/scripts/pb-add-employee-rates.py

90 lines
3.5 KiB
Python

#!/usr/bin/env python3
"""Create dated employee hourly-rate history without changing worker records.
Run: python3 scripts/pb-add-employee-rates.py
Credentials are loaded by pb_env from .env.local or the environment.
No rates are seeded: the previous/new payroll list must supply actual values.
Existing compatible collections are verified and left untouched.
"""
import sys
from pb_env import http, superuser_token
def definition(employees):
return {
"name": "EMPLOYEE_RATES",
"type": "base",
"fields": [
{"name": "employee", "type": "relation", "required": True,
"collectionId": employees["id"], "maxSelect": 1,
"cascadeDelete": False},
{"name": "effective_from", "type": "date", "required": True},
{"name": "rate_per_hour", "type": "number", "required": True,
"min": 0},
{"name": "notes", "type": "text", "required": False},
{"name": "created", "type": "autodate", "onCreate": True,
"onUpdate": False},
{"name": "updated", "type": "autodate", "onCreate": True,
"onUpdate": True},
],
"indexes": [
"CREATE UNIQUE INDEX `idx_employee_rates_employee_day` "
"ON `EMPLOYEE_RATES` (`employee`, substr(`effective_from`, 1, 10))",
"CREATE INDEX `idx_employee_rates_employee_date` "
"ON `EMPLOYEE_RATES` (`employee`, `effective_from`)",
],
# Inherit employee read visibility; all rate writes require superuser.
"listRule": employees.get("listRule"),
"viewRule": employees.get("viewRule"),
"createRule": None,
"updateRule": None,
"deleteRule": None,
}
def verify(actual, expected):
fields = {f["name"]: f for f in actual.get("fields", [])}
for wanted in expected["fields"]:
got = fields.get(wanted["name"], {})
for key, value in wanted.items():
if got.get(key) != value:
raise RuntimeError(f"Incompatible field: {wanted['name']}.{key}")
for index in expected["indexes"]:
if index not in actual.get("indexes", []):
raise RuntimeError("Missing expected rate-history index")
for rule in ("listRule", "viewRule", "createRule", "updateRule", "deleteRule"):
if actual.get(rule) != expected[rule]:
raise RuntimeError(f"Incompatible access rule: {rule}")
def main():
token = superuser_token()
code, employees = http("GET", "/api/collections/employees", token=token)
if code != 200:
raise RuntimeError(f"Cannot read employees schema: HTTP {code}")
expected = definition(employees)
code, existing = http("GET", "/api/collections/employee_rates", token=token)
if code == 404:
code, created = http("POST", "/api/collections", expected, token)
if code != 200:
raise RuntimeError(f"Create failed: HTTP {code}: {created}")
print(f"Created EMPLOYEE_RATES: {created['id']}")
elif code == 200:
verify(existing, expected)
print("EMPLOYEE_RATES already exists; no changes made")
else:
raise RuntimeError(f"Cannot inspect employee_rates: HTTP {code}")
code, actual = http("GET", "/api/collections/employee_rates", token=token)
if code != 200:
raise RuntimeError(f"Cannot verify new schema: HTTP {code}")
verify(actual, expected)
print("Verified fields, indexes and access rules. No employee or rate records changed.")
if __name__ == "__main__":
try:
main()
except Exception as exc:
sys.exit(str(exc))