记得上下班打卡 | git大法好,push需谨慎

Commit 8d4e2700 authored by wangyifan's avatar wangyifan

合并“退款原因需求”分支需求

parents 9ff4e5e6 a7e03161
-- 演出票退款原因配置表 + 退款单归因字段
CREATE TABLE IF NOT EXISTS `kylin_order_refund_reasons` (
`mid` int(11) NOT NULL AUTO_INCREMENT,
`reason_id` varchar(32) NOT NULL DEFAULT '' COMMENT '业务ID',
`name` varchar(100) NOT NULL DEFAULT '' COMMENT '退款理由名称',
`need_detail` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否需要二级补充输入 0否 1是',
`placeholder` varchar(200) NOT NULL DEFAULT '' COMMENT '二级输入placeholder',
`is_applied` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否已应用 0未应用 1应用中',
`sort` int(11) NOT NULL DEFAULT '0' COMMENT '排序,越大越靠前',
`is_deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否删除 0未删除 1已删除',
`created_at` datetime DEFAULT NULL,
`updated_at` datetime DEFAULT NULL,
PRIMARY KEY (`mid`),
UNIQUE KEY `uk_reason_id` (`reason_id`),
KEY `idx_is_applied_sort` (`is_applied`, `sort`),
KEY `idx_is_deleted` (`is_deleted`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='演出票退款原因配置';
-- 已建表环境补逻辑删除字段(若已存在可忽略报错)
ALTER TABLE `kylin_order_refund_reasons`
ADD COLUMN `is_deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否删除 0未删除 1已删除' AFTER `sort`;
ALTER TABLE `kylin_order_refund_reasons`
ADD KEY `idx_is_deleted` (`is_deleted`);
ALTER TABLE `kylin_order_refunds`
ADD COLUMN `reason_id` varchar(32) DEFAULT NULL COMMENT '退款原因配置ID' AFTER `reason`,
ADD COLUMN `reason_detail` varchar(200) DEFAULT NULL COMMENT '退款原因二级补充说明' AFTER `reason_id`;
-- 演出票退款原因管理 - 菜单与权限
-- 挂载在:正在映画 → 退款管理 下面(与「订单退款列表」「演出退款管理」同级)
SET @zhengzaiRootId = (
SELECT menu_id
FROM sys_menu
WHERE menu_name = '正在映画'
AND parent_id = 0
LIMIT 1
);
SET @refundManageId = (
SELECT menu_id
FROM sys_menu
WHERE menu_name = '退款管理'
AND parent_id = @zhengzaiRootId
LIMIT 1
);
INSERT INTO sys_menu (menu_name, parent_id, order_num, url, target, menu_type, visible, perms, icon, create_by, create_time, update_by, update_time, remark)
VALUES ('退款原因管理', @refundManageId, 2, '/kylin/refundReasons', 'menuItem', 'C', '0', 'kylin:refundReasons:list', '#', 'admin', NOW(), '', NULL, '演出票退款原因配置');
SET @menuId = LAST_INSERT_ID();
INSERT INTO sys_menu (menu_name, parent_id, order_num, url, target, menu_type, visible, perms, icon, create_by, create_time, update_by, update_time, remark)
VALUES
('退款原因查询', @menuId, 1, '#', '', 'F', '0', 'kylin:refundReasons:list', '#', 'admin', NOW(), '', NULL, ''),
('退款原因新增', @menuId, 2, '#', '', 'F', '0', 'kylin:refundReasons:create', '#', 'admin', NOW(), '', NULL, ''),
('退款原因修改', @menuId, 3, '#', '', 'F', '0', 'kylin:refundReasons:update', '#', 'admin', NOW(), '', NULL, ''),
('退款原因删除', @menuId, 4, '#', '', 'F', '0', 'kylin:refundReasons:delete', '#', 'admin', NOW(), '', NULL, ''),
('退款原因应用', @menuId, 5, '#', '', 'F', '0', 'kylin:refundReasons:apply', '#', 'admin', NOW(), '', NULL, '');
......@@ -106,6 +106,11 @@ public class KylinRedisConst {
public static final String KYLIN_EXPRESS_MODULES = "kylin:express:modules";
/**
* 已应用的演出票退款原因列表
*/
public static final String KYLIN_ORDER_REFUND_REASONS_APPLIED = "kylin:order:refund:reasons:applied";
public static final String REDIS_KEY_KYLIN_PERFORM_SUBSCRIBE = "kylin:performSubscribe:uid:";
public static final String REDIS_KEY_KYLIN_PERFORMANCE_SUBSCRIBE = "kylin:performance:subscribe:"; //演出预约
......
package com.liquidnet.service.kylin.dto.param;
import com.liquidnet.service.kylin.entity.KylinOrderRefundReasons;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.beans.BeanUtils;
import java.time.LocalDateTime;
import java.util.List;
/**
* 退款原因配置参数
*/
@Data
@ApiModel("退款原因配置参数")
public class OrderRefundReasonParam {
@ApiModelProperty(value = "原因业务ID")
private String reasonId;
@ApiModelProperty(value = "退款理由名称")
private String name;
@ApiModelProperty(value = "是否需要二级补充输入 0否 1是")
private Integer needDetail;
@ApiModelProperty(value = "二级输入placeholder")
private String placeholder;
@ApiModelProperty(value = "是否已应用 0未应用 1应用中")
private Integer isApplied;
@ApiModelProperty(value = "排序")
private Integer sort;
@ApiModelProperty(value = "批量操作ID列表")
private List<String> ids;
public KylinOrderRefundReasons getFields(String reasonId, LocalDateTime createdAt) {
KylinOrderRefundReasons entity = new KylinOrderRefundReasons();
BeanUtils.copyProperties(this, entity);
if (reasonId != null) {
entity.setReasonId(reasonId);
}
if (createdAt != null) {
entity.setCreatedAt(createdAt);
}
if (entity.getNeedDetail() == null) {
entity.setNeedDetail(0);
}
if (entity.getPlaceholder() == null) {
entity.setPlaceholder("");
}
if (entity.getIsApplied() == null) {
entity.setIsApplied(0);
}
if (entity.getIsDeleted() == null) {
entity.setIsDeleted(0);
}
if (entity.getSort() == null) {
entity.setSort(0);
}
if (entity.getNeedDetail() != null && entity.getNeedDetail() == 0) {
entity.setPlaceholder("");
}
entity.setUpdatedAt(LocalDateTime.now());
return entity;
}
}
package com.liquidnet.service.kylin.dto.param;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* 退款原因配置搜索参数
*/
@Data
@ApiModel("退款原因配置搜索参数")
public class OrderRefundReasonSearchParam {
@ApiModelProperty(value = "退款理由名称")
private String name;
@ApiModelProperty(value = "是否已应用 0未应用 1应用中")
private Integer isApplied;
@ApiModelProperty(value = "页码")
private Integer pageNum = 1;
@ApiModelProperty(value = "每页数量")
private Integer pageSize = 10;
}
......@@ -23,6 +23,16 @@ public class RefundApplyParam implements Serializable {
private String reason;
/**
* 退款原因配置ID
*/
private String reasonId;
/**
* 退款原因二级补充说明
*/
private String reasonDetail;
private BigDecimal RefundPriceExpress;
private List<String> ticketEntityIds;
......
......@@ -23,6 +23,16 @@ public class RefundBatchApplyParam implements Serializable {
private String reason;
/**
* 退款原因配置ID
*/
private String reasonId;
/**
* 退款原因二级补充说明
*/
private String reasonDetail;
private Integer status;
private Integer refundStatus;
......
package com.liquidnet.service.kylin.dto.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
/**
* 退款原因配置 VO
*/
@Data
@ApiModel("退款原因配置")
public class OrderRefundReasonVo implements Serializable, Cloneable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "原因业务ID")
private String reasonId;
@ApiModelProperty(value = "退款理由名称")
private String name;
@ApiModelProperty(value = "是否需要二级补充输入 0否 1是")
private Integer needDetail;
@ApiModelProperty(value = "二级输入placeholder")
private String placeholder;
@ApiModelProperty(value = "是否已应用 0未应用 1应用中")
private Integer isApplied;
@ApiModelProperty(value = "应用状态名称")
private String isAppliedName;
@ApiModelProperty(value = "排序")
private Integer sort;
@ApiModelProperty(value = "创建时间")
private String createdAt;
@ApiModelProperty(value = "修改时间")
private String updatedAt;
private static final OrderRefundReasonVo OBJ = new OrderRefundReasonVo();
public static OrderRefundReasonVo getNew() {
try {
return (OrderRefundReasonVo) OBJ.clone();
} catch (CloneNotSupportedException e) {
return new OrderRefundReasonVo();
}
}
}
......@@ -91,6 +91,12 @@ public class KylinOrderRefundsAdminVo implements Serializable,Cloneable {
@ApiModelProperty(value = "退款原因")
private String reason;
@ApiModelProperty(value = "退款原因配置ID")
private String reasonId;
@ApiModelProperty(value = "退款原因二级补充说明")
private String reasonDetail;
@ApiModelProperty(value = "审核人id")
private String auditorId;
......
......@@ -89,6 +89,12 @@ public class KylinOrderRefundsVo implements Serializable,Cloneable {
@ApiModelProperty(value = "退款原因")
private String reason;
@ApiModelProperty(value = "退款原因配置ID")
private String reasonId;
@ApiModelProperty(value = "退款原因二级补充说明")
private String reasonDetail;
@ApiModelProperty(value = "审核人id")
private String auditorId;
......
package com.liquidnet.service.kylin.service;
import com.liquidnet.service.kylin.dto.vo.OrderRefundReasonVo;
import java.util.List;
/**
* 退款原因(App/H5)
*/
public interface IKylinOrderRefundReasonService {
/**
* 已应用退款理由列表(Redis 缓存)
*/
List<OrderRefundReasonVo> listApplied();
/**
* 按 reasonId 从已应用列表取配置;不存在返回 null
*/
OrderRefundReasonVo getAppliedByReasonId(String reasonId);
}
package com.liquidnet.service.kylin.service.admin;
import com.github.pagehelper.PageInfo;
import com.liquidnet.service.kylin.dto.param.OrderRefundReasonParam;
import com.liquidnet.service.kylin.dto.param.OrderRefundReasonSearchParam;
import com.liquidnet.service.kylin.dto.vo.OrderRefundReasonVo;
import com.liquidnet.service.kylin.entity.KylinOrderRefundReasons;
import java.util.List;
/**
* 退款原因配置管理
*/
public interface IOrderRefundReasonAdminService {
Boolean create(OrderRefundReasonParam param);
Boolean update(OrderRefundReasonParam param);
OrderRefundReasonVo detail(String reasonId);
Boolean delete(List<String> reasonIds);
PageInfo<KylinOrderRefundReasons> reasonList(OrderRefundReasonSearchParam param);
/**
* 应用 / 取消应用
*
* @param reasonId 原因ID
* @param isApplied 1应用 0取消应用
*/
Boolean apply(String reasonId, Integer isApplied);
/**
* 已应用列表(读缓存)
*/
List<OrderRefundReasonVo> listApplied();
}
package com.liquidnet.service.kylin.utils;
import com.liquidnet.service.kylin.dto.vo.OrderRefundReasonVo;
import lombok.Getter;
import org.apache.commons.lang3.StringUtils;
import java.util.List;
/**
* 退款原因展示文案与校验工具
*/
public final class OrderRefundReasonUtils {
private OrderRefundReasonUtils() {
}
/**
* 校验已应用退款原因,并组装落库字段
*
* @param reasonId 原因配置 ID
* @param reasonDetail 二级补充说明
* @param appliedList 已应用原因列表(可从缓存取)
*/
public static ResolvedRefundReason resolve(String reasonId, String reasonDetail, List<OrderRefundReasonVo> appliedList) {
if (StringUtils.isBlank(reasonId)) {
return ResolvedRefundReason.fail("请选择退款原因");
}
OrderRefundReasonVo matched = findByReasonId(reasonId, appliedList);
if (matched == null) {
return ResolvedRefundReason.fail("退款原因无效或未应用");
}
return resolve(matched, reasonDetail);
}
/**
* 已拿到配置项时的校验与组装
*/
public static ResolvedRefundReason resolve(OrderRefundReasonVo matched, String reasonDetail) {
if (matched == null) {
return ResolvedRefundReason.fail("退款原因无效或未应用");
}
String detail = StringUtils.trimToEmpty(reasonDetail);
boolean needDetail = matched.getNeedDetail() != null && matched.getNeedDetail() == 1;
if (needDetail && StringUtils.isBlank(detail)) {
return ResolvedRefundReason.fail("请填写补充说明");
}
if (!needDetail) {
detail = null;
} else {
detail = truncate(detail, 200);
}
String snapshot = buildReasonSnapshot(matched.getName(), detail);
return ResolvedRefundReason.ok(matched.getReasonId(), detail, snapshot);
}
public static OrderRefundReasonVo findByReasonId(String reasonId, List<OrderRefundReasonVo> appliedList) {
if (StringUtils.isBlank(reasonId) || appliedList == null) {
return null;
}
for (OrderRefundReasonVo item : appliedList) {
if (reasonId.equals(item.getReasonId())) {
return item;
}
}
return null;
}
/**
* 组装 reason 快照:无二级写 name;有二级写 name:detail,截断至 200
*/
public static String buildReasonSnapshot(String name, String reasonDetail) {
String base = StringUtils.defaultString(name, "");
if (StringUtils.isBlank(reasonDetail)) {
return truncate(base, 200);
}
return truncate(base + ":" + reasonDetail.trim(), 200);
}
public static String truncate(String value, int maxLen) {
if (value == null) {
return "";
}
if (value.length() <= maxLen) {
return value;
}
return value.substring(0, maxLen);
}
@Getter
public static final class ResolvedRefundReason {
private final boolean success;
private final String errorMsg;
private final String reasonId;
private final String reasonDetail;
private final String reasonSnapshot;
private ResolvedRefundReason(boolean success, String errorMsg, String reasonId, String reasonDetail, String reasonSnapshot) {
this.success = success;
this.errorMsg = errorMsg;
this.reasonId = reasonId;
this.reasonDetail = reasonDetail;
this.reasonSnapshot = reasonSnapshot;
}
public static ResolvedRefundReason ok(String reasonId, String reasonDetail, String reasonSnapshot) {
return new ResolvedRefundReason(true, null, reasonId, reasonDetail, reasonSnapshot);
}
public static ResolvedRefundReason fail(String errorMsg) {
return new ResolvedRefundReason(false, errorMsg, null, null, null);
}
}
}
package com.liquidnet.client.admin.web.controller.zhengzai.kylin;
import com.github.pagehelper.PageInfo;
import com.liquidnet.client.admin.common.annotation.Log;
import com.liquidnet.client.admin.common.core.controller.BaseController;
import com.liquidnet.client.admin.common.core.domain.AjaxResult;
import com.liquidnet.client.admin.common.core.page.TableDataInfo;
import com.liquidnet.client.admin.common.enums.BusinessType;
import com.liquidnet.client.admin.zhengzai.kylin.service.impl.KylinOrderRefundReasonAdminServiceImpl;
import com.liquidnet.service.kylin.dto.param.OrderRefundReasonParam;
import com.liquidnet.service.kylin.dto.param.OrderRefundReasonSearchParam;
import com.liquidnet.service.kylin.dto.vo.OrderRefundReasonVo;
import com.liquidnet.service.kylin.entity.KylinOrderRefundReasons;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 退款原因管理
*/
@Controller
@RequestMapping("/kylin/refundReasons")
public class KylinOrderRefundReasonsAdminController extends BaseController {
private String prefix = "zhengzai/kylin/refundReasons";
@Autowired
private KylinOrderRefundReasonAdminServiceImpl refundReasonAdminService;
@RequiresPermissions("kylin:refundReasons:list")
@GetMapping()
public String list() {
return prefix + "/refundReasons";
}
@RequiresPermissions("kylin:refundReasons:list")
@PostMapping("list")
@ResponseBody
public TableDataInfo listData(OrderRefundReasonSearchParam param) {
PageInfo<KylinOrderRefundReasons> result = refundReasonAdminService.reasonList(param);
return getDataTable(result.getList());
}
@GetMapping("/create")
public String create() {
return prefix + "/create";
}
@Log(title = "创建退款原因", businessType = BusinessType.INSERT)
@RequiresPermissions("kylin:refundReasons:create")
@PostMapping("create")
@ResponseBody
public AjaxResult createSave(OrderRefundReasonParam param) {
Boolean res = refundReasonAdminService.create(param);
return res ? success() : error("添加退款原因失败");
}
@GetMapping("/update/{reasonId}")
public String update(@PathVariable("reasonId") String reasonId, ModelMap mmap) {
OrderRefundReasonVo vo = refundReasonAdminService.detail(reasonId);
if (vo == null || (vo.getIsApplied() != null && vo.getIsApplied() == 1)) {
mmap.put("errorMsg", "应用中的退款原因不可编辑,请先取消应用");
}
mmap.put("RefundReasonVo", vo);
return prefix + "/update";
}
@Log(title = "修改退款原因", businessType = BusinessType.UPDATE)
@RequiresPermissions("kylin:refundReasons:update")
@PostMapping("update")
@ResponseBody
public AjaxResult updateSave(OrderRefundReasonParam param) {
Boolean res = refundReasonAdminService.update(param);
return res ? success() : error("修改失败(应用中不可编辑,或数据不存在)");
}
@Log(title = "删除退款原因", businessType = BusinessType.DELETE)
@RequiresPermissions("kylin:refundReasons:delete")
@PostMapping("delete")
@ResponseBody
public AjaxResult delete(OrderRefundReasonParam param) {
List<String> ids = param.getIds();
Boolean result = refundReasonAdminService.delete(ids);
return result ? success("删除成功") : error("删除失败(应用中的原因需先取消应用,或数据不存在)");
}
@Log(title = "应用/取消应用退款原因", businessType = BusinessType.UPDATE)
@RequiresPermissions("kylin:refundReasons:apply")
@PutMapping("apply")
@ResponseBody
public AjaxResult apply(@RequestParam("reasonId") String reasonId,
@RequestParam("isApplied") Integer isApplied) {
Boolean result = refundReasonAdminService.apply(reasonId, isApplied);
return result ? success() : error("操作失败");
}
/**
* 已应用列表(供申请页下拉,走缓存)
*/
@RequiresPermissions(value = {"kylin:refund:apply", "kylin:refundBatch:apply", "kylin:refundReasons:list"}, logical = Logical.OR)
@GetMapping("appliedList")
@ResponseBody
public AjaxResult appliedList() {
List<OrderRefundReasonVo> list = refundReasonAdminService.listApplied();
return AjaxResult.success(list);
}
}
......@@ -34,9 +34,17 @@
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label layui-required is-required">备注</label>
<label class="col-sm-2 control-label layui-required is-required">退款原因</label>
<div class="col-sm-10">
<textarea name="reason" maxlength="500" class="form-control layui-required" rows="3"></textarea>
<select name="reasonId" id="reasonId" class="form-control layui-required" required>
<option value="">请选择退款原因</option>
</select>
</div>
</div>
<div class="form-group" id="reasonDetailGroup" style="display:none;">
<label class="col-sm-2 control-label layui-required is-required">补充说明:</label>
<div class="col-sm-10">
<textarea name="reasonDetail" id="reasonDetail" maxlength="200" class="form-control" rows="3"></textarea>
</div>
</div>
</form>
......@@ -44,6 +52,38 @@
<th:block th:include="include :: footer"/>
<script type="text/javascript">
var prefix = ctx + "kylin/refund";
var reasonPrefix = ctx + "kylin/refundReasons";
function loadAppliedReasons() {
$.ajax({
url: reasonPrefix + "/appliedList",
type: "get",
dataType: "json",
success: function (result) {
if (result.code == 0 && result.data) {
var $sel = $("#reasonId");
$sel.find("option:not(:first)").remove();
for (var i = 0; i < result.data.length; i++) {
var item = result.data[i];
$sel.append('<option value="' + item.reasonId + '" data-need-detail="' + item.needDetail + '" data-placeholder="' + (item.placeholder || '') + '">' + item.name + '</option>');
}
}
}
});
}
function onReasonChange() {
var $opt = $("#reasonId option:selected");
var needDetail = $opt.data("need-detail");
var placeholder = $opt.data("placeholder") || "请填写补充说明";
if (needDetail == 1) {
$("#reasonDetailGroup").show();
$("#reasonDetail").attr("placeholder", placeholder);
} else {
$("#reasonDetailGroup").hide();
$("#reasonDetail").val("");
}
}
$("#form-post-add").validate({
onkeyup: false,
......@@ -174,7 +214,8 @@
});
function submitHandler() {
var reason = $('#form-post-add').find("[name='reason']").val();
var reasonId = $('#form-post-add').find("[name='reasonId']").val();
var reasonDetail = $('#form-post-add').find("[name='reasonDetail']").val();
var orderTicketsId = $('#form-post-add').find("[name='orderTicketsId']").val();
var rows = $.common.isEmpty(table.options.uniqueId) ? $.table.selectFirstColumns() : $.table.selectColumns(table.options.uniqueId);
if (!orderTicketsId) {
......@@ -185,8 +226,13 @@
layer.msg("请选择需要退款的入场人订单");
return false;
}
if (!reason) {
layer.msg("请填写备注");
if (!reasonId) {
layer.msg("请选择退款原因");
return false;
}
var $opt = $("#reasonId option:selected");
if ($opt.data("need-detail") == 1 && !$.common.trim(reasonDetail)) {
layer.msg("请填写补充说明");
return false;
}
if ($.validate.form()) {
......@@ -204,6 +250,11 @@
}
}
$(function () {
loadAppliedReasons();
$("#reasonId").on("change", onReasonChange);
});
</script>
</body>
</html>
......@@ -147,7 +147,7 @@
<div class="form-control-static" th:text="${KylinOrderRefundsAdminVo.applicantName}"></div>
<label class="col-sm-2 control-label">申请时间:</label>
<div class="form-control-static" th:text="${KylinOrderRefundsAdminVo.applicantAt}"></div>
<label class="col-sm-2 control-label">申请备注</label>
<label class="col-sm-2 control-label">退款原因</label>
<div class="form-control-static" th:text="${KylinOrderRefundsAdminVo.reason}"></div>
</div>
<div class="form-group">
......
......@@ -368,6 +368,19 @@
field: 'priceExpress',
title: '退快递费金额'
},
{
field: 'reason',
title: '退款原因',
formatter: function (value) {
if (!value) {
return '';
}
if (value.length > 30) {
return '<span title="' + value.replace(/"/g, '&quot;') + '">' + value.substring(0, 30) + '...</span>';
}
return value;
}
},
{
field: 'statusName',
title: '退款状态'
......
......@@ -27,9 +27,17 @@
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label layui-required is-required">备注</label>
<label class="col-sm-3 control-label layui-required is-required">退款原因</label>
<div class="col-sm-8">
<textarea name="reason" maxlength="500" class="form-control layui-required" rows="3"></textarea>
<select name="reasonId" id="reasonId" class="form-control layui-required" required>
<option value="">请选择退款原因</option>
</select>
</div>
</div>
<div class="form-group" id="reasonDetailGroup" style="display:none;">
<label class="col-sm-3 control-label layui-required is-required">补充说明:</label>
<div class="col-sm-8">
<textarea name="reasonDetail" id="reasonDetail" maxlength="200" class="form-control" rows="3"></textarea>
</div>
</div>
</form>
......@@ -37,7 +45,38 @@
<th:block th:include="include :: footer" />
<script type="text/javascript">
var prefix = ctx + "kylin/refundBatch";
var reasonPrefix = ctx + "kylin/refundReasons";
function loadAppliedReasons() {
$.ajax({
url: reasonPrefix + "/appliedList",
type: "get",
dataType: "json",
success: function (result) {
if (result.code == 0 && result.data) {
var $sel = $("#reasonId");
$sel.find("option:not(:first)").remove();
for (var i = 0; i < result.data.length; i++) {
var item = result.data[i];
$sel.append('<option value="' + item.reasonId + '" data-need-detail="' + item.needDetail + '" data-placeholder="' + (item.placeholder || '') + '">' + item.name + '</option>');
}
}
}
});
}
function onReasonChange() {
var $opt = $("#reasonId option:selected");
var needDetail = $opt.data("need-detail");
var placeholder = $opt.data("placeholder") || "请填写补充说明";
if (needDetail == 1) {
$("#reasonDetailGroup").show();
$("#reasonDetail").attr("placeholder", placeholder);
} else {
$("#reasonDetailGroup").hide();
$("#reasonDetail").val("");
}
}
$("#form-post-add").validate({
onkeyup: false,
rules:{
......@@ -136,14 +175,20 @@
});
function submitHandler() {
var reason = $('#form-post-add').find("[name='reason']").val();
var reasonId = $('#form-post-add').find("[name='reasonId']").val();
var reasonDetail = $('#form-post-add').find("[name='reasonDetail']").val();
var targetId = $('#form-post-add').find("[name='targetId']").val();
if (!targetId) {
layer.msg("演出id有误");
return false;
}
if (!reason) {
layer.msg("请填写备注");
if (!reasonId) {
layer.msg("请选择退款原因");
return false;
}
var $opt = $("#reasonId option:selected");
if ($opt.data("need-detail") == 1 && !$.common.trim(reasonDetail)) {
layer.msg("请填写补充说明");
return false;
}
if ($.validate.form()) {
......@@ -151,6 +196,11 @@
$.operate.save(prefix + "/apply", data);
}
}
$(function () {
loadAppliedReasons();
$("#reasonId").on("change", onReasonChange);
});
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
<head>
<th:block th:include="include :: header('添加退款原因')"/>
</head>
<body class="white-bg">
<div class="wrapper wrapper-content animated fadeInRight ibox-content">
<form class="form-horizontal m" id="form-reason-add">
<div class="form-group">
<label class="col-sm-3 control-label is-required">退款理由名称:</label>
<div class="col-sm-8">
<input class="form-control" type="text" name="name" id="name"
maxlength="100" placeholder="展示给用户的文案" required>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label is-required">是否需补充说明:</label>
<div class="col-sm-8">
<div class="radio check-box">
<label>
<input type="radio" value="0" name="needDetail" checked> 否(仅选择)
</label>
</div>
<div class="radio check-box">
<label>
<input type="radio" value="1" name="needDetail"> 是(选择后需输入)
</label>
</div>
</div>
</div>
<div class="form-group" id="placeholderGroup" style="display:none;">
<label class="col-sm-3 control-label is-required">二级输入 placeholder:</label>
<div class="col-sm-8">
<input class="form-control" type="text" name="placeholder" id="placeholder"
maxlength="200" placeholder="请输入补充说明的提示文案">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">排序:</label>
<div class="col-sm-8">
<input class="form-control" type="number" name="sort" id="sort" value="0">
<span class="help-block m-b-none"><i class="fa fa-info-circle"></i> 数值越大越靠前</span>
</div>
</div>
</form>
</div>
<th:block th:include="include :: footer"/>
<script type="text/javascript">
var prefix = ctx + "kylin/refundReasons";
function togglePlaceholderGroup() {
if ($('input[name="needDetail"]:checked').val() == '1') {
$('#placeholderGroup').show();
} else {
$('#placeholderGroup').hide();
$('#placeholder').val('');
}
}
function submitHandler() {
var name = $('#name').val().trim();
if (!name) {
$.modal.alertWarning("请填写退款理由名称");
return false;
}
var needDetail = $('input[name="needDetail"]:checked').val();
if (needDetail == '1' && !$('#placeholder').val().trim()) {
$.modal.alertWarning("请填写二级输入 placeholder");
return false;
}
if ($.validate.form()) {
var data = $('#form-reason-add').serializeArray();
$.operate.save(prefix + "/create", data);
}
}
$(function () {
// 本页 radio 走 iCheck,必须用 ifChecked,否则选「是」不会展示 placeholder
$('input[name="needDetail"]').on('ifChecked change', togglePlaceholderGroup);
togglePlaceholderGroup();
});
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
<head>
<th:block th:include="include :: header('退款原因列表')"/>
<style>
.btn-disabled-edit {
color: #ccc !important;
cursor: not-allowed !important;
pointer-events: none;
}
</style>
</head>
<body class="gray-bg">
<div class="container-div">
<div class="row">
<div class="col-sm-12 search-collapse">
<form id="formId">
<div class="select-list">
<ul>
<li>
<label>名称:</label>
<input type="text" name="name"/>
</li>
<li>
<label>应用状态:</label>
<select name="isApplied">
<option value="">全部</option>
<option value="1">应用中</option>
<option value="0">未应用</option>
</select>
</li>
<li>
<a class="btn btn-primary btn-rounded btn-sm" onclick="$.table.search()"><i
class="fa fa-search"></i>&nbsp;搜索</a>
<a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset()"><i
class="fa fa-refresh"></i>&nbsp;重置</a>
</li>
</ul>
</div>
</form>
</div>
<div class="btn-group-sm" id="toolbar" role="group">
<a class="btn btn-success" onclick="$.operate.add()" shiro:hasPermission="kylin:refundReasons:create">
<i class="fa fa-plus"></i> 添加
</a>
</div>
<div class="col-sm-12 select-table table-bordered">
<table id="bootstrap-table"></table>
</div>
</div>
</div>
<th:block th:include="include :: footer"/>
<script th:inline="javascript">
var updateFlag = [[${@permission.hasPermi('kylin:refundReasons:update')}]];
var removeFlag = [[${@permission.hasPermi('kylin:refundReasons:delete')}]];
var applyFlag = [[${@permission.hasPermi('kylin:refundReasons:apply')}]];
var prefix = ctx + "kylin/refundReasons";
$(function () {
var options = {
url: prefix + "/list",
updateUrl: prefix + "/update/{id}",
createUrl: prefix + "/create",
removeUrl: prefix + "/delete",
modalName: "退款原因",
columns: [
{
field: 'name',
title: '退款理由'
},
{
field: 'needDetail',
title: '需补充说明',
formatter: function (value) {
return value == 1 ? '是' : '否';
}
},
{
field: 'placeholder',
title: '二级输入placeholder'
},
{
field: 'isApplied',
title: '应用状态',
formatter: function (value) {
if (value == 1) {
return '<span class="badge badge-primary">应用中</span>';
}
return '<span class="badge badge-warning">未应用</span>';
}
},
{
field: 'sort',
title: '排序'
},
{
field: 'updatedAt',
title: '更新时间',
formatter: function (value) {
if (!value) {
return '';
}
var date = new Date(value);
return date.getFullYear() + '-' +
String(date.getMonth() + 1).padStart(2, '0') + '-' +
String(date.getDate()).padStart(2, '0') + ' ' +
String(date.getHours()).padStart(2, '0') + ':' +
String(date.getMinutes()).padStart(2, '0') + ':' +
String(date.getSeconds()).padStart(2, '0');
}
},
{
title: '操作',
align: 'center',
formatter: function (value, row) {
var actions = [];
if (row.isApplied == 1) {
actions.push('<a class="btn btn-success btn-xs btn-disabled-edit" href="javascript:void(0)" title="请先取消应用"><i class="fa fa-edit"></i>编辑</a> ');
actions.push('<a class="btn btn-warning btn-xs ' + applyFlag + '" href="javascript:void(0)" onclick="toggleApply(\'' + row.reasonId + '\', 0)"><i class="fa fa-ban"></i>取消应用</a> ');
} else {
actions.push('<a class="btn btn-success btn-xs ' + updateFlag + '" href="javascript:void(0)" onclick="$.operate.edit(\'' + row.reasonId + '\')"><i class="fa fa-edit"></i>编辑</a> ');
actions.push('<a class="btn btn-primary btn-xs ' + applyFlag + '" href="javascript:void(0)" onclick="toggleApply(\'' + row.reasonId + '\', 1)"><i class="fa fa-check"></i>应用</a> ');
actions.push('<a class="btn btn-danger btn-xs ' + removeFlag + '" href="javascript:void(0)" onclick="removeReason(\'' + row.reasonId + '\')"><i class="fa fa-remove"></i>删除</a> ');
}
return actions.join('');
}
}]
};
$.table.init(options);
});
function removeReason(id) {
$.operate.remove(id, "确认删除该退款原因吗?");
}
function toggleApply(reasonId, isApplied) {
var title = isApplied == 1 ? '应用' : '取消应用';
$.modal.confirm('确定要' + title + '该退款原因吗?', function () {
$.ajax({
type: 'put',
url: prefix + '/apply',
data: {reasonId: reasonId, isApplied: isApplied},
success: function (e) {
if (e.code == 0) {
$.modal.msgSuccess(title + '成功');
$("button[name=refresh]").click();
} else {
$.modal.alertError(e.msg || (title + '失败'));
}
}
});
});
}
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
<head>
<th:block th:include="include :: header('修改退款原因')"/>
</head>
<body class="white-bg">
<div class="wrapper wrapper-content animated fadeInRight ibox-content">
<div th:if="${errorMsg != null}" class="alert alert-warning" th:text="${errorMsg}"></div>
<form class="form-horizontal m" id="form-reason-edit" th:if="${RefundReasonVo != null and RefundReasonVo.isApplied != 1}">
<input type="hidden" name="reasonId" th:value="${RefundReasonVo.reasonId}">
<div class="form-group">
<label class="col-sm-3 control-label is-required">退款理由名称:</label>
<div class="col-sm-8">
<input class="form-control" type="text" name="name" id="name"
maxlength="100" placeholder="展示给用户的文案"
th:value="${RefundReasonVo.name}" required>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label is-required">是否需补充说明:</label>
<div class="col-sm-8">
<div class="radio check-box">
<label>
<input type="radio" value="0" name="needDetail"
th:checked="${RefundReasonVo.needDetail == null or RefundReasonVo.needDetail == 0}"> 否(仅选择)
</label>
</div>
<div class="radio check-box">
<label>
<input type="radio" value="1" name="needDetail"
th:checked="${RefundReasonVo.needDetail == 1}"> 是(选择后需输入)
</label>
</div>
</div>
</div>
<div class="form-group" id="placeholderGroup"
th:style="${RefundReasonVo.needDetail == 1} ? '' : 'display:none;'">
<label class="col-sm-3 control-label is-required">二级输入 placeholder:</label>
<div class="col-sm-8">
<input class="form-control" type="text" name="placeholder" id="placeholder"
maxlength="200" placeholder="请输入补充说明的提示文案"
th:value="${RefundReasonVo.placeholder}">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">排序:</label>
<div class="col-sm-8">
<input class="form-control" type="number" name="sort" id="sort"
th:value="${RefundReasonVo.sort}">
<span class="help-block m-b-none"><i class="fa fa-info-circle"></i> 数值越大越靠前</span>
</div>
</div>
</form>
</div>
<th:block th:include="include :: footer"/>
<script type="text/javascript">
var prefix = ctx + "kylin/refundReasons";
function togglePlaceholderGroup() {
if ($('input[name="needDetail"]:checked').val() == '1') {
$('#placeholderGroup').show();
} else {
$('#placeholderGroup').hide();
$('#placeholder').val('');
}
}
function submitHandler() {
if ($('#form-reason-edit').length === 0) {
$.modal.alertWarning("应用中的退款原因不可编辑");
return false;
}
var name = $('#name').val().trim();
if (!name) {
$.modal.alertWarning("请填写退款理由名称");
return false;
}
var needDetail = $('input[name="needDetail"]:checked').val();
if (needDetail == '1' && !$('#placeholder').val().trim()) {
$.modal.alertWarning("请填写二级输入 placeholder");
return false;
}
if ($.validate.form()) {
var data = $('#form-reason-edit').serializeArray();
$.operate.save(prefix + "/update", data);
}
}
$(function () {
// 本页 radio 走 iCheck,必须用 ifChecked,否则选「是」不会展示 placeholder
$('input[name="needDetail"]').on('ifChecked change', togglePlaceholderGroup);
togglePlaceholderGroup();
});
</script>
</body>
</html>
package com.liquidnet.client.admin.zhengzai.kylin.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.liquidnet.client.admin.zhengzai.kylin.utils.DataUtils;
import com.liquidnet.commons.lang.util.BeanUtil;
import com.liquidnet.commons.lang.util.DateUtil;
import com.liquidnet.commons.lang.util.IDGenerator;
import com.liquidnet.service.kylin.dto.param.OrderRefundReasonParam;
import com.liquidnet.service.kylin.dto.param.OrderRefundReasonSearchParam;
import com.liquidnet.service.kylin.dto.vo.OrderRefundReasonVo;
import com.liquidnet.service.kylin.entity.KylinOrderRefundReasons;
import com.liquidnet.service.kylin.mapper.KylinOrderRefundReasonsMapper;
import com.liquidnet.service.kylin.service.admin.IOrderRefundReasonAdminService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* 退款原因配置管理
*/
@Slf4j
@Service
public class KylinOrderRefundReasonAdminServiceImpl
extends ServiceImpl<KylinOrderRefundReasonsMapper, KylinOrderRefundReasons>
implements IOrderRefundReasonAdminService {
@Autowired
private KylinOrderRefundReasonsMapper reasonsMapper;
@Autowired
private DataUtils dataUtils;
@Override
public Boolean create(OrderRefundReasonParam param) {
try {
if (StringUtils.isBlank(param.getName())) {
return false;
}
String reasonId = IDGenerator.nextSnowId();
LocalDateTime now = LocalDateTime.now();
KylinOrderRefundReasons entity = param.getFields(reasonId, now);
// 新建默认未应用、未删除
entity.setIsApplied(0);
entity.setIsDeleted(0);
reasonsMapper.insert(entity);
refreshAppliedCache();
return true;
} catch (Exception e) {
log.error("创建退款原因失败", e);
return false;
}
}
@Override
public Boolean update(OrderRefundReasonParam param) {
try {
if (StringUtils.isBlank(param.getReasonId()) || StringUtils.isBlank(param.getName())) {
return false;
}
KylinOrderRefundReasons existing = reasonsMapper.selectOne(
new QueryWrapper<KylinOrderRefundReasons>()
.eq("reason_id", param.getReasonId())
.eq("is_deleted", 0)
);
if (existing == null) {
return false;
}
// 应用中不可编辑
if (existing.getIsApplied() != null && existing.getIsApplied() == 1) {
return false;
}
KylinOrderRefundReasons entity = param.getFields(null, null);
// 不允许通过 update 直接改应用态/删除态
entity.setIsApplied(null);
entity.setIsDeleted(null);
entity.setReasonId(null);
entity.setCreatedAt(null);
entity.setUpdatedAt(LocalDateTime.now());
reasonsMapper.update(entity, new UpdateWrapper<KylinOrderRefundReasons>()
.eq("reason_id", param.getReasonId())
.eq("is_deleted", 0));
refreshAppliedCache();
return true;
} catch (Exception e) {
log.error("修改退款原因失败", e);
return false;
}
}
@Override
public OrderRefundReasonVo detail(String reasonId) {
KylinOrderRefundReasons data = reasonsMapper.selectOne(
new QueryWrapper<KylinOrderRefundReasons>()
.eq("reason_id", reasonId)
.eq("is_deleted", 0)
);
if (data == null) {
return null;
}
return toVo(data);
}
@Override
public PageInfo<KylinOrderRefundReasons> reasonList(OrderRefundReasonSearchParam param) {
try {
PageHelper.startPage(param.getPageNum(), param.getPageSize());
Map<String, Object> paramMap = BeanUtil.convertBeanToMap(param);
// convertBeanToMap(isAll) 会把 null 变成 "",isApplied=0 需保留为整型
if (param.getIsApplied() != null) {
paramMap.put("isApplied", param.getIsApplied());
} else {
paramMap.remove("isApplied");
}
List<KylinOrderRefundReasons> list = reasonsMapper.searchList(paramMap);
if (list != null) {
for (KylinOrderRefundReasons item : list) {
item.setIsAppliedName(formatAppliedName(item.getIsApplied()));
}
}
return new PageInfo<>(list);
} catch (Exception e) {
log.error("获取退款原因列表失败", e);
return new PageInfo<>();
}
}
@Override
public Boolean delete(List<String> reasonIds) {
try {
if (reasonIds == null || reasonIds.isEmpty()) {
return false;
}
List<KylinOrderRefundReasons> list = reasonsMapper.selectList(
new QueryWrapper<KylinOrderRefundReasons>()
.in("reason_id", reasonIds)
.eq("is_deleted", 0)
);
if (list == null || list.isEmpty()) {
return false;
}
for (KylinOrderRefundReasons item : list) {
if (item.getIsApplied() != null && item.getIsApplied() == 1) {
return false;
}
}
// 逻辑删除,保留 reason_id 供历史退款单关联
KylinOrderRefundReasons update = new KylinOrderRefundReasons();
update.setIsDeleted(1);
update.setUpdatedAt(LocalDateTime.now());
reasonsMapper.update(update, new UpdateWrapper<KylinOrderRefundReasons>()
.in("reason_id", reasonIds)
.eq("is_deleted", 0));
refreshAppliedCache();
return true;
} catch (Exception e) {
log.error("删除退款原因失败", e);
return false;
}
}
@Override
public Boolean apply(String reasonId, Integer isApplied) {
try {
if (StringUtils.isBlank(reasonId) || isApplied == null || (isApplied != 0 && isApplied != 1)) {
return false;
}
KylinOrderRefundReasons existing = reasonsMapper.selectOne(
new QueryWrapper<KylinOrderRefundReasons>()
.eq("reason_id", reasonId)
.eq("is_deleted", 0)
);
if (existing == null) {
return false;
}
KylinOrderRefundReasons update = new KylinOrderRefundReasons();
update.setIsApplied(isApplied);
update.setUpdatedAt(LocalDateTime.now());
reasonsMapper.update(update, new UpdateWrapper<KylinOrderRefundReasons>()
.eq("reason_id", reasonId)
.eq("is_deleted", 0));
refreshAppliedCache();
return true;
} catch (Exception e) {
log.error("应用/取消应用退款原因失败", e);
return false;
}
}
@Override
public List<OrderRefundReasonVo> listApplied() {
List<OrderRefundReasonVo> cached = dataUtils.getOrderRefundReasonsApplied();
if (cached != null) {
return cached;
}
return refreshAppliedCache();
}
private List<OrderRefundReasonVo> refreshAppliedCache() {
List<KylinOrderRefundReasons> list = reasonsMapper.listApplied();
List<OrderRefundReasonVo> voList = new ArrayList<>();
if (list != null) {
for (KylinOrderRefundReasons item : list) {
voList.add(toVo(item));
}
}
dataUtils.setOrderRefundReasonsApplied(voList);
return voList;
}
private OrderRefundReasonVo toVo(KylinOrderRefundReasons data) {
OrderRefundReasonVo vo = new OrderRefundReasonVo();
BeanUtils.copyProperties(data, vo);
vo.setIsAppliedName(formatAppliedName(data.getIsApplied()));
if (data.getCreatedAt() != null) {
vo.setCreatedAt(DateUtil.Formatter.yyyyMMddHHmmss.format(data.getCreatedAt()));
}
if (data.getUpdatedAt() != null) {
vo.setUpdatedAt(DateUtil.Formatter.yyyyMMddHHmmss.format(data.getUpdatedAt()));
}
return vo;
}
private String formatAppliedName(Integer isApplied) {
if (isApplied != null && isApplied == 1) {
return "应用中";
}
return "未应用";
}
}
......@@ -31,6 +31,7 @@ import com.liquidnet.service.kylin.dto.vo.returns.RefundOrderDetailsVo;
import com.liquidnet.service.kylin.entity.*;
import com.liquidnet.service.kylin.mapper.*;
import com.liquidnet.service.kylin.service.IKylinOrderRefundsService;
import com.liquidnet.service.kylin.utils.OrderRefundReasonUtils;
import com.mongodb.BasicDBObject;
import com.mongodb.client.result.UpdateResult;
import lombok.extern.slf4j.Slf4j;
......@@ -89,6 +90,9 @@ public class KylinOrderRefundsServiceImpl extends ServiceImpl<KylinOrderRefundsM
@Autowired
private KylinOrderRefundPicMapper kylinOrderRefundPicMapper;
@Autowired
private KylinOrderRefundReasonAdminServiceImpl refundReasonAdminService;
@Autowired
MongoTemplate mongoTemplate;
@Autowired
......@@ -96,6 +100,10 @@ public class KylinOrderRefundsServiceImpl extends ServiceImpl<KylinOrderRefundsM
public ResponseDto refundApply(RefundApplyParam refundApplyParam, String authId, String authName) {
try {
ResponseDto reasonCheck = fillRefundReason(refundApplyParam);
if (reasonCheck != null) {
return reasonCheck;
}
String orderTicketsId = refundApplyParam.getOrderTicketsId();
List<String> ticketEntityIds = refundApplyParam.getTicketEntityIds();
List<BigDecimal> entitiesPrice = refundApplyParam.getEntitiesPrice();
......@@ -574,4 +582,21 @@ public class KylinOrderRefundsServiceImpl extends ServiceImpl<KylinOrderRefundsM
}
return orderCode;
}
/**
* 校验并填充退款原因快照(从已应用配置缓存)
*
* @return 失败时返回 ResponseDto;成功返回 null
*/
private ResponseDto fillRefundReason(RefundApplyParam param) {
OrderRefundReasonUtils.ResolvedRefundReason resolved = OrderRefundReasonUtils.resolve(
param.getReasonId(), param.getReasonDetail(), refundReasonAdminService.listApplied());
if (!resolved.isSuccess()) {
return ResponseDto.failure(resolved.getErrorMsg());
}
param.setReasonId(resolved.getReasonId());
param.setReasonDetail(resolved.getReasonDetail());
param.setReason(resolved.getReasonSnapshot());
return null;
}
}
......@@ -52,7 +52,7 @@ public class KylinRefundExecuteServiceImpl {
private KylinOrderRefundsServiceImpl kylinOrderRefundsServiceImpl;
@Async
public void refundBatchApply(String targetId, String refundBatchId, String reason, String authId, String authName) {
public void refundBatchApply(String targetId, String refundBatchId, String reason, String reasonId, String reasonDetail, String authId, String authName) {
RefundApplyParam refundApplyParam = new RefundApplyParam();
int count;
int limitNum = 10;
......@@ -70,6 +70,8 @@ public class KylinRefundExecuteServiceImpl {
refundApplyParam.setOrderRefundBatchesId(refundBatchId);
refundApplyParam.setReason(reason);
refundApplyParam.setReasonId(reasonId);
refundApplyParam.setReasonDetail(reasonDetail);
refundApplyParam.setOrderTicketsId(order.getOrderTicketsId());
refundApplyParam.setTicketEntityIds(ticketEntityIds);
if (null != order.getPriceExpress()) {
......
......@@ -21,6 +21,7 @@ import com.liquidnet.service.kylin.mapper.KylinOrderRefundBatchesMapper;
import com.liquidnet.service.kylin.mapper.KylinOrderRefundsMapper;
import com.liquidnet.service.kylin.mapper.KylinOrderTicketsMapper;
import com.liquidnet.service.kylin.mapper.KylinPerformancesMapper;
import com.liquidnet.service.kylin.utils.OrderRefundReasonUtils;
import com.liquidnet.service.dragon.support.WepayAppletPaySupport;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
......@@ -65,7 +66,21 @@ public class KylinRefundPerformancesAdminServiceImpl {
@Autowired
RedisDataSourceUtil redisDataSourceUtil;
@Autowired
private KylinOrderRefundReasonAdminServiceImpl refundReasonAdminService;
public ResponseDto refundBatchApply(RefundBatchApplyParam refundBatchApplyParam) {
OrderRefundReasonUtils.ResolvedRefundReason resolved = OrderRefundReasonUtils.resolve(
refundBatchApplyParam.getReasonId(),
refundBatchApplyParam.getReasonDetail(),
refundReasonAdminService.listApplied());
if (!resolved.isSuccess()) {
return ResponseDto.failure(resolved.getErrorMsg());
}
refundBatchApplyParam.setReasonId(resolved.getReasonId());
refundBatchApplyParam.setReasonDetail(resolved.getReasonDetail());
refundBatchApplyParam.setReason(resolved.getReasonSnapshot());
String targetId = refundBatchApplyParam.getTargetId();
// 查询需要退的金额和数量
String[] paymentTypeAlipay = WepayAppletPaySupport.alipayPaymentTypesForRefundStatis();
......@@ -122,7 +137,8 @@ public class KylinRefundPerformancesAdminServiceImpl {
// 开始执行批量提交审核 分批处理退款申请
String authId = ShiroUtils.getUserId().toString();
String authName = ShiroUtils.getLoginName();
kylinRefundExecuteServiceImpl.refundBatchApply(targetId, refundBatchId, refundBatchApplyParam.getReason(), authId, authName);
kylinRefundExecuteServiceImpl.refundBatchApply(targetId, refundBatchId, refundBatchApplyParam.getReason(),
refundBatchApplyParam.getReasonId(), refundBatchApplyParam.getReasonDetail(), authId, authName);
return ResponseDto.success();
} else {
return ResponseDto.failure("操作失败");
......
......@@ -172,6 +172,8 @@ public class KylinRefundsStatusServiceImpl {
kylinOrderRefunds.setApplicantName(authName);
kylinOrderRefunds.setApplicantAt(LocalDateTime.now());
kylinOrderRefunds.setReason(reason);
kylinOrderRefunds.setReasonId(refundApplyParam.getReasonId());
kylinOrderRefunds.setReasonDetail(refundApplyParam.getReasonDetail());
kylinOrderRefunds.setCreatedAt(LocalDateTime.now());
int rows = kylinOrderRefundsMapper.insert(kylinOrderRefunds);
// 添加缓存
......
......@@ -10,6 +10,7 @@ import com.liquidnet.service.base.constant.RedisKeyExpireConst;
import com.liquidnet.service.candy.param.BackCouponParam;
import com.liquidnet.service.kylin.constant.KylinRedisConst;
import com.liquidnet.service.kylin.dto.vo.KylinExpressModuleVo;
import com.liquidnet.service.kylin.dto.vo.OrderRefundReasonVo;
import com.liquidnet.service.kylin.dto.vo.admin.OrderRefundAddress;
import com.liquidnet.service.kylin.dto.vo.admin.OrderRefundPoundage;
import com.liquidnet.service.kylin.dto.vo.express.KylinOrderExpressVo;
......@@ -464,6 +465,23 @@ public class DataUtils {
redisDataSourceUtil.getRedisKylinUtil().set(redisKey, voList);
}
public void setOrderRefundReasonsApplied(List<OrderRefundReasonVo> voList) {
redisDataSourceUtil.getRedisKylinUtil().set(KylinRedisConst.KYLIN_ORDER_REFUND_REASONS_APPLIED, voList);
}
@SuppressWarnings("unchecked")
public List<OrderRefundReasonVo> getOrderRefundReasonsApplied() {
Object obj = redisDataSourceUtil.getRedisKylinUtil().get(KylinRedisConst.KYLIN_ORDER_REFUND_REASONS_APPLIED);
if (obj == null) {
return null;
}
return (List<OrderRefundReasonVo>) obj;
}
public void delOrderRefundReasonsApplied() {
redisDataSourceUtil.getRedisKylinUtil().del(KylinRedisConst.KYLIN_ORDER_REFUND_REASONS_APPLIED);
}
/**
* 获取 票种快递票模板关联vo [第三方非线上]
*
......
package com.liquidnet.service.kylin.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* 演出票退款原因配置表
*/
@Data
@EqualsAndHashCode(callSuper = false)
public class KylinOrderRefundReasons implements Serializable, Cloneable {
private static final long serialVersionUID = 1L;
@TableId(value = "mid", type = IdType.AUTO)
private Integer mid;
/**
* 业务ID
*/
private String reasonId;
/**
* 退款理由名称
*/
private String name;
/**
* 是否需要二级补充输入 0否 1是
*/
private Integer needDetail;
/**
* 二级输入 placeholder
*/
private String placeholder;
/**
* 是否已应用 0未应用 1应用中
*/
private Integer isApplied;
/**
* 是否删除 0未删除 1已删除
*/
private Integer isDeleted;
/**
* 排序,越大越靠前
*/
private Integer sort;
private LocalDateTime createdAt;
private LocalDateTime updatedAt;
@TableField(exist = false)
private String isAppliedName;
private static final KylinOrderRefundReasons OBJ = new KylinOrderRefundReasons();
public static KylinOrderRefundReasons getNew() {
try {
return (KylinOrderRefundReasons) OBJ.clone();
} catch (CloneNotSupportedException e) {
return new KylinOrderRefundReasons();
}
}
}
......@@ -106,10 +106,20 @@ public class KylinOrderRefunds implements Serializable, Cloneable{
private LocalDateTime applicantAt;
/**
* 退款原因
* 退款原因(展示快照)
*/
private String reason;
/**
* 退款原因配置ID
*/
private String reasonId;
/**
* 退款原因二级补充说明
*/
private String reasonDetail;
/**
* 审核人id
*/
......
package com.liquidnet.service.kylin.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.liquidnet.service.kylin.entity.KylinOrderRefundReasons;
import java.util.List;
import java.util.Map;
/**
* 演出票退款原因配置 Mapper
*/
public interface KylinOrderRefundReasonsMapper extends BaseMapper<KylinOrderRefundReasons> {
List<KylinOrderRefundReasons> searchList(Map<String, Object> params);
List<KylinOrderRefundReasons> listApplied();
}
<?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="com.liquidnet.service.kylin.mapper.KylinOrderRefundReasonsMapper">
<select id="searchList" parameterType="java.util.Map" resultType="com.liquidnet.service.kylin.entity.KylinOrderRefundReasons">
SELECT
mid,
reason_id,
name,
need_detail,
placeholder,
is_applied,
sort,
is_deleted,
created_at,
updated_at
FROM kylin_order_refund_reasons
<where>
AND is_deleted = 0
<if test="name != null and name != ''">
AND name LIKE CONCAT('%', #{name}, '%')
</if>
<!-- isApplied=0 时不能写 != '',OGNL 会把 0 当成空 -->
<if test="isApplied != null">
AND is_applied = #{isApplied}
</if>
</where>
ORDER BY sort DESC, mid DESC
</select>
<select id="listApplied" resultType="com.liquidnet.service.kylin.entity.KylinOrderRefundReasons">
SELECT
mid,
reason_id,
name,
need_detail,
placeholder,
is_applied,
sort,
is_deleted,
created_at,
updated_at
FROM kylin_order_refund_reasons
WHERE is_applied = 1
AND is_deleted = 0
ORDER BY sort DESC, mid DESC
</select>
</mapper>
......@@ -793,6 +793,28 @@ alter table kylin_order_refunds add ticket_audit_name varchar(100) NOT NULL DE
alter table kylin_order_refunds add ticket_audit_at timestamp NULL DEFAULT NULL COMMENT '票务审核时间' after ticket_audit_name;
alter table kylin_order_refunds add ticket_audit_remark varchar(200) NOT NULL DEFAULT '' COMMENT '票务审核备至' after ticket_audit_at;
alter table kylin_order_refunds add reason_id varchar(32) DEFAULT NULL COMMENT '退款原因配置ID' after reason;
alter table kylin_order_refunds add reason_detail varchar(200) DEFAULT NULL COMMENT '退款原因二级补充说明' after reason_id;
# 演出票退款原因配置表
drop TABLE if exists `kylin_order_refund_reasons`;
CREATE TABLE `kylin_order_refund_reasons`
(
`mid` int(11) NOT NULL AUTO_INCREMENT,
`reason_id` varchar(32) NOT NULL DEFAULT '' COMMENT '业务ID',
`name` varchar(100) NOT NULL DEFAULT '' COMMENT '退款理由名称',
`need_detail` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否需要二级补充输入 0否 1是',
`placeholder` varchar(200) NOT NULL DEFAULT '' COMMENT '二级输入placeholder',
`is_applied` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否已应用 0未应用 1应用中',
`sort` int(11) NOT NULL DEFAULT '0' COMMENT '排序,越大越靠前',
`created_at` datetime DEFAULT NULL,
`updated_at` datetime DEFAULT NULL,
PRIMARY KEY (`mid`),
UNIQUE KEY `uk_reason_id` (`reason_id`),
KEY `idx_is_applied_sort` (`is_applied`, `sort`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4 COMMENT ='演出票退款原因配置';
drop TABLE if exists `kylin_order_refund_entities`;
CREATE TABLE `kylin_order_refund_entities`
(
......
package com.liquidnet.service.kylin.controller;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.kylin.dto.vo.OrderRefundReasonVo;
import com.liquidnet.service.kylin.service.impl.KylinOrderRefundReasonServiceImpl;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* 退款原因(App/H5)
*/
@Api(tags = "前端-退款原因")
@RestController
@RequestMapping("orderRefundReason")
@Validated
public class KylinOrderRefundReasonController {
@Autowired
private KylinOrderRefundReasonServiceImpl refundReasonService;
@GetMapping("appliedList")
@ApiOperation("已应用退款理由列表")
@ApiResponse(code = 200, message = "接口返回对象参数")
public ResponseDto<List<OrderRefundReasonVo>> appliedList() {
return ResponseDto.success(refundReasonService.listApplied());
}
}
......@@ -63,7 +63,9 @@ public class KylinOrderTicketsRefundController {
@ApiImplicitParams({
@ApiImplicitParam(type = "form", dataType = "String", name = "orderId", value = "订单ID", required = true),
@ApiImplicitParam(type = "form", dataType = "String", name = "orderTicketEntitiesId", value = "订单入场人ID", required = true),
@ApiImplicitParam(type = "form", dataType = "String", name = "reason", value = "退款申请备注", required = false),
@ApiImplicitParam(type = "form", dataType = "String", name = "reasonId", value = "退款原因配置ID", required = true),
@ApiImplicitParam(type = "form", dataType = "String", name = "reasonDetail", value = "退款原因补充说明"),
@ApiImplicitParam(type = "form", dataType = "String", name = "reason", value = "退款申请备注(兼容旧版,优先使用reasonId)", required = false),
@ApiImplicitParam(type = "form", dataType = "String", name = "picList", value = "图片"),
@ApiImplicitParam(type = "form", dataType = "String", name = "ticketNum", value = "纸质票号"),
@ApiImplicitParam(type = "form", dataType = "Integer", name = "sendExpressType", value = "快递方式 1上门取件 2自主发货"),
......@@ -78,7 +80,9 @@ public class KylinOrderTicketsRefundController {
public ResponseDto sendOrderRefund(
@RequestParam(value = "orderId", required = true) @NotNull(message = "订单ID不能为空") String orderId,
@RequestParam(value = "orderTicketEntitiesId", required = true) @NotNull(message = "票单ID不能为空") String orderTicketEntitiesId,
@RequestParam(value = "reason", required = false) @NotNull(message = "退款原因不能为空") String reason,
@RequestParam(value = "reasonId", required = false) String reasonId,
@RequestParam(value = "reasonDetail", required = false) String reasonDetail,
@RequestParam(value = "reason", required = false) String reason,
@RequestParam(value = "picList", required = false) String picList,
@RequestParam(value = "ticketNum", required = false) String ticketNum,
......@@ -97,7 +101,7 @@ public class KylinOrderTicketsRefundController {
return kylinOrderTicketsRefundService.systemFullRefund(orderId, orderTicketEntitiesId, reason);
}
return kylinOrderTicketsRefundService.sendOrderRefund(
orderId, orderTicketEntitiesId, reason, picList, ticketNum,
orderId, orderTicketEntitiesId, reasonId, reasonDetail, reason, picList, ticketNum,
sendExpressType, expressNumber, expressContacts, expressPhone, sendExpressAddress, appointmentTime
);
}
......
package com.liquidnet.service.kylin.service.impl;
import com.liquidnet.common.cache.redis.util.RedisUtil;
import com.liquidnet.service.kylin.constant.KylinRedisConst;
import com.liquidnet.service.kylin.dto.vo.OrderRefundReasonVo;
import com.liquidnet.service.kylin.entity.KylinOrderRefundReasons;
import com.liquidnet.service.kylin.mapper.KylinOrderRefundReasonsMapper;
import com.liquidnet.service.kylin.service.IKylinOrderRefundReasonService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
/**
* 退款原因(App/H5)
*/
@Slf4j
@Service
public class KylinOrderRefundReasonServiceImpl implements IKylinOrderRefundReasonService {
@Autowired
private RedisUtil redisUtil;
@Autowired
private KylinOrderRefundReasonsMapper reasonsMapper;
@Override
@SuppressWarnings("unchecked")
public List<OrderRefundReasonVo> listApplied() {
Object cached = redisUtil.get(KylinRedisConst.KYLIN_ORDER_REFUND_REASONS_APPLIED);
if (cached != null) {
return (List<OrderRefundReasonVo>) cached;
}
List<KylinOrderRefundReasons> list = reasonsMapper.listApplied();
List<OrderRefundReasonVo> voList = new ArrayList<>();
if (list != null) {
for (KylinOrderRefundReasons item : list) {
OrderRefundReasonVo vo = new OrderRefundReasonVo();
BeanUtils.copyProperties(item, vo);
voList.add(vo);
}
}
redisUtil.set(KylinRedisConst.KYLIN_ORDER_REFUND_REASONS_APPLIED, voList);
return voList;
}
@Override
public OrderRefundReasonVo getAppliedByReasonId(String reasonId) {
if (StringUtils.isBlank(reasonId)) {
return null;
}
List<OrderRefundReasonVo> list = listApplied();
if (list == null) {
return null;
}
for (OrderRefundReasonVo item : list) {
if (reasonId.equals(item.getReasonId())) {
return item;
}
}
return null;
}
}
......@@ -64,6 +64,8 @@ public class KylinOrderTicketsRefundServiceImpl {
private QueueUtils queueUtils;
@Autowired
private KylinRefundsStatusServiceImpl refundsStatusService;
@Autowired
private KylinOrderRefundReasonServiceImpl refundReasonService;
@Value("${liquidnet.express.shunfeng.custid}")
private String custid;
......@@ -170,21 +172,22 @@ public class KylinOrderTicketsRefundServiceImpl {
}
}
public ResponseDto sendOrderRefund(String orderId, String orderTicketEntitiesId, String reason, String picList, String ticketNum, Integer sendExpressType, String expressNumber, String expressContacts, String expressPhone, String sendExpressAddress, String appointmentTime) {
return sendOrderRefund(orderId, orderTicketEntitiesId, reason, picList, ticketNum,
public ResponseDto sendOrderRefund(String orderId, String orderTicketEntitiesId, String reasonId, String reasonDetail, String reason, String picList, String ticketNum, Integer sendExpressType, String expressNumber, String expressContacts, String expressPhone, String sendExpressAddress, String appointmentTime) {
return sendOrderRefund(orderId, orderTicketEntitiesId, reasonId, reasonDetail, reason, picList, ticketNum,
sendExpressType, expressNumber, expressContacts, expressPhone, sendExpressAddress, appointmentTime,
false, false);
}
/**
* 系统全额退(拼团散团/超时):跳过票主登录态与退票窗口,免手续费并触发自动退款。
* 原因按自由文本兼容写入(无 reasonId)。
*/
public ResponseDto systemFullRefund(String orderId, String orderTicketEntitiesId, String reason) {
return sendOrderRefund(orderId, orderTicketEntitiesId, reason, "", "",
return sendOrderRefund(orderId, orderTicketEntitiesId, null, null, reason, "", "",
0, "", "", "", "", "", true, true);
}
public ResponseDto sendOrderRefund(String orderId, String orderTicketEntitiesId, String reason, String picList, String ticketNum, Integer sendExpressType, String expressNumber, String expressContacts, String expressPhone, String sendExpressAddress, String appointmentTime, boolean skipCharges, boolean autoApproved) {
public ResponseDto sendOrderRefund(String orderId, String orderTicketEntitiesId, String reasonId, String reasonDetail, String reason, String picList, String ticketNum, Integer sendExpressType, String expressNumber, String expressContacts, String expressPhone, String sendExpressAddress, String appointmentTime, boolean skipCharges, boolean autoApproved) {
boolean isLock = dataUtils.setRefundLock(orderTicketEntitiesId);
if (!isLock) {
return ResponseDto.failure("正在处理,请勿重复操作~");
......@@ -192,6 +195,25 @@ public class KylinOrderTicketsRefundServiceImpl {
KylinOrderTicketEntitiesVo orderTicketEntitiesVo = null;
try {
String resolvedReason;
String resolvedReasonId = null;
String resolvedReasonDetail = null;
if (StringUtils.isNotBlank(reasonId)) {
OrderRefundReasonUtils.ResolvedRefundReason resolved = OrderRefundReasonUtils.resolve(
refundReasonService.getAppliedByReasonId(reasonId), reasonDetail);
if (!resolved.isSuccess()) {
return ResponseDto.failure(resolved.getErrorMsg());
}
resolvedReasonId = resolved.getReasonId();
resolvedReasonDetail = resolved.getReasonDetail();
resolvedReason = resolved.getReasonSnapshot();
} else if (StringUtils.isNotBlank(reason)) {
// 兼容旧版自由文本 / 系统退款文案
resolvedReason = OrderRefundReasonUtils.truncate(reason, 200);
} else {
return ResponseDto.failure("请选择退款原因");
}
String uid = null;
try {
uid = CurrentUtil.getCurrentUid();
......@@ -299,7 +321,7 @@ public class KylinOrderTicketsRefundServiceImpl {
username = StringUtils.defaultString(((String) token.get("nickname")), "");
}
Integer expressTypeParam = sendExpressType == null ? 0 : sendExpressType;
String orderRefundId = refundsStatusService.userOrderTicketRefunding(orderTicketVo, refundSinglePrice, priceExpress, priceCharges, orderTicketEntitiesId, reason, picList, ticketNum, uid, username, kylinOrderRefundsVoBaseList.size(), expressTypeParam);
String orderRefundId = refundsStatusService.userOrderTicketRefunding(orderTicketVo, refundSinglePrice, priceExpress, priceCharges, orderTicketEntitiesId, resolvedReason, resolvedReasonId, resolvedReasonDetail, picList, ticketNum, uid, username, kylinOrderRefundsVoBaseList.size(), expressTypeParam);
if (!orderRefundId.isEmpty()) {
// 退款申请成功 异步去快递下单
if (orderTicketVo.getGetTicketType().equals("express") && expressTypeParam > 0) {// 快递票
......
......@@ -56,6 +56,8 @@ public class KylinRefundsStatusServiceImpl {
BigDecimal priceCharges,
String orderEntitiesId,
String reason,
String reasonId,
String reasonDetail,
String picList,
String ticketNum,
String uid,
......@@ -120,6 +122,8 @@ public class KylinRefundsStatusServiceImpl {
kylinOrderRefunds.setApplicantName(username);
kylinOrderRefunds.setApplicantAt(time);
kylinOrderRefunds.setReason(reason);
kylinOrderRefunds.setReasonId(reasonId);
kylinOrderRefunds.setReasonDetail(reasonDetail);
kylinOrderRefunds.setCreatedAt(time);
KylinOrderRefundsVo orderRefundsVo = KylinOrderRefundsVo.getNew();
......@@ -182,7 +186,7 @@ public class KylinRefundsStatusServiceImpl {
kylinOrderRefunds.getOrderRefundsId(), kylinOrderRefunds.getOrderTicketsId(), kylinOrderRefunds.getOrderRefundCode(),
kylinOrderRefunds.getPrice(), kylinOrderRefunds.getPriceExpress(), kylinOrderRefunds.getPriceCharges(), ticketNum, kylinOrderRefunds.getStatus(),
kylinOrderRefunds.getType(), kylinOrderRefunds.getApplicantId(), kylinOrderRefunds.getApplicantName(),
kylinOrderRefunds.getApplicantAt(), kylinOrderRefunds.getReason(), kylinOrderRefunds.getCreatedAt()
kylinOrderRefunds.getApplicantAt(), kylinOrderRefunds.getReason(), kylinOrderRefunds.getReasonId(), kylinOrderRefunds.getReasonDetail(), kylinOrderRefunds.getCreatedAt()
});
sqlsDataD.add(new Object[]{
kylinOrderRefundEntities.getOrderRefundsEntitiesId(), kylinOrderRefundEntities.getOrderRefundsId(), kylinOrderRefundEntities.getRefundPrice(),
......@@ -332,9 +336,9 @@ public class KylinRefundsStatusServiceImpl {
});
sqlsDataC.add(new Object[]{
kylinOrderRefunds.getOrderRefundsId(), kylinOrderRefunds.getOrderTicketsId(), kylinOrderRefunds.getOrderRefundCode(),
kylinOrderRefunds.getPrice(), kylinOrderRefunds.getPriceExpress(), 0, kylinOrderRefunds.getStatus(),
kylinOrderRefunds.getPrice(), kylinOrderRefunds.getPriceExpress(), 0, null, kylinOrderRefunds.getStatus(),
kylinOrderRefunds.getType(), kylinOrderRefunds.getApplicantId(), kylinOrderRefunds.getApplicantName(),
kylinOrderRefunds.getApplicantAt(), kylinOrderRefunds.getReason(), kylinOrderRefunds.getCreatedAt()
kylinOrderRefunds.getApplicantAt(), kylinOrderRefunds.getReason(), null, null, kylinOrderRefunds.getCreatedAt()
});
sqlsDataD.add(new Object[]{
kylinOrderRefundEntities.getOrderRefundsEntitiesId(), kylinOrderRefundEntities.getOrderRefundsId(), kylinOrderRefundEntities.getRefundPrice(),
......
......@@ -16,7 +16,7 @@ kylin_order_ticket_entities.synPay=UPDATE kylin_order_ticket_entities SET is_pay
# ------------------------\u7528\u6237\u53D1\u8D77\u8BA2\u5355\u9000\u6B3E----------------------------
kylin_order_ticket_status.refund=UPDATE kylin_order_ticket_status SET status = ? ,updated_at = ? WHERE order_id = ? and (updated_at <= ? or created_at = ? or updated_at is null)
kylin_order_ticket_entities.refund=UPDATE kylin_order_ticket_entities SET is_payment = ? ,updated_at = ? WHERE order_ticket_entities_id = ? and (updated_at <= ? or created_at = ? or updated_at is null)
kylin_order_refund.refund=INSERT INTO kylin_order_refunds (order_refunds_id,order_tickets_id,order_refund_code,price,price_express,price_charges,ticket_num,status,type,applicant_id,applicant_name,applicant_at,reason,created_at) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?)
kylin_order_refund.refund=INSERT INTO kylin_order_refunds (order_refunds_id,order_tickets_id,order_refund_code,price,price_express,price_charges,ticket_num,status,type,applicant_id,applicant_name,applicant_at,reason,reason_id,reason_detail,created_at) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
kylin_order_refund_entities.refund=INSERT INTO kylin_order_refund_entities (order_refunds_entities_id,order_refunds_id,refund_price,order_ticket_entities_id,created_at) VALUES(?,?,?,?,?)
kylin_order_refund_pic.refund=INSERT INTO kylin_order_refund_pic (refund_pic_id,order_refunds_id,pic_url,created_at) VALUES (?,?,?,?)
kylin_order_refund.refundOrderExpress=INSERT INTO kylin_order_express (order_express_id,performances_id,order_tickets_id,order_refunds_id,order_express_code,mailno,express_type,filter_result,remark,express_status,send_type,send_express_type,express_contacts,express_phone,send_express_address,appointment_time,pro_name,cargo_type_code,limit_type_code,express_type_code,goods_value_total,goods_number,created_at) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment