| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185 |
- 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
- }
|