05/21 Fix issue with multiple photos 2

This commit is contained in:
Nguyen Ngo
2026-05-21 13:14:56 -04:00
parent 70f7978ce2
commit 1459b5316b
5 changed files with 114 additions and 45 deletions
+34 -37
View File
@@ -58,10 +58,12 @@ def _issue_payload(issue):
'reported_at': issue.reported_at.isoformat() if issue.reported_at else None,
'resolved_at': issue.resolved_at.isoformat() if issue.resolved_at else None,
'mobile_local_id': issue.mobile_local_id,
# photo_path is the primary issue photo; result_photos are resolution photos.
# Both are relative paths from the server static root.
'photo_path': issue.photo_path or None,
'result_photos': issue.result_photos or [],
# photo_path: primary evidence photo (first iPad photo).
# mobile_photo_paths: extra evidence photos from iPad (shown under Photo Evidence).
# result_photos: resolution photos added via the web update form.
'photo_path': issue.photo_path or None,
'mobile_photo_paths': issue.mobile_photo_paths or [],
'result_photos': issue.result_photos or [],
}
@@ -204,26 +206,24 @@ def create_issue():
inspection = None
# ── Create ────────────────────────────────────────────────────────────
# result_photos may be supplied by the mobile app as a list of paths that
# were already uploaded via /api/v1/photos/upload (one call per photo).
# Validate that it is a list of non-empty strings; silently drop bad entries.
raw_result_photos = data.get('result_photos')
if isinstance(raw_result_photos, list):
result_photos = [p for p in raw_result_photos if isinstance(p, str) and p.strip()]
else:
result_photos = []
# result_photos in the POST body = extra evidence photos from the iPad.
# Store in mobile_photo_paths (not result_photos) so they appear under
# "Photo Evidence" on the web, not "Resolution Details".
raw_mobile = data.get('result_photos')
mobile_photo_paths = [p for p in raw_mobile if isinstance(p, str) and p.strip()] \
if isinstance(raw_mobile, list) else []
issue = Issue(
inspection_id = inspection_id,
facility_id = facility_id,
severity = severity,
description = description,
photo_path = data.get('photo_path') or None,
result_photos = result_photos or None,
status = 'open',
reported_at = now_eastern(),
reported_by = user.id,
mobile_local_id = mobile_local_id,
inspection_id = inspection_id,
facility_id = facility_id,
severity = severity,
description = description,
photo_path = data.get('photo_path') or None,
mobile_photo_paths = mobile_photo_paths or None,
status = 'open',
reported_at = now_eastern(),
reported_by = user.id,
mobile_local_id = mobile_local_id,
)
db.session.add(issue)
db.session.flush() # get issue.id
@@ -352,17 +352,16 @@ def update_issue_status(issue_id):
@jwt_required
def update_issue_photos(issue_id):
"""
Attach additional photos to an existing issue created from the mobile app.
Attach additional evidence photos to an issue created from the mobile app.
Called by the iOS app immediately after create_issue when the inspector
attached more than one photo. The photos are already uploaded to the server
via /api/v1/photos/upload; this endpoint stores their paths in result_photos.
Called by the iOS app after create_issue when the inspector attached more
than one photo. Photos are already uploaded via /api/v1/photos/upload.
Stored in mobile_photo_paths so they display under "Photo Evidence" on the
web, not "Resolution Details".
Request JSON
------------
{
"result_photos": ["uploads/issue_photos/a.jpg", "uploads/issue_photos/b.jpg"]
}
{ "result_photos": ["uploads/issue_photos/a.jpg", "uploads/issue_photos/b.jpg"] }
Response 200
------------
@@ -376,12 +375,11 @@ def update_issue_photos(issue_id):
if issue is None:
return api_error('Issue not found', 404)
# Inspectors may only update issues they reported or are assigned to
if user.role == 'inspector' and issue.assigned_to != user.id and issue.reported_by != user.id:
return api_error('Access denied', 403)
data = request.get_json(silent=True) or {}
raw = data.get('result_photos')
raw = data.get('result_photos')
if not isinstance(raw, list):
return api_error('result_photos must be a list of path strings', 400)
@@ -390,19 +388,18 @@ def update_issue_photos(issue_id):
if not new_photos:
return api_error('result_photos must contain at least one valid path', 400)
# Merge with any existing result_photos rather than overwriting,
# so multiple PATCH calls (e.g. retry) are idempotent.
existing = issue.result_photos or []
# Merge idempotently with any existing mobile_photo_paths
existing = issue.mobile_photo_paths or []
merged = existing + [p for p in new_photos if p not in existing]
issue.result_photos = merged
issue.mobile_photo_paths = merged
db.session.commit()
log_action(ACTION_UPDATE, 'Issue', issue.id,
f'result_photos updated (+{len(new_photos)} photos)',
f'mobile_photo_paths updated (+{len(new_photos)} photos)',
f'source=mobile; updated_by={user.username}')
logger.info('API ISSUES | photos_updated | issue_id=%d | added=%d | user=%s',
issue.id, len(new_photos), user.username)
return api_ok({'issue_id': issue.id, 'result_photos_count': len(merged)})
return api_ok({'issue_id': issue.id, 'result_photos_count': len(merged)})