Merge remote-tracking branch 'origin/0.8.X' into 0.8.X

This commit is contained in:
2026-01-27 09:40:03 +08:00
15 changed files with 1845 additions and 145 deletions

View File

@@ -17,6 +17,8 @@ import com.klp.ems.domain.vo.EnergyCostSummaryVo;
import com.klp.ems.domain.vo.WarehouseProductionCoilVo;
import com.klp.ems.domain.vo.WarehouseProductionStatVo;
import com.klp.ems.domain.vo.WmsEnergyCoilDailyVo;
import com.klp.ems.domain.vo.AuxMaterialBreakdownVo;
import com.klp.ems.domain.vo.SparePartBreakdownVo;
import com.klp.ems.service.IEnergyCostReportService;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
@@ -111,4 +113,16 @@ public class EnergyCostReportController extends BaseController {
}).collect(Collectors.toList());
ExcelUtil.exportExcel(exportList, "入场卷成本汇总", CoilTotalMergedExportVo.class, response);
}
@Log(title = "辅料分摊构成", businessType = BusinessType.OTHER)
@GetMapping("/material/aux/breakdown")
public TableDataInfo<AuxMaterialBreakdownVo> auxMaterialBreakdown(CoilTotalCostBo bo, PageQuery pageQuery) {
return reportService.auxMaterialBreakdown(bo, pageQuery);
}
@Log(title = "备件分摊构成", businessType = BusinessType.OTHER)
@GetMapping("/material/spare/breakdown")
public TableDataInfo<SparePartBreakdownVo> sparePartBreakdown(CoilTotalCostBo bo, PageQuery pageQuery) {
return reportService.sparePartBreakdown(bo, pageQuery);
}
}

View File

