| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317 |
- package vehicle
- import (
- "errors"
- "fmt"
- "server/dao"
- "server/global"
- "server/model/vehicle/request"
- "time"
- )
- type VehicleService struct{}
- // CreateVehicle 创建车辆信息
- func (s *VehicleService) CreateVehicle(req request.VehicleCreate) error {
- // 检查车牌号是否已存在
- var existingVehicle dao.Vehicle
- result := global.GVA_DB.Where("plate_number = ? OR rfid_tag = ?", req.PlateNumber, req.RFIDTag).First(&existingVehicle)
- 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 ownerId *uint
- if req.OwnerId > 0 {
- ownerId = &req.OwnerId
- }
- vehicle := dao.Vehicle{
- PlateNumber: req.PlateNumber,
- VehicleTypeID: req.VehicleTypeID,
- VehicleBrand: req.VehicleBrand,
- VehicleColor: req.VehicleColor,
- OwnerId: ownerId,
- }
- return global.GVA_DB.Create(&vehicle).Error
- }
- // UpdateVehicle 更新车辆信息
- func (s *VehicleService) UpdateVehicle(req request.VehicleUpdate) error {
- var vehicle dao.Vehicle
- result := global.GVA_DB.First(&vehicle, req.ID)
- if result.RowsAffected == 0 {
- return errors.New("车辆不存在")
- }
- // 检查车牌号是否被其他车辆使用
- var existingVehicle dao.Vehicle
- result = global.GVA_DB.Where("(plate_number = ? OR rfid_tag = ?) AND id != ?", req.PlateNumber, req.RFIDTag, req.ID).First(&existingVehicle)
- fmt.Println("result", result.RowsAffected)
- 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 ownerId *uint
- if req.OwnerId > 0 {
- ownerId = &req.OwnerId
- } else {
- ownerId = nil
- }
- err := global.GVA_DB.Model(&vehicle).Updates(map[string]interface{}{
- "plate_number": req.PlateNumber,
- "rfid_tag": req.RFIDTag,
- "vehicle_type_id": req.VehicleTypeID,
- "vehicle_brand": req.VehicleBrand,
- "vehicle_color": req.VehicleColor,
- "owner_id": ownerId,
- }).Error
- return err
- }
- // GetVehicleByID 根据ID获取车辆信息
- func (s *VehicleService) GetVehicleByID(id uint) (dao.Vehicle, error) {
- var vehicle dao.Vehicle
- result := global.GVA_DB.First(&vehicle, id)
- if result.RowsAffected == 0 {
- return dao.Vehicle{}, errors.New("车辆不存在")
- }
- return vehicle, nil
- }
- // GetVehicleByPlateNumber 根据车牌号获取车辆信息
- func (s *VehicleService) GetVehicleByPlateNumber(plateNumber, RFIDTag string) (dao.Vehicle, error) {
- var vehicle dao.Vehicle
- result := global.GVA_DB.Where("plate_number = ? or rfid_tag = ?", plateNumber, RFIDTag).Preload("VehicleType").First(&vehicle)
- if result.RowsAffected == 0 {
- return dao.Vehicle{}, errors.New("车辆不存在")
- }
- return vehicle, nil
- }
- func (s *VehicleService) QueryAllVehicles() ([]dao.Vehicle, error) {
- var vehicles []dao.Vehicle
- err := global.GVA_DB.Find(&vehicles).Error
- if err != nil {
- return vehicles, err
- }
- return vehicles, nil
- }
- // ListVehicles 获取车辆列表
- func (s *VehicleService) ListVehicles(req request.VehicleQuery) (int64, []dao.Vehicle, error) {
- var vehicles []dao.Vehicle
- var total int64
- query := global.GVA_DB.Model(&dao.Vehicle{})
- if req.PlateNumber != "" {
- query = query.Where("plate_number LIKE ?", "%"+req.PlateNumber+"%")
- }
- if req.VehicleTypeID > 0 {
- query = query.Where("vehicle_type_id = ?", req.VehicleTypeID)
- }
- if req.OwnerId > 0 {
- query = query.Where("owner_id = ?", req.OwnerId)
- }
- // 计算总数
- query.Count(&total)
- // 分页查询
- offset := (req.Page - 1) * req.PageSize
- result := query.Offset(offset).Limit(req.PageSize).Preload("Owner").Preload("VehicleType").Find(&vehicles)
- if result.Error != nil {
- return 0, nil, result.Error
- }
- return total, vehicles, nil
- }
- // DeleteVehicle 删除车辆
- func (s *VehicleService) DeleteVehicle(id uint) error {
- result := global.GVA_DB.Delete(&dao.Vehicle{}, id)
- if result.RowsAffected == 0 {
- return errors.New("车辆不存在")
- }
- return result.Error
- }
- // VehicleEntry 车辆入场
- func (s *VehicleService) VehicleEntry(req request.VehicleEntry) (request.VehicleEntryResponse, error) {
- // 检查车辆是否存在
- vehicle, err := s.GetVehicleByPlateNumber(req.PlateNumber, req.RFIDTag)
- if err != nil {
- // 如果车辆不存在,创建新车辆,默认使用ID为1的车辆类型(临时车)
- createReq := request.VehicleCreate{
- PlateNumber: req.PlateNumber,
- VehicleTypeID: 1, // 默认类型ID为1(临时车)
- OwnerId: 0, // 默认无车主
- }
- err = s.CreateVehicle(createReq)
- if err != nil {
- return request.VehicleEntryResponse{}, err
- }
- vehicle, _ = s.GetVehicleByPlateNumber(req.PlateNumber, req.RFIDTag)
- }
- // 检查是否有未出场的记录
- var existingRecord dao.VehicleRecord
- result := global.GVA_DB.Where("(plate_number = ? OR rfid_tag = ?) AND exit_time IS NULL", req.PlateNumber, req.RFIDTag).First(&existingRecord)
- if result.RowsAffected > 0 {
- return request.VehicleEntryResponse{}, errors.New("车辆已入场,未出场")
- }
- // 创建入场记录
- entryTime := time.Now()
- record := dao.VehicleRecord{
- PlateNumber: req.PlateNumber,
- RFIDTag: req.RFIDTag,
- EntryTime: entryTime,
- ParkingLotID: req.ParkingLotID,
- ParkingSpaceID: req.ParkingSpaceID,
- EntryImage: req.EntryImage,
- PaymentStatus: "unpaid",
- }
- err = global.GVA_DB.Create(&record).Error
- if err != nil {
- return request.VehicleEntryResponse{}, err
- }
- // 更新车辆最近入场时间
- vehicle.LastEntryTime = &entryTime
- global.GVA_DB.Save(&vehicle)
- response := request.VehicleEntryResponse{
- Success: true,
- Message: "车辆入场成功",
- }
- response.Data.PlateNumber = req.PlateNumber
- response.Data.EntryTime = entryTime.Unix()
- response.Data.ParkingLotID = req.ParkingLotID
- response.Data.ParkingSpaceID = req.ParkingSpaceID
- return response, nil
- }
- // VehicleExit 车辆出场
- func (s *VehicleService) VehicleExit(req request.VehicleExit) (request.VehicleExitResponse, error) {
- // 1. 查询未出场记录
- var record dao.VehicleRecord
- if err := global.GVA_DB.Where("(plate_number = ? OR rfid_tag = ?) AND exit_time IS NULL", req.PlateNumber, req.RFIDTag).First(&record).Error; err != nil {
- return request.VehicleExitResponse{}, errors.New("车辆未入场或已出场")
- }
- // 2. 获取车辆信息
- vehicle, err := s.GetVehicleByPlateNumber(req.PlateNumber, req.RFIDTag)
- if err != nil {
- return request.VehicleExitResponse{}, err
- }
- // 3. 计算停留时长 & 费用
- exitTime := time.Now()
- stayTime := int64(exitTime.Sub(record.EntryTime).Minutes())
- if stayTime < 0 {
- stayTime = 0
- }
- fee := s.calculateFee(&vehicle, stayTime)
- // 4. 更新出场记录
- record.ExitTime = &exitTime
- record.StayTime = stayTime
- record.Fee = fee
- record.ExitImage = req.ExitImage
- record.PaymentStatus = "paid"
- if err := global.GVA_DB.Save(&record).Error; err != nil {
- return request.VehicleExitResponse{}, err
- }
- // 5. 更新车辆统计信息
- vehicle.LastExitTime = &exitTime
- vehicle.TotalStayTime += stayTime
- vehicle.TotalFee += fee
- global.GVA_DB.Save(&vehicle)
- // 6. 完全匹配你的匿名结构体返回(正确写法)
- var response request.VehicleExitResponse
- response.Success = true
- response.Message = "车辆出场成功"
- response.Data.PlateNumber = record.PlateNumber
- response.Data.EntryTime = record.EntryTime.Unix()
- response.Data.ExitTime = exitTime.Unix()
- response.Data.StayTime = stayTime
- response.Data.Fee = fee
- response.Data.PaymentStatus = record.PaymentStatus
- return response, nil
- }
- // calculateFee 计算停车费用
- func (s *VehicleService) calculateFee(vehicle *dao.Vehicle, stayTime int64) float64 {
- // 1. 根据车辆类型ID获取收费配置(唯一)
- var feeConfig dao.FeeConfig
- if err := global.GVA_DB.Where("vehicle_type_id = ?", vehicle.VehicleTypeID).First(&feeConfig).Error; err != nil {
- // 无配置 → 默认计费
- return float64(stayTime) * 0.1
- }
- // 2. 判断VIP有效性
- isVIP := false
- if vehicle.OwnerId != nil {
- var owner dao.Owner
- if err := global.GVA_DB.First(&owner, *vehicle.OwnerId).Error; err == nil {
- isVIP = owner.IsVip && time.Now().Before(owner.VipExpireTime)
- }
- }
- // 3. VIP 免费
- if isVIP && feeConfig.IsVIPFree {
- return 0
- }
- // ===================== 修复这里 =====================
- // 4. 在免费时长内 → 直接 0 元
- if stayTime <= int64(feeConfig.StartTime) {
- return 0
- }
- // 5. 超过免费时长 → 开始计费
- extraTime := stayTime - int64(feeConfig.StartTime)
- extraUnits := extraTime / int64(feeConfig.UnitTime)
- if extraTime%int64(feeConfig.UnitTime) > 0 {
- extraUnits++
- }
- // 起步费 + 超时费用
- fee := feeConfig.StartFee + float64(extraUnits)*feeConfig.UnitFee
- // 6. 每日封顶
- if feeConfig.DailyMaxFee > 0 && fee > feeConfig.DailyMaxFee {
- fee = feeConfig.DailyMaxFee
- }
- // 7. VIP 折扣
- if isVIP {
- fee *= feeConfig.VIPDiscount
- }
- return fee
- }
|