refactor(uploads): drop legacy multipart code paths
Backend CI / Test (push) Has been cancelled
Backend CI / Contract Tests (push) Has been cancelled
Backend CI / Build (push) Has been cancelled
Backend CI / Lint (push) Has been cancelled
Backend CI / Secret Scanning (push) Has been cancelled

The presigned-URL upload flow (POST /api/uploads/presign + direct B2 POST
+ upload_ids[] in entity creation) is now the only image upload path. The
legacy multipart routes and DTO fields used by older clients are removed:

Removed:
  - POST /api/uploads/image/        (legacy multipart upload → URL)
  - POST /api/uploads/document/     (legacy multipart upload → URL)
  - POST /api/uploads/completion/   (legacy multipart upload → URL)
  - Multipart branch in POST /api/task-completions/ (now JSON-only)
  - CreateTaskCompletionRequest.ImageURLs DTO field
  - UpdateTaskCompletionRequest.ImageURLs DTO field
  - CreateDocumentRequest.ImageURLs DTO field
  - Service-layer ImageURLs loops in task_service.CreateCompletion,
    task_service.UpdateCompletion, document_service.CreateDocument
  - Tests exercising the removed paths
  - Now-unused imports (strings/time/decimal) in task_handler.go

Kept:
  - DELETE /api/uploads/  (orphan-cleanup endpoint, still useful)
  - POST /api/uploads/presign/  (the new path)
  - POST /api/documents/:id/images/  (uses storage_service.Upload directly,
    same multipart pattern but separate code path; deferred for now)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Trey t
2026-05-01 15:19:21 -07:00
parent 29c9014a33
commit b7f83293b8
9 changed files with 43 additions and 261 deletions
+6 -41
View File
@@ -70,26 +70,10 @@ func TestDocumentService_CreateDocument_DefaultType(t *testing.T) {
assert.Equal(t, models.DocumentTypeGeneral, resp.DocumentType)
}
func TestDocumentService_CreateDocument_WithImages(t *testing.T) {
db := testutil.SetupTestDB(t)
documentRepo := repositories.NewDocumentRepository(db)
residenceRepo := repositories.NewResidenceRepository(db)
service := NewDocumentService(documentRepo, residenceRepo)
user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123")
residence := testutil.CreateTestResidence(t, db, user.ID, "Test House")
req := &requests.CreateDocumentRequest{
ResidenceID: residence.ID,
Title: "Receipt with photos",
ImageURLs: []string{"https://example.com/img1.jpg", "https://example.com/img2.jpg"},
}
resp, err := service.CreateDocument(context.Background(), req, user.ID)
require.NoError(t, err)
assert.NotNil(t, resp)
assert.Equal(t, "Receipt with photos", resp.Title)
}
// TestDocumentService_CreateDocument_WithImages was removed alongside the
// legacy ImageURLs field. The presigned-URL flow is exercised end-to-end
// in the integration tests; mocking B2 + a pending_uploads fixture for a
// unit test was deemed not worth the complexity.
func TestDocumentService_CreateDocument_AccessDenied(t *testing.T) {
db := testutil.SetupTestDB(t)
@@ -630,27 +614,8 @@ func TestDocumentService_ActivateDocument_AccessDenied(t *testing.T) {
testutil.AssertAppError(t, err, http.StatusForbidden, "error.document_access_denied")
}
// === CreateDocument — with empty image URL in array (should skip) ===
func TestDocumentService_CreateDocument_WithEmptyImageURL(t *testing.T) {
db := testutil.SetupTestDB(t)
documentRepo := repositories.NewDocumentRepository(db)
residenceRepo := repositories.NewResidenceRepository(db)
service := NewDocumentService(documentRepo, residenceRepo)
user := testutil.CreateTestUser(t, db, "owner", "owner@test.com", "Password123")
residence := testutil.CreateTestResidence(t, db, user.ID, "Test House")
req := &requests.CreateDocumentRequest{
ResidenceID: residence.ID,
Title: "Doc with empty images",
ImageURLs: []string{"", "https://example.com/img.jpg", ""},
}
resp, err := service.CreateDocument(context.Background(), req, user.ID)
require.NoError(t, err)
assert.NotNil(t, resp)
}
// TestDocumentService_CreateDocument_WithEmptyImageURL was removed alongside
// the legacy ImageURLs field — empty-URL filtering is no longer a code path.
// === UpdateDocument — all optional fields ===