From 572df690f72ed4a077d934823f261dec39b3cc7d Mon Sep 17 00:00:00 2001
From: 刘帅 <rr.iii@qq.com>
Date: 星期二, 08 九月 2026 17:11:34 +0800
Subject: [PATCH] feat&bug:文档内容修改

---
 cloud-server-management/src/main/java/com/dsh/guns/modular/system/controller/code/TicketController.java |  129 ++++++++++++++++++++++++++++++++++++++----
 1 files changed, 115 insertions(+), 14 deletions(-)

diff --git a/cloud-server-management/src/main/java/com/dsh/guns/modular/system/controller/code/TicketController.java b/cloud-server-management/src/main/java/com/dsh/guns/modular/system/controller/code/TicketController.java
index 718edc8..5f1507c 100644
--- a/cloud-server-management/src/main/java/com/dsh/guns/modular/system/controller/code/TicketController.java
+++ b/cloud-server-management/src/main/java/com/dsh/guns/modular/system/controller/code/TicketController.java
@@ -16,6 +16,7 @@
 import com.dsh.course.feignClient.activity.PointMercharsClient;
 import com.dsh.course.feignClient.activity.model.*;
 import com.dsh.guns.config.UserExt;
+import com.dsh.guns.modular.system.audit.ManagementAuditWriter;
 import com.dsh.guns.core.base.tips.SuccessTip;
 import com.dsh.guns.core.common.constant.factory.PageFactory;
 import com.dsh.guns.core.util.ToolUtil;
@@ -36,10 +37,7 @@
 import javax.annotation.Resource;
 import java.io.IOException;
 import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 import java.util.stream.Collectors;
 
 
@@ -71,6 +69,8 @@
     private PointMercharsClient pointMercharsClient;
     @Autowired
     private StoreStaffClient storeStaffClient;
+    @Resource
+    private ManagementAuditWriter auditWriter;
 
     /**
      * 跳转到优惠券管理首页
@@ -122,8 +122,53 @@
     @RequestMapping("/changeState")
     @ResponseBody
     public Object changeState(@RequestBody CoachChangeStateVO vo){
-        pointMercharsClient.changeState(vo);
-        return ResultUtil.success();
+        List<Map<String, Object>> before = new ArrayList<Map<String, Object>>();
+        for (Integer id : vo.getIds()) {
+            PointsMerchandise ticket = pointMercharsClient.getById(id);
+            Map<String, Object> item = new HashMap<String, Object>();
+            item.put("id", id);
+            item.put("name", ticket == null ? null : ticket.getName());
+            item.put("state", ticket == null ? null : ticket.getState());
+            before.add(item);
+        }
+        try {
+            pointMercharsClient.changeState(vo);
+            List<Map<String, Object>> after = new ArrayList<Map<String, Object>>();
+            for (Map<String, Object> item : before) {
+                Map<String, Object> changed = new HashMap<String, Object>(item);
+                changed.put("state", vo.getState());
+                after.add(changed);
+            }
+            appendTicketStateAudit(vo, before, after, "SUCCESS", null);
+            return ResultUtil.success();
+        } catch (RuntimeException ex) {
+            appendTicketStateAudit(vo, before, null, "FAIL", ex.getMessage());
+            throw ex;
+        }
+    }
+
+    private void appendTicketStateAudit(CoachChangeStateVO request, Object before, Object after, String result, String error) {
+        try {
+            Map<String, Object> audit = new HashMap<String, Object>();
+            audit.put("sourceService", "mb-cloud-management");
+            audit.put("sourceType", "HTTP");
+            audit.put("operationType", "STATUS_CHANGE");
+            audit.put("riskLevel", "CRITICAL");
+            audit.put("operationName", "管理员修改门票上下架状态");
+            audit.put("requestMethod", "POST");
+            audit.put("requestUri", "/ticket/changeState");
+            audit.put("requestParams", "ids=" + request.getIds() + ", targetState=" + request.getState());
+            audit.put("beforeData", JSONObject.toJSONString(before));
+            audit.put("afterData", JSONObject.toJSONString(after));
+            audit.put("userId", UserExt.getUser() == null ? null : UserExt.getUser().getId());
+            audit.put("userAccount", UserExt.getUser() == null ? null : UserExt.getUser().getAccount());
+            audit.put("result", result);
+            audit.put("errorMessage", error);
+            audit.put("createdAt", new Date());
+            auditWriter.append(audit);
+        } catch (Exception ignored) {
+            // 审计故障不影响实际的门票状态变更;由网关审计作为兜底记录。
+        }
     }
     /**
      * 获取门票列表
@@ -143,6 +188,13 @@
         integralGoodsOfSearch.setPage(page);
         integralGoodsOfSearch.setObjType(UserExt.getUser().getObjectType());
         integralGoodsOfSearch.setObjId(UserExt.getUser().getObjectId());
+        if (UserExt.getUser().getObjectType()==2){
+            // 查询这个运营商下的所有门店
+            List<Integer> operatorId = storeService.list(new QueryWrapper<TStore>()
+                    .eq("operatorId", UserExt.getUser().getObjectId())).stream().map(TStore::getId)
+                    .collect(Collectors.toList());
+            integralGoodsOfSearch.setStoreIds(operatorId);
+        }
         return pointMercharsClient.ticketList(integralGoodsOfSearch);
     }
 
@@ -350,28 +402,78 @@
         return new SuccessTip<>();
     }
     /**
-     *  上下架处理操作
-     * @return
+     * 根据管理员选择的入园方式核销门票,并写入管理端审计日志。
+     *
+     * @param id 用户已购门票记录ID
+     * @param goType 入园方式:1=手环,2=门票核销
      */
     @RequestMapping("/writeOff")
     @ResponseBody
