farmstar-survey-backend/internal/router/farmer.go

244 lines
9.6 KiB
Go

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
}