diff --git a/code/springboot/newBank/src/main/java/demo/weiyichi/controller/TransferAccount.java b/code/springboot/newBank/src/main/java/demo/weiyichi/controller/TransferAccount.java new file mode 100644 index 000000000..d47230fce --- /dev/null +++ b/code/springboot/newBank/src/main/java/demo/weiyichi/controller/TransferAccount.java @@ -0,0 +1,202 @@ +package demo.weiyichi.controller; + + +import demo.weiyichi.model.AccountTab; +import demo.weiyichi.model.ApiResponse; +import demo.weiyichi.model.RecordTable; +import demo.weiyichi.model.WithdrawMoneyDTO; +import demo.weiyichi.model.TransferDTO; +import demo.weiyichi.model.QueryDTO; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jdbc.core.JdbcTemplate; + +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import javax.transaction.Transactional; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@RestController +@RequestMapping("/weiyichi") +public class TransferAccount { + + // add 01 + @Autowired + private JdbcTemplate jdbcTemplate; + + //转账 + @Transactional + @PostMapping("/transfer") + public ApiResponse transfer(@RequestBody TransferDTO transferDTO) { + try { + // 参数校验 + if (transferDTO.getOutCardNo() == null || transferDTO.getInCardNo() == null) { + return ApiResponse.error("INVALID_CARDNO", "卡号不能为空"); + } + if (transferDTO.getAmount() == null || transferDTO.getAmount() <= 0) { + return ApiResponse.error("INVALID_AMOUNT", "转账金额必须大于0"); + } + + // 验证转出账户 + String outSql = "SELECT * FROM account_tab WHERE cardNo = ?"; + List> outAccount = jdbcTemplate.queryForList(outSql, transferDTO.getOutCardNo()); + if (CollectionUtils.isEmpty(outAccount)) { + return ApiResponse.error("ACCOUNT_NOT_FOUND", "转出账户不存在"); + } + + // 验证密码 + if (!verifyAccountPassword(transferDTO.getOutCardNo(), transferDTO.getPassword())) { + return ApiResponse.error("PASSWORD_MISMATCH", "密码错误"); + } + + // 验证转入账户 + String inSql = "SELECT * FROM account_tab WHERE cardNo = ?"; + if (CollectionUtils.isEmpty(jdbcTemplate.queryForList(inSql, transferDTO.getInCardNo()))) { + return ApiResponse.error("ACCOUNT_NOT_FOUND", "转入账户不存在"); + } + + // 检查余额 + double outBalance = Double.parseDouble(outAccount.get(0).get("balance").toString()); + if (outBalance < transferDTO.getAmount()) { + return ApiResponse.error("INSUFFICIENT_BALANCE", "余额不足"); + } + + // 更新余额 + jdbcTemplate.update("UPDATE account_tab SET balance = ? WHERE cardNo = ?", + outBalance - transferDTO.getAmount(), transferDTO.getOutCardNo()); + jdbcTemplate.update("UPDATE account_tab SET balance = balance + ? WHERE cardNo = ?", + transferDTO.getAmount(), transferDTO.getInCardNo()); + + // 生成流水记录 + generateTransferRecords(transferDTO, outBalance); + logger.info("转账成功:从 {} 到 {},金额 {}", + transferDTO.getOutCardNo(), transferDTO.getInCardNo(), transferDTO.getAmount()); + return ApiResponse.success(null); + } catch (Exception e) { + logger.error("转账失败:{}", e.getMessage()); + return ApiResponse.error("TRANSFER_FAILED", "转账失败"); + } + } + + + + // 账户查询 + @GetMapping("/query") + public ApiResponse> query( + @RequestParam String cardNo, + @RequestParam(required = false) String type, + @RequestParam(required = false) String filter, + @RequestParam(required = false) String startDate, + @RequestParam(required = false) String endDate) { + + // 参数校验 + if (cardNo == null || !cardNo.matches("\\d{16}")) { + return ApiResponse.error("INVALID_CARDNO", "卡号格式错误"); + } + + Map result = new HashMap<>(); + + // 余额查询 + if (type == null || "balance".equals(type)) { + try { + String balanceSql = "SELECT balance FROM account_tab WHERE cardNo = ?"; + Double balance = jdbcTemplate.queryForObject(balanceSql, Double.class, cardNo); + result.put("balance", balance); + } catch (Exception e) { + return ApiResponse.error("BALANCE_QUERY_FAILED", "余额查询失败"); + } + } + + // 交易记录查询 + if (type == null || "transactions".equals(type)) { + try { + String transSql = buildTransactionSql(filter, startDate, endDate); + List> transactions = jdbcTemplate.queryForList(transSql, cardNo); + result.put("transactions", transactions); + } catch (Exception e) { + return ApiResponse.error("TRANSACTION_QUERY_FAILED", "交易记录查询失败"); + } + } + + return ApiResponse.success(result); + } + + //构建交易记录查询 + private String buildTransactionSql(String filter, String startDate, String endDate) { + String sql = "SELECT " + + "date, cardNo, money, " + + "CASE serviceTy " + + "WHEN '1' THEN '存款' " + + "WHEN '2' THEN '取款' " + + "WHEN '3' THEN '转账' " + + "ELSE '未知' " + + "END AS serviceDesc, " + + "balance, recordNo " + + "FROM recordtable " + + "WHERE cardNo = ?"; + + if ("income".equals(filter)) { + sql += " AND serviceTy = '1'"; + } else if ("expense".equals(filter)) { + sql += " AND serviceTy IN ('2', '3')"; + } + + if (startDate != null && endDate != null) { + sql += " AND date BETWEEN ? AND ?"; + } + + return sql; + } + + //销户接口 + @PostMapping("/closeAccount") + public ApiResponse closeAccount( + @RequestParam String cardNo, + @RequestParam String password, + @RequestParam String staffNo, + @RequestParam String organiNm) { + + // 参数校验 + if (cardNo == null || cardNo.trim().isEmpty()) { + return ApiResponse.error("INVALID_CARDNO", "卡号不能为空"); + } + if (password == null || password.trim().isEmpty()) { + return ApiResponse.error("INVALID_PASSWORD", "密码不能为空"); + } + + // 验证密码 + if (!verifyAccountPassword(cardNo, password)) { + return ApiResponse.error("PASSWORD_MISMATCH", "密码错误"); + } + + // 检查余额 + Double balance = getBalance(cardNo).getData(); + if (balance == null || balance != 0) { + return ApiResponse.error("BALANCE_NOT_ZERO", "账户余额不为0,无法销户"); + } + + try { + // 更新账户状态 + String updateSql = "UPDATE account_tab SET status = '2' WHERE cardNo = ?"; + jdbcTemplate.update(updateSql, cardNo); + + // 生成销户流水记录 + RecordTable record = new RecordTable(); + record.setCardNo(cardNo); + record.setServiceTy("4"); // 4-销户 + record.setRecordNo(getRecordNo(staffNo, organiNm)); + saveRecordTable(record); + + logger.info("账户 {} 已销户,操作员工:{}", cardNo, staffNo); + return ApiResponse.success(null); + } catch (Exception e) { + logger.error("销户失败:{}", e.getMessage()); + return ApiResponse.error("CLOSE_FAILED", "销户失败"); + } + } + +} \ No newline at end of file diff --git a/code/springboot/newBank/src/main/java/demo/weiyichi/model/AccountTab.java b/code/springboot/newBank/src/main/java/demo/weiyichi/model/AccountTab.java new file mode 100644 index 000000000..2bf501907 --- /dev/null +++ b/code/springboot/newBank/src/main/java/demo/weiyichi/model/AccountTab.java @@ -0,0 +1,161 @@ +package demo.weiyichi.model; + +/** + * @author Administrator + * 账户表 + */ +public class AccountTab { + + /** + * 账号(卡号) + */ + private String cardNo; + + /** + * 客户号 + */ + private String customNo; + + /** + * 证件类型 + */ + private String idType; + /** + * 证件号码 + */ + private String idNo; + /** + * 开户机构 + */ + private String organiNm; + /** + * 开户日期 + */ + private String accountDa; + + /** + * 开户员工(员工号) + */ + private String accstaff; + + /** + * 余额 + */ + private Double balance; + + /** + * 类型(1个人、2企业) + */ + private String acctype; + + /** + * 存款类型 1存 2取 + */ + private String depositTy; + + /** + * 账户状态 1 正常 2 销户 + */ + private String status; + + /** + * 密码 + */ + private String password; + + public String getCardNo() { + return cardNo; + } + + public void setCardNo(String cardNo) { + this.cardNo = cardNo; + } + + public String getCustomNo() { + return customNo; + } + + public void setCustomNo(String customNo) { + this.customNo = customNo; + } + + public String getIdType() { + return idType; + } + + public void setIdType(String idType) { + this.idType = idType; + } + + public String getIdNo() { + return idNo; + } + + public void setIdNo(String idNo) { + this.idNo = idNo; + } + + public String getOrganiNm() { + return organiNm; + } + + public void setOrganiNm(String organiNm) { + this.organiNm = organiNm; + } + + public String getAccountDa() { + return accountDa; + } + + public void setAccountDa(String accountDa) { + this.accountDa = accountDa; + } + + public String getAccstaff() { + return accstaff; + } + + public void setAccstaff(String accstaff) { + this.accstaff = accstaff; + } + + public Double getBalance() { + return balance; + } + + public void setBalance(Double balance) { + this.balance = balance; + } + + public String getAcctype() { + return acctype; + } + + public void setAcctype(String acctype) { + this.acctype = acctype; + } + + public String getDepositTy() { + return depositTy; + } + + public void setDepositTy(String depositTy) { + this.depositTy = depositTy; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } +} diff --git a/code/springboot/newBank/src/main/java/demo/weiyichi/model/ApiResponse.java b/code/springboot/newBank/src/main/java/demo/weiyichi/model/ApiResponse.java new file mode 100644 index 000000000..d069e22c7 --- /dev/null +++ b/code/springboot/newBank/src/main/java/demo/weiyichi/model/ApiResponse.java @@ -0,0 +1,27 @@ +package demo.weiyichi.model; + +/** + * 统一接口响应对象 + */ +public class ApiResponse { + private boolean success; + private String code; + private String message; + private T data; + + // 构造方法和Getter/Setter + public ApiResponse(boolean success, String code, String message, T data) { + this.success = success; + this.code = code; + this.message = message; + this.data = data; + } + + public static ApiResponse success(T data) { + return new ApiResponse<>(true, "SUCCESS", "操作成功", data); + } + + public static ApiResponse error(String code, String message) { + return new ApiResponse<>(false, code, message, null); + } +} \ No newline at end of file diff --git a/code/springboot/newBank/src/main/java/demo/weiyichi/model/QueryDTO.java b/code/springboot/newBank/src/main/java/demo/weiyichi/model/QueryDTO.java new file mode 100644 index 000000000..f4c7eadb5 --- /dev/null +++ b/code/springboot/newBank/src/main/java/demo/weiyichi/model/QueryDTO.java @@ -0,0 +1,49 @@ +package demo.weiyichi.model; + +import java.time.LocalDateTime; + +/** + * 整合查询接口请求参数 + */ +public class QueryDTO { + private String cardNo; // 卡号 + private String type; // 查询类型:balance(余额)、transactions(交易记录) + private String filter; // 交易记录过滤:income(收入)、expense(支出) + private String startDate; // 起始日期(格式:xxxx-yy-zz) + private String endDate; // 结束日期(格式:xxxx-yy-zz) + private LocalDateTime date; // 交易时间 + private Double money; // 交易金额 + private String serviceDesc; // 交易类型(存款、取款、转账) + private Double balance; // 交易后余额 + private String recordNo; // 流水号 + // Getter 和 Setter 方法 + public String getCardNo() { return cardNo; } + public void setCardNo(String cardNo) { this.cardNo = cardNo; } + + public String getType() { return type; } + public void setType(String type) { this.type = type; } + + public String getFilter() { return filter; } + public void setFilter(String filter) { this.filter = filter; } + + public String getStartDate() { return startDate; } + public void setStartDate(String startDate) { this.startDate = startDate; } + + public String getEndDate() { return endDate; } + public void setEndDate(String endDate) { this.endDate = endDate; } + + public LocalDateTime getDate() { return date; } + public void setDate(LocalDateTime date) { this.date = date; } + + public Double getMoney() { return money; } + public void setMoney(Double money) { this.money = money; } + + public String getServiceDesc() { return serviceDesc; } + public void setServiceDesc(String serviceDesc) { this.serviceDesc = serviceDesc; } + + public Double getBalance() { return balance; } + public void setBalance(Double balance) { this.balance = balance; } + + public String getRecordNo() { return recordNo; } + public void setRecordNo(String recordNo) { this.recordNo = recordNo; } +} \ No newline at end of file diff --git a/code/springboot/newBank/src/main/java/demo/weiyichi/model/RecordTable.java b/code/springboot/newBank/src/main/java/demo/weiyichi/model/RecordTable.java new file mode 100644 index 000000000..dd0b0b5b8 --- /dev/null +++ b/code/springboot/newBank/src/main/java/demo/weiyichi/model/RecordTable.java @@ -0,0 +1,72 @@ +package demo.weiyichi.model; + +/** + * @author Administrator + */ +public class RecordTable { + + /** + * 卡号 + */ + private String cardNo; + + /** + * 金钱 + */ + private Double money; + + /** + * 存取钱 1存钱 2取钱 + */ + private String serviceTy; + + /** + * 金额 + */ + private Double balance; + + /** + * 流水号 + */ + private String recordNo; + + public String getCardNo() { + return cardNo; + } + + public void setCardNo(String cardNo) { + this.cardNo = cardNo; + } + + public String getServiceTy() { + return serviceTy; + } + + public void setServiceTy(String serviceTy) { + this.serviceTy = serviceTy; + } + + public Double getMoney() { + return money; + } + + public void setMoney(Double money) { + this.money = money; + } + + public Double getBalance() { + return balance; + } + + public void setBalance(Double balance) { + this.balance = balance; + } + + public String getRecordNo() { + return recordNo; + } + + public void setRecordNo(String recordNo) { + this.recordNo = recordNo; + } +} diff --git a/code/springboot/newBank/src/main/java/demo/weiyichi/model/TransferDTO.java b/code/springboot/newBank/src/main/java/demo/weiyichi/model/TransferDTO.java new file mode 100644 index 000000000..dcd876072 --- /dev/null +++ b/code/springboot/newBank/src/main/java/demo/weiyichi/model/TransferDTO.java @@ -0,0 +1,57 @@ +package demo.weiyichi.model; + +/** + * 转账操作数据传输对象 + */ +public class TransferDTO { + /** + * 转出账户卡号 + */ + private String outCardNo; + /** + * 转入账户卡号 + */ + private String inCardNo; + /** + * 转账金额 + */ + private Double amount; + /** + * 转出账户密码 + */ + private String password; + + + // Getter 和 Setter 方法 + public String getOutCardNo() { + return outCardNo; + } + + public void setOutCardNo(String outCardNo) { + this.outCardNo = outCardNo; + } + + public String getInCardNo() { + return inCardNo; + } + + public void setInCardNo(String inCardNo) { + this.inCardNo = inCardNo; + } + + public Double getAmount() { + return amount; + } + + public void setAmount(Double amount) { + this.amount = amount; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } +} \ No newline at end of file diff --git a/code/springboot/newBank/src/main/java/demo/weiyichi/model/WithdrawMoneyDTO.java b/code/springboot/newBank/src/main/java/demo/weiyichi/model/WithdrawMoneyDTO.java new file mode 100644 index 000000000..665118704 --- /dev/null +++ b/code/springboot/newBank/src/main/java/demo/weiyichi/model/WithdrawMoneyDTO.java @@ -0,0 +1,69 @@ +package demo.weiyichi.model; + + +/** + * @author Administrator + */ +public class WithdrawMoneyDTO { + + /** + * 账号 + */ + private String cardNo; + /** + * 金额 + */ + private Double money; + /** + * 存取 1存 2取 + */ + private String serviceTy; + /** + * 员工编号 + */ + private String staffNo; + /** + * 机构号 + */ + private String organiNm; + + public String getCardNo() { + return cardNo; + } + + public void setCardNo(String cardNo) { + this.cardNo = cardNo; + } + + public Double getMoney() { + return money; + } + + public void setMoney(Double money) { + this.money = money; + } + + public String getServiceTy() { + return serviceTy; + } + + public void setServiceTy(String serviceTy) { + this.serviceTy = serviceTy; + } + + public String getStaffNo() { + return staffNo; + } + + public void setStaffNo(String staffNo) { + this.staffNo = staffNo; + } + + public String getOrganiNm() { + return organiNm; + } + + public void setOrganiNm(String organiNm) { + this.organiNm = organiNm; + } +} diff --git a/code/springboot/newBank/src/main/java/demo/weiyichi/储蓄接口文档.docx b/code/springboot/newBank/src/main/java/demo/weiyichi/储蓄接口文档.docx new file mode 100644 index 000000000..2fbe2b4df Binary files /dev/null and b/code/springboot/newBank/src/main/java/demo/weiyichi/储蓄接口文档.docx differ