-    public Object writeOff(String id) {
+    public Object writeOff(String id, Integer goType) {
+        if (!Integer.valueOf(1).equals(goType) && !Integer.valueOf(2).equals(goType)) {
+            return ResultUtil.error("入园方式参数不正确");
+        }
         Long aLong = Long.valueOf(id);
         WriteOffDTO dto = new WriteOffDTO();
-        // 核销人员id
+        // 核销人员ID与所属门店由登录上下文确定,不能由前端传入。
         Integer objectId = UserExt.getUser().getId();
         if (UserExt.getUser().getObjectType() == 1){
             dto.setVerifiStoreId(null);
         }else if (UserExt.getUser().getObjectType() == 2){
-            storeService.getOne(new QueryWrapper<TStore>().eq("cityManagerId",objectId));
+            TStore store = storeService.getOne(new QueryWrapper<TStore>().eq("cityManagerId", objectId));
+            dto.setVerifiStoreId(store == null ? null : store.getId());
         }else{
             TStoreStaff storeByStoreStaffId = storeStaffClient.getStoreByStoreStaffId(objectId);
             dto.setVerifiStoreId(storeByStoreStaffId.getStoreId());
         }
         dto.setId(aLong);
+        dto.setGoType(goType);
         dto.setVerificationUserId(objectId);
-        pointMercharsClient.writeOff(dto);
-        return new SuccessTip<>();
+        try {
+            pointMercharsClient.writeOff(dto);
+            appendTicketWriteOffAudit(dto, "SUCCESS", null);
+            return new SuccessTip<>();
+        } catch (RuntimeException ex) {
+            appendTicketWriteOffAudit(dto, "FAIL", ex.getMessage());
+            throw ex;
+        }
+    }
+
+    /** 记录管理员核销门票及所选入园方式,审计失败不影响正常业务流程。 */
+    private void appendTicketWriteOffAudit(WriteOffDTO dto, String result, String errorMessage) {
+        try {
+            Map<String, Object> beforeData = new HashMap<>();
+            beforeData.put("id", dto.getId());
+            beforeData.put("status", "待核销");
+
+            Map<String, Object> afterData = new HashMap<>(beforeData);
+            afterData.put("status", "已核销");
+            afterData.put("goType", dto.getGoType());
+            afterData.put("goTypeName", dto.getGoType() == 1 ? "手环" : "门票核销");
+            afterData.put("verificationUserId", dto.getVerificationUserId());
+            afterData.put("verifiStoreId", dto.getVerifiStoreId());
+
+            Map<String, Object> audit = new HashMap<>();
+            audit.put("traceId", UUID.randomUUID().toString().replace("-", ""));
+            audit.put("sourceService", "mb-cloud-management");
+            audit.put("sourceType", "HTTP");
+            audit.put("operationType", "STATUS_CHANGE");
+            audit.put("riskLevel", "CRITICAL");
+            audit.put("operationName", "管理员核销门票");
+            audit.put("requestMethod", "POST");
+            audit.put("requestUri", "/ticket/writeOff");
+            audit.put("requestParams", "id=" + dto.getId() + ", goType=" + dto.getGoType());
+            audit.put("beforeData", JSONObject.toJSONString(beforeData));
+            audit.put("afterData", JSONObject.toJSONString(afterData));
+            audit.put("userId", UserExt.getUser() == null ? null : UserExt.getUser().getId());
+            audit.put("userAccount", UserExt.getUser() == null ? null : UserExt.getUser().getAccount());
+            audit.put("result", result);
+            audit.put("errorMessage", errorMessage);
+            audit.put("createdAt", new Date());
+            auditWriter.append(audit);
+        } catch (Exception ignored) {
+            // 审计不可用时不阻断门票核销,网关审计会记录请求作为兜底。
+        }
     }
 
     /**
@@ -438,7 +540,6 @@
     @ResponseBody
     public Object GoodsWriteOff(Integer id){
         System.out.println(id);
-        // TODO: 2023/8/15 核销操作
         return new SuccessTip<>();
     }
 

--
Gitblit v1.7.1