package test // import ( // "encoding/json" // "fmt" // "net/http" // "net/url" // "testing" // "github.com/gofiber/fiber/v2" // "gitlab.com/mbugroup/lti-api.git/internal/entities" // "gitlab.com/mbugroup/lti-api.git/internal/utils" // ) // func TestProjectFlockSummary(t *testing.T) { // app, db := setupIntegrationApp(t) // areaID := createArea(t, app, "Area Project") // locationID := createLocation(t, app, "Location Project", "Address", areaID) // flockID := createFlock(t, app, "Flock Summary") // 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, // "category": "growing", // "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"` // Category string `json:"category"` // Flock struct { // Id uint `json:"id"` // Name string `json:"name"` // } `json:"flock"` // Area struct { // Id uint `json:"id"` // Name string `json:"name"` // } `json:"area"` // 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.Category != string(utils.ProjectFlockCategoryGrowing) { // t.Fatalf("expected category to be %s, got %s", utils.ProjectFlockCategoryGrowing, createResp.Data.Category) // } // 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.Kandangs[0].Status != string(utils.KandangStatusPengajuan) { // t.Fatalf("expected kandang status to be PENGAJUAN, got %s", createResp.Data.Kandangs[0].Status) // } // if createResp.Data.Period != 1 { // t.Fatalf("expected period 1 to be assigned automatically, got %d", createResp.Data.Period) // } // createdKandang := fetchKandang(t, db, kandangID) // if createdKandang.Status != string(utils.KandangStatusPengajuan) { // t.Fatalf("expected kandang status in DB to be PENGAJUAN, got %s", createdKandang.Status) // } // var pivotRecords []entities.ProjectFlockKandang // if err := db.Where("project_flock_id = ?", createResp.Data.Id).Find(&pivotRecords).Error; err != nil { // t.Fatalf("failed to fetch pivot records: %v", err) // } // if len(pivotRecords) != 1 { // t.Fatalf("expected 1 pivot record, got %d", len(pivotRecords)) // } // firstPivotRecord := pivotRecords[0] // if firstPivotRecord.KandangId != kandangID { // t.Fatalf("expected pivot kandang id %d, got %d", kandangID, firstPivotRecord.KandangId) // } // secondKandangID := createKandang(t, app, "Kandang Summary 2", locationID, 1) // secondPayload := map[string]any{ // "flock_id": flockID, // "area_id": areaID, // "category": "laying", // "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"` // Category string `json:"category"` // } `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) // } // if createRespSecond.Data.Category != string(utils.ProjectFlockCategoryLaying) { // t.Fatalf("expected category to be %s, got %s", utils.ProjectFlockCategoryLaying, createRespSecond.Data.Category) // } // pivotRecords = nil // if err := db.Where("project_flock_id = ?", createRespSecond.Data.Id).Find(&pivotRecords).Error; err != nil { // t.Fatalf("failed to fetch second pivot records: %v", err) // } // if len(pivotRecords) != 1 { // t.Fatalf("expected 1 pivot record for second project, got %d", len(pivotRecords)) // } // secondPivotRecord := pivotRecords[0] // if secondPivotRecord.KandangId != secondKandangID { // t.Fatalf("expected second pivot kandang id %d, got %d", secondKandangID, secondPivotRecord.KandangId) // } // secondKandang := fetchKandang(t, db, secondKandangID) // if secondKandang.Status != string(utils.KandangStatusPengajuan) { // t.Fatalf("expected second kandang status in DB to be PENGAJUAN, got %s", secondKandang.Status) // } // 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)) // } // firstKandang := fetchKandang(t, db, kandangID) // if firstKandang.ProjectFlockId != nil { // t.Fatalf("expected project_flock_id to be nil after delete, got %v", *firstKandang.ProjectFlockId) // } // if firstKandang.Status != string(utils.KandangStatusNonActive) { // t.Fatalf("expected kandang status to revert to NON_ACTIVE, got %s", firstKandang.Status) // } // var remainingFirst int64 // if err := db.Model(&entities.ProjectFlockKandang{}). // Where("project_flock_id = ? AND kandang_id = ?", createResp.Data.Id, kandangID). // Count(&remainingFirst).Error; err != nil { // t.Fatalf("failed to count first pivot records after delete: %v", err) // } // if remainingFirst != 0 { // t.Fatalf("expected no pivot records remaining after delete, found %d", remainingFirst) // } // 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)) // } // secondKandang = fetchKandang(t, db, secondKandangID) // if secondKandang.ProjectFlockId != nil { // t.Fatalf("expected second project_flock_id to be nil after delete, got %v", *secondKandang.ProjectFlockId) // } // if secondKandang.Status != string(utils.KandangStatusNonActive) { // t.Fatalf("expected second kandang status to revert to NON_ACTIVE, got %s", secondKandang.Status) // } // var remainingSecond int64 // if err := db.Model(&entities.ProjectFlockKandang{}). // Where("project_flock_id = ? AND kandang_id = ?", createRespSecond.Data.Id, secondKandangID). // Count(&remainingSecond).Error; err != nil { // t.Fatalf("failed to count second pivot records after delete: %v", err) // } // if remainingSecond != 0 { // t.Fatalf("expected no second pivot records remaining after delete, found %d", remainingSecond) // } // 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) // } // func TestProjectFlockSearchByRelatedFields(t *testing.T) { // app, _ := setupIntegrationApp(t) // areaID := createArea(t, app, "Area Search Target") // locationID := createLocation(t, app, "Location Search Target", "Location Address Target", areaID) // flockID := createFlock(t, app, "Flock Search Target") // fcrID := createFcr(t, app, "FCR Search Target", []map[string]any{ // {"weight": 1.0, "fcr_number": 1.5, "mortality": 2.0}, // }) // kandangID := createKandang(t, app, "Kandang Search Target", locationID, 1) // createPayload := map[string]any{ // "flock_id": flockID, // "area_id": areaID, // "category": "growing", // "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"` // } `json:"data"` // } // if err := json.Unmarshal(body, &createResp); err != nil { // t.Fatalf("failed to parse create response: %v", err) // } // searchTerms := []string{ // "Flock Search Target", // "Area Search Target", // string(utils.ProjectFlockCategoryGrowing), // "growing", // "FCR Search Target", // "Kandang Search Target", // "Location Search Target", // "Location Address Target", // "Tester", // "1", // } // for _, term := range searchTerms { // path := "/api/production/project_flocks?search=" + url.QueryEscape(term) // resp, body := doJSONRequest(t, app, http.MethodGet, path, nil) // if resp.StatusCode != fiber.StatusOK { // t.Fatalf("expected 200 when searching for %q, got %d: %s", term, resp.StatusCode, string(body)) // } // var listResp struct { // Data []struct { // Id uint `json:"id"` // } `json:"data"` // Meta struct { // TotalResults int64 `json:"total_results"` // } `json:"meta"` // } // if err := json.Unmarshal(body, &listResp); err != nil { // t.Fatalf("failed to parse list response for %q: %v", term, err) // } // if listResp.Meta.TotalResults == 0 { // t.Fatalf("expected at least one result when searching for %q", term) // } // if len(listResp.Data) == 0 { // t.Fatalf("expected data when searching for %q", term) // } // if listResp.Data[0].Id != createResp.Data.Id { // t.Fatalf("expected project flock id %d for search term %q, got %d", createResp.Data.Id, term, listResp.Data[0].Id) // } // } // } // func TestProjectFlockSorting(t *testing.T) { // app, _ := setupIntegrationApp(t) // areaA := createArea(t, app, "Area Alpha") // areaB := createArea(t, app, "Area Beta") // locationA := createLocation(t, app, "Location Alpha", "Address Alpha", areaA) // locationB := createLocation(t, app, "Location Beta", "Address Beta", areaB) // flockOne := createFlock(t, app, "Flock Sort One") // flockTwo := createFlock(t, app, "Flock Sort Two") // fcrID := createFcr(t, app, "FCR Sort", []map[string]any{ // {"weight": 1.0, "fcr_number": 1.5, "mortality": 2.0}, // }) // kandangOne := createKandang(t, app, "Kandang Sort One", locationA, 1) // kandangTwo := createKandang(t, app, "Kandang Sort Two", locationB, 1) // kandangThree := createKandang(t, app, "Kandang Sort Three", locationB, 1) // projectOnePayload := map[string]any{ // "flock_id": flockOne, // "area_id": areaA, // "category": "growing", // "fcr_id": fcrID, // "location_id": locationA, // "kandang_ids": []uint{kandangOne}, // } // resp, body := doJSONRequest(t, app, http.MethodPost, "/api/production/project_flocks", projectOnePayload) // if resp.StatusCode != fiber.StatusCreated { // t.Fatalf("expected 201 for project one, got %d: %s", resp.StatusCode, string(body)) // } // projectOneID := parseProjectFlockID(t, body) // projectTwoPayload := map[string]any{ // "flock_id": flockTwo, // "area_id": areaB, // "category": "laying", // "fcr_id": fcrID, // "location_id": locationB, // "kandang_ids": []uint{kandangTwo, kandangThree}, // } // resp, body = doJSONRequest(t, app, http.MethodPost, "/api/production/project_flocks", projectTwoPayload) // if resp.StatusCode != fiber.StatusCreated { // t.Fatalf("expected 201 for project two, got %d: %s", resp.StatusCode, string(body)) // } // projectTwoID := parseProjectFlockID(t, body) // updatePeriodPayload := map[string]any{"period": 5} // resp, body = doJSONRequest(t, app, http.MethodPatch, "/api/production/project_flocks/"+uintToString(projectTwoID), updatePeriodPayload) // if resp.StatusCode != fiber.StatusOK { // t.Fatalf("expected 200 when updating period, got %d: %s", resp.StatusCode, string(body)) // } // assertOrder := func(t *testing.T, app *fiber.App, query string, expectedFirst uint) { // t.Helper() // resp, body := doJSONRequest(t, app, http.MethodGet, "/api/production/project_flocks?"+query, nil) // if resp.StatusCode != fiber.StatusOK { // t.Fatalf("expected 200 for query %q, got %d: %s", query, resp.StatusCode, string(body)) // } // var listResp struct { // Data []struct { // Id uint `json:"id"` // } `json:"data"` // } // if err := json.Unmarshal(body, &listResp); err != nil { // t.Fatalf("failed to parse list response for %q: %v", query, err) // } // if len(listResp.Data) == 0 { // t.Fatalf("expected data for query %q", query) // } // if listResp.Data[0].Id != expectedFirst { // t.Fatalf("expected first id %d for query %q, got %d", expectedFirst, query, listResp.Data[0].Id) // } // } // assertOrder(t, app, "sort_by=area&sort_order=asc", projectOneID) // assertOrder(t, app, "sort_by=location&sort_order=desc", projectTwoID) // assertOrder(t, app, "sort_by=period&sort_order=desc", projectTwoID) // assertOrder(t, app, "sort_by=kandangs&sort_order=desc", projectTwoID) // assertOrder(t, app, "sort_by=kandangs&sort_order=asc", projectOneID) // } // func parseProjectFlockID(t *testing.T, body []byte) uint { // t.Helper() // var resp struct { // Data struct { // Id uint `json:"id"` // } `json:"data"` // } // if err := json.Unmarshal(body, &resp); err != nil { // t.Fatalf("failed to parse project flock response: %v", err) // } // return resp.Data.Id // }