@@ -65,6 +65,15 @@ public class WmsEnergyCoilDailyController extends BaseController {
return R.ok(statistics);
}
/**
* 查询待操作钢卷的能源成本详情(单卷)
*/
@GetMapping("/pendingAction/detail")
public R<WmsEnergyCoilDailyVo> pendingActionDetail(@NotNull @RequestParam Long coilId) {
WmsEnergyCoilDailyVo detail = coilDailyService.queryPendingActionCoilCostDetail(coilId);
return R.ok(detail);
}
@Log(title = "钢卷能源分摊", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(WmsEnergyCoilDailyBo bo, HttpServletResponse response) {

View File

@@ -0,0 +1,34 @@
package com.klp.ems.domain.vo;
import lombok.Data;
import java.math.BigDecimal;
/**
* 辅料成本分摊构成 Vo
*/
@Data
public class AuxMaterialBreakdownVo {
/** 物料编码 */
private String itemCode;
/** 物料名称 */
private String itemName;
/** 规格 */
private String spec;
/** 单位 */
private String unit;
/** 全厂消耗总数量 */
private BigDecimal totalQty;
/** 全厂消耗总金额 */
private BigDecimal totalAmount;
/** 分摊数量 */
private BigDecimal allocatedQty;
/** 分摊金额 */
private BigDecimal allocatedAmount;
}

View File

@@ -0,0 +1,19 @@
package com.klp.ems.domain.vo;
import lombok.Data;
import java.math.BigDecimal;
@Data
public class SparePartBreakdownVo {
private String itemCode;
private String itemName;
private String spec;
private String unit;
private BigDecimal totalQty;
private BigDecimal totalAmount;
private BigDecimal allocatedQty;
private BigDecimal allocatedAmount;
}

View File

@@ -84,8 +84,14 @@ public interface WmsEnergyCoilDailyMapper extends BaseMapper<WmsEnergyCoilDaily>
/** 入场卷号维度能源+囤积成本汇总(导出) */
List<CoilTotalCostVo> selectCoilTotalMergedExport(@Param("bo") CoilTotalCostBo bo);
/** 辅料分摊构成(按物料汇总,金额与数量按卷的日分摊系数分摊) */
IPage<AuxMaterialBreakdownVo> selectAuxMaterialBreakdown(Page<AuxMaterialBreakdownVo> page, @Param("bo") CoilTotalCostBo bo);
/** 备件分摊构成(按备件汇总,金额与数量按卷的日分摊系数分摊) */
IPage<SparePartBreakdownVo> selectSparePartBreakdown(Page<SparePartBreakdownVo> page, @Param("bo") CoilTotalCostBo bo);
/** 查询待操作钢卷的能源成本一次性SQL查询 */
List<WmsEnergyCoilDailyVo> selectPendingActionCoilCost();
List<WmsEnergyCoilDailyVo> selectPendingActionCoilCost(@Param("bo") WmsEnergyCoilDailyBo bo);
/** 查询待操作钢卷的能源成本统计 */
WmsEnergyCoilDailyStatisticsVo selectPendingActionCoilCostStatistics(
@@ -93,4 +99,7 @@ public interface WmsEnergyCoilDailyMapper extends BaseMapper<WmsEnergyCoilDaily>
@Param("currentCoilNo") String currentCoilNo,
@Param("warehouseId") Long warehouseId
);
/** 查询待操作钢卷的能源成本详情(单卷) */
WmsEnergyCoilDailyVo selectPendingActionCoilCostDetail(@Param("coilId") Long coilId);
}

View File

@@ -11,6 +11,8 @@ import com.klp.ems.domain.vo.EnergyCostSummaryVo;
import com.klp.ems.domain.vo.WarehouseProductionCoilVo;
import com.klp.ems.domain.vo.WarehouseProductionStatVo;
import com.klp.ems.domain.vo.WmsEnergyCoilDailyVo;
import com.klp.ems.domain.vo.AuxMaterialBreakdownVo;
import com.klp.ems.domain.vo.SparePartBreakdownVo;
import java.util.List;
import java.util.Map;
@@ -49,4 +51,10 @@ public interface IEnergyCostReportService {
/** 入场卷号维度能源+囤积综合汇总导出 */
java.util.List<CoilTotalCostVo> coilTotalMergedExport(CoilTotalCostBo bo);
/** 辅料分摊构成(按物料汇总,数量与金额按卷的日分摊系数分摊) */
TableDataInfo<AuxMaterialBreakdownVo> auxMaterialBreakdown(CoilTotalCostBo bo, PageQuery pageQuery);
/** 备件分摊构成(按备件汇总,数量与金额按卷的日分摊系数分摊) */
TableDataInfo<SparePartBreakdownVo> sparePartBreakdown(CoilTotalCostBo bo, PageQuery pageQuery);
}

View File

@@ -34,6 +34,11 @@ public interface IWmsEnergyCoilDailyService {
*/
WmsEnergyCoilDailyStatisticsVo queryPendingActionCoilCostStatistics(String enterCoilNo, String currentCoilNo, Long warehouseId);
/**
* 查询待操作钢卷的能源成本详情(单卷)
*/
WmsEnergyCoilDailyVo queryPendingActionCoilCostDetail(Long coilId);
Boolean insertByBo(WmsEnergyCoilDailyBo bo);
Boolean updateByBo(WmsEnergyCoilDailyBo bo);

View File

@@ -13,6 +13,8 @@ import com.klp.ems.domain.vo.EnergyCostSummaryVo;
import com.klp.ems.domain.vo.WarehouseProductionCoilVo;
import com.klp.ems.domain.vo.WarehouseProductionStatVo;
import com.klp.ems.domain.vo.WmsEnergyCoilDailyVo;
import com.klp.ems.domain.vo.AuxMaterialBreakdownVo;
import com.klp.ems.domain.vo.SparePartBreakdownVo;
import com.klp.ems.mapper.WmsEnergyCoilDailyMapper;
import com.klp.ems.service.IEnergyCostReportService;
import lombok.RequiredArgsConstructor;
@@ -142,4 +144,22 @@ public class EnergyCostReportServiceImpl implements IEnergyCostReportService {
public java.util.List<CoilTotalCostVo> coilTotalMergedExport(CoilTotalCostBo bo) {
return coilDailyMapper.selectCoilTotalMergedExport(bo);
}
@Override
public TableDataInfo<AuxMaterialBreakdownVo> auxMaterialBreakdown(CoilTotalCostBo bo, PageQuery pageQuery) {
if (pageQuery.getPageSize() == null) {
pageQuery.setPageSize(15);
}
IPage<AuxMaterialBreakdownVo> page = coilDailyMapper.selectAuxMaterialBreakdown(pageQuery.build(), bo);
return TableDataInfo.build(page);
}
@Override
public TableDataInfo<SparePartBreakdownVo> sparePartBreakdown(CoilTotalCostBo bo, PageQuery pageQuery) {
if (pageQuery.getPageSize() == null) {
pageQuery.setPageSize(15);
}
IPage<SparePartBreakdownVo> page = coilDailyMapper.selectSparePartBreakdown(pageQuery.build(), bo);
return TableDataInfo.build(page);
}
}

View File

@@ -51,7 +51,7 @@ public class WmsEnergyCoilDailyServiceImpl implements IWmsEnergyCoilDailyService
public TableDataInfo<WmsEnergyCoilDailyVo> queryPendingActionCoilCost(WmsEnergyCoilDailyBo bo, PageQuery pageQuery) {
// 使用SQL一次性查询待操作钢卷的能源成本
// 所有的关联、聚合、计算都在SQL中完成性能更高
List<WmsEnergyCoilDailyVo> resultList = baseMapper.selectPendingActionCoilCost();
List<WmsEnergyCoilDailyVo> resultList = baseMapper.selectPendingActionCoilCost(bo);
if (CollUtil.isEmpty(resultList)) {
log.warn("[PendingActionCoilCost] No pending action coils found");
@@ -76,6 +76,11 @@ public class WmsEnergyCoilDailyServiceImpl implements IWmsEnergyCoilDailyService
return baseMapper.selectPendingActionCoilCostStatistics(enterCoilNo, currentCoilNo, warehouseId);
}
@Override
public WmsEnergyCoilDailyVo queryPendingActionCoilCostDetail(Long coilId) {
return baseMapper.selectPendingActionCoilCostDetail(coilId);
}
@Override
public Boolean insertByBo(WmsEnergyCoilDailyBo bo) {
WmsEnergyCoilDaily add = BeanUtil.toBean(bo, WmsEnergyCoilDaily.class);

View File

@@ -33,12 +33,12 @@
<select id="selectCoilTotalMerged" parameterType="map"
resultType="com.klp.ems.domain.vo.CoilTotalCostVo">
SELECT
aid.enter_coil_no AS enterCoilNo,
e.current_coil_no AS currentCoilNo,
e.coil_count AS coilCount,
e.total_duration AS totalDuration,
e.total_consumption AS totalConsumption,
e.energy_cost AS totalEnergyCost,
m.enter_coil_no AS enterCoilNo,
m.current_coil_no AS currentCoilNo,
IFNULL(e.coil_count, 0) AS coilCount,
IFNULL(e.total_duration, 0) AS totalDuration,
IFNULL(e.total_consumption, 0) AS totalConsumption,
IFNULL(e.energy_cost, 0) AS totalEnergyCost,
IFNULL(s.stock_cost, 0) AS stockCost,
IFNULL(x.aux_cost, 0) AS auxCost,
IFNULL(x.spare_cost, 0) AS spareCost,
@@ -46,47 +46,31 @@
IFNULL(s.total_gross_weight, 0) AS totalGrossWeight,
(IFNULL(e.energy_cost, 0) + IFNULL(s.stock_cost, 0) + IFNULL(x.aux_cost, 0) + IFNULL(x.spare_cost, 0)) AS totalCost
FROM (
SELECT enter_coil_no FROM (
SELECT DISTINCT c.enter_coil_no
FROM wms_coil_pending_action pa
LEFT JOIN wms_material_coil c ON pa.coil_id = c.coil_id
WHERE pa.action_status IN (0,1,2)
AND pa.warehouse_id IS NOT NULL
<if test="bo != null and bo.enterCoilNo != null and bo.enterCoilNo != ''">
AND c.enter_coil_no LIKE CONCAT('%', #{bo.enterCoilNo}, '%')
</if>
<if test="bo != null and bo.currentCoilNo != null and bo.currentCoilNo != ''">
AND pa.current_coil_no LIKE CONCAT('%', #{bo.currentCoilNo}, '%')
</if>
<if test="bo != null and bo.startDate != null and bo.startDate != ''">
AND pa.create_time <![CDATA[>=]]> CONCAT(#{bo.startDate}, ' 00:00:00')
</if>
<if test="bo != null and bo.endDate != null and bo.endDate != ''">
AND pa.create_time <![CDATA[<=]]> CONCAT(#{bo.endDate}, ' 23:59:59')
</if>
) eids
UNION
SELECT DISTINCT m.enter_coil_no
FROM wms_material_coil m
WHERE m.data_type IN (0,1)
AND m.del_flag = 0
SELECT
MAX(enter_coil_no) AS enter_coil_no,
current_coil_no,
MIN(create_time) AS create_time
FROM wms_material_coil
WHERE data_type = 1
AND del_flag = 0
AND status = 0
<if test="bo != null and bo.enterCoilNo != null and bo.enterCoilNo != ''">
AND m.enter_coil_no LIKE CONCAT('%', #{bo.enterCoilNo}, '%')
AND enter_coil_no LIKE CONCAT('%', #{bo.enterCoilNo}, '%')
</if>
<if test="bo != null and bo.currentCoilNo != null and bo.currentCoilNo != ''">
AND m.current_coil_no LIKE CONCAT('%', #{bo.currentCoilNo}, '%')
AND current_coil_no LIKE CONCAT('%', #{bo.currentCoilNo}, '%')
</if>
<if test="bo != null and bo.startDate != null and bo.startDate != ''">
AND m.create_time <![CDATA[>=]]> CONCAT(#{bo.startDate}, ' 00:00:00')
AND create_time <![CDATA[>=]]> CONCAT(#{bo.startDate}, ' 00:00:00')
</if>
<if test="bo != null and bo.endDate != null and bo.endDate != ''">
AND m.create_time <![CDATA[<=]]> CONCAT(#{bo.endDate}, ' 23:59:59')
AND create_time <![CDATA[<=]]> CONCAT(#{bo.endDate}, ' 23:59:59')
</if>
) aid
GROUP BY current_coil_no
) m
LEFT JOIN (
SELECT
c.enter_coil_no,
MIN(pa.current_coil_no) AS current_coil_no,
pa.current_coil_no,
COUNT(DISTINCT pa.coil_id) AS coil_count,
SUM(
CASE
@@ -137,7 +121,7 @@
END
) AS energy_cost
FROM wms_coil_pending_action pa
LEFT JOIN wms_material_coil c ON pa.coil_id = c.coil_id
LEFT JOIN wms_material_coil c ON pa.coil_id = c.coil_id AND c.data_type = 1 AND c.del_flag = 0 AND c.status = 0
LEFT JOIN (
<include refid="WarehouseMeterTime"/>
) wmt ON pa.warehouse_id = wmt.warehouse_id
@@ -174,6 +158,7 @@
GROUP BY pa_pd.warehouse_id
) wd_prod ON pa.warehouse_id = wd_prod.warehouse_id
WHERE pa.action_status IN (0, 1, 2)
and pa.del_flag='0'
AND pa.warehouse_id IS NOT NULL
<if test="bo != null and bo.enterCoilNo != null and bo.enterCoilNo != ''">
AND c.enter_coil_no LIKE CONCAT('%', #{bo.enterCoilNo}, '%')
@@ -187,29 +172,30 @@
<if test="bo != null and bo.endDate != null and bo.endDate != ''">
AND pa.create_time <![CDATA[<=]]> CONCAT(#{bo.endDate}, ' 23:59:59')
</if>
GROUP BY c.enter_coil_no
) e ON aid.enter_coil_no = e.enter_coil_no
GROUP BY pa.current_coil_no
) e ON m.current_coil_no = e.current_coil_no
LEFT JOIN (
SELECT
m.enter_coil_no,
current_coil_no,
SUM(CASE
WHEN cs.unit_cost IS NULL THEN 0
ELSE (
CASE
WHEN IFNULL(m.net_weight, 0) = 0 AND IFNULL(m.gross_weight, 0) > 0 THEN m.gross_weight
ELSE IFNULL(m.net_weight, 0)
WHEN IFNULL(net_weight, 0) = 0 AND IFNULL(gross_weight, 0) > 0 THEN gross_weight
ELSE IFNULL(net_weight, 0)
END
) * cs.unit_cost
END) AS stock_cost,
SUM(IFNULL(m.net_weight, 0)) AS total_net_weight,
SUM(IFNULL(m.gross_weight, 0)) AS total_gross_weight
SUM(IFNULL(net_weight, 0)) AS total_net_weight,
SUM(IFNULL(gross_weight, 0)) AS total_gross_weight
FROM wms_material_coil m
LEFT JOIN wms_cost_standard_config cs
ON cs.status = 1
AND DATE(m.create_time) >= cs.effective_date
AND (cs.expire_date IS NULL OR DATE(m.create_time) <![CDATA[<=]]> cs.expire_date)
WHERE m.data_type IN (0,1)
WHERE m.data_type = 1
AND m.del_flag = 0
AND m.status = 0
<if test="bo != null and bo.enterCoilNo != null and bo.enterCoilNo != ''">
AND m.enter_coil_no LIKE CONCAT('%', #{bo.enterCoilNo}, '%')
</if>
@@ -222,11 +208,11 @@
<if test="bo != null and bo.endDate != null and bo.endDate != ''">
AND m.create_time <![CDATA[<=]]> CONCAT(#{bo.endDate}, ' 23:59:59')
</if>
GROUP BY m.enter_coil_no
) s ON aid.enter_coil_no = s.enter_coil_no
GROUP BY current_coil_no
) s ON m.current_coil_no = s.current_coil_no
LEFT JOIN (
SELECT
dm.enter_coil_no,
dm.current_coil_no,
SUM(
CASE
WHEN dm.total_minutes > 0
@@ -244,7 +230,7 @@
FROM (
SELECT
DATE(pa.create_time) AS day_key,
c.enter_coil_no,
pa.current_coil_no,
SUM(
CASE
WHEN pa.create_time &lt; COALESCE(pa.complete_time, NOW())
@@ -254,7 +240,7 @@
) AS coil_minutes,
td.total_minutes
FROM wms_coil_pending_action pa
LEFT JOIN wms_material_coil c ON pa.coil_id = c.coil_id
LEFT JOIN wms_material_coil c ON pa.coil_id = c.coil_id AND c.data_type = 1 AND c.del_flag = 0 AND c.status = 0
LEFT JOIN (
SELECT
DATE(pa_all.create_time) AS day_key,
@@ -267,14 +253,28 @@
) AS total_minutes
FROM wms_coil_pending_action pa_all
WHERE pa_all.action_status IN (0,1,2)
<if test="bo != null and bo.startDate != null and bo.startDate != ''">
AND pa_all.create_time >= CONCAT(#{bo.startDate}, ' 00:00:00')
</if>
<if test="bo != null and bo.endDate != null and bo.endDate != ''">
AND pa_all.create_time &lt;= CONCAT(#{bo.endDate}, ' 23:59:59')
</if>
GROUP BY DATE(pa_all.create_time)
) td ON td.day_key = DATE(pa.create_time)
WHERE pa.action_status IN (0,1,2)
<if test="bo != null and bo.enterCoilNo != null and bo.enterCoilNo != ''">
AND c.enter_coil_no LIKE CONCAT('%', #{bo.enterCoilNo}, '%')
</if>
<if test="bo != null and bo.currentCoilNo != null and bo.currentCoilNo != ''">
AND pa.current_coil_no LIKE CONCAT('%', #{bo.currentCoilNo}, '%')
</if>
<if test="bo != null and bo.startDate != null and bo.startDate != ''">
AND pa.create_time >= CONCAT(#{bo.startDate}, ' 00:00:00')
</if>
<if test="bo != null and bo.endDate != null and bo.endDate != ''">
AND pa.create_time &lt;= CONCAT(#{bo.endDate}, ' 23:59:59')
GROUP BY DATE(pa.create_time), c.enter_coil_no, td.total_minutes
</if>
GROUP BY DATE(pa.create_time), pa.current_coil_no, td.total_minutes
) dm
LEFT JOIN (
SELECT
@@ -283,8 +283,12 @@
FROM eqp_auxiliary_material_change
WHERE del_flag = '0'
AND change_type = '减少'
<if test="bo != null and bo.startDate != null and bo.startDate != ''">
AND change_time >= CONCAT(#{bo.startDate}, ' 00:00:00')
</if>
<if test="bo != null and bo.endDate != null and bo.endDate != ''">
AND change_time &lt;= CONCAT(#{bo.endDate}, ' 23:59:59')
</if>
GROUP BY DATE(change_time)
) a ON dm.day_key = a.day_key
LEFT JOIN (
@@ -294,12 +298,17 @@
FROM eqp_spare_parts_change
WHERE del_flag = '0'
AND change_type = '减少'
<if test="bo != null and bo.startDate != null and bo.startDate != ''">
AND change_time >= CONCAT(#{bo.startDate}, ' 00:00:00')
</if>
<if test="bo != null and bo.endDate != null and bo.endDate != ''">
AND change_time &lt;= CONCAT(#{bo.endDate}, ' 23:59:59')
</if>
GROUP BY DATE(change_time)
) p ON dm.day_key = p.day_key
GROUP BY dm.enter_coil_no
) x ON aid.enter_coil_no = x.enter_coil_no
GROUP BY dm.current_coil_no
) x ON m.current_coil_no = x.current_coil_no
WHERE s.current_coil_no IS NOT NULL
ORDER BY totalCost DESC
LIMIT #{offset}, #{pageSize}
</select>
@@ -307,54 +316,42 @@
<!-- 入场卷号维度能源+囤积成本汇总总数 -->
<select id="selectCoilTotalMergedCount" parameterType="com.klp.ems.domain.bo.CoilTotalCostBo"
resultType="long">
SELECT COUNT(1) FROM (
SELECT DISTINCT c.enter_coil_no
FROM wms_coil_pending_action pa
LEFT JOIN wms_material_coil c ON pa.coil_id = c.coil_id
WHERE pa.action_status IN (0,1,2)
AND pa.warehouse_id IS NOT NULL
SELECT COUNT(1)
FROM (
SELECT
current_coil_no,
MAX(enter_coil_no) AS enter_coil_no,
MIN(create_time) AS create_time
FROM wms_material_coil
WHERE data_type = 1
AND del_flag = 0
AND status = 0
<if test="bo != null and bo.enterCoilNo != null and bo.enterCoilNo != ''">
AND c.enter_coil_no LIKE CONCAT('%', #{bo.enterCoilNo}, '%')
AND enter_coil_no LIKE CONCAT('%', #{bo.enterCoilNo}, '%')
</if>
<if test="bo != null and bo.currentCoilNo != null and bo.currentCoilNo != ''">
AND pa.current_coil_no LIKE CONCAT('%', #{bo.currentCoilNo}, '%')
AND current_coil_no LIKE CONCAT('%', #{bo.currentCoilNo}, '%')
</if>
<if test="bo != null and bo.startDate != null and bo.startDate != ''">
AND pa.create_time <![CDATA[>=]]> CONCAT(#{bo.startDate}, ' 00:00:00')
AND create_time <![CDATA[>=]]> CONCAT(#{bo.startDate}, ' 00:00:00')
</if>
<if test="bo != null and bo.endDate != null and bo.endDate != ''">
AND pa.create_time <![CDATA[<=]]> CONCAT(#{bo.endDate}, ' 23:59:59')
AND create_time <![CDATA[<=]]> CONCAT(#{bo.endDate}, ' 23:59:59')
</if>
UNION
SELECT DISTINCT m.enter_coil_no
FROM wms_material_coil m
WHERE m.data_type IN (0,1)
AND m.del_flag = 0
<if test="bo != null and bo.enterCoilNo != null and bo.enterCoilNo != ''">
AND m.enter_coil_no LIKE CONCAT('%', #{bo.enterCoilNo}, '%')
</if>
<if test="bo != null and bo.currentCoilNo != null and bo.currentCoilNo != ''">
AND m.current_coil_no LIKE CONCAT('%', #{bo.currentCoilNo}, '%')
</if>
<if test="bo != null and bo.startDate != null and bo.startDate != ''">
AND m.create_time <![CDATA[>=]]> CONCAT(#{bo.startDate}, ' 00:00:00')
</if>
<if test="bo != null and bo.endDate != null and bo.endDate != ''">
AND m.create_time <![CDATA[<=]]> CONCAT(#{bo.endDate}, ' 23:59:59')
</if>
) tmp
GROUP BY current_coil_no
) m
</select>
<!-- 入场卷号维度能源+囤积成本汇总(导出,全部) -->
<select id="selectCoilTotalMergedExport" parameterType="com.klp.ems.domain.bo.CoilTotalCostBo"
resultType="com.klp.ems.domain.vo.CoilTotalCostVo">
SELECT
aid.enter_coil_no AS enterCoilNo,
e.current_coil_no AS currentCoilNo,
e.coil_count AS coilCount,
e.total_duration AS totalDuration,
e.total_consumption AS totalConsumption,
e.energy_cost AS totalEnergyCost,
m.enter_coil_no AS enterCoilNo,
m.current_coil_no AS currentCoilNo,
IFNULL(e.coil_count, 0) AS coilCount,
IFNULL(e.total_duration, 0) AS totalDuration,
IFNULL(e.total_consumption, 0) AS totalConsumption,
IFNULL(e.energy_cost, 0) AS totalEnergyCost,
IFNULL(s.stock_cost, 0) AS stockCost,
IFNULL(x.aux_cost, 0) AS auxCost,
IFNULL(x.spare_cost, 0) AS spareCost,
@@ -362,23 +359,31 @@
IFNULL(s.total_gross_weight, 0) AS totalGrossWeight,
(IFNULL(e.energy_cost, 0) + IFNULL(s.stock_cost, 0) + IFNULL(x.aux_cost, 0) + IFNULL(x.spare_cost, 0)) AS totalCost
FROM (
SELECT enter_coil_no FROM (
SELECT DISTINCT c.enter_coil_no
FROM wms_coil_pending_action pa
LEFT JOIN wms_material_coil c ON pa.coil_id = c.coil_id
WHERE pa.action_status IN (0,1,2)
AND pa.warehouse_id IS NOT NULL
) eids
UNION
SELECT DISTINCT m.enter_coil_no
FROM wms_material_coil m
WHERE m.data_type IN (0,1)
AND m.del_flag = 0
) aid
SELECT
MAX(enter_coil_no) AS enter_coil_no,
current_coil_no,
MIN(create_time) AS create_time
FROM wms_material_coil
WHERE data_type IN (0,1)
AND del_flag = 0
AND status = 0
<if test="bo != null and bo.enterCoilNo != null and bo.enterCoilNo != ''">
AND enter_coil_no LIKE CONCAT('%', #{bo.enterCoilNo}, '%')
</if>
<if test="bo != null and bo.currentCoilNo != null and bo.currentCoilNo != ''">
AND current_coil_no LIKE CONCAT('%', #{bo.currentCoilNo}, '%')
</if>
<if test="bo != null and bo.startDate != null and bo.startDate != ''">
AND create_time <![CDATA[>=]]> CONCAT(#{bo.startDate}, ' 00:00:00')
</if>
<if test="bo != null and bo.endDate != null and bo.endDate != ''">
AND create_time <![CDATA[<=]]> CONCAT(#{bo.endDate}, ' 23:59:59')
</if>
GROUP BY current_coil_no
) m
LEFT JOIN (
SELECT
c.enter_coil_no,
MIN(pa.current_coil_no) AS current_coil_no,
pa.current_coil_no,
COUNT(DISTINCT pa.coil_id) AS coil_count,
SUM(
CASE
@@ -429,7 +434,7 @@
END
) AS energy_cost
FROM wms_coil_pending_action pa
LEFT JOIN wms_material_coil c ON pa.coil_id = c.coil_id
LEFT JOIN wms_material_coil c ON pa.coil_id = c.coil_id AND c.status = 0
LEFT JOIN (
<include refid="WarehouseMeterTime"/>
) wmt ON pa.warehouse_id = wmt.warehouse_id
@@ -468,7 +473,7 @@
WHERE pa.action_status IN (0, 1, 2)
AND pa.warehouse_id IS NOT NULL
GROUP BY c.enter_coil_no
) e ON aid.enter_coil_no = e.enter_coil_no
) e ON m.enter_coil_no = e.enter_coil_no
LEFT JOIN (
SELECT
m.enter_coil_no,
@@ -490,8 +495,9 @@
AND (cs.expire_date IS NULL OR DATE(m.create_time) <![CDATA[<=]]> cs.expire_date)
WHERE m.data_type IN (0,1)
AND m.del_flag = 0
AND m.status = 0
GROUP BY m.enter_coil_no
) s ON aid.enter_coil_no = s.enter_coil_no
) s ON m.enter_coil_no = s.enter_coil_no
LEFT JOIN (
SELECT
dm.enter_coil_no,
@@ -522,7 +528,7 @@
) AS coil_minutes,
td.total_minutes
FROM wms_coil_pending_action pa
LEFT JOIN wms_material_coil c ON pa.coil_id = c.coil_id
LEFT JOIN wms_material_coil c ON pa.coil_id = c.coil_id AND c.status = 0
LEFT JOIN (
SELECT
DATE(pa_all.create_time) AS day_key,
@@ -535,13 +541,21 @@
) AS total_minutes
FROM wms_coil_pending_action pa_all
WHERE pa_all.action_status IN (0,1,2)
<if test="bo != null and bo.startDate != null and bo.startDate != ''">
AND pa_all.create_time >= CONCAT(#{bo.startDate}, ' 00:00:00')
</if>
<if test="bo != null and bo.endDate != null and bo.endDate != ''">
AND pa_all.create_time &lt;= CONCAT(#{bo.endDate}, ' 23:59:59')
</if>
GROUP BY DATE(pa_all.create_time)
) td ON td.day_key = DATE(pa.create_time)
WHERE pa.action_status IN (0,1,2)
<if test="bo != null and bo.startDate != null and bo.startDate != ''">
AND pa.create_time >= CONCAT(#{bo.startDate}, ' 00:00:00')
</if>
<if test="bo != null and bo.endDate != null and bo.endDate != ''">
AND pa.create_time &lt;= CONCAT(#{bo.endDate}, ' 23:59:59')
</if>
GROUP BY DATE(pa.create_time), c.enter_coil_no, td.total_minutes
) dm
LEFT JOIN (
@@ -551,8 +565,12 @@
FROM eqp_auxiliary_material_change
WHERE del_flag = '0'
AND change_type = '减少'
<if test="bo != null and bo.startDate != null and bo.startDate != ''">
AND change_time >= CONCAT(#{bo.startDate}, ' 00:00:00')
</if>
<if test="bo != null and bo.endDate != null and bo.endDate != ''">
AND change_time &lt;= CONCAT(#{bo.endDate}, ' 23:59:59')
</if>
GROUP BY DATE(change_time)
) a ON dm.day_key = a.day_key
LEFT JOIN (
@@ -562,12 +580,16 @@
FROM eqp_spare_parts_change
WHERE del_flag = '0'
AND change_type = '减少'
<if test="bo != null and bo.startDate != null and bo.startDate != ''">
AND change_time >= CONCAT(#{bo.startDate}, ' 00:00:00')
</if>
<if test="bo != null and bo.endDate != null and bo.endDate != ''">
AND change_time &lt;= CONCAT(#{bo.endDate}, ' 23:59:59')
</if>
GROUP BY DATE(change_time)
) p ON dm.day_key = p.day_key
GROUP BY dm.enter_coil_no
) x ON aid.enter_coil_no = x.enter_coil_no
) x ON m.enter_coil_no = x.enter_coil_no
ORDER BY totalCost DESC
</select>
@@ -626,7 +648,7 @@
END
) AS totalEnergyCost
FROM wms_coil_pending_action pa
LEFT JOIN wms_material_coil c ON pa.coil_id = c.coil_id
LEFT JOIN wms_material_coil c ON pa.coil_id = c.coil_id AND c.status = 0
LEFT JOIN wms_warehouse w ON pa.warehouse_id = w.warehouse_id
LEFT JOIN (
<include refid="WarehouseMeterTime"/>
@@ -741,7 +763,7 @@
ELSE 0
END AS totalCost
FROM wms_coil_pending_action pa
LEFT JOIN wms_material_coil c ON pa.coil_id = c.coil_id
LEFT JOIN wms_material_coil c ON pa.coil_id = c.coil_id AND c.status = 0
LEFT JOIN wms_warehouse w ON pa.warehouse_id = w.warehouse_id
LEFT JOIN (
<include refid="WarehouseMeterTime"/>
@@ -776,9 +798,11 @@
) wmt_pd ON pa_pd.warehouse_id = wmt_pd.warehouse_id
WHERE pa_pd.action_status IN (0, 1)
AND pa_pd.warehouse_id IS NOT NULL
and pa_pd.del_flag=0
GROUP BY pa_pd.warehouse_id
) wd_prod ON pa.warehouse_id = wd_prod.warehouse_id
WHERE pa.action_status IN (0, 1, 2)
and pa.del_flag = 0
AND pa.warehouse_id IS NOT NULL
<if test="bo != null and bo.enterCoilNo != null and bo.enterCoilNo != ''">
AND c.enter_coil_no LIKE CONCAT('%', #{bo.enterCoilNo}, '%')
@@ -1019,7 +1043,7 @@
ELSE 0
END AS unitCost
FROM wms_coil_pending_action pa
LEFT JOIN wms_material_coil mc ON pa.coil_id = mc.coil_id
LEFT JOIN wms_material_coil mc ON pa.coil_id = mc.coil_id AND mc.status = 0
LEFT JOIN (
<include refid="WarehouseMeterTime"/>
) wmt ON pa.warehouse_id = wmt.warehouse_id
@@ -1135,7 +1159,7 @@
ELSE 0
END AS totalCost
FROM wms_coil_pending_action pa
LEFT JOIN wms_material_coil mc ON pa.coil_id = mc.coil_id
LEFT JOIN wms_material_coil mc ON pa.coil_id = mc.coil_id AND mc.status = 0
LEFT JOIN (
<include refid="WarehouseMeterTime"/>
) wmt ON pa.warehouse_id = wmt.warehouse_id
@@ -1379,7 +1403,7 @@
ELSE 0
END AS totalCost
FROM wms_coil_pending_action pa
LEFT JOIN wms_material_coil mc ON pa.coil_id = mc.coil_id
LEFT JOIN wms_material_coil mc ON pa.coil_id = mc.coil_id AND mc.status = 0
LEFT JOIN (
<include refid="WarehouseMeterTime"/>
) wmt ON pa.warehouse_id = wmt.warehouse_id
@@ -1719,7 +1743,7 @@
wmt.warehouse_start_time AS latestMeterReadStartTime,
wmt.warehouse_end_time AS latestMeterReadEndTime
FROM wms_coil_pending_action pa
LEFT JOIN wms_material_coil c ON pa.coil_id = c.coil_id
LEFT JOIN wms_material_coil c ON pa.coil_id = c.coil_id AND c.status = 0
LEFT JOIN wms_warehouse wh ON pa.warehouse_id = wh.warehouse_id
LEFT JOIN (
<include refid="WarehouseMeterTime"/>
@@ -1773,9 +1797,184 @@
) wd_count ON pa.warehouse_id = wd_count.warehouse_id
WHERE pa.action_status IN (0, 1, 2)
AND pa.warehouse_id IS NOT NULL
<if test="bo != null and bo.coilId != null">
AND pa.coil_id = #{bo.coilId}
</if>
<if test="bo != null and bo.enterCoilNo != null and bo.enterCoilNo != ''">
AND c.enter_coil_no LIKE CONCAT('%', #{bo.enterCoilNo}, '%')
</if>
<if test="bo != null and bo.currentCoilNo != null and bo.currentCoilNo != ''">
AND pa.current_coil_no LIKE CONCAT('%', #{bo.currentCoilNo}, '%')
</if>
<if test="bo != null and bo.warehouseId != null">
AND pa.warehouse_id = #{bo.warehouseId}
</if>
ORDER BY pa.warehouse_id, pa.create_time DESC
</select>
<!-- 查询待操作钢卷的能源成本详情(单卷) -->
<select id="selectPendingActionCoilCostDetail" resultType="com.klp.ems.domain.vo.WmsEnergyCoilDailyVo">
SELECT
pa.coil_id AS coilId,
pa.current_coil_no AS currentCoilNo,
c.enter_coil_no AS enterCoilNo,
pa.warehouse_id AS warehouseId,
wh.warehouse_name AS warehouseName,
pa.create_time AS scanTime,
-- 结束时间:优先使用库区绑定设备的最近一次抄表结束时间,其次使用钢卷自身的完成时间
CASE
WHEN pa.complete_time IS NOT NULL THEN pa.complete_time
WHEN wmt.warehouse_end_time IS NOT NULL THEN LEAST(wmt.warehouse_end_time, NOW())
ELSE NOW()
END AS completeTime,
-- 生产时长:
-- 1) 若库区有抄表时间,则按 创建时间 ~ min(完成时间, 库区最近抄表结束时间)
-- 2) 若库区无抄表时间,则仅在钢卷有完成时间时按 创建时间 ~ 完成时间
CASE
WHEN pa.create_time <![CDATA[<]]> (CASE
WHEN pa.complete_time IS NOT NULL THEN pa.complete_time
WHEN wmt.warehouse_end_time IS NOT NULL THEN LEAST(wmt.warehouse_end_time, NOW())
ELSE NOW()
END)
THEN TIMESTAMPDIFF(MINUTE,
pa.create_time,
CASE
WHEN pa.complete_time IS NOT NULL THEN pa.complete_time
WHEN wmt.warehouse_end_time IS NOT NULL THEN LEAST(wmt.warehouse_end_time, NOW())
ELSE NOW()
END
)
ELSE 0
END AS productionDuration,
-- 分摊比率:按生产时长占库区总生产时长的比例
CASE
WHEN wd_prod.total_prod_minutes IS NOT NULL
AND wd_prod.total_prod_minutes > 0
AND pa.create_time <![CDATA[<]]> (CASE
WHEN pa.complete_time IS NOT NULL THEN pa.complete_time
WHEN wmt.warehouse_end_time IS NOT NULL THEN LEAST(wmt.warehouse_end_time, NOW())
ELSE NOW()
END)
THEN CAST(
CASE
WHEN pa.create_time <![CDATA[<]]> (CASE
WHEN pa.complete_time IS NOT NULL THEN pa.complete_time
WHEN wmt.warehouse_end_time IS NOT NULL THEN LEAST(wmt.warehouse_end_time, NOW())
ELSE NOW()
END)
THEN TIMESTAMPDIFF(MINUTE,
pa.create_time,
CASE
WHEN pa.complete_time IS NOT NULL THEN pa.complete_time
WHEN wmt.warehouse_end_time IS NOT NULL THEN LEAST(wmt.warehouse_end_time, NOW())
ELSE NOW()
END
)
ELSE 0
END AS DECIMAL(20,6)
) / wd_prod.total_prod_minutes
ELSE 0
END AS allocationFactor,
-- 分摊能耗 = 总能耗 * 分摊比率
CASE
WHEN wd.total_warehouse_consumption IS NOT NULL
AND wd_prod.total_prod_minutes IS NOT NULL
AND wd_prod.total_prod_minutes > 0
THEN wd.total_warehouse_consumption *
(CAST(
CASE
WHEN pa.create_time <![CDATA[<]]> (CASE
WHEN pa.complete_time IS NOT NULL THEN pa.complete_time
WHEN wmt.warehouse_end_time IS NOT NULL THEN LEAST(wmt.warehouse_end_time, NOW())
ELSE NOW()
END)
THEN TIMESTAMPDIFF(MINUTE,
pa.create_time,
CASE
WHEN pa.complete_time IS NOT NULL THEN pa.complete_time
WHEN wmt.warehouse_end_time IS NOT NULL THEN LEAST(wmt.warehouse_end_time, NOW())
ELSE NOW()
END
)
ELSE 0
END AS DECIMAL(20,6)
) / wd_prod.total_prod_minutes)
ELSE 0
END AS consumptionQty,
-- 分摊成本 = 总成本 * 分摊比率
CASE
WHEN wd.total_warehouse_cost IS NOT NULL
AND wd_prod.total_prod_minutes IS NOT NULL
AND wd_prod.total_prod_minutes > 0
THEN wd.total_warehouse_cost *
(CAST(
CASE
WHEN pa.create_time <![CDATA[<]]> (CASE
WHEN pa.complete_time IS NOT NULL THEN pa.complete_time
WHEN wmt.warehouse_end_time IS NOT NULL THEN LEAST(wmt.warehouse_end_time, NOW())
ELSE NOW()
END)
THEN TIMESTAMPDIFF(MINUTE,
pa.create_time,
CASE
WHEN pa.complete_time IS NOT NULL THEN pa.complete_time
WHEN wmt.warehouse_end_time IS NOT NULL THEN LEAST(wmt.warehouse_end_time, NOW())
ELSE NOW()
END
)
ELSE 0
END AS DECIMAL(20,6)
) / wd_prod.total_prod_minutes)
ELSE 0
END AS costAmount,
wmt.warehouse_start_time AS latestMeterReadStartTime,
wmt.warehouse_end_time AS latestMeterReadEndTime
FROM wms_coil_pending_action pa
LEFT JOIN wms_material_coil c ON pa.coil_id = c.coil_id AND c.status = 0
LEFT JOIN wms_warehouse wh ON pa.warehouse_id = wh.warehouse_id
LEFT JOIN (
<include refid="WarehouseMeterTime"/>
) wmt ON pa.warehouse_id = wmt.warehouse_id
LEFT JOIN (
<include refid="WarehouseCost"/>
) wd ON pa.warehouse_id = wd.warehouse_id
LEFT JOIN (
SELECT
pa_pd.warehouse_id,
SUM(
CASE
WHEN wmt_pd.warehouse_end_time IS NOT NULL
AND pa_pd.create_time <![CDATA[<]]> COALESCE(pa_pd.complete_time, wmt_pd.warehouse_end_time)
THEN TIMESTAMPDIFF(MINUTE,
pa_pd.create_time,
COALESCE(pa_pd.complete_time, wmt_pd.warehouse_end_time)
)
WHEN wmt_pd.warehouse_end_time IS NULL
AND pa_pd.complete_time IS NOT NULL
AND pa_pd.create_time <![CDATA[<]]> pa_pd.complete_time
THEN TIMESTAMPDIFF(MINUTE,
pa_pd.create_time,
pa_pd.complete_time
)
ELSE 0
END
) AS total_prod_minutes
FROM wms_coil_pending_action pa_pd
LEFT JOIN (
<include refid="WarehouseMeterTime"/>
) wmt_pd ON pa_pd.warehouse_id = wmt_pd.warehouse_id
WHERE pa_pd.action_status IN (0, 1)
AND pa_pd.warehouse_id IS NOT NULL
AND wmt_pd.warehouse_end_time IS NOT NULL
GROUP BY pa_pd.warehouse_id
) wd_prod ON pa.warehouse_id = wd_prod.warehouse_id
WHERE pa.coil_id = #{coilId}
AND pa.action_status IN (0, 1, 2)
AND pa.warehouse_id IS NOT NULL
AND pa.del_flag = 0
LIMIT 1
</select>
<!-- 查询待操作钢卷的能源成本统计(按时间段分摊) -->
<select id="selectPendingActionCoilCostStatistics" resultType="com.klp.ems.domain.vo.WmsEnergyCoilDailyStatisticsVo">
SELECT
@@ -1918,7 +2117,7 @@
MIN(wmt.warehouse_start_time) AS latestMeterReadStartTime,
MAX(wmt.warehouse_end_time) AS latestMeterReadEndTime
FROM wms_coil_pending_action pa
LEFT JOIN wms_material_coil c ON pa.coil_id = c.coil_id
LEFT JOIN wms_material_coil c ON pa.coil_id = c.coil_id AND c.status = 0
LEFT JOIN wms_warehouse wh ON pa.warehouse_id = wh.warehouse_id
LEFT JOIN (
<include refid="WarehouseMeterTime"/>
@@ -2034,4 +2233,181 @@
ORDER BY c.calc_date DESC, c.energy_cost_id DESC
</select>
<!-- 辅料分摊构成(按物料汇总,数量与金额按卷的日分摊系数分摊) -->
<select id="selectAuxMaterialBreakdown" resultType="com.klp.ems.domain.vo.AuxMaterialBreakdownVo">
SELECT
CAST(t.auxiliary_id AS CHAR) AS itemCode,
t.item_name AS itemName,
t.spec AS spec,
t.unit AS unit,
SUM(t.total_qty) AS totalQty,
SUM(t.total_amount) AS totalAmount,
SUM(t.allocated_qty) AS allocatedQty,
SUM(t.allocated_amount) AS allocatedAmount
FROM (
SELECT
adc.day_key,
adc.auxiliary_id,
adc.item_name,
adc.spec,
adc.unit,
adc.total_qty,
adc.total_amount,
CASE
WHEN dtm.total_minutes > 0 AND cdm.coil_minutes IS NOT NULL AND cdm.coil_minutes > 0
THEN adc.total_qty * (cdm.coil_minutes / dtm.total_minutes)
ELSE 0
END AS allocated_qty,
CASE
WHEN dtm.total_minutes > 0 AND cdm.coil_minutes IS NOT NULL AND cdm.coil_minutes > 0
THEN adc.total_amount * (cdm.coil_minutes / dtm.total_minutes)
ELSE 0
END AS allocated_amount
FROM (
SELECT
DATE(amc.change_time) AS day_key,
am.auxiliary_id,
am.auxiliary_name AS item_name,
am.auxiliary_model AS spec,
am.unit,
SUM(ABS(amc.change_quantity)) AS total_qty,
SUM(ABS(IFNULL(amc.amount, 0))) AS total_amount
FROM eqp_auxiliary_material_change amc
JOIN eqp_auxiliary_material am ON amc.auxiliary_id = am.auxiliary_id
WHERE amc.del_flag = '0'
AND amc.change_type = '减少'
AND amc.change_time >= CONCAT(#{bo.startDate}, ' 00:00:00')
AND amc.change_time <![CDATA[<=]]> CONCAT(#{bo.endDate}, ' 23:59:59')
GROUP BY DATE(amc.change_time), am.auxiliary_id, am.auxiliary_name, am.auxiliary_model, am.unit
) adc
JOIN (
SELECT
DATE(pa_all.create_time) AS day_key,
SUM(
CASE
WHEN pa_all.create_time <![CDATA[<]]> COALESCE(pa_all.complete_time, NOW())
THEN TIMESTAMPDIFF(MINUTE, pa_all.create_time, COALESCE(pa_all.complete_time, NOW()))
ELSE 0
END
) AS total_minutes
FROM wms_coil_pending_action pa_all
WHERE pa_all.action_status IN (0,1,2)
AND pa_all.create_time >= CONCAT(#{bo.startDate}, ' 00:00:00')
AND pa_all.create_time <![CDATA[<=]]> CONCAT(#{bo.endDate}, ' 23:59:59')
GROUP BY DATE(pa_all.create_time)
) dtm ON adc.day_key = dtm.day_key
LEFT JOIN (
SELECT
c.enter_coil_no,
DATE(pa.create_time) AS day_key,
SUM(
CASE
WHEN pa.create_time <![CDATA[<]]> COALESCE(pa.complete_time, NOW())
THEN TIMESTAMPDIFF(MINUTE, pa.create_time, COALESCE(pa.complete_time, NOW()))
ELSE 0
END
) AS coil_minutes
FROM wms_coil_pending_action pa
JOIN wms_material_coil c ON pa.coil_id = c.coil_id AND c.status = 0
WHERE pa.action_status IN (0,1,2)
AND pa.create_time >= CONCAT(#{bo.startDate}, ' 00:00:00')
AND pa.create_time <![CDATA[<=]]> CONCAT(#{bo.endDate}, ' 23:59:59')
<if test="bo != null and bo.enterCoilNo != null and bo.enterCoilNo != ''">
AND c.enter_coil_no = #{bo.enterCoilNo}
</if>
GROUP BY c.enter_coil_no, DATE(pa.create_time)
) cdm ON adc.day_key = cdm.day_key
) t
GROUP BY t.auxiliary_id, t.item_name, t.spec, t.unit
ORDER BY allocatedAmount DESC
</select>
<!-- 备件分摊构成(按备件汇总,数量与金额按卷的日分摊系数分摊) -->
<select id="selectSparePartBreakdown" resultType="com.klp.ems.domain.vo.SparePartBreakdownVo">
SELECT
CAST(t.part_id AS CHAR) AS itemCode,
t.item_name AS itemName,
t.spec AS spec,
t.unit AS unit,
SUM(t.total_qty) AS totalQty,
SUM(t.total_amount) AS totalAmount,
SUM(t.allocated_qty) AS allocatedQty,
SUM(t.allocated_amount) AS allocatedAmount
FROM (
SELECT
sdc.day_key,
sdc.part_id,
sdc.item_name,
sdc.spec,
sdc.unit,
sdc.total_qty,
sdc.total_amount,
CASE
WHEN dtm.total_minutes > 0 AND cdm.coil_minutes IS NOT NULL AND cdm.coil_minutes > 0
THEN sdc.total_qty * (cdm.coil_minutes / dtm.total_minutes)
ELSE 0
END AS allocated_qty,
CASE
WHEN dtm.total_minutes > 0 AND cdm.coil_minutes IS NOT NULL AND cdm.coil_minutes > 0
THEN sdc.total_amount * (cdm.coil_minutes / dtm.total_minutes)
ELSE 0
END AS allocated_amount
FROM (
SELECT
DATE(spc.change_time) AS day_key,
sp.part_id,
sp.part_name AS item_name,
sp.model AS spec,
sp.unit,
SUM(ABS(spc.change_quantity)) AS total_qty,
SUM(ABS(IFNULL(spc.amount, 0))) AS total_amount
FROM eqp_spare_parts_change spc
JOIN eqp_spare_part sp ON spc.part_id = sp.part_id
WHERE spc.del_flag = '0'
AND spc.change_type = '减少'
AND spc.change_time >= CONCAT(#{bo.startDate}, ' 00:00:00')
AND spc.change_time <![CDATA[<=]]> CONCAT(#{bo.endDate}, ' 23:59:59')
GROUP BY DATE(spc.change_time), sp.part_id, sp.part_name, sp.model, sp.unit
) sdc
JOIN (
SELECT
DATE(pa_all.create_time) AS day_key,
SUM(
CASE
WHEN pa_all.create_time <![CDATA[<]]> COALESCE(pa_all.complete_time, NOW())
THEN TIMESTAMPDIFF(MINUTE, pa_all.create_time, COALESCE(pa_all.complete_time, NOW()))
ELSE 0
END
) AS total_minutes
FROM wms_coil_pending_action pa_all
WHERE pa_all.action_status IN (0,1,2)
AND pa_all.create_time >= CONCAT(#{bo.startDate}, ' 00:00:00')
AND pa_all.create_time <![CDATA[<=]]> CONCAT(#{bo.endDate}, ' 23:59:59')
GROUP BY DATE(pa_all.create_time)
) dtm ON sdc.day_key = dtm.day_key
LEFT JOIN (
SELECT
c.enter_coil_no,
DATE(pa.create_time) AS day_key,
SUM(
CASE
WHEN pa.create_time <![CDATA[<]]> COALESCE(pa.complete_time, NOW())
THEN TIMESTAMPDIFF(MINUTE, pa.create_time, COALESCE(pa.complete_time, NOW()))
ELSE 0
END
) AS coil_minutes
FROM wms_coil_pending_action pa
JOIN wms_material_coil c ON pa.coil_id = c.coil_id AND c.status = 0
WHERE pa.action_status IN (0,1,2)
AND pa.create_time >= CONCAT(#{bo.startDate}, ' 00:00:00')
AND pa.create_time <![CDATA[<=]]> CONCAT(#{bo.endDate}, ' 23:59:59')
<if test="bo != null and bo.enterCoilNo != null and bo.enterCoilNo != ''">
AND c.enter_coil_no = #{bo.enterCoilNo}
</if>
GROUP BY c.enter_coil_no, DATE(pa.create_time)
) cdm ON sdc.day_key = cdm.day_key
) t
GROUP BY t.part_id, t.item_name, t.spec, t.unit
ORDER BY allocatedAmount DESC
</select>
</mapper>

View File

@@ -60,3 +60,21 @@ export function exportCoilTotalMerged(query) {
responseType: 'blob'
})
}
// 辅料分摊构成(按物料汇总)
export function fetchAuxMaterialBreakdown(query) {
return request({
url: '/ems/energy/report/material/aux/breakdown',
method: 'get',
params: query
})
}
// 备件分摊构成(按备件汇总)
export function fetchSparePartBreakdown(query) {
return request({
url: '/ems/energy/report/material/spare/breakdown',
method: 'get',
params: query
})
}

View File

@@ -0,0 +1,496 @@
<template>
<div class="material-allocation-page">
<el-card class="search-card">
<el-form :model="queryParams" inline label-width="100px" size="small">
<el-form-item label="入场卷号" required>
<el-input v-model="queryParams.enterCoilNo" placeholder="必填,支持模糊"></el-input>
</el-form-item>
<el-form-item label="当前卷号">
<el-input v-model="queryParams.currentCoilNo" placeholder="支持模糊"></el-input>
</el-form-item>
<el-form-item label="开始日期">
<el-date-picker v-model="queryParams.startDate" type="date" value-format="yyyy-MM-dd" placeholder="开始日期"></el-date-picker>
</el-form-item>
<el-form-item label="结束日期">
<el-date-picker v-model="queryParams.endDate" type="date" value-format="yyyy-MM-dd" placeholder="结束日期"></el-date-picker>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" @click="handleSearch">查询</el-button>
<el-button icon="el-icon-refresh" @click="handleReset">重置</el-button>
</el-form-item>
</el-form>
</el-card>
<el-row :gutter="16" class="stats-row">
<el-col :xs="24" :sm="12" :md="6" :lg="5">
<div class="stat-card">
<div class="label">辅料分摊合计</div>
<div class="value">¥ {{ formatNumber(auxSummary.totalAuxCost, 2) }}</div>
<div class="desc">按日池 + 时长占比分摊</div>
</div>
</el-col>
<el-col :xs="24" :sm="12" :md="6" :lg="5">
<div class="stat-card">
<div class="label">卷数</div>
<div class="value">{{ mergedTotal }}</div>
<div class="desc">当前查询条件下</div>
</div>
</el-col>
<el-col :xs="24" :sm="12" :md="6" :lg="5">
<div class="stat-card">
<div class="label">种类数</div>
<div class="value">{{ breakdownSummary.kinds }}</div>
<div class="desc">按物料聚合</div>
</div>
</el-col>
<el-col :xs="24" :sm="12" :md="6" :lg="5">
<div class="stat-card">
<div class="label">分摊数量合计</div>
<div class="value">{{ formatNumber(breakdownSummary.totalAllocatedQty, 2) }}</div>
<div class="desc">数量按分摊系数切分</div>
</div>
</el-col>
<el-col :xs="24" :sm="12" :md="6" :lg="4">
<div class="stat-card">
<div class="label">分摊金额合计</div>
<div class="value">¥ {{ formatNumber(breakdownSummary.totalAllocatedAmount, 2) }}</div>
<div class="desc">金额按分摊系数切分</div>
</div>
</el-col>
</el-row>
<div class="section">
<div class="section-header">
<div class="title">分摊数据</div>
<div class="actions">
<el-button size="mini" type="primary" icon="el-icon-download" @click="exportSummary">导出汇总</el-button>
<el-button size="mini" icon="el-icon-document" @click="exportDetailCsv" :disabled="detailRows.length === 0">导出明细CSV</el-button>
<el-button size="mini" icon="el-icon-document" @click="exportBreakdownCsv" :disabled="breakdownRows.length === 0">导出构成CSV</el-button>
</div>
</div>
<div class="sub-title">辅料消耗构成</div>
<el-table :data="breakdownRows" border stripe v-loading="breakdownLoading">
<el-table-column prop="itemCode" label="编码" width="140"></el-table-column>
<el-table-column prop="itemName" label="名称" min-width="160"></el-table-column>
<el-table-column prop="spec" label="规格" min-width="140"></el-table-column>
<el-table-column prop="unit" label="单位" width="80"></el-table-column>
<el-table-column prop="totalQty" label="全厂消耗数量" width="140" align="right">
<template slot-scope="scope">{{ formatNumber(scope.row.totalQty, 2) }}</template>
</el-table-column>
<el-table-column prop="totalAmount" label="全厂消耗金额(元)" width="160" align="right">
<template slot-scope="scope">¥ {{ formatNumber(scope.row.totalAmount, 2) }}</template>
</el-table-column>
<el-table-column prop="allocatedQty" label="分摊数量" width="120" align="right">
<template slot-scope="scope">{{ formatNumber(scope.row.allocatedQty, 2) }}</template>
</el-table-column>
<el-table-column prop="allocatedAmount" label="分摊金额(元)" width="150" align="right">
<template slot-scope="scope">¥ {{ formatNumber(scope.row.allocatedAmount, 2) }}</template>
</el-table-column>
</el-table>
<pagination
v-show="breakdownTotal > 0"
:total="breakdownTotal"
:page.sync="breakdownQuery.pageNum"
:limit.sync="breakdownQuery.pageSize"
@pagination="loadBreakdown"
/>
<div class="sub-title" style="margin-top: 16px;">辅料成本分摊</div>
<el-table :data="mergedRows" border stripe v-loading="loading">
<el-table-column prop="enterCoilNo" label="入场卷号"></el-table-column>
<el-table-column prop="currentCoilNo" label="当前卷号"></el-table-column>
<el-table-column prop="auxCost" label="辅料成本">
<template slot-scope="scope">¥ {{ formatNumber(scope.row.auxCost, 2) }}</template>
</el-table-column>
<el-table-column prop="totalNetWeight" label="净重">
<template slot-scope="scope">{{ formatNumber(scope.row.totalNetWeight, 2) }}</template>
</el-table-column>
<el-table-column prop="totalGrossWeight" label="毛重">
<template slot-scope="scope">{{ formatNumber(scope.row.totalGrossWeight, 2) }}</template>
</el-table-column>
<el-table-column label="操作" width="180">
<template slot-scope="scope">
<el-button type="text" size="mini" @click="openDetail(scope.row)">分摊明细</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="mergedTotal > 0"
:total="mergedTotal"
:page.sync="mergedQuery.pageNum"
:limit.sync="mergedQuery.pageSize"
@pagination="loadMerged"
/>
</div>
<el-dialog title="辅料分摊明细(按日)" :visible.sync="detailVisible" width="80%" :close-on-click-modal="false">
<div class="detail-hint">入场卷号{{ detailEnterCoilNo }}</div>
<el-table :data="detailRows" stripe border max-height="420" v-loading="detailLoading">
<el-table-column prop="day" label="日期" width="120"></el-table-column>
<el-table-column prop="auxPoolAmount" label="当日辅料池(元)" width="140">
<template slot-scope="scope">¥ {{ formatNumber(scope.row.auxPoolAmount, 2) }}</template>
</el-table-column>
<el-table-column prop="totalMinutes" label="全厂分钟" width="120">
<template slot-scope="scope">{{ formatNumber(scope.row.totalMinutes, 0) }}</template>
</el-table-column>
<el-table-column prop="coilMinutes" label="卷分钟" width="120">
<template slot-scope="scope">{{ formatNumber(scope.row.coilMinutes, 0) }}</template>
</el-table-column>
<el-table-column prop="factor" label="占比" width="100">
<template slot-scope="scope">{{ toPercent(scope.row.factor) }}</template>
</el-table-column>
<el-table-column prop="allocatedAuxCost" label="分摊辅料(元)" width="140">
<template slot-scope="scope">¥ {{ formatNumber(scope.row.allocatedAuxCost, 2) }}</template>
</el-table-column>
</el-table>
<span slot="footer" class="dialog-footer">
<el-button @click="detailVisible = false"> </el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import { fetchCoilTotalMerged, exportCoilTotalMerged, fetchAuxMaterialBreakdown } from '@/api/ems/energyCostReport'
export default {
name: 'AuxCostAllocation',
data() {
return {
queryParams: {
enterCoilNo: '',
currentCoilNo: '',
startDate: undefined,
endDate: undefined
},
mergedQuery: {
pageNum: 1,
pageSize: 50
},
loading: false,
mergedRows: [],
mergedTotal: 0,
auxSummary: {
totalAuxCost: 0
},
detailVisible: false,
detailLoading: false,
detailEnterCoilNo: '',
detailRows: [],
breakdownLoading: false,
breakdownRows: [],
breakdownTotal: 0,
breakdownQuery: {
pageNum: 1,
pageSize: 10
},
breakdownSummary: {
kinds: 0,
totalAllocatedQty: 0,
totalAllocatedAmount: 0
}
}
},
mounted() {
this.handleSearch()
},
methods: {
handleSearch() {
this.mergedQuery.pageNum = 1
this.breakdownQuery.pageNum = 1
this.loadMerged()
this.loadBreakdown()
},
handleReset() {
this.queryParams = {
enterCoilNo: '',
currentCoilNo: '',
startDate: undefined,
endDate: undefined
}
this.mergedQuery.pageNum = 1
this.breakdownQuery.pageNum = 1
this.mergedRows = []
this.mergedTotal = 0
this.auxSummary = { totalAuxCost: 0 }
this.detailRows = []
this.breakdownRows = []
this.breakdownTotal = 0
this.breakdownSummary = { kinds: 0, totalAllocatedQty: 0, totalAllocatedAmount: 0 }
this.handleSearch()
},
loadMerged() {
const params = {
...this.queryParams,
pageNum: this.mergedQuery.pageNum,
pageSize: this.mergedQuery.pageSize
}
this.loading = true
fetchCoilTotalMerged(params).then(res => {
this.mergedRows = res.rows || []
this.mergedTotal = res.total || 0
const rows = this.mergedRows || []
this.auxSummary = {
totalAuxCost: rows.reduce((sum, r) => sum + (Number(r.auxCost) || 0), 0)
}
}).finally(() => {
this.loading = false
})
},
loadBreakdown() {
const params = {
...this.queryParams,
pageNum: this.breakdownQuery.pageNum,
pageSize: this.breakdownQuery.pageSize
}
this.breakdownLoading = true
fetchAuxMaterialBreakdown(params).then(res => {
this.breakdownRows = res.rows || []
this.breakdownTotal = res.total || 0
const rows = this.breakdownRows || []
this.breakdownSummary = {
kinds: this.breakdownTotal || rows.length || 0,
totalAllocatedQty: rows.reduce((sum, r) => sum + (Number(r.allocatedQty) || 0), 0),
totalAllocatedAmount: rows.reduce((sum, r) => sum + (Number(r.allocatedAmount) || 0), 0)
}
}).finally(() => {
this.breakdownLoading = false
})
},
exportBreakdownCsv() {
const headers = ['编码', '名称', '规格', '单位', '全厂消耗数量', '全厂消耗金额(元)', '分摊数量', '分摊金额(元)']
const lines = [headers.join(',')]
;(this.breakdownRows || []).forEach(r => {
const line = [
this.csvCell(r.itemCode),
this.csvCell(r.itemName),
this.csvCell(r.spec),
this.csvCell(r.unit),
this.csvCell(r.totalQty),
this.csvCell(r.totalAmount),
this.csvCell(r.allocatedQty),
this.csvCell(r.allocatedAmount)
].join(',')
lines.push(line)
})
const csv = lines.join('\n')
const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' })
const url = URL.createObjectURL(blob)
const link = document.createElement('a')
link.href = url
link.download = `aux_allocation_breakdown_${this.queryParams.enterCoilNo || 'all'}.csv`
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
URL.revokeObjectURL(url)
},
openDetail(row) {
if (!row || !row.enterCoilNo) return
this.detailEnterCoilNo = row.enterCoilNo
this.detailVisible = true
this.buildDetailByDay(row.enterCoilNo)
},
buildDetailByDay(enterCoilNo) {
// 明细口径按天切分A 方案),当日池金额 * (卷分钟/全厂分钟)
// 当前后端 merged 接口仅返回汇总后的 auxCost/spareCost不返回按日池/分钟细节。
// 因此这里采用前端“可解释明细”的方式:
// - 先拿同查询条件下的 merged 列表(分页内),并仅对选中卷号展示其 auxCost总额按单行 auxCost 展示为 1 行。
// 若后续补充后端明细接口,可在此替换为真实的按日明细。
this.detailLoading = true
const params = {
...this.queryParams,
enterCoilNo,
pageNum: 1,
pageSize: 1
}
fetchCoilTotalMerged(params).then(res => {
const row = (res.rows || [])[0]
const total = Number(row?.auxCost) || 0
this.detailRows = [
{
day: this.queryParams.startDate && this.queryParams.endDate ? `${this.queryParams.startDate} ~ ${this.queryParams.endDate}` : '-',
auxPoolAmount: null,
totalMinutes: null,
coilMinutes: null,
factor: null,
allocatedAuxCost: total
}
]
}).finally(() => {
this.detailLoading = false
})
},
exportSummary() {
const params = { ...this.queryParams }
exportCoilTotalMerged(params).then(res => {
const blob = new Blob([res], { type: 'application/vnd.ms-excel' })
const url = URL.createObjectURL(blob)
const link = document.createElement('a')
link.href = url
link.download = 'aux_cost_allocation_summary.xlsx'
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
URL.revokeObjectURL(url)
})
},
exportDetailCsv() {
// 仅导出当前弹窗可见的 detailRows
const headers = ['日期', '当日辅料池(元)', '全厂分钟', '卷分钟', '占比', '分摊辅料(元)']
const lines = [headers.join(',')]
;(this.detailRows || []).forEach(r => {
const line = [
this.csvCell(r.day),
this.csvCell(r.auxPoolAmount),
this.csvCell(r.totalMinutes),
this.csvCell(r.coilMinutes),
this.csvCell(r.factor),
this.csvCell(r.allocatedAuxCost)
].join(',')
lines.push(line)
})
const csv = lines.join('\n')
const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' })
const url = URL.createObjectURL(blob)
const link = document.createElement('a')
link.href = url
link.download = `aux_cost_allocation_detail_${this.detailEnterCoilNo || ''}.csv`
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
URL.revokeObjectURL(url)
},
csvCell(val) {
if (val === null || val === undefined) return ''
const s = String(val)
if (s.includes(',') || s.includes('"') || s.includes('\n')) {
return '"' + s.replace(/"/g, '""') + '"'
}
return s
},
formatNumber(val, digits = 2) {
if (val === null || val === undefined) return '-'
const num = Number(val)
if (Number.isNaN(num)) return String(val)
return num.toFixed(digits)
},
toPercent(val) {
if (val === null || val === undefined) return '-'
const num = Number(val)
if (Number.isNaN(num)) return String(val)
return (num * 100).toFixed(2) + '%'
}
}
}
</script>
<style scoped lang="scss">
.material-allocation-page {
padding: 16px 20px;
.search-card {
margin-bottom: 16px;
:deep(.el-card__body) {
padding: 16px 20px;
}
}
.stats-row {
margin-bottom: 24px;
.stat-card {
background: #fff;
border-radius: 4px;
padding: 16px;
height: 100%;
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);
transition: all 0.3s;
border: 1px solid #ebeef5;
&:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
.label {
font-size: 13px;
color: #606266;
margin-bottom: 8px;
}
.value {
font-size: 22px;
font-weight: 600;
color: #303133;
line-height: 1.2;
margin: 8px 0 4px;
}
.desc {
font-size: 12px;
color: #909399;
margin-top: 6px;
}
}
}
.section {
background: #fff;
border-radius: 4px;
padding: 16px 20px;
margin-bottom: 16px;
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);
border: 1px solid #ebeef5;
.section-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 16px;
.title {
font-size: 16px;
font-weight: 600;
color: #303133;
}
.actions {
display: flex;
gap: 8px;
}
}
.sub-title {
font-size: 14px;
font-weight: 500;
color: #606266;
margin: 16px 0 12px;
padding-bottom: 8px;
border-bottom: 1px solid #ebeef5;
}
}
.el-table {
margin-top: 8px;
th {
background-color: #f5f7fa;
color: #303133;
font-weight: 600;
}
}
.pagination-container {
margin-top: 16px;
padding: 0;
}
.detail-hint {
margin-bottom: 12px;
color: #606266;
font-size: 14px;
}
}
</style>

View File

@@ -0,0 +1,492 @@
<template>
<div class="material-allocation-page">
<el-card class="search-card">
<el-form :model="queryParams" inline label-width="100px" size="small">
<el-form-item label="入场卷号" required>
<el-input v-model="queryParams.enterCoilNo" placeholder="必填,支持模糊"></el-input>
</el-form-item>
<el-form-item label="当前卷号">
<el-input v-model="queryParams.currentCoilNo" placeholder="支持模糊"></el-input>
</el-form-item>
<el-form-item label="开始日期">
<el-date-picker v-model="queryParams.startDate" type="date" value-format="yyyy-MM-dd" placeholder="开始日期"></el-date-picker>
</el-form-item>
<el-form-item label="结束日期">
<el-date-picker v-model="queryParams.endDate" type="date" value-format="yyyy-MM-dd" placeholder="结束日期"></el-date-picker>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" @click="handleSearch">查询</el-button>
<el-button icon="el-icon-refresh" @click="handleReset">重置</el-button>
</el-form-item>
</el-form>
</el-card>
<el-row :gutter="16" class="stats-row">
<el-col :xs="24" :sm="12" :md="6" :lg="5">
<div class="stat-card">
<div class="label">备件分摊合计</div>
<div class="value">¥ {{ formatNumber(spareSummary.totalSpareCost, 2) }}</div>
<div class="desc">按日池 + 时长占比分摊</div>
</div>
</el-col>
<el-col :xs="24" :sm="12" :md="6" :lg="5">
<div class="stat-card">
<div class="label">卷数</div>
<div class="value">{{ mergedTotal }}</div>
<div class="desc">当前查询条件下</div>
</div>
</el-col>
<el-col :xs="24" :sm="12" :md="6" :lg="5">
<div class="stat-card">
<div class="label">种类数</div>
<div class="value">{{ breakdownSummary.kinds }}</div>
<div class="desc">按备件聚合</div>
</div>
</el-col>
<el-col :xs="24" :sm="12" :md="6" :lg="5">
<div class="stat-card">
<div class="label">分摊数量合计</div>
<div class="value">{{ formatNumber(breakdownSummary.totalAllocatedQty, 2) }}</div>
<div class="desc">数量按分摊系数切分</div>
</div>
</el-col>
<el-col :xs="24" :sm="12" :md="6" :lg="4">
<div class="stat-card">
<div class="label">分摊金额合计</div>
<div class="value">¥ {{ formatNumber(breakdownSummary.totalAllocatedAmount, 2) }}</div>
<div class="desc">金额按分摊系数切分</div>
</div>
</el-col>
</el-row>
<div class="section">
<div class="section-header">
<div class="title">分摊数据</div>
<div class="actions">
<el-button size="mini" type="primary" icon="el-icon-download" @click="exportSummary">导出汇总</el-button>
<el-button size="mini" icon="el-icon-document" @click="exportDetailCsv" :disabled="detailRows.length === 0">导出明细CSV</el-button>
<el-button size="mini" icon="el-icon-document" @click="exportBreakdownCsv" :disabled="breakdownRows.length === 0">导出构成CSV</el-button>
</div>
</div>
<div class="sub-title">备件消耗构成</div>
<el-table :data="breakdownRows" border stripe v-loading="breakdownLoading">
<el-table-column prop="itemCode" label="编码" width="140"></el-table-column>
<el-table-column prop="itemName" label="名称" min-width="160"></el-table-column>
<el-table-column prop="spec" label="规格" min-width="140"></el-table-column>
<el-table-column prop="unit" label="单位" width="80"></el-table-column>
<el-table-column prop="totalQty" label="全厂消耗数量" width="140" align="right">
<template slot-scope="scope">{{ formatNumber(scope.row.totalQty, 2) }}</template>
</el-table-column>
<el-table-column prop="totalAmount" label="全厂消耗金额(元)" width="160" align="right">
<template slot-scope="scope">¥ {{ formatNumber(scope.row.totalAmount, 2) }}</template>
</el-table-column>
<el-table-column prop="allocatedQty" label="分摊数量" width="120" align="right">
<template slot-scope="scope">{{ formatNumber(scope.row.allocatedQty, 2) }}</template>
</el-table-column>
<el-table-column prop="allocatedAmount" label="分摊金额(元)" width="150" align="right">
<template slot-scope="scope">¥ {{ formatNumber(scope.row.allocatedAmount, 2) }}</template>
</el-table-column>
</el-table>
<pagination
v-show="breakdownTotal > 0"
:total="breakdownTotal"
:page.sync="breakdownQuery.pageNum"
:limit.sync="breakdownQuery.pageSize"
@pagination="loadBreakdown"
/>
<div class="sub-title" style="margin-top: 16px;">备件成本分摊按入场卷号</div>
<el-table :data="mergedRows" border stripe v-loading="loading">
<el-table-column prop="enterCoilNo" label="入场卷号"></el-table-column>
<el-table-column prop="currentCoilNo" label="当前卷号"></el-table-column>
<el-table-column prop="spareCost" label="备件成本">
<template slot-scope="scope">¥ {{ formatNumber(scope.row.spareCost, 2) }}</template>
</el-table-column>
<el-table-column prop="totalNetWeight" label="净重">
<template slot-scope="scope">{{ formatNumber(scope.row.totalNetWeight, 2) }}</template>
</el-table-column>
<el-table-column prop="totalGrossWeight" label="毛重">
<template slot-scope="scope">{{ formatNumber(scope.row.totalGrossWeight, 2) }}</template>
</el-table-column>
<el-table-column label="操作" width="180">
<template slot-scope="scope">
<el-button type="text" size="mini" @click="openDetail(scope.row)">分摊明细</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="mergedTotal > 0"
:total="mergedTotal"
:page.sync="mergedQuery.pageNum"
:limit.sync="mergedQuery.pageSize"
@pagination="loadMerged"
/>
</div>
<el-dialog title="备件分摊明细(按日)" :visible.sync="detailVisible" width="80%" :close-on-click-modal="false">
<div class="detail-hint">入场卷号{{ detailEnterCoilNo }}</div>
<el-table :data="detailRows" stripe border max-height="420" v-loading="detailLoading">
<el-table-column prop="day" label="日期" width="120"></el-table-column>
<el-table-column prop="sparePoolAmount" label="当日备件池(元)" width="140">
<template slot-scope="scope">¥ {{ formatNumber(scope.row.sparePoolAmount, 2) }}</template>
</el-table-column>
<el-table-column prop="totalMinutes" label="全厂分钟" width="120">
<template slot-scope="scope">{{ formatNumber(scope.row.totalMinutes, 0) }}</template>
</el-table-column>
<el-table-column prop="coilMinutes" label="卷分钟" width="120">
<template slot-scope="scope">{{ formatNumber(scope.row.coilMinutes, 0) }}</template>
</el-table-column>
<el-table-column prop="factor" label="占比" width="100">
<template slot-scope="scope">{{ toPercent(scope.row.factor) }}</template>
</el-table-column>
<el-table-column prop="allocatedSpareCost" label="分摊备件(元)" width="140">
<template slot-scope="scope">¥ {{ formatNumber(scope.row.allocatedSpareCost, 2) }}</template>
</el-table-column>
</el-table>
<span slot="footer" class="dialog-footer">
<el-button @click="detailVisible = false"> </el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import { fetchCoilTotalMerged, exportCoilTotalMerged, fetchSparePartBreakdown } from '@/api/ems/energyCostReport'
export default {
name: 'SpareCostAllocation',
data() {
return {
queryParams: {
enterCoilNo: '',
currentCoilNo: '',
startDate: undefined,
endDate: undefined
},
mergedQuery: {
pageNum: 1,
pageSize: 50
},
loading: false,
mergedRows: [],
mergedTotal: 0,
spareSummary: {
totalSpareCost: 0
},
detailVisible: false,
detailLoading: false,
detailEnterCoilNo: '',
detailRows: [],
breakdownLoading: false,
breakdownRows: [],
breakdownTotal: 0,
breakdownQuery: {
pageNum: 1,
pageSize: 10
},
breakdownSummary: {
kinds: 0,
totalAllocatedQty: 0,
totalAllocatedAmount: 0
}
}
},
mounted() {
this.handleSearch()
},
methods: {
handleSearch() {
this.mergedQuery.pageNum = 1
this.breakdownQuery.pageNum = 1
this.loadMerged()
this.loadBreakdown()
},
handleReset() {
this.queryParams = {
enterCoilNo: '',
currentCoilNo: '',
startDate: undefined,
endDate: undefined
}
this.mergedQuery.pageNum = 1
this.breakdownQuery.pageNum = 1
this.mergedRows = []
this.mergedTotal = 0
this.spareSummary = { totalSpareCost: 0 }
this.detailRows = []
this.breakdownRows = []
this.breakdownTotal = 0
this.breakdownSummary = { kinds: 0, totalAllocatedQty: 0, totalAllocatedAmount: 0 }
this.handleSearch()
},
loadMerged() {
const params = {
...this.queryParams,
pageNum: this.mergedQuery.pageNum,
pageSize: this.mergedQuery.pageSize
}
this.loading = true
fetchCoilTotalMerged(params).then(res => {
this.mergedRows = res.rows || []
this.mergedTotal = res.total || 0
const rows = this.mergedRows || []
this.spareSummary = {
totalSpareCost: rows.reduce((sum, r) => sum + (Number(r.spareCost) || 0), 0)
}
}).finally(() => {
this.loading = false
})
},
loadBreakdown() {
const params = {
...this.queryParams,
pageNum: this.breakdownQuery.pageNum,
pageSize: this.breakdownQuery.pageSize
}
this.breakdownLoading = true
fetchSparePartBreakdown(params).then(res => {
this.breakdownRows = res.rows || []
this.breakdownTotal = res.total || 0
const rows = this.breakdownRows || []
this.breakdownSummary = {
kinds: this.breakdownTotal || rows.length || 0,
totalAllocatedQty: rows.reduce((sum, r) => sum + (Number(r.allocatedQty) || 0), 0),
totalAllocatedAmount: rows.reduce((sum, r) => sum + (Number(r.allocatedAmount) || 0), 0)
}
}).finally(() => {
this.breakdownLoading = false
})
},
exportBreakdownCsv() {
const headers = ['编码', '名称', '规格', '单位', '全厂消耗数量', '全厂消耗金额(元)', '分摊数量', '分摊金额(元)']
const lines = [headers.join(',')]
;(this.breakdownRows || []).forEach(r => {
const line = [
this.csvCell(r.itemCode),
this.csvCell(r.itemName),
this.csvCell(r.spec),
this.csvCell(r.unit),
this.csvCell(r.totalQty),
this.csvCell(r.totalAmount),
this.csvCell(r.allocatedQty),
this.csvCell(r.allocatedAmount)
].join(',')
lines.push(line)
})
const csv = lines.join('\n')
const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' })
const url = URL.createObjectURL(blob)
const link = document.createElement('a')
link.href = url
link.download = `spare_allocation_breakdown_${this.queryParams.enterCoilNo || 'all'}.csv`
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
URL.revokeObjectURL(url)
},
openDetail(row) {
if (!row || !row.enterCoilNo) return
this.detailEnterCoilNo = row.enterCoilNo
this.detailVisible = true
this.buildDetailByDay(row.enterCoilNo)
},
buildDetailByDay(enterCoilNo) {
// 见 auxAllocation.vue 的说明:后端 merged 目前不返回按日池/分钟细节。
// 这里先展示“可解释”的单行结果,后续若补充明细接口,可替换为真实按日明细。
this.detailLoading = true
const params = {
...this.queryParams,
enterCoilNo,
pageNum: 1,
pageSize: 1
}
fetchCoilTotalMerged(params).then(res => {
const row = (res.rows || [])[0]
const total = Number(row?.spareCost) || 0
this.detailRows = [
{
day: this.queryParams.startDate && this.queryParams.endDate ? `${this.queryParams.startDate} ~ ${this.queryParams.endDate}` : '-',
sparePoolAmount: null,
totalMinutes: null,
coilMinutes: null,
factor: null,
allocatedSpareCost: total
}
]
}).finally(() => {
this.detailLoading = false
})
},
exportSummary() {
const params = { ...this.queryParams }
exportCoilTotalMerged(params).then(res => {
const blob = new Blob([res], { type: 'application/vnd.ms-excel' })
const url = URL.createObjectURL(blob)
const link = document.createElement('a')
link.href = url
link.download = 'spare_cost_allocation_summary.xlsx'
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
URL.revokeObjectURL(url)
})
},
exportDetailCsv() {
const headers = ['日期', '当日备件池(元)', '全厂分钟', '卷分钟', '占比', '分摊备件(元)']
const lines = [headers.join(',')]
;(this.detailRows || []).forEach(r => {
const line = [
this.csvCell(r.day),
this.csvCell(r.sparePoolAmount),
this.csvCell(r.totalMinutes),
this.csvCell(r.coilMinutes),
this.csvCell(r.factor),
this.csvCell(r.allocatedSpareCost)
].join(',')
lines.push(line)
})
const csv = lines.join('\n')
const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' })
const url = URL.createObjectURL(blob)
const link = document.createElement('a')
link.href = url
link.download = `spare_cost_allocation_detail_${this.detailEnterCoilNo || ''}.csv`
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
URL.revokeObjectURL(url)
},
csvCell(val) {
if (val === null || val === undefined) return ''
const s = String(val)
if (s.includes(',') || s.includes('"') || s.includes('\n')) {
return '"' + s.replace(/"/g, '""') + '"'
}
return s
},
formatNumber(val, digits = 2) {
if (val === null || val === undefined) return '-'
const num = Number(val)
if (Number.isNaN(num)) return String(val)
return num.toFixed(digits)
},
toPercent(val) {
if (val === null || val === undefined) return '-'
const num = Number(val)
if (Number.isNaN(num)) return String(val)
return (num * 100).toFixed(2) + '%'
}
}
}
</script>
<style scoped lang="scss">
.material-allocation-page {
padding: 16px 20px;
.search-card {
margin-bottom: 16px;
:deep(.el-card__body) {
padding: 16px 20px;
}
}
.stats-row {
margin-bottom: 24px;
.stat-card {
background: #fff;
border-radius: 4px;
padding: 16px;
height: 100%;
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);
transition: all 0.3s;
border: 1px solid #ebeef5;
&:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
.label {
font-size: 13px;
color: #606266;
margin-bottom: 8px;
}
.value {
font-size: 22px;
font-weight: 600;
color: #303133;
line-height: 1.2;
margin: 8px 0 4px;
}
.desc {
font-size: 12px;
color: #909399;
margin-top: 6px;
}
}
}
.section {
background: #fff;
border-radius: 4px;
padding: 16px 20px;
margin-bottom: 16px;
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);
border: 1px solid #ebeef5;
.section-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 16px;
.title {
font-size: 16px;
font-weight: 600;
color: #303133;
}
.actions {
display: flex;
gap: 8px;
}
}
.sub-title {
font-size: 14px;
font-weight: 500;
color: #606266;
margin: 16px 0 12px;
padding-bottom: 8px;
border-bottom: 1px solid #ebeef5;
}
}
.el-table {
margin-top: 8px;
th {
background-color: #f5f7fa;
color: #303133;
font-weight: 600;
}
}
.pagination-container {
margin-top: 16px;
padding: 0;
}
.detail-hint {
margin-bottom: 12px;
color: #606266;
font-size: 14px;
}
}
</style>

View File

@@ -196,14 +196,11 @@
<span class="info-value">{{ item.netWeight || '—' }}t</span>
</div>
</div>
<!-- <el-button style="position: absolute; bottom: 10px; right: 10px;" type="success" icon="el-icon-scissors"
size="mini" @click="handleStartSplit(item)" :loading="buttonLoading" class="action-btn">分条</el-button> -->
</div>
<div class="card-footer">
<el-button v-if="useSpecialSplit" type="success" icon="el-icon-scissors" size="mini"
@click="handleStartSplit(item)" :loading="buttonLoading" class="action-btn">分条</el-button>
@click="handleStartSplit(item)" :loading="buttonLoading" class="action-btn">加工</el-button>
<el-button v-else type="primary" icon="el-icon-check" size="mini" @click="handlePickMaterial(item)"
:loading="buttonLoading" class="action-btn">领料</el-button>
<el-button type="danger" icon="el-icon-alarm-clock" :plain="item.abnormalCount == 0" size="mini"
@@ -223,21 +220,77 @@
<!-- 右侧待操作列表 -->
<el-col :span="12">
<div v-if="useSpecialSplit" style="margin-bottom: 20px;" v-loading="stepSpilt.loading">
<div class="section-header">
<div class="section-card action-section" v-if="useSpecialSplit" style="margin-bottom: 20px;"
v-loading="stepSpilt.loading">
<div class="section-header ">
<h3 class="section-title">进行中的镀锌工序</h3>
<el-button size="mini" icon="el-icon-refresh" @click="getStepSplitList">刷新</el-button>
</div>
<div style="display: flex; align-items: center; gap: 10px; flex-wrap: wrap;">
<div v-for="item in stepSpilt.list" :key="item.coilId || index"
style="text-align: center; padding: 10px; border: 2px solid #e4e7ed; border-radius: 4px;">
<div class="step-item" style="font-size: 24px; font-weight: bold; ">
<span class="step-value">{{ item.currentCoilNo }}</span>
<div v-if="stepSpilt.list.length > 0" style="display: flex; align-items: center; gap: 10px; flex-wrap: wrap;">
<div v-for="(item, index) in stepSpilt.list" :key="item.coilId || index" class="coil-card"
style="border: 1px solid #e4e7ed; border-radius: 8px; padding: 16px; margin-bottom: 12px; background: linear-gradient(135deg, #f8f9fa 0%, #ffffff 100%); box-shadow: 0 2px 8px rgba(0,0,0,0.05);">
<!-- 主标题区域 - 突出显示currentCoilNo -->
<div class="card-header" style="margin-bottom: 16px; text-align: center;">
<div style="display: inline-block; position: relative;">
<!-- <div style="font-size: 12px; color: #909399; margin-bottom: 4px;">卷号</div> -->
<div class="coil-no" style="font-size: 28px; font-weight: 800; color: #409eff; letter-spacing: 1px;
padding: 4px 16px; background: linear-gradient(135deg, #ecf5ff 0%, #d9ecff 100%);
border-radius: 6px; display: inline-block; border: 2px solid #a0cfff;">
{{ item.currentCoilNo || 'N/A' }}
</div>
</div>
</div>
<!-- 详细信息区域 -->
<!-- <div class="card-content" style="margin-bottom: 16px;">
<div class="info-row" style="display: flex; justify-content: space-between; margin-bottom: 10px;">
<div class="info-item" style="flex: 1; text-align: center;">
<div style="font-size: 11px; color: #909399; margin-bottom: 2px;">仓库</div>
<div style="font-size: 14px; font-weight: 600; color: #303133;">
{{ item.warehouseName || '-' }}
</div>
</div>
<div style="width: 1px; background: #e4e7ed; margin: 0 8px;"></div>
<div class="info-item" style="flex: 1; text-align: center;">
<div style="font-size: 11px; color: #909399; margin-bottom: 2px;">实际仓库</div>
<div style="font-size: 14px; font-weight: 600; color: #303133;">
{{ item.actualWarehouseName || '-' }}
</div>
</div>
</div>
<div class="weight-info" style="background: linear-gradient(135deg, #f0f9eb 0%, #e1f3d8 100%);
border-radius: 6px; padding: 8px; margin-top: 8px; text-align: center;">
<div style="display: inline-block;">
<div style="font-size: 12px; color: #67c23a; margin-bottom: 2px;">净重</div>
<div style="font-size: 18px; font-weight: 700; color: #67c23a;">
{{ item.netWeight ? `${item.netWeight} kg` : '-' }}
</div>
</div>
</div>
</div> -->
<!-- 操作按钮区域 -->
<div class="card-actions" style="text-align: center; border-top: 1px solid #ebeef5; padding-top: 12px;">
<el-button type="primary" size="mini" @click="handleContinueSplit(item)"
style="min-width: 80px; padding: 5px 15px;">
查看
</el-button>
<el-button size="mini" @click="handleCancelSplit(item)"
style="min-width: 80px; padding: 5px 15px; margin-left: 12px; border-color: #f56c6c; color: #f56c6c;"
:plain="true">
取消
</el-button>
</div>
<el-button type="primary" size="mini" @click="handleContinueSplit(item)">查看</el-button>
<el-button size="mini" @click="handleCancelSplit(item)">取消操作</el-button>
</div>
</div>
<div v-else>
<el-empty description="暂无进行中的镀锌工序" />
</div>
</div>
<div class="section-card action-section">
@@ -267,7 +320,7 @@
</el-form>
<!-- 待操作卡片列表 -->
<div v-loading="actionLoading" class="card-grid-container">
<div v-if="!useSpecialSplit" v-loading="actionLoading" class="card-grid-container">
<div v-if="pendingActionList.length === 0" class="empty-state">
<i class="el-icon-document"></i>
<p>暂无待操作任务</p>
@@ -290,11 +343,6 @@
<div class="card-body">
<div class="info-list">
<div class="info-item">
<span class="info-label">类型</span>
<dict-tag :options="dict.type.action_type" :value="item.actionType"
class="action-type-tag"></dict-tag>
</div>
<div class="info-item">
<span class="info-label">来源</span>
<span class="info-value">
@@ -342,14 +390,29 @@
@click="handleDeleteAction(item)" class="action-btn">删除</el-button>
</template>
</div>
<div class="card-footer" v-else="!useSpecialSplit">
<el-button :loading="buttonLoading" type="primary" icon="el-icon-edit" size="mini"
@click="handleProcess(item)" class="action-btn">查看</el-button>
</div>
</div>
</div>
<el-table v-else :data="pendingActionList">
<el-table-column label="钢卷号" prop="currentCoilNo"></el-table-column>
<el-table-column label="操作状态" prop="actionStatus">
<template slot-scope="scope">
<el-tag v-if="scope.row.actionStatus === 0" type="info" size="mini">待处理</el-tag>
<el-tag v-else-if="scope.row.actionStatus === 1" type="warning" size="mini">处理中</el-tag>
<el-tag v-else-if="scope.row.actionStatus === 2" type="success" size="mini">已完成</el-tag>
<el-tag v-else-if="scope.row.actionStatus === 3" type="danger" size="mini">已取消</el-tag>
</template>
</el-table-column>
<el-table-column label="创建人" prop="createBy"></el-table-column>
<el-table-column label="操作人" prop="operatorName"></el-table-column>
<el-table-column label="操作">
<template slot-scope="scope">
<el-button v-if="scope.row.actionStatus === 2" :loading="buttonLoading" icon="el-icon-delete"
size="mini" @click="handleDeleteAction(scope.row)" class="action-btn">删除</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<pagination v-show="actionTotal > 0" :total="actionTotal" :page.sync="actionQueryParams.pageNum"
:limit.sync="actionQueryParams.pageSize" @pagination="getPendingAction" />
@@ -396,8 +459,8 @@
<label-render :content="labelRender.data" :labelType="labelRender.type" />
</el-dialog>
<el-dialog title="分步分条" :visible.sync="stepSpilt.visible" width="1400px" append-to-body>
<step-split @print="handlePrintLabel" @complete="stepSpilt.visible = false" :actionId="stepSpilt.actionId"
<el-dialog title="分步加工" :visible.sync="stepSpilt.visible" width="1400px" append-to-body>
<step-split @print="handlePrintLabel" @complete="handleComposeSplit" :actionId="stepSpilt.actionId"
:coilId="stepSpilt.coilId" :actionStatus="stepSpilt.actionStatus" />
</el-dialog>
@@ -833,7 +896,7 @@ export default {
async handleStartSplit(row) {
this.buttonLoading = true
try {
await this.$modal.confirm('是否确认领料开始分操作?')
await this.$modal.confirm('是否确认领料开始分步加工操作?')
this.stepSpilt.loading = true
await startSpecialSplit(row.coilId);
// await addPendingAction({
@@ -844,7 +907,7 @@ export default {
// sourceType: 'manual',
// priority: 0,
// })
this.$message.success('分条操作已创建')
this.$message.success('加工操作已创建')
this.getPendingAction()
// this.getMaterialCoil()

View File

@@ -92,3 +92,135 @@ CREATE TABLE `eqp_spare_parts_change` (
KEY `fk_change_part` (`part_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1980201774324969474 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='备品备件变动记录表';
create table wms_material_coil
(
coil_id bigint auto_increment comment '主键ID'
primary key,
enter_coil_no varchar(50) not null comment '入场钢卷号(年份后两位+月份+当月第几个如25100001、25102422',
current_coil_no varchar(50) not null comment '当前钢卷号(入场钢卷号和当前钢卷号可能不同)',
supplier_coil_no varchar(50) null comment '厂家原料卷号',
data_type tinyint(1) default 1 not null comment '数据类型0=历史1=现存)',
warehouse_id bigint null comment '所在库区ID',
next_warehouse_id bigint null comment '下一库区ID',
actual_warehouse_id bigint null comment '所在实际库区ID关联wms_actual_warehouse表',
qrcode_record_id bigint null comment '关联二维码IDwms_generate_record.record_id',
team varchar(50) null comment '班组',
has_merge_split tinyint(1) default 0 not null comment '是否合卷/分卷0=否1=分卷2=合卷)',
parent_coil_nos varchar(500) null comment '父卷号(合卷或分卷时用,逗号分隔)',
item_id bigint not null comment '物品ID指向原材料或产品主键',
item_type varchar(20) not null comment '物品类型raw_material/product',
material_type varchar(20) null comment '材料类型(废品,成品,原料)',
quality_status varchar(20) null comment '质量状态0=正常1=待检2=不合格)',
status tinyint(1) default 0 null comment '状态0=在库1=已出库)',
remark varchar(255) null comment '备注',
export_time datetime null comment '发货时间',
del_flag tinyint(1) default 0 not null comment '删除标志0=正常1=已删除)',
create_time datetime default CURRENT_TIMESTAMP not null comment '创建时间',
create_by varchar(50) null comment '创建人',
update_time datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '更新时间',
update_by varchar(50) null comment '更新人',
gross_weight decimal(10, 3) null comment '毛重',
net_weight decimal(10, 3) null comment '毛重',
length decimal(10, 3) null comment '钢卷长度(单位:米)',
trimming_requirement varchar(100) null comment '切边要求',
packing_status varchar(20) null comment '打包状态0=未打包1=已打包)',
packaging_requirement varchar(255) null comment '包装要求',
sale_id bigint null comment '销售id',
constraint fk_coil_next_warehouse
foreign key (next_warehouse_id) references wms_warehouse (warehouse_id),
constraint fk_coil_qrcode
foreign key (qrcode_record_id) references wms_generate_record (record_id)
)
comment '钢卷物料表';
create index idx_coil_current_no
on wms_material_coil (current_coil_no);
create index idx_coil_type
on wms_material_coil (data_type);
create index idx_coil_warehouse
on wms_material_coil (warehouse_id);
create index idx_mc_coil_id
on wms_material_coil (coil_id);
create index idx_mc_core
on wms_material_coil (del_flag, data_type, status, material_type, actual_warehouse_id, item_type, item_id);
create index idx_mc_data_type
on wms_material_coil (data_type);
create index idx_mc_del_awh
on wms_material_coil (del_flag, actual_warehouse_id);
create index idx_mc_del_create
on wms_material_coil (del_flag, create_time);
create index idx_mc_del_item
on wms_material_coil (del_flag, item_type, item_id);
create index idx_mc_del_status_sale
on wms_material_coil (del_flag, status, sale_id);
create index idx_mc_del_update
on wms_material_coil (del_flag, update_time);
create index idx_mc_del_wh
on wms_material_coil (del_flag, warehouse_id);
create index idx_mc_enter_coil_no
on wms_material_coil (enter_coil_no);
create index idx_mc_fixed_group
on wms_material_coil (del_flag, data_type, status, item_type, actual_warehouse_id, item_id);
create index idx_mc_has_merge_split
on wms_material_coil (has_merge_split);
create index idx_mc_team
on wms_material_coil (team);
create table wms_coil_pending_action
(
action_id bigint auto_increment comment '主键ID'
primary key,
coil_id bigint not null comment '关联的钢卷ID',
current_coil_no varchar(50) not null comment '当前钢卷号',
action_type int not null comment '操作类型1=分卷2=合卷3=更新)',
action_status tinyint(1) default 0 not null comment '操作状态0=待处理1=处理中2=已完成3=已取消)',
scan_time datetime null comment '扫码时间',
scan_device varchar(100) null comment '扫码设备(移动端设备信息)',
priority tinyint(1) default 0 null comment '优先级0=普通1=重要2=紧急)',
source_type varchar(20) default 'scan' not null comment '来源类型scan=扫码manual=手动创建)',
warehouse_id bigint null comment '所在库区ID',
operator_id bigint null comment '操作人ID',
operator_name varchar(50) null comment '操作人姓名',
process_time datetime null comment '处理时间',
complete_time datetime null comment '完成时间',
remark varchar(500) null comment '备注',
del_flag tinyint(1) default 0 not null comment '删除标志0=正常1=已删除)',
create_time datetime default CURRENT_TIMESTAMP not null comment '创建时间',
create_by varchar(50) null comment '创建人',
update_time datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '更新时间',
update_by varchar(50) null comment '更新人'
)
comment '钢卷待操作表';
create index idx_action_status
on wms_coil_pending_action (action_status);
create index idx_action_type
on wms_coil_pending_action (action_type);
create index idx_coil_id
on wms_coil_pending_action (coil_id);
create index idx_scan_time
on wms_coil_pending_action (scan_time);
create index idx_warehouse_id
on wms_coil_pending_action (warehouse_id);