1.返回userlist
2.通过use_id,product_id 返回关联信息
This commit is contained in:
parent
0eb07eec03
commit
fafac05570
@ -327,3 +327,28 @@ func (r *EmployeeApi) GetUserList(c *gin.Context) {
|
|||||||
"data": result,
|
"data": result,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UpdateEmployeeSplitAccountConfigByAboutId 根据about_id更新员工分账配置ID
|
||||||
|
func (r *EmployeeApi) UpdateEmployeeSplitAccountConfigByAboutId(c *gin.Context) {
|
||||||
|
var req systemReq.UpdateEmployeeSplitAccountConfigRequest
|
||||||
|
|
||||||
|
if err := c.ShouldBind(&req); err != nil {
|
||||||
|
ValidAndFail(constant.LoggerChannelRequest, "更新员工分账配置请求参数异常", "参数错误: "+err.Error(), c, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取当前用户信息
|
||||||
|
userInfo := utils.GetUserInfo(c)
|
||||||
|
|
||||||
|
result, err := employeeService.UpdateEmployeeSplitAccountConfigByAboutId(req, userInfo.Username)
|
||||||
|
if err != nil {
|
||||||
|
utils.ErrorLog(constant.LoggerChannelWork, logrus.Fields{
|
||||||
|
"source": "更新员工分账配置异常",
|
||||||
|
"err_msg": err.Error(),
|
||||||
|
})
|
||||||
|
systemRes.FailWithMessage(err.Error(), c)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
systemRes.OkWithDetailed(result, "更新成功", c)
|
||||||
|
}
|
||||||
|
|||||||
@ -25,6 +25,19 @@ type Employee struct {
|
|||||||
ExpireTime int64 `json:"expire_time" gorm:"not null;default:0;comment:过期时间"`
|
ExpireTime int64 `json:"expire_time" gorm:"not null;default:0;comment:过期时间"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UpdateEmployeeSplitAccountConfigResponse 更新员工分账配置响应
|
||||||
|
type UpdateEmployeeSplitAccountConfigResponse struct {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
EmployeeIDStr string `json:"employee_id_str"`
|
||||||
|
Username string `json:"username"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Phone string `json:"phone"`
|
||||||
|
AboutId int64 `json:"about_id"`
|
||||||
|
SplitAccountConfigId int64 `json:"split_account_config_id"`
|
||||||
|
Status int8 `json:"status"`
|
||||||
|
UpdatedAt int64 `json:"updated_at"`
|
||||||
|
}
|
||||||
|
|
||||||
func (Employee) TableName() string {
|
func (Employee) TableName() string {
|
||||||
return "employees"
|
return "employees"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -65,8 +65,25 @@ type SetEmployeeLevelRequest struct {
|
|||||||
|
|
||||||
// GetUserListRequest 获取用户列表请求
|
// GetUserListRequest 获取用户列表请求
|
||||||
type GetUserListRequest struct {
|
type GetUserListRequest struct {
|
||||||
Page int `form:"page"`
|
Page int `form:"page"` // 页码
|
||||||
PageSize int `form:"page_size"`
|
PageSize int `form:"page_size"` // 页大小
|
||||||
Keyword string `form:"keyword"`
|
Username string `form:"username"` // 用户名
|
||||||
Status string `form:"status"`
|
Tel string `form:"tel"` // 手机号
|
||||||
|
//Keyword string `form:"keyword"` // 关键词 注释将keyword改为 username 和 tel
|
||||||
|
Status string `form:"status"` // 状态
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUserListRequest 获取用户列表请求
|
||||||
|
/*type GetUserListRequest struct {
|
||||||
|
Page int `form:"page"` // 页码
|
||||||
|
PageSize int `form:"page_size"` // 页大小
|
||||||
|
Username string `form:"username"` // 用户名
|
||||||
|
Tel string `form:"tel"` // 手机号
|
||||||
|
Status string `form:"status"` // 状态
|
||||||
|
}*/
|
||||||
|
|
||||||
|
// UpdateEmployeeSplitAccountConfigRequest 根据about_id更新员工分账配置请求
|
||||||
|
type UpdateEmployeeSplitAccountConfigRequest struct {
|
||||||
|
AboutId int64 `form:"about_id" binding:"required"`
|
||||||
|
SplitAccountConfigId int64 `form:"split_account_config_id" binding:"required"`
|
||||||
}
|
}
|
||||||
|
|||||||
@ -154,6 +154,7 @@ type DeleteProductLogRequest struct {
|
|||||||
type GetProductInventoryRequest struct {
|
type GetProductInventoryRequest struct {
|
||||||
UserID int64 `form:"user_id" binding:"required"` // 用户ID
|
UserID int64 `form:"user_id" binding:"required"` // 用户ID
|
||||||
ProductID int64 `form:"product_id" binding:"required"` // 商品ID
|
ProductID int64 `form:"product_id" binding:"required"` // 商品ID
|
||||||
|
Type int8 `form:"type"` // 类型: 0=原始数据, 1=按商品名称+ISBN+仓库聚合
|
||||||
}
|
}
|
||||||
|
|
||||||
type GetShopProductDetailRequest struct {
|
type GetShopProductDetailRequest struct {
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package response
|
package response
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"psi/models"
|
"psi/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -109,6 +110,7 @@ type UserListItem struct {
|
|||||||
Role int64 `json:"role"`
|
Role int64 `json:"role"`
|
||||||
Status int8 `json:"status"`
|
Status int8 `json:"status"`
|
||||||
SplitAccountConfigId int64 `json:"split_account_config_id"`
|
SplitAccountConfigId int64 `json:"split_account_config_id"`
|
||||||
|
SplitAccountConfig *SplitAccountConfigInfo `json:"split_account_config,omitempty"` // 分账配置详情
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetUserListResponse 用户列表响应
|
// GetUserListResponse 用户列表响应
|
||||||
@ -118,3 +120,47 @@ type GetUserListResponse struct {
|
|||||||
Page int `json:"page"`
|
Page int `json:"page"`
|
||||||
PageSize int `json:"page_size"`
|
PageSize int `json:"page_size"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UpdateEmployeeSplitAccountConfigResponse 更新员工分账配置响应
|
||||||
|
type UpdateEmployeeSplitAccountConfigResponse struct {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
EmployeeIDStr string `json:"employee_id_str"`
|
||||||
|
Username string `json:"username"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Phone string `json:"phone"`
|
||||||
|
AboutId int64 `json:"about_id"`
|
||||||
|
SplitAccountConfigId int64 `json:"split_account_config_id"`
|
||||||
|
Status int8 `json:"status"`
|
||||||
|
UpdatedAt int64 `json:"updated_at"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CurrentUserResponse 当前用户信息响应(包含分账配置)
|
||||||
|
type CurrentUserResponse struct {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
EmployeeIDStr string `json:"employee_id_str"`
|
||||||
|
Username string `json:"username"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Phone string `json:"phone"`
|
||||||
|
Role int64 `json:"role"`
|
||||||
|
Fid int64 `json:"fid"`
|
||||||
|
AboutId int64 `json:"about_id"`
|
||||||
|
Status int8 `json:"status"`
|
||||||
|
Score int64 `json:"score"`
|
||||||
|
SplitAccountConfigId int64 `json:"split_account_config_id"`
|
||||||
|
SplitAccountConfig *SplitAccountConfigInfo `json:"split_account_config,omitempty"` // 分账配置详情
|
||||||
|
CreatedAt int64 `json:"created_at"`
|
||||||
|
UpdatedAt int64 `json:"updated_at"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// SplitAccountConfigInfo 分账配置信息
|
||||||
|
type SplitAccountConfigInfo struct {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
RuleName string `json:"rule_name"`
|
||||||
|
RuleValue json.RawMessage `json:"rule_value"`
|
||||||
|
Status int8 `json:"status"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
CreatedBy string `json:"created_by"`
|
||||||
|
UpdatedBy string `json:"updated_by"`
|
||||||
|
CreatedAt int64 `json:"created_at"`
|
||||||
|
UpdatedAt int64 `json:"updated_at"`
|
||||||
|
}
|
||||||
|
|||||||
@ -146,7 +146,8 @@ type ProductLogListResponse struct {
|
|||||||
|
|
||||||
// ProductInventoryResponse 商品库存响应
|
// ProductInventoryResponse 商品库存响应
|
||||||
type ProductInventoryResponse struct {
|
type ProductInventoryResponse struct {
|
||||||
Quantity int64 `json:"quantity"`
|
Quantity int64 `json:"quantity"` // 总库存数量(type=0时使用)
|
||||||
|
Warehouses []ProductInventoryWarehouse `json:"warehouses,omitempty"` // 仓库列表(type=1时使用)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ShopProductDetailResponse 店铺商品详情响应
|
// ShopProductDetailResponse 店铺商品详情响应
|
||||||
@ -199,3 +200,14 @@ type ProductInShop struct {
|
|||||||
CreatedAt int64 `json:"created_at"` // 创建时间
|
CreatedAt int64 `json:"created_at"` // 创建时间
|
||||||
UpdatedAt int64 `json:"updated_at"` // 更新时间
|
UpdatedAt int64 `json:"updated_at"` // 更新时间
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ProductInventoryWarehouse 商品库存仓库信息
|
||||||
|
type ProductInventoryWarehouse struct {
|
||||||
|
WarehouseID int64 `json:"warehouse_id"` // 仓库ID
|
||||||
|
WarehouseName string `json:"warehouse_name"` // 仓库名称
|
||||||
|
WarehouseCode string `json:"warehouse_code"` // 仓库编码
|
||||||
|
ProductName string `json:"product_name"` // 商品名称
|
||||||
|
ISBN string `json:"isbn"` // ISBN/条码
|
||||||
|
Appearance int64 `json:"appearance"` // 品相
|
||||||
|
TotalQuantity int64 `json:"total_quantity"` // 该仓库下该商品的总库存
|
||||||
|
}
|
||||||
|
|||||||
@ -98,7 +98,7 @@ func initRouter() (r *gin.Engine) {
|
|||||||
// 管理员
|
// 管理员
|
||||||
auth.GET("/user/current", employeeApi.GetCurrentUser) // 获取当前用户信息
|
auth.GET("/user/current", employeeApi.GetCurrentUser) // 获取当前用户信息
|
||||||
auth.POST("/logout", employeeApi.Logout) // 登出
|
auth.POST("/logout", employeeApi.Logout) // 登出
|
||||||
auth.POST("/userList", employeeApi.GetUserList) // 获取用户列表
|
auth.GET("/userList", employeeApi.GetUserList) // 获取用户列表
|
||||||
// 配置管理
|
// 配置管理
|
||||||
auth.GET("/config/list", configApi.GetConfigList) // 获取配置列表
|
auth.GET("/config/list", configApi.GetConfigList) // 获取配置列表
|
||||||
auth.GET("/config/detail/:id", configApi.GetConfigDetail) // 获取配置详情
|
auth.GET("/config/detail/:id", configApi.GetConfigDetail) // 获取配置详情
|
||||||
@ -261,6 +261,7 @@ func initRouter() (r *gin.Engine) {
|
|||||||
admin.GET("/employee/check_expire_time", employeeApi.CheckExpireTimeEmployee) // 检查员工到期时间
|
admin.GET("/employee/check_expire_time", employeeApi.CheckExpireTimeEmployee) // 检查员工到期时间
|
||||||
admin.POST("/employee/set_level", employeeApi.SetEmployeeLevel) // 设置员工等级
|
admin.POST("/employee/set_level", employeeApi.SetEmployeeLevel) // 设置员工等级
|
||||||
admin.GET("/employee/level_config", employeeApi.GetLevelConfigList) // 获取员工等级配置列表
|
admin.GET("/employee/level_config", employeeApi.GetLevelConfigList) // 获取员工等级配置列表
|
||||||
|
admin.POST("/employee/update-split-account-config", employeeApi.UpdateEmployeeSplitAccountConfigByAboutId) // 根据about_id更新员工分账配置ID
|
||||||
// 用户类型管理
|
// 用户类型管理
|
||||||
admin.GET("/user-type/list", userTypeApi.GetUserTypeList) // 获取用户类型列表
|
admin.GET("/user-type/list", userTypeApi.GetUserTypeList) // 获取用户类型列表
|
||||||
admin.GET("/user-type/detail/:id", userTypeApi.GetUserTypeDetail) // 获取用户类型详情
|
admin.GET("/user-type/detail/:id", userTypeApi.GetUserTypeDetail) // 获取用户类型详情
|
||||||
|
|||||||
@ -839,7 +839,7 @@ func (s *EmployeeService) createEmployeeLevelLog(empId int64, operationType int8
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetUserList 获取用户列表(主库)
|
// GetUserList 获取用户列表(主库)
|
||||||
func (s *EmployeeService) GetUserList(req systemReq.GetUserListRequest) (*systemRes.GetUserListResponse, error) {
|
/*func (s *EmployeeService) GetUserList(req systemReq.GetUserListRequest) (*systemRes.GetUserListResponse, error) {
|
||||||
if req.Page < 1 {
|
if req.Page < 1 {
|
||||||
req.Page = 1
|
req.Page = 1
|
||||||
}
|
}
|
||||||
@ -888,3 +888,149 @@ func (s *EmployeeService) GetUserList(req systemReq.GetUserListRequest) (*system
|
|||||||
PageSize: req.PageSize,
|
PageSize: req.PageSize,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
func (s *EmployeeService) GetUserList(req systemReq.GetUserListRequest) (*systemRes.GetUserListResponse, error) {
|
||||||
|
if req.Page < 1 {
|
||||||
|
req.Page = 1
|
||||||
|
}
|
||||||
|
if req.PageSize < 1 || req.PageSize > 100 {
|
||||||
|
req.PageSize = 20
|
||||||
|
}
|
||||||
|
|
||||||
|
query := database.DB.Model(&models.Employee{}).Where("deleted_at = ?", 0)
|
||||||
|
|
||||||
|
if req.Status != "" {
|
||||||
|
query = query.Where("status = ?", req.Status)
|
||||||
|
}
|
||||||
|
if req.Username != "" {
|
||||||
|
query = query.Where("username LIKE ?", "%"+req.Username+"%")
|
||||||
|
}
|
||||||
|
if req.Tel != "" {
|
||||||
|
query = query.Where("phone LIKE ?", "%"+req.Tel+"%")
|
||||||
|
}
|
||||||
|
|
||||||
|
var total int64
|
||||||
|
if err := query.Count(&total).Error; err != nil {
|
||||||
|
return nil, utils.NewError("查询总数失败")
|
||||||
|
}
|
||||||
|
|
||||||
|
var employees []models.Employee
|
||||||
|
offset := (req.Page - 1) * req.PageSize
|
||||||
|
if err := query.Order("created_at DESC").Offset(offset).Limit(req.PageSize).Find(&employees).Error; err != nil {
|
||||||
|
return nil, utils.NewError("查询用户列表失败")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 收集所有需要查询的分账配置ID
|
||||||
|
splitConfigIDs := make([]int64, 0)
|
||||||
|
for _, emp := range employees {
|
||||||
|
if emp.SplitAccountConfigId > 0 {
|
||||||
|
splitConfigIDs = append(splitConfigIDs, emp.SplitAccountConfigId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 批量查询分账配置
|
||||||
|
splitConfigMap := make(map[int64]*systemRes.SplitAccountConfigInfo)
|
||||||
|
if len(splitConfigIDs) > 0 {
|
||||||
|
var splitConfigs []models.SplitAccountConfig
|
||||||
|
database.DB.Where("id IN ? AND deleted_at = ?", splitConfigIDs, 0).Find(&splitConfigs)
|
||||||
|
|
||||||
|
for _, config := range splitConfigs {
|
||||||
|
splitConfigMap[config.ID] = &systemRes.SplitAccountConfigInfo{
|
||||||
|
ID: config.ID,
|
||||||
|
RuleName: config.RuleName,
|
||||||
|
RuleValue: json.RawMessage(config.RuleValue),
|
||||||
|
Status: config.Status,
|
||||||
|
Description: config.Description,
|
||||||
|
CreatedBy: config.CreatedBy,
|
||||||
|
UpdatedBy: config.UpdatedBy,
|
||||||
|
CreatedAt: config.CreatedAt,
|
||||||
|
UpdatedAt: config.UpdatedAt,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var items []systemRes.UserListItem
|
||||||
|
for _, emp := range employees {
|
||||||
|
item := systemRes.UserListItem{
|
||||||
|
ID: emp.ID,
|
||||||
|
EmployeeIDStr: emp.EmployeeIDStr,
|
||||||
|
Username: emp.Username,
|
||||||
|
Name: emp.Name,
|
||||||
|
Role: emp.Role,
|
||||||
|
Status: emp.Status,
|
||||||
|
SplitAccountConfigId: emp.SplitAccountConfigId,
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果有关联的分账配置,添加详情
|
||||||
|
if emp.SplitAccountConfigId > 0 {
|
||||||
|
if config, exists := splitConfigMap[emp.SplitAccountConfigId]; exists {
|
||||||
|
item.SplitAccountConfig = config
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
items = append(items, item)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &systemRes.GetUserListResponse{
|
||||||
|
List: items,
|
||||||
|
Total: total,
|
||||||
|
Page: req.Page,
|
||||||
|
PageSize: req.PageSize,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateEmployeeSplitAccountConfigByAboutId 根据about_id更新员工分账配置ID
|
||||||
|
func (s *EmployeeService) UpdateEmployeeSplitAccountConfigByAboutId(req systemReq.UpdateEmployeeSplitAccountConfigRequest, username string) (*systemRes.UpdateEmployeeSplitAccountConfigResponse, error) {
|
||||||
|
var employee models.Employee
|
||||||
|
result := database.DB.Where("about_id = ? AND deleted_at = ?", req.AboutId, 0).First(&employee)
|
||||||
|
if result.Error != nil {
|
||||||
|
return nil, utils.NewError("员工不存在")
|
||||||
|
}
|
||||||
|
|
||||||
|
updateData := map[string]interface{}{
|
||||||
|
"split_account_config_id": req.SplitAccountConfigId,
|
||||||
|
"updated_at": time.Now().Unix(),
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := database.DB.Model(&employee).Updates(updateData).Error; err != nil {
|
||||||
|
return nil, utils.NewError("更新员工分账配置失败: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重新查询更新后的员工数据
|
||||||
|
if err := database.DB.Where("id = ? AND deleted_at = ?", employee.ID, 0).First(&employee).Error; err != nil {
|
||||||
|
return nil, utils.NewError("查询更新后的员工数据失败")
|
||||||
|
}
|
||||||
|
|
||||||
|
return &systemRes.UpdateEmployeeSplitAccountConfigResponse{
|
||||||
|
ID: employee.ID,
|
||||||
|
EmployeeIDStr: employee.EmployeeIDStr,
|
||||||
|
Username: employee.Username,
|
||||||
|
Name: employee.Name,
|
||||||
|
Phone: employee.Phone,
|
||||||
|
AboutId: employee.AboutId,
|
||||||
|
SplitAccountConfigId: employee.SplitAccountConfigId,
|
||||||
|
Status: employee.Status,
|
||||||
|
UpdatedAt: employee.UpdatedAt,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ... existing code ...
|
||||||
|
/*func (s *EmployeeService) UpdateEmployeeSplitAccountConfigByAboutId(req systemReq.UpdateEmployeeSplitAccountConfigRequest, username string) error {
|
||||||
|
var employee models.Employee
|
||||||
|
result := database.DB.Where("about_id = ? AND deleted_at = ?", req.AboutId, 0).First(&employee)
|
||||||
|
if result.Error != nil {
|
||||||
|
return utils.NewError("员工不存在")
|
||||||
|
}
|
||||||
|
|
||||||
|
updateData := map[string]interface{}{
|
||||||
|
"split_account_config_id": req.SplitAccountConfigId,
|
||||||
|
"updated_at": time.Now().Unix(),
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := database.DB.Model(&employee).Updates(updateData).Error; err != nil {
|
||||||
|
return utils.NewError("更新员工分账配置失败: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|||||||
@ -3974,12 +3974,7 @@ func (s *ProcessService) syncProductsToExternal(receivingOrderID, waveTaskID, us
|
|||||||
group.totalQty += item.quantity
|
group.totalQty += item.quantity
|
||||||
} else {
|
} else {
|
||||||
// 新建ISBN组
|
// 新建ISBN组
|
||||||
var imgList []string
|
imgList := parseImageList(product.LiveImage)
|
||||||
if product.LiveImage != nil && len(product.LiveImage) > 0 {
|
|
||||||
if err := json.Unmarshal(product.LiveImage, &imgList); err != nil {
|
|
||||||
return fmt.Errorf("解析json失败: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
skuCode := warehouse.Code
|
skuCode := warehouse.Code
|
||||||
if item.locationID > 0 {
|
if item.locationID > 0 {
|
||||||
@ -4046,12 +4041,7 @@ func (s *ProcessService) syncProductsToExternal(receivingOrderID, waveTaskID, us
|
|||||||
}
|
}
|
||||||
|
|
||||||
isbn := product.Barcode
|
isbn := product.Barcode
|
||||||
var imgList []string
|
imgList := parseImageList(product.LiveImage)
|
||||||
if product.LiveImage != nil && len(product.LiveImage) > 0 {
|
|
||||||
if err := json.Unmarshal(product.LiveImage, &imgList); err != nil {
|
|
||||||
return fmt.Errorf("解析json失败: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
skuCode := warehouse.Code
|
skuCode := warehouse.Code
|
||||||
if item.locationID > 0 {
|
if item.locationID > 0 {
|
||||||
@ -4379,3 +4369,34 @@ func getSalesStatusText(status int8) string {
|
|||||||
return "未知状态"
|
return "未知状态"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// parseImageList 解析图片列表,支持JSON数组和逗号分隔字符串两种格式
|
||||||
|
func parseImageList(liveImage datatypes.JSON) []string {
|
||||||
|
if liveImage == nil || len(liveImage) == 0 {
|
||||||
|
return []string{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 尝试解析为字符串数组
|
||||||
|
var imgList []string
|
||||||
|
if err := json.Unmarshal(liveImage, &imgList); err == nil {
|
||||||
|
return imgList
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果解析失败,尝试解析为字符串,然后按逗号分割
|
||||||
|
var imgStr string
|
||||||
|
if err := json.Unmarshal(liveImage, &imgStr); err == nil {
|
||||||
|
// 去除空格并按逗号分割
|
||||||
|
parts := strings.Split(imgStr, ",")
|
||||||
|
result := make([]string, 0, len(parts))
|
||||||
|
for _, part := range parts {
|
||||||
|
trimmed := strings.TrimSpace(part)
|
||||||
|
if trimmed != "" {
|
||||||
|
result = append(result, trimmed)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// 都不成功,返回空数组
|
||||||
|
return []string{}
|
||||||
|
}
|
||||||
|
|||||||
@ -651,18 +651,123 @@ func (s *ProductService) UpdatePrice(req systemReq.UpdatePriceRequest) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetProductInventory 获取商品库存数量
|
//// GetProductInventory 获取商品库存数量
|
||||||
|
//func (s *ProductService) GetProductInventory(req systemReq.GetProductInventoryRequest) (*systemRes.ProductInventoryResponse, error) {
|
||||||
|
// databaseConn, err := database.GetTenantDB(req.UserID)
|
||||||
|
// if err != nil {
|
||||||
|
// return nil, fmt.Errorf("获取数据库连接失败: %v", err)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // 验证商品是否存在
|
||||||
|
// var product models.Product
|
||||||
|
// if err := databaseConn.Where("id = ? AND is_del = ?", req.ProductID, 0).First(&product).Error; err != nil {
|
||||||
|
// return nil, fmt.Errorf("商品不存在")
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// //// type=1: 按品相+ISBN+仓库聚合
|
||||||
|
// //if req.Type == 1 {
|
||||||
|
// // type warehouseStock struct {
|
||||||
|
// // WarehouseID int64 `gorm:"column:warehouse_id"`
|
||||||
|
// // WarehouseName string `gorm:"column:warehouse_name"`
|
||||||
|
// // WarehouseCode string `gorm:"column:warehouse_code"`
|
||||||
|
// // ProductName string `gorm:"column:product_name"`
|
||||||
|
// // ISBN string `gorm:"column:isbn"`
|
||||||
|
// // Appearance int64 `gorm:"column:appearance"`
|
||||||
|
// // TotalQuantity int64 `gorm:"column:total_quantity"`
|
||||||
|
// // }
|
||||||
|
// //
|
||||||
|
// // var warehouseList []warehouseStock
|
||||||
|
// // databaseConn.Table("inventory").
|
||||||
|
// // Select(`
|
||||||
|
// // inventory.warehouse_id,
|
||||||
|
// // w.name as warehouse_name,
|
||||||
|
// // w.code as warehouse_code,
|
||||||
|
// // p.name as product_name,
|
||||||
|
// // p.barcode as isbn,
|
||||||
|
// // p.appearance as appearance,
|
||||||
|
// // COALESCE(SUM(inventory.quantity), 0) as total_quantity
|
||||||
|
// // `).
|
||||||
|
// // Joins("LEFT JOIN warehouse w ON inventory.warehouse_id = w.id AND w.is_del = ?", 0).
|
||||||
|
// // Joins("LEFT JOIN product p ON inventory.product_id = p.id AND p.is_del = ?", 0).
|
||||||
|
// // Where("inventory.product_id = ? AND inventory.is_del = ?", req.ProductID, 0).
|
||||||
|
// // Group("inventory.warehouse_id, w.name, w.code, p.name, p.barcode, p.appearance").
|
||||||
|
// // Scan(&warehouseList)
|
||||||
|
// //
|
||||||
|
// // warehouses := make([]systemRes.ProductInventoryWarehouse, 0, len(warehouseList))
|
||||||
|
// // totalQuantity := int64(0)
|
||||||
|
// // for _, ws := range warehouseList {
|
||||||
|
// // warehouses = append(warehouses, systemRes.ProductInventoryWarehouse{
|
||||||
|
// // WarehouseID: ws.WarehouseID,
|
||||||
|
// // WarehouseName: ws.WarehouseName,
|
||||||
|
// // WarehouseCode: ws.WarehouseCode,
|
||||||
|
// // ProductName: ws.ProductName,
|
||||||
|
// // ISBN: ws.ISBN,
|
||||||
|
// // Appearance: ws.Appearance,
|
||||||
|
// // TotalQuantity: ws.TotalQuantity,
|
||||||
|
// // })
|
||||||
|
// // totalQuantity += ws.TotalQuantity
|
||||||
|
// // }
|
||||||
|
//
|
||||||
|
// return &systemRes.ProductInventoryResponse{
|
||||||
|
// Quantity: totalQuantity,
|
||||||
|
// //Warehouses: warehouses,
|
||||||
|
// }, nil
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // type=0: 返回原始数据(总库存)
|
||||||
|
// var totalQuantity int64
|
||||||
|
// //databaseConn.Table("inventory").
|
||||||
|
// // Select("COALESCE(SUM(quantity), 0)").
|
||||||
|
// // Where("product_id = ? AND is_del = ?", req.ProductID, 0).
|
||||||
|
// // Scan(&totalQuantity)
|
||||||
|
//
|
||||||
|
// return &systemRes.ProductInventoryResponse{
|
||||||
|
// Quantity: totalQuantity,
|
||||||
|
// }, nil
|
||||||
|
//}
|
||||||
|
|
||||||
func (s *ProductService) GetProductInventory(req systemReq.GetProductInventoryRequest) (*systemRes.ProductInventoryResponse, error) {
|
func (s *ProductService) GetProductInventory(req systemReq.GetProductInventoryRequest) (*systemRes.ProductInventoryResponse, error) {
|
||||||
databaseConn, err := database.GetTenantDB(req.UserID)
|
databaseConn, err := database.GetTenantDB(req.UserID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("获取数据库连接失败: %v", err)
|
return nil, fmt.Errorf("获取数据库连接失败: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 验证商品是否存在,并获取商品信息
|
||||||
|
var product models.Product
|
||||||
|
if err := databaseConn.Where("id = ? AND is_del = ?", req.ProductID, 0).First(&product).Error; err != nil {
|
||||||
|
return nil, fmt.Errorf("商品不存在")
|
||||||
|
}
|
||||||
|
|
||||||
var totalQuantity int64
|
var totalQuantity int64
|
||||||
|
|
||||||
|
// type=1: 按品相+ISBN+仓库分组后统计总数量
|
||||||
|
if req.Type == 1 {
|
||||||
|
type GroupStock struct {
|
||||||
|
TotalQuantity int64 `gorm:"column:total_quantity"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var groupList []GroupStock
|
||||||
|
// 先根据商品的 ISBN 和品相,查询所有匹配的库存记录,再按仓库分组统计
|
||||||
|
databaseConn.Table("inventory").
|
||||||
|
Select(`
|
||||||
|
COALESCE(SUM(inventory.quantity), 0) as total_quantity
|
||||||
|
`).
|
||||||
|
Joins("LEFT JOIN product p ON inventory.product_id = p.id AND p.is_del = ?", 0).
|
||||||
|
Where("p.barcode = ? AND p.appearance = ? AND inventory.warehouse_id IS NOT NULL AND inventory.is_del = ?",
|
||||||
|
product.Barcode, product.Appearance, 0).
|
||||||
|
Group("inventory.warehouse_id").
|
||||||
|
Scan(&groupList)
|
||||||
|
|
||||||
|
// 累加所有分组的数量
|
||||||
|
for _, group := range groupList {
|
||||||
|
totalQuantity += group.TotalQuantity
|
||||||
|
}
|
||||||
|
} else {
|
||||||
databaseConn.Table("inventory").
|
databaseConn.Table("inventory").
|
||||||
Select("COALESCE(SUM(quantity), 0)").
|
Select("COALESCE(SUM(quantity), 0)").
|
||||||
Where("product_id = ? AND is_del = ?", req.ProductID, 0).
|
Where("product_id = ? AND is_del = ?", req.ProductID, 0).
|
||||||
Scan(&totalQuantity)
|
Scan(&totalQuantity)
|
||||||
|
}
|
||||||
|
|
||||||
return &systemRes.ProductInventoryResponse{
|
return &systemRes.ProductInventoryResponse{
|
||||||
Quantity: totalQuantity,
|
Quantity: totalQuantity,
|
||||||
@ -1443,7 +1548,8 @@ func (s *ProductService) PushProductToShop(req systemReq.PushProductToShopReques
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ProductService) batchPushProductBody(db *gorm.DB, outTask models.OutTask, product models.Product, stock, salePrice, cost, now, userID int64, warehouseCode string, locationCode string, condition int64) {
|
// 批量上架
|
||||||
|
/*func (s *ProductService) batchPushProductBody(db *gorm.DB, outTask models.OutTask, product models.Product, stock, salePrice, cost, now, userID int64, warehouseCode string, locationCode string, condition int64) {
|
||||||
isbn := product.Barcode
|
isbn := product.Barcode
|
||||||
var imgList []string
|
var imgList []string
|
||||||
if product.LiveImage != nil && len(product.LiveImage) > 0 {
|
if product.LiveImage != nil && len(product.LiveImage) > 0 {
|
||||||
@ -1527,6 +1633,89 @@ func (s *ProductService) batchPushProductBody(db *gorm.DB, outTask models.OutTas
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// batchPushProductBody 批量上架商品到外部任务
|
||||||
|
func (s *ProductService) batchPushProductBody(db *gorm.DB, outTask models.OutTask, product models.Product, stock, salePrice, cost, now, userID int64, warehouseCode string, locationCode string, condition int64) {
|
||||||
|
isbn := product.Barcode
|
||||||
|
|
||||||
|
// 使用 parseImageList 解析图片列表,支持多种格式
|
||||||
|
imgList := s.parseImageList(product.LiveImage)
|
||||||
|
|
||||||
|
msgData := map[string]interface{}{
|
||||||
|
"product_id": product.ID,
|
||||||
|
"user_id": strconv.FormatInt(userID, 10),
|
||||||
|
"is_distribution": "1",
|
||||||
|
}
|
||||||
|
msgJSON, _ := json.Marshal(msgData)
|
||||||
|
|
||||||
|
bodyData := map[string]interface{}{
|
||||||
|
"book_info": map[string]interface{}{
|
||||||
|
"isbn": isbn,
|
||||||
|
"image_object": map[string]interface{}{
|
||||||
|
"carousel_url_array": imgList,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"detail": map[string]interface{}{
|
||||||
|
"stock": stock,
|
||||||
|
"price": salePrice,
|
||||||
|
"shipping_cost": cost,
|
||||||
|
"msg": string(msgJSON),
|
||||||
|
"sku_code": warehouseCode + "##" + locationCode,
|
||||||
|
"condition": condition,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
bodyDataJSON, err := json.Marshal(bodyData)
|
||||||
|
if err != nil {
|
||||||
|
s.saveOutTaskLogWithStock(outTask, product.ID, isbn, product.LiveImage, stock, salePrice, cost, fmt.Sprintf("序列化请求体失败: %v", err), db)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
bodyList := []string{string(bodyDataJSON)}
|
||||||
|
taskID := fmt.Sprintf("%d", outTask.OutTaskID)
|
||||||
|
allBody := strings.Join(bodyList, "")
|
||||||
|
|
||||||
|
signParams := map[string]string{
|
||||||
|
"task_id": taskID,
|
||||||
|
"body": allBody,
|
||||||
|
}
|
||||||
|
|
||||||
|
sign := utils.SignParams(signParams)
|
||||||
|
|
||||||
|
url := config.AppConfig.ExternalAPI.SyncTaskBodyURL
|
||||||
|
resp, err := utils.SubmitMultiBody(url, taskID, bodyList, sign)
|
||||||
|
if err != nil {
|
||||||
|
s.saveOutTaskLogWithStock(outTask, product.ID, isbn, product.LiveImage, stock, salePrice, cost, fmt.Sprintf("请求外部接口失败: %v", err), db)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var resData systemRes.ExternalAPIResponse
|
||||||
|
if err := json.Unmarshal([]byte(resp), &resData); err != nil {
|
||||||
|
s.saveOutTaskLogWithStock(outTask, product.ID, isbn, product.LiveImage, stock, salePrice, cost, fmt.Sprintf("解析响应失败: %v", err), db)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if resData.Code != "200" {
|
||||||
|
s.saveOutTaskLogWithStock(outTask, product.ID, isbn, product.LiveImage, stock, salePrice, cost, fmt.Sprintf("外部接口返回错误: code=%s, msg=%s", resData.Code, resData.Msg), db)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if updateErr := db.Model(&models.OutTaskLog{}).
|
||||||
|
Where("shop_id = ? AND product_id = ? AND is_del = ?", outTask.ShopID, product.ID, 0).
|
||||||
|
Updates(map[string]interface{}{
|
||||||
|
"status": 1,
|
||||||
|
"msg": "成功",
|
||||||
|
"updated_at": now,
|
||||||
|
}).Error; updateErr != nil {
|
||||||
|
utils.ErrorLog(constant.LoggerChannelWork, map[string]interface{}{
|
||||||
|
"source": "批量推送-更新历史日志状态失败",
|
||||||
|
"shop_id": outTask.ShopID,
|
||||||
|
"product_id": product.ID,
|
||||||
|
"error": fmt.Sprintf("更新失败: %v", updateErr),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// saveRetryLog 保存重试任务日志
|
// saveRetryLog 保存重试任务日志
|
||||||
func (s *ProductService) saveRetryLog(shopID, outTaskID, productID int64, product models.Product, waveTaskDetail models.WaveTaskDetail, hasWaveTask bool, msg string, db *gorm.DB) {
|
func (s *ProductService) saveRetryLog(shopID, outTaskID, productID int64, product models.Product, waveTaskDetail models.WaveTaskDetail, hasWaveTask bool, msg string, db *gorm.DB) {
|
||||||
@ -1765,7 +1954,7 @@ func (s *ProductService) syncPriceToExternal(waveTaskDetail models.WaveTaskDetai
|
|||||||
}
|
}
|
||||||
|
|
||||||
// syncPriceToExternalTask 同步售价到单个外部任务
|
// syncPriceToExternalTask 同步售价到单个外部任务
|
||||||
func (s *ProductService) syncPriceToExternalTask(outTask models.OutTask, product models.Product, waveTaskDetail models.WaveTaskDetail, salePrice, cost, userId int64, db *gorm.DB) error {
|
/*func (s *ProductService) syncPriceToExternalTask(outTask models.OutTask, product models.Product, waveTaskDetail models.WaveTaskDetail, salePrice, cost, userId int64, db *gorm.DB) error {
|
||||||
isbn := product.Barcode
|
isbn := product.Barcode
|
||||||
var imgList []string
|
var imgList []string
|
||||||
if product.LiveImage != nil && len(product.LiveImage) > 0 {
|
if product.LiveImage != nil && len(product.LiveImage) > 0 {
|
||||||
@ -1837,6 +2026,78 @@ func (s *ProductService) syncPriceToExternalTask(outTask models.OutTask, product
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// syncPriceToExternalTask 同步售价到单个外部任务
|
||||||
|
func (s *ProductService) syncPriceToExternalTask(outTask models.OutTask, product models.Product, waveTaskDetail models.WaveTaskDetail, salePrice, cost, userId int64, db *gorm.DB) error {
|
||||||
|
isbn := product.Barcode
|
||||||
|
|
||||||
|
// 使用 parseImageList 解析图片列表,支持多种格式
|
||||||
|
imgList := s.parseImageList(product.LiveImage)
|
||||||
|
|
||||||
|
msgData := map[string]interface{}{
|
||||||
|
"product_id": product.ID,
|
||||||
|
"user_id": fmt.Sprintf("%d", userId),
|
||||||
|
}
|
||||||
|
msgJSON, _ := json.Marshal(msgData)
|
||||||
|
|
||||||
|
bodyData := map[string]interface{}{
|
||||||
|
"book_info": map[string]interface{}{
|
||||||
|
"isbn": isbn,
|
||||||
|
"image_object": map[string]interface{}{
|
||||||
|
"carousel_url_array": imgList,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"detail": map[string]interface{}{
|
||||||
|
"stock": waveTaskDetail.PlannedQuantity,
|
||||||
|
"price": salePrice,
|
||||||
|
"shipping_cost": cost,
|
||||||
|
"msg": string(msgJSON),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
bodyDataJSON, err := json.Marshal(bodyData)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("序列化请求体失败: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
bodyList := []string{
|
||||||
|
string(bodyDataJSON),
|
||||||
|
}
|
||||||
|
|
||||||
|
taskID := fmt.Sprintf("%d", outTask.OutTaskID)
|
||||||
|
|
||||||
|
allBody := strings.Join(bodyList, "") // 直接无缝拼接(和服务端一致)
|
||||||
|
|
||||||
|
signParams := map[string]string{
|
||||||
|
"task_id": taskID,
|
||||||
|
"body": allBody,
|
||||||
|
}
|
||||||
|
|
||||||
|
sign := utils.SignParams(signParams)
|
||||||
|
|
||||||
|
// 发送请求
|
||||||
|
url := config.AppConfig.ExternalAPI.SyncTaskBodyURL
|
||||||
|
resp, err := utils.SubmitMultiBody(url, taskID, bodyList, sign)
|
||||||
|
if err != nil {
|
||||||
|
s.saveOutTaskLog(outTask, product.ID, isbn, product.LiveImage, waveTaskDetail.PlannedQuantity, salePrice, cost, fmt.Sprintf("请求外部接口失败: %v", err), db)
|
||||||
|
return fmt.Errorf("请求外部接口失败: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var resData systemRes.ExternalAPIResponse
|
||||||
|
if err := json.Unmarshal([]byte(resp), &resData); err != nil {
|
||||||
|
return fmt.Errorf("解析响应失败: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if resData.Code != "200" {
|
||||||
|
s.saveOutTaskLog(outTask, product.ID, isbn, product.LiveImage, waveTaskDetail.PlannedQuantity, salePrice, cost, fmt.Sprintf("外部接口返回错误: code=%s, msg=%s", resData.Code, resData.Msg), db)
|
||||||
|
return fmt.Errorf("外部接口返回错误: code=%s, msg=%s", resData.Code, resData.Msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
s.saveOutTaskLog(outTask, product.ID, isbn, product.LiveImage, waveTaskDetail.PlannedQuantity, salePrice, cost, "成功", db)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// saveOutTaskLog 保存外部任务日志
|
// saveOutTaskLog 保存外部任务日志
|
||||||
func (s *ProductService) saveOutTaskLog(outTask models.OutTask, productID int64, isbn string, liveImage []byte, stock, salePrice, cost int64, msg string, db *gorm.DB) {
|
func (s *ProductService) saveOutTaskLog(outTask models.OutTask, productID int64, isbn string, liveImage []byte, stock, salePrice, cost int64, msg string, db *gorm.DB) {
|
||||||
@ -2687,6 +2948,45 @@ func (s *ProductService) convertProductLogToItem(log models.ProductLog) systemRe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// parseImageList 解析图片列表,支持JSON数组和逗号分隔字符串两种格式
|
||||||
|
func (s *ProductService) parseImageList(liveImage datatypes.JSON) []string {
|
||||||
|
if liveImage == nil || len(liveImage) == 0 {
|
||||||
|
return []string{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 尝试解析为字符串数组
|
||||||
|
var imgList []string
|
||||||
|
if err := json.Unmarshal(liveImage, &imgList); err == nil {
|
||||||
|
// 成功解析为数组,过滤空字符串后返回
|
||||||
|
result := make([]string, 0, len(imgList))
|
||||||
|
for _, img := range imgList {
|
||||||
|
trimmed := strings.TrimSpace(img)
|
||||||
|
if trimmed != "" {
|
||||||
|
result = append(result, trimmed)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果解析失败,尝试解析为字符串,然后按逗号分割
|
||||||
|
var imgStr string
|
||||||
|
if err := json.Unmarshal(liveImage, &imgStr); err == nil {
|
||||||
|
// 去除空格并按逗号分割
|
||||||
|
parts := strings.Split(imgStr, ",")
|
||||||
|
result := make([]string, 0, len(parts))
|
||||||
|
for _, part := range parts {
|
||||||
|
trimmed := strings.TrimSpace(part)
|
||||||
|
if trimmed != "" {
|
||||||
|
result = append(result, trimmed)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// 都不成功,返回空数组
|
||||||
|
return []string{}
|
||||||
|
}
|
||||||
|
|
||||||
func (s *ProductService) getShopTypeName(shopType int8) string {
|
func (s *ProductService) getShopTypeName(shopType int8) string {
|
||||||
switch shopType {
|
switch shopType {
|
||||||
case 1:
|
case 1:
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user