2.在商品管理下的商品列表接口里 分别统计:已落位 locatedCount, 未落位 unlocatedCount, 启用中 enabledCount, 已禁用 disabledCount 4个字段并进行返回 3.新增一个接口 对商品名称字段进行修改,对实拍图字段修改,实拍图可以为单图或者多图 4.波次任务列表- 缺少统计信息:分别为今日入库波次数 today_inbound_waves, 昨日入库波次数 ,yesterday_inbound_waves 今日入库数量,today_inbound_qty 昨日入库数量,yesterday_inbound_qty 今日出库数量,today_outbound_qty 昨日出库数量 yesterday_outbound_qty 5.采购单列表- 缺少导出到旺店通功能
350 lines
11 KiB
Go
350 lines
11 KiB
Go
package service
|
|
|
|
import (
|
|
"encoding/json"
|
|
"psi/constant"
|
|
|
|
"fmt"
|
|
"psi/config"
|
|
|
|
"psi/database"
|
|
"psi/models"
|
|
systemReq "psi/models/request"
|
|
systemRes "psi/models/response"
|
|
|
|
"psi/utils"
|
|
"time"
|
|
|
|
"github.com/xuri/excelize/v2"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
type PurchaseService struct{}
|
|
|
|
// ExportPurchaseOrderToWDT 导出采购单到旺店通
|
|
func (s *PurchaseService) ExportPurchaseOrderToWDT(req systemReq.ExportPurchaseOrderToWDTRequest, creatorID int64, role int64, db ...*gorm.DB) (*systemRes.ExportProductResponse, error) {
|
|
databaseConn := database.OptionalDB(db...)
|
|
|
|
query := databaseConn.Model(&models.PurchaseOrder{}).Where("purchase_order.is_del = ?", 0)
|
|
|
|
if role == 128 {
|
|
query = query.Where("purchase_order.creator_id = ?", creatorID)
|
|
}
|
|
if len(req.IDs) > 0 {
|
|
query = query.Where("purchase_order.id IN ?", req.IDs)
|
|
}
|
|
if req.Status > 0 {
|
|
query = query.Where("purchase_order.status = ?", req.Status)
|
|
}
|
|
if req.SupplierID > 0 {
|
|
query = query.Where("purchase_order.supplier_id = ?", req.SupplierID)
|
|
}
|
|
if req.WarehouseID > 0 {
|
|
query = query.Where("purchase_order.warehouse_id = ?", req.WarehouseID)
|
|
}
|
|
if req.PoNo != "" {
|
|
query = query.Where("purchase_order.po_no LIKE ?", "%"+req.PoNo+"%")
|
|
}
|
|
if req.StartDate > 0 {
|
|
query = query.Where("purchase_order.created_at >= ?", req.StartDate)
|
|
}
|
|
if req.EndDate > 0 {
|
|
query = query.Where("purchase_order.created_at <= ?", req.EndDate)
|
|
}
|
|
|
|
var total int64
|
|
if err := query.Count(&total).Error; err != nil {
|
|
return nil, utils.NewError("查询总数失败")
|
|
}
|
|
|
|
if total == 0 {
|
|
return nil, fmt.Errorf("没有符合条件的采购单数据")
|
|
}
|
|
|
|
type PurchaseOrderExportData struct {
|
|
PoNo string `gorm:"column:po_no"`
|
|
SupplierName string `gorm:"column:supplier_name"`
|
|
WarehouseName string `gorm:"column:warehouse_name"`
|
|
ProductName string `gorm:"column:product_name"`
|
|
Barcode string `gorm:"column:barcode"`
|
|
Quantity int64 `gorm:"column:quantity"`
|
|
UnitPrice int64 `gorm:"column:unit_price"`
|
|
Amount int64 `gorm:"column:amount"`
|
|
OrderDate int64 `gorm:"column:order_date"`
|
|
ExpectedArrivalDate int64 `gorm:"column:expected_arrival_date"`
|
|
Status int8 `gorm:"column:status"`
|
|
Creator string `gorm:"column:creator"`
|
|
Remark string `gorm:"column:remark"`
|
|
}
|
|
|
|
var orders []PurchaseOrderExportData
|
|
if err := query.Select(`purchase_order.po_no,
|
|
s.name as supplier_name,
|
|
w.name as warehouse_name,
|
|
p.name as product_name,
|
|
p.barcode,
|
|
poi.quantity,
|
|
poi.unit_price,
|
|
poi.amount,
|
|
purchase_order.order_date,
|
|
purchase_order.expected_arrival_date,
|
|
purchase_order.status,
|
|
purchase_order.creator,
|
|
purchase_order.remark`).
|
|
Joins("LEFT JOIN supplier s ON purchase_order.supplier_id = s.id AND s.is_del = 0").
|
|
Joins("LEFT JOIN warehouse w ON purchase_order.warehouse_id = w.id AND w.is_del = 0").
|
|
Joins("LEFT JOIN purchase_order_item poi ON poi.purchase_order_id = purchase_order.id AND poi.is_del = 0").
|
|
Joins("LEFT JOIN product p ON poi.product_id = p.id AND p.is_del = 0").
|
|
Order("purchase_order.created_at DESC").
|
|
Find(&orders).Error; err != nil {
|
|
return nil, utils.NewError("查询采购单数据失败")
|
|
}
|
|
|
|
f := excelize.NewFile()
|
|
defer func() {
|
|
if err := f.Close(); err != nil {
|
|
utils.ErrorLog(constant.LoggerChannelWork, map[string]interface{}{
|
|
"source": "关闭Excel文件",
|
|
"error": fmt.Sprintf("关闭失败: %v", err),
|
|
})
|
|
}
|
|
}()
|
|
|
|
sheetName := "Sheet1"
|
|
f.SetSheetName("Sheet1", sheetName)
|
|
|
|
headers := []string{"采购单号", "供应商", "仓库", "商品名称", "ISBN/条码", "采购数量", "单价(元)", "金额(元)", "订单日期", "预计到货日期", "状态", "创建人", "备注"}
|
|
for i, header := range headers {
|
|
cell, _ := excelize.CoordinatesToCellName(i+1, 1)
|
|
f.SetCellValue(sheetName, cell, header)
|
|
}
|
|
|
|
headerStyle, _ := f.NewStyle(&excelize.Style{
|
|
Font: &excelize.Font{
|
|
Bold: true,
|
|
Size: 12,
|
|
},
|
|
Alignment: &excelize.Alignment{
|
|
Horizontal: "center",
|
|
Vertical: "center",
|
|
},
|
|
Fill: excelize.Fill{
|
|
Type: "pattern",
|
|
Color: []string{"#E0E0E0"},
|
|
Pattern: 1,
|
|
},
|
|
})
|
|
f.SetCellStyle(sheetName, "A1", "M1", headerStyle)
|
|
|
|
statusMap := map[int8]string{
|
|
1: "草稿",
|
|
2: "已提交",
|
|
3: "已审核",
|
|
4: "部分收货",
|
|
5: "已收货",
|
|
6: "已取消",
|
|
}
|
|
|
|
for idx, order := range orders {
|
|
row := idx + 2
|
|
|
|
f.SetCellValue(sheetName, fmt.Sprintf("A%d", row), order.PoNo)
|
|
f.SetCellValue(sheetName, fmt.Sprintf("B%d", row), order.SupplierName)
|
|
f.SetCellValue(sheetName, fmt.Sprintf("C%d", row), order.WarehouseName)
|
|
f.SetCellValue(sheetName, fmt.Sprintf("D%d", row), order.ProductName)
|
|
f.SetCellValue(sheetName, fmt.Sprintf("E%d", row), order.Barcode)
|
|
f.SetCellValue(sheetName, fmt.Sprintf("F%d", row), order.Quantity)
|
|
f.SetCellValue(sheetName, fmt.Sprintf("G%d", row), float64(order.UnitPrice)/100.0)
|
|
f.SetCellValue(sheetName, fmt.Sprintf("H%d", row), float64(order.Amount)/100.0)
|
|
|
|
orderDateStr := time.Unix(order.OrderDate, 0).Format("2006-01-02")
|
|
f.SetCellValue(sheetName, fmt.Sprintf("I%d", row), orderDateStr)
|
|
|
|
expectedDateStr := time.Unix(order.ExpectedArrivalDate, 0).Format("2006-01-02")
|
|
f.SetCellValue(sheetName, fmt.Sprintf("J%d", row), expectedDateStr)
|
|
|
|
statusText := statusMap[order.Status]
|
|
if statusText == "" {
|
|
statusText = "未知"
|
|
}
|
|
f.SetCellValue(sheetName, fmt.Sprintf("K%d", row), statusText)
|
|
|
|
f.SetCellValue(sheetName, fmt.Sprintf("L%d", row), order.Creator)
|
|
f.SetCellValue(sheetName, fmt.Sprintf("M%d", row), order.Remark)
|
|
}
|
|
|
|
colWidths := map[string]float64{
|
|
"A": 20,
|
|
"B": 15,
|
|
"C": 15,
|
|
"D": 30,
|
|
"E": 15,
|
|
"F": 12,
|
|
"G": 12,
|
|
"H": 12,
|
|
"I": 15,
|
|
"J": 15,
|
|
"K": 12,
|
|
"L": 12,
|
|
"M": 30,
|
|
}
|
|
for col, width := range colWidths {
|
|
f.SetColWidth(sheetName, col, col, width)
|
|
}
|
|
|
|
now := time.Now()
|
|
fileName := fmt.Sprintf("purchase_order_wdt_%s.xlsx", now.Format("20060102150405"))
|
|
filePath := fmt.Sprintf("excel/%s", fileName)
|
|
|
|
if err := f.SaveAs(filePath); err != nil {
|
|
return nil, fmt.Errorf("保存Excel文件失败: %v", err)
|
|
}
|
|
|
|
return &systemRes.ExportProductResponse{
|
|
Total: total,
|
|
FileName: fileName,
|
|
FilePath: config.AppConfig.Server.Host + filePath,
|
|
}, nil
|
|
}
|
|
|
|
// GetPurchaseOrderList 获取采购订单列表
|
|
func (s *PurchaseService) GetPurchaseOrderList(req systemReq.GetPurchaseOrderListRequest, creatorID int64, role int64, db ...*gorm.DB) (*systemRes.PurchaseOrderListResponse, error) {
|
|
databaseConn := database.OptionalDB(db...)
|
|
|
|
if req.Page < 1 {
|
|
req.Page = 1
|
|
}
|
|
if req.PageSize < 1 || req.PageSize > 100 {
|
|
req.PageSize = 20
|
|
}
|
|
|
|
query := databaseConn.Model(&models.PurchaseOrder{}).Where("purchase_order.is_del = ?", 0)
|
|
if role == 128 {
|
|
query = query.Where("purchase_order.creator_id = ?", creatorID)
|
|
}
|
|
if req.Status > 0 {
|
|
query = query.Where("purchase_order.status = ?", req.Status)
|
|
}
|
|
if req.SupplierID > 0 {
|
|
query = query.Where("purchase_order.supplier_id = ?", req.SupplierID)
|
|
}
|
|
if req.WarehouseID > 0 {
|
|
query = query.Where("purchase_order.warehouse_id = ?", req.WarehouseID)
|
|
}
|
|
if req.PoNo != "" {
|
|
query = query.Where("purchase_order.po_no LIKE ?", "%"+req.PoNo+"%")
|
|
}
|
|
if req.StartDate > 0 {
|
|
query = query.Where("purchase_order.created_at >= ?", req.StartDate)
|
|
}
|
|
if req.EndDate > 0 {
|
|
query = query.Where("purchase_order.created_at <= ?", req.EndDate)
|
|
}
|
|
|
|
var total int64
|
|
if err := query.Count(&total).Error; err != nil {
|
|
return nil, utils.NewError("查询总数失败")
|
|
}
|
|
|
|
if total == 0 {
|
|
return &systemRes.PurchaseOrderListResponse{
|
|
List: []systemRes.PurchaseOrderItem{},
|
|
Total: 0,
|
|
Page: req.Page,
|
|
PageSize: req.PageSize,
|
|
}, nil
|
|
}
|
|
|
|
var orders []systemRes.OrderWithInfo
|
|
offset := (req.Page - 1) * req.PageSize
|
|
if err := query.Select("purchase_order.*, s.name as supplier_name, w.name as warehouse_name").
|
|
Joins("LEFT JOIN supplier s ON purchase_order.supplier_id = s.id AND s.is_del = 0").
|
|
Joins("LEFT JOIN warehouse w ON purchase_order.warehouse_id = w.id AND w.is_del = 0").
|
|
Order("purchase_order.created_at DESC").
|
|
Offset(offset).
|
|
Limit(req.PageSize).
|
|
Find(&orders).Error; err != nil {
|
|
return nil, utils.NewError("查询采购订单列表失败")
|
|
}
|
|
|
|
orderItems := make([]systemRes.PurchaseOrderItem, 0, len(orders))
|
|
for _, order := range orders {
|
|
orderItems = append(orderItems, systemRes.ConvertPurchaseOrderToItem(
|
|
order.PurchaseOrder,
|
|
order.SupplierName,
|
|
order.WarehouseName,
|
|
))
|
|
}
|
|
|
|
return &systemRes.PurchaseOrderListResponse{
|
|
List: orderItems,
|
|
Total: total,
|
|
Page: req.Page,
|
|
PageSize: req.PageSize,
|
|
}, nil
|
|
}
|
|
|
|
// GetPurchaseOrderDetail 获取采购订单详情
|
|
func (s *PurchaseService) GetPurchaseOrderDetail(id int64, creatorID int64, role int64, db ...*gorm.DB) (*systemRes.PurchaseOrderDetailResponse, error) {
|
|
databaseConn := database.OptionalDB(db...)
|
|
|
|
query := databaseConn.Model(&models.PurchaseOrder{}).
|
|
Select("purchase_order.*, s.name as supplier_name, w.name as warehouse_name").
|
|
Joins("LEFT JOIN supplier s ON purchase_order.supplier_id = s.id AND s.is_del = 0").
|
|
Joins("LEFT JOIN warehouse w ON purchase_order.warehouse_id = w.id AND w.is_del = 0").
|
|
Where("purchase_order.id = ? AND purchase_order.is_del = ?", id, 0)
|
|
|
|
if role == 128 {
|
|
query = query.Where("purchase_order.creator_id = ?", creatorID)
|
|
}
|
|
|
|
var order systemRes.OrderWithInfo
|
|
result := query.First(&order)
|
|
|
|
if result.Error != nil {
|
|
return nil, utils.NewError("采购订单不存在")
|
|
}
|
|
|
|
var items []systemRes.ItemWithProduct
|
|
databaseConn.Model(&models.PurchaseOrderItem{}).
|
|
Select("purchase_order_item.*, p.name as product_name, p.barcode as product_code, p.category_id,p.sale_price, c.name as category_name, p.live_image, roi.location_id, l.code as location_code").
|
|
Joins("LEFT JOIN product p ON purchase_order_item.product_id = p.id AND p.is_del = 0").
|
|
Joins("LEFT JOIN product_category c ON p.category_id = c.id AND c.is_del = 0").
|
|
Joins("LEFT JOIN receiving_order ro ON ro.purchase_order_id = purchase_order_item.purchase_order_id AND ro.is_del = 0").
|
|
Joins("LEFT JOIN receiving_order_item roi ON roi.receiving_order_id = ro.id AND roi.product_id = purchase_order_item.product_id AND roi.is_del = 0").
|
|
Joins("LEFT JOIN location l ON roi.location_id = l.id AND l.is_del = 0").
|
|
Where("purchase_order_item.purchase_order_id = ? AND purchase_order_item.is_del = ?", order.ID, 0).
|
|
Find(&items)
|
|
|
|
detailItems := make([]systemRes.PurchaseOrderDetailItem, 0, len(items))
|
|
for _, item := range items {
|
|
var imageList []string
|
|
if len(item.LiveImage) > 0 {
|
|
json.Unmarshal(item.LiveImage, &imageList)
|
|
}
|
|
|
|
detailItems = append(detailItems, systemRes.PurchaseOrderDetailItem{
|
|
ID: item.ID,
|
|
PurchaseOrderID: item.PurchaseOrderID,
|
|
ProductID: item.ProductID,
|
|
ProductName: item.ProductName,
|
|
ProductCode: item.ProductCode,
|
|
SalePrice: item.SalePrice,
|
|
CategoryID: item.CategoryID,
|
|
CategoryName: item.CategoryName,
|
|
LiveImage: imageList,
|
|
Quantity: item.Quantity,
|
|
ReceivedQuantity: item.ReceivedQuantity,
|
|
UnitPrice: item.UnitPrice,
|
|
Amount: item.Amount,
|
|
LocationID: item.LocationID,
|
|
LocationCode: item.LocationCode,
|
|
CreatedAt: item.CreatedAt,
|
|
UpdatedAt: item.UpdatedAt,
|
|
})
|
|
}
|
|
|
|
detail := systemRes.ConvertPurchaseOrderToDetail(order.PurchaseOrder, order.SupplierName, order.WarehouseName, detailItems)
|
|
return &detail, nil
|
|
}
|