package router import ( "strconv" "github.com/labstack/echo/v5" "github.com/pocketbase/pocketbase/apis" "github.com/pocketbase/pocketbase/core" "github.com/pocketbase/pocketbase/daos" "github.com/pocketbase/pocketbase/forms" "github.com/pocketbase/pocketbase/models" ) func (r *RouterContainer) bootstrapFarmerSurveyRoute() { r.PB.OnBeforeServe().Add(func(e *core.ServeEvent) error { e.Router.POST("/farmer", func(c echo.Context) error { requestData := struct { Phone string `json:"phone"` County string `json:"county" ` SubCounty string `json:"sub_county"` FarmingAreaAcres string `json:"farming_area_acres"` PlannedCrops []string `json:"planned_crops"` PastHarvestDetails []struct { CropType string `json:"crop_type"` AverageHarvest string `json:"average_harvest"` AverageEarning string `json:"average_earning"` } `json:"past_harvest_details"` TotalExpenditure string `json:"total_expenditure"` SeedsExpenditurePercentage string `json:"seeds_expenditure_percentage"` FertilizerExpenditurePercentage string `json:"fertilizer_expenditure_percentage"` CropsProtectionExpenditurePercentage string `json:"crops_protection_expenditure_percentage"` SyntheticFertilizersExpenditurePercentage string `json:"synthetic_fertilizers_expenditure_percentage"` NaturalFertilizersExpenditure string `json:"natural_fertilizers_expenditure_percentage"` IncreasedExpenses []struct { ExpenseType string `json:"expense_type"` IncreasedExpenseActions []string `json:"increased_expense_actions"` ExpenseActionOverallEffect string `json:"expense_action_overall_effect"` } `json:"increased_expenses"` EvergrowPast string `json:"evergrow_past"` EvergrowFirst string `json:"evergrow_first"` EvergrowApplication string `json:"evergrow_application"` EvergrowCrops []string `json:"evergrow_crops"` EvergrowYield string `json:"evergrow_yield"` OtherFertilizers string `json:"other_fertilizers"` PurchaseChannels []string `json:"purchase_channels"` OtherFertilizersDetails []struct { OtherFertilizerType string `json:"other_fertilizer_type"` OtherFertilizerApplication string `json:"other_fertilizer_application"` OtherFertilizerCrops []string `json:"other_fertilizer_crops"` } `json:"other_fertilizers_details"` }{} if err := c.Bind(&requestData); err != nil { return apis.NewBadRequestError("Failed to read request data", err) } budgetSplit, err := validatePercentage(requestData.CropsProtectionExpenditurePercentage, requestData.FertilizerExpenditurePercentage, requestData.SeedsExpenditurePercentage) if err != nil { return apis.NewBadRequestError("Could not validate budget split percentage", err) } if !budgetSplit { return apis.NewNotFoundError("Budget split percentage should add up to 100% ", err) } fertilizerSplit, err := validatePercentage(requestData.SyntheticFertilizersExpenditurePercentage, requestData.NaturalFertilizersExpenditure) if err != nil { return apis.NewBadRequestError("Could not validate fertilizer split percentage", err) } if !fertilizerSplit { return apis.NewNotFoundError("Fertilizer split percentage should add up to 100% ", err) } if err := r.PB.Dao().RunInTransaction(func(txDao *daos.Dao) error { userRecord, err := r.PB.Dao().FindFirstRecordByData("users", "phone", requestData.Phone) if err != nil { return apis.NewNotFoundError("Phone number not found", err) } if userRecord.GetString("participant_type") != "farmer" { return apis.NewNotFoundError("User is not registered as a farmer", err) } farmerFarmCollection, err := r.PB.Dao().FindCollectionByNameOrId("farmer_farm") if err != nil { return err } farmerFarmRecord := models.NewRecord(farmerFarmCollection) farmerFarmForm := forms.NewRecordUpsert(r.PB, farmerFarmRecord) farmerFarmForm.SetDao(txDao) farmerFarmForm.LoadData(map[string]any{ "user": userRecord.Id, "county": requestData.County, "sub_county": requestData.SubCounty, "farming_area_acres": requestData.FarmingAreaAcres, "planned_crops": requestData.PlannedCrops, }) if err := farmerFarmForm.Submit(); err != nil { return apis.NewBadRequestError("Failed to submit farm details", err) } farmerPastHarvestCollection, err := r.PB.Dao().FindCollectionByNameOrId("farmer_past_harvest") if err != nil { return err } for _, v := range requestData.PastHarvestDetails { farmerPastHarvestRecord := models.NewRecord(farmerPastHarvestCollection) farmerPastHarvestForm := forms.NewRecordUpsert(r.PB, farmerPastHarvestRecord) farmerPastHarvestForm.SetDao(txDao) farmerPastHarvestForm.LoadData(map[string]any{ "user": userRecord.Id, "crop": v.CropType, "average_harvest": v.AverageHarvest, "average_earning": v.AverageEarning, }) if err := farmerPastHarvestForm.Submit(); err != nil { return apis.NewBadRequestError("Failed to submit harvest details", err) } } farmerExpenditureBaseCollection, err := r.PB.Dao().FindCollectionByNameOrId("farmer_expenditure_base") if err != nil { return err } farmerExpenditureBaseRecord := models.NewRecord(farmerExpenditureBaseCollection) farmerExpenditureBaseFarmForm := forms.NewRecordUpsert(r.PB, farmerExpenditureBaseRecord) farmerExpenditureBaseFarmForm.SetDao(txDao) farmerExpenditureBaseFarmForm.LoadData(map[string]any{ "user": userRecord.Id, "total_expenditure": requestData.TotalExpenditure, "seeds_expenditure_percentage": requestData.SeedsExpenditurePercentage, "fertilizer_expenditure_percentage": requestData.FertilizerExpenditurePercentage, "crops_protection_expenditure_percentage": requestData.CropsProtectionExpenditurePercentage, "synthetic_fertilizers_expenditure_percentage": requestData.SyntheticFertilizersExpenditurePercentage, "natural_fertilizers_expenditure_percentage": requestData.NaturalFertilizersExpenditure, }) if err := farmerExpenditureBaseFarmForm.Submit(); err != nil { return apis.NewBadRequestError("Failed to submit expenditure base details", err) } farmerExpenditureIncreasedCollection, err := r.PB.Dao().FindCollectionByNameOrId("farmer_expenditure_increased") if err != nil { return err } for _, v := range requestData.IncreasedExpenses { farmerExpenditureIncreasedRecord := models.NewRecord(farmerExpenditureIncreasedCollection) farmerExpenditureIncreasedForm := forms.NewRecordUpsert(r.PB, farmerExpenditureIncreasedRecord) farmerExpenditureIncreasedForm.SetDao(txDao) farmerExpenditureIncreasedForm.LoadData(map[string]any{ "user": userRecord.Id, "expense": v.ExpenseType, "actions": v.IncreasedExpenseActions, "overall_effect": v.ExpenseActionOverallEffect, }) if err := farmerExpenditureIncreasedForm.Submit(); err != nil { return apis.NewBadRequestError("Failed to submit farmer expenditure increased details", err) } } farmerEvergrowCollection, err := r.PB.Dao().FindCollectionByNameOrId("farmer_evergrow") if err != nil { return err } farmerEvergrowRecord := models.NewRecord(farmerEvergrowCollection) farmerEvergrowForm := forms.NewRecordUpsert(r.PB, farmerEvergrowRecord) farmerEvergrowForm.SetDao(txDao) farmerEvergrowForm.LoadData(map[string]any{ "user": userRecord.Id, "evergrow_past": requestData.EvergrowPast, "evergrow_first": requestData.EvergrowFirst, "evergrow_application": requestData.EvergrowApplication, "evergrow_crops": requestData.EvergrowCrops, "evergrow_yield": requestData.EvergrowYield, "other_fertilizers": requestData.OtherFertilizers, "purchase_channels": requestData.PurchaseChannels, }) if err := farmerEvergrowForm.Submit(); err != nil { return apis.NewBadRequestError("Failed to submit evergrow details", err) } farmerOtherFertilizersCollection, err := r.PB.Dao().FindCollectionByNameOrId("farmer_other_fertilizers") if err != nil { return err } for _, v := range requestData.OtherFertilizersDetails { farmerOtherFertilizersRecord := models.NewRecord(farmerOtherFertilizersCollection) farmerOtherFertilizersForm := forms.NewRecordUpsert(r.PB, farmerOtherFertilizersRecord) farmerOtherFertilizersForm.SetDao(txDao) farmerOtherFertilizersForm.LoadData(map[string]any{ "user": userRecord.Id, "fertilizer_type": v.OtherFertilizerType, "fertilizer_application": v.OtherFertilizerApplication, "crops": v.OtherFertilizerCrops, }) if err := farmerOtherFertilizersForm.Submit(); err != nil { return apis.NewBadRequestError("Failed to submit other fertilizers details", err) } } return nil }); err != nil { c.JSON(400, map[string]any{"ok": "false", "error": err.Error()}) return nil } c.JSON(200, map[string]any{"ok": "true"}) return nil }) return nil }) } func validatePercentage(inputs ...string) (bool, error) { sum := 0 for _, numStr := range inputs { num, err := strconv.Atoi(numStr) if err != nil { return false, err } sum += num } return sum == 100, nil }