@@ -41,6 +41,15 @@ import java.util.*;
import java.util.stream.Collectors ;
import java.math.BigDecimal ;
import java.util.Arrays ;
import java.io.IOException ;
import java.net.URLEncoder ;
import java.nio.charset.StandardCharsets ;
import java.text.SimpleDateFormat ;
import javax.servlet.ServletOutputStream ;
import javax.servlet.http.HttpServletResponse ;
import org.apache.poi.ss.usermodel.* ;
import org.apache.poi.ss.util.CellRangeAddress ;
import org.apache.poi.xssf.usermodel.XSSFWorkbook ;
/**
* 钢卷物料表Service业务层处理
@@ -73,6 +82,8 @@ public class WmsMaterialCoilServiceImpl implements IWmsMaterialCoilService {
private final WmsCoilWarehouseOperationLogMapper wmsCoilWarehouseOperationLogMapper ;
private final IWmsCoilAbnormalService coilAbnormalService ;
private final WmsCoilContractRelMapper coilContractRelMapper ;
private final WmsCoilQualityRejudgeMapper wmsCoilQualityRejudgeMapper ;
private final WmsCoilAbnormalMapper coilAbnormalMapper ;
/**
* 查询钢卷物料表
@@ -5280,5 +5291,266 @@ public class WmsMaterialCoilServiceImpl implements IWmsMaterialCoilService {
return false ;
}
@Override
public void exportAbnormalReport ( WmsMaterialCoilBo bo , HttpServletResponse response ) {
// 1. 查询钢卷列表
List < WmsMaterialCoilVo > coilList = queryList ( bo ) ;
if ( coilList = = null | | coilList . isEmpty ( ) ) {
throw new RuntimeException ( " 未找到符合条件的钢卷数据 " ) ;
}
// 2. 收集所有钢卷ID
List < Long > coilIds = coilList . stream ( )
. map ( WmsMaterialCoilVo : : getCoilId )
. distinct ( )
. collect ( Collectors . toList ( ) ) ;
// 3. 批量查询异常信息
Map < Long , List < WmsCoilAbnormal > > abnormalMap = new HashMap < > ( ) ;
if ( ! coilIds . isEmpty ( ) ) {
LambdaQueryWrapper < WmsCoilAbnormal > abnormalQuery = new LambdaQueryWrapper < > ( ) ;
abnormalQuery . in ( WmsCoilAbnormal : : getCoilId , coilIds ) ;
abnormalQuery . eq ( WmsCoilAbnormal : : getDelFlag , 0 ) ;
List < WmsCoilAbnormal > allAbnormals = coilAbnormalMapper . selectList ( abnormalQuery ) ;
if ( allAbnormals ! = null & & ! allAbnormals . isEmpty ( ) ) {
abnormalMap = allAbnormals . stream ( )
. collect ( Collectors . groupingBy ( WmsCoilAbnormal : : getCoilId ) ) ;
}
}
// 4. 批量查询改判原因(最新的一条)
Map < Long , String > rejudgeReasonMap = new HashMap < > ( ) ;
if ( ! coilIds . isEmpty ( ) ) {
LambdaQueryWrapper < WmsCoilQualityRejudge > rejudgeQuery = new LambdaQueryWrapper < > ( ) ;
rejudgeQuery . in ( WmsCoilQualityRejudge : : getCoilId , coilIds ) ;
rejudgeQuery . eq ( WmsCoilQualityRejudge : : getDelFlag , " 0 " ) ;
rejudgeQuery . orderByDesc ( WmsCoilQualityRejudge : : getCreateTime ) ;
List < WmsCoilQualityRejudge > allRejudges = wmsCoilQualityRejudgeMapper . selectList ( rejudgeQuery ) ;
if ( allRejudges ! = null & & ! allRejudges . isEmpty ( ) ) {
// 按钢卷ID分组, 每组取最新的一条
Map < Long , List < WmsCoilQualityRejudge > > rejudgeGroupMap = allRejudges . stream ( )
. collect ( Collectors . groupingBy ( WmsCoilQualityRejudge : : getCoilId ) ) ;
for ( Map . Entry < Long , List < WmsCoilQualityRejudge > > entry : rejudgeGroupMap . entrySet ( ) ) {
List < WmsCoilQualityRejudge > rejudges = entry . getValue ( ) ;
if ( ! rejudges . isEmpty ( ) ) {
// 由于已按创建时间降序排列,第一条就是最新的
WmsCoilQualityRejudge latestRejudge = rejudges . get ( 0 ) ;
if ( latestRejudge . getRejudgeReason ( ) ! = null ) {
rejudgeReasonMap . put ( entry . getKey ( ) , latestRejudge . getRejudgeReason ( ) ) ;
}
}
}
}
}
// 5. 构建导出数据(扁平化:一个钢卷+一个异常 = 一行)
List < WmsCoilAbnormalExportRow > exportData = new ArrayList < > ( ) ;
for ( WmsMaterialCoilVo coil : coilList ) {
Long coilId = coil . getCoilId ( ) ;
List < WmsCoilAbnormal > abnormalList = abnormalMap . getOrDefault ( coilId , new ArrayList < > ( ) ) ;
String rejudgeReason = rejudgeReasonMap . get ( coilId ) ;
if ( abnormalList . isEmpty ( ) ) {
WmsCoilAbnormalExportRow row = new WmsCoilAbnormalExportRow ( ) ;
row . setCoil ( coil ) ;
row . setRejudgeReason ( rejudgeReason ) ;
row . setAbnormal ( null ) ;
exportData . add ( row ) ;
} else {
for ( WmsCoilAbnormal abnormal : abnormalList ) {
WmsCoilAbnormalExportRow row = new WmsCoilAbnormalExportRow ( ) ;
row . setCoil ( coil ) ;
row . setRejudgeReason ( rejudgeReason ) ;
row . setAbnormal ( abnormal ) ;
exportData . add ( row ) ;
}
}
}
// 6. 导出Excel
try ( Workbook wb = new XSSFWorkbook ( ) ) {
Sheet sheet = wb . createSheet ( " 异常报表 " ) ;
int r = 0 ;
// 标题行
Row titleRow = sheet . createRow ( r + + ) ;
titleRow . setHeightInPoints ( 36f ) ;
Cell titleCell = titleRow . createCell ( 0 ) ;
titleCell . setCellValue ( " 钢卷异常报表 " ) ;
CellStyle titleStyle = wb . createCellStyle ( ) ;
titleStyle . setAlignment ( HorizontalAlignment . CENTER ) ;
titleStyle . setVerticalAlignment ( VerticalAlignment . CENTER ) ;
Font titleFont = wb . createFont ( ) ;
titleFont . setBold ( true ) ;
titleFont . setFontHeightInPoints ( ( short ) 15 ) ;
titleStyle . setFont ( titleFont ) ;
CellRangeAddress titleRegion = new CellRangeAddress ( 0 , 0 , 0 , 41 ) ;
sheet . addMergedRegion ( titleRegion ) ;
for ( int i = titleRegion . getFirstColumn ( ) ; i < = titleRegion . getLastColumn ( ) ; i + + ) {
Cell cell = titleRow . getCell ( i ) ;
if ( cell = = null ) cell = titleRow . createCell ( i ) ;
cell . setCellStyle ( titleStyle ) ;
}
// 表头
String [ ] headers = {
" 类型 " , " 逻辑库区 " , " 实际库区 " , " 入场卷号 " , " 厂家卷号 " , " 成品卷号 " , " 日期 " ,
" 重量 " , " 用途 " , " 切边要求 " , " 包装种类 " , " 产品质量 " , " 原料材质 " ,
" 库存状态 " , " 备注 " , " 名称 " , " 规格 " , " 长度 " , " 材质 " , " 厂家 " ,
" 表面处理 " , " 锌层 " , " 物品ID " , " 操作完成时间 " , " 调拨类型 " ,
" 改判原因 " ,
" 产线 " , " 位置 " , " 长度坐标 " , " 缺陷开始位置 " , " 缺陷结束位置 " ,
" 缺陷代码 " , " 缺陷类型 " , " 缺陷率 " , " 缺陷重量 " , " 程度 " , " 判级 " ,
" 判级人 " , " 判级时间 " , " 主标记 " , " 整卷标记 " , " 异常备注 " , " 板面 "
} ;
CellStyle headStyle = wb . createCellStyle ( ) ;
Font headFont = wb . createFont ( ) ;
headFont . setBold ( true ) ;
headStyle . setFont ( headFont ) ;
headStyle . setAlignment ( HorizontalAlignment . CENTER ) ;
headStyle . setVerticalAlignment ( VerticalAlignment . CENTER ) ;
headStyle . setFillPattern ( FillPatternType . SOLID_FOREGROUND ) ;
headStyle . setFillForegroundColor ( IndexedColors . PALE_BLUE . getIndex ( ) ) ;
headStyle . setWrapText ( true ) ;
Row headRow = sheet . createRow ( r + + ) ;
headRow . setHeightInPoints ( 24 ) ;
for ( int i = 0 ; i < headers . length ; i + + ) {
Cell cell = headRow . createCell ( i ) ;
cell . setCellValue ( headers [ i ] ) ;
cell . setCellStyle ( headStyle ) ;
}
// 数据行样式
CellStyle centerStyle = wb . createCellStyle ( ) ;
centerStyle . setAlignment ( HorizontalAlignment . CENTER ) ;
centerStyle . setVerticalAlignment ( VerticalAlignment . CENTER ) ;
// 填充数据
int dataStartRow = r ;
SimpleDateFormat sdf = new SimpleDateFormat ( " yyyy-MM-dd HH:mm:ss " ) ;
for ( WmsCoilAbnormalExportRow rowData : exportData ) {
WmsMaterialCoilVo coil = rowData . getCoil ( ) ;
WmsCoilAbnormal abnormal = rowData . getAbnormal ( ) ;
String rejudgeReason = rowData . getRejudgeReason ( ) ;
Row row = sheet . createRow ( r + + ) ;
int cc = 0 ;
// 钢卷信息( 前25列)
row . createCell ( cc + + ) . setCellValue ( coil . getItemType ( ) ! = null ? coil . getItemType ( ) : " " ) ;
row . createCell ( cc + + ) . setCellValue ( coil . getWarehouseName ( ) ! = null ? coil . getWarehouseName ( ) : " " ) ;
row . createCell ( cc + + ) . setCellValue ( coil . getActualWarehouseName ( ) ! = null ? coil . getActualWarehouseName ( ) : " " ) ;
row . createCell ( cc + + ) . setCellValue ( coil . getEnterCoilNo ( ) ! = null ? coil . getEnterCoilNo ( ) : " " ) ;
row . createCell ( cc + + ) . setCellValue ( coil . getSupplierCoilNo ( ) ! = null ? coil . getSupplierCoilNo ( ) : " " ) ;
row . createCell ( cc + + ) . setCellValue ( coil . getCurrentCoilNo ( ) ! = null ? coil . getCurrentCoilNo ( ) : " " ) ;
row . createCell ( cc + + ) . setCellValue ( coil . getCreateTime ( ) ! = null ? sdf . format ( coil . getCreateTime ( ) ) : " " ) ;
row . createCell ( cc + + ) . setCellValue ( coil . getNetWeight ( ) ! = null ? coil . getNetWeight ( ) . toString ( ) : " " ) ;
row . createCell ( cc + + ) . setCellValue ( coil . getBusinessPurpose ( ) ! = null ? coil . getBusinessPurpose ( ) : " " ) ;
row . createCell ( cc + + ) . setCellValue ( coil . getTrimmingRequirement ( ) ! = null ? coil . getTrimmingRequirement ( ) : " " ) ;
row . createCell ( cc + + ) . setCellValue ( coil . getPackagingRequirement ( ) ! = null ? coil . getPackagingRequirement ( ) : " " ) ;
row . createCell ( cc + + ) . setCellValue ( coil . getQualityStatus ( ) ! = null ? coil . getQualityStatus ( ) : " " ) ;
row . createCell ( cc + + ) . setCellValue ( coil . getPackingStatus ( ) ! = null ? coil . getPackingStatus ( ) : " " ) ;
row . createCell ( cc + + ) . setCellValue ( coil . getStatus ( ) ! = null ? coil . getStatus ( ) . toString ( ) : " " ) ;
row . createCell ( cc + + ) . setCellValue ( coil . getRemark ( ) ! = null ? coil . getRemark ( ) : " " ) ;
row . createCell ( cc + + ) . setCellValue ( coil . getItemName ( ) ! = null ? coil . getItemName ( ) : " " ) ;
row . createCell ( cc + + ) . setCellValue ( coil . getSpecification ( ) ! = null ? coil . getSpecification ( ) : " " ) ;
row . createCell ( cc + + ) . setCellValue ( coil . getLength ( ) ! = null ? coil . getLength ( ) . toString ( ) : " " ) ;
row . createCell ( cc + + ) . setCellValue ( coil . getMaterial ( ) ! = null ? coil . getMaterial ( ) : " " ) ;
row . createCell ( cc + + ) . setCellValue ( coil . getManufacturer ( ) ! = null ? coil . getManufacturer ( ) : " " ) ;
row . createCell ( cc + + ) . setCellValue ( coil . getSurfaceTreatmentDesc ( ) ! = null ? coil . getSurfaceTreatmentDesc ( ) : " " ) ;
row . createCell ( cc + + ) . setCellValue ( coil . getZincLayer ( ) ! = null ? coil . getZincLayer ( ) : " " ) ;
row . createCell ( cc + + ) . setCellValue ( coil . getItemId ( ) ! = null ? coil . getItemId ( ) . toString ( ) : " " ) ;
row . createCell ( cc + + ) . setCellValue ( coil . getActionCompleteTime ( ) ! = null ? sdf . format ( coil . getActionCompleteTime ( ) ) : " " ) ;
row . createCell ( cc + + ) . setCellValue ( coil . getTransferType ( ) ! = null ? coil . getTransferType ( ) : " " ) ;
// 改判原因
row . createCell ( cc + + ) . setCellValue ( rejudgeReason ! = null ? rejudgeReason : " " ) ;
// 异常信息
if ( abnormal ! = null ) {
row . createCell ( cc + + ) . setCellValue ( abnormal . getProductionLine ( ) ! = null ? abnormal . getProductionLine ( ) : " " ) ;
row . createCell ( cc + + ) . setCellValue ( abnormal . getPosition ( ) ! = null ? abnormal . getPosition ( ) : " " ) ;
row . createCell ( cc + + ) . setCellValue ( abnormal . getLength ( ) ! = null ? abnormal . getLength ( ) . toString ( ) : " " ) ;
row . createCell ( cc + + ) . setCellValue ( abnormal . getStartPosition ( ) ! = null ? abnormal . getStartPosition ( ) . toString ( ) : " " ) ;
row . createCell ( cc + + ) . setCellValue ( abnormal . getEndPosition ( ) ! = null ? abnormal . getEndPosition ( ) . toString ( ) : " " ) ;
row . createCell ( cc + + ) . setCellValue ( abnormal . getDefectCode ( ) ! = null ? abnormal . getDefectCode ( ) : " " ) ;
row . createCell ( cc + + ) . setCellValue ( abnormal . getDefectType ( ) ! = null ? abnormal . getDefectType ( ) : " " ) ;
row . createCell ( cc + + ) . setCellValue ( abnormal . getDefectRate ( ) ! = null ? abnormal . getDefectRate ( ) . toString ( ) : " " ) ;
row . createCell ( cc + + ) . setCellValue ( abnormal . getDefectWeight ( ) ! = null ? abnormal . getDefectWeight ( ) . toString ( ) : " " ) ;
row . createCell ( cc + + ) . setCellValue ( abnormal . getDegree ( ) ! = null ? abnormal . getDegree ( ) : " " ) ;
row . createCell ( cc + + ) . setCellValue ( abnormal . getJudgeLevel ( ) ! = null ? abnormal . getJudgeLevel ( ) : " " ) ;
row . createCell ( cc + + ) . setCellValue ( abnormal . getJudgeBy ( ) ! = null ? abnormal . getJudgeBy ( ) : " " ) ;
row . createCell ( cc + + ) . setCellValue ( abnormal . getJudgeTime ( ) ! = null ? sdf . format ( abnormal . getJudgeTime ( ) ) : " " ) ;
row . createCell ( cc + + ) . setCellValue ( abnormal . getMainMark ( ) ! = null ? abnormal . getMainMark ( ) . toString ( ) : " " ) ;
row . createCell ( cc + + ) . setCellValue ( abnormal . getWholeCoilMark ( ) ! = null ? abnormal . getWholeCoilMark ( ) . toString ( ) : " " ) ;
row . createCell ( cc + + ) . setCellValue ( abnormal . getRemark ( ) ! = null ? abnormal . getRemark ( ) : " " ) ;
row . createCell ( cc + + ) . setCellValue ( abnormal . getPlateSurface ( ) ! = null ? abnormal . getPlateSurface ( ) : " " ) ;
} else {
for ( int j = 0 ; j < 17 ; j + + ) row . createCell ( cc + + ) . setCellValue ( " " ) ;
}
}
// 合并钢卷信息列( 前26列: 25列钢卷信息 + 1列改判原因)
int currentRow = dataStartRow ;
while ( currentRow < r ) {
Long currentCoilId = exportData . get ( currentRow - dataStartRow ) . getCoil ( ) . getCoilId ( ) ;
int startRow = currentRow ;
int endRow = currentRow ;
while ( endRow < r & & exportData . get ( endRow - dataStartRow ) . getCoil ( ) . getCoilId ( ) . equals ( currentCoilId ) ) {
endRow + + ;
}
if ( endRow - startRow > 1 ) {
for ( int col = 0 ; col < 26 ; col + + ) {
sheet . addMergedRegion ( new CellRangeAddress ( startRow , endRow - 1 , col , col ) ) ;
}
}
// 设置居中样式
for ( int rowIdx = startRow ; rowIdx < endRow ; rowIdx + + ) {
Row row = sheet . getRow ( rowIdx ) ;
if ( row ! = null ) {
for ( int col = 0 ; col < 26 ; col + + ) {
Cell cell = row . getCell ( col ) ;
if ( cell ! = null ) cell . setCellStyle ( centerStyle ) ;
}
}
}
currentRow = endRow ;
}
// 自适应列宽
for ( int i = 0 ; i < headers . length ; i + + ) {
sheet . autoSizeColumn ( i , true ) ;
int w = sheet . getColumnWidth ( i ) ;
sheet . setColumnWidth ( i , Math . min ( Math . max ( w , 3000 ) , 12000 ) ) ;
}
// 输出
String filename = " abnormal_report_ " + System . currentTimeMillis ( ) + " .xlsx " ;
String encoded = URLEncoder . encode ( filename , StandardCharsets . UTF_8 . name ( ) ) ;
response . setCharacterEncoding ( StandardCharsets . UTF_8 . name ( ) ) ;
response . setContentType ( " application/vnd.openxmlformats-officedocument.spreadsheetml.sheet " ) ;
response . setHeader ( " Content-Disposition " , " attachment; filename*=UTF-8'' " + encoded ) ;
try ( ServletOutputStream os = response . getOutputStream ( ) ) {
wb . write ( os ) ;
os . flush ( ) ;
}
} catch ( IOException e ) {
throw new RuntimeException ( " 导出失败: " + e . getMessage ( ) ) ;
}
}
}