@@ -7,9 +7,11 @@ import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.utils.SecurityUtils ;
import com.ruoyi.common.utils.StringUtils ;
import com.ruoyi.common.utils.file.FileUploadUtils ;
import com.ruoyi.common.exception.ServiceException ;
import com.ruoyi.jarvis.domain.GroupRebateExcelUpload ;
import com.ruoyi.jarvis.domain.JDOrder ;
import com.ruoyi.jarvis.domain.dto.RebateRemarkItem ;
import com.ruoyi.jarvis.mapper.GroupRebateExcelUploadMapper ;
import com.ruoyi.jarvis.mapper.JDOrderMapper ;
import com.ruoyi.jarvis.service.IGroupRebateExcelUploadService ;
import org.apache.poi.ss.usermodel.Cell ;
@@ -38,6 +40,7 @@ import java.util.LinkedHashSet;
import java.util.List ;
import java.util.Locale ;
import java.util.Map ;
import java.util.Objects ;
import java.util.Set ;
import java.util.regex.Pattern ;
@@ -62,6 +65,9 @@ public class GroupRebateExcelImportService {
@Resource
private JDOrderMapper jdOrderMapper ;
@Resource
private GroupRebateExcelUploadMapper groupRebateExcelUploadMapper ;
@Resource
private IGroupRebateExcelUploadService groupRebateExcelUploadService ;
@@ -104,9 +110,10 @@ public class GroupRebateExcelImportService {
}
File diskFile = resolveDiskFile ( webPath ) ;
Long recordId = insertInitialUploadRecord ( originalFilename , webPath , fileSize , title ) ;
Map < String , Object > result ;
try {
result = self . processWorkbookTransactional ( diskFile , title ) ;
result = self . processWorkbookTransactional ( diskFile , title , recordId );
} catch ( Exception e ) {
log . error ( " 后返表导入处理异常 " , e ) ;
result = new HashMap < > ( ) ;
@@ -115,13 +122,136 @@ public class GroupRebateExcelImportService {
result . put ( " documentTitle " , title ) ;
}
result . put ( " savedFilePath " , webPath ) ;
Long recordId = persistUploadRecord ( originalFilename , webPath , fileSize , title , result ) ;
finalizeUploadRecord ( recordId , originalFilename , webPath , fileSize , title , result ) ;
result . put ( " uploadRecordId " , recordId ) ;
return result ;
}
/**
* 批量导入:按顺序逐个调用 {@link #importExcel},在同一请求内由后台依次处理完成。
*
* @param documentTitle 仅当恰好 1 个有效文件时作为文档标题;多文件时忽略,各文件用各自文件名。
*/
public Map < String , Object > importExcelBatch ( MultipartFile [ ] files , String documentTitle ) {
if ( files = = null | | files . length = = 0 ) {
Map < String , Object > empty = new HashMap < > ( ) ;
empty . put ( " success " , false ) ;
empty . put ( " message " , " 请选择文件 " ) ;
return empty ;
}
List < MultipartFile > list = new ArrayList < > ( ) ;
for ( MultipartFile f : files ) {
if ( f ! = null & & ! f . isEmpty ( ) ) {
list . add ( f ) ;
}
}
if ( list . isEmpty ( ) ) {
Map < String , Object > empty = new HashMap < > ( ) ;
empty . put ( " success " , false ) ;
empty . put ( " message " , " 没有有效文件 " ) ;
return empty ;
}
boolean single = list . size ( ) = = 1 ;
String sharedTitle = ( single & & StringUtils . isNotEmpty ( documentTitle ) ) ? documentTitle . trim ( ) : null ;
int ok = 0 ;
int fail = 0 ;
List < Map < String , Object > > failures = new ArrayList < > ( ) ;
for ( MultipartFile file : list ) {
try {
Map < String , Object > r = importExcel ( file , sharedTitle ) ;
if ( Boolean . TRUE . equals ( r . get ( " success " ) ) ) {
ok + + ;
} else {
fail + + ;
addBatchFailureBrief ( failures , file . getOriginalFilename ( ) , r . get ( " message " ) ) ;
}
} catch ( Exception e ) {
log . warn ( " 批量后返表:单文件导入失败 {} " , file . getOriginalFilename ( ) , e ) ;
fail + + ;
addBatchFailureBrief ( failures , file . getOriginalFilename ( ) , e . getMessage ( ) ) ;
}
}
Map < String , Object > out = new HashMap < > ( ) ;
out . put ( " success " , true ) ;
out . put ( " totalFiles " , list . size ( ) ) ;
out . put ( " successCount " , ok ) ;
out . put ( " failCount " , fail ) ;
out . put ( " message " , String . format ( Locale . ROOT ,
" 已处理 %d 个文件:成功 %d, 失败 %d。明细可在「后返上传记录」查看。 " ,
list . size ( ) , ok , fail ) ) ;
if ( ! failures . isEmpty ( ) ) {
out . put ( " failures " , failures ) ;
}
return out ;
}
private static void addBatchFailureBrief ( List < Map < String , Object > > failures , String filename , Object message ) {
if ( failures . size ( ) > = 15 ) {
return ;
}
Map < String , Object > fb = new HashMap < > ( 2 ) ;
fb . put ( " filename " , filename ) ;
fb . put ( " message " , message ! = null ? message . toString ( ) : " " ) ;
failures . add ( fb ) ;
}
/**
* 删除一条上传记录:从订单 rebate_remark_json 中移除本次导入写入的条目,并删除数据库记录与磁盘文件。
*/
public Map < String , Object > deleteUploadRecord ( Long id ) {
if ( id = = null ) {
throw new ServiceException ( " 记录 ID 无效 " ) ;
}
GroupRebateExcelUpload rec = groupRebateExcelUploadService . selectGroupRebateExcelUploadById ( id ) ;
if ( rec = = null ) {
throw new ServiceException ( " 上传记录不存在 " ) ;
}
String filePath = rec . getFilePath ( ) ;
Map < String , Object > data = self . deleteUploadRecordTransactional ( id , rec ) ;
deleteUploadDiskFileIfPresent ( filePath ) ;
return data ;
}
@Transactional ( rollbackFor = Exception . class )
public Map < String , Object > processWorkbook Transactional( File diskFile , String title ) throws Exception {
public Map < String , Object > deleteUploadRecord Transactional( Long id , GroupRebateExcelUpload rec ) {
Set < Long > orderIds = new LinkedHashSet < > ( ) ;
List < Long > fromDetail = parseAffectedOrderIds ( rec . getResultDetailJson ( ) ) ;
if ( fromDetail ! = null ) {
orderIds . addAll ( fromDetail ) ;
}
if ( orderIds . isEmpty ( ) ) {
List < Long > fromJson = jdOrderMapper . selectOrderIdsByRebateRemarkUploadRecordId ( id ) ;
if ( fromJson ! = null ) {
orderIds . addAll ( fromJson ) ;
}
}
int ordersUpdated = 0 ;
for ( Long oid : orderIds ) {
if ( stripRebateRemarkItemsByUploadRecordId ( oid , id ) ) {
ordersUpdated + + ;
}
}
int deleted = groupRebateExcelUploadMapper . deleteGroupRebateExcelUploadById ( id ) ;
if ( deleted = = 0 ) {
throw new ServiceException ( " 删除上传记录失败 " ) ;
}
Map < String , Object > data = new HashMap < > ( ) ;
data . put ( " ordersScanned " , orderIds . size ( ) ) ;
data . put ( " ordersRemarkUpdated " , ordersUpdated ) ;
data . put ( " revertedByUploadRecordId " , id ) ;
if ( orderIds . isEmpty ( ) ) {
data . put ( " message " , " 已删除上传记录;未找到可回滚的订单后返备注(多为本功能上线前的历史导入,请按需手工改订单) " ) ;
} else {
data . put ( " message " , String . format ( Locale . ROOT ,
" 已删除上传记录;已扫描 %d 个订单,从 %d 个订单移除了本次导入对应的后返备注 " ,
orderIds . size ( ) , ordersUpdated ) ) ;
}
return data ;
}
@Transactional ( rollbackFor = Exception . class )
public Map < String , Object > processWorkbookTransactional ( File diskFile , String title , Long uploadRecordId ) throws Exception {
Map < String , Object > result = new HashMap < > ( ) ;
try ( InputStream is = new FileInputStream ( diskFile ) ; Workbook wb = WorkbookFactory . create ( is ) ) {
Sheet sheet = wb . getNumberOfSheets ( ) > 0 ? wb . getSheetAt ( 0 ) : null ;
@@ -155,8 +285,40 @@ public class GroupRebateExcelImportService {
return result ;
}
if ( hm . whetherRebateCol > = 0 ) {
int orderDataRows = 0 ;
boolean anyWhetherFilled = false ;
for ( int r = headerRowIndex + 1 ; r < = sheet . getLastRowNum ( ) ; r + + ) {
Row scanRow = sheet . getRow ( r ) ;
if ( scanRow = = null ) {
continue ;
}
String orderNoScan = normalizeOrderNo ( getCellText ( scanRow , hm . orderCol ) ) ;
if ( orderNoScan . isEmpty ( ) ) {
continue ;
}
orderDataRows + + ;
String w = trimToNull ( getCellText ( scanRow , hm . whetherRebateCol ) ) ;
if ( w ! = null ) {
anyWhetherFilled = true ;
break ;
}
}
if ( orderDataRows > 0 & & ! anyWhetherFilled ) {
result . put ( " success " , false ) ;
result . put ( " message " , " 「是否返现」列全部为空,未写入任何订单,请补全该列后重新上传。 " ) ;
result . put ( " documentTitle " , title ) ;
result . put ( " dataRows " , orderDataRows ) ;
result . put ( " updatedOrders " , 0 ) ;
result . put ( " notFoundOrderNos " , new ArrayList < > ( ) ) ;
result . put ( " errors " , new ArrayList < > ( ) ) ;
return result ;
}
}
int dataRows = 0 ;
int updatedOrders = 0 ;
Set < Long > affectedOrderIds = new LinkedHashSet < > ( ) ;
Set < String > notFound = new LinkedHashSet < > ( ) ;
List < String > errors = new ArrayList < > ( ) ;
@@ -194,7 +356,8 @@ public class GroupRebateExcelImportService {
}
try {
appendRebateRemark ( order , title , whether , amountStr ) ;
appendRebateRemark ( order , title , whether , amountStr , uploadRecordId );
affectedOrderIds . add ( order . getId ( ) ) ;
updatedOrders + + ;
} catch ( Exception e ) {
log . warn ( " 写入后返备注失败 orderNo={} id={} " , orderNo , order . getId ( ) , e ) ;
@@ -208,6 +371,7 @@ public class GroupRebateExcelImportService {
result . put ( " updatedOrders " , updatedOrders ) ;
result . put ( " notFoundOrderNos " , new ArrayList < > ( notFound ) ) ;
result . put ( " errors " , errors ) ;
result . put ( " affectedOrderIds " , new ArrayList < > ( affectedOrderIds ) ) ;
result . put ( " message " , String . format ( Locale . ROOT ,
" 解析完成:有效数据行 %d, 匹配并更新订单 %d, 未找到订单 %d 条 " ,
dataRows , updatedOrders , notFound . size ( ) ) ) ;
@@ -215,18 +379,46 @@ public class GroupRebateExcelImportService {
}
}
private Long persist UploadRecord( String originalFilename , String webPath , long fileSize ,
String title , Map < String , Object > procResult ) {
private Long insertInitial UploadRecord( String originalFilename , String webPath , long fileSize , String title ) {
GroupRebateExcelUpload row = new GroupRebateExcelUpload ( ) ;
row . setOriginalFilename ( originalFilename ) ;
row . setFilePath ( StringUtils . isNotEmpty ( webPath ) ? webPath : " " ) ;
row . setFilePath ( webPath ) ;
row . setFileSize ( fileSize ) ;
row . setDocumentTitle ( title ) ;
row . setImportStatus ( 1 ) ;
row . setDataRows ( 0 ) ;
row . setUpdatedOrders ( 0 ) ;
row . setNotFoundCount ( 0 ) ;
JSONObject d = new JSONObject ( ) ;
d . put ( " message " , " 解析中 " ) ;
d . put ( " documentTitle " , title ) ;
row . setResultDetailJson ( d . toJSONString ( ) ) ;
try {
row . setCreateBy ( SecurityUtils . getUsername ( ) ) ;
} catch ( Exception e ) {
row . setCreateBy ( " " ) ;
}
groupRebateExcelUploadService . saveRecordInNewTransaction ( row ) ;
return row . getId ( ) ;
}
private void finalizeUploadRecord ( Long recordId , String originalFilename , String webPath , long fileSize ,
String title , Map < String , Object > procResult ) {
GroupRebateExcelUpload row = new GroupRebateExcelUpload ( ) ;
row . setId ( recordId ) ;
row . setOriginalFilename ( originalFilename ) ;
row . setFilePath ( StringUtils . isNotEmpty ( webPath ) ? webPath : " " ) ;
row . setFileSize ( fileSize ) ;
row . setDocumentTitle ( title ) ;
applyProcResultToRow ( row , procResult ) ;
try {
groupRebateExcelUploadService . updateRecordInNewTransaction ( row ) ;
} catch ( Exception e ) {
log . error ( " 更新后返上传记录失败 id={} " , recordId , e ) ;
}
}
private void applyProcResultToRow ( GroupRebateExcelUpload row , Map < String , Object > procResult ) {
boolean ok = Boolean . TRUE . equals ( procResult . get ( " success " ) ) ;
row . setImportStatus ( ok ? 2 : 1 ) ;
row . setDataRows ( asInt ( procResult . get ( " dataRows " ) ) ) ;
@@ -247,7 +439,25 @@ public class GroupRebateExcelImportService {
if ( procResult . containsKey ( " savedFilePath " ) ) {
detail . put ( " savedFilePath " , procResult . get ( " savedFilePath " ) ) ;
}
if ( procResult . containsKey ( " affectedOrderIds " ) ) {
detail . put ( " affectedOrderIds " , procResult . get ( " affectedOrderIds " ) ) ;
}
row . setResultDetailJson ( detail . toJSONString ( ) ) ;
}
private Long persistUploadRecord ( String originalFilename , String webPath , long fileSize ,
String title , Map < String , Object > procResult ) {
GroupRebateExcelUpload row = new GroupRebateExcelUpload ( ) ;
row . setOriginalFilename ( originalFilename ) ;
row . setFilePath ( StringUtils . isNotEmpty ( webPath ) ? webPath : " " ) ;
row . setFileSize ( fileSize ) ;
row . setDocumentTitle ( title ) ;
try {
row . setCreateBy ( SecurityUtils . getUsername ( ) ) ;
} catch ( Exception e ) {
row . setCreateBy ( " " ) ;
}
applyProcResultToRow ( row , procResult ) ;
try {
groupRebateExcelUploadService . saveRecordInNewTransaction ( row ) ;
@@ -258,6 +468,69 @@ public class GroupRebateExcelImportService {
}
}
private static List < Long > parseAffectedOrderIds ( String resultDetailJson ) {
if ( StringUtils . isEmpty ( resultDetailJson ) ) {
return null ;
}
try {
JSONObject o = JSON . parseObject ( resultDetailJson ) ;
if ( o = = null | | ! o . containsKey ( " affectedOrderIds " ) ) {
return null ;
}
return o . getList ( " affectedOrderIds " , Long . class ) ;
} catch ( Exception e ) {
return null ;
}
}
private boolean stripRebateRemarkItemsByUploadRecordId ( Long orderId , Long uploadRecordId ) {
JDOrder order = jdOrderMapper . selectJDOrderById ( orderId ) ;
if ( order = = null ) {
return false ;
}
List < RebateRemarkItem > list = new ArrayList < > ( ) ;
String existing = order . getRebateRemarkJson ( ) ;
if ( existing ! = null & & ! existing . trim ( ) . isEmpty ( ) ) {
try {
list . addAll ( JSON . parseArray ( existing , RebateRemarkItem . class ) ) ;
} catch ( Exception e ) {
return false ;
}
}
int before = list . size ( ) ;
list . removeIf ( it - > Objects . equals ( uploadRecordId , it . getUploadRecordId ( ) ) ) ;
if ( list . size ( ) = = before ) {
return false ;
}
boolean hasAbnormal = false ;
for ( RebateRemarkItem it : list ) {
if ( Boolean . TRUE . equals ( it . getAbnormal ( ) ) ) {
hasAbnormal = true ;
break ;
}
}
JDOrder upd = new JDOrder ( ) ;
upd . setId ( order . getId ( ) ) ;
upd . setRebateRemarkJson ( list . isEmpty ( ) ? " [] " : JSON . toJSONString ( list ) ) ;
upd . setRebateRemarkHasAbnormal ( hasAbnormal ? 1 : 0 ) ;
jdOrderMapper . updateJDOrder ( upd ) ;
return true ;
}
private void deleteUploadDiskFileIfPresent ( String webPath ) {
if ( StringUtils . isEmpty ( webPath ) ) {
return ;
}
try {
File f = resolveDiskFile ( webPath ) ;
if ( f . isFile ( ) & & ! f . delete ( ) ) {
log . warn ( " 删除后返上传文件失败: {} " , f . getAbsolutePath ( ) ) ;
}
} catch ( Exception e ) {
log . warn ( " 删除后返上传文件异常 path={} " , webPath , e ) ;
}
}
private static Integer asInt ( Object o ) {
if ( o = = null ) {
return null ;
@@ -299,7 +572,8 @@ public class GroupRebateExcelImportService {
return new File ( RuoYiConfig . getProfile ( ) , sub ) ;
}
private void appendRebateRemark ( JDOrder order , String documentTitle , String whetherRebate , String rebateAmount ) {
private void appendRebateRemark ( JDOrder order , String documentTitle , String whetherRebate , String rebateAmount ,
Long uploadRecordId ) {
List < RebateRemarkItem > list = new ArrayList < > ( ) ;
String existing = order . getRebateRemarkJson ( ) ;
if ( existing ! = null & & ! existing . trim ( ) . isEmpty ( ) ) {
@@ -317,6 +591,7 @@ public class GroupRebateExcelImportService {
item . setRebateAmount ( rebateAmount ) ;
item . setUploadTime ( System . currentTimeMillis ( ) ) ;
item . setAbnormal ( isAbnormalWhetherRebate ( whetherRebate ) ) ;
item . setUploadRecordId ( uploadRecordId ) ;
list . add ( item ) ;
boolean hasAbnormal = false ;