ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TErpClinicWarehousingController.java
@@ -142,7 +142,7 @@ @ApiOperation(value = "诊所 盘点 出库 商品选择") @ApiOperation(value = "诊所 盘点 出库 商品选择 患者诊疗商品选择") @PostMapping(value = "/pageInventoryGoodsPageList") public R<PageInfo<TErpGoodsInventoryVO>> pageInventoryGoodsPageList(@RequestBody @Valid TErpGoodsInventoryQuery query) { SysUser user = tokenService.getLoginUser().getUser(); ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TErpProcurementController.java
@@ -27,6 +27,7 @@ import javax.validation.Valid; import java.math.BigDecimal; import java.math.RoundingMode; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; @@ -56,12 +57,19 @@ private final TErpClinicWarehousingBatchService erpClinicWarehousingBatchService; private final TCrmSupplierService crmSupplierService; private final TErpMaintenanceReminderService erpMaintenanceReminderService; private final TSysOtherConfigService sysOtherConfigService; private final TCrmClinicPointsService crmClinicPointsService; private final TCrmChangePointsService crmChangePointsService; private final TCrmBranchService crmBranchService; private final TCrmSalespersonService crmSalespersonService; private final TErpProcurementCommissionService erpProcurementCommissionService; @Autowired public TErpProcurementController(TErpProcurementService erpProcurementService, TokenService tokenService,TCrmClinicService crmClinicService,TErpProcurementGoodsService erpProcurementGoodsService , TErpGoodsService erpGoodsService,TErpClinicWarehousingService erpClinicWarehousingService,TErpClinicWarehousingBatchService erpClinicWarehousingBatchService, TCrmSupplierService crmSupplierService,TErpMaintenanceReminderService erpMaintenanceReminderService) { public TErpProcurementController(TErpProcurementService erpProcurementService, TokenService tokenService, TCrmClinicService crmClinicService, TErpProcurementGoodsService erpProcurementGoodsService , TErpGoodsService erpGoodsService, TErpClinicWarehousingService erpClinicWarehousingService, TErpClinicWarehousingBatchService erpClinicWarehousingBatchService, TCrmSupplierService crmSupplierService, TErpMaintenanceReminderService erpMaintenanceReminderService, TSysOtherConfigService sysOtherConfigService, TCrmClinicPointsService crmClinicPointsService, TCrmChangePointsService crmChangePointsService, TCrmBranchService crmBranchService, TCrmSalespersonService crmSalespersonService, TErpProcurementCommissionService erpProcurementCommissionService) { this.erpProcurementService = erpProcurementService; this.tokenService = tokenService; this.crmClinicService = crmClinicService; @@ -71,6 +79,13 @@ this.erpClinicWarehousingBatchService = erpClinicWarehousingBatchService; this.crmSupplierService = crmSupplierService; this.erpMaintenanceReminderService = erpMaintenanceReminderService; this.sysOtherConfigService = sysOtherConfigService; this.crmClinicPointsService = crmClinicPointsService; this.crmChangePointsService = crmChangePointsService; this.crmBranchService = crmBranchService; this.crmSalespersonService = crmSalespersonService; this.erpProcurementCommissionService = erpProcurementCommissionService; } @@ -198,9 +213,10 @@ SysUser user = tokenService.getLoginUser().getUser(); Integer roleType = user.getRoleType(); String clinicSupplierId=null; TCrmClinic crmClinic = null; if(roleType == 5){ // 诊所 TCrmClinic crmClinic = crmClinicService.getOne(Wrappers.lambdaQuery(TCrmClinic.class) crmClinic = crmClinicService.getOne(Wrappers.lambdaQuery(TCrmClinic.class) .eq(TCrmClinic::getUserId, user.getUserId()) .last("LIMIT 1")); clinicSupplierId = crmClinic.getId(); @@ -266,6 +282,94 @@ } BigDecimal payMoney = erpProcurement.getPayMoney(); // 诊所添加积分 分公司添加积分 业务员添加积分 分公司添加分佣记录 业务员添加分佣记录 TSysOtherConfig sysOtherConfig= sysOtherConfigService.getById(1); if(sysOtherConfig!=null && sysOtherConfig.getPointsExpiration()!=null){ Integer pointsExpiration = sysOtherConfig.getPointsExpiration(); if(sysOtherConfig.getExpireUnit().equals(2)){ pointsExpiration = pointsExpiration * 31; } if(sysOtherConfig.getExpireUnit().equals(3)){ pointsExpiration = pointsExpiration * 365; } Double procurementConditions = sysOtherConfig.getProcurementConditions(); // 积分数 int points = payMoney.divide(BigDecimal.valueOf(procurementConditions), 2, RoundingMode.HALF_DOWN).intValue(); TCrmClinicPoints tCrmClinicPoints = new TCrmClinicPoints(); tCrmClinicPoints.setClinicId(erpProcurement.getClinicId()); tCrmClinicPoints.setPoints(points); tCrmClinicPoints.setExpireTime(LocalDateTime.now().plusDays(pointsExpiration)); crmClinicPointsService.save(tCrmClinicPoints); TCrmChangePoints tCrmChangePoints = new TCrmChangePoints(); tCrmChangePoints.setProcurementId(erpProcurement.getId()); tCrmChangePoints.setBranchSalespersonId(erpProcurement.getClinicId()); tCrmChangePoints.setUserType(3); tCrmChangePoints.setChangeType(1); tCrmChangePoints.setChangeReason(1); tCrmChangePoints.setChangeValue(points); crmChangePointsService.save(tCrmChangePoints); } String branchId = crmClinic.getBranchId(); TCrmBranch branch = crmBranchService.getById(branchId); if(branch!=null){ // 积分数 int points = payMoney.divide(branch.getPointsCommission(), 2, RoundingMode.HALF_DOWN).intValue(); TCrmChangePoints tCrmChangePoints = new TCrmChangePoints(); tCrmChangePoints.setProcurementId(erpProcurement.getId()); tCrmChangePoints.setBranchSalespersonId(branchId); tCrmChangePoints.setUserType(1); tCrmChangePoints.setChangeType(1); tCrmChangePoints.setChangeReason(1); tCrmChangePoints.setChangeValue(points); crmChangePointsService.save(tCrmChangePoints); // 分佣 BigDecimal commission = branch.getMoneyCommission().divide(BigDecimal.valueOf(100), 4, RoundingMode.HALF_DOWN).multiply(payMoney).setScale(2, RoundingMode.HALF_UP); TErpProcurementCommission tErpProcurementCommission = new TErpProcurementCommission(); tErpProcurementCommission.setProcurementId(erpProcurement.getId()); tErpProcurementCommission.setCommissionType(1); tErpProcurementCommission.setBranchSalespersonId(branchId); tErpProcurementCommission.setMoney(commission.doubleValue()); erpProcurementCommissionService.save(tErpProcurementCommission); } String salespersonId = crmClinic.getSalespersonId(); TCrmSalesperson salesperson = crmSalespersonService.getById(salespersonId); if(salesperson!=null){ // 积分数 int points = payMoney.divide(salesperson.getPointsCommission(), 2, RoundingMode.HALF_DOWN).intValue(); TCrmChangePoints tCrmChangePoints = new TCrmChangePoints(); tCrmChangePoints.setProcurementId(erpProcurement.getId()); tCrmChangePoints.setBranchSalespersonId(salespersonId); tCrmChangePoints.setUserType(2); tCrmChangePoints.setChangeType(1); tCrmChangePoints.setChangeReason(1); tCrmChangePoints.setChangeValue(points); crmChangePointsService.save(tCrmChangePoints); // 分佣 BigDecimal commission = salesperson.getMoneyCommission().divide(BigDecimal.valueOf(100), 4, RoundingMode.HALF_DOWN).multiply(payMoney).setScale(2, RoundingMode.HALF_UP); TErpProcurementCommission tErpProcurementCommission = new TErpProcurementCommission(); tErpProcurementCommission.setProcurementId(erpProcurement.getId()); tErpProcurementCommission.setCommissionType(2); tErpProcurementCommission.setBranchSalespersonId(salespersonId); tErpProcurementCommission.setMoney(commission.doubleValue()); erpProcurementCommissionService.save(tErpProcurementCommission); } return R.ok(); } @@ -276,5 +380,6 @@ } ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TOrderController.java
New file @@ -0,0 +1,683 @@ package com.ruoyi.web.controller.api; import cn.hutool.http.HttpRequest; import cn.hutool.http.HttpUtil; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.lkl.laop.sdk.exception.SDKException; import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.domain.entity.SysUser; import com.ruoyi.common.utils.DateUtils; import com.ruoyi.common.utils.ip.IpUtils; import com.ruoyi.framework.web.service.TokenService; import com.ruoyi.system.model.TCrmSupplier; import com.ruoyi.system.model.TErpProcurement; import com.ruoyi.system.model.TErpProcurementGoods; import com.ruoyi.system.service.TCrmSupplierService; import com.ruoyi.system.service.TErpProcurementGoodsService; import com.ruoyi.system.service.TErpProcurementService; import com.ruoyi.web.core.config.LakalaConfig; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.SneakyThrows; import org.apache.commons.codec.binary.Base64; import org.apache.commons.io.IOUtils; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpPost; import org.apache.http.conn.ClientConnectionManager; import org.apache.http.conn.scheme.Scheme; import org.apache.http.conn.scheme.SchemeRegistry; import org.apache.http.conn.ssl.SSLSocketFactory; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.DefaultHttpClient; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import javax.servlet.http.HttpServletRequest; import java.io.*; import java.math.BigDecimal; import java.math.RoundingMode; import java.nio.charset.StandardCharsets; import java.security.*; import java.security.cert.*; import java.security.spec.InvalidKeySpecException; import java.security.spec.PKCS8EncodedKeySpec; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; /** * <p> * 订单管理 前端控制器 * </p> * * @author xiaochen * @since 2025-08-20 */ @RestController @RequestMapping("/t-sys-order") @Api(tags = "支付管理") public class TOrderController { private final TErpProcurementService erpProcurementService; private final TErpProcurementGoodsService erpProcurementGoodsService; private final TCrmSupplierService crmSupplierService; private final TokenService tokenService; @Autowired public TOrderController(TErpProcurementService erpProcurementService, TokenService tokenService, TErpProcurementGoodsService erpProcurementGoodsService, TCrmSupplierService crmSupplierService) { this.erpProcurementService = erpProcurementService; this.tokenService = tokenService; this.erpProcurementGoodsService = erpProcurementGoodsService; this.crmSupplierService = crmSupplierService; } private static final String SYMBOLS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; /** * API schema ,固定 LKLAPI-SHA256withRSA */ public final static String SCHEMA = "LKLAPI-SHA256withRSA"; /** * 字符集固定 utf-8 */ public static final String ENCODING = "utf-8"; private static final SecureRandom RANDOM = new SecureRandom(); @ApiOperation(value = "支付") @PostMapping(value = "/payOrder") @SneakyThrows public R<?> payOrder(@RequestParam String id, String type, HttpServletRequest request) { try { // 查出采购单 算出价格 下单 算出应该分佣金额 应该分给谁 TErpProcurement erpProcurement = erpProcurementService.getById(id); if (erpProcurement.getStatus()>2) { return R.fail("订单已支付"); } String ipAddr = IpUtils.getIpAddr(request); String time = DateUtils.dateTimeNow(); // SYMBOLS 随机取4位数 String nonce = ""; for (int i = 0; i < 6; i++) { nonce += SYMBOLS.charAt(RANDOM.nextInt(SYMBOLS.length())); } String outTradeNo = time + nonce; String amount = String.valueOf(erpProcurement.getPayMoney().multiply(new BigDecimal("100")).intValue()); TCrmSupplier supplier = crmSupplierService.getById(erpProcurement.getSupplierId()); String trans_type ="41"; if("WECHAT".equals(type)){ trans_type= "51"; } String apiPath = "sit/api/v3/labs/trans/preorder"; String body = "{\n" + "\t\"req_time\": \"" + time + "\",\n" + "\t\"version\": \"3.0\",\n" + "\t\"req_data\": {\n" + "\t\t\"out_trade_no\": \"" + outTradeNo + "\",\n" + "\t\t\"merchant_no\": \""+supplier.getRecvMerchantNo()+"\",\n" + "\t\t\"term_no\": \""+supplier.getTermNo()+"\",\n" + "\t\t\"notify_url\": \"http://221.182.45.100:8089/t-sys-order/messageHandle\",\n" + "\t\t\"location_info\": {\n" + "\t\t\t\"request_ip\": \"" + ipAddr + "\"\n" + "\t\t},\n" + "\t\t\"subject\": \"商品采购\",\n" + "\t\t\"settle_type\": \"1\",\n" + "\t\t\"total_amount\": " + amount + ",\n" + "\t\t\"account_type\": \"" + type + "\",\n" + "\t\t\"trans_type\": \""+trans_type+"\"\n" + "\t}\n" + "}"; String authorization = getAuthorization(body); System.err.println("支付请求"+body); org.apache.http.HttpResponse response = post(LakalaConfig.getServerUrl() + apiPath, body, authorization); if (response.getStatusLine().getStatusCode() != 200) { return R.fail(500, "请求失败,statusCode " + response.getStatusLine() + IOUtils.toString(response.getEntity().getContent(), ENCODING)); } String responseStr = IOUtils.toString(response.getEntity().getContent(), ENCODING); System.err.println("支付结果"+responseStr); erpProcurement.setPayNumber(outTradeNo); JSONObject jsonObject = JSONObject.parseObject(responseStr); JSONObject jsonObject1 = jsonObject.getJSONObject("resp_data"); String code = jsonObject1.getString("log_no"); erpProcurement.setPayTransactionId(code); erpProcurement.setStatus(2); erpProcurement.setTermNo(supplier.getTermNo()); erpProcurement.setAccountType(type); erpProcurement.setTransType(trans_type); erpProcurementService.updateById(erpProcurement); return R.ok(responseStr); } catch (SDKException e) { e.printStackTrace(); } return R.fail(500, "调用支付宝支付预下单接口错误"); } @RequestMapping("/messageHandle") @ApiOperation(value = "拉卡拉支付信息回调接口") public Object messageHandle(HttpServletRequest request) throws Exception { String body = this.getBody(request); String authorization = request.getHeader("Authorization"); String timestamp = null; String nonce = null; String signature = null; authorization = authorization.replaceAll("LKLAPI-SHA256withRSA ", ""); String[] split = authorization.split(","); for (String s : split) { if (s.startsWith("timestamp")) { timestamp = s.split("=")[1].replaceAll("\"", ""); } if (s.startsWith("nonce")) { nonce = s.split("=")[1].replaceAll("\"", ""); } if (s.startsWith("signature")) { // 取出签名 signature = s.split("signature=")[1].replaceAll("\"", ""); } } X509Certificate lklCertificate = loadCertificate(new FileInputStream(new File(LakalaConfig.getLklNotifyCerStr()))); String preSignData = timestamp + "\n" + nonce + "\n" + body + "\n"; boolean verify = verify(lklCertificate, preSignData.getBytes(ENCODING), signature); // 先处理支付完成 修改状态 后处理分账 后走分账回调 JSONObject jsonObject1 = JSONObject.parseObject(body); Object o = jsonObject1.get("out_trade_no"); TErpProcurement erpProcurement = erpProcurementService.getOne(new LambdaQueryWrapper<TErpProcurement>().eq(TErpProcurement::getPayNumber, o)); if (verify && erpProcurement.getStatus()==2) { erpProcurement.setPayTime(LocalDateTime.now()); erpProcurement.setStatus(3); List<TErpProcurementGoods> list = erpProcurementGoodsService.list(new LambdaQueryWrapper<TErpProcurementGoods>().eq(TErpProcurementGoods::getProcurementId, erpProcurement.getId())); // 操作分账 HttpRequest post = HttpUtil.createPost(LakalaConfig.getServerUrl() + "sit/api/v3/sacs/separate"); HashMap<String, Object> reqMap = new HashMap<>(); reqMap.put("version", "3.0"); reqMap.put("req_time", DateUtils.dateTimeNow()); HashMap<String, Object> map = new HashMap<>(); map.put("merchant_no", erpProcurement.getMerchantNo()); map.put("log_no", erpProcurement.getPayTransactionId()); map.put("log_date", DateUtils.dateTime()); map.put("cal_type", "0"); map.put("notify_url", "http://221.182.45.100:8089/t-sys-order/messageSeparateHandle"); String time = DateUtils.dateTimeNow(); // SYMBOLS 随机取4位数 String str = ""; for (int i = 0; i < 6; i++) { str += SYMBOLS.charAt(RANDOM.nextInt(SYMBOLS.length())); } String outTradeNo = time + str; map.put("out_separate_no", outTradeNo); map.put("total_amt", erpProcurement.getPayMoney().multiply(BigDecimal.valueOf(100)).intValue() + ""); BigDecimal allMoney = erpProcurement.getPayMoney(); // 平台应得分账 BigDecimal payMoney = erpProcurement.getMoney(); ArrayList<HashMap<String, Object>> objects = new ArrayList<>(); HashMap<String, Object> map1 = new HashMap<>(); //TODO hzt map1.put("recv_no", "SR2024021195402"); // 手续费 BigDecimal bigDecimal = allMoney.multiply(new BigDecimal("0.038")).setScale(2, RoundingMode.HALF_UP); payMoney = payMoney.subtract(bigDecimal); map1.put("separate_value", payMoney.multiply(BigDecimal.valueOf(100)).intValue() + ""); if(payMoney.doubleValue()>0){ objects.add(map1); } // 根据供应商id分组 Map<String, List<TErpProcurementGoods>> collect = list.stream().collect(Collectors.groupingBy(TErpProcurementGoods::getSupplierId)); for (Map.Entry<String, List<TErpProcurementGoods>> entry : collect.entrySet()) { HashMap<String, Object> map2 = new HashMap<>(); String supplierId = entry.getKey(); TCrmSupplier supplier = crmSupplierService.getById(supplierId); // List<TErpProcurementGoods> value = entry.getValue(); // BigDecimal reduce = value.stream().map(TErpProcurementGoods::getSupplierMoney).reduce(BigDecimal.ZERO, BigDecimal::add); // payMoney = payMoney.subtract(reduce); map2.put("recv_merchant_no", supplier.getRecvMerchantNo()); int count = allMoney.subtract(payMoney).multiply(BigDecimal.valueOf(100)).intValue(); if(count>0){ map2.put("separate_value", count+ ""); objects.add(map2); } } erpProcurement.setMoney(payMoney); erpProcurement.setOutSeparateNo(outTradeNo); erpProcurementService.updateById(erpProcurement); // 添加平台的 map.put("recv_datas", objects); reqMap.put("req_data", map); String jsonString = JSON.toJSONString(reqMap); // String authorization1 = getAuthorization(jsonString); // post.header("Authorization", SCHEMA + " " + authorization); // // post.body(jsonString); // HttpResponse response = post.execute(); // String responseStr = response.body(); String authorization1 = getAuthorization(jsonString); org.apache.http.HttpResponse response1 = post(LakalaConfig.getServerUrl() + "sit/api/v3/sacs/separate", jsonString, authorization1); String responseStr = IOUtils.toString(response1.getEntity().getContent(), ENCODING); JSONObject jsonObject = JSONObject.parseObject(responseStr); if ("成功".equals(jsonObject.getString("msg"))) { Object o1 = jsonObject.get("resp_data"); JSONObject jsonObject2 = JSONObject.parseObject(o1.toString()); String separate_no = jsonObject2.getString("separate_no"); erpProcurement.setSeparateNo(separate_no); erpProcurementService.updateById(erpProcurement); } // 响应success JSONObject responseJsonObject = new JSONObject(); responseJsonObject.put("code", "SUCCESS"); responseJsonObject.put("message", "执行成功"); return responseJsonObject; } return null; } @RequestMapping("/messageSeparateHandle") @ApiOperation(value = "拉卡拉分账信息回调接口") public Object messageSeparateHandle(HttpServletRequest request) throws Exception { String body = this.getBody(request); // 先处理支付完成 修改状态 后处理分账 后走分账回调 JSONObject jsonObject1 = JSONObject.parseObject(body); Object o = jsonObject1.get("out_separate_no"); Object status = jsonObject1.get("status"); Object cmd_type = jsonObject1.get("cmd_type"); Object detail_datas = jsonObject1.get("detail_datas"); JSONArray jsonArray = JSONArray.parseArray(detail_datas.toString()); if("SEPARATE".equals(cmd_type.toString())){ TErpProcurement erpProcurement = erpProcurementService.getOne(new LambdaQueryWrapper<TErpProcurement>().eq(TErpProcurement::getOutSeparateNo, o.toString())); if ( erpProcurement!=null && "SUCCESS".equals(status) && erpProcurement.getRefundStatus()!=1) { erpProcurement.setRefundStatus(1); erpProcurementService.updateById(erpProcurement); // 修改分账状态 List<TErpProcurementGoods> list1 = erpProcurementGoodsService.list(new LambdaQueryWrapper<TErpProcurementGoods>().eq(TErpProcurementGoods::getProcurementId, erpProcurement.getId())); list1.stream().forEach(e->e.setStatus(1)); erpProcurementGoodsService.updateBatchById(list1); // 响应success JSONObject jsonObject = new JSONObject(); jsonObject.put("code", "SUCCESS"); jsonObject.put("message", "执行成功"); return jsonObject; } }else if("FALLBACK".equals(cmd_type.toString())){ TErpProcurement erpProcurement = erpProcurementService.getOne(new LambdaQueryWrapper<TErpProcurement>().eq(TErpProcurement::getRefundOutSeparateNo, o.toString())); if ( erpProcurement!=null && "SUCCESS".equals(status) && erpProcurement.getRefundStatus()!=2) { erpProcurement.setRefundStatus(2); erpProcurementService.updateById(erpProcurement); List<TErpProcurementGoods> list1 = erpProcurementGoodsService.list(new LambdaQueryWrapper<TErpProcurementGoods>().eq(TErpProcurementGoods::getProcurementId, erpProcurement.getId())); list1.stream().forEach(e->e.setStatus(2)); erpProcurementGoodsService.updateBatchById(list1); // 发起退款 String time = DateUtils.dateTimeNow(); String ipAddr = IpUtils.getIpAddr(request); // SYMBOLS 随机取4位数 String str = ""; for (int i = 0; i < 6; i++) { str += SYMBOLS.charAt(RANDOM.nextInt(SYMBOLS.length())); } String outTradeNo = time + str; String refund_amount = erpProcurement.getPayMoney().multiply(BigDecimal.valueOf(100)).intValue() + ""; String apiPath = "sit/api/v3/rfd/refund_front/refund"; String body1 = "{\n" + "\t\"req_time\": \"" + time + "\",\n" + "\t\"version\": \"3.0\",\n" + "\t\"req_data\": {\n" + "\t\t\"merchant_no\": \""+erpProcurement.getMerchantNo()+"\",\n" + "\t\t\"term_no\": \""+erpProcurement.getTermNo()+"\",\n" + "\t\t\"refund_amount\": " + refund_amount + ",\n" + "\t\t\"out_trade_no\": \"" + outTradeNo + "\",\n" + "\t\t\"notify_url\": \"" + "http://221.182.45.100:8089/t-sys-order/messageRefundHandle" + "\",\n" + "\t\t\"origin_log_no\": \"" + erpProcurement.getPayTransactionId() + "\",\n" + "\t\t\"location_info\": {\n" + "\t\t\t\"request_ip\": \"" + ipAddr + "\"\n" + "\t\t},\n" + "\t}\n" + "}"; String authorization = getAuthorization(body1); org.apache.http.HttpResponse response = post(LakalaConfig.getServerUrl() + apiPath, body1, authorization); if (response.getStatusLine().getStatusCode() != 200) { return R.fail(500, "请求失败,statusCode " + response.getStatusLine() + IOUtils.toString(response.getEntity().getContent(), ENCODING)); } String responseStr = IOUtils.toString(response.getEntity().getContent(), ENCODING); JSONObject jsonObject = JSONObject.parseObject(responseStr); JSONObject jsonObject2 = jsonObject.getJSONObject("resp_data"); String code = jsonObject2.getString("log_no"); erpProcurement.setRefundLogNo(code); erpProcurement.setRefundNo(outTradeNo); erpProcurementService.updateById(erpProcurement); // 响应success JSONObject jsonObject3 = new JSONObject(); jsonObject3.put("code", "SUCCESS"); jsonObject3.put("message", "执行成功"); return jsonObject3; } } return null; } @RequestMapping("/messageRefundHandle") @ApiOperation(value = "拉卡拉退款信息回调接口") public Object messageRefundHandle(HttpServletRequest request) throws Exception { String body = this.getBody(request); // 先处理支付完成 修改状态 后处理分账 后走分账回调 JSONObject jsonObject1 = JSONObject.parseObject(body); Object status = jsonObject1.get("trade_status"); Object out_trade_no = jsonObject1.get("out_trade_no"); if(status !=null && "SUCCESS".equals(status.toString())){ TErpProcurement erpProcurement = erpProcurementService.getOne(new LambdaQueryWrapper<TErpProcurement>().eq(TErpProcurement::getRefundNo, out_trade_no.toString())); if ( erpProcurement!=null && "SUCCESS".equals(status)) { erpProcurement.setStatus(6); erpProcurementService.updateById(erpProcurement); // 响应success JSONObject jsonObject = new JSONObject(); jsonObject.put("code", "SUCCESS"); jsonObject.put("message", "执行成功"); return jsonObject; } } return null; } @ApiOperation(value = "退款") @PostMapping(value = "/refundOrder") @SneakyThrows public R<?> refundOrder(@RequestParam String id, HttpServletRequest request) { SysUser user = tokenService.getLoginUser().getUser(); try { // 先退分账 在退订单 // 查出采购单 算出价格 下单 算出应该分佣金额 应该分给谁 TErpProcurement erpProcurement = erpProcurementService.getById(id); // 还未分账成功不能退款 if(erpProcurement.getStatus()==null || erpProcurement.getStatus()!=1){ return R.fail("订单处理中,请稍后操作"); } String time = DateUtils.dateTimeNow(); // SYMBOLS 随机取4位数 String str = ""; for (int i = 0; i < 6; i++) { str += SYMBOLS.charAt(RANDOM.nextInt(SYMBOLS.length())); } String outTradeNo = time + str; // 操作分账 // HttpRequest post = HttpUtil.createPost(LakalaConfig.getServerUrl() + "sit/api/v3/sacs/fallback"); HashMap<String, Object> reqMap = new HashMap<>(); reqMap.put("version", "3.0"); reqMap.put("req_time", DateUtils.dateTimeNow()); HashMap<String, Object> map = new HashMap<>(); map.put("merchant_no", erpProcurement.getMerchantNo()); map.put("origin_separate_no", erpProcurement.getSeparateNo()); map.put("out_separate_no",outTradeNo); erpProcurement.setRefundOutSeparateNo(outTradeNo); erpProcurementService.updateById(erpProcurement); // List<TErpProcurementGoods> list = erpProcurementGoodsService.list(new LambdaQueryWrapper<TErpProcurementGoods>().eq(TErpProcurementGoods::getProcurementId, erpProcurement.getId())); // 根据供应商id分组 // Map<String, List<TErpProcurementGoods>> collect = list.stream().collect(Collectors.groupingBy(TErpProcurementGoods::getSupplierId)); ArrayList<HashMap<String, Object>> objects = new ArrayList<>(); // BigDecimal allMoney = list.stream().map(TErpProcurementGoods::getSupplierMoney).reduce(BigDecimal.ZERO, BigDecimal::add); // for (Map.Entry<String, List<TErpProcurementGoods>> entry : collect.entrySet()) { // // List<TErpProcurementGoods> value = entry.getValue(); // BigDecimal reduce = value.stream().map(TErpProcurementGoods::getSupplierMoney).reduce(BigDecimal.ZERO, BigDecimal::add); // String recv_no = value.stream().map(TErpProcurementGoods::getRecvNo).collect(Collectors.toList()).get(0); // } HashMap<String, Object> map1 = new HashMap<>(); // TODO hzt map1.put("recv_no", "SR2024021195402"); map1.put("amt", erpProcurement.getMoney().multiply(BigDecimal.valueOf(100)).intValue() + ""); objects.add(map1); map.put("total_amt",erpProcurement.getMoney().multiply(BigDecimal.valueOf(100)).intValue() + ""); map.put("origin_recv_datas",objects); reqMap.put("req_data", map); String jsonString = JSON.toJSONString(reqMap); String authorization1 = getAuthorization(jsonString); org.apache.http.HttpResponse response1 = post(LakalaConfig.getServerUrl() + "sit/api/v3/sacs/fallback", jsonString, authorization1); String responseStr = IOUtils.toString(response1.getEntity().getContent(), ENCODING); // post.body(jsonString); // HttpResponse response = post.execute(); // String responseStr = response.body(); return R.ok(responseStr); } catch (Exception e) { e.printStackTrace(); } return R.fail(500, "退款失败请联系平台管理员"); } public org.apache.http.HttpResponse post(String url, String message, String authorization) throws Exception { SSLContext ctx = SSLContext.getInstance("TLS"); X509TrustManager tm = new X509TrustManager() { public X509Certificate[] getAcceptedIssuers() { return null; } public void checkClientTrusted(X509Certificate[] xcs, String str) { } public void checkServerTrusted(X509Certificate[] xcs, String str) { } }; HttpClient http = new DefaultHttpClient(); ClientConnectionManager ccm = http.getConnectionManager(); ctx.init(null, new TrustManager[]{tm}, null); SSLSocketFactory ssf = new SSLSocketFactory(ctx); ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); SchemeRegistry registry = ccm.getSchemeRegistry(); registry.register(new Scheme("https", ssf, 443)); HttpPost post = new HttpPost(url); StringEntity myEntity = new StringEntity(message, ENCODING); post.setEntity(myEntity); post.setHeader("Authorization", SCHEMA + " " + authorization); post.setHeader("Accept", "application/json"); post.setHeader("Content-Type", "application/json"); return http.execute(post); } public final String getAuthorization(String body) throws IOException { String nonceStr = generateNonceStr(); long timestamp = generateTimestamp(); String message = LakalaConfig.getAppId() + "\n" + LakalaConfig.getMerchantNo() + "\n" + timestamp + "\n" + nonceStr + "\n" + body + "\n"; System.out.println("getToken message : " + message); PrivateKey merchantPrivateKey = loadPrivateKey(new FileInputStream(new File(LakalaConfig.getPriKeyStr()))); String signature = this.sign(message.getBytes(ENCODING), merchantPrivateKey); String authorization = "appid=\"" + LakalaConfig.getAppId() + "\"," + "serial_no=\"" + LakalaConfig.getMerchantNo() + "\"," + "timestamp=\"" + timestamp + "\"," + "nonce_str=\"" + nonceStr + "\"," + "signature=\"" + signature + "\""; System.out.println("authorization message :" + authorization); return authorization; } public long generateTimestamp() { return System.currentTimeMillis() / 1000; } public String generateNonceStr() { char[] nonceChars = new char[32]; for (int index = 0; index < nonceChars.length; ++index) { nonceChars[index] = SYMBOLS.charAt(RANDOM.nextInt(SYMBOLS.length())); } return new String(nonceChars); } public static PrivateKey loadPrivateKey(InputStream inputStream) { try { ByteArrayOutputStream array = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int length; while ((length = inputStream.read(buffer)) != -1) { array.write(buffer, 0, length); } String privateKey = array.toString("utf-8").replace("-----BEGIN PRIVATE KEY-----", "") .replace("-----END PRIVATE KEY-----", "").replaceAll("\\s+", ""); KeyFactory kf = KeyFactory.getInstance("RSA"); return kf.generatePrivate(new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKey))); } catch (NoSuchAlgorithmException e) { throw new RuntimeException("当前Java环境不支持RSA", e); } catch (InvalidKeySpecException e) { throw new RuntimeException("无效的密钥格式"); } catch (IOException e) { throw new RuntimeException("无效的密钥"); } } public String sign(byte[] message, PrivateKey privateKey) { try { Signature sign = Signature.getInstance("SHA256withRSA"); sign.initSign(privateKey); sign.update(message); return new String(Base64.encodeBase64(sign.sign())); } catch (NoSuchAlgorithmException e) { throw new RuntimeException("当前Java环境不支持SHA256withRSA", e); } catch (SignatureException e) { throw new RuntimeException("签名计算失败", e); } catch (InvalidKeyException e) { throw new RuntimeException("无效的私钥", e); } } public final String getBody(HttpServletRequest request) { InputStreamReader in = null; try { in = new InputStreamReader(request.getInputStream(), StandardCharsets.UTF_8); StringBuffer bf = new StringBuffer(); int len; char[] chs = new char[1024]; while ((len = in.read(chs)) != -1) { bf.append(new String(chs, 0, len)); } return bf.toString(); } catch (Exception e) { e.printStackTrace(); } finally { if (null != in) { try { in.close(); } catch (Exception e) { } } } return null; } public static X509Certificate loadCertificate(InputStream inputStream) { try { CertificateFactory cf = CertificateFactory.getInstance("X509"); X509Certificate cert = (X509Certificate) cf.generateCertificate(inputStream); cert.checkValidity(); return cert; } catch (CertificateExpiredException e) { throw new RuntimeException("证书已过期", e); } catch (CertificateNotYetValidException e) { throw new RuntimeException("证书尚未生效", e); } catch (CertificateException e) { throw new RuntimeException("无效的证书", e); } } private static boolean verify(X509Certificate certificate, byte[] message, String signature) { try { Signature sign = Signature.getInstance("SHA256withRSA"); sign.initVerify(certificate); sign.update(message); byte[] signatureB = Base64.decodeBase64(signature); return sign.verify(signatureB); } catch (NoSuchAlgorithmException e) { throw new RuntimeException("当前Java环境不支持SHA256withRSA", e); } catch (SignatureException e) { throw new RuntimeException("签名验证过程发生了错误", e); } catch (InvalidKeyException e) { throw new RuntimeException("无效的证书", e); } } } ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TSysOrderController.java
@@ -8,17 +8,23 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.lkl.laop.sdk.exception.SDKException; import com.ruoyi.common.basic.PageInfo; import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.domain.entity.SysUser; import com.ruoyi.common.utils.DateUtils; import com.ruoyi.common.utils.ip.IpUtils; import com.ruoyi.framework.web.service.TokenService; import com.ruoyi.system.model.TCrmSupplier; import com.ruoyi.system.model.TErpProcurement; import com.ruoyi.system.model.TErpProcurementGoods; import com.ruoyi.system.dto.TSysOrderDto; import com.ruoyi.system.model.*; import com.ruoyi.system.query.TErpGoodsWarehouseQuery; import com.ruoyi.system.query.TSysAppUserQuery; import com.ruoyi.system.query.TSysEducationalInfoQuery; import com.ruoyi.system.query.TSysOrderQuery; import com.ruoyi.system.service.*; import com.ruoyi.system.vo.TSysOrderDetailVo; import com.ruoyi.system.vo.TSysOrderPageVo; import com.ruoyi.web.core.config.LakalaConfig; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; @@ -68,605 +74,99 @@ * @since 2025-08-20 */ @RestController @RequestMapping("/t-sys-order") @RequestMapping("") @Api(tags = "订单管理") public class TSysOrderController { private final TErpProcurementService erpProcurementService; private final TErpProcurementGoodsService erpProcurementGoodsService; private final TCrmSupplierService crmSupplierService; private final TSysOrderService sysOrderService; private final TokenService tokenService; private final TCrmClinicService crmClinicService; private final TSysAppUserService sysAppUserService; private final TSysOrderGoodsService sysOrderGoodsService; @Autowired public TSysOrderController(TErpProcurementService erpProcurementService, TokenService tokenService, TErpProcurementGoodsService erpProcurementGoodsService, TCrmSupplierService crmSupplierService) { this.erpProcurementService = erpProcurementService; public TSysOrderController(TokenService tokenService, TSysOrderService sysOrderService, TCrmClinicService crmClinicService, TSysAppUserService sysAppUserService, TSysOrderGoodsService sysOrderGoodsService) { this.sysOrderService = sysOrderService; this.tokenService = tokenService; this.erpProcurementGoodsService = erpProcurementGoodsService; this.crmSupplierService = crmSupplierService; } this.crmClinicService = crmClinicService; this.sysAppUserService = sysAppUserService; this.sysOrderGoodsService = sysOrderGoodsService; private static final String SYMBOLS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; } /** * API schema ,固定 LKLAPI-SHA256withRSA * 获取诊所患者诊疗 订单列表 */ public final static String SCHEMA = "LKLAPI-SHA256withRSA"; @ApiOperation(value = "获取诊所患者诊疗订单列表") @PostMapping(value = "/pageList") public R<PageInfo<TSysOrderPageVo>> pageList(@RequestBody TSysOrderQuery query) { /** * 字符集固定 utf-8 */ public static final String ENCODING = "utf-8"; private static final SecureRandom RANDOM = new SecureRandom(); @ApiOperation(value = "支付") @PostMapping(value = "/payOrder") @SneakyThrows public R<?> payOrder(@RequestParam String id, String type, HttpServletRequest request) { try { // 查出采购单 算出价格 下单 算出应该分佣金额 应该分给谁 TErpProcurement erpProcurement = erpProcurementService.getById(id); if (erpProcurement.getStatus()>2) { return R.fail("订单已支付"); } String ipAddr = IpUtils.getIpAddr(request); String time = DateUtils.dateTimeNow(); // SYMBOLS 随机取4位数 String nonce = ""; for (int i = 0; i < 6; i++) { nonce += SYMBOLS.charAt(RANDOM.nextInt(SYMBOLS.length())); } String outTradeNo = time + nonce; String amount = String.valueOf(erpProcurement.getPayMoney().multiply(new BigDecimal("100")).intValue()); TCrmSupplier supplier = crmSupplierService.getById(erpProcurement.getSupplierId()); String trans_type ="41"; if("WECHAT".equals(type)){ trans_type= "51"; } String apiPath = "sit/api/v3/labs/trans/preorder"; String body = "{\n" + "\t\"req_time\": \"" + time + "\",\n" + "\t\"version\": \"3.0\",\n" + "\t\"req_data\": {\n" + "\t\t\"out_trade_no\": \"" + outTradeNo + "\",\n" + "\t\t\"merchant_no\": \""+supplier.getRecvMerchantNo()+"\",\n" + "\t\t\"term_no\": \""+supplier.getTermNo()+"\",\n" + "\t\t\"notify_url\": \"http://221.182.45.100:8089/t-sys-order/messageHandle\",\n" + "\t\t\"location_info\": {\n" + "\t\t\t\"request_ip\": \"" + ipAddr + "\"\n" + "\t\t},\n" + "\t\t\"subject\": \"商品采购\",\n" + "\t\t\"settle_type\": \"1\",\n" + "\t\t\"total_amount\": " + amount + ",\n" + "\t\t\"account_type\": \"" + type + "\",\n" + "\t\t\"trans_type\": \""+trans_type+"\"\n" + "\t}\n" + "}"; String authorization = getAuthorization(body); org.apache.http.HttpResponse response = post(LakalaConfig.getServerUrl() + apiPath, body, authorization); if (response.getStatusLine().getStatusCode() != 200) { return R.fail(500, "请求失败,statusCode " + response.getStatusLine() + IOUtils.toString(response.getEntity().getContent(), ENCODING)); } String responseStr = IOUtils.toString(response.getEntity().getContent(), ENCODING); erpProcurement.setPayNumber(outTradeNo); JSONObject jsonObject = JSONObject.parseObject(responseStr); JSONObject jsonObject1 = jsonObject.getJSONObject("resp_data"); String code = jsonObject1.getString("log_no"); erpProcurement.setPayTransactionId(code); erpProcurement.setStatus(2); erpProcurement.setTermNo(supplier.getTermNo()); erpProcurement.setAccountType(type); erpProcurement.setTransType(trans_type); erpProcurementService.updateById(erpProcurement); return R.ok(responseStr); } catch (SDKException e) { e.printStackTrace(); } return R.fail(500, "调用支付宝支付预下单接口错误"); } @RequestMapping("/messageHandle") @ApiOperation(value = "拉卡拉支付信息回调接口") public Object messageHandle(HttpServletRequest request) throws Exception { String body = this.getBody(request); String authorization = request.getHeader("Authorization"); String timestamp = null; String nonce = null; String signature = null; authorization = authorization.replaceAll("LKLAPI-SHA256withRSA ", ""); String[] split = authorization.split(","); for (String s : split) { if (s.startsWith("timestamp")) { timestamp = s.split("=")[1].replaceAll("\"", ""); } if (s.startsWith("nonce")) { nonce = s.split("=")[1].replaceAll("\"", ""); } if (s.startsWith("signature")) { // 取出签名 signature = s.split("signature=")[1].replaceAll("\"", ""); } } X509Certificate lklCertificate = loadCertificate(new FileInputStream(new File(LakalaConfig.getLklNotifyCerStr()))); String preSignData = timestamp + "\n" + nonce + "\n" + body + "\n"; boolean verify = verify(lklCertificate, preSignData.getBytes(ENCODING), signature); // 先处理支付完成 修改状态 后处理分账 后走分账回调 JSONObject jsonObject1 = JSONObject.parseObject(body); Object o = jsonObject1.get("out_trade_no"); TErpProcurement erpProcurement = erpProcurementService.getOne(new LambdaQueryWrapper<TErpProcurement>().eq(TErpProcurement::getPayNumber, o)); if (verify && erpProcurement.getStatus()==2) { erpProcurement.setPayTime(LocalDateTime.now()); erpProcurement.setStatus(3); List<TErpProcurementGoods> list = erpProcurementGoodsService.list(new LambdaQueryWrapper<TErpProcurementGoods>().eq(TErpProcurementGoods::getProcurementId, erpProcurement.getId())); // 操作分账 HttpRequest post = HttpUtil.createPost(LakalaConfig.getServerUrl() + "sit/api/v3/sacs/separate"); HashMap<String, Object> reqMap = new HashMap<>(); reqMap.put("version", "3.0"); reqMap.put("req_time", DateUtils.dateTimeNow()); HashMap<String, Object> map = new HashMap<>(); map.put("merchant_no", erpProcurement.getMerchantNo()); map.put("log_no", erpProcurement.getPayTransactionId()); map.put("log_date", DateUtils.dateTime()); map.put("notify_url", "http://221.182.45.100:8089/t-sys-order/messageSeparateHandle"); String time = DateUtils.dateTimeNow(); // SYMBOLS 随机取4位数 String str = ""; for (int i = 0; i < 6; i++) { str += SYMBOLS.charAt(RANDOM.nextInt(SYMBOLS.length())); } String outTradeNo = time + str; map.put("out_separate_no", outTradeNo); map.put("total_amt", erpProcurement.getPayMoney().multiply(BigDecimal.valueOf(100)).intValue() + ""); BigDecimal allMoney = erpProcurement.getPayMoney(); // 平台应得分账 BigDecimal payMoney = erpProcurement.getMoney(); ArrayList<HashMap<String, Object>> objects = new ArrayList<>(); // 根据供应商id分组 Map<String, List<TErpProcurementGoods>> collect = list.stream().collect(Collectors.groupingBy(TErpProcurementGoods::getSupplierId)); // for (Map.Entry<String, List<TErpProcurementGoods>> entry : collect.entrySet()) { // HashMap<String, Object> map1 = new HashMap<>(); // String supplierId = entry.getKey(); // TCrmSupplier supplier = crmSupplierService.getById(supplierId); // List<TErpProcurementGoods> value = entry.getValue(); // BigDecimal reduce = value.stream().map(TErpProcurementGoods::getSupplierMoney).reduce(BigDecimal.ZERO, BigDecimal::add); // payMoney = payMoney.subtract(reduce); // map1.put("recv_no", supplier.getRecvMerchantNo()); // map1.put("separate_value", reduce.multiply(BigDecimal.valueOf(100)).intValue() + ""); //// objects.add(map1); // } HashMap<String, Object> map1 = new HashMap<>(); //TODO hzt map1.put("recv_no", "SR2024000006413"); // 手续费 BigDecimal bigDecimal = allMoney.multiply(new BigDecimal("0.038")).setScale(2, RoundingMode.HALF_UP); payMoney = payMoney.subtract(bigDecimal); map1.put("separate_value", payMoney.multiply(BigDecimal.valueOf(100)).intValue() + ""); if(payMoney.doubleValue()>0){ objects.add(map1); } erpProcurement.setMoney(payMoney); erpProcurement.setOutSeparateNo(outTradeNo); erpProcurementService.updateById(erpProcurement); // 添加平台的 map.put("recv_datas", objects); reqMap.put("req_data", map); String jsonString = JSON.toJSONString(reqMap); // String authorization1 = getAuthorization(jsonString); // post.header("Authorization", SCHEMA + " " + authorization); // // post.body(jsonString); // HttpResponse response = post.execute(); // String responseStr = response.body(); String authorization1 = getAuthorization(jsonString); org.apache.http.HttpResponse response1 = post(LakalaConfig.getServerUrl() + "sit/api/v3/sacs/separate", jsonString, authorization1); String responseStr = IOUtils.toString(response1.getEntity().getContent(), ENCODING); JSONObject jsonObject = JSONObject.parseObject(responseStr); if ("成功".equals(jsonObject.getString("msg"))) { Object o1 = jsonObject.get("resp_data"); JSONObject jsonObject2 = JSONObject.parseObject(o1.toString()); String separate_no = jsonObject2.getString("separate_no"); erpProcurement.setSeparateNo(separate_no); erpProcurementService.updateById(erpProcurement); } // 响应success JSONObject responseJsonObject = new JSONObject(); responseJsonObject.put("code", "SUCCESS"); responseJsonObject.put("message", "执行成功"); return responseJsonObject; } return null; } @RequestMapping("/messageSeparateHandle") @ApiOperation(value = "拉卡拉分账信息回调接口") public Object messageSeparateHandle(HttpServletRequest request) throws Exception { String body = this.getBody(request); // 先处理支付完成 修改状态 后处理分账 后走分账回调 JSONObject jsonObject1 = JSONObject.parseObject(body); Object o = jsonObject1.get("out_separate_no"); Object status = jsonObject1.get("status"); Object cmd_type = jsonObject1.get("cmd_type"); Object detail_datas = jsonObject1.get("detail_datas"); JSONArray jsonArray = JSONArray.parseArray(detail_datas.toString()); if("SEPARATE".equals(cmd_type.toString())){ TErpProcurement erpProcurement = erpProcurementService.getOne(new LambdaQueryWrapper<TErpProcurement>().eq(TErpProcurement::getOutSeparateNo, o.toString())); if ( erpProcurement!=null && "SUCCESS".equals(status)) { erpProcurement.setRefundStatus(1); erpProcurementService.updateById(erpProcurement); // 修改分账状态 List<TErpProcurementGoods> list1 = erpProcurementGoodsService.list(new LambdaQueryWrapper<TErpProcurementGoods>().eq(TErpProcurementGoods::getProcurementId, erpProcurement.getId())); list1.stream().forEach(e->e.setStatus(1)); erpProcurementGoodsService.updateBatchById(list1); // 响应success JSONObject jsonObject = new JSONObject(); jsonObject.put("code", "SUCCESS"); jsonObject.put("message", "执行成功"); return jsonObject; } }else if("FALLBACK".equals(cmd_type.toString())){ TErpProcurement erpProcurement = erpProcurementService.getOne(new LambdaQueryWrapper<TErpProcurement>().eq(TErpProcurement::getRefundOutSeparateNo, o.toString())); if ( erpProcurement!=null && "SUCCESS".equals(status) && erpProcurement.getRefundStatus()==1) { erpProcurement.setRefundStatus(2); erpProcurementService.updateById(erpProcurement); List<TErpProcurementGoods> list1 = erpProcurementGoodsService.list(new LambdaQueryWrapper<TErpProcurementGoods>().eq(TErpProcurementGoods::getProcurementId, erpProcurement.getId())); list1.stream().forEach(e->e.setStatus(2)); erpProcurementGoodsService.updateBatchById(list1); // 发起退款 String time = DateUtils.dateTimeNow(); String ipAddr = IpUtils.getIpAddr(request); // SYMBOLS 随机取4位数 String str = ""; for (int i = 0; i < 6; i++) { str += SYMBOLS.charAt(RANDOM.nextInt(SYMBOLS.length())); } String outTradeNo = time + str; String refund_amount = erpProcurement.getPayMoney().multiply(BigDecimal.valueOf(100)).intValue() + ""; String apiPath = "sit/api/v3/rfd/refund_front/refund"; String body1 = "{\n" + "\t\"req_time\": \"" + time + "\",\n" + "\t\"version\": \"3.0\",\n" + "\t\"req_data\": {\n" + "\t\t\"merchant_no\": \""+erpProcurement.getMerchantNo()+"\",\n" + "\t\t\"term_no\": \""+erpProcurement.getTermNo()+"\",\n" + "\t\t\"refund_amount\": " + refund_amount + ",\n" + "\t\t\"out_trade_no\": \"" + outTradeNo + "\",\n" + "\t\t\"notify_url\": \"" + "http://221.182.45.100:8089/t-sys-order/messageRefundHandle" + "\",\n" + "\t\t\"origin_log_no\": \"" + erpProcurement.getPayTransactionId() + "\",\n" + "\t\t\"location_info\": {\n" + "\t\t\t\"request_ip\": \"" + ipAddr + "\"\n" + "\t\t},\n" + "\t}\n" + "}"; String authorization = getAuthorization(body1); org.apache.http.HttpResponse response = post(LakalaConfig.getServerUrl() + apiPath, body1, authorization); if (response.getStatusLine().getStatusCode() != 200) { return R.fail(500, "请求失败,statusCode " + response.getStatusLine() + IOUtils.toString(response.getEntity().getContent(), ENCODING)); } String responseStr = IOUtils.toString(response.getEntity().getContent(), ENCODING); JSONObject jsonObject = JSONObject.parseObject(responseStr); JSONObject jsonObject2 = jsonObject.getJSONObject("resp_data"); String code = jsonObject2.getString("log_no"); erpProcurement.setRefundLogNo(code); erpProcurement.setRefundNo(outTradeNo); erpProcurementService.updateById(erpProcurement); // 响应success JSONObject jsonObject3 = new JSONObject(); jsonObject3.put("code", "SUCCESS"); jsonObject3.put("message", "执行成功"); return jsonObject3; } } return null; } @RequestMapping("/messageRefundHandle") @ApiOperation(value = "拉卡拉退款信息回调接口") public Object messageRefundHandle(HttpServletRequest request) throws Exception { String body = this.getBody(request); // 先处理支付完成 修改状态 后处理分账 后走分账回调 JSONObject jsonObject1 = JSONObject.parseObject(body); Object status = jsonObject1.get("trade_status"); Object out_trade_no = jsonObject1.get("out_trade_no"); if(status !=null && "SUCCESS".equals(status.toString())){ TErpProcurement erpProcurement = erpProcurementService.getOne(new LambdaQueryWrapper<TErpProcurement>().eq(TErpProcurement::getRefundNo, out_trade_no.toString())); if ( erpProcurement!=null && "SUCCESS".equals(status)) { erpProcurement.setStatus(6); erpProcurementService.updateById(erpProcurement); // 响应success JSONObject jsonObject = new JSONObject(); jsonObject.put("code", "SUCCESS"); jsonObject.put("message", "执行成功"); return jsonObject; } } return null; } @ApiOperation(value = "退款") @PostMapping(value = "/refundOrder") @SneakyThrows public R<?> refundOrder(@RequestParam String id, HttpServletRequest request) { SysUser user = tokenService.getLoginUser().getUser(); try { // 先退分账 在退订单 // 查出采购单 算出价格 下单 算出应该分佣金额 应该分给谁 TErpProcurement erpProcurement = erpProcurementService.getById(id); // 还未分账成功不能退款 if(erpProcurement.getStatus()==null || erpProcurement.getStatus()!=1){ return R.fail("订单处理中,请稍后操作"); Integer roleType = user.getRoleType(); if(roleType == 5){ // 诊所 TCrmClinic crmClinic = crmClinicService.getOne(Wrappers.lambdaQuery(TCrmClinic.class) .eq(TCrmClinic::getUserId, user.getUserId()) .last("LIMIT 1")); query.setClinicId(crmClinic.getId()); } String time = DateUtils.dateTimeNow(); // SYMBOLS 随机取4位数 String str = ""; for (int i = 0; i < 6; i++) { str += SYMBOLS.charAt(RANDOM.nextInt(SYMBOLS.length())); } String outTradeNo = time + str; // 操作分账 // HttpRequest post = HttpUtil.createPost(LakalaConfig.getServerUrl() + "sit/api/v3/sacs/fallback"); HashMap<String, Object> reqMap = new HashMap<>(); reqMap.put("version", "3.0"); reqMap.put("req_time", DateUtils.dateTimeNow()); return R.ok(sysOrderService.pageList(query)); } HashMap<String, Object> map = new HashMap<>(); map.put("merchant_no", erpProcurement.getMerchantNo()); map.put("origin_separate_no", erpProcurement.getSeparateNo()); map.put("out_separate_no",outTradeNo); erpProcurement.setRefundOutSeparateNo(outTradeNo); erpProcurementService.updateById(erpProcurement); // List<TErpProcurementGoods> list = erpProcurementGoodsService.list(new LambdaQueryWrapper<TErpProcurementGoods>().eq(TErpProcurementGoods::getProcurementId, erpProcurement.getId())); // 根据供应商id分组 // Map<String, List<TErpProcurementGoods>> collect = list.stream().collect(Collectors.groupingBy(TErpProcurementGoods::getSupplierId)); ArrayList<HashMap<String, Object>> objects = new ArrayList<>(); // BigDecimal allMoney = list.stream().map(TErpProcurementGoods::getSupplierMoney).reduce(BigDecimal.ZERO, BigDecimal::add); // for (Map.Entry<String, List<TErpProcurementGoods>> entry : collect.entrySet()) { // // List<TErpProcurementGoods> value = entry.getValue(); // BigDecimal reduce = value.stream().map(TErpProcurementGoods::getSupplierMoney).reduce(BigDecimal.ZERO, BigDecimal::add); // String recv_no = value.stream().map(TErpProcurementGoods::getRecvNo).collect(Collectors.toList()).get(0); // } HashMap<String, Object> map1 = new HashMap<>(); // TODO hzt map1.put("recv_no", "SR2024000006413"); map1.put("amt", erpProcurement.getMoney().multiply(BigDecimal.valueOf(100)).intValue() + ""); objects.add(map1); map.put("total_amt",erpProcurement.getMoney().multiply(BigDecimal.valueOf(100)).intValue() + ""); map.put("origin_recv_datas",objects); reqMap.put("req_data", map); String jsonString = JSON.toJSONString(reqMap); String authorization1 = getAuthorization(jsonString); org.apache.http.HttpResponse response1 = post(LakalaConfig.getServerUrl() + "sit/api/v3/sacs/fallback", jsonString, authorization1); String responseStr = IOUtils.toString(response1.getEntity().getContent(), ENCODING); // post.body(jsonString); // HttpResponse response = post.execute(); // String responseStr = response.body(); return R.ok(responseStr); } catch (Exception e) { e.printStackTrace(); @ApiOperation(value = "获取诊所患者诊疗--搜索用户") @PostMapping(value = "/userList") public R<List<TSysAppUser>> pageList(@RequestBody TSysAppUserQuery query) { LambdaQueryWrapper<TSysAppUser> eq = new LambdaQueryWrapper<TSysAppUser>().eq(TSysAppUser::getStatus, 1); if(query.getNickName() != null && !query.getNickName().isEmpty()){ eq.like(TSysAppUser::getNickName, query.getNickName()); } return R.fail(500, "退款失败请联系平台管理员"); } public org.apache.http.HttpResponse post(String url, String message, String authorization) throws Exception { SSLContext ctx = SSLContext.getInstance("TLS"); X509TrustManager tm = new X509TrustManager() { public X509Certificate[] getAcceptedIssuers() { return null; } public void checkClientTrusted(X509Certificate[] xcs, String str) { } public void checkServerTrusted(X509Certificate[] xcs, String str) { } }; HttpClient http = new DefaultHttpClient(); ClientConnectionManager ccm = http.getConnectionManager(); ctx.init(null, new TrustManager[]{tm}, null); SSLSocketFactory ssf = new SSLSocketFactory(ctx); ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); SchemeRegistry registry = ccm.getSchemeRegistry(); registry.register(new Scheme("https", ssf, 443)); HttpPost post = new HttpPost(url); StringEntity myEntity = new StringEntity(message, ENCODING); post.setEntity(myEntity); post.setHeader("Authorization", SCHEMA + " " + authorization); post.setHeader("Accept", "application/json"); post.setHeader("Content-Type", "application/json"); return http.execute(post); } public final String getAuthorization(String body) throws IOException { String nonceStr = generateNonceStr(); long timestamp = generateTimestamp(); String message = LakalaConfig.getAppId() + "\n" + LakalaConfig.getMerchantNo() + "\n" + timestamp + "\n" + nonceStr + "\n" + body + "\n"; System.out.println("getToken message : " + message); PrivateKey merchantPrivateKey = loadPrivateKey(new FileInputStream(new File(LakalaConfig.getPriKeyStr()))); String signature = this.sign(message.getBytes(ENCODING), merchantPrivateKey); String authorization = "appid=\"" + LakalaConfig.getAppId() + "\"," + "serial_no=\"" + LakalaConfig.getMerchantNo() + "\"," + "timestamp=\"" + timestamp + "\"," + "nonce_str=\"" + nonceStr + "\"," + "signature=\"" + signature + "\""; System.out.println("authorization message :" + authorization); return authorization; } public long generateTimestamp() { return System.currentTimeMillis() / 1000; } public String generateNonceStr() { char[] nonceChars = new char[32]; for (int index = 0; index < nonceChars.length; ++index) { nonceChars[index] = SYMBOLS.charAt(RANDOM.nextInt(SYMBOLS.length())); if(query.getPhone() != null && !query.getPhone().isEmpty()){ eq.like(TSysAppUser::getPhone, query.getPhone()); } return new String(nonceChars); } public static PrivateKey loadPrivateKey(InputStream inputStream) { try { ByteArrayOutputStream array = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int length; while ((length = inputStream.read(buffer)) != -1) { array.write(buffer, 0, length); } String privateKey = array.toString("utf-8").replace("-----BEGIN PRIVATE KEY-----", "") .replace("-----END PRIVATE KEY-----", "").replaceAll("\\s+", ""); KeyFactory kf = KeyFactory.getInstance("RSA"); return kf.generatePrivate(new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKey))); } catch (NoSuchAlgorithmException e) { throw new RuntimeException("当前Java环境不支持RSA", e); } catch (InvalidKeySpecException e) { throw new RuntimeException("无效的密钥格式"); } catch (IOException e) { throw new RuntimeException("无效的密钥"); } } public String sign(byte[] message, PrivateKey privateKey) { try { Signature sign = Signature.getInstance("SHA256withRSA"); sign.initSign(privateKey); sign.update(message); return new String(Base64.encodeBase64(sign.sign())); } catch (NoSuchAlgorithmException e) { throw new RuntimeException("当前Java环境不支持SHA256withRSA", e); } catch (SignatureException e) { throw new RuntimeException("签名计算失败", e); } catch (InvalidKeyException e) { throw new RuntimeException("无效的私钥", e); } List<TSysAppUser> list = sysAppUserService.list(eq); return R.ok(list); } public final String getBody(HttpServletRequest request) { InputStreamReader in = null; try { in = new InputStreamReader(request.getInputStream(), StandardCharsets.UTF_8); StringBuffer bf = new StringBuffer(); int len; char[] chs = new char[1024]; while ((len = in.read(chs)) != -1) { bf.append(new String(chs, 0, len)); } return bf.toString(); } catch (Exception e) { e.printStackTrace(); } finally { if (null != in) { try { in.close(); } catch (Exception e) { } } @ApiOperation(value = "诊所患者诊疗--确认添加") @PostMapping(value = "/add") public R<String> add(@RequestBody @Valid TSysOrderDto dto) { SysUser user = tokenService.getLoginUser().getUser(); Integer roleType = user.getRoleType(); if(roleType == 5){ // 诊所 TCrmClinic crmClinic = crmClinicService.getOne(Wrappers.lambdaQuery(TCrmClinic.class) .eq(TCrmClinic::getUserId, user.getUserId()) .last("LIMIT 1")); sysOrderService.add(dto,crmClinic); return R.ok("添加成功"); } return null; return R.fail("添加失败"); } public static X509Certificate loadCertificate(InputStream inputStream) { try { CertificateFactory cf = CertificateFactory.getInstance("X509"); X509Certificate cert = (X509Certificate) cf.generateCertificate(inputStream); cert.checkValidity(); return cert; } catch (CertificateExpiredException e) { throw new RuntimeException("证书已过期", e); } catch (CertificateNotYetValidException e) { throw new RuntimeException("证书尚未生效", e); } catch (CertificateException e) { throw new RuntimeException("无效的证书", e); } } @ApiOperation(value = "诊所患者诊疗--详情") @GetMapping(value = "/detail/{id}") public R<TSysOrderDetailVo> detail(@PathVariable String id) { TSysOrder tSysOrder = sysOrderService.getById(id); private static boolean verify(X509Certificate certificate, byte[] message, String signature) { try { Signature sign = Signature.getInstance("SHA256withRSA"); sign.initVerify(certificate); sign.update(message); byte[] signatureB = Base64.decodeBase64(signature); return sign.verify(signatureB); } catch (NoSuchAlgorithmException e) { throw new RuntimeException("当前Java环境不支持SHA256withRSA", e); } catch (SignatureException e) { throw new RuntimeException("签名验证过程发生了错误", e); } catch (InvalidKeyException e) { throw new RuntimeException("无效的证书", e); } TSysOrderDetailVo detail = new TSysOrderDetailVo(); detail.setId(tSysOrder.getId()); String appUserId = tSysOrder.getAppUserId(); TSysAppUser appUser = sysAppUserService.getById(appUserId); detail.setUserName(appUser.getNickName()); detail.setCheckTime(tSysOrder.getCheckTime()); detail.setTotalMoney(tSysOrder.getTotalMoney()); List<TSysOrderGoods> list = sysOrderGoodsService.list(new LambdaQueryWrapper<TSysOrderGoods>().eq(TSysOrderGoods::getOrderId, id)); detail.setList(list); return R.ok(detail); } ruoyi-system/src/main/java/com/ruoyi/system/dto/TSysOrderDto.java
New file @@ -0,0 +1,53 @@ package com.ruoyi.system.dto; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import com.fasterxml.jackson.annotation.JsonFormat; import com.ruoyi.common.core.domain.BaseModel; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import lombok.EqualsAndHashCode; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.List; /** * <p> * 订单管理 * </p> * * @author xiaochen * @since 2025-08-20 */ @Data @ApiModel("患者诊疗 确认添加Dto") public class TSysOrderDto { @ApiModelProperty(value = "用户id") @NotBlank(message = "用户id不能为空") private String appUserId; @ApiModelProperty(value = "检测信息id") private String inspectionId; @ApiModelProperty(value = "订单总价") @NotNull(message = "订单总价不能为空") private BigDecimal totalMoney; @ApiModelProperty(value = "检查时间") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private LocalDateTime checkTime; @ApiModelProperty(value = "二级参数") private List<TSysOrderNextDto> dtoList; } ruoyi-system/src/main/java/com/ruoyi/system/dto/TSysOrderNextDto.java
New file @@ -0,0 +1,42 @@ package com.ruoyi.system.dto; import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; import java.math.BigDecimal; import java.time.LocalDateTime; /** * <p> * 订单管理 * </p> * * @author xiaochen * @since 2025-08-20 */ @Data @ApiModel("患者诊疗 确认添加二级Dto") public class TSysOrderNextDto { @ApiModelProperty("批次id") @NotBlank(message = "批次id不能为空") private String batchId; @ApiModelProperty("订单数量") @NotNull(message = "订单数量不能为空") private Integer num; @ApiModelProperty("售价") @NotNull(message = "售价不能为空") private BigDecimal saleAmount; @ApiModelProperty("剩余数量") @NotNull(message = "剩余数量不能为空") private Integer remainingQuantity; } ruoyi-system/src/main/java/com/ruoyi/system/mapper/TErpGoodsMapper.java
@@ -35,7 +35,7 @@ List<TErpGoodsInventoryVO> pageInventoryGoodsList1(@Param("warehouseId") String warehouseId, @Param("user") SysUser user, @Param("supplierClinicId") String supplierClinicId, @Param("endDate") Date endDate); List<TErpGoodsInventoryVO> pageInventoryGoodsPageList1(@Param("query") TErpGoodsInventoryQuery query, @Param("pageInfo") PageInfo<TErpGoodsInventoryVO> pageInfo, @Param("user") SysUser user, @Param("supplierClinicId") String supplierClinicId, @Param("endDate") Date endDate); List<TErpGoodsInventoryVO> pageInventoryGoodsPageList1(@Param("query") TErpGoodsInventoryQuery query, @Param("pageInfo") PageInfo<TErpGoodsInventoryVO> pageInfo, @Param("user") SysUser user, @Param("supplierClinicId") String supplierClinicId, @Param("time") Date endDate); TErpGoods getGoodsById(@Param("goodsId") String goodsId); ruoyi-system/src/main/java/com/ruoyi/system/mapper/TSysOrderMapper.java
@@ -1,7 +1,10 @@ package com.ruoyi.system.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.ruoyi.common.basic.PageInfo; import com.ruoyi.system.model.TSysOrder; import com.ruoyi.system.query.TSysOrderQuery; import com.ruoyi.system.vo.TSysOrderPageVo; import com.ruoyi.system.vo.TSysOrderVO; import org.apache.ibatis.annotations.Param; @@ -24,4 +27,8 @@ * @return 订单列表 */ List<TSysOrderVO> queryListByAppUserId(@Param("appUserId") String appUserId); List<TSysOrderPageVo> pageList(@Param("page") PageInfo<TSysOrderPageVo> page, @Param("query") TSysOrderQuery query, @Param("sTime") String sTime, @Param("eTime") String eTime); } ruoyi-system/src/main/java/com/ruoyi/system/model/TCrmClinicPoints.java
@@ -37,7 +37,7 @@ @ApiModelProperty(value = "积分数") @TableField("points") private Double points; private Integer points; @ApiModelProperty(value = "积分到期时间") @TableField("expire_time") ruoyi-system/src/main/java/com/ruoyi/system/model/TSysOrder.java
@@ -35,6 +35,10 @@ @TableField("app_user_id") private String appUserId; @ApiModelProperty(value = "诊所id") @TableField("clinic_id") private String clinicId; @ApiModelProperty(value = "检测信息id") @TableField("inspection_id") private String inspectionId; ruoyi-system/src/main/java/com/ruoyi/system/model/TSysOrderGoods.java
@@ -58,4 +58,16 @@ @TableField("sale_amount") private BigDecimal saleAmount; @ApiModelProperty(value = "批次id") @TableField("batch_id") private String batchId; @ApiModelProperty(value = "批次号") @TableField("batch_number") private String batchNumber; @ApiModelProperty(value = "剩于数量") @TableField("remaining_quantity") private Integer remainingQuantity; } ruoyi-system/src/main/java/com/ruoyi/system/query/TSysOrderQuery.java
New file @@ -0,0 +1,23 @@ package com.ruoyi.system.query; import com.ruoyi.common.core.domain.BasePage; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @Data @ApiModel("患者诊疗 订单列表query") public class TSysOrderQuery extends BasePage { @ApiModelProperty("用户名称") private String userName; @ApiModelProperty("手机号") private String phone; @ApiModelProperty("时间 2022-02-02 - 2022-02-02") private String time; private String clinicId; } ruoyi-system/src/main/java/com/ruoyi/system/service/TSysOrderService.java
@@ -1,9 +1,15 @@ package com.ruoyi.system.service; import com.baomidou.mybatisplus.extension.service.IService; import com.ruoyi.common.basic.PageInfo; import com.ruoyi.system.dto.TSysOrderDto; import com.ruoyi.system.model.TCrmClinic; import com.ruoyi.system.model.TSysOrder; import com.ruoyi.system.query.TSysOrderQuery; import com.ruoyi.system.vo.TSysOrderPageVo; import com.ruoyi.system.vo.TSysOrderVO; import javax.validation.Valid; import java.util.List; /** @@ -22,4 +28,10 @@ * @return */ List<TSysOrderVO> queryListByAppUserId(String id); PageInfo<TSysOrderPageVo> pageList(TSysOrderQuery query); void add(TSysOrderDto dto, TCrmClinic crmClinic); } ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TErpProcurementServiceImpl.java
@@ -194,6 +194,9 @@ tErpProcurementVo.setStatus(tErpProcurement.getStatus()); tErpProcurementVo.setSendTime(tErpProcurement.getSendTime()); tErpProcurementVo.setMoney(tErpProcurement.getMoney()); tErpProcurementVo.setTotalPrice(tErpProcurement.getPayMoney()); List<TErpProcurementGoods> tErpProcurementGoods = erpProcurementGoodsMapper.selectList (new LambdaQueryWrapper<TErpProcurementGoods>().eq(TErpProcurementGoods::getProcurementId, id) .like(goodsName != null && !goodsName.isEmpty(), TErpProcurementGoods::getGoodsName, goodsName) @@ -210,6 +213,7 @@ tErpProcurementDetailNextVo.setNum(tErpProcurementGood.getPurchaseCount()); tErpProcurementDetailNextVo.setTotalPrice(tErpProcurementGood.getTotalPrice()); tErpProcurementDetailNextVo.setQuasiNumber(tErpProcurementGood.getQuasiNumber()); tErpProcurementDetailNextVo.setPurchasePrice(tErpProcurementGood.getPurchasePrice()); List<TSysCommission> tSysCommissions = sysCommissionMapper.selectList(new LambdaQueryWrapper<TSysCommission>().eq(TSysCommission::getTErpProcurementGoodsId, tErpProcurementGood.getId())); ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TSysOrderServiceImpl.java
@@ -1,17 +1,27 @@ package com.ruoyi.system.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.system.mapper.TSysOrderGoodsMapper; import com.ruoyi.system.mapper.TSysOrderMapper; import com.ruoyi.system.model.TSysOrder; import com.ruoyi.system.model.TSysOrderGoods; import com.ruoyi.common.basic.PageInfo; import com.ruoyi.system.dto.TSysOrderDto; import com.ruoyi.system.dto.TSysOrderNextDto; import com.ruoyi.system.mapper.*; import com.ruoyi.system.model.*; import com.ruoyi.system.query.TSysOrderQuery; import com.ruoyi.system.service.TCrmClinicService; import com.ruoyi.system.service.TErpClinicOutboundService; import com.ruoyi.system.service.TSysOrderService; import com.ruoyi.system.vo.TSysOrderPageVo; import com.ruoyi.system.vo.TSysOrderVO; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; import javax.annotation.Resource; import java.math.BigDecimal; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; @@ -29,6 +39,24 @@ @Autowired private TSysOrderGoodsMapper sysOrderGoodsMapper; @Resource private TErpClinicWarehousingBatchMapper erpClinicWarehousingBatchMapper; @Resource private TErpClinicOutboundGoodsMapper erpClinicOutboundGoodsMapper; @Resource private TErpGoodsMapper erpGoodsMapper; @Resource private TErpGoodsTypeMapper erpGoodsTypeMapper; @Resource private TErpGoodsUnitMapper erpGoodsUnitMapper; @Resource private TErpClinicOutboundMapper erpClinicOutboundMapper; @Override public List<TSysOrderVO> queryListByAppUserId(String id) { List<TSysOrderVO> sysOrderVOS = this.baseMapper.queryListByAppUserId(id); @@ -43,4 +71,89 @@ } return this.baseMapper.queryListByAppUserId(id); } @Override public PageInfo<TSysOrderPageVo> pageList(TSysOrderQuery query) { PageInfo<TSysOrderPageVo> page = new PageInfo<>(query.getPageNum(), query.getPageSize()); String sTime =null; String eTime = null; if(query.getTime() != null && !query.getTime().isEmpty()){ String[] split = query.getTime().split(" - "); sTime = split[0] + " 00:00:00"; eTime = split[1] + " 23:59:59"; } List<TSysOrderPageVo> sysOrderPageVOS = this.baseMapper.pageList(page, query,sTime,eTime); page.setRecords(sysOrderPageVOS); return page; } @Override @Transactional(rollbackFor = Exception.class) public void add(TSysOrderDto dto, TCrmClinic crmClinic) { // 判断库存够不够 添加订单 添加订单二级 出库记录 List<TSysOrderNextDto> dtoList = dto.getDtoList(); ArrayList<TSysOrderGoods> tSysOrderGoods = new ArrayList<>(); ArrayList<TErpClinicOutboundGoods> erpClinicOutboundGoods = new ArrayList<>(); for (TSysOrderNextDto sysOrderNextDto : dtoList) { TErpClinicWarehousingBatch tErpClinicWarehousingBatch = erpClinicWarehousingBatchMapper.selectById(sysOrderNextDto.getBatchId()); // 找出这个批次出库多少 List<TErpClinicOutboundGoods> tErpClinicOutboundGoods = erpClinicOutboundGoodsMapper.selectList(new LambdaQueryWrapper<TErpClinicOutboundGoods>().eq(TErpClinicOutboundGoods::getWarehousingBatchId, sysOrderNextDto.getBatchId())); int count = tErpClinicOutboundGoods.stream().mapToInt(TErpClinicOutboundGoods::getOutboundCount).sum(); if(tErpClinicWarehousingBatch.getPurchaseCount() < count + sysOrderNextDto.getNum()){ throw new RuntimeException("库存不足"); } TErpGoods goods = erpGoodsMapper.selectById(tErpClinicWarehousingBatch.getGoodsId()); TSysOrderGoods tSysOrderGoods1 = new TSysOrderGoods(); tSysOrderGoods1.setGoodsName(goods.getGoodsName()); TErpGoodsType tErpGoodsType = erpGoodsTypeMapper.selectById(goods.getTypeId()); tSysOrderGoods1.setTypeName(tErpGoodsType.getTypeName()); tSysOrderGoods1.setQuasiNumber(goods.getQuasiNumber()); TErpGoodsUnit tErpGoodsUnit = erpGoodsUnitMapper.selectById(goods.getPackingUnitId()); tSysOrderGoods1.setGoodsUnit(tErpGoodsUnit.getUnitName()); tSysOrderGoods1.setSaleCount(sysOrderNextDto.getNum()); tSysOrderGoods1.setSaleAmount(goods.getSalesAmount()); tSysOrderGoods1.setBatchId(tErpClinicWarehousingBatch.getId()); tSysOrderGoods1.setBatchNumber(tErpClinicWarehousingBatch.getBatchNumber()); tSysOrderGoods1.setRemainingQuantity(sysOrderNextDto.getRemainingQuantity()); tSysOrderGoods.add(tSysOrderGoods1); TErpClinicOutboundGoods tErpClinicOutboundGoods1 = new TErpClinicOutboundGoods(); tErpClinicOutboundGoods1.setWarehousingId(tErpClinicWarehousingBatch.getWarehousingId()); tErpClinicOutboundGoods1.setWarehousingBatchId(tErpClinicWarehousingBatch.getId()); tErpClinicOutboundGoods1.setOutboundCount(sysOrderNextDto.getNum()); tErpClinicOutboundGoods1.setGoodsId(goods.getId()); tErpClinicOutboundGoods1.setTotalPrice(sysOrderNextDto.getSaleAmount().multiply(BigDecimal.valueOf(sysOrderNextDto.getNum()))); erpClinicOutboundGoods.add(tErpClinicOutboundGoods1); } TSysOrder tSysOrder = new TSysOrder(); tSysOrder.setAppUserId(dto.getAppUserId()); tSysOrder.setClinicId(crmClinic.getId()); tSysOrder.setInspectionId(dto.getInspectionId()); tSysOrder.setTotalMoney(dto.getTotalMoney()); tSysOrder.setCheckTime(dto.getCheckTime()); tSysOrder.setOrderNumber(System.currentTimeMillis() + ""); this.save(tSysOrder); for (TSysOrderGoods tSysOrderGood : tSysOrderGoods) { tSysOrderGood.setOrderId(tSysOrder.getId()); sysOrderGoodsMapper.insert(tSysOrderGood); } TErpClinicOutbound tErpClinicOutbound = new TErpClinicOutbound(); tErpClinicOutbound.setClinicId(crmClinic.getId()); tErpClinicOutbound.setOutboundType(7); tErpClinicOutbound.setOrderNumber(tSysOrder.getOrderNumber()); tErpClinicOutbound.setTotalMoney(dto.getTotalMoney()); tErpClinicOutbound.setOutboundNumber("G"+System.currentTimeMillis()); erpClinicOutboundMapper.insert(tErpClinicOutbound); for (TErpClinicOutboundGoods erpClinicOutboundGood : erpClinicOutboundGoods) { erpClinicOutboundGood.setOutboundId(tErpClinicOutbound.getId()); erpClinicOutboundGoodsMapper.insert(erpClinicOutboundGood); } } } ruoyi-system/src/main/java/com/ruoyi/system/vo/TErpProcurementDetailNextVo.java
@@ -34,6 +34,9 @@ @ApiModelProperty(value = "国药准字号") private String quasiNumber; @ApiModelProperty(value = "采购价") private BigDecimal purchasePrice; ruoyi-system/src/main/java/com/ruoyi/system/vo/TErpProcurementDetailVo.java
@@ -41,6 +41,12 @@ @ApiModelProperty(value = "状态 1=草稿 2=待支付 3=待发货 4=已发货 5=已入库 6=已取消") private Integer status; @ApiModelProperty(value = "总金额") private BigDecimal totalPrice=BigDecimal.ZERO; @ApiModelProperty(value = "平台佣金") private BigDecimal money=BigDecimal.ZERO; @ApiModelProperty(value = "采购单详情二级") private List<TErpProcurementDetailNextVo> list; } ruoyi-system/src/main/java/com/ruoyi/system/vo/TSysOrderDetailVo.java
New file @@ -0,0 +1,30 @@ package com.ruoyi.system.vo; import com.fasterxml.jackson.annotation.JsonFormat; import com.ruoyi.system.model.TSysOrderGoods; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import javax.validation.constraints.NotNull; import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.List; @Data @ApiModel("患者诊疗详情Vo") public class TSysOrderDetailVo { private String id; private String userName; @ApiModelProperty(value = "检查时间") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private LocalDateTime checkTime; @ApiModelProperty(value = "订单总价") private BigDecimal totalMoney; @ApiModelProperty(value = "二级参数") private List<TSysOrderGoods> list; } ruoyi-system/src/main/java/com/ruoyi/system/vo/TSysOrderPageVo.java
New file @@ -0,0 +1,30 @@ package com.ruoyi.system.vo; import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.math.BigDecimal; import java.util.Date; @Data @ApiModel("患者诊疗 订单管理分页对象") public class TSysOrderPageVo { @ApiModelProperty("id") private String id; @ApiModelProperty("用户名称") private String userName; @ApiModelProperty("手机号") private String phone; @ApiModelProperty("时间") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private Date createTime; @ApiModelProperty("金额") private BigDecimal totalMoney; } ruoyi-system/src/main/resources/mapper/system/TSysOrderMapper.xml
@@ -28,4 +28,22 @@ where app_user_id = #{appUserId} and disabled = ${@com.ruoyi.common.enums.DisabledEnum@NO.getCode()} </select> <select id="pageList" resultType="com.ruoyi.system.vo.TSysOrderPageVo"> select t1.id,t1.create_time,t1.total_money,t2.nick_name as userName,t2.phone from t_sys_order t1 left join t_sys_app_user t2 on t1.app_user_id = t2.id where t1.disabled = 0 and t1.clinic_id =#{query.clinicId} <if test="query.userName != null and query.userName != ''"> and t2.nick_name like concat('%',#{query.userName},'%') </if> <if test="query.phone != null and query.phone != ''"> and t2.phone like concat('%',#{query.phone},'%') </if> <if test="sTime != null and eTime != ''"> and t1.create_time between #{sTime} and #{eTime} </if> order by t1.create_time desc </select> </mapper>