| Server IP : 216.92.14.13 / Your IP : 216.73.217.126 Web Server : Apache System : Linux vps4089.pairvps.com 5.15.0-190-generic #200-Ubuntu SMP Fri Aug 7 15:06:04 UTC 2026 x86_64 User : rmlac2fmr ( 1040637) PHP Version : 8.2.32 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : ON | Pkexec : ON Directory : /usr/home/rmlac2fmr/ |
Upload File : |
#!/usr/bin/env python3
"""
Repair hotel bookings that were created without a name by the old
assign-from-Need-Room flow (and merge the leftover "shell" duplicate).
For the active show, for each crew member:
- Backfill LAST/FIRST name, dept and title from their crew profile onto
any assigned booking that is missing them.
- If a person has BOTH a hotel-assigned booking (hotel name filled) AND a
leftover shell (assigned, no hotel name), copy the shell's dates/room type
onto the real booking where missing, then drop the redundant shell.
- A person with only a shell (not yet assigned a hotel) is left alone — they
still belong in Need Room.
Safety:
- Writes a timestamped backup of db.json before changing anything.
- Idempotent: safe to run more than once.
After running: restart the app, then have everyone hard-refresh so no stale
browser tab re-saves an old copy.
Run: python3 ~/repair_hotel_names.py
"""
import json, os, shutil, datetime
DB_PATH = os.path.expanduser("~/public_html/jn.com/ops/data/db.json")
SHOW = "S3" # ACF2026. Change to "S2" for NMDC, etc.
# --- backup first ---
stamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
backup = f"{DB_PATH}.bak.{stamp}"
shutil.copy2(DB_PATH, backup)
print(f"Backup written: {backup}")
with open(DB_PATH, "r", encoding="utf-8") as f:
db = json.load(f)
persons = {p.get("id"): p for p in db.get("persons", [])}
bookings = db.get("hotelBookings", [])
def has_name(h):
return bool((h.get("lastName") or "").strip() or (h.get("firstName") or "").strip())
def has_hotel(h):
return bool((h.get("hotel") or "").strip())
def blank(v):
return v is None or str(v).strip() == ""
# Group this show's bookings by person
by_person = {}
for h in bookings:
if h.get("showId") != SHOW:
continue
by_person.setdefault(h.get("personId"), []).append(h)
remove_ids = set()
name_fixes = 0
merges = 0
for pid, hbs in by_person.items():
p = persons.get(pid)
# 1) Backfill name/dept/title from the crew profile
for h in hbs:
if p and not has_name(h):
h["lastName"] = h.get("lastName") or p.get("lastName", "")
h["firstName"] = h.get("firstName") or p.get("firstName", "")
h["dept"] = h.get("dept") or p.get("dept", "")
h["title"] = h.get("title") or p.get("title", "")
name_fixes += 1
# 2) Merge a leftover shell into the real (hotel-assigned) booking
assigned = [h for h in hbs if h.get("assigned")]
real = [h for h in assigned if has_hotel(h)]
shells = [h for h in assigned if not has_hotel(h)]
if real and shells:
primary = real[0]
for sh in shells:
if blank(primary.get("checkIn")) and not blank(sh.get("checkIn")):
primary["checkIn"] = sh.get("checkIn")
if blank(primary.get("checkOut")) and not blank(sh.get("checkOut")):
primary["checkOut"] = sh.get("checkOut")
if blank(primary.get("roomType")) and not blank(sh.get("roomType")):
primary["roomType"] = sh.get("roomType")
if blank(primary.get("notesForHotel")) and not blank(sh.get("notesForHotel")):
primary["notesForHotel"] = sh.get("notesForHotel")
remove_ids.add(sh.get("id"))
merges += 1
# Drop the redundant shells
before = len(db["hotelBookings"])
db["hotelBookings"] = [h for h in db["hotelBookings"] if h.get("id") not in remove_ids]
after = len(db["hotelBookings"])
with open(DB_PATH, "w", encoding="utf-8") as f:
json.dump(db, f, indent=2)
print(f"\nName/dept/title backfilled on : {name_fixes} booking(s)")
print(f"Redundant shells merged+removed: {merges} ({before - after} record(s) deleted)")
print("\nAffected crew (show {}):".format(SHOW))
for pid, hbs in by_person.items():
p = persons.get(pid)
nm = f"{p.get('lastName','')}, {p.get('firstName','')}".strip(", ") if p else "(no profile)"
kept = [h for h in hbs if h.get("id") not in remove_ids and h.get("showId") == SHOW]
for h in kept:
if has_hotel(h):
print(f" {nm:30} {h.get('hotel','')[:28]:28} "
f"{h.get('checkIn','')} -> {h.get('checkOut','')}")
print("\nDone. Restart the app, then hard-refresh all open tabs.")