feat(system): 添加电票管理系统功能
- 新增发票记录的增删改查功能 - 实现发票状态管理(未处理、处理失败、已成功) - 集成外部开票系统接口对接 - 添加批量处理发票功能 - 配置发票系统相关参数 - 创建发票管理前后端页面模板 - 实现发票数据与外部系统的同步机制
This commit is contained in:
45
pom.xml
45
pom.xml
@@ -247,7 +247,50 @@
|
||||
<groupId>org.xerial</groupId>
|
||||
<artifactId>sqlite-jdbc</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>com.oracle.database.jdbc</groupId>
|
||||
<artifactId>ojdbc8</artifactId>
|
||||
<version>19.8.0.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.oracle.database.nls</groupId>
|
||||
<artifactId>orai18n</artifactId>
|
||||
<version>19.8.0.0</version>
|
||||
</dependency>
|
||||
<!-- Java 21 必加:解决 JAXB 缺失报错 -->
|
||||
<!-- JAXB API -->
|
||||
<dependency>
|
||||
<groupId>jakarta.xml.bind</groupId>
|
||||
<artifactId>jakarta.xml.bind-api</artifactId>
|
||||
<version>2.3.3</version>
|
||||
</dependency>
|
||||
<!-- JAXB 实现 -->
|
||||
<dependency>
|
||||
<groupId>com.sun.xml.bind</groupId>
|
||||
<artifactId>jaxb-core</artifactId>
|
||||
<version>2.3.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.sun.xml.bind</groupId>
|
||||
<artifactId>jaxb-impl</artifactId>
|
||||
<version>2.3.0</version>
|
||||
</dependency>
|
||||
<!-- 高版本 JDK 必须的激活依赖 -->
|
||||
<dependency>
|
||||
<groupId>jakarta.activation</groupId>
|
||||
<artifactId>jakarta.activation-api</artifactId>
|
||||
<version>1.2.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
||||
BIN
sql/sqlite3.db
BIN
sql/sqlite3.db
Binary file not shown.
@@ -0,0 +1,13 @@
|
||||
package top.lidee.common.constant;
|
||||
|
||||
public class InvoiceConstants {
|
||||
|
||||
/** 未处理 */
|
||||
public static final String UNTREATED = "0";
|
||||
|
||||
/** 已处理 但未成功 Processed but not successful*/
|
||||
public static final String PROCESSED_NOT_SUCCESSFUL = "1";
|
||||
|
||||
/** 已成功 */
|
||||
public static final String SUCCESSFUL = "2";
|
||||
}
|
||||
@@ -0,0 +1,203 @@
|
||||
package top.lidee.project.monitor.job.task;
|
||||
|
||||
/*
|
||||
* 发票引入定时任务
|
||||
* */
|
||||
|
||||
import org.apache.shiro.util.CollectionUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
import top.lidee.common.constant.InvoiceConstants;
|
||||
import top.lidee.project.monitor.job.util.HttpXml;
|
||||
import top.lidee.project.monitor.job.util.InvoiceXmlSy;
|
||||
import top.lidee.project.system.record.domain.GrInvoiceRecord;
|
||||
import top.lidee.project.system.record.mapper.GrInvoiceRecordMapper;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.sql.*;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
import java.util.Date;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* 发票定时任务(更新发票状态)
|
||||
*
|
||||
*/
|
||||
|
||||
@Component("suYuanScheduledTask")
|
||||
public class SuYuanScheduledTask {
|
||||
private static final Logger log = LoggerFactory.getLogger(SuYuanScheduledTask.class);
|
||||
// 数据库连接信息
|
||||
|
||||
@Value("${invoice.url}")
|
||||
private String URL;
|
||||
|
||||
@Value("${invoice.eiInvWebService}")
|
||||
private String eiInvWebServiceUrl;
|
||||
/**
|
||||
* 数据库用户名
|
||||
*/
|
||||
@Value("${invoice.username}")
|
||||
private String USERNAME;
|
||||
/**
|
||||
* 数据库密码
|
||||
*/
|
||||
@Value("${invoice.password}")
|
||||
private String PASSWORD;
|
||||
@Value("${invoice.taxId}")
|
||||
private String taxId;
|
||||
@Value("${invoice.authCode}")
|
||||
private String authCode;
|
||||
@Value("${invoice.updateCode}")
|
||||
private String interfaceCode;
|
||||
private static final String fPath = "C:\\log\\fplog.log";
|
||||
|
||||
@Resource
|
||||
private GrInvoiceRecordMapper grInvoiceRecordMapper;
|
||||
|
||||
public void updateInvoice() {
|
||||
GrInvoiceRecord grInvoiceRecord = new GrInvoiceRecord();
|
||||
grInvoiceRecord.setStatus(InvoiceConstants.UNTREATED);
|
||||
List<GrInvoiceRecord> grInvoiceRecords = grInvoiceRecordMapper.selectGrInvoiceRecordList(grInvoiceRecord);
|
||||
if (CollectionUtils.isEmpty(grInvoiceRecords)) {
|
||||
System.out.println("没有待请求数据");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
|
||||
for (GrInvoiceRecord invoiceRecord : grInvoiceRecords) {
|
||||
String key = invoiceRecord.getDjh();
|
||||
String txtCon = "";
|
||||
List<String> billNos = new ArrayList<>();
|
||||
billNos.add(key);
|
||||
|
||||
System.out.println("溯源 Id:" + billNos);
|
||||
txtCon += "溯源 Id:" + billNos + "\n";
|
||||
//封装 请求报文
|
||||
String xmldata = InvoiceXmlSy.generateDwzsXml(billNos);
|
||||
|
||||
// 组装接口需要的请求报文
|
||||
String payload = HttpXml.bulidSoapXML(interfaceCode, taxId, authCode, xmldata, "eiInterface");
|
||||
System.out.println(payload);
|
||||
boolean hasError = false;
|
||||
try {
|
||||
// 调用接口
|
||||
Map<String, Object> res = HttpXml.webServiceExecute(eiInvWebServiceUrl, payload);
|
||||
System.out.println("接口请求状态:" + res.get("httpStatus"));
|
||||
System.out.println("接口返回的原始报文:" + res.get("data"));
|
||||
txtCon += "接口请求状态:" + res.get("httpStatus") + "\n";
|
||||
txtCon += "接口返回的原始报文:" + res.get("data") + "\n";
|
||||
if (200 == (int) res.get("httpStatus")) {
|
||||
try {
|
||||
// 解析接口返回的报文
|
||||
HashMap<String, String> serviceData = HttpXml.parseResponseXML((String) res.get("data"));
|
||||
System.out.println("业务处理返回代码:" + serviceData.get("returnCode"));
|
||||
System.out.println("业务处理返回提示:" + serviceData.get("returnMessage"));
|
||||
System.out.println("业务处理返回数据:" + serviceData.get("data"));
|
||||
|
||||
txtCon += "业务处理返回代码:" + serviceData.get("returnCode") + "\n";
|
||||
txtCon += "业务处理返回提示:" + serviceData.get("returnMessage") + "\n";
|
||||
txtCon += "业务处理返回数据:" + serviceData.get("data") + "\n";
|
||||
// appendToFile(fPath, txtCon);
|
||||
String invNumber = "1";
|
||||
String xml = serviceData.get("data");
|
||||
Pattern pattern = Pattern.compile("<INV_NUMBER>(.*?)</INV_NUMBER>");
|
||||
Matcher matcher = pattern.matcher(xml);
|
||||
if (matcher.find()) {
|
||||
invNumber = matcher.group(1);
|
||||
}
|
||||
|
||||
// 如果没有被开发票(invNumber 为 1)
|
||||
if (invNumber.equals("1")) {
|
||||
log.error("单据号 " + key + " 还未开票");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (serviceData.get("returnCode").equals("0000")) {
|
||||
//更新数据库
|
||||
Connection conn = null;
|
||||
Statement stmt = null;
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
System.out.println("更新视图开始");
|
||||
// 1. 加载 Oracle JDBC 驱动
|
||||
Class.forName("oracle.jdbc.driver.OracleDriver");
|
||||
// 2. 建立数据库连接
|
||||
conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);
|
||||
// 3. 创建 Statement 对象
|
||||
stmt = conn.createStatement();
|
||||
// 4. 执行查询语句
|
||||
String sql = "update gr_dp_saset_sdhm_v a set a.zxcolumn1 = '" + invNumber + "' where a.sasettleid =" + key;
|
||||
PreparedStatement pstmt = conn.prepareStatement(sql);
|
||||
int rowsA = pstmt.executeUpdate();
|
||||
System.out.println("完成更新视图:" + rowsA);
|
||||
invoiceRecord.setStatus(InvoiceConstants.SUCCESSFUL);
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
|
||||
invoiceRecord.setKpsj(sdf.format(new Date()));
|
||||
invoiceRecord.setInvNumber(invNumber);
|
||||
grInvoiceRecordMapper.updateGrInvoiceRecord(invoiceRecord);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
// 发生错误,标记为已尝试但不需要重试
|
||||
hasError = true;
|
||||
// 6. 关闭资源
|
||||
try {
|
||||
if (rs != null) rs.close();
|
||||
if (stmt != null) stmt.close();
|
||||
if (conn != null) conn.close();
|
||||
} catch (SQLException e11) {
|
||||
e11.printStackTrace();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 业务处理失败,标记为已尝试但不需要重试
|
||||
hasError = true;
|
||||
log.error("业务处理失败:" + serviceData.get("returnMessage"));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("解析报文出错的,保持业务为处理中状态,需要检查原因");
|
||||
e.printStackTrace();
|
||||
hasError = true;
|
||||
}
|
||||
} else {
|
||||
// HTTP 请求状态不是 200,标记为已尝试但不需要重试
|
||||
hasError = true;
|
||||
log.error("HTTP 请求失败,状态码:" + res.get("httpStatus"));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
hasError = true;
|
||||
}
|
||||
|
||||
// 如果发生错误,更新状态为 1(已尝试但不需要重试)
|
||||
if (hasError) {
|
||||
invoiceRecord.setStatus(InvoiceConstants.PROCESSED_NOT_SUCCESSFUL);
|
||||
grInvoiceRecordMapper.updateGrInvoiceRecord(invoiceRecord);
|
||||
log.error("单据号 " + key + " 处理失败,标记为已尝试状态");
|
||||
}
|
||||
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
// 追加写入模式
|
||||
public static void appendToFile(String filePath, String content) throws IOException {
|
||||
try (BufferedWriter writer = new BufferedWriter(new FileWriter(filePath, true))) {
|
||||
writer.newLine(); // 换行后再追加
|
||||
writer.write(content);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,228 @@
|
||||
package top.lidee.project.monitor.job.task;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
import org.springframework.stereotype.Component;
|
||||
import top.lidee.common.constant.InvoiceConstants;
|
||||
import top.lidee.project.monitor.job.util.HttpXml;
|
||||
import top.lidee.project.monitor.job.util.InvoiceXmlGenerator;
|
||||
import top.lidee.project.system.record.domain.GrInvoiceRecord;
|
||||
import top.lidee.project.system.record.mapper.GrInvoiceRecordMapper;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.xml.bind.JAXBException;
|
||||
import java.sql.*;
|
||||
import java.util.*;
|
||||
import java.util.Date;
|
||||
|
||||
|
||||
/**
|
||||
* 发票定时任务
|
||||
*
|
||||
*/
|
||||
@Component("yinEuScheduledTask")
|
||||
public class YinEuScheduledTask {
|
||||
|
||||
@Value("${invoice.url}")
|
||||
private String URL;
|
||||
/**
|
||||
* 数据库用户名
|
||||
*/
|
||||
@Value("${invoice.username}")
|
||||
private String USERNAME;
|
||||
/**
|
||||
* 数据库密码
|
||||
*/
|
||||
@Value("${invoice.password}")
|
||||
private String PASSWORD;
|
||||
@Value("${invoice.taxId}")
|
||||
private String taxId;
|
||||
@Value("${invoice.authCode}")
|
||||
private String authCode;
|
||||
@Value("${invoice.interfaceCode}")
|
||||
private String interfaceCode;
|
||||
@Value("${invoice.iBillInterfaceWebService}")
|
||||
private String iBillInterfaceWebServiceUrl;
|
||||
|
||||
|
||||
@Resource
|
||||
private GrInvoiceRecordMapper grInvoiceRecordMapper;
|
||||
|
||||
// 每隔5秒执行一次
|
||||
public void insertInvoice() {
|
||||
|
||||
System.out.println("单据引入开始执行");
|
||||
//查询是否有待处理数据
|
||||
Connection conn = null;
|
||||
Statement stmt = null;
|
||||
ResultSet rs = null;
|
||||
|
||||
try {
|
||||
// 1. 加载Oracle JDBC驱动
|
||||
Class.forName("oracle.jdbc.driver.OracleDriver");
|
||||
// 2. 建立数据库连接
|
||||
conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);
|
||||
// 3. 创建Statement对象
|
||||
stmt = conn.createStatement();
|
||||
// 4. 执行查询语句
|
||||
String sql = "SELECT g.*,COUNT(*) OVER (PARTITION BY g.SASETTLEID) AS MXS FROM GR_DP_SASET_V g";
|
||||
sql = "SELECT DJH,DJRQ,FPZL,KPLX,GMF_MC,HSBZ,XMMC,GGXH,DW,XMSL,XMDJ,XMJE,SL,ZKJE,CREATE_PERSON_NAME,BZ,SASETTLEID,SASETTLEDTLID,MXS FROM (SELECT t.*,COUNT(*) OVER (PARTITION BY DJH) AS MXS,\n" +
|
||||
"ROW_NUMBER() OVER (PARTITION BY DJH ORDER BY SASETTLEID) AS rn FROM GR_DP_SASET_V t) WHERE rn = 1";
|
||||
rs = stmt.executeQuery(sql);
|
||||
if (!rs.isBeforeFirst()) {
|
||||
System.out.println("警告:查询结果为空,没有待处理的单据数据!");
|
||||
} else {
|
||||
System.out.println("查询成功,开始处理单据数据...");
|
||||
}
|
||||
// 5. 处理查询结果
|
||||
while (rs.next()) {
|
||||
String SASETTLEID = rs.getString("SASETTLEID");
|
||||
// 1. 构造根对象
|
||||
InvoiceXmlGenerator.RequestCommonDjlr request = new InvoiceXmlGenerator.RequestCommonDjlr();
|
||||
|
||||
// 2. 构造发票集合
|
||||
InvoiceXmlGenerator.CommonDjlrFpts fpts = new InvoiceXmlGenerator.CommonDjlrFpts();
|
||||
List<InvoiceXmlGenerator.CommonDjlrFpt> fptList = new ArrayList<>();
|
||||
|
||||
// 3. 构造一张发票头
|
||||
InvoiceXmlGenerator.CommonDjlrFpt fpt = new InvoiceXmlGenerator.CommonDjlrFpt();
|
||||
String djh = rs.getString("DJH");
|
||||
String djrq = rs.getString("DJRQ");
|
||||
String fpzl = rs.getString("FPZL");
|
||||
String gmfMc = rs.getString("GMF_MC");
|
||||
GrInvoiceRecord grInvoiceRecord = new GrInvoiceRecord();
|
||||
grInvoiceRecord.setDjh(djh);
|
||||
grInvoiceRecord.setDjrq(djrq);
|
||||
grInvoiceRecord.setFpzl(fpzl);
|
||||
grInvoiceRecord.setGmfMc(gmfMc);
|
||||
grInvoiceRecord.setCreateTime(new Date());
|
||||
fpt.setDjh(djh);
|
||||
fpt.setDjrq(djrq);
|
||||
fpt.setFpzl(fpzl);
|
||||
fpt.setKplx(rs.getString("KPLX"));
|
||||
fpt.setGmfMc(gmfMc);
|
||||
fpt.setHsbz(rs.getString("HSBZ"));
|
||||
fpt.setKpr("方国旭");
|
||||
fpt.setSkr("方国旭");
|
||||
fpt.setFhr("方国旭");
|
||||
fpt.setBz(rs.getString("BZ"));
|
||||
fpt.setZzbm("ORG001");
|
||||
// fpt.setCreatePersonName(rs.getString("CREATE_PERSON_NAME"));
|
||||
fpt.setCreatePersonName("陈志");
|
||||
|
||||
// 4. 构造明细集合
|
||||
InvoiceXmlGenerator.CommonDjlrXmxxs xmxxs = new InvoiceXmlGenerator.CommonDjlrXmxxs();
|
||||
List<InvoiceXmlGenerator.CommonDjlrXmxx> xmxxList = new ArrayList<>();
|
||||
if (rs.getString("MXS").toString().equals("1")) {
|
||||
System.out.println("查询明细数据:1条");
|
||||
InvoiceXmlGenerator.CommonDjlrXmxx xm1 = new InvoiceXmlGenerator.CommonDjlrXmxx();
|
||||
xm1.setXh("1");
|
||||
xm1.setXmmc(rs.getString("XMMC"));
|
||||
xm1.setGgxh(rs.getString("GGXH"));
|
||||
xm1.setDw(rs.getString("DW"));
|
||||
xm1.setXmsl(rs.getString("XMSL"));
|
||||
xm1.setXmje(rs.getString("XMJE"));
|
||||
xm1.setSl(rs.getString("SL"));
|
||||
xm1.setZkje(rs.getString("ZKJE"));
|
||||
xmxxList.add(xm1);
|
||||
|
||||
} else {
|
||||
//多条明细
|
||||
ResultSet rsmx = null;
|
||||
String sqlmx = "SELECT * FROM GR_DP_SASET_V where SASETTLEID=" + rs.getString("SASETTLEID");
|
||||
rsmx = stmt.executeQuery(sqlmx);
|
||||
System.out.println("查询明细数据:" + rsmx.getFetchSize() + "条");
|
||||
int i = 1;
|
||||
while (rsmx.next()) {
|
||||
InvoiceXmlGenerator.CommonDjlrXmxx xm1 = new InvoiceXmlGenerator.CommonDjlrXmxx();
|
||||
xm1.setXh(i + "");
|
||||
xm1.setXmmc(rsmx.getString("XMMC"));
|
||||
xm1.setGgxh(rsmx.getString("GGXH"));
|
||||
xm1.setDw(rsmx.getString("DW"));
|
||||
xm1.setXmsl(rsmx.getString("XMSL"));
|
||||
xm1.setXmje(rsmx.getString("XMJE"));
|
||||
xm1.setSl(rsmx.getString("SL"));
|
||||
xm1.setZkje(rsmx.getString("ZKJE"));
|
||||
xmxxList.add(xm1);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
xmxxs.setCommonDjlrXmxxList(xmxxList);
|
||||
fpt.setCommonDjlrXmxxs(xmxxs);
|
||||
|
||||
fptList.add(fpt);
|
||||
fpts.setCommonDjlrFptList(fptList);
|
||||
request.setCommonDjlrFpts(fpts);
|
||||
|
||||
// 5. 生成 XML 字符串
|
||||
String xmldata = InvoiceXmlGenerator.generateXml(request).replace("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>", "");
|
||||
//封装 请求报文
|
||||
// 组装接口需要的请求报文
|
||||
String payload = HttpXml.bulidSoapXML(interfaceCode, taxId, authCode, xmldata, "impSoHeaderInterface");
|
||||
|
||||
try {
|
||||
// 调用接口
|
||||
Map<String, Object> res = HttpXml.webServiceExecute(iBillInterfaceWebServiceUrl, payload);
|
||||
System.out.println("接口请求状态:" + res.get("httpStatus"));
|
||||
System.out.println("接口返回的原始报文:" + res.get("data"));
|
||||
if (200 == (int) res.get("httpStatus")) {
|
||||
try {
|
||||
// 解析接口返回的报文
|
||||
// HashMap<String, String> serviceData= parseResponseXML((String) res.get("data"));
|
||||
// System.out.println("业务处理返回代码:"+serviceData.get("returnCode"));
|
||||
// System.out.println("业务处理返回提示:"+serviceData.get("returnMessage"));
|
||||
// System.out.println("业务处理返回数据:"+serviceData.get("data"));
|
||||
if (res.get("data").toString().contains("returnCode>0000</returnCode>")) {
|
||||
//更新视图
|
||||
System.out.println("更新视图");
|
||||
String sqlupdate = "update GR_DP_SASET_V a set a.zxcolumn2 = '1' where a.sasettleid =" + SASETTLEID;
|
||||
PreparedStatement pstmt = conn.prepareStatement(sqlupdate);
|
||||
pstmt.execute();
|
||||
System.out.println("完成更新视图");
|
||||
grInvoiceRecord.setStatus(InvoiceConstants.UNTREATED);
|
||||
grInvoiceRecord.setCreateTime(new Date());
|
||||
grInvoiceRecordMapper.insertGrInvoiceRecord(grInvoiceRecord);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
System.out.println("解析报文出错的,保持业务为处理中状态,需要检查原因");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
System.out.println("数据库操作失败");
|
||||
}
|
||||
System.out.println(xmldata);
|
||||
}
|
||||
|
||||
} catch (ClassNotFoundException e) {
|
||||
System.out.println("Oracle JDBC驱动未找到!");
|
||||
e.printStackTrace();
|
||||
} catch (SQLException | JAXBException e) {
|
||||
System.out.println("数据库访问异常!");
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
// 6. 关闭资源
|
||||
try {
|
||||
if (rs != null) rs.close();
|
||||
if (stmt != null) stmt.close();
|
||||
if (conn != null) conn.close();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
// // 1. XML构造根对象
|
||||
// InvoiceXmlGenerator.RequestCommonDjlr request = new InvoiceXmlGenerator.RequestCommonDjlr();
|
||||
//
|
||||
// // 2. 构造发票集合
|
||||
// InvoiceXmlGenerator.CommonDjlrFpts fpts = new InvoiceXmlGenerator.CommonDjlrFpts();
|
||||
// List<InvoiceXmlGenerator.CommonDjlrFpt> fptList = new ArrayList<>();
|
||||
|
||||
|
||||
System.out.println("定时任务完成");
|
||||
}
|
||||
|
||||
}
|
||||
140
src/main/java/top/lidee/project/monitor/job/util/HttpXml.java
Normal file
140
src/main/java/top/lidee/project/monitor/job/util/HttpXml.java
Normal file
@@ -0,0 +1,140 @@
|
||||
package top.lidee.project.monitor.job.util;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Base64;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
public class HttpXml {
|
||||
|
||||
/*
|
||||
* 数据请求
|
||||
* @param requesturl 请求地址
|
||||
* @param soapXML 请求报文
|
||||
* */
|
||||
public static Map<String, Object> webServiceExecute(String requesturl, String soapXML) throws Exception {
|
||||
HttpURLConnection conn = null;
|
||||
OutputStream os = null;
|
||||
Map<String, Object> reslut = new HashMap<>();
|
||||
try {
|
||||
//1创建连接
|
||||
URL url = new URL(requesturl);
|
||||
conn = (HttpURLConnection) url.openConnection();
|
||||
//2设置连接的配置
|
||||
conn.setRequestMethod("POST");
|
||||
conn.setRequestProperty("content-type", "text/xml;charset=utf-8");
|
||||
conn.setDoInput(true);
|
||||
conn.setDoOutput(true);
|
||||
//3打开连接发送数据
|
||||
os = conn.getOutputStream();
|
||||
os.write(soapXML.getBytes());
|
||||
|
||||
String temp = null;
|
||||
//4接收服务端的响应
|
||||
//4.1http的响应码
|
||||
int responseCode = conn.getResponseCode();
|
||||
//4.2获取返回报文
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8));
|
||||
StringBuilder response = new StringBuilder();
|
||||
String responseLine;
|
||||
while ((responseLine = br.readLine()) != null) {
|
||||
response.append(responseLine.trim());
|
||||
}
|
||||
//简单模拟封装返回结果
|
||||
reslut.put("httpStatus", responseCode);
|
||||
reslut.put("data", response.toString());
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("调用"+requesturl+"webservice出错!", e);
|
||||
} finally {
|
||||
if (conn != null) {
|
||||
conn.disconnect();
|
||||
}
|
||||
}
|
||||
return reslut;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建Soap请求报文
|
||||
* @param interfaceCode 接口编码
|
||||
* @param taxId 税号
|
||||
* @param authCode 授权码
|
||||
* @param content 内层业务报文的明文
|
||||
*/
|
||||
public static String bulidSoapXML(String interfaceCode, String taxId, String authCode, String content, String ffmc) {
|
||||
//数据报文通过base64编码
|
||||
String payload = Base64.getEncoder().encodeToString(content.getBytes(StandardCharsets.UTF_8));
|
||||
return "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:ws=\"http://ws.aisino.com\">\n" +
|
||||
"<soapenv:Header/>\n" +
|
||||
"<soapenv:Body>\n" +
|
||||
"<ws:"+ffmc+">\n" +
|
||||
"\t<ws:in0><![CDATA[<?xml version=\"1.0\" encoding=\"utf-8\"?> <interface xmlns=\"\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"> \t\n" +
|
||||
"\t<globalInfo> \t\t\n" +
|
||||
"\t\t<version>1.0</version> \t\t\n" +
|
||||
"\t\t<taxpayerId>" + taxId + "</taxpayerId> \t\t\n" +
|
||||
"\t\t<interfaceCode>" + interfaceCode + "</interfaceCode> \t\t\n" +
|
||||
"\t\t<authorizationCode>" + authCode + "</authorizationCode> \t\n" +
|
||||
"\t</globalInfo> \t\n" +
|
||||
"\t\t<returnStateInfo> \t\t\n" +
|
||||
"\t\t<returnCode>0000</returnCode> \t\t\n" +
|
||||
"\t\t<returnMessage></returnMessage> \t\n" +
|
||||
"\t</returnStateInfo> \t\n" +
|
||||
"\t<Data> \t\t\n" +
|
||||
"\t\t<dataDescription> \t\t\t\n" +
|
||||
"\t\t\t<zipCode>0</zipCode> \t\t\t\n" +
|
||||
"\t\t\t<encryptCode>0</encryptCode> \t\t\t\n" +
|
||||
"\t\t\t<codeType>0</codeType> \t\t\n" +
|
||||
"\t\t</dataDescription> \t\t\n" +
|
||||
"\t\t<content>" + payload + "</content>\t\n" +
|
||||
"\t</Data>\n" +
|
||||
"\t</interface>]]>\n" +
|
||||
"\t</ws:in0>\n" +
|
||||
|
||||
"</ws:"+ffmc+">\n" +
|
||||
"</soapenv:Body>\n" +
|
||||
"</soapenv:Envelope>";
|
||||
}
|
||||
|
||||
public static HashMap<String, String> parseResponseXML(String resData){
|
||||
try {
|
||||
// 获取DocumentBuilderFactory实例
|
||||
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||
// 配置安全选项防止XXE攻击
|
||||
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
|
||||
// 创建DocumentBuilder
|
||||
DocumentBuilder builder = factory.newDocumentBuilder();
|
||||
// 解析XML文件
|
||||
Document document = builder.parse(new ByteArrayInputStream(resData.getBytes(StandardCharsets.UTF_8)));
|
||||
// 获取根元素
|
||||
Element root = document.getDocumentElement();
|
||||
// 获取out节点
|
||||
Node out = root.getFirstChild().getFirstChild().getFirstChild();
|
||||
Document outXML = builder.parse(new ByteArrayInputStream(out.getTextContent().getBytes(StandardCharsets.UTF_8)));
|
||||
// 解析返回的业务处理结果
|
||||
String returnCode = outXML.getElementsByTagName("returnCode").item(0).getTextContent();
|
||||
String returnMessage = outXML.getElementsByTagName("returnMessage").item(0).getTextContent();
|
||||
String data = outXML.getElementsByTagName("content").item(0).getTextContent();
|
||||
HashMap<String, String> resMap = new HashMap<>();
|
||||
resMap.put("returnCode", returnCode);
|
||||
resMap.put("returnMessage", new String(Base64.getDecoder().decode(returnMessage)));
|
||||
resMap.put("data", new String(Base64.getDecoder().decode(data)));
|
||||
return resMap;
|
||||
}catch (Exception e){
|
||||
throw new RuntimeException("解析返回报文报错",e);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
package top.lidee.project.monitor.job.util;
|
||||
|
||||
|
||||
import javax.xml.bind.JAXBContext;
|
||||
import javax.xml.bind.JAXBException;
|
||||
import javax.xml.bind.Marshaller;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import javax.xml.bind.annotation.XmlType;
|
||||
import java.io.StringWriter;
|
||||
import java.util.List;
|
||||
|
||||
public class InvoiceXmlGenerator {
|
||||
|
||||
// ========== XML 映射类 ==========
|
||||
@XmlRootElement(name = "REQUEST_COMMON_DJLR")
|
||||
@XmlType(propOrder = {"commonDjlrFpts"})
|
||||
public static class RequestCommonDjlr {
|
||||
private CommonDjlrFpts commonDjlrFpts;
|
||||
@XmlElement(name = "COMMON_DJLR_FPTS")
|
||||
public CommonDjlrFpts getCommonDjlrFpts() { return commonDjlrFpts; }
|
||||
public void setCommonDjlrFpts(CommonDjlrFpts commonDjlrFpts) { this.commonDjlrFpts = commonDjlrFpts; }
|
||||
}
|
||||
|
||||
@XmlType(propOrder = {"commonDjlrFptList"})
|
||||
public static class CommonDjlrFpts {
|
||||
private List<CommonDjlrFpt> commonDjlrFptList;
|
||||
@XmlElement(name = "COMMON_DJLR_FPT")
|
||||
public List<CommonDjlrFpt> getCommonDjlrFptList() { return commonDjlrFptList; }
|
||||
public void setCommonDjlrFptList(List<CommonDjlrFpt> commonDjlrFptList) { this.commonDjlrFptList = commonDjlrFptList; }
|
||||
}
|
||||
|
||||
@XmlType(propOrder = {"djh", "djrq", "fpzl", "kplx", "gmfMc", "hsbz", "kpr", "skr", "fhr", "bz", "zzbm", "createPersonName", "commonDjlrXmxxs"})
|
||||
public static class CommonDjlrFpt {
|
||||
private String djh, djrq, fpzl, kplx, gmfMc, hsbz, kpr, skr, fhr, bz, zzbm, createPersonName;
|
||||
private CommonDjlrXmxxs commonDjlrXmxxs;
|
||||
// getter/setter (均使用 @XmlElement 指定标签名)
|
||||
@XmlElement(name = "DJH") public String getDjh() { return djh; } public void setDjh(String djh) { this.djh = djh; }
|
||||
@XmlElement(name = "DJRQ") public String getDjrq() { return djrq; } public void setDjrq(String djrq) { this.djrq = djrq; }
|
||||
@XmlElement(name = "FPZL") public String getFpzl() { return fpzl; } public void setFpzl(String fpzl) { this.fpzl = fpzl; }
|
||||
@XmlElement(name = "KPLX") public String getKplx() { return kplx; } public void setKplx(String kplx) { this.kplx = kplx; }
|
||||
@XmlElement(name = "GMF_MC") public String getGmfMc() { return gmfMc; } public void setGmfMc(String gmfMc) { this.gmfMc = gmfMc; }
|
||||
@XmlElement(name = "HSBZ") public String getHsbz() { return hsbz; } public void setHsbz(String hsbz) { this.hsbz = hsbz; }
|
||||
@XmlElement(name = "KPR") public String getKpr() { return kpr; } public void setKpr(String kpr) { this.kpr = kpr; }
|
||||
@XmlElement(name = "SKR") public String getSkr() { return skr; } public void setSkr(String skr) { this.skr = skr; }
|
||||
@XmlElement(name = "FHR") public String getFhr() { return fhr; } public void setFhr(String fhr) { this.fhr = fhr; }
|
||||
@XmlElement(name = "BZ") public String getBz() { return bz; } public void setBz(String bz) { this.bz = bz; }
|
||||
@XmlElement(name = "ZZBM") public String getZzbm() { return zzbm; } public void setZzbm(String zzbm) { this.zzbm = zzbm; }
|
||||
@XmlElement(name = "CREATE_PERSON_NAME") public String getCreatePersonName() { return createPersonName; } public void setCreatePersonName(String createPersonName) { this.createPersonName = createPersonName; }
|
||||
@XmlElement(name = "COMMON_DJLR_XMXXS") public CommonDjlrXmxxs getCommonDjlrXmxxs() { return commonDjlrXmxxs; } public void setCommonDjlrXmxxs(CommonDjlrXmxxs commonDjlrXmxxs) { this.commonDjlrXmxxs = commonDjlrXmxxs; }
|
||||
}
|
||||
|
||||
@XmlType(propOrder = {"commonDjlrXmxxList"})
|
||||
public static class CommonDjlrXmxxs {
|
||||
private List<CommonDjlrXmxx> commonDjlrXmxxList;
|
||||
@XmlElement(name = "COMMON_DJLR_XMXX")
|
||||
public List<CommonDjlrXmxx> getCommonDjlrXmxxList() { return commonDjlrXmxxList; }
|
||||
public void setCommonDjlrXmxxList(List<CommonDjlrXmxx> commonDjlrXmxxList) { this.commonDjlrXmxxList = commonDjlrXmxxList; }
|
||||
}
|
||||
|
||||
@XmlType(propOrder = {"xh", "xmmc", "ggxh", "dw", "xmsl", "xmje", "sl", "zkje"})
|
||||
public static class CommonDjlrXmxx {
|
||||
private String xh, xmmc, ggxh, dw, xmsl, xmje, sl, zkje;
|
||||
@XmlElement(name = "XH") public String getXh() { return xh; } public void setXh(String xh) { this.xh = xh; }
|
||||
@XmlElement(name = "XMMC") public String getXmmc() { return xmmc; } public void setXmmc(String xmmc) { this.xmmc = xmmc; }
|
||||
@XmlElement(name = "GGXH") public String getGgxh() { return ggxh; } public void setGgxh(String ggxh) { this.ggxh = ggxh; }
|
||||
@XmlElement(name = "DW") public String getDw() { return dw; } public void setDw(String dw) { this.dw = dw; }
|
||||
@XmlElement(name = "XMSL") public String getXmsl() { return xmsl; } public void setXmsl(String xmsl) { this.xmsl = xmsl; }
|
||||
@XmlElement(name = "XMJE") public String getXmje() { return xmje; } public void setXmje(String xmje) { this.xmje = xmje; }
|
||||
@XmlElement(name = "SL") public String getSl() { return sl; } public void setSl(String sl) { this.sl = sl; }
|
||||
@XmlElement(name = "ZKJE") public String getZkje() { return zkje; } public void setZkje(String zkje) { this.zkje = zkje; }
|
||||
}
|
||||
|
||||
// ========== 生成 XML 字符串的方法 ==========
|
||||
public static String generateXml(RequestCommonDjlr request) throws JAXBException {
|
||||
JAXBContext context = JAXBContext.newInstance(RequestCommonDjlr.class);
|
||||
Marshaller marshaller = context.createMarshaller();
|
||||
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
|
||||
marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
|
||||
|
||||
StringWriter sw = new StringWriter();
|
||||
marshaller.marshal(request, sw);
|
||||
return sw.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package top.lidee.project.monitor.job.util;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.transform.OutputKeys;
|
||||
import javax.xml.transform.Transformer;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.transform.TransformerFactory;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
import java.io.StringWriter;
|
||||
import java.util.List;
|
||||
|
||||
public class InvoiceXmlSy {
|
||||
|
||||
/**
|
||||
* 生成 XML 字符串
|
||||
* @param billNoList 单据号列表,每个元素将生成一个 <BILLNO> 节点
|
||||
* @return 格式化的 XML 字符串(不含 XML 声明)
|
||||
* @throws ParserConfigurationException XML 解析器配置异常
|
||||
* @throws TransformerException XML 转换异常
|
||||
*/
|
||||
public static String generateDwzsXml(List<String> billNoList) throws ParserConfigurationException, TransformerException {
|
||||
// 1. 创建 Document 对象
|
||||
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||
DocumentBuilder builder = factory.newDocumentBuilder();
|
||||
Document doc = builder.newDocument();
|
||||
|
||||
// 2. 创建根元素 REQUEST_COMMON_DWZS,并设置 class 属性
|
||||
Element root = doc.createElement("REQUEST_COMMON_DWZS");
|
||||
root.setAttribute("class", "REQUEST_COMMON_DWZS");
|
||||
doc.appendChild(root);
|
||||
|
||||
// 3. 创建 COMMON_DWZS_HEADERS 元素
|
||||
Element headers = doc.createElement("COMMON_DWZS_HEADERS");
|
||||
root.appendChild(headers);
|
||||
|
||||
// 4. 遍历单据号列表,为每个单据号创建一个 COMMON_DWZS_HEADER
|
||||
for (String billNo : billNoList) {
|
||||
Element header = doc.createElement("COMMON_DWZS_HEADER");
|
||||
header.setAttribute("class", "COMMON_DWZS_HEADER");
|
||||
headers.appendChild(header);
|
||||
|
||||
Element billNoElem = doc.createElement("BILLNO");
|
||||
// 如果单据号为 null,则设为空字符串,避免 null 值导致异常
|
||||
billNoElem.setTextContent(billNo != null ? billNo : "");
|
||||
header.appendChild(billNoElem);
|
||||
}
|
||||
|
||||
// 5. 将 Document 对象转换为格式化的 XML 字符串
|
||||
TransformerFactory tf = TransformerFactory.newInstance();
|
||||
Transformer transformer = tf.newTransformer();
|
||||
|
||||
// 设置输出属性:省略 XML 声明,启用缩进(4空格)
|
||||
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
|
||||
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
|
||||
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
|
||||
|
||||
StringWriter writer = new StringWriter();
|
||||
transformer.transform(new DOMSource(doc), new StreamResult(writer));
|
||||
return writer.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
package top.lidee.project.system.record.controller;
|
||||
|
||||
import java.util.List;
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import top.lidee.framework.aspectj.lang.annotation.Log;
|
||||
import top.lidee.framework.aspectj.lang.enums.BusinessType;
|
||||
import top.lidee.framework.web.controller.BaseController;
|
||||
import top.lidee.framework.web.domain.AjaxResult;
|
||||
import top.lidee.common.utils.poi.ExcelUtil;
|
||||
import top.lidee.framework.web.page.TableDataInfo;
|
||||
import top.lidee.project.system.record.domain.GrInvoiceRecord;
|
||||
import top.lidee.project.system.record.service.IGrInvoiceRecordService;
|
||||
|
||||
/**
|
||||
* 发票Controller
|
||||
*
|
||||
* @author yuheng
|
||||
* @date 2026-04-02
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/system/record")
|
||||
public class GrInvoiceRecordController extends BaseController
|
||||
{
|
||||
private String prefix = "system/record";
|
||||
|
||||
@Autowired
|
||||
private IGrInvoiceRecordService grInvoiceRecordService;
|
||||
|
||||
@RequiresPermissions("system:record:view")
|
||||
@GetMapping()
|
||||
public String record()
|
||||
{
|
||||
return prefix + "/record";
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询发票列表
|
||||
*/
|
||||
@RequiresPermissions("system:record:list")
|
||||
@PostMapping("/list")
|
||||
@ResponseBody
|
||||
public TableDataInfo list(GrInvoiceRecord grInvoiceRecord)
|
||||
{
|
||||
startPage();
|
||||
List<GrInvoiceRecord> list = grInvoiceRecordService.selectGrInvoiceRecordList(grInvoiceRecord);
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出发票列表
|
||||
*/
|
||||
@RequiresPermissions("system:record:export")
|
||||
@Log(title = "发票", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/export")
|
||||
@ResponseBody
|
||||
public AjaxResult export(GrInvoiceRecord grInvoiceRecord)
|
||||
{
|
||||
List<GrInvoiceRecord> list = grInvoiceRecordService.selectGrInvoiceRecordList(grInvoiceRecord);
|
||||
ExcelUtil<GrInvoiceRecord> util = new ExcelUtil<GrInvoiceRecord>(GrInvoiceRecord.class);
|
||||
return util.exportExcel(list, "发票数据");
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增发票
|
||||
*/
|
||||
@GetMapping("/add")
|
||||
public String add()
|
||||
{
|
||||
return prefix + "/add";
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增保存发票
|
||||
*/
|
||||
@RequiresPermissions("system:record:add")
|
||||
@Log(title = "发票", businessType = BusinessType.INSERT)
|
||||
@PostMapping("/add")
|
||||
@ResponseBody
|
||||
public AjaxResult addSave(GrInvoiceRecord grInvoiceRecord)
|
||||
{
|
||||
return toAjax(grInvoiceRecordService.insertGrInvoiceRecord(grInvoiceRecord));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改发票
|
||||
*/
|
||||
@RequiresPermissions("system:record:edit")
|
||||
@GetMapping("/edit/{id}")
|
||||
public String edit(@PathVariable("id") String id, ModelMap mmap)
|
||||
{
|
||||
GrInvoiceRecord grInvoiceRecord = grInvoiceRecordService.selectGrInvoiceRecordById(id);
|
||||
mmap.put("grInvoiceRecord", grInvoiceRecord);
|
||||
return prefix + "/edit";
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改保存发票
|
||||
*/
|
||||
@RequiresPermissions("system:record:edit")
|
||||
@Log(title = "发票", businessType = BusinessType.UPDATE)
|
||||
@PostMapping("/edit")
|
||||
@ResponseBody
|
||||
public AjaxResult editSave(GrInvoiceRecord grInvoiceRecord)
|
||||
{
|
||||
return toAjax(grInvoiceRecordService.updateGrInvoiceRecord(grInvoiceRecord));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除发票
|
||||
*/
|
||||
@RequiresPermissions("system:record:remove")
|
||||
@Log(title = "发票", businessType = BusinessType.DELETE)
|
||||
@PostMapping( "/remove")
|
||||
@ResponseBody
|
||||
public AjaxResult remove(String ids)
|
||||
{
|
||||
return toAjax(grInvoiceRecordService.deleteGrInvoiceRecordByIds(ids));
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量处理发票
|
||||
*/
|
||||
@RequiresPermissions("system:record:list")
|
||||
@Log(title = "发票", businessType = BusinessType.UPDATE)
|
||||
@PostMapping("/batchProcess")
|
||||
@ResponseBody
|
||||
public AjaxResult batchProcess(@RequestParam List<String> idList)
|
||||
{
|
||||
return toAjax(grInvoiceRecordService.batchProcess(idList));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package top.lidee.project.system.record.domain;
|
||||
|
||||
import lombok.Data;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
import top.lidee.framework.aspectj.lang.annotation.Excel;
|
||||
import top.lidee.framework.web.domain.BaseEntity;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 发票对象 gr_invoice_record
|
||||
*
|
||||
* @author yuheng
|
||||
* @date 2026-04-02
|
||||
*/
|
||||
@Data
|
||||
public class GrInvoiceRecord extends BaseEntity {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** */
|
||||
private Long id;
|
||||
|
||||
/**单据号*/
|
||||
@Excel(name = "")
|
||||
private String djh;
|
||||
|
||||
/**单据日期*/
|
||||
@Excel(name = "")
|
||||
private String djrq;
|
||||
|
||||
/**发票种类*/
|
||||
@Excel(name = "")
|
||||
private String fpzl;
|
||||
|
||||
/**开票时间*/
|
||||
@Excel(name = "")
|
||||
private String kpsj;
|
||||
|
||||
/**开票状态*/
|
||||
@Excel(name = "")
|
||||
private String status;
|
||||
|
||||
private List<String> statusList;
|
||||
/**客户名称*/
|
||||
private String gmfMc;
|
||||
|
||||
private String invNumber;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package top.lidee.project.system.record.mapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import top.lidee.project.system.record.domain.GrInvoiceRecord;
|
||||
|
||||
/**
|
||||
* 发票Mapper接口
|
||||
*
|
||||
* @author yuheng
|
||||
* @date 2026-04-02
|
||||
*/
|
||||
public interface GrInvoiceRecordMapper
|
||||
{
|
||||
/**
|
||||
* 查询发票
|
||||
*
|
||||
* @param id 发票主键
|
||||
* @return 发票
|
||||
*/
|
||||
public GrInvoiceRecord selectGrInvoiceRecordById(String id);
|
||||
|
||||
/**
|
||||
* 查询发票列表
|
||||
*
|
||||
* @param grInvoiceRecord 发票
|
||||
* @return 发票集合
|
||||
*/
|
||||
public List<GrInvoiceRecord> selectGrInvoiceRecordList(GrInvoiceRecord grInvoiceRecord);
|
||||
|
||||
/**
|
||||
* 新增发票
|
||||
*
|
||||
* @param grInvoiceRecord 发票
|
||||
* @return 结果
|
||||
*/
|
||||
public int insertGrInvoiceRecord(GrInvoiceRecord grInvoiceRecord);
|
||||
|
||||
/**
|
||||
* 修改发票
|
||||
*
|
||||
* @param grInvoiceRecord 发票
|
||||
* @return 结果
|
||||
*/
|
||||
public int updateGrInvoiceRecord(GrInvoiceRecord grInvoiceRecord);
|
||||
|
||||
/**
|
||||
* 删除发票
|
||||
*
|
||||
* @param id 发票主键
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteGrInvoiceRecordById(String id);
|
||||
|
||||
/**
|
||||
* 批量删除发票
|
||||
*
|
||||
* @param ids 需要删除的数据主键集合
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteGrInvoiceRecordByIds(String[] ids);
|
||||
|
||||
List<GrInvoiceRecord> selectGrInvoiceRecordListByIdList(@Param("list") List<String> idList);
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package top.lidee.project.system.record.service;
|
||||
|
||||
import java.util.List;
|
||||
import top.lidee.project.system.record.domain.GrInvoiceRecord;
|
||||
|
||||
/**
|
||||
* 发票Service接口
|
||||
*
|
||||
* @author yuheng
|
||||
* @date 2026-04-02
|
||||
*/
|
||||
public interface IGrInvoiceRecordService
|
||||
{
|
||||
/**
|
||||
* 查询发票
|
||||
*
|
||||
* @param id 发票主键
|
||||
* @return 发票
|
||||
*/
|
||||
public GrInvoiceRecord selectGrInvoiceRecordById(String id);
|
||||
|
||||
/**
|
||||
* 查询发票列表
|
||||
*
|
||||
* @param grInvoiceRecord 发票
|
||||
* @return 发票集合
|
||||
*/
|
||||
public List<GrInvoiceRecord> selectGrInvoiceRecordList(GrInvoiceRecord grInvoiceRecord);
|
||||
|
||||
/**
|
||||
* 新增发票
|
||||
*
|
||||
* @param grInvoiceRecord 发票
|
||||
* @return 结果
|
||||
*/
|
||||
public int insertGrInvoiceRecord(GrInvoiceRecord grInvoiceRecord);
|
||||
|
||||
/**
|
||||
* 修改发票
|
||||
*
|
||||
* @param grInvoiceRecord 发票
|
||||
* @return 结果
|
||||
*/
|
||||
public int updateGrInvoiceRecord(GrInvoiceRecord grInvoiceRecord);
|
||||
|
||||
/**
|
||||
* 批量删除发票
|
||||
*
|
||||
* @param ids 需要删除的发票主键集合
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteGrInvoiceRecordByIds(String ids);
|
||||
|
||||
/**
|
||||
* 删除发票信息
|
||||
*
|
||||
* @param id 发票主键
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteGrInvoiceRecordById(String id);
|
||||
|
||||
int batchProcess(List<String> idList);
|
||||
}
|
||||
@@ -0,0 +1,280 @@
|
||||
package top.lidee.project.system.record.service.impl;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.sql.*;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import top.lidee.common.constant.InvoiceConstants;
|
||||
import top.lidee.common.utils.DateUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import top.lidee.common.utils.StringUtils;
|
||||
import top.lidee.project.monitor.job.util.HttpXml;
|
||||
import top.lidee.project.monitor.job.util.InvoiceXmlSy;
|
||||
import top.lidee.project.system.record.mapper.GrInvoiceRecordMapper;
|
||||
import top.lidee.project.system.record.domain.GrInvoiceRecord;
|
||||
import top.lidee.project.system.record.service.IGrInvoiceRecordService;
|
||||
import top.lidee.common.utils.text.Convert;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
* 发票Service业务层处理
|
||||
*
|
||||
* @author yuheng
|
||||
* @date 2026-04-02
|
||||
*/
|
||||
@Service
|
||||
public class GrInvoiceRecordServiceImpl implements IGrInvoiceRecordService {
|
||||
@Autowired
|
||||
private GrInvoiceRecordMapper grInvoiceRecordMapper;
|
||||
|
||||
@Value("${invoice.url}")
|
||||
private String URL;
|
||||
|
||||
@Value("${invoice.eiInvWebService}")
|
||||
private String eiInvWebServiceUrl;
|
||||
/**
|
||||
* 数据库用户名
|
||||
*/
|
||||
@Value("${invoice.username}")
|
||||
private String USERNAME;
|
||||
/**
|
||||
* 数据库密码
|
||||
*/
|
||||
@Value("${invoice.password}")
|
||||
private String PASSWORD;
|
||||
@Value("${invoice.taxId}")
|
||||
private String taxId;
|
||||
@Value("${invoice.authCode}")
|
||||
private String authCode;
|
||||
@Value("${invoice.updateCode}")
|
||||
private String interfaceCode;
|
||||
private static final String fPath = "C:\\log\\fplog.log";
|
||||
|
||||
|
||||
/**
|
||||
* 查询发票
|
||||
*
|
||||
* @param id 发票主键
|
||||
* @return 发票
|
||||
*/
|
||||
@Override
|
||||
public GrInvoiceRecord selectGrInvoiceRecordById(String id) {
|
||||
return grInvoiceRecordMapper.selectGrInvoiceRecordById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询发票列表
|
||||
*
|
||||
* @param grInvoiceRecord 发票
|
||||
* @return 发票
|
||||
*/
|
||||
@Override
|
||||
public List<GrInvoiceRecord> selectGrInvoiceRecordList(GrInvoiceRecord grInvoiceRecord) {
|
||||
if (StringUtils.isNotBlank(grInvoiceRecord.getStatus()) && InvoiceConstants.UNTREATED.equals(grInvoiceRecord.getStatus())) {
|
||||
List<String> statusList = new ArrayList<>();
|
||||
statusList.add(InvoiceConstants.UNTREATED);
|
||||
statusList.add(InvoiceConstants.PROCESSED_NOT_SUCCESSFUL);
|
||||
grInvoiceRecord.setStatus(null);
|
||||
grInvoiceRecord.setStatusList(statusList);
|
||||
}
|
||||
return grInvoiceRecordMapper.selectGrInvoiceRecordList(grInvoiceRecord);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增发票
|
||||
*
|
||||
* @param grInvoiceRecord 发票
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int insertGrInvoiceRecord(GrInvoiceRecord grInvoiceRecord) {
|
||||
grInvoiceRecord.setCreateTime(DateUtils.getNowDate());
|
||||
return grInvoiceRecordMapper.insertGrInvoiceRecord(grInvoiceRecord);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改发票
|
||||
*
|
||||
* @param grInvoiceRecord 发票
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int updateGrInvoiceRecord(GrInvoiceRecord grInvoiceRecord) {
|
||||
grInvoiceRecord.setUpdateTime(DateUtils.getNowDate());
|
||||
return grInvoiceRecordMapper.updateGrInvoiceRecord(grInvoiceRecord);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除发票
|
||||
*
|
||||
* @param ids 需要删除的发票主键
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int deleteGrInvoiceRecordByIds(String ids) {
|
||||
return grInvoiceRecordMapper.deleteGrInvoiceRecordByIds(Convert.toStrArray(ids));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除发票信息
|
||||
*
|
||||
* @param id 发票主键
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int deleteGrInvoiceRecordById(String id) {
|
||||
return grInvoiceRecordMapper.deleteGrInvoiceRecordById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int batchProcess(List<String> idList) {
|
||||
if (CollectionUtils.isEmpty(idList)) {
|
||||
return 1;
|
||||
}
|
||||
List<GrInvoiceRecord> grInvoiceRecords = grInvoiceRecordMapper.selectGrInvoiceRecordListByIdList(idList);
|
||||
if (CollectionUtils.isEmpty(grInvoiceRecords)) {
|
||||
System.out.println("没有待请求数据");
|
||||
return 1;
|
||||
}
|
||||
try {
|
||||
for (GrInvoiceRecord invoiceRecord : grInvoiceRecords) {
|
||||
String key = invoiceRecord.getDjh();
|
||||
String txtCon = "";
|
||||
List<String> billNos = new ArrayList<>();
|
||||
billNos.add(key);
|
||||
|
||||
System.out.println("溯源 Id:" + billNos);
|
||||
txtCon += "溯源 Id:" + billNos + "\n";
|
||||
//封装 请求报文
|
||||
String xmldata = InvoiceXmlSy.generateDwzsXml(billNos);
|
||||
|
||||
// 组装接口需要的请求报文
|
||||
String payload = HttpXml.bulidSoapXML(interfaceCode, taxId, authCode, xmldata, "eiInterface");
|
||||
System.out.println(payload);
|
||||
boolean hasError = false;
|
||||
try {
|
||||
// 调用接口
|
||||
Map<String, Object> res = HttpXml.webServiceExecute(eiInvWebServiceUrl, payload);
|
||||
System.out.println("接口请求状态:" + res.get("httpStatus"));
|
||||
System.out.println("接口返回的原始报文:" + res.get("data"));
|
||||
txtCon += "接口请求状态:" + res.get("httpStatus") + "\n";
|
||||
txtCon += "接口返回的原始报文:" + res.get("data") + "\n";
|
||||
if (200 == (int) res.get("httpStatus")) {
|
||||
try {
|
||||
// 解析接口返回的报文
|
||||
HashMap<String, String> serviceData = HttpXml.parseResponseXML((String) res.get("data"));
|
||||
System.out.println("业务处理返回代码:" + serviceData.get("returnCode"));
|
||||
System.out.println("业务处理返回提示:" + serviceData.get("returnMessage"));
|
||||
System.out.println("业务处理返回数据:" + serviceData.get("data"));
|
||||
|
||||
txtCon += "业务处理返回代码:" + serviceData.get("returnCode") + "\n";
|
||||
txtCon += "业务处理返回提示:" + serviceData.get("returnMessage") + "\n";
|
||||
txtCon += "业务处理返回数据:" + serviceData.get("data") + "\n";
|
||||
// appendToFile(fPath, txtCon);
|
||||
String invNumber = "1";
|
||||
String xml = serviceData.get("data");
|
||||
Pattern pattern = Pattern.compile("<INV_NUMBER>(.*?)</INV_NUMBER>");
|
||||
Matcher matcher = pattern.matcher(xml);
|
||||
if (matcher.find()) {
|
||||
invNumber = matcher.group(1);
|
||||
}
|
||||
|
||||
// 如果没有被开发票(invNumber 为 1)
|
||||
if (invNumber.equals("1")) {
|
||||
System.out.println("单据号 " + key + " 还未开票");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (serviceData.get("returnCode").equals("0000")) {
|
||||
//更新数据库
|
||||
Connection conn = null;
|
||||
Statement stmt = null;
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
System.out.println("更新视图开始");
|
||||
// 1. 加载 Oracle JDBC 驱动
|
||||
Class.forName("oracle.jdbc.driver.OracleDriver");
|
||||
// 2. 建立数据库连接
|
||||
conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);
|
||||
// 3. 创建 Statement 对象
|
||||
stmt = conn.createStatement();
|
||||
// 4. 执行查询语句
|
||||
String sql = "update gr_dp_saset_sdhm_v a set a.zxcolumn1 = '" + invNumber + "' where a.sasettleid =" + key;
|
||||
PreparedStatement pstmt = conn.prepareStatement(sql);
|
||||
int rowsA = pstmt.executeUpdate();
|
||||
System.out.println("完成更新视图:" + rowsA);
|
||||
invoiceRecord.setStatus(InvoiceConstants.SUCCESSFUL);
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
|
||||
invoiceRecord.setKpsj(sdf.format(new Date()));
|
||||
invoiceRecord.setInvNumber(invNumber);
|
||||
grInvoiceRecordMapper.updateGrInvoiceRecord(invoiceRecord);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
// 发生错误,标记为已尝试但不需要重试
|
||||
hasError = true;
|
||||
// 6. 关闭资源
|
||||
try {
|
||||
if (rs != null) rs.close();
|
||||
if (stmt != null) stmt.close();
|
||||
if (conn != null) conn.close();
|
||||
} catch (SQLException e11) {
|
||||
e11.printStackTrace();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 业务处理失败,标记为已尝试但不需要重试
|
||||
hasError = true;
|
||||
System.out.println("业务处理失败:" + serviceData.get("returnMessage"));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.out.println("解析报文出错的,保持业务为处理中状态,需要检查原因");
|
||||
e.printStackTrace();
|
||||
hasError = true;
|
||||
}
|
||||
} else {
|
||||
// HTTP 请求状态不是 200,标记为已尝试但不需要重试
|
||||
hasError = true;
|
||||
System.out.println("HTTP 请求失败,状态码:" + res.get("httpStatus"));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
hasError = true;
|
||||
}
|
||||
// 如果发生错误,更新状态为 1(已尝试但不需要重试)
|
||||
if (hasError) {
|
||||
invoiceRecord.setStatus(InvoiceConstants.PROCESSED_NOT_SUCCESSFUL);
|
||||
grInvoiceRecordMapper.updateGrInvoiceRecord(invoiceRecord);
|
||||
System.out.println("单据号 " + key + " 处理失败,标记为已尝试状态");
|
||||
}
|
||||
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
// 追加写入模式
|
||||
public static void appendToFile(String filePath, String content) throws IOException {
|
||||
try (BufferedWriter writer = new BufferedWriter(new FileWriter(filePath, true))) {
|
||||
writer.newLine(); // 换行后再追加
|
||||
writer.write(content);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,8 @@ spring:
|
||||
druid:
|
||||
# 主库数据源 root
|
||||
master:
|
||||
url: jdbc:sqlite:D:/uploadPath/SQLite/sqlite3.db?date_string_format=yyyy-MM-dd HH:mm:ss
|
||||
# url: jdbc:sqlite:D:/work/gr_fapiao/sql/sqlite3.db?date_string_format=yyyy-MM-dd HH:mm:ss
|
||||
url: jdbc:sqlite:c:/SQLite/sql/sqlite3.db?date_string_format=yyyy-MM-dd HH:mm:ss
|
||||
username:
|
||||
password:
|
||||
# 从库数据源
|
||||
|
||||
@@ -150,4 +150,23 @@ gen:
|
||||
# 自动去除表前缀,默认是true
|
||||
autoRemovePre: true
|
||||
# 表前缀(生成类名不会包含表前缀,多个用逗号分隔)
|
||||
tablePrefix: sys_
|
||||
tablePrefix: sys_
|
||||
invoice:
|
||||
# 开票系统地址
|
||||
url: jdbc:oracle:thin:@192.168.1.247:1521:gryy
|
||||
# 开票系统用户名
|
||||
username: GRYYINV
|
||||
# 开票系统密码
|
||||
password: xxb147258368
|
||||
|
||||
taxId: 9134040072334670XN
|
||||
|
||||
authCode: 7G5X2YSSMA
|
||||
|
||||
interfaceCode: DJLR
|
||||
|
||||
updateCode: DWZS
|
||||
|
||||
eiInvWebService: https://csxtqd.nuocity.com/open/services/eiInvWebService?wsdl
|
||||
|
||||
iBillInterfaceWebService: https://csxtqd.nuocity.com/open/services/iBillInterfaceWebService?wsdl
|
||||
|
||||
131
src/main/resources/mybatis/system/GrInvoiceRecordMapper.xml
Normal file
131
src/main/resources/mybatis/system/GrInvoiceRecordMapper.xml
Normal file
@@ -0,0 +1,131 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="top.lidee.project.system.record.mapper.GrInvoiceRecordMapper">
|
||||
|
||||
<resultMap type="GrInvoiceRecord" id="GrInvoiceRecordResult">
|
||||
<result property="id" column="id"/>
|
||||
<result property="djh" column="djh"/>
|
||||
<result property="djrq" column="djrq"/>
|
||||
<result property="fpzl" column="fpzl"/>
|
||||
<result property="kpsj" column="kpsj"/>
|
||||
<result property="createBy" column="create_by"/>
|
||||
<result property="createTime" column="create_time"/>
|
||||
<result property="updateBy" column="update_by"/>
|
||||
<result property="updateTime" column="update_time"/>
|
||||
<result property="status" column="status"/>
|
||||
<result property="gmfMc" column="gmf_mc"/>
|
||||
<result property="invNumber" column="inv_number"/>
|
||||
</resultMap>
|
||||
|
||||
<sql id="selectGrInvoiceRecordVo">
|
||||
select id,
|
||||
djh,
|
||||
djrq,
|
||||
fpzl,
|
||||
kpsj,
|
||||
create_by,
|
||||
create_time,
|
||||
update_by,
|
||||
update_time,
|
||||
status,
|
||||
gmf_mc,
|
||||
inv_number
|
||||
from gr_invoice_record
|
||||
</sql>
|
||||
|
||||
<select id="selectGrInvoiceRecordList" parameterType="GrInvoiceRecord" resultMap="GrInvoiceRecordResult">
|
||||
<include refid="selectGrInvoiceRecordVo"/>
|
||||
<where>
|
||||
<if test="djh != null and djh != ''">AND djh LIKE '%' || #{djh} || '%'</if>
|
||||
<if test="status != null and status != ''">and status = #{status}</if>
|
||||
<if test="gmfMc != null and gmfMc != ''">AND gmf_mc LIKE '%' || #{gmfMc} || '%'</if>
|
||||
<if test="invNumber != null and invNumber != ''">AND inv_number LIKE '%' || #{invNumber} || '%'</if>
|
||||
<if test="statusList != null">
|
||||
AND status in
|
||||
<foreach item="statusItem" collection="statusList" open="(" separator="," close=")">
|
||||
#{statusItem}
|
||||
</foreach>
|
||||
</if>
|
||||
</where>
|
||||
ORDER BY create_time DESC
|
||||
</select>
|
||||
|
||||
<select id="selectGrInvoiceRecordById" parameterType="String" resultMap="GrInvoiceRecordResult">
|
||||
<include refid="selectGrInvoiceRecordVo"/>
|
||||
where id = #{id}
|
||||
</select>
|
||||
|
||||
<insert id="insertGrInvoiceRecord" parameterType="GrInvoiceRecord">
|
||||
insert into gr_invoice_record
|
||||
<trim prefix="(" suffix=")" suffixOverrides=",">
|
||||
<if test="id != null">id,</if>
|
||||
<if test="djh != null">djh,</if>
|
||||
<if test="djrq != null">djrq,</if>
|
||||
<if test="fpzl != null">fpzl,</if>
|
||||
<if test="kpsj != null">kpsj,</if>
|
||||
<if test="createBy != null">create_by,</if>
|
||||
<if test="createTime != null">create_time,</if>
|
||||
<if test="updateBy != null">update_by,</if>
|
||||
<if test="updateTime != null">update_time,</if>
|
||||
<if test="status != null ">status,</if>
|
||||
<if test="gmfMc != null">gmf_mc,</if>
|
||||
<if test="invNumber != null">inv_number,</if>
|
||||
</trim>
|
||||
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
||||
<if test="id != null">#{id},</if>
|
||||
<if test="djh != null">#{djh},</if>
|
||||
<if test="djrq != null">#{djrq},</if>
|
||||
<if test="fpzl != null">#{fpzl},</if>
|
||||
<if test="kpsj != null">#{kpsj},</if>
|
||||
<if test="createBy != null">#{createBy},</if>
|
||||
<if test="createTime != null">#{createTime},</if>
|
||||
<if test="updateBy != null">#{updateBy},</if>
|
||||
<if test="updateTime != null">#{updateTime},</if>
|
||||
<if test="status != null">#{status},</if>
|
||||
<if test="gmfMc != null">#{gmfMc},</if>
|
||||
<if test="invNumber != null">#{invNumber},</if>
|
||||
</trim>
|
||||
</insert>
|
||||
|
||||
<update id="updateGrInvoiceRecord" parameterType="GrInvoiceRecord">
|
||||
update gr_invoice_record
|
||||
<trim prefix="SET" suffixOverrides=",">
|
||||
<if test="djh != null">djh = #{djh},</if>
|
||||
<if test="djrq != null">djrq = #{djrq},</if>
|
||||
<if test="fpzl != null">fpzl = #{fpzl},</if>
|
||||
<if test="kpsj != null">kpsj = #{kpsj},</if>
|
||||
<if test="createBy != null">create_by = #{createBy},</if>
|
||||
<if test="createTime != null">create_time = #{createTime},</if>
|
||||
<if test="updateBy != null">update_by = #{updateBy},</if>
|
||||
<if test="updateTime != null">update_time = #{updateTime},</if>
|
||||
<if test="status != null">status = #{status},</if>
|
||||
<if test="gmfMc != null">gmf_mc = #{gmfMc},</if>
|
||||
<if test="invNumber != null">inv_number = #{invNumber},</if>
|
||||
</trim>
|
||||
where id = #{id}
|
||||
</update>
|
||||
|
||||
<delete id="deleteGrInvoiceRecordById" parameterType="String">
|
||||
delete
|
||||
from gr_invoice_record
|
||||
where id = #{id}
|
||||
</delete>
|
||||
|
||||
<delete id="deleteGrInvoiceRecordByIds" parameterType="String">
|
||||
delete from gr_invoice_record where id in
|
||||
<foreach item="id" collection="array" open="(" separator="," close=")">
|
||||
#{id}
|
||||
</foreach>
|
||||
</delete>
|
||||
|
||||
<select id="selectGrInvoiceRecordListByIdList" parameterType="java.util.List" resultMap="GrInvoiceRecordResult">
|
||||
<include refid="selectGrInvoiceRecordVo"/>
|
||||
where id in
|
||||
<foreach item="id" collection="list" open="(" separator="," close=")">
|
||||
#{id}
|
||||
</foreach>
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
@@ -26,7 +26,7 @@
|
||||
</div>
|
||||
<a th:href="@{/index}">
|
||||
<li class="logo hidden-xs">
|
||||
<span class="logo-lg">lidee</span>
|
||||
<span class="logo-lg">电票系统</span>
|
||||
</li>
|
||||
</a>
|
||||
<div class="sidebar-collapse">
|
||||
|
||||
49
src/main/resources/templates/system/record/add.html
Normal file
49
src/main/resources/templates/system/record/add.html
Normal file
@@ -0,0 +1,49 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
|
||||
<head>
|
||||
<th:block th:include="include :: header('新增发票')" />
|
||||
</head>
|
||||
<body class="white-bg">
|
||||
<div class="wrapper wrapper-content animated fadeInRight ibox-content">
|
||||
<form class="form-horizontal m" id="form-record-add">
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">:</label>
|
||||
<div class="col-sm-8">
|
||||
<input name="DJH" class="form-control" type="text">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">:</label>
|
||||
<div class="col-sm-8">
|
||||
<input name="DJRQ" class="form-control" type="text">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">:</label>
|
||||
<div class="col-sm-8">
|
||||
<input name="FPZL" class="form-control" type="text">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">:</label>
|
||||
<div class="col-sm-8">
|
||||
<input name="KPSJ" class="form-control" type="text">
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<th:block th:include="include :: footer" />
|
||||
<script th:inline="javascript">
|
||||
var prefix = ctx + "system/record"
|
||||
$("#form-record-add").validate({
|
||||
focusCleanup: true
|
||||
});
|
||||
|
||||
function submitHandler() {
|
||||
if ($.validate.form()) {
|
||||
$.operate.save(prefix + "/add", $('#form-record-add').serialize());
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
50
src/main/resources/templates/system/record/edit.html
Normal file
50
src/main/resources/templates/system/record/edit.html
Normal file
@@ -0,0 +1,50 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
|
||||
<head>
|
||||
<th:block th:include="include :: header('修改发票')" />
|
||||
</head>
|
||||
<body class="white-bg">
|
||||
<div class="wrapper wrapper-content animated fadeInRight ibox-content">
|
||||
<form class="form-horizontal m" id="form-record-edit" th:object="${grInvoiceRecord}">
|
||||
<input name="id" th:field="*{id}" type="hidden">
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">:</label>
|
||||
<div class="col-sm-8">
|
||||
<input name="DJH" th:field="*{DJH}" class="form-control" type="text">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">:</label>
|
||||
<div class="col-sm-8">
|
||||
<input name="DJRQ" th:field="*{DJRQ}" class="form-control" type="text">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">:</label>
|
||||
<div class="col-sm-8">
|
||||
<input name="FPZL" th:field="*{FPZL}" class="form-control" type="text">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">:</label>
|
||||
<div class="col-sm-8">
|
||||
<input name="KPSJ" th:field="*{KPSJ}" class="form-control" type="text">
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<th:block th:include="include :: footer" />
|
||||
<script th:inline="javascript">
|
||||
var prefix = ctx + "system/record";
|
||||
$("#form-record-edit").validate({
|
||||
focusCleanup: true
|
||||
});
|
||||
|
||||
function submitHandler() {
|
||||
if ($.validate.form()) {
|
||||
$.operate.save(prefix + "/edit", $('#form-record-edit').serialize());
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
187
src/main/resources/templates/system/record/record.html
Normal file
187
src/main/resources/templates/system/record/record.html
Normal file
@@ -0,0 +1,187 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
|
||||
<head>
|
||||
<th:block th:include="include :: header('发票列表')"/>
|
||||
</head>
|
||||
<body class="gray-bg">
|
||||
<div class="container-div">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 search-collapse">
|
||||
<form id="formId">
|
||||
<div class="select-list">
|
||||
<ul>
|
||||
<li>
|
||||
<label>单据号:</label>
|
||||
<input type="text" name="djh" style="width: 200px;"/>
|
||||
</li>
|
||||
<li>
|
||||
<label style="width: 120px;">客户名称:</label>
|
||||
<input type="text" name="gmfMc" style="width: 200px;"/>
|
||||
</li>
|
||||
<li>
|
||||
<label style="width: 120px;">发票号码:</label>
|
||||
<input type="text" name="invNumber" style="width: 200px;"/>
|
||||
</li>
|
||||
<li style="margin-left: 40px;">
|
||||
<label>开票状态:</label>
|
||||
<select name="status" style="width: 120px;">
|
||||
<option value="">全部</option>
|
||||
<option value="0">未开票</option>
|
||||
<option value="2">已开票</option>
|
||||
</select>
|
||||
</li>
|
||||
<li>
|
||||
<a class="btn btn-primary btn-rounded btn-sm" onclick="$.table.search()"><i
|
||||
class="fa fa-search"></i> 搜索</a>
|
||||
<a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset()"><i
|
||||
class="fa fa-refresh"></i> 重置</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="btn-group-sm" id="toolbar" role="group">
|
||||
<a class="btn btn-success multiple disabled" onclick="batchProcess()" shiro:hasPermission="system:record:list">
|
||||
<i class="fa fa-edit"></i> 批量处理
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-sm-12 select-table table-striped">
|
||||
<table id="bootstrap-table"></table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<th:block th:include="include :: footer"/>
|
||||
<script th:inline="javascript">
|
||||
var editFlag = [[${@permission.hasPermi('system:record:edit')}]];
|
||||
var removeFlag = [[${@permission.hasPermi('system:record:remove')}]];
|
||||
var prefix = ctx + "system/record";
|
||||
|
||||
|
||||
// 批量处理函数
|
||||
function batchProcess() {
|
||||
var rows = $.common.isEmpty(table.options.uniqueId) ? $.table.selectFirstColumns() : $.table.selectColumns(table.options.uniqueId);
|
||||
if (rows.length == 0) {
|
||||
$.modal.alertWarning("请至少选择一条记录");
|
||||
return;
|
||||
}
|
||||
$.modal.confirm("确认要处理选中的" + rows.length + "条数据吗?", function() {
|
||||
$.modal.loading("正在处理,请稍候...");
|
||||
$.ajax({
|
||||
url: prefix + "/batchProcess",
|
||||
type: "post",
|
||||
dataType: "json",
|
||||
traditional: true,
|
||||
data: {
|
||||
"idList": rows
|
||||
},
|
||||
success: function(result) {
|
||||
if (result.code == web_status.SUCCESS) {
|
||||
$.modal.msgSuccess(result.msg);
|
||||
$.table.refresh();
|
||||
} else {
|
||||
$.modal.alertError(result.msg);
|
||||
}
|
||||
},
|
||||
complete: function() {
|
||||
$.modal.closeLoading();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
$(function () {
|
||||
var options = {
|
||||
url: prefix + "/list",
|
||||
createUrl: prefix + "/add",
|
||||
updateUrl: prefix + "/edit/{id}",
|
||||
removeUrl: prefix + "/remove",
|
||||
exportUrl: prefix + "/export",
|
||||
modalName: "发票",
|
||||
columns: [{
|
||||
checkbox: true
|
||||
},
|
||||
{
|
||||
field: 'id',
|
||||
title: '',
|
||||
visible: false
|
||||
},
|
||||
{
|
||||
field: 'djh',
|
||||
title: '单据号',
|
||||
align: 'center'
|
||||
|
||||
},
|
||||
{
|
||||
field: 'djrq',
|
||||
title: '单据日期',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
field: 'invNumber',
|
||||
title: '发票号码',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
field: 'fpzl',
|
||||
title: '发票种类',
|
||||
align: 'center',
|
||||
formatter: function(value, row, index) {
|
||||
if (value === "81") {
|
||||
return '<span>数电专票</span>';
|
||||
} else if (value === "82") {
|
||||
return '<span>数电普票</span>';
|
||||
}
|
||||
return value;
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'gmfMc',
|
||||
title: '客户名称',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
field: 'kpsj',
|
||||
title: '开票时间',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
field: 'createTime',
|
||||
title: '上传时间',
|
||||
align: 'center'
|
||||
},
|
||||
|
||||
{
|
||||
field: 'status',
|
||||
title: '开票状态',
|
||||
align: 'center',
|
||||
formatter: function(value, row, index) {
|
||||
if (value === "2") {
|
||||
return '<span style="color: #28a745;">已开票</span>';
|
||||
} else if (value === "1") {
|
||||
return '<span style="color: #17a2b8;">处理中</span>';
|
||||
} else if (value === "0") {
|
||||
return '<span style="color: #dc3545;">未开票</span>';
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
// {
|
||||
// title: '操作',
|
||||
// align: 'center',
|
||||
// formatter: function (value, row, index) {
|
||||
// var actions = [];
|
||||
// actions.push('<a class="btn btn-success btn-xs ' + editFlag + '" href="javascript:void(0)" onclick="$.operate.edit(\'' + row.id + '\')"><i class="fa fa-edit"></i>编辑</a> ');
|
||||
// actions.push('<a class="btn btn-danger btn-xs ' + removeFlag + '" href="javascript:void(0)" onclick="$.operate.remove(\'' + row.id + '\')"><i class="fa fa-remove"></i>删除</a>');
|
||||
// return actions.join('');
|
||||
// }
|
||||
// }
|
||||
]
|
||||
};
|
||||
$.table.init(options);
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user