feat(postcard): profile country, country_from, per-user card number uniqueness, public page overhaul - Profile: add country field for default origin country - Postcard: add country_from field, auto-fill from profile.country on create - card_number uniqueness: change from global to per-user (profile_id + card_number) - Public pages: remove card_number display, only show cards with image_front - Public pages: show country as from→to format - Index page: no time display, add register button, fix lightbox with prev/next - Infinite scroll: add /api/public/cards endpoints and IntersectionObserver - Internal pages: update postcards list/detail for country_from display - i18n: add profiles.country_ph, pc_form.country_from, pc_detail.route
This commit is contained in:
@@ -81,13 +81,16 @@ def get_api_user_optional(
|
||||
|
||||
class ProfileCreate(BaseModel):
|
||||
nickname: str
|
||||
country: str | None = None
|
||||
|
||||
class ProfileUpdate(BaseModel):
|
||||
nickname: str | None = None
|
||||
country: str | None = None
|
||||
|
||||
class ProfileOut(BaseModel):
|
||||
id: int
|
||||
nickname: str
|
||||
country: str | None
|
||||
showcase_enabled: bool
|
||||
showcase_visible: str
|
||||
notes: str
|
||||
@@ -101,6 +104,7 @@ class PostcardCreate(BaseModel):
|
||||
status: str
|
||||
recipient_name: str | None = None
|
||||
country: str | None = None
|
||||
country_from: str | None = None
|
||||
send_time: str | None = None
|
||||
arrival_time: str | None = None
|
||||
sender_name: str | None = None
|
||||
@@ -112,6 +116,7 @@ class PostcardUpdate(BaseModel):
|
||||
status: str | None = None
|
||||
recipient_name: str | None = None
|
||||
country: str | None = None
|
||||
country_from: str | None = None
|
||||
send_time: str | None = None
|
||||
arrival_time: str | None = None
|
||||
sender_name: str | None = None
|
||||
@@ -125,6 +130,7 @@ class PostcardOut(BaseModel):
|
||||
status: str
|
||||
recipient_name: str | None
|
||||
country: str | None
|
||||
country_from: str | None
|
||||
send_time: datetime | None
|
||||
arrival_time: datetime | None
|
||||
sender_name: str | None
|
||||
@@ -205,7 +211,8 @@ def create_profile(
|
||||
db: DbSession = Depends(get_db),
|
||||
ak: ApiKey = Depends(require_scopes(PERM_PROFILES_WRITE)),
|
||||
):
|
||||
p = Profile(nickname=body.nickname.strip(), user_id=ak.user_id)
|
||||
c = body.country.strip().upper() if body.country else None
|
||||
p = Profile(nickname=body.nickname.strip(), user_id=ak.user_id, country=c)
|
||||
db.add(p)
|
||||
db.commit()
|
||||
db.refresh(p)
|
||||
@@ -231,6 +238,8 @@ def update_profile(
|
||||
p = _profile_or_404(ak.user, profile_id, db)
|
||||
if body.nickname is not None:
|
||||
p.nickname = body.nickname.strip()
|
||||
if body.country is not None:
|
||||
p.country = body.country.strip().upper() if body.country else None
|
||||
db.commit()
|
||||
db.refresh(p)
|
||||
return p
|
||||
@@ -275,7 +284,10 @@ def create_postcard(
|
||||
):
|
||||
_profile_or_404(ak.user, profile_id, db)
|
||||
cn = body.card_number.strip()
|
||||
if db.query(Postcard).filter(Postcard.card_number == cn).first():
|
||||
dup = db.query(Postcard).join(Profile).filter(
|
||||
Postcard.card_number == cn, Profile.user_id == ak.user.id
|
||||
).first()
|
||||
if dup:
|
||||
raise HTTPException(status_code=409, detail="Card number already exists")
|
||||
pc = Postcard(
|
||||
profile_id=profile_id,
|
||||
@@ -283,6 +295,7 @@ def create_postcard(
|
||||
status=body.status,
|
||||
recipient_name=body.recipient_name,
|
||||
country=body.country.strip().upper() if body.country else None,
|
||||
country_from=body.country_from.strip().upper() if body.country_from else None,
|
||||
send_time=_parse_date(body.send_time),
|
||||
arrival_time=_parse_date(body.arrival_time),
|
||||
sender_name=body.sender_name,
|
||||
@@ -320,12 +333,17 @@ def update_postcard(
|
||||
setattr(pc, field, val.strip() if isinstance(val, str) else val)
|
||||
if body.card_number is not None:
|
||||
cn = body.card_number.strip()
|
||||
dup = db.query(Postcard).filter(Postcard.card_number == cn, Postcard.id != postcard_id).first()
|
||||
dup = db.query(Postcard).join(Profile).filter(
|
||||
Postcard.card_number == cn, Postcard.id != postcard_id,
|
||||
Profile.user_id == ak.user.id
|
||||
).first()
|
||||
if dup:
|
||||
raise HTTPException(status_code=409, detail="Card number already exists")
|
||||
pc.card_number = cn
|
||||
if body.country is not None:
|
||||
pc.country = body.country.strip().upper() if body.country else None
|
||||
if body.country_from is not None:
|
||||
pc.country_from = body.country_from.strip().upper() if body.country_from else None
|
||||
for field in ("send_time", "arrival_time", "receive_time"):
|
||||
val = getattr(body, field)
|
||||
if val is not None:
|
||||
|
||||
Reference in New Issue
Block a user