Jun 24 - Update API to support Issue resolve photos
This commit is contained in:
@@ -433,3 +433,64 @@ def update_issue_photos(issue_id):
|
|||||||
issue.id, len(new_photos), user.username)
|
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)})
|
||||||
|
|
||||||
|
# ── Attach Resolution Photos (mobile) ─────────────────────────────────────────
|
||||||
|
|
||||||
|
@bp.route('/issues/<int:issue_id>/result_photos', methods=['PATCH'])
|
||||||
|
@jwt_required
|
||||||
|
def update_issue_result_photos(issue_id):
|
||||||
|
"""
|
||||||
|
Attach resolution photos to an issue from the mobile app.
|
||||||
|
|
||||||
|
Called when an inspector marks an issue resolved and uploads photos
|
||||||
|
showing the fix. Stored in Issue.result_photos so they appear under
|
||||||
|
"Resolution Details" on the web — identical to photos uploaded via the
|
||||||
|
web update form.
|
||||||
|
|
||||||
|
Request JSON
|
||||||
|
------------
|
||||||
|
{ "result_photos": ["uploads/issue_result_photos/a.jpg", ...] }
|
||||||
|
|
||||||
|
Response 200
|
||||||
|
------------
|
||||||
|
{ "ok": true, "data": { "issue_id": 99, "result_photos_count": 2 } }
|
||||||
|
"""
|
||||||
|
user = g.api_user
|
||||||
|
if user.role not in _ALLOWED_ROLES:
|
||||||
|
return api_error('Access denied', 403)
|
||||||
|
|
||||||
|
issue = db.session.get(Issue, issue_id)
|
||||||
|
if issue is None:
|
||||||
|
return api_error('Issue not found', 404)
|
||||||
|
|
||||||
|
if user.role == 'inspector':
|
||||||
|
fids = get_inspector_scope(user)
|
||||||
|
facility = issue.resolved_facility
|
||||||
|
if not fids or not facility or facility.id not in fids:
|
||||||
|
return api_error('Access denied', 403)
|
||||||
|
|
||||||
|
data = request.get_json(silent=True) or {}
|
||||||
|
raw = data.get('result_photos')
|
||||||
|
|
||||||
|
if not isinstance(raw, list):
|
||||||
|
return api_error('result_photos must be a list of path strings', 400)
|
||||||
|
|
||||||
|
new_photos = [p for p in raw if isinstance(p, str) and p.strip()]
|
||||||
|
if not new_photos:
|
||||||
|
return api_error('result_photos must contain at least one valid path', 400)
|
||||||
|
|
||||||
|
# Merge idempotently with any existing result_photos
|
||||||
|
existing = issue.result_photos or []
|
||||||
|
merged = existing + [p for p in new_photos if p not in existing]
|
||||||
|
issue.result_photos = merged
|
||||||
|
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
log_action(ACTION_UPDATE, 'Issue', issue.id,
|
||||||
|
f'result_photos updated (+{len(new_photos)} photos)',
|
||||||
|
f'source=mobile; updated_by={user.username}')
|
||||||
|
|
||||||
|
logger.info('API ISSUES | result_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)})
|
||||||
|
|||||||
+3
-1
@@ -46,7 +46,7 @@ def upload_photo():
|
|||||||
Multipart form fields
|
Multipart form fields
|
||||||
---------------------
|
---------------------
|
||||||
file — binary image data (jpg / png / gif)
|
file — binary image data (jpg / png / gif)
|
||||||
entity_type — "inspection" | "issue" (controls subfolder)
|
entity_type — "inspection" | "issue" | "issue_result" (controls subfolder)
|
||||||
|
|
||||||
Response 200
|
Response 200
|
||||||
------------
|
------------
|
||||||
@@ -80,6 +80,8 @@ def upload_photo():
|
|||||||
# Determine destination subfolder
|
# Determine destination subfolder
|
||||||
if entity_type == 'issue':
|
if entity_type == 'issue':
|
||||||
subfolder = 'issue_photos'
|
subfolder = 'issue_photos'
|
||||||
|
elif entity_type == 'issue_result':
|
||||||
|
subfolder = 'issue_result_photos'
|
||||||
else:
|
else:
|
||||||
subfolder = 'inspection_photos'
|
subfolder = 'inspection_photos'
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user