/*
* Copyright (c) Huawei Technologies Co., Ltd. 2025-2025. All rights reserved.
*/
package com.huawei.it.tgmes.tmas.excel.wavejuxin;
import com.huawei.it.jalor5.core.base.PageVO;
import com.huawei.it.jalor5.core.exception.ApplicationException;
import com.huawei.it.jalor5.excel.exporter.IExcelDataProvider;
import com.huawei.it.jalor5.excel.exporter.IExcelExportContext;
import com.huawei.it.jalor5.excel.exporter.IExcelExtentionDataProvider;
import com.huawei.it.jalor5.excel.meta.ColumnMeta;
import com.huawei.it.jalor5.excel.meta.SheetMeta;
import com.huawei.it.tgmes.tmas.common.exception.TgmesTmasApplicationException;
import com.huawei.it.tgmes.tmas.common.security.ValuesUtils;
import com.huawei.it.tgmes.tmas.unit.ConstantsUtil;
import com.huawei.it.tgmes.tmas.unit.DynamicVo;
import com.huawei.it.tgmes.tmas.wavejuxin.dao.IApsSupplyRequireDao;
import com.huawei.it.tgmes.tmas.wavejuxin.entity.bo.ApsSupplyRequireHead;
import com.huawei.it.tgmes.tmas.wavejuxin.entity.vo.ApsSupplyRequireCondition;
import com.huawei.it.tgmes.tmas.wavejuxin.entity.vo.ApsSupplyRequireVO;
import com.huawei.it.tgmes.tmas.wavejuxin.service.IApsSupplyRequireService;
import com.alibaba.excel.metadata.property.ExcelContentProperty;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import javax.inject.Named;
/**
* 排产供需匹配导出
*
* @author zhongweiquan
* @date 2025/6/23
*/
@Named("IExcelDataProvider.apsSupplyRequireExport")
public class ApsSupplyRequireExport implements IExcelDataProvider, IExcelExtentionDataProvider {
private static final Logger LOGGER = LoggerFactory.getLogger(ApsSupplyRequireExport.class);
/**
* 类型:排产
*/
private static final String DATA_TYPE_SCHEDULING = "排产";
/**
* 类型:预计供应
*/
private static final String DATA_TYPE_PROJECTED_SUPPLY = "预计供应";
/**
* 类型:过站供应
*/
private static final String DATA_TYPE_STOP_SUPPLY = "过站供应";
/**
* 类型:排产需求
*/
private static final String DATA_TYPE_SCHEDULING_REQUIRE = "排产需求";
/**
* 类型:供需匹配
*/
private static final String DATA_TYPE_SUPPLY_REQUIRE = "供需匹配";
@Autowired
private IApsSupplyRequireDao apsSupplyRequireDao;
@Autowired
private IApsSupplyRequireService apsSupplyRequireService;
@Override
public List<?> getBatchData(Serializable serializable, PageVO pageVO) throws ApplicationException {
ApsSupplyRequireCondition condition = (ApsSupplyRequireCondition) serializable;
if (ValuesUtils.isEmpty(condition) || ValuesUtils.isEmpty(condition.getPlanId())) {
throw new TgmesTmasApplicationException("版本号不能为空");
}
List<DynamicVo> resultList = new ArrayList<>();
condition.setDataType(DATA_TYPE_SCHEDULING);
// 查询出的头表数据按照部门名称升序,产品族名称升序,工序按照“服务组件->副板->主板->前壳->后壳->组装->包装”排序,编码升序
List<ApsSupplyRequireHead> headList = apsSupplyRequireDao.getApsSupplyRequireHeadByCondition(condition);
if (ValuesUtils.isEmpty(headList)) {
return resultList;
}
// 根据版本号、厂区、部门与排产编码查询排产供需匹配数据
List<ApsSupplyRequireVO> apsSupplyRequireList = apsSupplyRequireService.getApsSupplyRequireListByHeadList(
headList, condition);
if (ValuesUtils.isEmpty(apsSupplyRequireList)) {
return resultList;
}
List<List<ApsSupplyRequireVO>> asrsList = getApsSupplyRequiresList(condition, apsSupplyRequireList,
headList);
for (List<ApsSupplyRequireVO> asrList : asrsList) {
if (ValuesUtils.isEmpty(asrList)) {
continue;
}
// 封装头行表数据
ApsSupplyRequireVO apsSupplyRequire = asrList.get(0);
DynamicVo dynamicVo = new DynamicVo();
dynamicVo.getDataMap().put("planId", apsSupplyRequire.getPlanId());
dynamicVo.getDataMap().put("locationName", apsSupplyRequire.getLocationName());
dynamicVo.getDataMap().put("deptName", apsSupplyRequire.getDeptName());
dynamicVo.getDataMap().put("prodLineCnName", apsSupplyRequire.getProdLineCnName());
dynamicVo.getDataMap().put("prodFamilyEnName", apsSupplyRequire.getProdFamilyEnName());
dynamicVo.getDataMap().put("prodModelCode", apsSupplyRequire.getProdModelCode());
dynamicVo.getDataMap().put("workSerction", apsSupplyRequire.getWorkSerction());
dynamicVo.getDataMap().put("itemCode", apsSupplyRequire.getItemCode());
dynamicVo.getDataMap().put("dataType", apsSupplyRequire.getDataType());
dynamicVo.getDataMap().put("invQty", apsSupplyRequire.getInvQty());
dynamicVo.getDataMap().put("prodDelayQty", apsSupplyRequire.getProdDelayQty());
dynamicVo.getDataMap().put("hisQty", apsSupplyRequire.getHisQty());
for (ApsSupplyRequireVO asr : asrList) {
dynamicVo.getDataMap().put(asr.getBucket(), asr.getQty());
}
resultList.add(dynamicVo);
}
return resultList;
}
@Override
public void begin(IExcelExportContext iExcelExportContext) throws ApplicationException {
SheetMeta sheetMeta = iExcelExportContext.getCurrentSheet();
if (sheetMeta == null) {
return;
}
ApsSupplyRequireCondition condition = (ApsSupplyRequireCondition) iExcelExportContext.getRequest()
.getConditionObject();
List<String> bucketList = apsSupplyRequireService.getHeadBucketList(condition);
List<ColumnMeta> columns = sheetMeta.getColumns();
columns.clear();
this.createColumnMeta("planId", "版本", "planId", "String", columns);
this.createColumnMeta("locationName", "厂区", "locationName", "String", columns);
this.createColumnMeta("deptName", "部门", "deptName", "String", columns);
this.createColumnMeta("prodLineCnName", "产品线", "prodLineCnName", "String", columns);
this.createColumnMeta("prodFamilyEnName", "产品族", "prodFamilyEnName", "String", columns);
this.createColumnMeta("prodModelCode", "产品型号", "prodModelCode", "String", columns);
this.createColumnMeta("workSerction", "工序", "workSerction", "String", columns);
this.createColumnMeta("itemCode", "物料编码", "itemCode", "String", columns);
this.createColumnMeta("dataType", "类型", "dataType", "String", columns);
this.createColumnMeta("invQty", "库存", "invQty", "BigDecimal", columns);
this.createColumnMeta("prodDelayQty", "落产", "prodDelayQty", "BigDecimal", columns);
this.createColumnMeta("hisQty", "历史", "hisQty", "BigDecimal", columns);
List<String> formattedBucketList = new ArrayList<>();
for (String bucket : bucketList) {
String displayName = bucket;
if (bucket != null && bucket.length() >= 10) {
displayName = bucket.substring(5, 10).replace('-', '/');
}
this.createColumnMeta(bucket, displayName, bucket, "BigDecimal", columns);
}
}
@Override
public void fail(IExcelExportContext iExcelExportContext) throws ApplicationException {
}
@Override
public void end(IExcelExportContext iExcelExportContext) throws ApplicationException {
}
/**
* 获取本次导出的排产供需匹配数据集合
*
* @param condition 查询条件
* @param apsSupplyRequireList 未过滤的排产供需匹配数据
* @param headList 头表数据集合
* @return Map<String, List<ApsSupplyRequireVO>> 本次导出的排产供需匹配数据集合
*/
private List<List<ApsSupplyRequireVO>> getApsSupplyRequiresList(ApsSupplyRequireCondition condition,
List<ApsSupplyRequireVO> apsSupplyRequireList, List<ApsSupplyRequireHead> headList) {
List<List<ApsSupplyRequireVO>> result = new ArrayList<>();
// 按照厂区+部门+排产编码对排产供需匹配数据进行分组
Map<String, List<ApsSupplyRequireVO>> apsSupplyRequireMap = apsSupplyRequireList.stream()
.collect(Collectors.groupingBy(
item -> ConstantsUtil.getKey(item.getLocationCode(), item.getDeptCode(), item.getSchedulingCode())));
// 筛选出本次查询的数据集合
List<String> keyList = headList.stream()
.map(item -> ConstantsUtil.getKey(item.getLocationCode(), item.getDeptCode(), item.getSchedulingCode()))
.collect(Collectors.toList());
for (String key : keyList) {
List<ApsSupplyRequireVO> dataList = apsSupplyRequireMap.get(key);
if (ValuesUtils.isEmpty(dataList)) {
continue;
}
// 每个分组内的排产供需匹配数据,按照“排产->预计供应->过站供应->排产需求->供需匹配”排序
setAsrListByDataType(condition.getDataTypeArray(), DATA_TYPE_SCHEDULING, dataList, result);
// 由于混拼板展示的排产编码与物料编码存在一对多的关系,所以还需要再按物料编码进行分组
Map<String, List<ApsSupplyRequireVO>> itemCodeMap = dataList.stream()
.collect(Collectors.groupingBy(ApsSupplyRequireVO::getItemCode));
for (Map.Entry<String, List<ApsSupplyRequireVO>> entry : itemCodeMap.entrySet()) {
setAsrListByDataType(condition.getDataTypeArray(), DATA_TYPE_PROJECTED_SUPPLY, entry.getValue(),
result);
setAsrListByDataType(condition.getDataTypeArray(), DATA_TYPE_STOP_SUPPLY, entry.getValue(), result);
setAsrListByDataType(condition.getDataTypeArray(), DATA_TYPE_SCHEDULING_REQUIRE, entry.getValue(),
result);
setAsrListByDataType(condition.getDataTypeArray(), DATA_TYPE_SUPPLY_REQUIRE, entry.getValue(), result);
}
}
return result;
}
/**
* 根据类型筛选对应的排产供需匹配数据
*
* @param dataTypeArray 类型查询条件数组
* @param dataType 类型
* @param dataList 未过滤数据的排产供需匹配数据
* @param result 分组并过滤后的排产供需匹配数据集合
*/
private void setAsrListByDataType(String[] dataTypeArray, String dataType,
List<ApsSupplyRequireVO> dataList, List<List<ApsSupplyRequireVO>> result) {
if (ValuesUtils.isEmpty(dataList) || ValuesUtils.isEmpty(dataType)) {
return;
}
if (ValuesUtils.isEmpty(dataTypeArray) || Arrays.asList(dataTypeArray).contains(dataType)) {
List<ApsSupplyRequireVO> list = dataList.stream()
.filter(item -> dataType.equals(item.getDataType()))
.collect(Collectors.toList());
if (ValuesUtils.isNotEmpty(list)) {
result.add(list);
}
}
}
/**
* 创建动态列模板
*
* @param column 列名
* @param displayName 显示名
* @param fieldName 字段名
* @param type 数据类型
* @param columns 列对象
*/
private void createColumnMeta(String column, String displayName, String fieldName, String type,
List<ColumnMeta> columns) {
ColumnMeta itemLineColumn = new ColumnMeta(column);
itemLineColumn.setDisplayName(displayName);
itemLineColumn.setFieldName("dataMap." + fieldName);
itemLineColumn.setType(type);
columns.add(itemLineColumn);
}
}