提交 e8ee2edb authored 作者: hzh's avatar hzh

Merge branch 'dev'

......@@ -3,6 +3,7 @@ package org.dromara.order.api;
import org.dromara.order.api.domain.OrderPay;
import org.dromara.order.api.domain.RemoteOrder;
import org.dromara.order.api.domain.RemoteSaveOrder;
import org.dromara.order.api.domain.RemoteSaveRefundOrder;
import org.dromara.order.api.enums.OrderType;
import org.dromara.order.api.enums.Source;
......@@ -23,6 +24,14 @@ public interface RemoteOrderService {
*/
OrderPay createOrder(RemoteSaveOrder order) throws Exception;
/**
* 创建退款订单
*
* @param order 订单信息
* @return 是否成功
*/
Boolean createRefundOrder(RemoteSaveRefundOrder order) throws Exception;
/**
* 查询订单列表
*
......@@ -51,4 +60,12 @@ public interface RemoteOrderService {
*/
RemoteSaveOrder.Fee calcServiceFee(Source source, OrderType orderType, List<RemoteSaveOrder.Fee> feeList);
/**
* 查询退款订单列表
*
* @param orderType 订单类型
* @param orderNoList 订单号列表
* @return 退款订单列表
*/
List<RemoteOrder> queryRefundList(String orderType, List<String> orderNoList);
}
package org.dromara.order.api.domain;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.experimental.Accessors;
import org.dromara.order.api.enums.OrderType;
import java.io.Serial;
import java.io.Serializable;
/**
* 生成退款单
*
* @author hzh
* @date 2024-12-05
**/
@Data
@Accessors(chain = true)
public class RemoteSaveRefundOrder implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 原订单号
*/
@NotNull(message = "原订单号不能为空")
private String originOrderNo;
/**
* 订单类型
*/
private OrderType orderType;
}
......@@ -53,5 +53,10 @@ public class WechatPayConfiguration {
* 回调函数的接口路径
*/
private String notify;
/**
* 退款回调函数的接口路径
*/
private String refundNotify;
}
package org.dromara.common.pay.domain;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* @author hzh
* @date 2025-01-02
* @desc 退款回调body
**/
@Data
@Accessors(chain = true)
public class JsapiRefundNotifyBodyModel implements Serializable {
/**
* 【通知ID】回调通知的唯一编号。
*/
private String id;
/**
* 【通知创建时间】
* <p>
* 1、定义:本次回调通知创建的时间。
*/
private String create_time;
/**
* 【通知的类型】微信支付回调通知的类型。
*/
private String event_type;
/**
* 【通知数据类型】通知的资源数据类型,固定为encrypt-resource。
*/
private String resource_type;
/**
* 【通知资源数据】通知资源数据
*/
private Resource resource;
@Data
@Accessors(chain = true)
public static class Resource implements Serializable {
/**
* 【加密算法类型】
* 回调数据密文的加密算法类型,目前为AEAD_AES_256_GCM,开发者需要使用同样类型的数据进行解密。
*/
private String algorithm;
/**
* 【原始回调类型】
* 加密前的对象类型,为refund。
*/
private String original_type;
/**
* 【数据密文】
* Base64编码后的回调数据密文,商户需Base64解码并使用APIV3密钥解密,参考如何解密证书和回调报文。
*/
private String ciphertext;
/**
* 【附加数据】
* 参与解密的附加数据,该值可能为空。
*/
private String associated_data;
/**
* 【随机串】
* 参与解密的随机串。
*/
private String nonce;
}
}
package org.dromara.common.pay.domain;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* @author hzh
* @date 2024-12-31
* @desc jsapi退款回调模型
**/
@Data
@Accessors(chain = true)
public class JsapiRefundNotifyModel {
/**
* 【商户号】商户下单时传入的商户号。
*/
private String mchid;
/**
* 【商户订单号】 商户下单时传入的商户系统内部订单号。
*/
private String out_trade_no;
/**
* 【微信支付订单号】 微信支付侧订单的唯一标识。
*/
private String transaction_id;
/**
* 【商户退款单号】 商户申请退款时传的商户系统内部退款单号。
*/
private String out_refund_no;
/**
* 【微信支付退款单号】 申请退款受理成功时,该笔退款单在微信支付侧生成的唯一标识。
*/
private String refund_id;
/**
* 【退款状态】 退款状态:
* SUCCESS—退款成功
* CLOSED—退款关闭。
* PROCESSING—退款处理中
* ABNORMAL—退款异常,退款到银行发现用户的卡作废或者冻结了,导致原路退款银行卡失败,可前往商户平台-交易中心,手动处理此笔退款,可参考: 退款异常的处理,或者通过发起异常退款接口进行处理。
*/
private String refund_status;
/**
* 【退款成功时间】 退款成功的时间。
*/
private String success_time;
/**
* 【退款入账账户】
*/
private String user_received_account;
/**
* 【退款金额】 退款总金额,单位为元。
*/
private Amount amount;
@Data
@Accessors(chain = true)
public static class Amount implements Serializable {
/**
* 订单总金额,单位为分。
*/
private Integer total;
/**
* 【退款金额】 退款标价金额,单位为分,可以做部分退款
*/
private Integer refund;
/**
* 用户支付金额,单位为分。
*/
private Integer payer_total;
/**
* 【用户退款金额】 退款给用户的金额,单位为分,不包含所有优惠券金额
*/
private Integer payer_refund;
}
}
......@@ -3,6 +3,7 @@ package org.dromara.common.pay.service;
import com.ijpay.wxpay.model.v3.RefundModel;
import com.ijpay.wxpay.model.v3.UnifiedOrderModel;
import org.dromara.common.pay.domain.JsapiNotifyModel;
import org.dromara.common.pay.domain.JsapiRefundNotifyModel;
/**
* @author wenhe
......@@ -55,13 +56,32 @@ public interface IWxPayService {
*/
JsapiNotifyModel notify(String timestamp, String nonce, String serialNo, String signature, String result);
/**
* 退款回调
*
* @param timestamp 时间搓
* @param nonce nonce
* @param serialNo serialNo
* @param signature 签名
* @param result 支付通知密文
* @return 退款通知明文
*/
JsapiRefundNotifyModel refundNotify(String timestamp, String nonce, String serialNo, String signature, String result);
/**
* 退款
*
* @param model model
* @return 退款结果
* @throws Exception 异常
*/
org.dromara.common.pay.domain.RefundModel refund(RefundModel model) throws Exception;
/**
* 退款查询
*
* @param outRefundNo 退款单号
* @return 退款结果
*/
org.dromara.common.pay.domain.RefundModel refundQuery(String outRefundNo);
}
......@@ -25,6 +25,7 @@ import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.dromara.common.pay.config.WechatPayConfiguration;
import org.dromara.common.pay.domain.JsapiNotifyModel;
import org.dromara.common.pay.domain.JsapiRefundNotifyModel;
import org.dromara.common.pay.service.IWxPayService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
......@@ -228,6 +229,29 @@ public class WxPayServiceImpl implements IWxPayService {
}
}
@Override
public JsapiRefundNotifyModel refundNotify(String timestamp, String nonce, String serialNo, String signature, String result) {
log.info("timestamp:{} nonce:{} serialNo:{} signature:{}", timestamp, nonce, serialNo, signature);
log.info("退款通知密文 {}", result);
try {
// 需要通过证书序列号查找对应的证书,verifyNotify 中有验证证书的序列号
String plainText = WxPayKit.verifyNotify(
serialNo,
result,
signature,
nonce,
timestamp,
config.getApiKey3(),
config.getPlatformCertPath()
);
log.info("退款通知明文 {}", plainText);
return JSON.parseObject(plainText, JsapiRefundNotifyModel.class);
} catch (Exception e) {
log.error("系统异常", e);
throw new RuntimeException("系统异常!");
}
}
@Override
public JsapiNotifyModel query(String outTradeNo) {
try {
......@@ -262,6 +286,37 @@ public class WxPayServiceImpl implements IWxPayService {
}
}
@Override
public org.dromara.common.pay.domain.RefundModel refundQuery(String outRefundNo) {
try {
log.info("退款订单查询,退款单号:{}", outRefundNo);
IJPayHttpResponse response = WxPayApi.v3(
RequestMethodEnum.GET,
WxDomainEnum.CHINA.toString(),
String.format(BasePayApiEnum.REFUND_QUERY_BY_OUT_REFUND_NO.toString(), outRefundNo),
config.getMchId(),
getSerialNumber(),
null,
config.getKeyPath(),
Collections.emptyMap());
log.info("查询退款单:{} 查询响应 {}", outRefundNo, response);
if (response.getStatus() == IJPayConstants.CODE_200) {
// 根据证书序列号查询对应的证书来验证签名结果
boolean verifySignature = WxPayKit.verifySignature(response, config.getPlatformCertPath());
log.info("verifySignature: {}", verifySignature);
//验签成功
if (verifySignature) {
JSONObject result = JSONUtil.parseObj(response.getBody());
return JSON.parseObject(JSON.toJSONString(result), org.dromara.common.pay.domain.RefundModel.class);
}
}
throw new RuntimeException("退款单:" + outRefundNo + "查询失败!");
} catch (Exception e) {
log.error("系统异常", e);
throw new RuntimeException("退款单:" + outRefundNo + "查询失败!");
}
}
@Override
public Boolean close(String outTradeNo) {
try {
......@@ -280,7 +335,7 @@ public class WxPayServiceImpl implements IWxPayService {
JSONUtil.toJsonStr(params));
log.info("关闭订单:{} 查询响应 {}", outTradeNo, response);
if (response.getStatus() == IJPayConstants.CODE_204) {
return true;
return true;
}
throw new RuntimeException("订单:" + outTradeNo + "关闭失败!");
} catch (Exception e) {
......@@ -291,7 +346,7 @@ public class WxPayServiceImpl implements IWxPayService {
@Override
public org.dromara.common.pay.domain.RefundModel refund(RefundModel model) throws Exception {
model.setNotify_url(config.getNotify());
model.setNotify_url(config.getDomain() + config.getRefundNotify());
log.info("统一退款参数 {}", JSONUtil.toJsonStr(model));
IJPayHttpResponse response = WxPayApi.v3(
RequestMethodEnum.POST,
......
package org.dromara.common.pay.util;
import java.math.BigDecimal;
import java.math.RoundingMode;
/**
* @author hzh
* @date 2025-01-02
* @desc 货币工具类
**/
public class CurrencyUtils {
/**
* 分转元
*
* @param score 分
* @return 元
*/
public static BigDecimal convertScoreToYuan(Integer score) {
if (score == null) {
return null;
}
return new BigDecimal(score).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP);
}
}
......@@ -20,6 +20,7 @@ import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
......@@ -50,33 +51,78 @@ public class OrderController extends BaseController {
Map<String, String> map = new HashMap<>(12);
try {
log.info("微信回调开始");
log.info("微信支付回调开始");
jakarta.servlet.http.HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
ImmutableMap<String, String> builder = ImmutableMap.<String, String>builder()
.put("timestamp", request.getHeader("Wechatpay-Timestamp"))
.put("nonce", request.getHeader("Wechatpay-Nonce"))
.put("serialNo", request.getHeader("Wechatpay-Serial"))
.put("signature", request.getHeader("Wechatpay-Signature"))
.put("result", CustomHttpKit.readData(request))
.build();
//获取请求参数
ImmutableMap<String, String> builder = getParams();
boolean result = orderPayService.notify(JSON.toJSONString(new HashMap<>(builder)));
if (result) {
response.setStatus(200);
map.put("code", "SUCCESS");
map.put("message", "SUCCESS");
} else {
response.setStatus(500);
map.put("code", "ERROR");
map.put("message", "签名错误");
}
response.setHeader("Content-type", ContentType.JSON.toString());
response.getOutputStream().write(JSONUtil.toJsonStr(map).getBytes(StandardCharsets.UTF_8));
response.flushBuffer();
//设置响应参数
setResponse(result, response, map);
} catch (Exception e) {
log.error("系统异常", e);
}
}
/**
* 获取请求参数
*
* @return ImmutableMap<String, String> 请求参数
*/
private ImmutableMap<String, String> getParams() {
jakarta.servlet.http.HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
return ImmutableMap.<String, String>builder()
.put("timestamp", request.getHeader("Wechatpay-Timestamp"))
.put("nonce", request.getHeader("Wechatpay-Nonce"))
.put("serialNo", request.getHeader("Wechatpay-Serial"))
.put("signature", request.getHeader("Wechatpay-Signature"))
.put("result", CustomHttpKit.readData(request))
.build();
}
/**
* 设置响应参数
*
* @param result result
* @param response response
* @param map map
* @throws IOException IOException 异常信息
*/
private void setResponse(boolean result, HttpServletResponse response, Map<String, String> map) throws IOException {
if (result) {
response.setStatus(200);
map.put("code", "SUCCESS");
map.put("message", "SUCCESS");
} else {
response.setStatus(500);
map.put("code", "ERROR");
map.put("message", "签名错误");
}
response.setHeader("Content-type", ContentType.JSON.toString());
response.getOutputStream().write(JSONUtil.toJsonStr(map).getBytes(StandardCharsets.UTF_8));
response.flushBuffer();
}
/**
* 退款函数
*
* @param response response
*/
@RequestMapping(value = "/v3/refundNotify", method = {RequestMethod.POST, RequestMethod.GET})
public void refundNotify(HttpServletResponse response) {
Map<String, String> map = new HashMap<>(12);
try {
log.info("微信退款回调开始");
//获取请求参数
ImmutableMap<String, String> builder = getParams();
boolean result = orderPayService.refundNotify(JSON.toJSONString(new HashMap<>(builder)));
setResponse(result, response, map);
} catch (Exception e) {
log.error("系统异常", e);
}
......
package org.dromara.order.controller;
import lombok.RequiredArgsConstructor;
import org.dromara.common.web.core.BaseController;
import org.dromara.order.service.IOrderRefundService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 订单退款
* 前端访问路由地址为:/order/orderRefund
*
* @author hzh
* @date 2024-12-31
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/orderRefund")
public class OrderRefundController extends BaseController {
private final IOrderRefundService orderRefundService;
}
package org.dromara.order.domain;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.dromara.common.tenant.core.TenantEntity;
import java.io.Serial;
import java.math.BigDecimal;
/**
* 订单退款对象 biz_order_refund
*
* @author hzh
* @date 2024-12-31
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("biz_order_refund")
public class OrderRefund extends TenantEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
* id
*/
@TableId(value = "id")
private Long id;
/**
* 用户id
*/
private Long userId;
/**
* 原始订单编号
*/
private String originOrderNo;
/**
* 订单编号
*/
private String orderNo;
/**
* 订单支付编号
*/
private String orderPayNo;
/**
* 微信支付订单号
*/
private String transactionId;
/**
* 微信退款单号
*/
private String orderRefundNo;
/**
* 微信支付退款单号
*/
private String refundId;
/**
* 退款原因
*/
private String reason;
/**
* 订单总金额
*/
private BigDecimal total;
/**
* 退款金额
*/
private BigDecimal amount;
/**
* 退款渠道
*/
private String channel;
/**
* 退款入账账户
*/
private String userReceivedAccount;
/**
* 退款成功时间
*/
private String successTime;
/**
* 退款创建时间
*/
private String refundCreateTime;
/**
* 【资金账户】 退款所使用资金对应的资金账户类型
*/
private String fundsAccount;
/**
* 用户实际支付金额
*/
private BigDecimal payerTotal;
/**
* 用户退款金额
*/
private BigDecimal payerRefund;
/**
* 应结退款金额
*/
private BigDecimal settlementRefund;
/**
* 应结订单金额
*/
private BigDecimal settlementTotal;
/**
* 优惠退款金额
*/
private BigDecimal discountRefund;
/**
* 手续费退款金额
*/
private BigDecimal refundFee;
/**
* 退款明文信息
*/
private String info;
/**
* 退款状态
*/
private String status;
/**
* 备注
*/
private String remark;
/**
* 删除标志(0代表存在 2代表删除)
*/
@TableLogic
private String delFlag;
}
package org.dromara.order.domain.bo;
import io.github.linpeilie.annotations.AutoMapper;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import org.dromara.order.domain.OrderRefund;
import java.math.BigDecimal;
/**
* 订单退款业务对象 biz_order_refund
*
* @author hzh
* @date 2024-12-31
*/
@Data
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = true)
@AutoMapper(target = OrderRefund.class, reverseConvertGenerate = false)
public class OrderRefundBo extends BaseEntity {
/**
* id
*/
@NotNull(message = "id不能为空", groups = {EditGroup.class})
private Long id;
/**
* 用户id
*/
@NotNull(message = "用户id不能为空", groups = {AddGroup.class, EditGroup.class})
private Long userId;
/**
* 原始订单编号
*/
@NotBlank(message = "原始订单编号不能为空", groups = {AddGroup.class, EditGroup.class})
private String originOrderNo;
/**
* 订单编号
*/
@NotBlank(message = "订单编号不能为空", groups = {AddGroup.class, EditGroup.class})
private String orderNo;
/**
* 订单支付编号
*/
@NotBlank(message = "订单支付编号不能为空", groups = {AddGroup.class, EditGroup.class})
private String orderPayNo;
/**
* 微信支付订单号
*/
@NotBlank(message = "微信支付订单号不能为空", groups = {AddGroup.class, EditGroup.class})
private String transactionId;
/**
* 微信退款单号
*/
@NotBlank(message = "微信退款单号不能为空", groups = {AddGroup.class, EditGroup.class})
private String orderRefundNo;
/**
* 微信支付退款单号
*/
@NotBlank(message = "微信支付退款单号不能为空", groups = {AddGroup.class, EditGroup.class})
private String refundId;
/**
* 退款原因
*/
@NotBlank(message = "退款原因不能为空", groups = {AddGroup.class, EditGroup.class})
private String reason;
/**
* 订单总金额
*/
@NotBlank(message = "订单总金额", groups = {AddGroup.class, EditGroup.class})
private BigDecimal total;
/**
* 退款金额
*/
@NotNull(message = "退款金额不能为空", groups = {AddGroup.class, EditGroup.class})
private BigDecimal amount;
/**
* 退款渠道
*/
@NotBlank(message = "退款渠道不能为空", groups = {AddGroup.class, EditGroup.class})
private String channel;
/**
* 退款入账账户
*/
@NotBlank(message = "退款入账账户不能为空", groups = {AddGroup.class, EditGroup.class})
private String userReceivedAccount;
/**
* 退款成功时间
*/
@NotBlank(message = "退款成功时间不能为空", groups = {AddGroup.class, EditGroup.class})
private String successTime;
/**
* 退款创建时间
*/
@NotBlank(message = "退款创建时间不能为空", groups = {AddGroup.class, EditGroup.class})
private String refundCreateTime;
/**
* 【资金账户】 退款所使用资金对应的资金账户类型
*/
@NotBlank(message = "【资金账户】 退款所使用资金对应的资金账户类型不能为空", groups = {AddGroup.class, EditGroup.class})
private String fundsAccount;
/**
* 用户实际支付金额
*/
@NotNull(message = "用户实际支付金额不能为空", groups = {AddGroup.class, EditGroup.class})
private BigDecimal payerTotal;
/**
* 用户退款金额
*/
@NotNull(message = "用户退款金额不能为空", groups = {AddGroup.class, EditGroup.class})
private BigDecimal payerRefund;
/**
* 应结退款金额
*/
@NotNull(message = "应结退款金额不能为空", groups = {AddGroup.class, EditGroup.class})
private BigDecimal settlementRefund;
/**
* 应结订单金额
*/
@NotNull(message = "应结订单金额不能为空", groups = {AddGroup.class, EditGroup.class})
private BigDecimal settlementTotal;
/**
* 优惠退款金额
*/
@NotNull(message = "优惠退款金额不能为空", groups = {AddGroup.class, EditGroup.class})
private BigDecimal discountRefund;
/**
* 手续费退款金额
*/
@NotNull(message = "手续费退款金额不能为空", groups = {AddGroup.class, EditGroup.class})
private BigDecimal refundFee;
/**
* 退款明文信息
*/
@NotBlank(message = "退款明文信息不能为空", groups = {AddGroup.class, EditGroup.class})
private String info;
/**
* 退款状态
*/
@NotBlank(message = "退款状态不能为空", groups = {AddGroup.class, EditGroup.class})
private String status;
/**
* 备注
*/
@NotBlank(message = "备注不能为空", groups = {AddGroup.class, EditGroup.class})
private String remark;
}
package org.dromara.order.domain.vo;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import lombok.experimental.Accessors;
import org.dromara.order.domain.OrderRefund;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* 订单退款视图对象 biz_order_refund
*
* @author hzh
* @date 2024-12-31
*/
@Data
@Accessors(chain = true)
@ExcelIgnoreUnannotated
@AutoMapper(target = OrderRefund.class)
public class OrderRefundVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* id
*/
@ExcelProperty(value = "id")
private Long id;
/**
* 用户id
*/
@ExcelProperty(value = "用户id")
private Long userId;
/**
* 原始订单编号
*/
@ExcelProperty(value = "原始订单编号")
private String originOrderNo;
/**
* 订单编号
*/
@ExcelProperty(value = "订单编号")
private String orderNo;
/**
* 订单支付编号
*/
@ExcelProperty(value = "订单支付编号")
private String orderPayNo;
/**
* 微信支付订单号
*/
@ExcelProperty(value = "微信支付订单号")
private String transactionId;
/**
* 微信退款单号
*/
@ExcelProperty(value = "微信退款单号")
private String orderRefundNo;
/**
* 微信支付退款单号
*/
@ExcelProperty(value = "微信支付退款单号")
private String refundId;
/**
* 退款原因
*/
@ExcelProperty(value = "退款原因")
private String reason;
/**
* 订单总金额
*/
@ExcelProperty(value = "订单总金额")
private BigDecimal total;
/**
* 退款金额
*/
@ExcelProperty(value = "退款金额")
private BigDecimal amount;
/**
* 退款渠道
*/
@ExcelProperty(value = "退款渠道")
private String channel;
/**
* 退款入账账户
*/
@ExcelProperty(value = "退款入账账户")
private String userReceivedAccount;
/**
* 退款成功时间
*/
@ExcelProperty(value = "退款成功时间")
private String successTime;
/**
* 退款创建时间
*/
@ExcelProperty(value = "退款创建时间")
private String refundCreateTime;
/**
* 【资金账户】 退款所使用资金对应的资金账户类型
*/
@ExcelProperty(value = "【资金账户】 退款所使用资金对应的资金账户类型")
private String fundsAccount;
/**
* 用户实际支付金额
*/
@ExcelProperty(value = "用户实际支付金额")
private BigDecimal payerTotal;
/**
* 用户退款金额
*/
@ExcelProperty(value = "用户退款金额")
private BigDecimal payerRefund;
/**
* 应结退款金额
*/
@ExcelProperty(value = "应结退款金额")
private BigDecimal settlementRefund;
/**
* 应结订单金额
*/
@ExcelProperty(value = "应结订单金额")
private BigDecimal settlementTotal;
/**
* 优惠退款金额
*/
@ExcelProperty(value = "优惠退款金额")
private BigDecimal discountRefund;
/**
* 手续费退款金额
*/
@ExcelProperty(value = "手续费退款金额")
private BigDecimal refundFee;
/**
* 退款明文信息
*/
@ExcelProperty(value = "退款明文信息")
private String info;
/**
* 退款状态
*/
@ExcelProperty(value = "退款状态")
private String status;
/**
* 备注
*/
@ExcelProperty(value = "备注")
private String remark;
}
......@@ -12,20 +12,26 @@ import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.StreamUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.core.utils.ValidatorUtils;
import org.dromara.common.json.utils.JsonUtils;
import org.dromara.common.pay.domain.RefundModel;
import org.dromara.common.pay.service.IWxPayService;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.order.api.RemoteOrderService;
import org.dromara.order.api.domain.OrderPay;
import org.dromara.order.api.domain.RemoteOrder;
import org.dromara.order.api.domain.RemoteSaveOrder;
import org.dromara.order.api.domain.RemoteSaveRefundOrder;
import org.dromara.order.api.enums.OrderStatus;
import org.dromara.order.api.enums.OrderType;
import org.dromara.order.api.enums.Source;
import org.dromara.order.api.enums.TradeType;
import org.dromara.order.constant.WechatTradeState;
import org.dromara.order.domain.bo.OrderBo;
import org.dromara.order.domain.bo.OrderFeeBo;
import org.dromara.order.domain.bo.OrderRefundBo;
import org.dromara.order.domain.bo.OrderTradeBo;
import org.dromara.order.domain.vo.OrderFeeVo;
import org.dromara.order.domain.vo.OrderRefundVo;
import org.dromara.order.domain.vo.OrderTradeVo;
import org.dromara.order.domain.vo.OrderVo;
import org.dromara.order.service.*;
......@@ -38,6 +44,8 @@ import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import static org.dromara.common.pay.util.CurrencyUtils.convertScoreToYuan;
/**
* @author hzh
* @date 2024-12-05
......@@ -49,6 +57,7 @@ public class RemoteOrderServiceImpl implements RemoteOrderService {
private final IOrderService orderService;
private final IOrderTradeService orderTradeService;
private final IOrderRefundService orderRefundService;
private final IOrderFeeService orderFeeService;
private final IWxPayService wxPayService;
......@@ -160,6 +169,65 @@ public class RemoteOrderServiceImpl implements RemoteOrderService {
.setPayInfo(IPayStrategy.pay(JSON.toJSONString(ot), feeList, remoteOrder.getTradeType().name()));
}
@Override
public Boolean createRefundOrder(RemoteSaveRefundOrder remoteOrder) throws Exception {
OrderVo order = orderService.queryList(new OrderBo()
.setOriginOrderNo(remoteOrder.getOriginOrderNo())
.setOrderType(remoteOrder.getOrderType().getType())
).stream().findFirst().orElse(null);
if (Objects.isNull(order)) {
throw new ServiceException("订单不存在,无法进行退款");
}
if (!StringUtils.equals(order.getStatus(), OrderStatus.PAYED.getCode())) {
throw new ServiceException("订单未支付,无法进行退款");
}
OrderRefundVo or = orderRefundService.queryList(
new OrderRefundBo()
.setOrderNo(order.getOrderNo())
.setOrderPayNo(order.getOrderPayNo())
).stream().findFirst().orElse(null);
if (Objects.nonNull(or)) {
throw new ServiceException("订单已发起退款,无法再次进行退款");
}
or = new OrderRefundVo()
.setUserId(order.getUserId())
.setOriginOrderNo(order.getOriginOrderNo())
.setOrderNo(order.getOrderNo())
.setOrderPayNo(order.getOrderPayNo())
.setOrderRefundNo(System.currentTimeMillis() + "")
.setTotal(order.getPayAmount())
.setAmount(order.getPayAmount());
String refund = IPayStrategy.refund(JSON.toJSONString(or), TradeType.JSAPI.name());
RefundModel model = JsonUtils.parseObject(refund, RefundModel.class);
if (Objects.nonNull(model)) {
or.setTransactionId(model.getTransaction_id());
or.setRefundId(model.getRefund_id());
or.setChannel(model.getChannel());
or.setUserReceivedAccount(model.getUser_received_account());
or.setSuccessTime(model.getSuccess_time());
or.setRefundCreateTime(model.getCreate_time());
or.setFundsAccount(model.getFunds_account());
RefundModel.RefundAmount amount = model.getAmount();
if (Objects.nonNull(amount)) {
or.setPayerTotal(convertScoreToYuan(amount.getPayer_total()));
or.setPayerRefund(convertScoreToYuan(amount.getPayer_refund()));
or.setSettlementRefund(convertScoreToYuan(amount.getSettlement_refund()));
or.setSettlementTotal(convertScoreToYuan(amount.getSettlement_total()));
or.setDiscountRefund(convertScoreToYuan(amount.getDiscount_refund()));
or.setRefundFee(convertScoreToYuan(amount.getRefund_fee()));
}
orderRefundService.insertByBo(BeanUtil.copyProperties(or, OrderRefundBo.class));
}
return true;
}
@Override
public List<RemoteOrder> queryList(String orderType, List<String> orderNoList) {
if (CollectionUtils.isEmpty(orderNoList)) {
......@@ -174,6 +242,27 @@ public class RemoteOrderServiceImpl implements RemoteOrderService {
}).collect(Collectors.toList());
}
@Override
public List<RemoteOrder> queryRefundList(String orderType, List<String> orderNoList) {
if (CollectionUtils.isEmpty(orderNoList)) {
return List.of();
}
return orderNoList.stream().map(orderNo -> {
OrderVo order = orderService.getOne(new OrderBo().setOrderType(orderType).setOriginOrderNo(orderNo));
if (Objects.nonNull(order)) {
OrderRefundVo or = orderRefundService.getOne(
new OrderRefundBo().setOrderNo(order.getOrderNo()).setOrderPayNo(order.getOrderPayNo()));
if (Objects.nonNull(or)) {
return new RemoteOrder()
.setOrderType(order.getOrderType())
.setOriginOrderNo(orderNo)
.setStatus(or.getStatus());
}
}
return null;
}).collect(Collectors.toList());
}
@Override
public boolean autoUpdateOrGetCertificate(String serialNumber) throws Exception {
return wxPayService.autoUpdateOrGetCertificate(serialNumber);
......
package org.dromara.order.mapper;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
import org.dromara.order.domain.OrderRefund;
import org.dromara.order.domain.vo.OrderRefundVo;
/**
* 订单退款Mapper接口
*
* @author hzh
* @date 2024-12-31
*/
public interface OrderRefundMapper extends BaseMapperPlus<OrderRefund, OrderRefundVo> {
}
......@@ -16,11 +16,27 @@ public interface IOrderPayService {
*/
boolean notify(String body);
/**
* 退款回调
*
* @param body 回调参数
* @return 回调结果
*/
boolean refundNotify(String body);
/**
* 微信支付查询
*
* @param outTradeNo 【商户订单号】 商户系统内部订单号,只能是数字、大小写字母_-*且在同一个商户号下唯一。
* @return 支付结果
*/
JsapiNotifyModel query(String outTradeNo);
/**
* 退款查询
* @param outRefundNo 商户申请退款时传入的商户系统内部退款单号。
* @return 退款结果
*/
org.dromara.common.pay.domain.RefundModel refundQuery(String outRefundNo);
}
package org.dromara.order.service;
import org.dromara.common.mybatis.service.IBaseService;
import org.dromara.order.domain.OrderRefund;
import org.dromara.order.domain.bo.OrderRefundBo;
import org.dromara.order.domain.vo.OrderRefundVo;
/**
* 订单退款Service接口
*
* @author hzh
* @date 2024-12-31
*/
public interface IOrderRefundService extends IBaseService<OrderRefundVo, OrderRefundBo, OrderRefund> {
}
......@@ -31,6 +31,24 @@ public interface IPayStrategy {
return instance.pay(tradeBody, feeList);
}
/**
* 退款
*
* @param tradeBody 交易对象
* @param tradeType 支付类型
* @return 退款信息
* @throws Exception
*/
static String refund(String tradeBody, String tradeType) throws Exception {
// 授权类型和客户端id
String beanName = tradeType + BASE_NAME;
if (!SpringUtils.containsBean(beanName)) {
throw new ServiceException("支付类型不正确!");
}
IPayStrategy instance = SpringUtils.getBean(beanName);
return instance.refund(tradeBody);
}
/**
* 获得支付信息
*
......@@ -40,4 +58,14 @@ public interface IPayStrategy {
*/
String pay(String tradeBody, List<OrderFeeVo> feeList) throws Exception;
/**
* 退款
*
* @param tradeBody 交易对象
* @return 退款信息
* @throws Exception
*/
String refund(String tradeBody) throws Exception;
}
package org.dromara.order.service.impl;
import com.ijpay.core.utils.DateTimeZoneUtil;
import com.ijpay.wxpay.model.v3.Amount;
import com.ijpay.wxpay.model.v3.Payer;
import com.ijpay.wxpay.model.v3.UnifiedOrderModel;
import com.ijpay.wxpay.model.v3.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.json.utils.JsonUtils;
import org.dromara.common.pay.service.IWxPayService;
import org.dromara.order.domain.bo.OrderTradeBo;
import org.dromara.order.domain.vo.OrderFeeVo;
import org.dromara.order.domain.vo.OrderRefundVo;
import org.dromara.order.service.IPayStrategy;
import org.springframework.stereotype.Service;
......@@ -52,5 +51,20 @@ public class JsapiPayStrategy implements IPayStrategy {
return wxPayService.jsapi(model);
}
@Override
public String refund(String tradeBody) throws Exception {
OrderRefundVo or = JsonUtils.parseObject(tradeBody, OrderRefundVo.class);
//获取支付金额
int amount = new BigDecimal("100").multiply(or.getAmount()).intValue();
if (amount <= 0) {
throw new RuntimeException("退款金额不能小于等于0");
}
amount = 1;
RefundModel model = new RefundModel()
.setOut_trade_no(or.getOrderPayNo())
.setOut_refund_no(or.getOrderRefundNo())
.setAmount(new RefundAmount().setRefund(amount).setTotal(amount).setCurrency("CNY"));
return JsonUtils.toJsonString(wxPayService.refund(model));
}
}
package org.dromara.order.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
import org.dromara.common.mybatis.service.AbstractBaseService;
import org.dromara.order.domain.OrderRefund;
import org.dromara.order.domain.bo.OrderRefundBo;
import org.dromara.order.domain.vo.OrderRefundVo;
import org.dromara.order.mapper.OrderRefundMapper;
import org.dromara.order.service.IOrderRefundService;
import org.springframework.stereotype.Service;
import java.util.Map;
/**
* 订单退款Service业务层处理
*
* @author hzh
* @date 2024-12-31
*/
@RequiredArgsConstructor
@Service
public class OrderRefundServiceImpl extends AbstractBaseService<OrderRefundVo, OrderRefundBo, OrderRefund> implements IOrderRefundService {
private final OrderRefundMapper baseMapper;
@Override
public BaseMapperPlus<OrderRefund, OrderRefundVo> mapper() {
return baseMapper;
}
@Override
public LambdaQueryWrapper<OrderRefund> buildQueryWrapper(OrderRefundBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<OrderRefund> lqw = Wrappers.lambdaQuery();
lqw.eq(bo.getUserId() != null, OrderRefund::getUserId, bo.getUserId());
lqw.eq(StringUtils.isNotBlank(bo.getOrderNo()), OrderRefund::getOrderNo, bo.getOrderNo());
lqw.eq(StringUtils.isNotBlank(bo.getOrderPayNo()), OrderRefund::getOrderPayNo, bo.getOrderPayNo());
lqw.eq(StringUtils.isNotBlank(bo.getTransactionId()), OrderRefund::getTransactionId, bo.getTransactionId());
lqw.eq(StringUtils.isNotBlank(bo.getOrderRefundNo()), OrderRefund::getOrderRefundNo, bo.getOrderRefundNo());
lqw.eq(StringUtils.isNotBlank(bo.getRefundId()), OrderRefund::getRefundId, bo.getRefundId());
lqw.eq(StringUtils.isNotBlank(bo.getReason()), OrderRefund::getReason, bo.getReason());
lqw.eq(bo.getAmount() != null, OrderRefund::getAmount, bo.getAmount());
lqw.eq(StringUtils.isNotBlank(bo.getChannel()), OrderRefund::getChannel, bo.getChannel());
lqw.eq(StringUtils.isNotBlank(bo.getUserReceivedAccount()), OrderRefund::getUserReceivedAccount, bo.getUserReceivedAccount());
lqw.eq(StringUtils.isNotBlank(bo.getSuccessTime()), OrderRefund::getSuccessTime, bo.getSuccessTime());
lqw.eq(StringUtils.isNotBlank(bo.getRefundCreateTime()), OrderRefund::getRefundCreateTime, bo.getRefundCreateTime());
lqw.eq(StringUtils.isNotBlank(bo.getFundsAccount()), OrderRefund::getFundsAccount, bo.getFundsAccount());
lqw.eq(bo.getPayerTotal() != null, OrderRefund::getPayerTotal, bo.getPayerTotal());
lqw.eq(bo.getPayerRefund() != null, OrderRefund::getPayerRefund, bo.getPayerRefund());
lqw.eq(bo.getSettlementRefund() != null, OrderRefund::getSettlementRefund, bo.getSettlementRefund());
lqw.eq(bo.getSettlementTotal() != null, OrderRefund::getSettlementTotal, bo.getSettlementTotal());
lqw.eq(bo.getDiscountRefund() != null, OrderRefund::getDiscountRefund, bo.getDiscountRefund());
lqw.eq(bo.getRefundFee() != null, OrderRefund::getRefundFee, bo.getRefundFee());
lqw.eq(StringUtils.isNotBlank(bo.getInfo()), OrderRefund::getInfo, bo.getInfo());
lqw.eq(StringUtils.isNotBlank(bo.getStatus()), OrderRefund::getStatus, bo.getStatus());
return lqw;
}
}
......@@ -10,14 +10,19 @@ import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.dromara.common.pay.domain.JsapiNotifyModel;
import org.dromara.common.pay.domain.JsapiRefundNotifyModel;
import org.dromara.common.pay.enums.RefundStatus;
import org.dromara.common.pay.service.IWxPayService;
import org.dromara.order.api.enums.OrderStatus;
import org.dromara.order.constant.WechatTradeState;
import org.dromara.order.domain.bo.OrderBo;
import org.dromara.order.domain.bo.OrderRefundBo;
import org.dromara.order.domain.bo.OrderTradeBo;
import org.dromara.order.domain.vo.OrderRefundVo;
import org.dromara.order.domain.vo.OrderTradeVo;
import org.dromara.order.domain.vo.OrderVo;
import org.dromara.order.service.IOrderPayService;
import org.dromara.order.service.IOrderRefundService;
import org.dromara.order.service.IOrderService;
import org.dromara.order.service.IOrderTradeService;
import org.dromara.server.api.RemoteYsOrderService;
......@@ -30,6 +35,8 @@ import java.util.List;
import java.util.Objects;
import java.util.Optional;
import static org.dromara.common.pay.util.CurrencyUtils.convertScoreToYuan;
/**
* @author hzh
* @date 2024-12-09
......@@ -39,6 +46,7 @@ import java.util.Optional;
@RequiredArgsConstructor
public class WeChatOrderPayServiceImpl implements IOrderPayService {
private final IOrderRefundService orderRefundService;
private final IOrderTradeService orderTradeService;
private final IOrderService orderService;
@DubboReference
......@@ -70,6 +78,65 @@ public class WeChatOrderPayServiceImpl implements IOrderPayService {
}
}
@GlobalTransactional(rollbackFor = Exception.class)
@Override
public boolean refundNotify(String body) {
log.info("微信退款回调参数:{}", body);
JSONObject bodyJson = JSONObject.parseObject(body);
try {
JsapiRefundNotifyModel model = wxPayService.refundNotify(
bodyJson.getString("timestamp"),
bodyJson.getString("nonce"),
bodyJson.getString("serialNo"),
bodyJson.getString("signature"),
bodyJson.getString("result")
);
//处理订单
dealRefundOrder(model);
return true;
} catch (Exception e) {
log.error("系统异常", e);
return false;
}
}
/**
* 处理退款订单
*
* @param model 退款回调参数
*/
private void dealRefundOrder(JsapiRefundNotifyModel model) {
OrderRefundVo or = orderRefundService.queryList(new OrderRefundBo()
.setOrderRefundNo(model.getOut_refund_no()))
.stream().findFirst().orElse(null);
if (or == null) {
throw new RuntimeException("退款订单不存在");
}
if (StringUtils.equals(or.getStatus(), RefundStatus.SUCCESS.name())) {
throw new RuntimeException("退款订单已处理");
}
if (StringUtils.equals(model.getRefund_status(), RefundStatus.SUCCESS.name())) {
or.setSuccessTime(model.getSuccess_time());
or.setStatus(model.getRefund_status());
or.setUserReceivedAccount(model.getUser_received_account());
or.setRefundId(model.getRefund_id());
JsapiRefundNotifyModel.Amount amount = model.getAmount();
if (Objects.nonNull(amount)) {
or.setTotal(convertScoreToYuan(amount.getTotal()));
or.setAmount(convertScoreToYuan(amount.getRefund()));
or.setPayerTotal(convertScoreToYuan(amount.getPayer_total()));
or.setPayerRefund(convertScoreToYuan(amount.getPayer_refund()));
}
} else {
or.setRefundId(model.getRefund_id());
or.setStatus(model.getRefund_status());
}
orderRefundService.updateByBo(BeanUtil.copyProperties(or, OrderRefundBo.class));
}
@GlobalTransactional(rollbackFor = Exception.class)
@Override
public JsapiNotifyModel query(String outTradeNo) {
......@@ -79,6 +146,12 @@ public class WeChatOrderPayServiceImpl implements IOrderPayService {
return model;
}
@GlobalTransactional(rollbackFor = Exception.class)
@Override
public org.dromara.common.pay.domain.RefundModel refundQuery(String outRefundNo) {
return wxPayService.refundQuery(outRefundNo);
}
private void dealOrder(JsapiNotifyModel model) {
//支付订单号
String orderPayNo = model.getOut_trade_no();
......
<?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="org.dromara.order.mapper.OrderRefundMapper">
</mapper>
package org.dromara.server.constant;
/**
* @author wenhe
*/
public enum InvoiceType {
//企业
ENTERPRISE,
//个人
PERSONAL;
}
......@@ -5,6 +5,7 @@ import lombok.Getter;
import org.dromara.common.core.utils.StreamUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.order.api.enums.OrderType;
import org.dromara.server.constant.ApplyRelateType;
import org.dromara.server.domain.ApplyPerson;
import org.dromara.server.domain.vo.TravelControlMethodVo;
......@@ -21,8 +22,52 @@ import java.util.function.BiFunction;
public enum ControlMethod {
//申请人和出行人都可以、 申请人可以、出行人可以,不控制
APPLY_AND_TRAVEL("1", "申请人和出行人都可以控制", (cm, personList) -> false),
APPLY_AND_TRAVEL("1", "申请人和出行人都可以控制", (cm, personList) -> {
List<String> phoneList = StreamUtils.toList(personList, ApplyPerson::getPhone);
if (!phoneList.contains(cm.getOrderPersonPhone())) {
return false;
}
List<String> personInfoList = StreamUtils.toList(personList, ApplyPerson::getIdCard);
OrderType orderType = cm.getOrderType();
if (StringUtils.equals(OrderType.AIRPORT.getType(), orderType.getType())) {
return personInfoList.containsAll(cm.getInfoList());
} else if (StringUtils.equals(OrderType.TRAIN.getType(), orderType.getType())) {
return personInfoList.containsAll(cm.getInfoList());
} else if (StringUtils.equals(OrderType.HOTEL.getType(), orderType.getType())) {
return personInfoList.containsAll(cm.getInfoList());
} else {
personInfoList = StreamUtils.toList(personList, ApplyPerson::getPhone);
return personInfoList.containsAll(cm.getInfoList());
}
}),
ONLY_APPLY("2", "申请人可以控制", (cm, personList) -> {
ApplyPerson selfPerson = StreamUtils.findFirst(personList, person -> StringUtils.equals(person.getRelatedType(), ApplyRelateType.SELF.getCode()));
if (selfPerson == null) {
return false;
}
if (!StringUtils.equals(selfPerson.getPhone(), cm.getOrderPersonPhone())) {
return false;
}
List<String> personInfoList = StreamUtils.toList(personList, ApplyPerson::getIdCard);
OrderType orderType = cm.getOrderType();
if (StringUtils.equals(OrderType.AIRPORT.getType(), orderType.getType())) {
return personInfoList.containsAll(cm.getInfoList());
} else if (StringUtils.equals(OrderType.TRAIN.getType(), orderType.getType())) {
return personInfoList.containsAll(cm.getInfoList());
} else if (StringUtils.equals(OrderType.HOTEL.getType(), orderType.getType())) {
return personInfoList.containsAll(cm.getInfoList());
} else {
personInfoList = StreamUtils.toList(personList, ApplyPerson::getPhone);
return personInfoList.containsAll(cm.getInfoList());
}
}),
ONLY_TRAVEL("3", "出行人可以控制", (cm, personList) -> {
List<String> phoneList = StreamUtils.toList(
StreamUtils.filter(personList, person -> !StringUtils.equals(person.getRelatedType(), ApplyRelateType.SELF.getCode())),
ApplyPerson::getPhone);
if (!phoneList.contains(cm.getOrderPersonPhone())) {
return false;
}
List<String> personInfoList = StreamUtils.toList(personList, ApplyPerson::getIdCard);
OrderType orderType = cm.getOrderType();
if (StringUtils.equals(OrderType.AIRPORT.getType(), orderType.getType())) {
......@@ -36,7 +81,6 @@ public enum ControlMethod {
return personInfoList.containsAll(cm.getInfoList());
}
}),
ONLY_TRAVEL("3", "出行人可以控制", (cm, personList) -> false),
NOT_CONTROL("4", "不控制", (cm, personList) -> true);
private final String code;
......@@ -46,7 +90,7 @@ public enum ControlMethod {
public void isMatched(TravelControlMethodVo cm, List<ApplyPerson> personList) {
boolean test = function.apply(cm, personList);
if (!test) {
throw new RuntimeException("管控方式功能配置,请使用合适的申请单!");
throw new RuntimeException("管控方式功能配置,请使用合适的申请单!");
}
}
......
......@@ -7,6 +7,7 @@ import org.dromara.order.api.enums.OrderType;
import org.dromara.server.domain.Apply;
import org.dromara.server.domain.vo.TravelTripLimitVo;
import java.util.List;
import java.util.function.BiFunction;
/**
......@@ -23,16 +24,15 @@ public enum TripLimit {
String startCity = ttl.getStartCity();
String endCity = ttl.getEndCity();
OrderType orderType = ttl.getOrderType();
List<String> addressList = StringUtils.isEmpty(apply.getAddress()) ? List.of() : List.of(apply.getAddress().split(","));
if (StringUtils.equals(OrderType.AIRPORT.getType(), orderType.getType())) {
return StringUtils.equals(startCity, apply.getDepartAddress()) &&
StringUtils.equals(endCity, apply.getArriveAddress());
return addressList.contains(startCity) && addressList.contains(endCity);
} else if (StringUtils.equals(OrderType.TRAIN.getType(), orderType.getType())) {
return StringUtils.equals(startCity, apply.getDepartAddress()) &&
StringUtils.equals(endCity, apply.getArriveAddress());
return addressList.contains(startCity) && addressList.contains(endCity);
} else if (StringUtils.equals(OrderType.HOTEL.getType(), orderType.getType())) {
return StringUtils.equals(endCity, apply.getArriveAddress());
return addressList.contains(endCity);
} else {
return StringUtils.equals(endCity, apply.getArriveAddress());
return addressList.contains(endCity);
}
});
......
......@@ -71,9 +71,11 @@ public class ApplyController extends BaseController {
* 查询出差申请单个人
*/
@GetMapping("/list/self")
public TableDataInfo<ApplyVo> listSelf(PageQuery pageQuery) {
ApplyBo bo = new ApplyBo()
.setApplyUserId(LoginHelper.getUserId());
public TableDataInfo<ApplyVo> listSelf(@RequestParam(required = false, value = "endTimes") String endTime, ApplyBo bo, PageQuery pageQuery) {
bo.setApplyUserId(LoginHelper.getUserId());
if (endTime != null) {
bo.setParams(Map.of("endTime", endTime));
}
return applyService.queryPageList(bo, pageQuery);
}
......
package org.dromara.server.controller;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.common.web.core.BaseController;
import org.dromara.server.domain.bo.CrmAddressBo;
import org.dromara.server.domain.vo.CrmAddressVo;
import org.dromara.server.service.ICrmAddressService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* crm-常用地址
* 前端访问路由地址为:/server/address
*
* @author hzh
* @date 2024-12-24
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/address")
public class CrmAddressController extends BaseController {
private final ICrmAddressService crmAddressService;
/**
* 查询crm-常用地址列表
*/
@GetMapping("/list")
public TableDataInfo<CrmAddressVo> list(PageQuery pageQuery) {
CrmAddressBo bo = new CrmAddressBo().setUserId(LoginHelper.getUserId());
return crmAddressService.queryPageList(bo, pageQuery);
}
/**
* 查询crm-常用地址全量列表
*/
@GetMapping("/listAll")
public R<List<CrmAddressVo>> listAll() {
CrmAddressBo bo = new CrmAddressBo().setUserId(LoginHelper.getUserId());
return R.ok(crmAddressService.queryList(bo));
}
/**
* 获取crm-常用地址详细信息
*
* @param id 主键
*/
@GetMapping("/{id}")
public R<CrmAddressVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long id) {
return R.ok(crmAddressService.queryById(id));
}
/**
* 新增crm-常用地址
*/
@Log(title = "crm-常用地址", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody CrmAddressBo bo) {
bo.setUserId(LoginHelper.getUserId());
return toAjax(crmAddressService.insertByBo(bo));
}
/**
* 设为默认
*/
@Log(title = "crm-常用地址-设为默认", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PostMapping("/setDefault")
public R<Void> setDefault( @RequestBody Long id) {
return toAjax(crmAddressService.setDefault(id));
}
/**
* 修改crm-常用地址
*/
@Log(title = "crm-常用地址", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody CrmAddressBo bo) {
return toAjax(crmAddressService.updateByBo(bo));
}
/**
* 删除crm-常用地址
*
* @param ids 主键串
*/
@Log(title = "crm-常用地址", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] ids) {
return toAjax(crmAddressService.deleteWithValidByIds(List.of(ids), true));
}
}
package org.dromara.server.controller;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.common.web.core.BaseController;
import org.dromara.server.domain.bo.CrmContractBo;
import org.dromara.server.domain.vo.CrmContractVo;
import org.dromara.server.service.ICrmContractService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* crm-常用联系人
* 前端访问路由地址为:/server/contract
*
* @author hzh
* @date 2024-12-24
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/contract")
public class CrmContractController extends BaseController {
private final ICrmContractService crmContractService;
/**
* 查询crm-常用联系人列表
*/
@GetMapping("/list")
public TableDataInfo<CrmContractVo> list(PageQuery pageQuery) {
CrmContractBo bo = new CrmContractBo().setUserId(LoginHelper.getUserId());
return crmContractService.queryPageList(bo, pageQuery);
}
/**
* 查询crm-常用联系人全量列表
*/
@GetMapping("/listAll")
public R<List<CrmContractVo>> listAll() {
CrmContractBo bo = new CrmContractBo().setUserId(LoginHelper.getUserId());
return R.ok(crmContractService.queryList(bo));
}
/**
* 获取crm-常用联系人详细信息
*
* @param id 主键
*/
@GetMapping("/{id}")
public R<CrmContractVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long id) {
return R.ok(crmContractService.queryById(id));
}
/**
* 新增crm-常用联系人
*/
@Log(title = "crm-常用联系人", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody CrmContractBo bo) {
bo.setUserId(LoginHelper.getUserId());
return toAjax(crmContractService.insertByBo(bo));
}
/**
* 修改crm-常用联系人
*/
@Log(title = "crm-常用联系人", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody CrmContractBo bo) {
return toAjax(crmContractService.updateByBo(bo));
}
/**
* 删除crm-常用联系人
*
* @param ids 主键串
*/
@Log(title = "crm-常用联系人", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] ids) {
return toAjax(crmContractService.deleteWithValidByIds(List.of(ids), true));
}
}
package org.dromara.server.controller;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.common.web.core.BaseController;
import org.dromara.server.domain.bo.CrmInvoiceHeaderBo;
import org.dromara.server.domain.vo.CrmInvoiceHeaderVo;
import org.dromara.server.service.ICrmInvoiceHeaderService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* crm-发票抬头管理
* 前端访问路由地址为:/server/invoiceHeader
*
* @author hzh
* @date 2024-12-24
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/invoiceHeader")
public class CrmInvoiceHeaderController extends BaseController {
private final ICrmInvoiceHeaderService crmInvoiceHeaderService;
/**
* 查询crm-发票抬头管理列表
*/
@GetMapping("/list")
public TableDataInfo<CrmInvoiceHeaderVo> list(PageQuery pageQuery) {
CrmInvoiceHeaderBo bo = new CrmInvoiceHeaderBo().setUserId(LoginHelper.getUserId());
return crmInvoiceHeaderService.queryPageList(bo, pageQuery);
}
/**
* 查询crm-发票抬头管理全量列表
*/
@GetMapping("/listAll")
public R<List<CrmInvoiceHeaderVo>> listAll() {
CrmInvoiceHeaderBo bo = new CrmInvoiceHeaderBo().setUserId(LoginHelper.getUserId());
return R.ok(crmInvoiceHeaderService.queryList(bo));
}
/**
* 获取crm-发票抬头管理详细信息
*
* @param id 主键
*/
@GetMapping("/{id}")
public R<CrmInvoiceHeaderVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long id) {
return R.ok(crmInvoiceHeaderService.queryById(id));
}
/**
* 新增crm-发票抬头管理
*/
@Log(title = "crm-发票抬头管理", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody CrmInvoiceHeaderBo bo) {
bo.setUserId(LoginHelper.getUserId());
return toAjax(crmInvoiceHeaderService.insertByBo(bo));
}
/**
* 修改crm-发票抬头管理
*/
@Log(title = "crm-发票抬头管理", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody CrmInvoiceHeaderBo bo) {
return toAjax(crmInvoiceHeaderService.updateByBo(bo));
}
/**
* 删除crm-发票抬头管理
*
* @param ids 主键串
*/
@Log(title = "crm-发票抬头管理", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] ids) {
return toAjax(crmInvoiceHeaderService.deleteWithValidByIds(List.of(ids), true));
}
}
......@@ -2,6 +2,7 @@ package org.dromara.server.controller;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.domain.R;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.order.api.domain.OrderPay;
import org.dromara.order.api.domain.RemoteOrder;
import org.dromara.order.api.domain.RemoteSaveOrder;
......@@ -33,6 +34,7 @@ public class OrderController {
/**
* 下单支付接口
*/
@RepeatSubmit()
@PostMapping("/pay")
public R<OrderPay> pay(@Validated @RequestBody OrderPayVo vo) throws Exception {
OrderType ot = OrderType.getEnum(vo.getOrderType());
......@@ -40,7 +42,29 @@ public class OrderController {
}
/**
* 查询订单状态
* 退款申请接口
*
* @param vo vo
* @return 退款结果
* @throws Exception
*/
@RepeatSubmit()
@PostMapping("/refund")
public R<Boolean> refund(@Validated @RequestBody OrderPayVo vo) throws Exception {
OrderType ot = OrderType.getEnum(vo.getOrderType());
return R.ok(service.refund(vo.getOrderNo(), ot));
}
/**
* 查询订单退款状态
*/
@PostMapping("/orderRefundStatus")
public R<List<RemoteOrder>> orderRefundStatus(@Validated @RequestBody OrderQueryVo vo) {
return R.ok(service.queryRefundList(vo.getOrderType(), vo.getOrderNoList()));
}
/**
* 查询订单支付状态
*/
@PostMapping("/orderStatus")
public R<List<RemoteOrder>> orderStatus(@Validated @RequestBody OrderQueryVo vo) {
......
......@@ -197,4 +197,20 @@ public class TravelConfigController extends BaseController {
return R.ok(travelConfigService.updateByBo(BeanUtil.copyProperties(tc, TravelConfigBo.class)));
}
/**
* 更新用车开关
*
* @param useCar 用车开关
* @return 是否成功
*/
@Log(title = "差旅通用设置-更行用车开关", businessType = BusinessType.UPDATE)
@SaCheckPermission("server:travel:edit")
@RepeatSubmit()
@PutMapping("/updateUseCar")
public R<Boolean> updateUseCar(@RequestBody Boolean useCar) {
TravelConfigVo tc = getTravelConfigVo();
tc.setUseCar(useCar);
return R.ok(travelConfigService.updateByBo(BeanUtil.copyProperties(tc, TravelConfigBo.class)));
}
}
......@@ -56,14 +56,9 @@ public class Apply extends TenantEntity {
private Date applyTime;
/**
* 到达地
* 地址,多个以,分割
*/
private String arriveAddress;
/**
* 出发地
*/
private String departAddress;
private String address;
/**
* 开始时间
......
package org.dromara.server.domain;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import org.dromara.common.tenant.core.TenantEntity;
import java.io.Serial;
import java.math.BigDecimal;
/**
* crm-常用地址对象 crm_address
*
* @author hzh
* @date 2024-12-24
*/
@Data
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = true)
@TableName("crm_address")
public class CrmAddress extends TenantEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
* id
*/
@TableId(value = "id")
private Long id;
/**
* 用户id
*/
private Long userId;
/**
* 地址
*/
private String address;
/**
* 详细地址
*/
private String addressName;
/**
* 纬度
*/
private BigDecimal latitude;
/**
* 经度
*/
private BigDecimal longitude;
/**
* 标签
*/
private String tag;
/**
* 备注
*/
private String remark;
/**
* 是否为默认地址(布尔型,例如 0 表示否,1 表示是)
*/
private Boolean isDefault;
/**
* 删除标志(0代表存在 2代表删除)
*/
@TableLogic
private String delFlag;
}
package org.dromara.server.domain;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.dromara.common.tenant.core.TenantEntity;
import java.io.Serial;
/**
* crm-常用联系人对象 crm_contract
*
* @author hzh
* @date 2024-12-24
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("crm_contract")
public class CrmContract extends TenantEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
* id
*/
@TableId(value = "id")
private Long id;
/**
* 用户id
*/
private Long userId;
/**
* 姓名
*/
private String name;
/**
* 手机号
*/
private String phone;
/**
* 身份证
*/
private String idCard;
/**
* 邮箱
*/
private String email;
/**
* 备注
*/
private String remark;
/**
* 删除标志(0代表存在 2代表删除)
*/
@TableLogic
private String delFlag;
}
package org.dromara.server.domain;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.dromara.common.tenant.core.TenantEntity;
import java.io.Serial;
/**
* crm-发票抬头管理对象 crm_invoice_header
*
* @author hzh
* @date 2024-12-24
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("crm_invoice_header")
public class CrmInvoiceHeader extends TenantEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
* id
*/
@TableId(value = "id")
private Long id;
/**
* 用户id
*/
private Long userId;
/**
* 发票类型
*/
private String invoiceType;
/**
* 公司名称
*/
private String companyName;
/**
* 税号
*/
private String taxId;
/**
* 是否专票
*/
private Boolean isSpecialInvoice;
/**
* 地址
*/
private String address;
/**
* 联系电话
*/
private String phoneNumber;
/**
* 邮箱
*/
private String email;
/**
* 开户银行名称
*/
private String bankName;
/**
* 银行账号
*/
private String bankAccount;
/**
* 是否为默认抬头(布尔型,例如 0 表示否,1 表示是)
*/
private Boolean isDefault;
/**
* 备注
*/
private String remark;
/**
* 删除标志(0代表存在 2代表删除)
*/
@TableLogic
private String delFlag;
}
package org.dromara.server.domain;
import com.alibaba.excel.annotation.ExcelProperty;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
......@@ -71,6 +72,11 @@ public class TravelConfig extends TenantEntity {
*/
private String payMethod;
/**
* 用车开关
*/
private Boolean useCar;
/**
* 删除标志(0代表存在 2代表删除)
*/
......
......@@ -74,6 +74,11 @@ public class TravelConfigPerson extends TenantEntity {
*/
private String payMethod;
/**
* 用车开关
*/
private Boolean useCar;
/**
* 删除标志(0代表存在 2代表删除)
*/
......
......@@ -59,16 +59,11 @@ public class ApplyBo extends BaseEntity {
private Date applyTime;
/**
* 到达地
* 地址,多个以,分割
*/
@NotBlank(message = "到达地不能为空", groups = {AddGroup.class, EditGroup.class})
private String arriveAddress;
@NotBlank(message = "地址不能为空", groups = {AddGroup.class, EditGroup.class})
private String address;
/**
* 出发地
*/
@NotBlank(message = "出发地不能为空", groups = {AddGroup.class, EditGroup.class})
private String departAddress;
/**
* 开始时间
......
package org.dromara.server.domain.bo;
import io.github.linpeilie.annotations.AutoMapper;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import org.dromara.server.domain.CrmAddress;
import java.math.BigDecimal;
/**
* crm-常用地址业务对象 crm_address
*
* @author hzh
* @date 2024-12-24
*/
@Data
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = true)
@AutoMapper(target = CrmAddress.class, reverseConvertGenerate = false)
public class CrmAddressBo extends BaseEntity {
/**
* id
*/
@NotNull(message = "id不能为空", groups = {EditGroup.class})
private Long id;
/**
* 用户id
*/
private Long userId;
/**
* 地址
*/
@NotBlank(message = "地址不能为空", groups = {AddGroup.class, EditGroup.class})
private String address;
/**
* 详细地址
*/
@NotBlank(message = "详细地址不能为空", groups = {AddGroup.class, EditGroup.class})
private String addressName;
/**
* 纬度
*/
@NotNull(message = "纬度不能为空", groups = {AddGroup.class, EditGroup.class})
private BigDecimal latitude;
/**
* 经度
*/
@NotNull(message = "经度不能为空", groups = {AddGroup.class, EditGroup.class})
private BigDecimal longitude;
/**
* 标签
*/
@NotBlank(message = "标签不能为空", groups = {AddGroup.class, EditGroup.class})
private String tag;
/**
* 是否为默认地址(布尔型,例如 0 表示否,1 表示是)
*/
private Boolean isDefault;
/**
* 备注
*/
private String remark;
}
package org.dromara.server.domain.bo;
import io.github.linpeilie.annotations.AutoMapper;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import org.dromara.server.domain.CrmContract;
/**
* crm-常用联系人业务对象 crm_contract
*
* @author hzh
* @date 2024-12-24
*/
@Data
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = true)
@AutoMapper(target = CrmContract.class, reverseConvertGenerate = false)
public class CrmContractBo extends BaseEntity {
/**
* id
*/
@NotNull(message = "id不能为空", groups = {EditGroup.class})
private Long id;
/**
* 用户id
*/
private Long userId;
/**
* 姓名
*/
@NotBlank(message = "姓名不能为空", groups = {AddGroup.class, EditGroup.class})
private String name;
/**
* 手机号
*/
@NotBlank(message = "手机号不能为空", groups = {AddGroup.class, EditGroup.class})
private String phone;
/**
* 身份证
*/
@NotBlank(message = "身份证不能为空", groups = {AddGroup.class, EditGroup.class})
private String idCard;
/**
* 邮箱
*/
@NotBlank(message = "邮箱不能为空", groups = {AddGroup.class, EditGroup.class})
private String email;
/**
* 备注
*/
private String remark;
}
package org.dromara.server.domain.bo;
import io.github.linpeilie.annotations.AutoMapper;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import org.dromara.server.domain.CrmInvoiceHeader;
/**
* crm-发票抬头管理业务对象 crm_invoice_header
*
* @author hzh
* @date 2024-12-24
*/
@Data
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = true)
@AutoMapper(target = CrmInvoiceHeader.class, reverseConvertGenerate = false)
public class CrmInvoiceHeaderBo extends BaseEntity {
/**
* id
*/
@NotNull(message = "id不能为空", groups = {EditGroup.class})
private Long id;
/**
* 用户id
*/
private Long userId;
/**
* 发票类型
*/
@NotBlank(message = "发票类型不能为空", groups = {AddGroup.class, EditGroup.class})
private String invoiceType;
/**
* 公司名称
*/
@NotBlank(message = "公司名称不能为空", groups = {AddGroup.class, EditGroup.class})
private String companyName;
/**
* 税号
*/
private String taxId;
/**
* 是否专票
*/
private Boolean isSpecialInvoice;
/**
* 地址
*/
private String address;
/**
* 联系电话
*/
private String phoneNumber;
/**
* 邮箱
*/
private String email;
/**
* 开户银行名称
*/
private String bankName;
/**
* 银行账号
*/
private String bankAccount;
/**
* 是否为默认抬头(布尔型,例如 0 表示否,1 表示是)
*/
private Boolean isDefault;
/**
* 备注
*/
private String remark;
}
......@@ -73,4 +73,10 @@ public class TravelConfigBo extends BaseEntity {
*/
private String payMethod;
/**
* 用车开关
*/
@NotBlank(message = "用车开关不能为空", groups = {AddGroup.class, EditGroup.class})
private Boolean useCar;
}
......@@ -83,5 +83,9 @@ public class TravelConfigPersonBo extends BaseEntity {
@NotBlank(message = "支付方式不能为空", groups = {AddGroup.class, EditGroup.class})
private String payMethod;
/**
* 用车开关
*/
@NotBlank(message = "用车开关不能为空", groups = {AddGroup.class, EditGroup.class})
private Boolean useCar;
}
......@@ -63,16 +63,10 @@ public class ApplyVo implements Serializable {
private Date applyTime;
/**
* 到达地
* 地址,多个以,分割
*/
@ExcelProperty(value = "到达地")
private String arriveAddress;
/**
* 出发地
*/
@ExcelProperty(value = "出发地")
private String departAddress;
@ExcelProperty(value = "地址")
private String address;
/**
* 开始时间
......
package org.dromara.server.domain.vo;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import org.dromara.common.excel.annotation.ExcelDictFormat;
import org.dromara.common.excel.convert.ExcelDictConvert;
import org.dromara.server.domain.CrmAddress;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* crm-常用地址视图对象 crm_address
*
* @author hzh
* @date 2024-12-24
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = CrmAddress.class)
public class CrmAddressVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* id
*/
@ExcelProperty(value = "id")
private Long id;
/**
* 用户id
*/
@ExcelProperty(value = "用户id")
private Long userId;
/**
* 地址
*/
@ExcelProperty(value = "地址")
private String address;
/**
* 详细地址
*/
@ExcelProperty(value = "详细地址")
private String addressName;
/**
* 纬度
*/
@ExcelProperty(value = "纬度")
private BigDecimal latitude;
/**
* 经度
*/
@ExcelProperty(value = "经度")
private BigDecimal longitude;
/**
* 标签
*/
@ExcelProperty(value = "标签")
private String tag;
/**
* 是否为默认地址(布尔型,例如 0 表示否,1 表示是)
*/
@ExcelProperty(value = "是否为默认地址", converter = ExcelDictConvert.class)
@ExcelDictFormat(readConverterExp = "布=尔型,例如,0=,表=示否,1,表=示是")
private Boolean isDefault;
/**
* 备注
*/
@ExcelProperty(value = "备注")
private String remark;
}
package org.dromara.server.domain.vo;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import org.dromara.server.domain.CrmContract;
import java.io.Serial;
import java.io.Serializable;
/**
* crm-常用联系人视图对象 crm_contract
*
* @author hzh
* @date 2024-12-24
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = CrmContract.class)
public class CrmContractVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* id
*/
@ExcelProperty(value = "id")
private Long id;
/**
* 用户id
*/
@ExcelProperty(value = "用户id")
private Long userId;
/**
* 姓名
*/
@ExcelProperty(value = "姓名")
private String name;
/**
* 手机号
*/
@ExcelProperty(value = "手机号")
private String phone;
/**
* 身份证
*/
@ExcelProperty(value = "身份证")
private String idCard;
/**
* 邮箱
*/
@ExcelProperty(value = "邮箱")
private String email;
/**
* 备注
*/
@ExcelProperty(value = "备注")
private String remark;
}
package org.dromara.server.domain.vo;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import org.dromara.common.excel.annotation.ExcelDictFormat;
import org.dromara.common.excel.convert.ExcelDictConvert;
import org.dromara.server.domain.CrmInvoiceHeader;
import java.io.Serial;
import java.io.Serializable;
/**
* crm-发票抬头管理视图对象 crm_invoice_header
*
* @author hzh
* @date 2024-12-24
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = CrmInvoiceHeader.class)
public class CrmInvoiceHeaderVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* id
*/
@ExcelProperty(value = "id")
private Long id;
/**
* 用户id
*/
@ExcelProperty(value = "用户id")
private Long userId;
/**
* 发票类型
*/
@ExcelProperty(value = "发票类型")
private String invoiceType;
/**
* 公司名称
*/
@ExcelProperty(value = "公司名称")
private String companyName;
/**
* 税号
*/
@ExcelProperty(value = "税号")
private String taxId;
/**
* 是否专票
*/
@ExcelProperty(value = "是否专票", converter = ExcelDictConvert.class)
@ExcelDictFormat(readConverterExp = "布=尔型,例如,0=,表=示否,1,表=示是")
private Boolean isSpecialInvoice;
/**
* 地址
*/
@ExcelProperty(value = "地址")
private String address;
/**
* 联系电话
*/
@ExcelProperty(value = "联系电话")
private String phoneNumber;
/**
* 邮箱
*/
@ExcelProperty(value = "邮箱")
private String email;
/**
* 开户银行名称
*/
@ExcelProperty(value = "开户银行名称")
private String bankName;
/**
* 银行账号
*/
@ExcelProperty(value = "银行账号")
private String bankAccount;
/**
* 是否为默认抬头(布尔型,例如 0 表示否,1 表示是)
*/
@ExcelProperty(value = "是否为默认抬头", converter = ExcelDictConvert.class)
@ExcelDictFormat(readConverterExp = "布=尔型,例如,0=,表=示否,1,表=示是")
private Boolean isDefault;
/**
* 备注
*/
@ExcelProperty(value = "备注")
private String remark;
}
......@@ -9,7 +9,6 @@ import java.util.List;
/**
* @author hzh
* @date 2024-12-09
* @desc TODO
**/
@Data
public class OrderQueryVo {
......
......@@ -94,4 +94,10 @@ public class TravelConfigPersonVo implements Serializable {
*/
private String userPhone;
/**
* 用车开关
*/
@ExcelProperty(value = "支付方式")
private Boolean useCar;
}
......@@ -79,4 +79,10 @@ public class TravelConfigVo implements Serializable {
@ExcelProperty(value = "支付方式")
private String payMethod;
/**
* 用车开关
*/
@ExcelProperty(value = "支付方式")
private Boolean useCar;
}
......@@ -20,4 +20,9 @@ public class TravelControlMethodVo extends TravelVo {
*/
private List<String> infoList;
/**
* 下单人手机号
*/
private String orderPersonPhone;
}
package org.dromara.server.mapper;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
import org.dromara.server.domain.CrmAddress;
import org.dromara.server.domain.vo.CrmAddressVo;
/**
* crm-常用地址Mapper接口
*
* @author hzh
* @date 2024-12-24
*/
public interface CrmAddressMapper extends BaseMapperPlus<CrmAddress, CrmAddressVo> {
}
package org.dromara.server.mapper;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
import org.dromara.server.domain.CrmContract;
import org.dromara.server.domain.vo.CrmContractVo;
/**
* crm-常用联系人Mapper接口
*
* @author hzh
* @date 2024-12-24
*/
public interface CrmContractMapper extends BaseMapperPlus<CrmContract, CrmContractVo> {
}
package org.dromara.server.mapper;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
import org.dromara.server.domain.CrmInvoiceHeader;
import org.dromara.server.domain.vo.CrmInvoiceHeaderVo;
/**
* crm-发票抬头管理Mapper接口
*
* @author hzh
* @date 2024-12-24
*/
public interface CrmInvoiceHeaderMapper extends BaseMapperPlus<CrmInvoiceHeader, CrmInvoiceHeaderVo> {
}
package org.dromara.server.service;
import org.dromara.common.mybatis.service.IBaseService;
import org.dromara.server.domain.CrmAddress;
import org.dromara.server.domain.bo.CrmAddressBo;
import org.dromara.server.domain.vo.CrmAddressVo;
/**
* crm-常用地址Service接口
*
* @author hzh
* @date 2024-12-24
*/
public interface ICrmAddressService extends IBaseService<CrmAddressVo, CrmAddressBo, CrmAddress> {
/**
* 设置为默认地址
*
* @param id id
* @return 是否成功
*/
boolean setDefault(Long id);
}
package org.dromara.server.service;
import org.dromara.common.mybatis.service.IBaseService;
import org.dromara.server.domain.CrmContract;
import org.dromara.server.domain.bo.CrmContractBo;
import org.dromara.server.domain.vo.CrmContractVo;
/**
* crm-常用联系人Service接口
*
* @author hzh
* @date 2024-12-24
*/
public interface ICrmContractService extends IBaseService<CrmContractVo, CrmContractBo, CrmContract> {
}
package org.dromara.server.service;
import org.dromara.common.mybatis.service.IBaseService;
import org.dromara.server.domain.CrmInvoiceHeader;
import org.dromara.server.domain.bo.CrmInvoiceHeaderBo;
import org.dromara.server.domain.vo.CrmInvoiceHeaderVo;
/**
* crm-发票抬头管理Service接口
*
* @author hzh
* @date 2024-12-24
*/
public interface ICrmInvoiceHeaderService extends IBaseService<CrmInvoiceHeaderVo, CrmInvoiceHeaderBo, CrmInvoiceHeader> {
}
......@@ -22,6 +22,16 @@ public interface IPayOrderService {
*/
OrderPay createOrder(String orderNo, OrderType orderType) throws Exception;
/**
* 退款
*
* @param orderNo 订单号
* @param orderType 订单类型
* @return 退款结果
* @throws Exception
*/
Boolean refund(String orderNo, OrderType orderType) throws Exception;
/**
* 查询订单列表
*
......@@ -33,9 +43,19 @@ public interface IPayOrderService {
/**
* 计算费用
*
* @param orderNo 订单号
* @param ot 订单类型
* @param ot 订单类型
* @return 费用列表
*/
List<RemoteSaveOrder.Fee> calcFee(String orderNo, OrderType ot);
/**
* 查询退款订单列表
*
* @param orderType 订单类型
* @param orderNoList 订单号列表
* @return 退款订单列表
*/
List<RemoteOrder> queryRefundList(String orderType, List<String> orderNoList);
}
......@@ -62,8 +62,7 @@ public class ApplyServiceImpl extends AbstractBaseService<ApplyVo, ApplyBo, Appl
lqw.like(StringUtils.isNotEmpty(bo.getApplyName()), Apply::getApplyName, bo.getApplyName());
lqw.like(StringUtils.isNotEmpty(bo.getApplyDeptName()), Apply::getApplyDeptName, bo.getApplyDeptName());
lqw.eq(bo.getApplyTime() != null, Apply::getApplyTime, bo.getApplyTime());
lqw.eq(StringUtils.isNotEmpty(bo.getArriveAddress()), Apply::getArriveAddress, bo.getArriveAddress());
lqw.eq(StringUtils.isNotEmpty(bo.getDepartAddress()), Apply::getDepartAddress, bo.getDepartAddress());
lqw.eq(StringUtils.isNotEmpty(bo.getAddress()), Apply::getAddress, bo.getAddress());
lqw.eq(bo.getStartTime() != null, Apply::getStartTime, bo.getStartTime());
lqw.eq(bo.getEndTime() != null, Apply::getEndTime, bo.getEndTime());
lqw.eq(StringUtils.isNotEmpty(bo.getApplyReason()), Apply::getApplyReason, bo.getApplyReason());
......@@ -77,6 +76,10 @@ public class ApplyServiceImpl extends AbstractBaseService<ApplyVo, ApplyBo, Appl
lqw.in(Apply::getId, CollectionUtils.isEmpty(apList) ? List.of(-1) : StreamUtils.toList(apList, ApplyPerson::getApplyId));
}
});
Optional.ofNullable(params).map(map -> map.get("endTime"))
.ifPresent(endTime -> {
lqw.ge(Apply::getEndTime, endTime);
});
return lqw;
}
......
......@@ -41,7 +41,7 @@ public class CarOrderStrategy implements IOrderStrategy {
//火车票费
RemoteSaveOrder.Fee carFee = new RemoteSaveOrder.Fee()
.setFeeDesc("用车费")
.setFeeAmount(detail.getServiceFee())
.setFeeAmount(detail.getUseVehicleFee())
.setFeeType(FeeType.CAR_FEE);
return new RemoteSaveOrder()
.setFeeList(List.of(fineFee, serviceFee, carFee));
......
package org.dromara.server.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.common.base.Objects;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.utils.StreamUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
import org.dromara.common.mybatis.service.AbstractBaseService;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.server.domain.CrmAddress;
import org.dromara.server.domain.bo.CrmAddressBo;
import org.dromara.server.domain.vo.CrmAddressVo;
import org.dromara.server.mapper.CrmAddressMapper;
import org.dromara.server.service.ICrmAddressService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Map;
/**
* crm-常用地址Service业务层处理
*
* @author hzh
* @date 2024-12-24
*/
@RequiredArgsConstructor
@Service
public class CrmAddressServiceImpl extends AbstractBaseService<CrmAddressVo, CrmAddressBo, CrmAddress> implements ICrmAddressService {
private final CrmAddressMapper baseMapper;
@Override
public BaseMapperPlus<CrmAddress, CrmAddressVo> mapper() {
return baseMapper;
}
@Override
public LambdaQueryWrapper<CrmAddress> buildQueryWrapper(CrmAddressBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<CrmAddress> lqw = Wrappers.lambdaQuery();
lqw.eq(bo.getUserId() != null, CrmAddress::getUserId, bo.getUserId());
lqw.eq(bo.getIsDefault() != null, CrmAddress::getIsDefault, bo.getIsDefault());
lqw.eq(StringUtils.isNotBlank(bo.getAddress()), CrmAddress::getAddress, bo.getAddress());
lqw.like(StringUtils.isNotBlank(bo.getAddressName()), CrmAddress::getAddressName, bo.getAddressName());
lqw.eq(bo.getLatitude() != null, CrmAddress::getLatitude, bo.getLatitude());
lqw.eq(bo.getLongitude() != null, CrmAddress::getLongitude, bo.getLongitude());
lqw.eq(StringUtils.isNotBlank(bo.getTag()), CrmAddress::getTag, bo.getTag());
return lqw;
}
@Override
public void validEntityBeforeSave(CrmAddress entity) {
super.validEntityBeforeSave(entity);
if (Boolean.TRUE.equals(entity.getIsDefault())) {
List<CrmAddress> list = baseMapper.selectList(
buildQueryWrapper(new CrmAddressBo()
.setUserId(LoginHelper.getUserId())
.setIsDefault(true)));
CrmAddress address = StreamUtils.findFirst(list, header -> entity.getId() == null || !Objects.equal(header.getId(), entity.getId()));
if (address != null) {
throw new IllegalArgumentException("只能有一个默认地址");
}
}
}
@Transactional(rollbackFor = Exception.class)
@Override
public boolean setDefault(Long id) {
List<CrmAddress> list = baseMapper.selectList(
buildQueryWrapper(new CrmAddressBo()
.setUserId(LoginHelper.getUserId())
.setIsDefault(true)));
list.forEach(address -> {
address.setIsDefault(false);
baseMapper.updateById(address);
});
CrmAddress address = baseMapper.selectById(id);
if (address == null) {
throw new RuntimeException("地址不存在");
}
address.setIsDefault(true);
baseMapper.updateById(address);
return true;
}
}
package org.dromara.server.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
import org.dromara.common.mybatis.service.AbstractBaseService;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.server.domain.CrmContract;
import org.dromara.server.domain.bo.CrmContractBo;
import org.dromara.server.domain.vo.CrmContractVo;
import org.dromara.server.mapper.CrmContractMapper;
import org.dromara.server.service.ICrmContractService;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
/**
* crm-常用联系人Service业务层处理
*
* @author hzh
* @date 2024-12-24
*/
@RequiredArgsConstructor
@Service
public class CrmContractServiceImpl extends AbstractBaseService<CrmContractVo, CrmContractBo, CrmContract> implements ICrmContractService {
private final CrmContractMapper baseMapper;
@Override
public BaseMapperPlus<CrmContract, CrmContractVo> mapper() {
return baseMapper;
}
@Override
public LambdaQueryWrapper<CrmContract> buildQueryWrapper(CrmContractBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<CrmContract> lqw = Wrappers.lambdaQuery();
lqw.eq(bo.getUserId() != null, CrmContract::getUserId, bo.getUserId());
lqw.like(StringUtils.isNotBlank(bo.getName()), CrmContract::getName, bo.getName());
lqw.eq(StringUtils.isNotBlank(bo.getPhone()), CrmContract::getPhone, bo.getPhone());
lqw.eq(StringUtils.isNotBlank(bo.getIdCard()), CrmContract::getIdCard, bo.getIdCard());
lqw.eq(StringUtils.isNotBlank(bo.getEmail()), CrmContract::getEmail, bo.getEmail());
return lqw;
}
@Override
public void validEntityBeforeSave(CrmContract entity) {
super.validEntityBeforeSave(entity);
List<CrmContract> list = baseMapper.selectList(
buildQueryWrapper(new CrmContractBo()
.setName(entity.getName())
.setPhone(entity.getPhone())
.setUserId(LoginHelper.getUserId())
));
if (CollectionUtils.isNotEmpty(list)) {
throw new RuntimeException("联系人已存在");
}
}
}
package org.dromara.server.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.common.base.Objects;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.utils.StreamUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
import org.dromara.common.mybatis.service.AbstractBaseService;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.server.constant.InvoiceType;
import org.dromara.server.domain.CrmInvoiceHeader;
import org.dromara.server.domain.bo.CrmInvoiceHeaderBo;
import org.dromara.server.domain.vo.CrmInvoiceHeaderVo;
import org.dromara.server.mapper.CrmInvoiceHeaderMapper;
import org.dromara.server.service.ICrmInvoiceHeaderService;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
/**
* crm-发票抬头管理Service业务层处理
*
* @author hzh
* @date 2024-12-24
*/
@RequiredArgsConstructor
@Service
public class CrmInvoiceHeaderServiceImpl extends AbstractBaseService<CrmInvoiceHeaderVo, CrmInvoiceHeaderBo, CrmInvoiceHeader> implements ICrmInvoiceHeaderService {
private final CrmInvoiceHeaderMapper baseMapper;
@Override
public BaseMapperPlus<CrmInvoiceHeader, CrmInvoiceHeaderVo> mapper() {
return baseMapper;
}
@Override
public LambdaQueryWrapper<CrmInvoiceHeader> buildQueryWrapper(CrmInvoiceHeaderBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<CrmInvoiceHeader> lqw = Wrappers.lambdaQuery();
lqw.eq(bo.getUserId() != null, CrmInvoiceHeader::getUserId, bo.getUserId());
lqw.eq(StringUtils.isNotBlank(bo.getInvoiceType()), CrmInvoiceHeader::getInvoiceType, bo.getInvoiceType());
lqw.like(StringUtils.isNotBlank(bo.getCompanyName()), CrmInvoiceHeader::getCompanyName, bo.getCompanyName());
lqw.eq(StringUtils.isNotBlank(bo.getTaxId()), CrmInvoiceHeader::getTaxId, bo.getTaxId());
lqw.eq(bo.getIsSpecialInvoice() != null, CrmInvoiceHeader::getIsSpecialInvoice, bo.getIsSpecialInvoice());
lqw.eq(StringUtils.isNotBlank(bo.getAddress()), CrmInvoiceHeader::getAddress, bo.getAddress());
lqw.eq(StringUtils.isNotBlank(bo.getPhoneNumber()), CrmInvoiceHeader::getPhoneNumber, bo.getPhoneNumber());
lqw.eq(StringUtils.isNotBlank(bo.getEmail()), CrmInvoiceHeader::getEmail, bo.getEmail());
lqw.like(StringUtils.isNotBlank(bo.getBankName()), CrmInvoiceHeader::getBankName, bo.getBankName());
lqw.eq(StringUtils.isNotBlank(bo.getBankAccount()), CrmInvoiceHeader::getBankAccount, bo.getBankAccount());
lqw.eq(bo.getIsDefault() != null, CrmInvoiceHeader::getIsDefault, bo.getIsDefault());
return lqw;
}
@Override
public void validEntityBeforeSave(CrmInvoiceHeader entity) {
super.validEntityBeforeSave(entity);
if (StringUtils.equals(entity.getInvoiceType(), InvoiceType.ENTERPRISE.name())) {
if (StringUtils.isEmpty(entity.getTaxId())) {
throw new IllegalArgumentException("企业类型发票抬头必须填写税号");
}
if (Boolean.TRUE.equals(entity.getIsSpecialInvoice())) {
if (StringUtils.isEmpty(entity.getAddress())) {
throw new IllegalArgumentException("专票类型发票抬头必须填写公司地址");
}
if (StringUtils.isEmpty(entity.getPhoneNumber())) {
throw new IllegalArgumentException("专票类型发票抬头必须填写公司电话");
}
if (StringUtils.isEmpty(entity.getBankName())) {
throw new IllegalArgumentException("专票类型发票抬头必须填写银行名称");
}
if (StringUtils.isEmpty(entity.getBankAccount())) {
throw new IllegalArgumentException("专票类型发票抬头必须填写银行账号");
}
}
}
if (Boolean.TRUE.equals(entity.getIsDefault())) {
List<CrmInvoiceHeader> list = baseMapper.selectList(
buildQueryWrapper(new CrmInvoiceHeaderBo()
.setUserId(LoginHelper.getUserId())
.setIsDefault(true)));
CrmInvoiceHeader cih = StreamUtils.findFirst(list, header -> entity.getId() == null || !Objects.equal(header.getId(), entity.getId()));
if (cih != null) {
throw new IllegalArgumentException("只能有一个默认发票抬头");
}
}
}
}
package org.dromara.server.service.impl;
import com.alibaba.nacos.common.utils.CollectionUtils;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.RequiredArgsConstructor;
import org.apache.dubbo.config.annotation.DubboReference;
import org.dromara.order.api.RemoteOrderService;
import org.dromara.order.api.domain.OrderPay;
import org.dromara.order.api.domain.RemoteOrder;
import org.dromara.order.api.domain.RemoteSaveOrder;
import org.dromara.order.api.domain.RemoteSaveRefundOrder;
import org.dromara.order.api.enums.OrderType;
import org.dromara.order.api.enums.Source;
import org.dromara.order.api.enums.TradeType;
......@@ -43,11 +45,24 @@ public class PayOrderServiceImpl implements IPayOrderService {
return remoteOrderService.createOrder(order);
}
@GlobalTransactional(timeoutMills = 60000, rollbackFor = Exception.class)
@Override
public Boolean refund(String orderNo, OrderType orderType) throws Exception {
return remoteOrderService.createRefundOrder(new RemoteSaveRefundOrder()
.setOrderType(orderType)
.setOriginOrderNo(orderNo));
}
@Override
public List<RemoteOrder> queryList(String orderType, List<String> orderNoList) {
return remoteOrderService.queryList(orderType, orderNoList);
}
@Override
public List<RemoteOrder> queryRefundList(String orderType, List<String> orderNoList) {
return remoteOrderService.queryRefundList(orderType, orderNoList);
}
@Override
public List<RemoteSaveOrder.Fee> calcFee(String orderNo, OrderType ot) {
RemoteSaveOrder order = IOrderStrategy.createOrder(orderNo, ot);
......
......@@ -127,7 +127,8 @@ public class TravelConfigServiceImpl extends AbstractBaseService<TravelConfigVo,
Arrays.stream(ControlMethod.values()).filter(cm -> Objects.equals(cm.getCode(), tc.getControlMethod()))
.findAny().ifPresent(cm -> {
TravelControlMethodVo tcm = new TravelControlMethodVo()
.setInfoList(travelApply.getPersonInfoList());
.setInfoList(travelApply.getPersonInfoList())
.setOrderPersonPhone(LoginHelper.getUserNo().split("-")[1]);
tcm.setOrderType(orderType);
//获取人员信息
List<ApplyPerson> personList = Optional.ofNullable(apply)
......
<?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="org.dromara.server.mapper.CrmAddressMapper">
</mapper>
<?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="org.dromara.server.mapper.CrmContractMapper">
</mapper>
<?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="org.dromara.server.mapper.CrmInvoiceHeaderMapper">
</mapper>
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论