package vehicle import ( "errors" "math" "wails-app/internal/dao" "wails-app/internal/global" "wails-app/internal/model/vehicle/request" ) type FeeConfigService struct{} // validateFeeRules 校验收费规则的数值合法性,防止脏配置静默改变计费。 // 全零配置允许(显式免费),但单位时间必须大于 0,金额必须非负且有限。 func validateFeeRules(req request.FeeConfigCreate) error { if req.StartTime < 0 { return errors.New("免费时长不能为负数") } if req.UnitTime <= 0 { return errors.New("单位时间必须大于0分钟") } if req.StartFee < 0 || math.IsNaN(req.StartFee) || math.IsInf(req.StartFee, 0) { return errors.New("起步价必须为非负有限数值") } if req.UnitFee < 0 || math.IsNaN(req.UnitFee) || math.IsInf(req.UnitFee, 0) { return errors.New("单位费用必须为非负有限数值") } if req.DailyMaxFee < 0 || math.IsNaN(req.DailyMaxFee) || math.IsInf(req.DailyMaxFee, 0) { return errors.New("日封顶金额必须为非负有限数值") } if req.DailyMaxFee > 0 && req.DailyMaxFee < req.StartFee { return errors.New("日封顶金额不能低于起步价") } if req.VIPDiscount <= 0 || req.VIPDiscount > 1 || math.IsNaN(req.VIPDiscount) || math.IsInf(req.VIPDiscount, 0) { return errors.New("VIP折扣必须在(0,1]区间,如0.8表示八折") } if req.FreeExitMinutes < 0 { return errors.New("缴费后免费离场分钟数不能为负数") } return nil } // CreateFeeConfig 创建收费配置 func (s *FeeConfigService) CreateFeeConfig(req request.FeeConfigCreate) error { if err := validateFeeRules(req); err != nil { return err } // 检查车辆类型是否存在 var vehicleType dao.VehicleType result := global.GVA_DB.First(&vehicleType, req.VehicleTypeID) if result.RowsAffected == 0 { return errors.New("车辆类型不存在") } // 检查车辆类型是否已存在收费配置 var existingConfig dao.FeeConfig result = global.GVA_DB.Where("vehicle_type_id = ?", req.VehicleTypeID).First(&existingConfig) if result.RowsAffected > 0 { return errors.New("该车辆类型的收费配置已存在") } config := dao.FeeConfig{ VehicleTypeID: req.VehicleTypeID, StartTime: req.StartTime, StartFee: req.StartFee, UnitTime: req.UnitTime, UnitFee: req.UnitFee, DailyMaxFee: req.DailyMaxFee, FreeExitMinutes: req.FreeExitMinutes, IsVIPFree: req.IsVIPFree, VIPDiscount: req.VIPDiscount, Description: req.Description, } return global.GVA_DB.Create(&config).Error } // UpdateFeeConfig 更新收费配置 func (s *FeeConfigService) UpdateFeeConfig(req request.FeeConfigUpdate) error { if err := validateFeeRules(request.FeeConfigCreate{ VehicleTypeID: req.VehicleTypeID, StartTime: req.StartTime, StartFee: req.StartFee, UnitTime: req.UnitTime, UnitFee: req.UnitFee, DailyMaxFee: req.DailyMaxFee, FreeExitMinutes: req.FreeExitMinutes, IsVIPFree: req.IsVIPFree, VIPDiscount: req.VIPDiscount, Description: req.Description, }); err != nil { return err } var config dao.FeeConfig result := global.GVA_DB.First(&config, req.ID) if result.RowsAffected == 0 { return errors.New("收费配置不存在") } // 检查车辆类型是否存在 var vehicleType dao.VehicleType result = global.GVA_DB.First(&vehicleType, req.VehicleTypeID) if result.RowsAffected == 0 { return errors.New("车辆类型不存在") } // 检查车辆类型是否被其他配置使用 var existingConfig dao.FeeConfig result = global.GVA_DB.Where("vehicle_type_id = ? AND id != ?", req.VehicleTypeID, req.ID).First(&existingConfig) if result.RowsAffected > 0 { return errors.New("该车辆类型的收费配置已存在") } config.VehicleTypeID = req.VehicleTypeID config.StartTime = req.StartTime config.StartFee = req.StartFee config.UnitTime = req.UnitTime config.UnitFee = req.UnitFee config.DailyMaxFee = req.DailyMaxFee config.FreeExitMinutes = req.FreeExitMinutes config.IsVIPFree = req.IsVIPFree config.VIPDiscount = req.VIPDiscount config.Description = req.Description return global.GVA_DB.Save(&config).Error } // GetFeeConfigByID 根据ID获取收费配置 func (s *FeeConfigService) GetFeeConfigByID(id uint) (dao.FeeConfig, error) { var config dao.FeeConfig result := global.GVA_DB.First(&config, id) if result.RowsAffected == 0 { return dao.FeeConfig{}, errors.New("收费配置不存在") } return config, nil } // GetFeeConfigByVehicleType 根据车辆类型ID获取收费配置 func (s *FeeConfigService) GetFeeConfigByVehicleType(vehicleTypeID uint) (dao.FeeConfig, error) { var config dao.FeeConfig result := global.GVA_DB.Where("vehicle_type_id = ?", vehicleTypeID).First(&config) if result.RowsAffected == 0 { return dao.FeeConfig{}, errors.New("收费配置不存在") } return config, nil } // ListFeeConfigs 获取收费配置列表 func (s *FeeConfigService) ListFeeConfigs(req request.FeeConfigQuery) (int64, []dao.FeeConfig, error) { var configs []dao.FeeConfig var total int64 query := global.GVA_DB.Model(&dao.FeeConfig{}) if req.VehicleTypeID > 0 { query = query.Where("vehicle_type_id = ?", req.VehicleTypeID) } // 计算总数 query.Count(&total) // 分页兜底(gin 不解析 default 标签,Page/PageSize 可能为 0 或负数) if req.Page <= 0 { req.Page = 1 } if req.PageSize <= 0 { req.PageSize = 10 } offset := (req.Page - 1) * req.PageSize result := query.Offset(offset).Limit(req.PageSize).Preload("VehicleType").Find(&configs) if result.Error != nil { return 0, nil, result.Error } return total, configs, nil } // DeleteFeeConfig 删除收费配置 func (s *FeeConfigService) DeleteFeeConfig(id uint) error { result := global.GVA_DB.Delete(&dao.FeeConfig{}, id) if result.RowsAffected == 0 { return errors.New("收费配置不存在") } return result.Error }