daShangDao_psiServer/service/logistics.go

282 lines
7.8 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package service
import (
"encoding/json"
"errors"
"gorm.io/gorm"
"log"
"math"
"psi/database"
"psi/models"
"psi/models/request"
"psi/models/response"
"strconv"
"time"
)
type LogisticsService struct{}
// GetLogisticsList 获取物流模板列表
func (s *LogisticsService) GetLogisticsList(req request.QueryLogisticsRequest, db ...*gorm.DB) ([]response.LogisticsResponse, int64, error) {
databaseConn := database.OptionalDB(db...)
if req.Page < 1 {
req.Page = 1
}
if req.PageSize < 1 || req.PageSize > 100 {
req.PageSize = 20
}
// 如果提供了 about_id先查询该租户下的所有仓库
var warehouseIDs []int64
if req.AboutID > 0 {
if err := databaseConn.Model(&models.Warehouse{}).
Where("about_id = ? AND is_del = ?", req.AboutID, 0).
Pluck("id", &warehouseIDs).Error; err != nil {
return nil, 0, errors.New("查询仓库信息失败")
}
// 如果没有找到仓库,直接返回空结果
if len(warehouseIDs) == 0 {
return []response.LogisticsResponse{}, 0, nil
}
}
query := databaseConn.Model(&models.Logistics{}).Where("del_flag = ?", "0")
// 如果有仓库ID列表只查询这些仓库关联的物流模板
if len(warehouseIDs) > 0 {
query = query.Where("id IN (?)", warehouseIDs)
}
if req.Keyword != "" {
query = query.Where("template_name LIKE ? OR delivery_province LIKE ? OR delivery_city LIKE ?",
"%"+req.Keyword+"%", "%"+req.Keyword+"%", "%"+req.Keyword+"%")
}
if req.Status != nil {
query = query.Where("status = ?", *req.Status)
}
// === debug: 打印完整SQL ===
log.Printf("[GetLogisticsList] 请求参数 page=%d pageSize=%d keyword=%q about_id=%d", req.Page, req.PageSize, req.Keyword, req.AboutID)
// === debug end ===
var total int64
if err := query.Debug().Count(&total).Error; err != nil {
return nil, 0, errors.New("查询物流模板总数失败")
}
var logistics []models.Logistics
offset := (req.Page - 1) * req.PageSize
if err := query.Debug().Order("id DESC").Offset(offset).Limit(req.PageSize).Find(&logistics).Error; err != nil {
return nil, 0, errors.New("查询物流模板列表失败")
}
responses := make([]response.LogisticsResponse, 0, len(logistics))
for _, item := range logistics {
resp := response.ConvertLogisticsToResponse(item)
responses = append(responses, resp)
}
return responses, total, nil
}
// GetLogisticsByID 获取物流模板详情
func (s *LogisticsService) GetLogisticsByID(id uint64, db ...*gorm.DB) (*response.LogisticsResponse, error) {
databaseConn := database.OptionalDB(db...)
var logistics models.Logistics
if err := databaseConn.Where("id = ? AND del_flag = ?", id, "0").First(&logistics).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, errors.New("物流模板不存在")
}
return nil, errors.New("查询物流模板失败")
}
resp := response.ConvertLogisticsToResponse(logistics)
return &resp, nil
}
// CreateLogistics 创建物流模板
// calculateMinFirstFee 从 shipping_range JSON 中计算最小首费
func (s *LogisticsService) calculateMinFirstFee(shippingRange string) (float64, error) {
if shippingRange == "" {
return 0, errors.New("运送范围不能为空")
}
var rangeMap map[string][]interface{}
if err := json.Unmarshal([]byte(shippingRange), &rangeMap); err != nil {
return 0, errors.New("运送范围格式错误")
}
minFee := math.MaxFloat64
found := false
for _, values := range rangeMap {
if len(values) < 2 {
continue
}
// values[1] 是首费,可能是 string 或 float64
var fee float64
switch v := values[1].(type) {
case float64:
fee = v
case string:
var err error
fee, err = strconv.ParseFloat(v, 64)
if err != nil {
continue
}
default:
continue
}
if fee < minFee {
minFee = fee
}
found = true
}
if !found {
return 0, errors.New("运送范围数据格式错误")
}
return minFee, nil
}
// CreateLogistics 创建物流模板
func (s *LogisticsService) CreateLogistics(req request.CreateLogisticsRequest, db ...*gorm.DB) (uint64, error) {
databaseConn := database.OptionalDB(db...)
var count int64
databaseConn.Model(&models.Logistics{}).
Where("template_name = ? AND del_flag = ?", req.TemplateName, "0").
Count(&count)
if count > 0 {
return 0, errors.New("物流模板名称已存在")
}
// 计算最小首费
minFirPrice, err := s.calculateMinFirstFee(req.ShippingRange)
if err != nil {
return 0, err
}
now := time.Now()
logistics := models.Logistics{
TemplateName: req.TemplateName,
DeliveryProvince: req.DeliveryProvince,
DeliveryCity: req.DeliveryCity,
DeliveryArea: req.DeliveryArea,
DeliveryAddress: req.DeliveryAddress,
PricingMethod: req.PricingMethod,
Shipping: req.Shipping,
FirWbv: req.FirWbv,
FirPrice: minFirPrice,
ContinueWbv: req.ContinueWbv,
ContinuePrice: req.ContinuePrice,
Contact: req.Contact,
PhoneNumber: req.PhoneNumber,
FullAddress: req.FullAddress,
ShippingRange: req.ShippingRange,
WarehouseId: req.WarehouseId,
Remark: req.Remark,
Status: req.Status,
DelFlag: "0",
CreateTime: &now,
UpdateTime: &now,
}
if logistics.Status == "" {
logistics.Status = "0"
}
if err := databaseConn.Create(&logistics).Error; err != nil {
return 0, errors.New("创建物流模板失败")
}
return logistics.Id, nil
}
// UpdateLogistics 修改物流模板
func (s *LogisticsService) UpdateLogistics(req request.UpdateLogisticsRequest, db ...*gorm.DB) error {
databaseConn := database.OptionalDB(db...)
var logistics models.Logistics
if err := databaseConn.Where("id = ? AND del_flag = ?", req.Id, "0").First(&logistics).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return errors.New("物流模板不存在")
}
return errors.New("查询物流模板失败")
}
var count int64
databaseConn.Model(&models.Logistics{}).
Where("template_name = ? AND id != ? AND del_flag = ?", req.TemplateName, req.Id, "0").
Count(&count)
if count > 0 {
return errors.New("物流模板名称已存在")
}
// 计算最小首费
minFirPrice, err := s.calculateMinFirstFee(req.ShippingRange)
if err != nil {
return err
}
now := time.Now()
updates := map[string]interface{}{
"template_name": req.TemplateName,
"delivery_province": req.DeliveryProvince,
"delivery_city": req.DeliveryCity,
"delivery_area": req.DeliveryArea,
"delivery_address": req.DeliveryAddress,
"pricing_method": req.PricingMethod,
"shipping": req.Shipping,
"fir_wbv": req.FirWbv,
"fir_price": minFirPrice,
"continue_wbv": req.ContinueWbv,
"continue_price": req.ContinuePrice,
"contact": req.Contact,
"phone_number": req.PhoneNumber,
"full_address": req.FullAddress,
"shipping_range": req.ShippingRange,
"warehouse_id": req.WarehouseId,
"remark": req.Remark,
"status": req.Status,
"update_time": &now,
}
if err := databaseConn.Model(&logistics).Updates(updates).Error; err != nil {
return errors.New("更新物流模板失败")
}
return nil
}
// DeleteLogistics 删除物流模板
func (s *LogisticsService) DeleteLogistics(id uint64, db ...*gorm.DB) error {
databaseConn := database.OptionalDB(db...)
if id == 0 {
return errors.New("物流模板ID不能为空")
}
var logistics models.Logistics
if err := databaseConn.Where("id = ? AND del_flag = ?", id, "0").First(&logistics).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return errors.New("物流模板不存在")
}
return errors.New("查询物流模板失败")
}
now := time.Now()
if err := databaseConn.Model(&logistics).Update("del_flag", "1").Update("update_time", &now).Error; err != nil {
return errors.New("删除物流模板失败")
}
return nil
}