summaryrefslogtreecommitdiff
path: root/jimbrella/umbrellas.py
diff options
context:
space:
mode:
Diffstat (limited to 'jimbrella/umbrellas.py')
-rw-r--r--jimbrella/umbrellas.py59
1 files changed, 36 insertions, 23 deletions
diff --git a/jimbrella/umbrellas.py b/jimbrella/umbrellas.py
index ff88277..2525a31 100644
--- a/jimbrella/umbrellas.py
+++ b/jimbrella/umbrellas.py
@@ -1,7 +1,8 @@
import sqlite3
-from datetime import datetime, timedelta
+from datetime import datetime, timezone, timedelta
+from dateutil.parser import isoparse
from typing import Union
-from .utils import human_datetime, human_timedelta
+from .utils import human_datetime, human_timedelta, CST
from .config import DUE_HOURS, ADMIN_LOG_PATH
from .exceptions import *
@@ -27,8 +28,8 @@ class Umbrellas:
- tenant_id | string. student or faculty ID.
- tenant_phone | string. phone number via which to contact tenant when the lease is due.
- tenant_email | string. for future compatibility. always None for the time being.
- - lent_at | an ISO 8601 date string "YYYY-MM-DDThh:mm:ss.mmm+08:00" if status is
- | "lent" or "overdue. is None otherwise.
+ - lent_at | an ISO 8601 datetime string if status is "lent" or "overdue", empty string
+ | otherwise.
Schema:
CREATE TABLE Umbrellas(
@@ -54,7 +55,9 @@ class Umbrellas:
if umbid is None:
data = db.execute("SELECT * FROM Umbrellas").fetchall()
else:
- data = db.execute("SELECT * FROM Umbrellas WHERE id = ?", (umbid,)).fetchone()
+ data = db.execute(
+ "SELECT * FROM Umbrellas WHERE id = ?", (umbid,)
+ ).fetchone()
db.close()
return data
@@ -64,13 +67,14 @@ class Umbrellas:
Not all fields in an umbrella dict need to be present in `umb`. Only `id` is required.
If an optional field is not found, its value is left untouched. If an optional field is
- present but its value is an empty string or None, the old datum will become NULL.
+ present but its value is an empty string, it will be erased.
Invalid values are rejected as an UmbrellaValueError.
If `status` is not "lent" or "overdue", `tenant_*` and `lent_at` are automatically erased.
- `lent_at` may be either an ISO 8601 string or a datetime.datetime object. Must be UTC+8.
+ `lent_at` may be either an ISO 8601 string or a datetime.datetime object. If no timezone is
+ supplied, UTC+8 is assumed.
Returns a dict of <field>: (<prior_value>, <updated_value>) for each updated field unless
its erasure can be inferred. For AdminLog.
@@ -82,11 +86,13 @@ class Umbrellas:
raise UmbrellaValueError("id")
db = sqlite3.connect(self.path)
- db.row_factory = sqlite.Row
+ db.row_factory = sqlite3.Row
# check if umbrella #<id> exists in database
umbid = umb["id"]
- umb_in_db = db.execute("SELECT * FROM Umbrellas WHERE id = ?", (umbid,)).fetchone()
+ umb_in_db = db.execute(
+ "SELECT * FROM Umbrellas WHERE id = ?", (umbid,)
+ ).fetchone()
if umb_in_db is None:
raise UmbrellaNotFoundError(umbid)
@@ -99,12 +105,14 @@ class Umbrellas:
if umb_in_db["status"] != umb["status"]:
diff["status"] = (umb_in_db["status"], umb["status"])
- db.execute("UPDATE Umbrellas SET status = ? WHERE id = ?", (status, umbid))
+ db.execute(
+ "UPDATE Umbrellas SET status = ? WHERE id = ?", (status, umbid)
+ )
else:
raise UmbrellaValueError("status")
if status in ("lent", "overdue"):
- for key in (
+ for col in (
"tenant_name",
"tenant_id",
"tenant_phone",
@@ -115,16 +123,17 @@ class Umbrellas:
diff[col] = (umb_in_db[col], umb[col])
db.execute(
- "UPDATE Umbrellas SET ? = ? WHERE id = ?",
- (col,
- umb[col],
- umbid,)
+ f"UPDATE Umbrellas SET {col} = ? WHERE id = ?",
+ (
+ umb[col],
+ umbid,
+ ),
)
if "lent_at" in umb:
try:
# lent_at could be a string, in which case it is parsed
- lent_at = datetime.fromisoformat(umb["lent_at"])
+ lent_at = isoparse(umb["lent_at"])
except TypeError:
# or it could be a datetime.datetime
lent_at = umb["lent_at"]
@@ -132,16 +141,20 @@ class Umbrellas:
# anything else is invalid
raise UmbrellaValueError("lent_at")
- if lent_at.tzinfo.utcoffset(None).seconds != 28800:
- # timezone must be +08:00
- raise UmbrellaValueError("lent_at")
+ if lent_at.tzinfo is None:
+ lent_at = lent_at.replace(tzinfo=CST)
- diff["lent_at"] = (umb_in_db["lent_at"], lent_at.isoformat(timespec="milliseconds"))
+ diff["lent_at"] = (
+ umb_in_db["lent_at"],
+ lent_at.isoformat(timespec="milliseconds"),
+ )
db.execute(
"UPDATE Umbrellas SET lent_at = ? WHERE id = ?",
- ( lent_at.isoformat(timespec="milliseconds"),
- umbid,)
+ (
+ lent_at.isoformat(timespec="milliseconds"),
+ umbid,
+ ),
)
else:
# discard unneeded fields
@@ -152,7 +165,7 @@ class Umbrellas:
"tenant_email",
"lent_at",
):
- db.execute("UPDATE Umbrellas SET ? = NULL WHERE id = ?", (col, umbid))
+ db.execute(f"UPDATE Umbrellas SET {col} = '' WHERE id = ?", (umbid,))
# now that new data are validated, commit the SQL transaction
db.commit()