diff --git a/models/request/inventory.go b/models/request/inventory.go index 4af9e67..abc0c5b 100644 --- a/models/request/inventory.go +++ b/models/request/inventory.go @@ -6,16 +6,19 @@ type GetInventoryListRequest struct { PageSize int `form:"page_size"` // 分页大小 ProductId int64 `form:"product_id"` // 商品ID WarehouseID int64 `form:"warehouse_id"` // 仓库ID + LocationID int64 `form:"location_id"` // 库位ID ISBN string `form:"isbn"` // ISBN Name string `form:"name"` // 商品名称 } // GetInventoryGroupedListRequest 获取按仓库库位分组的库存列表请求 type GetInventoryGroupedListRequest struct { - Page int `form:"page"` // 页码 - PageSize int `form:"page_size"` // 分页大小 - ProductId int64 `form:"product_id"` // 商品ID - WarehouseID int64 `form:"warehouse_id"` // 仓库ID + Page int `form:"page"` // 页码 + PageSize int `form:"page_size"` // 分页大小 + ProductId int64 `form:"product_id"` // 商品ID + WarehouseID int64 `form:"warehouse_id"` // 仓库ID + LocationID int64 `form:"location_id"` // 库位ID + Keyword string `form:"keyword"` // 关键词搜索(库位编号/商品名称/条码) } // GetInventoryDetailRequest 获取库存明细请求 @@ -30,6 +33,7 @@ type GetInventoryLogListRequest struct { ISBN string `form:"isbn"` // ISBN BookName string `form:"book_name"` // 图书名称 WarehouseID int64 `form:"warehouse_id"` // 仓库ID + LocationID int64 `form:"location_id"` // 库位ID ChangeType int8 `form:"change_type"` // 库存流水类型 RelatedOrderNo string `form:"related_order_no"` // 关联订单号 StartDate int64 `form:"start_date"` // 开始时间 diff --git a/models/request/outbound.go b/models/request/outbound.go index 1cb1444..3ccd658 100644 --- a/models/request/outbound.go +++ b/models/request/outbound.go @@ -8,6 +8,7 @@ type GetOutboundOrderListRequest struct { Status int8 `form:"status"` CustomerID int64 `form:"customer_id"` WarehouseID int64 `form:"warehouse_id"` + LocationID int64 `form:"location_id"` StartDate int64 `form:"start_date"` EndDate int64 `form:"end_date"` AssociationOrderNo string `form:"association_order_no"` diff --git a/models/request/sales.go b/models/request/sales.go index f6c23cb..0e28cf3 100644 --- a/models/request/sales.go +++ b/models/request/sales.go @@ -8,6 +8,7 @@ type GetSalesOrderListRequest struct { Status int8 `form:"status"` CustomerID int64 `form:"customer_id"` WarehouseID int64 `form:"warehouse_id"` + LocationID int64 `form:"location_id"` StartDate int64 `form:"start_date"` EndDate int64 `form:"end_date"` AssociationOrderNo string `form:"association_order_no"` @@ -22,18 +23,13 @@ type GetSalesOrderDetailRequest struct { // GetSalesOrderDetailListRequest 获取销售订单详情列表请求 type GetSalesOrderDetailListRequest struct { - Page int `form:"page"` - PageSize int `form:"page_size"` - //SoNo string `form:"so_no"` - //Status int8 `form:"status"` - //CustomerID int64 `form:"customer_id"` - //WarehouseID int64 `form:"warehouse_id"` - //StartDate int64 `form:"start_date"` - //EndDate int64 `form:"end_date"` + Page int `form:"page"` + PageSize int `form:"page_size"` SoNo string `form:"so_no"` Status int8 `form:"status"` CustomerID int64 `form:"customer_id"` WarehouseID int64 `form:"warehouse_id"` + LocationID int64 `form:"location_id"` StartDate int64 `form:"start_date"` EndDate int64 `form:"end_date"` AssociationOrderNo string `form:"association_order_no"` diff --git a/models/request/shipping.go b/models/request/shipping.go index 3bc8034..35ff292 100644 --- a/models/request/shipping.go +++ b/models/request/shipping.go @@ -12,6 +12,8 @@ type GetShippingOrderListRequest struct { AssociationOrderNo string `form:"association_order_no" json:"association_order_no"` LogisticsNo string `form:"logistics_no" json:"logistics_no"` ShopType int `form:"shop_type" json:"shop_type"` + WarehouseID int64 `form:"warehouse_id" json:"warehouse_id"` + LocationID int64 `form:"location_id" json:"location_id"` } // GetShippingOrderDetailRequest 获取发货单详情请求 @@ -31,4 +33,6 @@ type GetShippingOrderDetailListRequest struct { AssociationOrderNo string `form:"association_order_no" json:"association_order_no"` LogisticsNo string `form:"logistics_no" json:"logistics_no"` ShopType int `form:"shop_type" json:"shop_type"` + WarehouseID int64 `form:"warehouse_id" json:"warehouse_id"` + LocationID int64 `form:"location_id" json:"location_id"` } diff --git a/models/response/sales.go b/models/response/sales.go index 0774939..9b3554a 100644 --- a/models/response/sales.go +++ b/models/response/sales.go @@ -52,6 +52,7 @@ type SalesOrderItem struct { SalesPersonID int64 `json:"sales_person_id"` Remark string `json:"remark"` LogisticsNo string `json:"logistics_no"` + LocationCode string `json:"location_code"` CreatedAt int64 `json:"created_at"` UpdatedAt int64 `json:"updated_at"` } @@ -107,7 +108,7 @@ type SalesOrderDetailItem struct { } // ConvertSalesOrderToItem 将销售订单模型转换为响应项 -func ConvertSalesOrderToItem(order models.SalesOrder, customerName string, warehouseName string, logisticsNo string) SalesOrderItem { +func ConvertSalesOrderToItem(order models.SalesOrder, customerName string, warehouseName string, logisticsNo string, locationCode string) SalesOrderItem { return SalesOrderItem{ ID: order.ID, SoNo: order.SoNo, @@ -129,6 +130,7 @@ func ConvertSalesOrderToItem(order models.SalesOrder, customerName string, wareh SalesPersonID: order.SalesPersonID, Remark: order.Remark, LogisticsNo: logisticsNo, + LocationCode: locationCode, CreatedAt: order.CreatedAt, UpdatedAt: order.UpdatedAt, } diff --git a/models/response/statist.go b/models/response/statist.go index 328f730..3fe4346 100644 --- a/models/response/statist.go +++ b/models/response/statist.go @@ -5,11 +5,13 @@ type DashboardStatistResponse struct { TotalOrderCount int64 `json:"total_order_count"` // 今日订单数 TotalReceivingCount int64 `json:"total_receiving_count"` // 今日入库数 TotalOutboundCount int64 `json:"total_outbound_count"` // 今日出库数 - TotalSaleCount int64 `json:"total_sale_count"` // 今日销售数 + TotalSaleCount int64 `json:"total_sale_count"` // 今日销售数(保留兼容) + TodaySaleAmount int64 `json:"today_sale_amount"` // 今日销售金额(分) YesterdayOrderCount int64 `json:"yesterday_order_count"` // 昨日订单数 YesterdayReceivingCount int64 `json:"yesterday_receiving_count"` // 昨日入库数 YesterdayOutboundCount int64 `json:"yesterday_outbound_count"` // 昨日出库数 - YesterdaySaleCount int64 `json:"yesterday_sale_count"` // 昨日销售数 + YesterdaySaleCount int64 `json:"yesterday_sale_count"` // 昨日销售数(保留兼容) + YesterdaySaleAmount int64 `json:"yesterday_sale_amount"` // 昨日销售金额(分) UserStats []UserStatItem `json:"user_stats"` // 个人统计数据 ProductTotal int64 `json:"product_total"` // 商品总量 InventoryTotal int64 `json:"inventory_total"` // 库存量 diff --git a/models/response/store_info.go b/models/response/store_info.go index d446d28..2520ebf 100644 --- a/models/response/store_info.go +++ b/models/response/store_info.go @@ -4,7 +4,7 @@ package response type StoreInfoResponse struct { StoreName string `json:"store_name"` // 店铺名称 StoreType string `json:"store_type"` // 店铺类型描述 - SaleCount int64 `json:"sale_count"` // 销售数量(时间范围内该店铺的销售订单数) + SaleAmount int64 `json:"sale_amount"` // 销售金额(时间范围内该店铺的销售订单总金额,单位:分) OutboundCount int64 `json:"outbound_count"` // 出库次数(当前表结构无店铺维度,暂返回 0) ReceivingCount int64 `json:"receiving_count"` // 入库次数(当前表结构无店铺维度,暂返回 0) OrderCount int64 `json:"order_count"` // 订单数量(同 sale_count,从 sales_order 表统计) diff --git a/service/inventory.go b/service/inventory.go index 4718d9c..afe043a 100644 --- a/service/inventory.go +++ b/service/inventory.go @@ -51,6 +51,9 @@ func (s *InventoryService) GetInventoryList(req systemReq.GetInventoryListReques if req.WarehouseID > 0 { query = query.Where("inventory.warehouse_id = ?", req.WarehouseID) } + if req.LocationID > 0 { + query = query.Where("i.location_id = ?", req.LocationID) + } if req.ISBN != "" { query = query.Where("p.barcode LIKE ?", "%"+req.ISBN+"%") } @@ -142,12 +145,21 @@ func (s *InventoryService) GetInventoryGroupedList(req systemReq.GetInventoryGro `). Joins("LEFT JOIN warehouse w ON inventory_detail.warehouse_id = w.id AND w.is_del = 0"). Joins("LEFT JOIN location l ON inventory_detail.location_id = l.id AND l.is_del = 0"). + Joins("LEFT JOIN product p ON inventory_detail.product_id = p.id AND p.is_del = 0"). Where("inventory_detail.is_del = ?", 0). Group("inventory_detail.warehouse_id, w.name, w.code, inventory_detail.location_id, l.code") if req.WarehouseID > 0 { groupQuery = groupQuery.Where("inventory_detail.warehouse_id = ?", req.WarehouseID) } + if req.LocationID > 0 { + groupQuery = groupQuery.Where("inventory_detail.location_id = ?", req.LocationID) + } + + if req.Keyword != "" { + kw := "%" + req.Keyword + "%" + groupQuery = groupQuery.Where("(l.code LIKE ? OR p.name LIKE ? OR p.barcode LIKE ?)", kw, kw, kw) + } var total int64 if err := groupQuery.Count(&total).Error; err != nil { @@ -199,6 +211,10 @@ func (s *InventoryService) GetInventoryGroupedList(req systemReq.GetInventoryGro if req.ProductId > 0 { detailQuery = detailQuery.Where("inventory_detail.product_id = ?", req.ProductId) } + if req.Keyword != "" { + kw := "%" + req.Keyword + "%" + detailQuery = detailQuery.Where("(p.name LIKE ? OR p.barcode LIKE ?)", kw, kw) + } var details []struct { models.InventoryDetail @@ -459,6 +475,9 @@ func (s *InventoryService) GetInventoryLogList(req systemReq.GetInventoryLogList if req.WarehouseID > 0 { query = query.Where("inventory_log.warehouse_id = ?", req.WarehouseID) } + if req.LocationID > 0 { + query = query.Where("inventory_log.location_id = ?", req.LocationID) + } if req.ChangeType > 0 { query = query.Where("inventory_log.change_type = ?", req.ChangeType) } diff --git a/service/outbound.go b/service/outbound.go index d2d6498..9cc8168 100644 --- a/service/outbound.go +++ b/service/outbound.go @@ -35,6 +35,12 @@ func (s *OutboundService) GetOutboundOrderList(req systemReq.GetOutboundOrderLis if req.WarehouseID > 0 { query = query.Where("outbound_order.warehouse_id = ?", req.WarehouseID) } + if req.LocationID > 0 { + subQuery := databaseConn.Table("outbound_order_item"). + Select("outbound_order_item.out_order_id"). + Where("outbound_order_item.is_del = 0 AND outbound_order_item.location_id = ?", req.LocationID) + query = query.Where("outbound_order.id IN (?)", subQuery) + } if req.OutNo != "" { query = query.Where("outbound_order.out_no LIKE ?", "%"+req.OutNo+"%") } diff --git a/service/sales.go b/service/sales.go index b9e16d5..4fb3634 100644 --- a/service/sales.go +++ b/service/sales.go @@ -60,6 +60,14 @@ func (s *SalesService) GetSalesOrderList(req systemReq.GetSalesOrderListRequest, if req.ShopType > 0 { query = query.Where("sales_order.shop_type = ?", req.ShopType) } + if req.LocationID > 0 { + subQuery := databaseConn.Table("sales_order_item soi"). + Select("DISTINCT soi.sales_order_id"). + Joins("JOIN product p ON soi.product_id = p.id AND p.is_del = 0"). + Joins("JOIN inventory_detail id ON p.id = id.product_id AND id.is_del = 0"). + Where("id.location_id = ?", req.LocationID) + query = query.Where("sales_order.id IN (?)", subQuery) + } var total int64 if err := query.Count(&total).Error; err != nil { @@ -109,6 +117,26 @@ func (s *SalesService) GetSalesOrderList(req systemReq.GetSalesOrderListRequest, logByOrderID[row.SalesOrderID] = row.LogisticsNos } + // 收集库位编码(通过 sales_order_item → product → inventory_detail → location 链路) + type locRow struct { + SalesOrderID int64 `gorm:"column:sales_order_id"` + LocationCodes string `gorm:"column:location_codes"` + } + var locRows []locRow + databaseConn.Table("sales_order_item"). + Select("sales_order_id, COALESCE(GROUP_CONCAT(DISTINCT l.code SEPARATOR ', '), '') as location_codes"). + Joins("JOIN product p ON sales_order_item.product_id = p.id AND p.is_del = 0"). + Joins("JOIN inventory_detail id ON p.id = id.product_id AND id.is_del = 0"). + Joins("JOIN location l ON id.location_id = l.id"). + Where("sales_order_id IN ? AND sales_order_item.is_del = ?", orderIDs, 0). + Group("sales_order_id"). + Scan(&locRows) + + locByOrderID := make(map[int64]string, len(locRows)) + for _, row := range locRows { + locByOrderID[row.SalesOrderID] = row.LocationCodes + } + orderItems := make([]systemRes.SalesOrderItem, 0, len(orders)) for _, order := range orders { orderItems = append(orderItems, systemRes.ConvertSalesOrderToItem( @@ -116,6 +144,7 @@ func (s *SalesService) GetSalesOrderList(req systemReq.GetSalesOrderListRequest, order.CustomerName, order.WarehouseName, logByOrderID[order.ID], + locByOrderID[order.ID], )) } @@ -190,6 +219,14 @@ func (s *SalesService) GetSalesOrderDetailList(req systemReq.GetSalesOrderDetail if req.ShopType > 0 { query = query.Where("sales_order.shop_type = ?", req.ShopType) } + if req.LocationID > 0 { + subQuery := databaseConn.Table("sales_order_item soi"). + Select("DISTINCT soi.sales_order_id"). + Joins("JOIN product p ON soi.product_id = p.id AND p.is_del = 0"). + Joins("JOIN inventory_detail id ON p.id = id.product_id AND id.is_del = 0"). + Where("id.location_id = ?", req.LocationID) + query = query.Where("sales_order.id IN (?)", subQuery) + } var total int64 if err := query.Count(&total).Error; err != nil { diff --git a/service/shipping.go b/service/shipping.go index 190d6bf..36433fc 100644 --- a/service/shipping.go +++ b/service/shipping.go @@ -65,6 +65,21 @@ func (s *ShippingService) GetShippingOrderList(req systemReq.GetShippingOrderLis Where("shipping_order_item.is_del = 0 AND sales_order.shop_type = ?", req.ShopType) query = query.Where("shipping_order.id IN (?)", subQuery) } + if req.WarehouseID > 0 { + subQuery := databaseConn.Table("shipping_order_item"). + Select("shipping_order_item.shipping_order_id"). + Joins("INNER JOIN outbound_order_item ON shipping_order_item.outbound_order_item_id = outbound_order_item.id AND outbound_order_item.is_del = 0"). + Joins("INNER JOIN location ON outbound_order_item.location_id = location.id AND location.is_del = 0"). + Where("shipping_order_item.is_del = 0 AND location.warehouse_id = ?", req.WarehouseID) + query = query.Where("shipping_order.id IN (?)", subQuery) + } + if req.LocationID > 0 { + subQuery := databaseConn.Table("shipping_order_item"). + Select("shipping_order_item.shipping_order_id"). + Joins("INNER JOIN outbound_order_item ON shipping_order_item.outbound_order_item_id = outbound_order_item.id AND outbound_order_item.is_del = 0"). + Where("shipping_order_item.is_del = 0 AND outbound_order_item.location_id = ?", req.LocationID) + query = query.Where("shipping_order.id IN (?)", subQuery) + } var total int64 if err := query.Count(&total).Error; err != nil { @@ -339,6 +354,21 @@ func (s *ShippingService) GetShippingOrderDetailList(req systemReq.GetShippingOr Where("shipping_order_item.is_del = 0 AND sales_order.shop_type = ?", req.ShopType) query = query.Where("shipping_order.id IN (?)", subQuery) } + if req.WarehouseID > 0 { + subQuery := databaseConn.Table("shipping_order_item"). + Select("shipping_order_item.shipping_order_id"). + Joins("INNER JOIN outbound_order_item ON shipping_order_item.outbound_order_item_id = outbound_order_item.id AND outbound_order_item.is_del = 0"). + Joins("INNER JOIN location ON outbound_order_item.location_id = location.id AND location.is_del = 0"). + Where("shipping_order_item.is_del = 0 AND location.warehouse_id = ?", req.WarehouseID) + query = query.Where("shipping_order.id IN (?)", subQuery) + } + if req.LocationID > 0 { + subQuery := databaseConn.Table("shipping_order_item"). + Select("shipping_order_item.shipping_order_id"). + Joins("INNER JOIN outbound_order_item ON shipping_order_item.outbound_order_item_id = outbound_order_item.id AND outbound_order_item.is_del = 0"). + Where("shipping_order_item.is_del = 0 AND outbound_order_item.location_id = ?", req.LocationID) + query = query.Where("shipping_order.id IN (?)", subQuery) + } var total int64 if err := query.Count(&total).Error; err != nil { diff --git a/service/statist.go b/service/statist.go index 0a96a5c..18d9e27 100644 --- a/service/statist.go +++ b/service/statist.go @@ -223,8 +223,8 @@ func (s *StatistService) getDashboardStatRealtime(databaseConn *gorm.DB, startDa defer wg.Done() statErr = databaseConn.Model(&models.SalesOrder{}). Select(` - COALESCE(SUM(CASE WHEN created_at >= ? AND created_at <= ? THEN 1 ELSE 0 END), 0) as today_count, - COALESCE(SUM(CASE WHEN created_at >= ? AND created_at <= ? THEN 1 ELSE 0 END), 0) as yesterday_count + COALESCE(SUM(CASE WHEN created_at >= ? AND created_at <= ? THEN total_amount ELSE 0 END), 0) as today_count, + COALESCE(SUM(CASE WHEN created_at >= ? AND created_at <= ? THEN total_amount ELSE 0 END), 0) as yesterday_count `, todayStart, todayEnd, yesterdayStart, yesterdayEnd). Where("is_del = ?", 0). Scan(&salesStat).Error @@ -338,11 +338,11 @@ func (s *StatistService) getDashboardStatRealtime(databaseConn *gorm.DB, startDa TotalOrderCount: salesStat.TodayCount, TotalReceivingCount: receivingStat.TodayCount, TotalOutboundCount: outboundStat.TodayCount, - TotalSaleCount: salesStat.TodayCount, + TodaySaleAmount: salesStat.TodayCount, YesterdayOrderCount: salesStat.YesterdayCount, YesterdayReceivingCount: receivingStat.YesterdayCount, YesterdayOutboundCount: outboundStat.YesterdayCount, - YesterdaySaleCount: salesStat.YesterdayCount, + YesterdaySaleAmount: salesStat.YesterdayCount, UserStats: userStats, ProductTotal: productTotal, InventoryTotal: inventoryTotal, diff --git a/service/store_info.go b/service/store_info.go index 90a3572..790fe75 100644 --- a/service/store_info.go +++ b/service/store_info.go @@ -76,6 +76,7 @@ func (s *StoreInfoService) StoreInfo(req systemReq.StoreInfoRequest, db ...*gorm type storeStat struct { ShopName string SaleCount int64 + SaleAmount int64 OutboundCount int64 ReceivingCount int64 ShippingCount int64 @@ -93,10 +94,11 @@ func (s *StoreInfoService) StoreInfo(req systemReq.StoreInfoRequest, db ...*gorm type row struct { Name string `gorm:"column:sales_person"` Cnt int64 `gorm:"column:cnt"` + Amt int64 `gorm:"column:amt"` } var rows []row err := databaseConn.Raw(` - SELECT sales_person, COUNT(*) AS cnt + SELECT sales_person, COUNT(*) AS cnt, COALESCE(SUM(total_amount), 0) AS amt FROM sales_order WHERE is_del = 0 AND created_at >= ? AND created_at <= ? AND sales_person != '' GROUP BY sales_person @@ -115,6 +117,7 @@ func (s *StoreInfoService) StoreInfo(req systemReq.StoreInfoRequest, db ...*gorm statByName[n] = &storeStat{ShopName: n} } statByName[n].SaleCount = r.Cnt + statByName[n].SaleAmount = r.Amt } mu.Unlock() }() @@ -254,7 +257,7 @@ func (s *StoreInfoService) StoreInfo(req systemReq.StoreInfoRequest, db ...*gorm result = append(result, systemRes.StoreInfoResponse{ StoreName: name, StoreType: storeType, - SaleCount: st.SaleCount, + SaleAmount: st.SaleAmount, OutboundCount: st.OutboundCount, ReceivingCount: st.ReceivingCount, OrderCount: st.SaleCount,