package handler import ( "time" "github.com/gin-gonic/gin" "github.com/kennethcheng/fuellog-api/internal/dto" "github.com/kennethcheng/fuellog-api/internal/model" "github.com/kennethcheng/fuellog-api/internal/service" ) // RefuelHandler 加油记录路由。 type RefuelHandler struct{ svc service.RefuelRecordService } func NewRefuelHandler(svc service.RefuelRecordService) *RefuelHandler { return &RefuelHandler{svc: svc} } // POST /api/refuels func (h *RefuelHandler) Create(c *gin.Context) { var in dto.RefuelCreate if err := bindJSON(c, &in); err != nil { writeError(c, err) return } rec, err := h.svc.Create(c.Request.Context(), &in) if err != nil { writeError(c, err) return } sendJSON(c, rec) } // GET /api/refuels/:id func (h *RefuelHandler) Get(c *gin.Context) { id, err := parseUint64(c, "id") if err != nil { writeError(c, err) return } rec, err := h.svc.Get(c.Request.Context(), id) if err != nil { writeError(c, err) return } sendJSON(c, rec) } // PUT /api/refuels/:id func (h *RefuelHandler) Update(c *gin.Context) { id, err := parseUint64(c, "id") if err != nil { writeError(c, err) return } var in dto.RefuelUpdate if err := bindJSON(c, &in); err != nil { writeError(c, err) return } rec, err := h.svc.Update(c.Request.Context(), id, &in) if err != nil { writeError(c, err) return } sendJSON(c, rec) } // DELETE /api/refuels/:id func (h *RefuelHandler) Delete(c *gin.Context) { id, err := parseUint64(c, "id") if err != nil { writeError(c, err) return } if err := h.svc.Delete(c.Request.Context(), id); err != nil { writeError(c, err) return } c.Status(204) } // GET /api/refuels?vehicle_id=...&start_date=...&end_date=... func (h *RefuelHandler) List(c *gin.Context) { vehicleIDStr := c.Query("vehicle_id") if vehicleIDStr == "" { writeError(c, errInvalidVehicleID()) return } vehicleID, err := parseUint64Query(vehicleIDStr) if err != nil { writeError(c, err) return } var startPtr, endPtr *time.Time if s := c.Query("start_date"); s != "" { t, err := time.Parse(time.RFC3339, s) if err != nil { writeError(c, errInvalid("start_date 需为 RFC3339 时间")) return } startPtr = &t } if s := c.Query("end_date"); s != "" { t, err := time.Parse(time.RFC3339, s) if err != nil { writeError(c, errInvalid("end_date 需为 RFC3339 时间")) return } endPtr = &t } records, err := h.svc.ListByVehicle(c.Request.Context(), vehicleID, startPtr, endPtr) if err != nil { writeError(c, err) return } if records == nil { records = []model.RefuelRecord{} } sendJSON(c, records) } // GET /api/vehicles/:id/statistics func (h *RefuelHandler) Statistics(c *gin.Context) { vehicleID, err := parseUint64(c, "id") if err != nil { writeError(c, err) return } stats, err := h.svc.Statistics(c.Request.Context(), vehicleID) if err != nil { writeError(c, err) return } sendJSON(c, stats) } func parseUint64Query(s string) (uint64, error) { v, err := parseUint64Impl(s) if err != nil { return 0, errInvalid("vehicle_id 必须是正整数") } return v, nil } func parseUint64Impl(s string) (uint64, error) { var v uint64 for _, c := range s { if c < '0' || c > '9' { return 0, errInvalid("非数字字符") } v = v*10 + uint64(c-'0') } if v == 0 { return 0, errInvalid("id 不能为 0") } return v, nil }