From 3c17ff219ff824d66e681fe3ced01430c93934ca Mon Sep 17 00:00:00 2001 From: lihao Date: Fri, 5 Dec 2025 16:40:18 +0800 Subject: [PATCH] =?UTF-8?q?=E9=94=80=E5=94=AE=E5=8F=91=E7=A5=A8=E5=BC=80?= =?UTF-8?q?=E7=A5=A8=E5=8C=B9=E9=85=8D=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../action/SaleInvoiceNumImportAction.java | 273 ++++++++++++++ .../saleincoive/config/action/saleinvoice.xml | 339 ++++++++++++++++++ .../authorize/saleinvoice_authorize.xml | 74 ++++ 3 files changed, 686 insertions(+) create mode 100644 so/src/client/nccloud/web/so/saleorder/action/SaleInvoiceNumImportAction.java create mode 100644 so/src/client/yyconfig/modules/so/saleincoive/config/action/saleinvoice.xml create mode 100644 so/src/client/yyconfig/modules/so/saleincoive/config/authorize/saleinvoice_authorize.xml diff --git a/so/src/client/nccloud/web/so/saleorder/action/SaleInvoiceNumImportAction.java b/so/src/client/nccloud/web/so/saleorder/action/SaleInvoiceNumImportAction.java new file mode 100644 index 00000000..f0570952 --- /dev/null +++ b/so/src/client/nccloud/web/so/saleorder/action/SaleInvoiceNumImportAction.java @@ -0,0 +1,273 @@ +package nccloud.web.so.saleorder.action; + + +import nccloud.commons.lang.ArrayUtils; +import com.yonyou.cloud.utils.StringUtils; +import nc.bs.dao.BaseDAO; +import nc.bs.dao.DAOException; +import nc.bs.logging.Logger; +import nccloud.framework.core.exception.BusinessException; +import nccloud.framework.core.exception.ExceptionUtils; +import nccloud.framework.core.io.WebFile; +import nccloud.framework.core.json.IJson; +import nccloud.framework.web.action.itf.ICommonAction; +import nccloud.framework.web.container.IRequest; +import nccloud.framework.web.container.SessionContext; +import nccloud.framework.web.json.JsonFactory; +import nccloud.web.hrwa.psndocwadoc.vo.ImportHead; +import nccloud.web.hrwa.pub.ErrorContent; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.CellType; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class SaleInvoiceNumImportAction implements ICommonAction { + public SaleInvoiceNumImportAction() { + } + + @Override + public Object doAction(IRequest request) { + WebFile[] webFiles = request.readFiles(); + if (ArrayUtils.isEmpty(webFiles)) { + ExceptionUtils.wrapBusinessException(ErrorContent.FILEUPLOADNULL); + } + + try { + // 导入Excel文件,获取数据列表 + List> dataList = importFormFile( + webFiles[0].getInputStream(), + webFiles[0].getFileName()); + + Map result = new HashMap<>(); + if (dataList == null || dataList.isEmpty()) { + result.put("isSuccess", "N"); + result.put("error", "导入的数据为空"); + } else { + result.put("isSuccess", "Y"); + result.put("data", dataList); // 返回数据列表 + result.put("totalCount", dataList.size()); // 返回总记录数 + } + return result; + + } catch (BusinessException e) { + throw e; + } catch (Exception e) { + Logger.error("导入Excel文件失败", e); + throw new BusinessException("导入失败:" + e.getMessage()); + } + } + + /** + * 导入Excel文件,返回数据列表 + * @param fileInput 文件输入流 + * @param fileName 文件名 + * @return 数据列表,每个Map包含一行数据 + * @throws BusinessException 业务异常 + */ + public List> importFormFile(InputStream fileInput, String fileName) + throws BusinessException { + + List> dataList = new ArrayList<>(); + + try { + if (null == fileInput || StringUtils.isBlank(fileName)) { + throw new BusinessException("文件输入流或文件名为空"); + } + + // 检查文件格式 + if (!fileName.endsWith(".xlsx") && !fileName.endsWith(".xls")) { + throw new BusinessException(ErrorContent.FILETYPEERROR); + } + + Workbook workbook = null; + if (fileName.endsWith(".xlsx")) { + workbook = new XSSFWorkbook(fileInput); + } else if (fileName.endsWith(".xls")) { + workbook = new HSSFWorkbook(fileInput); + } + + if (workbook == null) { + throw new BusinessException("无法创建Workbook对象"); + } + + Sheet sheet = workbook.getSheetAt(0); + if (sheet == null) { + throw new BusinessException("Excel文件中没有工作表"); + } + + // 获取表头行 + Row headerRow = sheet.getRow(0); + if (headerRow == null) { + throw new BusinessException("Excel文件第一行(表头)为空"); + } + + // 验证表头 + validateHeader(headerRow); + + // 从第二行开始读取数据(跳过表头) + for (int rowNum = 1; rowNum <= sheet.getLastRowNum(); rowNum++) { + Row row = sheet.getRow(rowNum); + if (row == null) { + continue; // 跳过空行 + } + + try { + Map rowData = parseRowData(row, rowNum + 1); + if (rowData != null && !rowData.isEmpty()) { + // 添加行号,方便前端定位 + rowData.put("rowNumber", rowNum + 1); + dataList.add(rowData); + } + } catch (Exception e) { + Logger.warn("解析第" + (rowNum + 1) + "行数据失败,跳过此行", e); + // 可以选择继续处理其他行,或者抛出异常停止导入 + continue; + } + } + + workbook.close(); + + return dataList; + + } catch (IOException e) { + Logger.error("读取Excel文件失败", e); + throw new BusinessException("读取Excel文件失败:" + e.getMessage()); + } finally { + if (fileInput != null) { + try { + fileInput.close(); + } catch (IOException e) { + Logger.error("关闭文件流失败", e); + } + } + } + } + + /** + * 验证表头格式 + */ + private void validateHeader(Row headerRow) throws BusinessException { + String[] expectedHeaders = {"物料编码", "含税单价", "匹配数量"}; + + if (headerRow.getLastCellNum() < expectedHeaders.length) { + throw new BusinessException("表头列数不正确,应为" + expectedHeaders.length + "列"); + } + + for (int i = 0; i < expectedHeaders.length; i++) { + Cell cell = headerRow.getCell(i); + if (cell == null) { + throw new BusinessException("第" + (i + 1) + "列表头为空,应为:" + expectedHeaders[i]); + } + + String cellValue = getCellValue(cell).trim(); + if (!expectedHeaders[i].equals(cellValue)) { + throw new BusinessException("第" + (i + 1) + "列表头不正确,应为:" + expectedHeaders[i] + ",实际为:" + cellValue); + } + } + } + + /** + * 解析行数据 + */ + private Map parseRowData(Row row, int rowNumber) { + Map rowData = new HashMap<>(); + + // 检查是否为空行 + boolean isEmptyRow = true; + + // 物料编码 + Cell materialCodeCell = row.getCell(0); + String materialCode = getCellValue(materialCodeCell); + if (StringUtils.isNotBlank(materialCode)) { + rowData.put("materialCode", materialCode.trim()); + isEmptyRow = false; + } else { + rowData.put("materialCode", ""); + } + + // 含税单价 + Cell priceCell = row.getCell(1); + BigDecimal taxPrice = null; + try { + String priceStr = getCellValue(priceCell); + if (StringUtils.isNotBlank(priceStr)) { + taxPrice = new BigDecimal(priceStr.trim()); + rowData.put("taxPrice", taxPrice); + rowData.put("taxPriceStr", priceStr.trim()); // 保留字符串格式 + isEmptyRow = false; + } + } catch (Exception e) { + Logger.warn("第" + rowNumber + "行含税单价格式不正确"); + rowData.put("taxPriceError", "含税单价格式不正确"); + } + + // 匹配数量 + Cell quantityCell = row.getCell(2); + BigDecimal matchQuantity = null; + try { + String quantityStr = getCellValue(quantityCell); + if (StringUtils.isNotBlank(quantityStr)) { + // 如果是整数,直接使用整数 + if (quantityStr.matches("\\d+")) { + matchQuantity = new BigDecimal(quantityStr.trim()); + } else { + matchQuantity = new BigDecimal(quantityStr.trim()); + } + rowData.put("matchQuantity", matchQuantity); + rowData.put("matchQuantityStr", quantityStr.trim()); // 保留字符串格式 + isEmptyRow = false; + } + } catch (Exception e) { + Logger.warn("第" + rowNumber + "行匹配数量格式不正确"); + rowData.put("quantityError", "匹配数量格式不正确"); + } + + // 如果是空行,返回null + return isEmptyRow ? null : rowData; + } + + /** + * 获取单元格的值 + */ + private String getCellValue(Cell cell) { + if (cell == null) { + return ""; + } + + try { + cell.setCellType(CellType.STRING); + return cell.getStringCellValue(); + } catch (Exception e) { + try { + // 尝试获取数值 + double numericValue = cell.getNumericCellValue(); + // 如果是整数,去掉小数部分 + if (numericValue == (long) numericValue) { + return String.valueOf((long) numericValue); + } else { + return String.valueOf(numericValue); + } + } catch (Exception ex) { + // 如果还是失败,尝试布尔值 + try { + boolean booleanValue = cell.getBooleanCellValue(); + return String.valueOf(booleanValue); + } catch (Exception ex2) { + return ""; + } + } + } + } +} \ No newline at end of file diff --git a/so/src/client/yyconfig/modules/so/saleincoive/config/action/saleinvoice.xml b/so/src/client/yyconfig/modules/so/saleincoive/config/action/saleinvoice.xml new file mode 100644 index 00000000..48f00af5 --- /dev/null +++ b/so/src/client/yyconfig/modules/so/saleincoive/config/action/saleinvoice.xml @@ -0,0 +1,339 @@ + + + + so.saleinvoice.coop25 + + nccloud.web.so.saleinvoice.action.SaleInvoiceCoopTo25Action + + + so.saleinvoice.save + + nccloud.web.so.saleinvoice.action.SaveAction + Save + + + so.saleinvoice.rowopr + + nccloud.web.so.saleinvoice.action.SaleInvoiceRowOprAction + + + + + so.saleinvoice.query + + nccloud.web.so.saleinvoice.action.QueryAction + + + + so.saleinvoice.delete + + nccloud.web.so.saleinvoice.action.DeleteAction + Delete + + + so.saleinvoice.griddelete + + nccloud.web.so.saleinvoice.action.GridDeleteAction + Delete + + + so.saleinvoice.commit + + nccloud.web.so.saleinvoice.action.CommitAction + Commit + + + so.saleinvoice.savecommit + + nccloud.web.so.saleinvoice.action.SaveAndCommitAction + SaveCommit + + + so.saleinvoice.uncommit + + nccloud.web.so.saleinvoice.action.UnCommitAction + UnCommit + + + so.saleinvoice.gridcommit + + nccloud.web.so.saleinvoice.action.BatchCommitAction + Commit + + + so.saleinvoice.griduncommit + + nccloud.web.so.saleinvoice.action.BatchUnCommitAction + UnCommit + + + so.saleinvoice.querycard + + nccloud.web.so.saleinvoice.action.CardQueryAction + + + so.saleinvoice.headafter + + nccloud.web.so.saleinvoice.event.HeadAfterEditAction + + + so.saleinvoice.bodyafter + + nccloud.web.so.saleinvoice.event.BodyAfterEditAction + + + so.saleinvoice.bodybefore + + nccloud.web.so.saleinvoice.event.BodyBeforeEditAction + + + so.saleinvoice.headbefore + + nccloud.web.so.saleinvoice.event.HeadBeforeEditAction + + + + so.saleinvoice.fetchcost + + nccloud.web.so.saleinvoice.action.FetchCostAction + FetchCost + + + so.saleinvoice.querypagebypks + + nccloud.web.so.saleinvoice.action.QueryByPKsAction + + + + so.saleinvoice.unitarsub + + nccloud.web.so.saleinvoice.action.UnitArsubAction + Offset + + + so.saleinvoice.cancelunitarsub + + nccloud.web.so.saleinvoice.action.CancelUnitArsubAction + UnOffset + + + so.saleinvoice.showcombine + + nccloud.web.so.saleinvoice.action.ShowCombineAction + ShowCombine + + + so.saleinvoice.showdetail + + nccloud.web.so.saleinvoice.action.ShowDetailAction + ShowDetail + + + so.saleinvoice.arsubdetail + + nccloud.web.so.saleinvoice.action.ArsubDetailQueryAction + + + + so.saleinvoice.creditquery + + nccloud.web.so.saleinvoice.action.CreditQueryAction + CreditQuery + + + so.saleinvoice.gridarsubdetail + + nccloud.web.so.saleinvoice.action.BatchArsubDetailAction + + + + so.saleinvoice.gridcreditquery + + nccloud.web.so.saleinvoice.action.GridCreditQueryAction + CreditQuery + + + so.saleinvoice.query30for32 + + nccloud.web.so.saleinvoice.action.SaleOrderQueryFor32Action + + + + + so.saleinvoice.query4330for32 + + nccloud.web.so.saleinvoice.action.InitoutregQueryFor32Action + + + + + so.saleinvoice.query4cfor32 + + nccloud.web.so.saleinvoice.action.SaleoutQueryFor32Action + + + + so.saleinvoice.queryallfor32 + + nccloud.web.so.saleinvoice.action.QueryAllFor32Action + + + so.saleinvoice.linkqueryallfor32 + + nccloud.web.so.saleinvoice.action.LinkQueryAllFor32Action + + + so.saleinvoice.queryaddtab + + nccloud.web.so.saleinvoice.action.QueryAddTabAction + + + so.saleinvoice.transfer + + nccloud.web.so.saleinvoice.action.TransToSaleInvoiceAction + + + + so.saleinvoice.outrush + + nccloud.web.so.saleinvoice.action.SaleOutRushAction + + + so.saleinvoice.refaddline + + nccloud.web.so.saleinvoice.action.SaleInvoiceRefAddLineAction + + + + + so.saleinvoice.print + + nccloud.web.so.saleinvoice.action.SaleInvoicePrintAction + + Print,Output,Print_list + + + so.saleinvoice.printpermission + + nccloud.web.so.saleinvoice.action.SaleInvoicePrintPermissionAction + + Print,Output,Print_list + + + so.saleinvoice.opposeadd + + nccloud.web.so.saleinvoice.action.SaleInvoiceOpposeAddAction + + OpposeAdd + + + + so.saleinvoice.exportGoldTax + + nccloud.web.so.saleinvoice.action.SaleInvoiceExportGoldTaxAction + + ExportGoldTax + + + so.saleinvoice.translateGoldTax + + nccloud.web.so.saleinvoice.action.SaleInvoiceTranslateGoldTaxAction + + + + so.saleinvoice.importtaxcode + + nccloud.web.so.saleinvoice.action.SaleInvoiceImportTaxCodeAction + + ImportTaxCode + + + so.saleinvoice.querytranstype + + nccloud.web.so.saleinvoice.trantype.M32TransTypeQueryAction + + + + so.saleinvoice.edit + + nccloud.web.so.saleinvoice.action.SaleInvoiceEditAction + Edit + + + so.saleinvoice.linkqueryfromvoucher + + nccloud.web.so.saleinvoice.action.LinkQueryFromVoucherAction + + + + so.saleinvoice.vatsub + + nccloud.web.so.saleinvoice.action.SaleInvoiceVatSubAction + + + + so.saleinvoice.cardvatsub + + nccloud.web.so.saleinvoice.action.SaleInvoiceCardVatSubAction + + + + so.saleinvoice.saleprofit + + nccloud.web.so.saleinvoice.action.SaleInvoiceProfitAction + + CrossProfitRpt + + + so.saleinvoice.saleeditprofit + + nccloud.web.so.saleinvoice.action.SaleInvoiceEditProfitAction + + CrossProfitRpt + + + so.saleinvoice.invoicequeryexec + + nccloud.web.so.saleinvoice.action.SaleInvoiceQueryExecAction + + InvoiceQueryExec + + + so.saleinvoice.issueInvoice + + nccloud.web.so.saleinvoice.action.SaleInvoiceBatchIssueInvAction + + MakeInv_1,MakeInv_4,MakeInv_3,MakeInv_11,MakeInv_10,MakeInv_8,MakeInv_99,MakeInv_31,MakeInv_32 + + + so.saleinvoice.checkissueInvoice + + nccloud.web.so.saleinvoice.action.SaleInvoiceCheckForSSCINV + + + + so.saleinvoice.linkQueryVoucher + + nccloud.web.so.saleinvoice.action.LinkQueryVoucherAction + + LinkQueryVoucher + + + so.saleinvoice.checkSagaStatus + + nccloud.web.so.saleinvoice.action.CheckSagaStatusAction + + + + so.saleinvoice.maintainandLinkInvoice + + nccloud.web.so.saleinvoice.action.MaintainandLinkInvoiceAction + + + + so.saleinvoice.SaleInvoiceNumImport + + nccloud.web.so.saleorder.action.SaleInvoiceNumImportAction + + + diff --git a/so/src/client/yyconfig/modules/so/saleincoive/config/authorize/saleinvoice_authorize.xml b/so/src/client/yyconfig/modules/so/saleincoive/config/authorize/saleinvoice_authorize.xml new file mode 100644 index 00000000..49ddc73a --- /dev/null +++ b/so/src/client/yyconfig/modules/so/saleincoive/config/authorize/saleinvoice_authorize.xml @@ -0,0 +1,74 @@ + + + 400601200,400601202,400601206 + + so.saleinvoice.coop25 + so.saleinvoice.batchcoop25 + so.saleinvoice.query + so.saleinvoice.delete + so.saleinvoice.griddelete + so.saleinvoice.save + so.saleinvoice.commit + so.saleinvoice.uncommit + so.saleinvoice.gridcommit + so.saleinvoice.griduncommit + so.saleinvoice.rowopr + so.saleinvoice.querycard + so.saleinvoice.headafter + so.saleinvoice.bodyafter + so.saleinvoice.bodybefore + so.saleinvoice.headbefore + so.saleinvoice.fetchcost + so.saleinvoice.querypagebypks + so.saleinvoice.unitarsub + + so.saleinvoice.cancelunitarsub + so.saleinvoice.showcombine + so.saleinvoice.showdetail + so.saleinvoice.arsubdetail + so.saleinvoice.creditquery + so.saleinvoice.gridarsubdetail + so.saleinvoice.gridcreditquery + so.saleinvoice.query30for32 + so.saleinvoice.query4330for32 + so.saleinvoice.query4cfor32 + so.saleinvoice.queryallfor32 + so.saleinvoice.linkqueryallfor32 + so.saleinvoice.queryaddtab + so.saleinvoice.transfer + so.saleinvoice.outrush + so.saleinvoice.refaddline + so.saleinvoice.print + so.saleinvoice.printpermission + + so.saleinvoice.opposeadd + so.saleinvoice.exportGoldTax + so.saleinvoice.translateGoldTax + so.saleinvoice.importtaxcode + so.saleinvoice.edit + so.saleinvoice.linkqueryfromvoucher + so.saleinvoice.linkQueryVoucher + + so.saleinvoice.vatsub + so.saleinvoice.cardvatsub + so.saleinvoice.saleprofit + so.saleinvoice.saleeditprofit + so.saleinvoice.invoicequeryexec + so.saleinvoice.issueInvoice + so.saleinvoice.checkissueInvoice + + so.saleinvoice.savecommit + so.saleinvoice.checkSagaStatus + so.saleinvoice.maintainandLinkInvoice + so.saleinvoice.SaleInvoiceNumImport + + + + + * + + so.saleinvoice.querytranstype + + + +