package test import ( "encoding/json" "fmt" "net/http" "testing" "github.com/gofiber/fiber/v2" ) func TestProjectFlockSummary(t *testing.T) { app, _ := setupIntegrationApp(t) areaID := createArea(t, app, "Area Project") locationID := createLocation(t, app, "Location Project", "Address", areaID) flockID := createFlock(t, app, "Flock Summary") categoryID := createProductCategory(t, app, "DOC Summary", "DOCS") fcrID := createFcr(t, app, "FCR Summary", []map[string]any{ {"weight": 1.0, "fcr_number": 1.5, "mortality": 2.0}, }) kandangID := createKandang(t, app, "Kandang Summary", locationID, 1) createPayload := map[string]any{ "flock_id": flockID, "area_id": areaID, "product_category_id": categoryID, "fcr_id": fcrID, "location_id": locationID, "kandang_ids": []uint{kandangID}, } resp, body := doJSONRequest(t, app, http.MethodPost, "/api/production/project_flocks", createPayload) if resp.StatusCode != fiber.StatusCreated { t.Fatalf("expected 201 when creating project flock, got %d: %s", resp.StatusCode, string(body)) } var createResp struct { Data struct { Id uint `json:"id"` Period int `json:"period"` Flock struct { Id uint `json:"id"` Name string `json:"name"` } `json:"flock"` Area struct { Id uint `json:"id"` Name string `json:"name"` } `json:"area"` ProductCategory struct { Id uint `json:"id"` Name string `json:"name"` Code string `json:"code"` } `json:"product_category"` Fcr struct { Id uint `json:"id"` Name string `json:"name"` } `json:"fcr"` Location struct { Id uint `json:"id"` Name string `json:"name"` Address string `json:"address"` } `json:"location"` Kandangs []struct { Id uint `json:"id"` Name string `json:"name"` Status string `json:"status"` } `json:"kandangs"` CreatedUser struct { Id uint `json:"id"` IdUser uint `json:"id_user"` Email string `json:"email"` Name string `json:"name"` } `json:"created_user"` } `json:"data"` } if err := json.Unmarshal(body, &createResp); err != nil { t.Fatalf("failed to parse create response: %v", err) } if createResp.Data.Flock.Id != flockID || createResp.Data.Flock.Name == "" { t.Fatalf("expected flock detail to be present, got %+v", createResp.Data.Flock) } if createResp.Data.Area.Id != areaID || createResp.Data.Area.Name == "" { t.Fatalf("expected area detail to be present, got %+v", createResp.Data.Area) } if createResp.Data.Location.Id != locationID || createResp.Data.Location.Name == "" { t.Fatalf("expected location detail to be present, got %+v", createResp.Data.Location) } if len(createResp.Data.Kandangs) != 1 || createResp.Data.Kandangs[0].Id != kandangID { t.Fatalf("expected kandang detail to be present, got %+v", createResp.Data.Kandangs) } if createResp.Data.Period != 1 { t.Fatalf("expected period 1 to be assigned automatically, got %d", createResp.Data.Period) } secondKandangID := createKandang(t, app, "Kandang Summary 2", locationID, 1) secondPayload := map[string]any{ "flock_id": flockID, "area_id": areaID, "product_category_id": categoryID, "fcr_id": fcrID, "location_id": locationID, "kandang_ids": []uint{secondKandangID}, } resp, body = doJSONRequest(t, app, http.MethodPost, "/api/production/project_flocks", secondPayload) if resp.StatusCode != fiber.StatusCreated { t.Fatalf("expected 201 when creating second project flock, got %d: %s", resp.StatusCode, string(body)) } var createRespSecond struct { Data struct { Id uint `json:"id"` Period int `json:"period"` } `json:"data"` } if err := json.Unmarshal(body, &createRespSecond); err != nil { t.Fatalf("failed to parse second create response: %v", err) } if createRespSecond.Data.Period != 2 { t.Fatalf("expected second period to be 2, got %d", createRespSecond.Data.Period) } resp, body = doJSONRequest(t, app, http.MethodGet, "/api/production/project_flocks/flocks/"+uintToString(flockID)+"/periods", nil) if resp.StatusCode != fiber.StatusOK { t.Fatalf("expected 200 when fetching summary, got %d: %s", resp.StatusCode, string(body)) } var summary struct { Data struct { NextPeriod int `json:"next_period"` } `json:"data"` } if err := json.Unmarshal(body, &summary); err != nil { t.Fatalf("failed to parse summary response: %v", err) } if summary.Data.NextPeriod != 3 { t.Fatalf("expected next_period 3, got %d", summary.Data.NextPeriod) } resp, body = doJSONRequest(t, app, http.MethodDelete, "/api/production/project_flocks/"+uintToString(createResp.Data.Id), nil) if resp.StatusCode != fiber.StatusOK { t.Fatalf("expected 200 when deleting first project flock, got %d: %s", resp.StatusCode, string(body)) } resp, body = doJSONRequest(t, app, http.MethodDelete, "/api/production/project_flocks/"+uintToString(createRespSecond.Data.Id), nil) if resp.StatusCode != fiber.StatusOK { t.Fatalf("expected 200 when deleting second project flock, got %d: %s", resp.StatusCode, string(body)) } resp, body = doJSONRequest(t, app, http.MethodGet, "/api/production/project_flocks/flocks/"+uintToString(flockID)+"/periods", nil) if resp.StatusCode != fiber.StatusOK { t.Fatalf("expected 200 when fetching summary after delete, got %d: %s", resp.StatusCode, string(body)) } if err := json.Unmarshal(body, &summary); err != nil { t.Fatalf("failed to parse summary response after delete: %v", err) } if summary.Data.NextPeriod != 1 { t.Fatalf("expected next_period 1 after soft deletes, got %d", summary.Data.NextPeriod) } } func uintToString(v uint) string { return fmt.Sprintf("%d", v) }