Quellcode durchsuchen

fix(app):
1.商家端课程接口
2.订单-小程序支付后回显逻辑
3.订单详情

wzq vor 3 Tagen
Ursprung
Commit
951e158498
35 geänderte Dateien mit 1584 neuen und 118 gelöschten Zeilen
  1. 13 0
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/controller/OrderController.java
  2. 125 0
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/controller/commercial/CommercialController.java
  3. 91 0
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/dto/AppOrderInfoDTO.java
  4. 34 0
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/form/CourseQueryUsersForm.java
  5. 2 2
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/form/CreateOrderForm.java
  6. 3 0
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/form/UserPayForm.java
  7. 3 0
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/service/IOrderService.java
  8. 181 65
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/service/impl/OrderServiceImpl.java
  9. 57 0
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/vo/CoursesPriceRulesVO.java
  10. 22 0
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/vo/VerifyCourseInfoDTO.java
  11. 21 0
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/vo/VerifyCourseInfoVO.java
  12. 164 0
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/system/app/controller/AppCoursesVerificationRecordController.java
  13. 14 1
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/system/app/controller/AppOrderController.java
  14. 38 0
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/system/app/dto/IsinUserInfoDTO.java
  15. 29 0
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/system/app/dto/VerificationRecordDTO.java
  16. 2 0
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/system/app/entity/AppCourses.java
  17. 187 0
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/system/app/entity/AppCoursesVerificationRecord.java
  18. 30 9
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/system/app/entity/AppIsin.java
  19. 6 5
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/system/app/entity/AppOrder.java
  20. 17 1
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/system/app/entity/AppOrderProInfo.java
  21. 9 1
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/system/app/form/AppOrderPageForm.java
  22. 31 0
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/system/app/form/CoursesVerificationRecordForm.java
  23. 15 0
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/system/app/mapper/AppCoursesVerificationRecordMapper.java
  24. 2 1
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/system/app/mapper/AppOrderMapper.java
  25. 5 0
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/system/app/mapper/xml/AppCoursesVerificationRecordMapper.xml
  26. 34 1
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/system/app/mapper/xml/AppOrderMapper.xml
  27. 9 1
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/system/app/service/IAppCoureseService.java
  28. 19 0
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/system/app/service/IAppCoursesVerificationRecordService.java
  29. 2 0
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/system/app/service/IAppOrderService.java
  30. 119 21
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/system/app/service/impl/AppCoureseServiceImpl.java
  31. 44 0
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/system/app/service/impl/AppCoursesVerificationRecordServiceImpl.java
  32. 128 8
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/system/app/service/impl/AppOrderServiceImpl.java
  33. 42 0
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/system/app/vo/AppIsinVO.java
  34. 79 0
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/system/app/vo/AppOrderInfoVO.java
  35. 7 2
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/system/app/vo/OrderPageVO.java

+ 13 - 0
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/controller/OrderController.java

@@ -6,6 +6,7 @@ import io.swagger.v3.oas.annotations.media.Schema;
 import io.swagger.v3.oas.annotations.tags.Tag;
 import lombok.extern.slf4j.Slf4j;
 import org.jeecg.common.api.vo.Result;
+import org.jeecg.modules.app.dto.AppOrderInfoDTO;
 import org.jeecg.modules.app.form.CreateOrderForm;
 import org.jeecg.modules.app.form.UserPayForm;
 import org.jeecg.modules.app.service.IOrderService;
@@ -118,6 +119,18 @@ public class OrderController {
         return Result.ok(appOrderService.createOrder(createOrderForm));
     }
 
+    /**
+     * 订单-小程序支付后回显信息
+     *
+     * @param orderId
+     * @return
+     */
+    @Operation(summary = "订单-小程序支付后回显信息")
+    @GetMapping("/queryOrderInfo")
+    public Result<AppOrderInfoDTO> queryOrderInfo(@Schema(description = "订单ID") @RequestParam(name = "orderId") String orderId) {
+        return Result.ok(appOrderService.queryOrderInfo(orderId));
+    }
+
     /**
      * @Author SheepHy
      * @Description 体育馆无固定场-预览页

+ 125 - 0
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/controller/commercial/CommercialController.java

@@ -0,0 +1,125 @@
+package org.jeecg.modules.app.controller.commercial;
+
+import cn.hutool.core.util.ObjectUtil;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.jeecg.common.api.vo.Result;
+import org.jeecg.modules.app.form.CourseQueryUsersForm;
+import org.jeecg.modules.app.vo.VerifyCourseInfoVO;
+import org.jeecg.modules.system.app.entity.AppCourses;
+import org.jeecg.modules.system.app.entity.AppCoursesVerificationRecord;
+import org.jeecg.modules.system.app.entity.FamilyMembers;
+import org.jeecg.modules.system.app.form.CoursesVerificationRecordForm;
+import org.jeecg.modules.system.app.service.IAppCoureseService;
+import org.jeecg.modules.system.app.service.IAppCoursesVerificationRecordService;
+import org.jeecg.modules.system.app.service.IFamilyMembersService;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+@Slf4j
+@Tag(name = "App商家端课程相关接口")
+@RestController
+@AllArgsConstructor
+@RequestMapping("/app/course")
+public class CommercialController {
+
+    private final IAppCoureseService appCoureseService;
+
+    private final IAppCoursesVerificationRecordService appCoursesVerificationRecordService;
+
+    private final IFamilyMembersService familyMembersService;
+
+    /**
+     * 查询部门下的课程
+     *
+     * @param orgCode
+     * @param pageNo
+     * @param pageSize
+     * @return
+     */
+    @Operation(summary = "查询部门下的课程 ")
+    @GetMapping("/getPageCourse")
+    public Result<IPage<AppCourses>> getPageCourse(@Schema(description = "部门编号") @RequestParam(name = "orgCode") String orgCode,
+                                                   @Schema(description = "页数") @RequestParam(name = "pageNo") Integer pageNo,
+                                                   @Schema(description = "条数") @RequestParam(name = "pageSize") Integer pageSize) {
+        Page<AppCourses> page = new Page<AppCourses>(pageNo, pageSize);
+        IPage<AppCourses> pageList = appCoureseService.page(page, Wrappers.<AppCourses>lambdaQuery().eq(AppCourses::getOrgCode, orgCode));
+        return Result.OK(pageList);
+    }
+
+    /**
+     * 课程详情
+     *
+     * @param courseId
+     * @return
+     */
+    @Operation(summary = "课程详情")
+    @GetMapping("/getCourseInfo/{courseId}")
+    public Result<VerifyCourseInfoVO> getCourseInfo(@Schema(description = "课程ID") @PathVariable("courseId") String courseId) {
+        return Result.OK(appCoureseService.getCourseInfo(courseId));
+    }
+
+    /**
+     * 拍照验课上传图片
+     *
+     * @param formList
+     * @return
+     */
+    @Operation(summary = "拍照验课上传图片")
+    @PostMapping("/courseUploadImage")
+    public Result<Boolean> courseUploadImage(@RequestBody List<CoursesVerificationRecordForm> formList) {
+        return Result.OK(appCoursesVerificationRecordService.courseUploadImage(formList));
+    }
+
+    /**
+     * 拍照验课人员查看
+     *
+     * @param form
+     * @return
+     */
+    @Operation(summary = "拍照验课人员查看")
+    @PostMapping("/courseQueryUsers")
+    public Result<List<AppCoursesVerificationRecord>> courseQueryUsers(@RequestBody CourseQueryUsersForm form) {
+        List<AppCoursesVerificationRecord> verificationRecords =
+                appCoursesVerificationRecordService.list(Wrappers.<AppCoursesVerificationRecord>lambdaQuery()
+                        .eq(AppCoursesVerificationRecord::getCoursesPriceRuleId, form.getCoursePriceRulesId())
+                        .eq(ObjectUtil.isNotNull(form.getOrPostpone()), AppCoursesVerificationRecord::getOrPostpone, form.getOrPostpone())
+                        .eq(ObjectUtil.isNotNull(form.getVerifyStatus()), AppCoursesVerificationRecord::getVerifyStatus, form.getVerifyStatus())
+                );
+        return Result.OK(verificationRecords);
+    }
+
+    /**
+     * 根据姓名查询用户
+     *
+     * @param name
+     * @return
+     */
+    @Operation(summary = "根据姓名查询用户 ")
+    @GetMapping("/getFamilyMembersByName")
+    public Result<List<FamilyMembers>> getFamilyMembersByName(@Schema(description = "页数") @RequestParam(name = "name") String name) {
+        List<FamilyMembers> list = familyMembersService.list(Wrappers.<FamilyMembers>lambdaQuery().like(FamilyMembers::getFullName, name));
+        return Result.OK(list);
+    }
+
+    /**
+     * 临时约课
+     *
+     * @param coursePriceRulesId
+     * @param userId
+     * @return
+     */
+    @Operation(summary = "临时约课")
+    @GetMapping("/temporaryCourse")
+    public Result<Boolean> temporaryCourse(@Schema(description = "页数") @RequestParam(name = "coursePriceRulesId") String coursePriceRulesId,
+                                           @Schema(description = "页数") @RequestParam(name = "userId") String userId) {
+        return Result.OK(appCoureseService.temporaryCourse(coursePriceRulesId, userId));
+    }
+}

+ 91 - 0
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/dto/AppOrderInfoDTO.java

@@ -0,0 +1,91 @@
+package org.jeecg.modules.app.dto;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+import org.jeecg.modules.system.app.entity.AppCourses;
+import org.jeecg.modules.system.app.entity.AppOrderProInfo;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.List;
+
+@Data
+@Accessors(chain = true)
+@EqualsAndHashCode(callSuper = false)
+@AllArgsConstructor
+@NoArgsConstructor
+@Schema(description = "订单详情响应对象")
+public class AppOrderInfoDTO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    @Schema(description = "订单ID")
+    private String id;
+
+    @Schema(description = "订单号")
+    private String orderCode;
+
+    @Schema(description = "订单状态")
+    private Integer orderStatus;
+
+    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @Schema(description = "下单时间")
+    private Date createTime;
+
+    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @Schema(description = "付款时间")
+    private Date payTime;
+
+    @Schema(description = "门店名称")
+    private String siteName;
+    @Schema(description = "经营状态 0-营业 1-休息")
+    private Integer runStatus;
+
+    @Schema(description = "上课地址")
+    private String courseSiteAddress;
+
+    @Schema(description = "纬度")
+    private BigDecimal latitude;
+
+    @Schema(description = "经度")
+    private BigDecimal longitude;
+
+    @Schema(description = "客服电话")
+    private String phone;
+
+    @Schema(description = "买家电话")
+    private String phoneNumber;
+
+    @Schema(description = "商品数量")
+    private Integer amount;
+
+    @Schema(description = "商品总额")
+    private BigDecimal totalPrice;
+
+    @Schema(description = "试听优惠金额")
+    private BigDecimal sDiscounts;
+
+    @Schema(description = "团购优惠金额")
+    private BigDecimal tDiscounts;
+
+    @Schema(description = "实际付款")
+    private BigDecimal price;
+
+    @Schema(description = "订单信息")
+    private List<AppOrderProInfo> proInfoList;
+
+    //商品信息
+    private AppCourses appCourses;
+
+    //使用须知
+    @Schema(description = "提示/须知")
+    private String reminder;
+}

+ 34 - 0
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/form/CourseQueryUsersForm.java

@@ -0,0 +1,34 @@
+package org.jeecg.modules.app.form;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+import javax.validation.constraints.NotBlank;
+import java.io.Serializable;
+
+@Data
+@Accessors(chain = true)
+@EqualsAndHashCode(callSuper = false)
+@Schema(description = "课程人员查询表单对象")
+public class CourseQueryUsersForm implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 课时ID
+     */
+    @Schema(description = "课时ID")
+    @NotBlank(message = "课时ID不能为空")
+    private String coursePriceRulesId;
+    /**
+     * 核销状态(0-未核销 1-已核销)
+     */
+    @Schema(description = "核销状态(0-未核销 1-已核销)")
+    private Integer verifyStatus;
+    /**
+     * 是否延课(0-未延课 1-已延课)
+     */
+    @Schema(description = "是否延课(0-未延课 1-已延课)")
+    private Integer orPostpone;
+}

+ 2 - 2
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/form/CreateOrderForm.java

@@ -48,7 +48,7 @@ public class CreateOrderForm implements Serializable {
     private InsureOrderInfoForm insureOrderInfoForm;
 
     //参赛资质
-//    @Schema(description = "参赛资质")
-//    private String gameCertificationForm;
+    @Schema(description = "参赛资质")
+    private String gameCertificationForm;
 
 }

+ 3 - 0
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/form/UserPayForm.java

@@ -15,6 +15,9 @@ public class UserPayForm implements Serializable {
 
     private static final long serialVersionUID = 1L;
 
+    @Schema(description = "订单ID")
+    private String orderId;
+
     @Schema(description = "订单号")
     private String orderCode;
 }

+ 3 - 0
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/service/IOrderService.java

@@ -1,5 +1,6 @@
 package org.jeecg.modules.app.service;
 
+import org.jeecg.modules.app.dto.AppOrderInfoDTO;
 import org.jeecg.modules.app.form.CreateOrderForm;
 import org.jeecg.modules.app.form.UserPayForm;
 import org.jeecg.modules.app.vo.OrderVO;
@@ -73,4 +74,6 @@ public interface IOrderService {
      * @return
      **/
     OrderVO.PreviewOrderPlaceGymnasiumNoFixation previewOrderPlaceGymnasiumNoFixation(String placeId);
+
+    AppOrderInfoDTO queryOrderInfo(String orderCode);
 }

+ 181 - 65
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/service/impl/OrderServiceImpl.java

@@ -1,6 +1,8 @@
 package org.jeecg.modules.app.service.impl;
 
 import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.util.RandomUtil;
+import cn.hutool.core.util.StrUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
@@ -12,6 +14,7 @@ import org.jeecg.common.constant.CommonConstant;
 import org.jeecg.common.exception.JeecgBootException;
 import org.jeecg.common.system.vo.LoginUser;
 import org.jeecg.common.util.DictAnnotationUtil;
+import org.jeecg.modules.app.dto.AppOrderInfoDTO;
 import org.jeecg.modules.app.form.CreateOrderForm;
 import org.jeecg.modules.app.form.InsureOrderInfoForm;
 import org.jeecg.modules.app.form.UserPayForm;
@@ -73,7 +76,10 @@ public class OrderServiceImpl implements IOrderService {
     private AppGameScheduleMapper appGameScheduleMapper;
     @Resource
     private InsurePriceMapper insurePriceMapper;
-
+    @Resource
+    private AppCoursesPriceRulesMapper appCoursesPriceRulesMapper;
+    @Resource
+    private AppCoursesVerificationRecordMapper appCoursesVerificationRecordMapper;
 
     @Override
     @Transactional(rollbackFor = Exception.class)
@@ -129,17 +135,17 @@ public class OrderServiceImpl implements IOrderService {
         previewOrderPlaceSchool.setName(appSitePlace.getName())
                 .setId(appSitePlace.getId())
                 .setTimeSlot(timeSlot);
-        if (StringUtils.isNotEmpty(appSitePlace.getInsureIds())){
+        if (StringUtils.isNotEmpty(appSitePlace.getInsureIds())) {
             List<String> aptitudesList = new ArrayList<>();
-            if (appSitePlace.getInsureIds().indexOf(",")>0){
-                aptitudesList =  Arrays.asList(appSitePlace.getInsureIds().split(","));
-            }else {
+            if (appSitePlace.getInsureIds().indexOf(",") > 0) {
+                aptitudesList = Arrays.asList(appSitePlace.getInsureIds().split(","));
+            } else {
                 aptitudesList.add(appSitePlace.getInsureIds());
             }
             LambdaQueryWrapper<AppInsure> wrapper = new LambdaQueryWrapper<>();
             wrapper.in(AppInsure::getId, aptitudesList)
-                    .eq(AppInsure::getStatus,0)
-                    .eq(AppInsure::getDelFlag,0);  // 方法引用 + 集合
+                    .eq(AppInsure::getStatus, 0)
+                    .eq(AppInsure::getDelFlag, 0);  // 方法引用 + 集合
             List<AppInsure> appInsureList = appInsureMapper.selectList(wrapper);
             DictAnnotationUtil.translateDictList(appInsureList);
             for (AppInsure appInsure : appInsureList) {
@@ -162,7 +168,7 @@ public class OrderServiceImpl implements IOrderService {
         List<String> list = Arrays.asList(appCourses.getCover().split(","));
         boolean checkCourseDiscount = checkCourseDiscount(appCourses.getCategoryId(), user.getId());
         previousOrderCourse.setId(appCourses.getId())
-                .setCover(list.get(0).split( ",")[0])
+                .setCover(list.get(0).split(",")[0])
                 .setName(appCourses.getName())
                 .setSellingPrice(appCourses.getSellingPrice())
                 .setReminder(appCourses.getReminder())
@@ -179,17 +185,17 @@ public class OrderServiceImpl implements IOrderService {
             previousOrderCourse.setTotalPrice(appCourses.getSellingPrice());
         }
 
-        if (StringUtils.isNotEmpty(appCourses.getInsureIds())){
+        if (StringUtils.isNotEmpty(appCourses.getInsureIds())) {
             List<String> aptitudesList = new ArrayList<>();
-            if (appCourses.getInsureIds().indexOf(",")>0){
-                aptitudesList =  Arrays.asList(appCourses.getInsureIds().split(","));
-            }else {
+            if (appCourses.getInsureIds().indexOf(",") > 0) {
+                aptitudesList = Arrays.asList(appCourses.getInsureIds().split(","));
+            } else {
                 aptitudesList.add(appCourses.getInsureIds());
             }
             LambdaQueryWrapper<AppInsure> wrapper = new LambdaQueryWrapper<>();
             wrapper.in(AppInsure::getId, aptitudesList)
-                    .eq(AppInsure::getStatus,0)
-                    .eq(AppInsure::getDelFlag,0);  // 方法引用 + 集合
+                    .eq(AppInsure::getStatus, 0)
+                    .eq(AppInsure::getDelFlag, 0);  // 方法引用 + 集合
             List<AppInsure> appInsureList = appInsureMapper.selectList(wrapper);
             DictAnnotationUtil.translateDictList(appInsureList);
             for (AppInsure appInsure : appInsureList) {
@@ -277,6 +283,8 @@ public class OrderServiceImpl implements IOrderService {
 
         List<InsureOrderInfo> insureOrderInfoList = new ArrayList<>();
 
+        List<AppCoursesVerificationRecord> appCoursesVerificationRecordList = new ArrayList<>();
+
         //订单内容
         switch (createOrderForm.getType()) {
             //场地(学校,包场,无固定场)
@@ -295,7 +303,7 @@ public class OrderServiceImpl implements IOrderService {
                             //使用人IDs
                             .setFamilyIds(createOrderForm.getFamilyIds())
                             .setOriginalPrice(priceRule.getSellingPrice())
-                            .setPrice(priceRule.getSellingPrice())
+                            .setPrice(totalPrice)
                             .setCreateTime(new Date())
                             .setUpdateTime(new Date())
                             .setCreateBy(user.getId())
@@ -314,6 +322,7 @@ public class OrderServiceImpl implements IOrderService {
                                 .setType(CommonConstant.ORDER_PRO_INFO_TYPE_1)
                                 .setUseDateStr(DateUtil.format(priceRule.getDateOfSale(), "yyyy-MM-dd"))
                                 .setFrameTimeStr(priceRule.getStartTime() + "-" + priceRule.getEndTime())
+                                .setOriginalPrice(priceRule.getOriginalPrice())
                                 .setPrice(priceRule.getSellingPrice())
                                 .setOrderStatus(2)
                                 .setQuantity(1)
@@ -338,11 +347,14 @@ public class OrderServiceImpl implements IOrderService {
                     for (String id : list) {
                         AppSitePriceRules priceRule = appSitePriceRulesMapper.selectById(list.get(0));
                         AppSitePlace appSitePlace = appSitePlaceMapper.selectById(priceRule.getSitePlaceId());
+                        AppSite appSite = appSiteMapper.selectById(appSitePlace.getSiteId());
 
                         AppOrderProInfo appOrderProInfo = new AppOrderProInfo();
                         appOrderProInfo.setProductId(id);
-                        appOrderProInfo.setProductName(priceRule.getDateOfSale()+" "+priceRule.getStartTime()+"-"+priceRule.getEndTime()+"|"+appSitePlace.getName());
+                        appOrderProInfo.setProductName(priceRule.getDateOfSale() + " " + priceRule.getStartTime() + "-" + priceRule.getEndTime() + "|" + appSitePlace.getName());
+                        appOrderProInfo.setAddress(appSite.getAddress());
                         appOrderProInfo.setType(CommonConstant.ORDER_PRO_INFO_TYPE_2);
+                        appOrderProInfo.setOriginalPrice(priceRule.getOriginalPrice());
                         appOrderProInfo.setPrice(priceRule.getSellingPrice());
                         appOrderProInfo.setOrderStatus(0);
                         appOrderProInfo.setQuantity(1);
@@ -356,6 +368,9 @@ public class OrderServiceImpl implements IOrderService {
                         sumPrice = sumPrice.add(priceRule.getSellingPrice()).setScale(2, BigDecimal.ROUND_HALF_UP);
                     }
 
+                    //计算订单总价
+                    totalPrice = totalPrice.add(sumPrice).setScale(2, BigDecimal.ROUND_HALF_UP);
+
                     appOrder
                             .setType(CommonConstant.ORDER_TYPE_0)
                             .setOriginalPrice(sumPrice)
@@ -383,8 +398,10 @@ public class OrderServiceImpl implements IOrderService {
                         AppOrderProInfo appOrderProInfo = new AppOrderProInfo();
                         appOrderProInfo.setProductId(createOrderForm.getProductIds());
                         appOrderProInfo.setProductName(appSitePlace.getName());
+                        appOrderProInfo.setAddress(appSite.getAddress());
                         appOrderProInfo.setType(CommonConstant.ORDER_PRO_INFO_TYPE_3);
                         appOrderProInfo.setFrameTimeStr(appSite.getStartTime() + "-" + appSite.getEndTime());
+                        appOrderProInfo.setOriginalPrice(priceRule.getOriginalPrice());
                         appOrderProInfo.setPrice(priceRule.getSellingPrice());
                         appOrderProInfo.setOrderStatus(0);
                         appOrderProInfo.setQuantity(1);
@@ -397,6 +414,9 @@ public class OrderServiceImpl implements IOrderService {
                         sumPrice = sumPrice.add(priceRule.getSellingPrice()).setScale(2, BigDecimal.ROUND_HALF_UP);
                     }
 
+                    //计算订单总价
+                    totalPrice = totalPrice.add(sumPrice).setScale(2, BigDecimal.ROUND_HALF_UP);
+
                     appOrder
                             .setOrgCode(appSite.getOrgCode())
                             .setTenantId(appSite.getTenantId())
@@ -414,61 +434,66 @@ public class OrderServiceImpl implements IOrderService {
             //赛事
             case 1:
                 //个人赛
+                AppGamePriceRules appGamePriceRules = appGamePriceRulesMapper.selectById(createOrderForm.getProductIds());
+                AppGame appGame = appGameMapper.selectById(appGamePriceRules.getGameId());
 
-                    AppGamePriceRules appGamePriceRules = appGamePriceRulesMapper.selectById(createOrderForm.getProductIds());
-                    AppGame appGame = appGameMapper.selectById(appGamePriceRules.getGameId());
-
-                    appOrder.setOrgCode(appGamePriceRules.getOrgCode());
-                    appOrder.setTenantId(appGamePriceRules.getTenantId());
+                appOrder.setOrgCode(appGamePriceRules.getOrgCode());
+                appOrder.setTenantId(appGamePriceRules.getTenantId());
 
-                    //订单总价(商品的售价总和)
-                    BigDecimal sumPrice = new BigDecimal(0);
-
-                    for (int i = 1; i <= createOrderForm.getAmount(); i++) {
-
-                        String familyUserId = createOrderForm.getFamilyIds().split(",")[i - 1];
-                        FamilyMembers familyMembers = familyMembersMapper.selectById(familyUserId);
-                        AppOrderProInfo appOrderProInfo = new AppOrderProInfo();
-                        appOrderProInfo.setProductId(createOrderForm.getProductIds());
-                        appOrderProInfo.setProductName(appGame.getName());
-                        if (createOrderForm.getOrderType() == 3) {
-                            appOrderProInfo.setType(CommonConstant.ORDER_PRO_INFO_TYPE_4);
-                        }
-                        if (createOrderForm.getOrderType() == 4) {
-                            appOrderProInfo.setType(CommonConstant.ORDER_PRO_INFO_TYPE_5);
-                        }
-                        appOrderProInfo.setFrameTimeStr(appGame.getStartTime() + "-" + appGame.getEndTime());
-                        appOrderProInfo.setPrice(appGamePriceRules.getSellingPrice());
-                        appOrderProInfo.setOrderStatus(0);
-                        appOrderProInfo.setQuantity(1);
-                        appOrderProInfo.setFamilyUserId(familyUserId);
-                        appOrderProInfo.setUserName(familyMembers.getFullName());
-                        appOrderProInfo.setUserPhone(familyMembers.getPhone());
-                        appOrderProInfo.setStatus(CommonConstant.STATUS_0_INT);
-                        appOrderProInfo.setDelFlag(CommonConstant.DEL_FLAG_0);
+                //订单总价(商品的售价总和)
+                BigDecimal sumPrice = new BigDecimal(0);
 
-                        proInfoList.add(appOrderProInfo);
+                for (int i = 1; i <= createOrderForm.getAmount(); i++) {
 
-                        sumPrice = sumPrice.add(appGamePriceRules.getSellingPrice()).setScale(2, BigDecimal.ROUND_HALF_UP);
+                    String familyUserId = createOrderForm.getFamilyIds().split(",")[i - 1];
+                    FamilyMembers familyMembers = familyMembersMapper.selectById(familyUserId);
+                    AppOrderProInfo appOrderProInfo = new AppOrderProInfo();
+                    appOrderProInfo.setProductId(createOrderForm.getProductIds());
+                    appOrderProInfo.setProductName(appGame.getName());
+                    appOrderProInfo.setAddress(appGame.getAddress());
+                    if (createOrderForm.getOrderType() == 3) {
+                        appOrderProInfo.setType(CommonConstant.ORDER_PRO_INFO_TYPE_4);
                     }
+                    if (createOrderForm.getOrderType() == 4) {
+                        appOrderProInfo.setType(CommonConstant.ORDER_PRO_INFO_TYPE_5);
+                    }
+                    appOrderProInfo.setFrameTimeStr(appGame.getStartTime() + "-" + appGame.getEndTime());
+                    appOrderProInfo.setOriginalPrice(appGamePriceRules.getSellingPrice());
+                    appOrderProInfo.setPrice(appGamePriceRules.getSellingPrice());
+                    appOrderProInfo.setOrderStatus(0);
+                    appOrderProInfo.setQuantity(1);
+                    appOrderProInfo.setFamilyUserId(familyUserId);
+                    appOrderProInfo.setUserName(familyMembers.getFullName());
+                    appOrderProInfo.setUserPhone(familyMembers.getPhone());
+                    appOrderProInfo.setStatus(CommonConstant.STATUS_0_INT);
+                    appOrderProInfo.setDelFlag(CommonConstant.DEL_FLAG_0);
 
-                    appOrder
-                            .setType(CommonConstant.ORDER_TYPE_1)
-                            .setOriginalPrice(sumPrice)
-                            .setCreateTime(new Date())
-                            .setUpdateTime(new Date())
-                            .setCreateBy(user.getId())
-                            .setUpdateBy(user.getId())
-                            .setStatus(CommonConstant.STATUS_NORMAL)
-                            .setDelFlag(CommonConstant.DEL_FLAG_0);
-//                    if (StrUtil.isNotBlank(createOrderForm.getGameCertificationForm())) {
-//                        appOrder.setGameCertification(createOrderForm.getGameCertificationForm());
-//                    }
+                    proInfoList.add(appOrderProInfo);
+
+                    sumPrice = sumPrice.add(appGamePriceRules.getSellingPrice()).setScale(2, BigDecimal.ROUND_HALF_UP);
+                }
+                //计算订单总价
+                totalPrice = totalPrice.add(sumPrice).setScale(2, BigDecimal.ROUND_HALF_UP);
+
+                appOrder
+                        .setType(CommonConstant.ORDER_TYPE_1)
+                        .setOriginalPrice(sumPrice)
+                        .setCreateTime(new Date())
+                        .setUpdateTime(new Date())
+                        .setCreateBy(user.getId())
+                        .setUpdateBy(user.getId())
+                        .setStatus(CommonConstant.STATUS_NORMAL)
+                        .setDelFlag(CommonConstant.DEL_FLAG_0);
+                if (StrUtil.isNotBlank(createOrderForm.getGameCertificationForm())) {
+                    appOrder.setGameCertification(createOrderForm.getGameCertificationForm());
+                }
                 break;
             //课程
             case 2:
                 //课程
                 AppCourses appCourse = appCoursesMapper.selectById(appOrder.getProductIds());
+                List<AppCoursesPriceRules> priceRulesList = appCoursesPriceRulesMapper.selectList(Wrappers.<AppCoursesPriceRules>lambdaQuery().eq(AppCoursesPriceRules::getCoursesId, appCourse.getId()));
+                AppSite appSite = appSiteMapper.selectById(appCourse.getAddressSiteId());
 
                 appOrder.setType(CommonConstant.ORDER_TYPE_2);
                 appOrder.setOrgCode(appCourse.getOrgCode());
@@ -492,8 +517,10 @@ public class OrderServiceImpl implements IOrderService {
                     AppOrderProInfo appOrderProInfo = new AppOrderProInfo();
                     appOrderProInfo.setProductId(createOrderForm.getProductIds());
                     appOrderProInfo.setProductName(appCourse.getName());
+                    appOrderProInfo.setAddress(appSite.getAddress());
                     appOrderProInfo.setType(CommonConstant.ORDER_PRO_INFO_TYPE_6);
-                    appOrderProInfo.setFrameTimeStr(DateUtil.format(appCourse.getStartTime(),"yyyy-MM-dd") + "-" + DateUtil.format(appCourse.getEndTime(),"yyyy-MM-dd"));
+                    appOrderProInfo.setFrameTimeStr(DateUtil.format(appCourse.getStartTime(), "yyyy-MM-dd") + "-" + DateUtil.format(appCourse.getEndTime(), "yyyy-MM-dd"));
+                    appOrderProInfo.setOriginalPrice(appCourse.getOriginalPrice());
                     appOrderProInfo.setPrice(appCourse.getSellingPrice());
                     appOrderProInfo.setOrderStatus(0);
                     appOrderProInfo.setQuantity(1);
@@ -503,7 +530,23 @@ public class OrderServiceImpl implements IOrderService {
                     appOrderProInfo.setStatus(CommonConstant.STATUS_0_INT);
                     appOrderProInfo.setDelFlag(CommonConstant.DEL_FLAG_0);
 
-                    if (createOrderForm.getOrFreeOrder()== 1){
+                    //创建核销记录
+                    for (AppCoursesPriceRules appCoursesPriceRules : priceRulesList) {
+                        AppCoursesVerificationRecord appCoursesVerificationRecord = new AppCoursesVerificationRecord();
+                        appCoursesVerificationRecord.setCoursesId(appCourse.getId());
+                        appCoursesVerificationRecord.setCoursesPriceRuleId(appCoursesPriceRules.getId());
+                        appCoursesVerificationRecord.setCoursesName(appCourse.getName());
+                        appCoursesVerificationRecord.setCoursesStartTime(appCoursesPriceRules.getStartTime());
+                        appCoursesVerificationRecord.setCoursesEndTime(appCoursesPriceRules.getEndTime());
+                        appCoursesVerificationRecord.setUseUserId(familyUserId);
+                        appCoursesVerificationRecord.setUseUserName(familyMembers.getFullName());
+                        appCoursesVerificationRecord.setVerifyStatus(0);
+                        appCoursesVerificationRecord.setOrPostpone(0);
+                        appCoursesVerificationRecord.setCoursesType(0);
+                        appCoursesVerificationRecordList.add(appCoursesVerificationRecord);
+                    }
+
+                    if (createOrderForm.getOrFreeOrder() == 1) {
                         Boolean flag = checkOrderOrFree(user.getId(), appCourse.getCategoryId());
                         if (!flag && i == 1) {
                             //订单中的多个商品中的第一个商品触发免费,将金额设置为优惠金额
@@ -521,6 +564,9 @@ public class OrderServiceImpl implements IOrderService {
                     sumCoursePrice = sumCoursePrice.add(appCourse.getSellingPrice()).setScale(2, BigDecimal.ROUND_HALF_UP);
                 }
 
+                //计算订单总价
+                totalPrice = totalPrice.add(sumCoursePrice).setScale(2, BigDecimal.ROUND_HALF_UP);
+
                 //团购优惠
                 appOrder.setTDiscounts(tDiscounts);
                 //原订单总价
@@ -576,14 +622,31 @@ public class OrderServiceImpl implements IOrderService {
                 appOrderProInfo.setDelFlag(CommonConstant.DEL_FLAG_0);
             }
             //计算总价 = 订单金额 + 保单金额
+            totalPrice = totalPrice.add(sumPrice);
         }
-
+        appOrder.setPrice(totalPrice);
         appOrderMapper.insert(appOrder);
 
-        //保存订单商品信息
+        //todo 优化异步执行 -> 保存订单商品信息
         for (AppOrderProInfo appOrderProInfo : proInfoList) {
-            appOrderProInfo.setOrderId(appOrder.getId());
+            appOrderProInfo
+                    .setOrderId(appOrder.getId())
+                    .setOrderCode(appOrder.getOrderCode())
+                    //生成10位随机券号
+                    .setTicketNo(RandomUtil.randomNumbers(10))
+            ;
             appOrderProInfoMapper.insert(appOrderProInfo);
+            //订单券号记录
+            AppIsin appIsin = new AppIsin();
+            appIsin
+                    .setOrderId(appOrder.getId())
+                    .setOrderCode(appOrder.getOrderCode())
+                    .setOrderProInfoId(appOrderProInfo.getId())
+                    .setFamilyId(appOrderProInfo.getFamilyUserId())
+                    .setUseAddress(StrUtil.isBlank(appOrderProInfo.getAddress()) ? null : appOrderProInfo.getAddress())
+                    //生成10位随机券号
+                    .setIsinCode(appOrderProInfo.getTicketNo())
+                    .setIsinStatus(CommonConstant.STATUS_0_INT);
         }
 
         //保存保险
@@ -592,9 +655,17 @@ public class OrderServiceImpl implements IOrderService {
             insureOrderInfoMapper.insert(insureOrderInfo);
         }
 
+        //保存核销记录
+        for (AppCoursesVerificationRecord appCoursesVerificationRecord : appCoursesVerificationRecordList) {
+            appCoursesVerificationRecord.setOrderId(appOrder.getId());
+            appCoursesVerificationRecord.setOrderCode(appOrder.getOrderCode());
+            appCoursesVerificationRecordMapper.insert(appCoursesVerificationRecord);
+        }
+
         //构建支付表单返回给前端支撑支付调用
         UserPayForm payForm = new UserPayForm();
         payForm
+                .setOrderId(appOrder.getId())
                 .setOrderCode(orderCode)
         ;
         return payForm;
@@ -605,6 +676,51 @@ public class OrderServiceImpl implements IOrderService {
         return appSitePlaceMapper.previewOrderPlaceGymnasiumNoFixation(placeId);
     }
 
+    @Override
+    public AppOrderInfoDTO queryOrderInfo(String orderId) {
+
+        AppOrderInfoDTO appOrderInfoDTO = new AppOrderInfoDTO();
+
+        AppOrder appOrder = appOrderMapper.selectById(orderId);
+        appOrderInfoDTO.setId(appOrder.getId());
+        appOrderInfoDTO.setOrderCode(appOrder.getOrderCode());
+        appOrderInfoDTO.setOrderStatus(appOrder.getOrderStatus());
+        appOrderInfoDTO.setCreateTime(appOrder.getCreateTime());
+        appOrderInfoDTO.setPayTime(appOrder.getPayTime());
+        appOrderInfoDTO.setPhoneNumber(appOrder.getUserPhone());
+        appOrderInfoDTO.setTotalPrice(appOrder.getOriginalPrice());
+        appOrderInfoDTO.setPrice(appOrder.getPrice());
+        if (appOrder.getType().equals(CommonConstant.ORDER_TYPE_2)) {
+            appOrderInfoDTO.setSDiscounts(appOrder.getSDiscounts());
+            appOrderInfoDTO.setTDiscounts(appOrder.getTDiscounts());
+        }
+
+        //子订单
+        List<AppOrderProInfo> proInfoList = appOrderProInfoMapper.selectList(Wrappers.<AppOrderProInfo>lambdaQuery().eq(AppOrderProInfo::getOrderId, orderId));
+        appOrderInfoDTO.setProInfoList(proInfoList);
+
+        //商品信息
+        String productIds = appOrder.getProductIds();
+        AppCourses appCourses = appCoursesMapper.selectById(productIds);
+        appOrderInfoDTO.setAppCourses(appCourses);
+        //使用须知
+        if (ObjectUtils.isNotEmpty(appCourses.getReminder())) {
+            appOrderInfoDTO.setReminder(appCourses.getReminder());
+        }
+        //门店信息
+        AppSite site = appSiteMapper.selectById(appCourses.getSiteId());
+        appOrderInfoDTO.setSiteName(site.getName());
+        appOrderInfoDTO.setRunStatus(site.getRunStatus());
+        //上课地点(经纬度)
+        AppSite courseSite = appSiteMapper.selectById(appCourses.getAddressSiteId());
+        appOrderInfoDTO.setCourseSiteAddress(courseSite.getAddress());
+        appOrderInfoDTO.setLatitude(courseSite.getLatitude());
+        appOrderInfoDTO.setLongitude(courseSite.getLongitude());
+        appOrderInfoDTO.setPhone(courseSite.getPhone());
+
+        return appOrderInfoDTO;
+    }
+
 
     /**
      * @return boolean

+ 57 - 0
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/vo/CoursesPriceRulesVO.java

@@ -0,0 +1,57 @@
+package org.jeecg.modules.app.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.io.Serializable;
+import java.util.Date;
+
+@Data
+@Accessors(chain = true)
+@EqualsAndHashCode(callSuper = false)
+@Schema(description = "课程小节信息响应对象")
+public class CoursesPriceRulesVO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    @Schema(description = "id")
+    private String id;
+
+    @Schema(description = "课程id")
+    private String coursesId;
+
+    @Schema(description = "名称")
+    private String name;
+
+    @Schema(description = "是否今日")
+    private Boolean orToday;
+
+    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @Schema(description = "开始时间")
+    private Date startTime;
+
+    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @Schema(description = "结束时间")
+    private Date endTime;
+
+    @Schema(description = "课程类型(0-正常 1-补课)")
+    private Integer coursesType;
+
+    @Schema(description = "上课人数")
+    private Integer totalNum;
+
+    @Schema(description = "延课人数")
+    private Integer postponeNum;
+
+    @Schema(description = "已核销人数")
+    private Integer writtenOffNum;
+
+    @Schema(description = "未核销人数")
+    private Integer unwrittenOffNum;
+
+}

+ 22 - 0
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/vo/VerifyCourseInfoDTO.java

@@ -0,0 +1,22 @@
+package org.jeecg.modules.app.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+import java.util.List;
+
+@Data
+@Accessors(chain = true)
+@EqualsAndHashCode(callSuper = false)
+@Schema(description = "验课信息响应对象")
+public class VerifyCourseInfoDTO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    @Schema(description = "课程类型")
+    private Integer courseType;
+
+    private List<CoursesPriceRulesVO> voList;
+}

+ 21 - 0
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/vo/VerifyCourseInfoVO.java

@@ -0,0 +1,21 @@
+package org.jeecg.modules.app.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+import java.util.List;
+
+@Data
+@Accessors(chain = true)
+@EqualsAndHashCode(callSuper = false)
+@Schema(description = "验课信息响应对象")
+public class VerifyCourseInfoVO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    private CoursesPriceRulesVO priceRulesVO;
+
+    private List<VerifyCourseInfoDTO> verifyCourseInfoVOList;
+}

+ 164 - 0
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/system/app/controller/AppCoursesVerificationRecordController.java

@@ -0,0 +1,164 @@
+package org.jeecg.modules.system.app.controller;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.jeecg.common.api.vo.Result;
+import org.jeecg.common.aspect.annotation.AutoLog;
+import org.jeecg.common.system.base.controller.JeecgController;
+import org.jeecg.common.system.query.QueryGenerator;
+import org.jeecg.modules.system.app.entity.AppCoursesVerificationRecord;
+import org.jeecg.modules.system.app.service.IAppCoursesVerificationRecordService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.servlet.ModelAndView;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.Arrays;
+
+/**
+ * @Description: app_courses_verification_record
+ * @Author: jeecg-boot
+ * @Date: 2025-08-04
+ * @Version: V1.0
+ */
+@Tag(name = "app_courses_verification_record")
+@RestController
+@RequestMapping("/app/appCoursesVerificationRecord")
+@Slf4j
+public class AppCoursesVerificationRecordController extends JeecgController<AppCoursesVerificationRecord, IAppCoursesVerificationRecordService> {
+    @Autowired
+    private IAppCoursesVerificationRecordService appCoursesVerificationRecordService;
+
+    /**
+     * 分页列表查询
+     *
+     * @param appCoursesVerificationRecord
+     * @param pageNo
+     * @param pageSize
+     * @param req
+     * @return
+     */
+    @Operation(summary = "app_courses_verification_record-分页列表查询")
+    @GetMapping(value = "/list")
+    public Result<IPage<AppCoursesVerificationRecord>> queryPageList(AppCoursesVerificationRecord appCoursesVerificationRecord,
+                                                                     @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
+                                                                     @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
+                                                                     HttpServletRequest req) {
+
+
+        QueryWrapper<AppCoursesVerificationRecord> queryWrapper = QueryGenerator.initQueryWrapper(appCoursesVerificationRecord, req.getParameterMap());
+        Page<AppCoursesVerificationRecord> page = new Page<AppCoursesVerificationRecord>(pageNo, pageSize);
+        IPage<AppCoursesVerificationRecord> pageList = appCoursesVerificationRecordService.page(page, queryWrapper);
+        return Result.OK(pageList);
+    }
+
+    /**
+     * 添加
+     *
+     * @param appCoursesVerificationRecord
+     * @return
+     */
+    @AutoLog(value = "app_courses_verification_record-添加")
+    @Operation(summary = "app_courses_verification_record-添加")
+    @RequiresPermissions("org.jeecg.modules.system.app:app_courses_verification_record:add")
+    @PostMapping(value = "/add")
+    public Result<String> add(@RequestBody AppCoursesVerificationRecord appCoursesVerificationRecord) {
+        appCoursesVerificationRecordService.save(appCoursesVerificationRecord);
+
+        return Result.OK("添加成功!");
+    }
+
+    /**
+     * 编辑
+     *
+     * @param appCoursesVerificationRecord
+     * @return
+     */
+    @AutoLog(value = "app_courses_verification_record-编辑")
+    @Operation(summary = "app_courses_verification_record-编辑")
+    @RequiresPermissions("org.jeecg.modules.system.app:app_courses_verification_record:edit")
+    @RequestMapping(value = "/edit", method = {RequestMethod.PUT, RequestMethod.POST})
+    public Result<String> edit(@RequestBody AppCoursesVerificationRecord appCoursesVerificationRecord) {
+        appCoursesVerificationRecordService.updateById(appCoursesVerificationRecord);
+        return Result.OK("编辑成功!");
+    }
+
+    /**
+     * 通过id删除
+     *
+     * @param id
+     * @return
+     */
+    @AutoLog(value = "app_courses_verification_record-通过id删除")
+    @Operation(summary = "app_courses_verification_record-通过id删除")
+    @RequiresPermissions("org.jeecg.modules.system.app:app_courses_verification_record:delete")
+    @DeleteMapping(value = "/delete")
+    public Result<String> delete(@RequestParam(name = "id", required = true) String id) {
+        appCoursesVerificationRecordService.removeById(id);
+        return Result.OK("删除成功!");
+    }
+
+    /**
+     * 批量删除
+     *
+     * @param ids
+     * @return
+     */
+    @AutoLog(value = "app_courses_verification_record-批量删除")
+    @Operation(summary = "app_courses_verification_record-批量删除")
+    @RequiresPermissions("org.jeecg.modules.system.app:app_courses_verification_record:deleteBatch")
+    @DeleteMapping(value = "/deleteBatch")
+    public Result<String> deleteBatch(@RequestParam(name = "ids", required = true) String ids) {
+        this.appCoursesVerificationRecordService.removeByIds(Arrays.asList(ids.split(",")));
+        return Result.OK("批量删除成功!");
+    }
+
+    /**
+     * 通过id查询
+     *
+     * @param id
+     * @return
+     */
+    //@AutoLog(value = "app_courses_verification_record-通过id查询")
+    @Operation(summary = "app_courses_verification_record-通过id查询")
+    @GetMapping(value = "/queryById")
+    public Result<AppCoursesVerificationRecord> queryById(@RequestParam(name = "id", required = true) String id) {
+        AppCoursesVerificationRecord appCoursesVerificationRecord = appCoursesVerificationRecordService.getById(id);
+        if (appCoursesVerificationRecord == null) {
+            return Result.error("未找到对应数据");
+        }
+        return Result.OK(appCoursesVerificationRecord);
+    }
+
+    /**
+     * 导出excel
+     *
+     * @param request
+     * @param appCoursesVerificationRecord
+     */
+    @RequiresPermissions("org.jeecg.modules.system.app:app_courses_verification_record:exportXls")
+    @RequestMapping(value = "/exportXls")
+    public ModelAndView exportXls(HttpServletRequest request, AppCoursesVerificationRecord appCoursesVerificationRecord) {
+        return super.exportXls(request, appCoursesVerificationRecord, AppCoursesVerificationRecord.class, "app_courses_verification_record");
+    }
+
+    /**
+     * 通过excel导入数据
+     *
+     * @param request
+     * @param response
+     * @return
+     */
+    @RequiresPermissions("org.jeecg.modules.system.app:app_courses_verification_record:importExcel")
+    @RequestMapping(value = "/importExcel", method = RequestMethod.POST)
+    public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
+        return super.importExcel(request, response, AppCoursesVerificationRecord.class);
+    }
+
+}

+ 14 - 1
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/system/app/controller/AppOrderController.java

@@ -14,6 +14,7 @@ import org.jeecg.common.system.query.QueryGenerator;
 import org.jeecg.modules.system.app.entity.AppOrder;
 import org.jeecg.modules.system.app.form.AppOrderPageForm;
 import org.jeecg.modules.system.app.service.IAppOrderService;
+import org.jeecg.modules.system.app.vo.AppOrderInfoVO;
 import org.jeecg.modules.system.app.vo.OrderPageVO;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
@@ -61,7 +62,7 @@ public class AppOrderController extends JeecgController<AppOrder, IAppOrderServi
 	}
 
 	 /**
-	  *
+	  * 订单分页
 	  * @param appOrderPageForm
 	  * @return
 	  */
@@ -70,6 +71,18 @@ public class AppOrderController extends JeecgController<AppOrder, IAppOrderServi
 	 public Result<Page<OrderPageVO>> queryPage(@RequestBody AppOrderPageForm appOrderPageForm) {
 		 return Result.OK(appOrderService.queryPage(appOrderPageForm));
 	 }
+
+	 /**
+	  * 查询详情
+	  *
+	  * @param orderId
+	  * @return
+	  */
+	 @Operation(summary = "订单-查询详情")
+	 @GetMapping(value = "/queryInfoById/{orderId}")
+	 public Result<AppOrderInfoVO> queryInfoById(@PathVariable(name = "orderId") String orderId) {
+		 return Result.OK(appOrderService.queryInfoById(orderId));
+	 }
 	
 	/**
 	 *   添加

+ 38 - 0
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/system/app/dto/IsinUserInfoDTO.java

@@ -0,0 +1,38 @@
+package org.jeecg.modules.system.app.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+import org.jeecgframework.poi.excel.annotation.Excel;
+
+import java.io.Serializable;
+
+@Data
+@Accessors(chain = true)
+@EqualsAndHashCode(callSuper = false)
+@AllArgsConstructor
+@NoArgsConstructor
+@Schema(description = "使用记录用户信息响应对象")
+public class IsinUserInfoDTO implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @Excel(name = "用户ID(关联家庭用户表)", width = 15)
+    @Schema(description = "用户ID(关联家庭用户表)")
+    private String familyId;
+
+    @Excel(name = "用户名", width = 15)
+    @Schema(description = "用户名")
+    private String familyUserName;
+
+    @Excel(name = "手机号码", width = 15)
+    @Schema(description = "手机号码")
+    private String UserPhone;
+
+    @Excel(name = "券码号", width = 15)
+    @Schema(description = "券码号")
+    private String isinCode;
+}

+ 29 - 0
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/system/app/dto/VerificationRecordDTO.java

@@ -0,0 +1,29 @@
+package org.jeecg.modules.system.app.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+import org.jeecg.modules.system.app.entity.AppCoursesVerificationRecord;
+
+import java.io.Serializable;
+import java.util.List;
+
+@Data
+@Accessors(chain = true)
+@EqualsAndHashCode(callSuper = false)
+@AllArgsConstructor
+@NoArgsConstructor
+@Schema(description = "核销记录响应对象")
+public class VerificationRecordDTO implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @Schema(description = "课程类型(0-正常课 1-补课)")
+    private Integer coursesType;
+
+    @Schema(description = "核销记录")
+    private List<AppCoursesVerificationRecord> verificationRecordList;
+}

+ 2 - 0
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/system/app/entity/AppCourses.java

@@ -83,6 +83,8 @@ public class AppCourses implements Serializable {
     @Excel(name = "售价", width = 15)
     @Schema(description = "售价")
     private java.math.BigDecimal sellingPrice;
+    @Schema(description = "课时数")
+    private Integer classNum;
     /**适用人群*/
     @Excel(name = "适用人群", width = 15)
     @Schema(description = "适用人群")

+ 187 - 0
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/system/app/entity/AppCoursesVerificationRecord.java

@@ -0,0 +1,187 @@
+package org.jeecg.modules.system.app.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableLogic;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+import org.jeecgframework.poi.excel.annotation.Excel;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * @Description: nm_courses_verification_record
+ * @Author: jeecg-boot
+ * @Date: 2025-08-04
+ * @Version: V1.0
+ */
+@Data
+@TableName("nm_courses_verification_record")
+@Accessors(chain = true)
+@EqualsAndHashCode(callSuper = false)
+@Schema(description = "课程核销记录")
+public class AppCoursesVerificationRecord implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * id
+     */
+    @TableId(type = IdType.ASSIGN_ID)
+    @Schema(description = "id")
+    private String id;
+    /**
+     * 订单id
+     */
+    @Excel(name = "订单id", width = 15)
+    @Schema(description = "订单id")
+    private String orderId;
+    /**
+     * 订单编号
+     */
+    @Excel(name = "订单编号", width = 15)
+    @Schema(description = "订单编号")
+    private String orderCode;
+    /**
+     * 课程ID
+     */
+    @Excel(name = "课程ID", width = 15)
+    @Schema(description = "课程ID")
+    private String coursesId;
+    /**
+     * 课程小节ID
+     */
+    @Excel(name = "课程小节ID", width = 15)
+    @Schema(description = "课程小节ID")
+    private String coursesPriceRuleId;
+    /**
+     * 课时名称
+     */
+    @Excel(name = "课时名称", width = 15)
+    @Schema(description = "课时名称")
+    private String coursesName;
+    /**
+     * 上课时间
+     */
+    @Excel(name = "上课时间", width = 20, format = "yyyy-MM-dd HH:mm:ss")
+    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @Schema(description = "上课时间")
+    private Date coursesStartTime;
+
+    @Excel(name = "上课时间", width = 20, format = "yyyy-MM-dd HH:mm:ss")
+    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @Schema(description = "上课时间")
+    private Date coursesEndTime;
+    /**
+     * 使用人ID
+     */
+    @Excel(name = "使用人ID", width = 15)
+    @Schema(description = "使用人ID")
+    private String useUserId;
+    /**
+     * 使用人名称
+     */
+    @Excel(name = "使用人名称", width = 15)
+    @Schema(description = "使用人名称")
+    private String useUserName;
+    /**
+     * 使用人人脸照片
+     */
+    @Excel(name = "使用人人脸照片", width = 15)
+    @Schema(description = "使用人人脸照片")
+    private String useUserImage;
+    /**
+     * 核销状态(0-未核销 1-已核销)
+     */
+    @Excel(name = "核销状态(0-未核销 1-已核销)", width = 15)
+    @Schema(description = "核销状态(0-未核销 1-已核销)")
+    private Integer verifyStatus;
+    /**
+     * 是否延课(0-未延课 1-已延课)
+     */
+    @Excel(name = "是否延课(0-未延课 1-已延课)", width = 15)
+    @Schema(description = "是否延课(0-未延课 1-已延课)")
+    private Integer orPostpone;
+    /**
+     * 延课原因
+     */
+    @Excel(name = "延课原因", width = 15)
+    @Schema(description = "延课原因")
+    private String postponeReason;
+    /**
+     * 核验人ID
+     */
+    @Excel(name = "核验人ID", width = 15)
+    @Schema(description = "核验人ID")
+    private String verifyUserId;
+    /**
+     * 核验人名称
+     */
+    @Excel(name = "核验人名称", width = 15)
+    @Schema(description = "核验人名称")
+    private String verifyUserName;
+    /**
+     * 核验照片
+     */
+    @Excel(name = "核验照片", width = 15)
+    @Schema(description = "核验照片")
+    private String verifyImage;
+    /**
+     * 核验时间
+     */
+    @Excel(name = "核验时间", width = 20, format = "yyyy-MM-dd HH:mm:ss")
+    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @Schema(description = "核验时间")
+    private Date verifyTime;
+    /**
+     * 课程类型(0-正常课 1-补课)
+     */
+    @Excel(name = "课程类型(0-正常课 1-补课)", width = 15)
+    @Schema(description = "课程类型(0-正常课 1-补课)")
+    private Integer coursesType;
+    /**
+     * 创建人;创建人
+     */
+    @Schema(description = "创建人;创建人")
+    private String createBy;
+    /**
+     * 创建时间;创建时间
+     */
+    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @Schema(description = "创建时间;创建时间")
+    private Date createTime;
+    /**
+     * 更新人;更新人
+     */
+    @Schema(description = "更新人;更新人")
+    private String updateBy;
+    /**
+     * 更新时间;更新时间
+     */
+    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @Schema(description = "更新时间;更新时间")
+    private Date updateTime;
+    /**
+     * 系统状态;状态(0-正常,1-冻结)
+     */
+    @Excel(name = "系统状态;状态(0-正常,1-冻结)", width = 15)
+    @Schema(description = "系统状态;状态(0-正常,1-冻结)")
+    private Integer status;
+    /**
+     * 删除标志;删除状态(0-正常,1-已删除)
+     */
+    @Excel(name = "删除标志;删除状态(0-正常,1-已删除)", width = 15)
+    @Schema(description = "删除标志;删除状态(0-正常,1-已删除)")
+    @TableLogic
+    private Integer delFlag;
+}

+ 30 - 9
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/system/app/entity/AppIsin.java

@@ -37,10 +37,22 @@ public class AppIsin implements Serializable {
 	@Excel(name = "订单ID", width = 15)
     @Schema(description = "订单ID")
     private String orderId;
+    @Excel(name = "订单编号", width = 15)
+    @Schema(description = "订单编号")
+    private String orderCode;
+    @Excel(name = "子订单商品ID", width = 15)
+    @Schema(description = "子订单商品ID")
+    private String orderProInfoId;
 	/**用户ID*/
 	@Excel(name = "用户ID(关联家庭用户表)", width = 15)
     @Schema(description = "用户ID(关联家庭用户表)")
     private String familyId;
+    @Excel(name = "用户名", width = 15)
+    @Schema(description = "用户名")
+    private String familyUserName;
+    @Excel(name = "手机号码", width = 15)
+    @Schema(description = "手机号码")
+    private String UserPhone;
 	/**券码号*/
 	@Excel(name = "券码号", width = 15)
     @Schema(description = "券码号")
@@ -49,40 +61,49 @@ public class AppIsin implements Serializable {
 	@Excel(name = "券状态 1、待使用 2、已使用 3、已失效", width = 15)
     @Schema(description = "券状态 1、待使用 2、已使用 3、已失效")
     private Integer isinStatus;
+    @Excel(name = "核验人ID", width = 15)
+    @Schema(description = "核验人ID")
+    private String verifyUserId;
     /**核验人*/
-    @Excel(name = "核验人", width = 15)
-    @Schema(description = "核验人")
-    private String verifyBy;
+    @Excel(name = "核验人名称", width = 15)
+    @Schema(description = "核验人名称")
+    private String verifyUserName;
 	/**使用时间*/
 	@Excel(name = "使用时间", width = 20, format = "yyyy-MM-dd HH:mm:ss")
 	@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
     @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
     @Schema(description = "使用时间")
     private Date useTime;
+    @Excel(name = "使用地点", width = 20)
+    @Schema(description = "使用地点")
+    private String useAddress;
+    @Excel(name = "使用照片", width = 20)
+    @Schema(description = "使用照片")
+    private String useImage;
 	/**创建人;创建人*/
     @Schema(description = "创建人;创建人")
     private String createBy;
 	/**创建时间;创建时间*/
 	@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
     @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
-    @Schema(description = "创建时间;创建时间")
+    @Schema(description = "创建时间")
     private Date createTime;
 	/**更新时间;更新时间*/
 	@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
     @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
-    @Schema(description = "更新时间;更新时间")
+    @Schema(description = "更新时间")
     private Date updateTime;
     @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
     @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
-    @Schema(description = "到期时间;到期时间")
+    @Schema(description = "到期时间")
     private Date expireTime;
 	/**系统状态;状态(0-正常,1-冻结)*/
 	@Excel(name = "系统状态;状态(0-正常,1-冻结)", width = 15)
-    @Schema(description = "系统状态;状态(0-正常,1-冻结)")
+    @Schema(description = "系统状态(0-正常,1-冻结)")
     private Integer status;
 	/**删除标志;删除状态(0-正常,1-已删除)*/
-	@Excel(name = "删除标志;删除状态(0-正常,1-已删除)", width = 15)
-    @Schema(description = "删除标志;删除状态(0-正常,1-已删除)")
+    @Excel(name = "删除状态(0-正常,1-已删除)", width = 15)
+    @Schema(description = "删除状态(0-正常,1-已删除)")
     @TableLogic
     private Integer delFlag;
 }

+ 6 - 5
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/system/app/entity/AppOrder.java

@@ -40,7 +40,7 @@ public class AppOrder implements Serializable {
     private String orderCode;
     /**订单类型*/
     @Excel(name = "订单类型", width = 15)
-    @Schema(description = "订单类型")
+    @Schema(description = "订单类型 0场地/1赛事/2课程")
     private Integer type;
     /**部门id*/
     @Excel(name = "部门编码", width = 15)
@@ -112,6 +112,11 @@ public class AppOrder implements Serializable {
     @Excel(name = "使用人ID", width = 15)
     @Schema(description = "使用人ID")
     private String familyIds;
+    @Excel(name = "使用人ID", width = 15)
+    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @Schema(description = "支付时间")
+    private Date payTime;
 	/**取消备注*/
 	@Excel(name = "取消备注", width = 15)
     @Schema(description = "取消备注")
@@ -128,10 +133,6 @@ public class AppOrder implements Serializable {
     @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
     @Schema(description = "创建时间;创建时间")
     private Date createTime;
-    @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
-    @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
-    @Schema(description = "支付时间;支付时间")
-    private Date payTime;
 	/**更新人;更新人*/
     @Schema(description = "更新人;更新人")
     private String updateBy;

+ 17 - 1
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/system/app/entity/AppOrderProInfo.java

@@ -34,6 +34,13 @@ public class AppOrderProInfo  implements Serializable {
     @Schema(description = "订单id")
     private String orderId;
 
+    /**
+     * 订单id
+     */
+    @Excel(name = "订单编号", width = 15)
+    @Schema(description = "订单编号")
+    private String orderCode;
+
     /**产品id;场地/赛事/课程*/
     @Excel(name = "商品id;场地/赛事/课程", width = 15)
     @Schema(description = "产品id;场地/赛事/课程")
@@ -43,7 +50,12 @@ public class AppOrderProInfo  implements Serializable {
     @Excel(name = "商品名称", width = 15)
     @Schema(description = "商品名称")
     private String productName;
-
+    @Excel(name = "地点", width = 15)
+    @Schema(description = "地点")
+    private String address;
+    @Excel(name = "商品图片", width = 15)
+    @Schema(description = "商品图片")
+    private String productImage;
     @Schema(description = "商品类型(1-学校 2-包场 3-无固定场 4-个人赛 5-团队赛 6-课程 7-保险)")
     private Integer type;
     @Schema(description = "日期")
@@ -55,9 +67,13 @@ public class AppOrderProInfo  implements Serializable {
     @Schema(description = "券号")
     private String ticketNo;
     @Schema(description = "原价/元")
+    private BigDecimal originalPrice;
+    @Schema(description = "实际价格/元")
     private BigDecimal price;
     @Schema(description = "订单状态")
     private Integer orderStatus;
+    @Schema(description = "售后状态")
+    private Integer afterSaleStatus;
     @Schema(description = "数量")
     private Integer quantity;
     @Schema(description = "使用人ID")

+ 9 - 1
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/system/app/form/AppOrderPageForm.java

@@ -1,5 +1,6 @@
 package org.jeecg.modules.system.app.form;
 
+import com.fasterxml.jackson.annotation.JsonFormat;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.AllArgsConstructor;
 import lombok.Data;
@@ -7,7 +8,9 @@ import lombok.EqualsAndHashCode;
 import lombok.NoArgsConstructor;
 import lombok.experimental.Accessors;
 import org.jeecg.modules.system.app.dto.BasePageDTO;
+import org.springframework.format.annotation.DateTimeFormat;
 
+import javax.validation.constraints.NotBlank;
 import java.io.Serializable;
 import java.util.Date;
 
@@ -26,7 +29,8 @@ public class AppOrderPageForm extends BasePageDTO implements Serializable {
     @Schema(description = "订单编号")
     private String orderCode;
 
-    @Schema(description = "部门编号")
+    @Schema(description = "部门编码")
+    @NotBlank(message = "部门编码不能为空")
     private String orgCode;
 
     @Schema(description = "订单状态 0-待付款 1-待使用 2-已使用 3-已到期 4-已取消")
@@ -36,8 +40,12 @@ public class AppOrderPageForm extends BasePageDTO implements Serializable {
     private Integer afterSaleStatus;
 
     @Schema(description = "开始时间")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
     private Date startTime;
 
     @Schema(description = "结束时间")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
     private Date endTime;
 }

+ 31 - 0
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/system/app/form/CoursesVerificationRecordForm.java

@@ -0,0 +1,31 @@
+package org.jeecg.modules.system.app.form;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+
+@Data
+@Accessors(chain = true)
+@EqualsAndHashCode(callSuper = false)
+@AllArgsConstructor
+@NoArgsConstructor
+@Schema(description = "拍照验课上传图片表单对象")
+public class CoursesVerificationRecordForm implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * id
+     */
+    @Schema(description = "id")
+    private String id;
+    /**
+     * 核验照片
+     */
+    @Schema(description = "核验照片")
+    private String verifyImage;
+}

+ 15 - 0
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/system/app/mapper/AppCoursesVerificationRecordMapper.java

@@ -0,0 +1,15 @@
+package org.jeecg.modules.system.app.mapper;
+
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.jeecg.modules.system.app.entity.AppCoursesVerificationRecord;
+
+/**
+ * @Description: nm_courses_verification_record
+ * @Author: jeecg-boot
+ * @Date: 2025-08-04
+ * @Version: V1.0
+ */
+public interface AppCoursesVerificationRecordMapper extends BaseMapper<AppCoursesVerificationRecord> {
+
+}

+ 2 - 1
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/system/app/mapper/AppOrderMapper.java

@@ -2,6 +2,7 @@ package org.jeecg.modules.system.app.mapper;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import org.apache.ibatis.annotations.Param;
 import org.jeecg.modules.system.app.entity.AppOrder;
 import org.jeecg.modules.system.app.form.AppOrderPageForm;
 import org.jeecg.modules.system.app.vo.OrderPageVO;
@@ -14,5 +15,5 @@ import org.jeecg.modules.system.app.vo.OrderPageVO;
  */
 public interface AppOrderMapper extends BaseMapper<AppOrder> {
 
-    Page<OrderPageVO> queryPage(Page<OrderPageVO> page, AppOrderPageForm appOrderPageForm);
+    Page<OrderPageVO> queryPage(Page<OrderPageVO> page, @Param("appOrderPageForm") AppOrderPageForm appOrderPageForm);
 }

+ 5 - 0
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/system/app/mapper/xml/AppCoursesVerificationRecordMapper.xml

@@ -0,0 +1,5 @@
+<?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.jeecg.modules.demo.org.jeecg.modules.system.app.mapper.NmCoursesVerificationRecordMapper">
+
+</mapper>

+ 34 - 1
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/system/app/mapper/xml/AppOrderMapper.xml

@@ -3,6 +3,39 @@
 <mapper namespace="org.jeecg.modules.system.app.mapper.AppOrderMapper">
 
     <select id="queryPage" resultType="org.jeecg.modules.system.app.vo.OrderPageVO">
-
+        SELECT
+        o.id,
+        o.order_code,
+        o.create_time,
+        s.`name` siteName,
+        o.amount,
+        o.price
+        FROM
+        nm_order o
+        LEFT JOIN nm_site s ON s.org_code = o.org_code
+        <where>
+            <if test="appOrderPageForm.orgCode != null and appOrderPageForm.orgCode !=''">
+                and o.org_code = #{appOrderPageForm.orgCode}
+            </if>
+            <if test="appOrderPageForm.userPhone != null and appOrderPageForm.userPhone !=''">
+                and o.use_phone LIKE CONCAT('%',#{appOrderPageForm.userPhone},'%')
+            </if>
+            <if test="appOrderPageForm.orderCode != null and appOrderPageForm.orderCode !=''">
+                and o.order_code LIKE CONCAT('%',#{appOrderPageForm.orderCode},'%')
+            </if>
+            <if test="appOrderPageForm.orderStatus != null">
+                and o.order_status = #{appOrderPageForm.orderStatus}
+            </if>
+            <if test="appOrderPageForm.afterSaleStatus != null">
+                and o.after_sale_status = #{appOrderPageForm.afterSaleStatus}
+            </if>
+            <if test="appOrderPageForm.startTime != null">
+                and DATE_FORMAT(create_time,'%Y-%m-%d %H:%i:%s') <![CDATA[ >= ]]> #{appOrderPageForm.startTime}
+            </if>
+            <if test="appOrderPageForm.endTime != null">
+                and DATE_FORMAT(create_time,'%Y-%m-%d %H:%i:%s') <![CDATA[ <= ]]> #{appOrderPageForm.endTime}
+            </if>
+        </where>
+        ORDER BY o.create_time DESC
     </select>
 </mapper>

+ 9 - 1
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/system/app/service/IAppCoureseService.java

@@ -2,7 +2,11 @@ package org.jeecg.modules.system.app.service;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.IService;
-import org.jeecg.modules.system.app.dto.*;
+import org.jeecg.modules.app.vo.VerifyCourseInfoVO;
+import org.jeecg.modules.system.app.dto.AppCoursesDTO;
+import org.jeecg.modules.system.app.dto.AppCoursesInfoPageDTO;
+import org.jeecg.modules.system.app.dto.AppCoursesPageDTO;
+import org.jeecg.modules.system.app.dto.AppSiteAddressDTO;
 import org.jeecg.modules.system.app.entity.AppCourses;
 
 import java.util.List;
@@ -42,4 +46,8 @@ public interface IAppCoureseService extends IService<AppCourses> {
     IPage<AppCoursesInfoPageDTO> queryWitchPriceRulesPage(AppCoursesPageDTO dto);
 
     List<AppSiteAddressDTO> queryAddressList();
+
+    VerifyCourseInfoVO getCourseInfo(String courseId);
+
+    Boolean temporaryCourse(String coursePriceRulesId, String userId);
 }

+ 19 - 0
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/system/app/service/IAppCoursesVerificationRecordService.java

@@ -0,0 +1,19 @@
+package org.jeecg.modules.system.app.service;
+
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import org.jeecg.modules.system.app.entity.AppCoursesVerificationRecord;
+import org.jeecg.modules.system.app.form.CoursesVerificationRecordForm;
+
+import java.util.List;
+
+/**
+ * @Description: nm_courses_verification_record
+ * @Author: jeecg-boot
+ * @Date: 2025-08-04
+ * @Version: V1.0
+ */
+public interface IAppCoursesVerificationRecordService extends IService<AppCoursesVerificationRecord> {
+
+    Boolean courseUploadImage(List<CoursesVerificationRecordForm> formList);
+}

+ 2 - 0
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/system/app/service/IAppOrderService.java

@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.extension.service.IService;
 import org.jeecg.modules.system.app.dto.AppOrderDTO;
 import org.jeecg.modules.system.app.entity.AppOrder;
 import org.jeecg.modules.system.app.form.AppOrderPageForm;
+import org.jeecg.modules.system.app.vo.AppOrderInfoVO;
 import org.jeecg.modules.system.app.vo.OrderPageVO;
 
 /**
@@ -44,4 +45,5 @@ public interface IAppOrderService extends IService<AppOrder> {
 
     Page<OrderPageVO> queryPage(AppOrderPageForm appOrderPageForm);
 
+    AppOrderInfoVO queryInfoById(String orderId);
 }

+ 119 - 21
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/system/app/service/impl/AppCoureseServiceImpl.java

@@ -1,5 +1,6 @@
 package org.jeecg.modules.system.app.service.impl;
 
+import cn.hutool.core.util.ObjUtil;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@@ -9,21 +10,20 @@ import org.apache.shiro.SecurityUtils;
 import org.jeecg.common.constant.CommonConstant;
 import org.jeecg.common.exception.JeecgBootException;
 import org.jeecg.common.system.vo.LoginUser;
+import org.jeecg.modules.app.vo.CoursesPriceRulesVO;
+import org.jeecg.modules.app.vo.VerifyCourseInfoDTO;
+import org.jeecg.modules.app.vo.VerifyCourseInfoVO;
 import org.jeecg.modules.system.app.dto.*;
-import org.jeecg.modules.system.app.entity.AppCategory;
-import org.jeecg.modules.system.app.entity.AppCourses;
-import org.jeecg.modules.system.app.entity.AppCoursesPriceRules;
-import org.jeecg.modules.system.app.entity.AppSite;
-import org.jeecg.modules.system.app.mapper.AppCategoryMapper;
-import org.jeecg.modules.system.app.mapper.AppCoursesMapper;
-import org.jeecg.modules.system.app.mapper.AppCoursesPriceRulesMapper;
-import org.jeecg.modules.system.app.mapper.AppSiteMapper;
+import org.jeecg.modules.system.app.entity.*;
+import org.jeecg.modules.system.app.mapper.*;
 import org.jeecg.modules.system.app.service.IAppCoureseService;
 import org.springframework.beans.BeanUtils;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 import javax.annotation.Resource;
+import java.time.LocalDate;
+import java.time.ZoneId;
 import java.util.*;
 import java.util.stream.Collectors;
 
@@ -43,7 +43,10 @@ public class AppCoureseServiceImpl extends ServiceImpl<AppCoursesMapper, AppCour
     private AppSiteMapper siteMapper;
     @Resource
     private AppCategoryMapper categoryMapper;
-
+    @Resource
+    private AppCoursesVerificationRecordMapper appCoursesVerificationRecordMapper;
+    @Resource
+    private FamilyMembersMapper familyMembersMapper;
 
     @Override
     @Transactional(rollbackFor = Exception.class)
@@ -58,7 +61,7 @@ public class AppCoureseServiceImpl extends ServiceImpl<AppCoursesMapper, AppCour
         appCourses.setTenantId(site.getTenantId());
         appCourses.setUserId(coursesCuDTO.getUserId());
         appCourses.setAddressSiteId(coursesCuDTO.getAddressSiteId());
-        List<AppCoursesRuleDTO> coursesRuleDTOS= appCoursesDTO.getPriceRulesList();
+        List<AppCoursesRuleDTO> coursesRuleDTOS = appCoursesDTO.getPriceRulesList();
         //起止时间计算
         Optional<Date> minStartTime = coursesRuleDTOS.stream()
                 .map(AppCoursesRuleDTO::getStartTime)
@@ -71,6 +74,7 @@ public class AppCoureseServiceImpl extends ServiceImpl<AppCoursesMapper, AppCour
                 .max(Date::compareTo);
         appCourses.setStartTime(minStartTime.orElse(null));
         appCourses.setEndTime(maxEndTime.orElse(null));
+        appCourses.setClassNum(coursesRuleDTOS.size());
         int saveCourseResult = baseMapper.insert(appCourses);
         if (saveCourseResult < 1) {
             throw new JeecgBootException("课程信息保存失败");
@@ -98,7 +102,7 @@ public class AppCoureseServiceImpl extends ServiceImpl<AppCoursesMapper, AppCour
         AppCourses appCourses = baseMapper.selectById(coursesCuDTO.getId());
         BeanUtils.copyProperties(coursesCuDTO, appCourses);
         appCourses.setAddressSiteId(coursesCuDTO.getAddressSiteId());
-        List<AppCoursesRuleDTO> coursesRuleDTOS= appCoursesDTO.getPriceRulesList();
+        List<AppCoursesRuleDTO> coursesRuleDTOS = appCoursesDTO.getPriceRulesList();
         //起止时间计算
         Optional<Date> minStartTime = coursesRuleDTOS.stream()
                 .map(AppCoursesRuleDTO::getStartTime)
@@ -111,6 +115,7 @@ public class AppCoureseServiceImpl extends ServiceImpl<AppCoursesMapper, AppCour
                 .max(Date::compareTo);
         appCourses.setStartTime(minStartTime.orElse(null));
         appCourses.setEndTime(maxEndTime.orElse(null));
+        appCourses.setClassNum(coursesRuleDTOS.size());
         int updateResult = baseMapper.updateById(appCourses);
         if (updateResult < 1) {
             throw new JeecgBootException("课程信息保存失败");
@@ -120,9 +125,9 @@ public class AppCoureseServiceImpl extends ServiceImpl<AppCoursesMapper, AppCour
         List<AppCoursesPriceRules> coursesPriceRules = priceRulesMapper.selectList(Wrappers.lambdaQuery(AppCoursesPriceRules.class).eq(AppCoursesPriceRules::getCoursesId, appCourses.getId()));
         List<String> localList = coursesPriceRules.stream().map(AppCoursesPriceRules::getCoursesId).collect(Collectors.toList());
         //表单数据
-        List<String> formList = coursesRuleDTOS.stream().filter(e->ObjectUtils.isNotEmpty(e.getId())).map(AppCoursesRuleDTO::getId).collect(Collectors.toList());
+        List<String> formList = coursesRuleDTOS.stream().filter(e -> ObjectUtils.isNotEmpty(e.getId())).map(AppCoursesRuleDTO::getId).collect(Collectors.toList());
         //有ID的做更新
-        coursesRuleDTOS.stream().filter(e->ObjectUtils.isNotEmpty(e.getId())).forEach(coursesRule -> {
+        coursesRuleDTOS.stream().filter(e -> ObjectUtils.isNotEmpty(e.getId())).forEach(coursesRule -> {
             AppCoursesPriceRules appCoursesPriceRules = new AppCoursesPriceRules();
             BeanUtils.copyProperties(coursesRule, appCoursesPriceRules);
             priceRulesMapper.updateById(appCoursesPriceRules);
@@ -138,7 +143,7 @@ public class AppCoureseServiceImpl extends ServiceImpl<AppCoursesMapper, AppCour
             }
         }
         //id为空做新增
-        List<AppCoursesRuleDTO> nullList = coursesRuleDTOS.stream().filter(e->ObjectUtils.isEmpty(e.getId())).collect(Collectors.toList());
+        List<AppCoursesRuleDTO> nullList = coursesRuleDTOS.stream().filter(e -> ObjectUtils.isEmpty(e.getId())).collect(Collectors.toList());
         for (AppCoursesRuleDTO rule : nullList) {
             //做新增
             AppCoursesPriceRules appCoursesPriceRules = new AppCoursesPriceRules();
@@ -180,15 +185,15 @@ public class AppCoureseServiceImpl extends ServiceImpl<AppCoursesMapper, AppCour
     @Override
     public AppCoursesDTO queryWitchPriceRulesById(String id) {
         AppCourses dbCourse = baseMapper.selectById(id);
-        if (null==dbCourse) throw new JeecgBootException("未找到对应数据", SC_INTERNAL_SERVER_ERROR_500);
+        if (null == dbCourse) throw new JeecgBootException("未找到对应数据", SC_INTERNAL_SERVER_ERROR_500);
         LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
 //        checkPermission(sysUser,dbCourse);
         List<AppCoursesPriceRules> priceRulesList =
                 priceRulesMapper.selectList(Wrappers.<AppCoursesPriceRules>lambdaQuery().eq(AppCoursesPriceRules::getCoursesId, id));
         AppCoursesCuDTO coursesCuDTO = new AppCoursesCuDTO();
         BeanUtils.copyProperties(dbCourse, coursesCuDTO);
-        List<AppCoursesRuleDTO> priceRules =new ArrayList<>();
-        priceRulesList.forEach(rule-> {
+        List<AppCoursesRuleDTO> priceRules = new ArrayList<>();
+        priceRulesList.forEach(rule -> {
             AppCoursesRuleDTO appCoursesRuleDTO = new AppCoursesRuleDTO();
             BeanUtils.copyProperties(rule, appCoursesRuleDTO);
             priceRules.add(appCoursesRuleDTO);
@@ -201,7 +206,7 @@ public class AppCoureseServiceImpl extends ServiceImpl<AppCoursesMapper, AppCour
     @Transactional(rollbackFor = Exception.class)
     public Boolean deleteWitchPriceRulesById(String id) {
         AppCourses dbCourse = baseMapper.selectById(id);
-        if (null==dbCourse) throw new JeecgBootException("未找到对应数据", SC_INTERNAL_SERVER_ERROR_500);
+        if (null == dbCourse) throw new JeecgBootException("未找到对应数据", SC_INTERNAL_SERVER_ERROR_500);
         LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
 //        checkPermission(sysUser,dbCourse);
         int deleteCourseResult = baseMapper.deleteById(id);
@@ -209,7 +214,7 @@ public class AppCoureseServiceImpl extends ServiceImpl<AppCoursesMapper, AppCour
             throw new JeecgBootException("课程信息删除失败", SC_INTERNAL_SERVER_ERROR_500);
         }
         int deletePriceResult = priceRulesMapper.delete(Wrappers.<AppCoursesPriceRules>lambdaQuery().eq(AppCoursesPriceRules::getCoursesId, id));
-        if (deletePriceResult<1) throw new JeecgBootException("课程价格规则删除失败", SC_INTERNAL_SERVER_ERROR_500);
+        if (deletePriceResult < 1) throw new JeecgBootException("课程价格规则删除失败", SC_INTERNAL_SERVER_ERROR_500);
         return Boolean.TRUE;
     }
 
@@ -251,12 +256,105 @@ public class AppCoureseServiceImpl extends ServiceImpl<AppCoursesMapper, AppCour
         return dtoList;
     }
 
+    @Override
+    public VerifyCourseInfoVO getCourseInfo(String courseId) {
+
+        VerifyCourseInfoVO verifyCourseInfoVO = new VerifyCourseInfoVO();
+
+        List<VerifyCourseInfoDTO> verifyCourseInfoDTOList = new ArrayList<>();
+        List<CoursesPriceRulesVO> voList = new ArrayList<>();
+
+        List<AppCoursesPriceRules> priceRulesList = priceRulesMapper.selectList(Wrappers.lambdaQuery(AppCoursesPriceRules.class).eq(AppCoursesPriceRules::getCoursesId, courseId));
+        for (AppCoursesPriceRules priceRules : priceRulesList) {
+            CoursesPriceRulesVO coursesPriceRulesVO = new CoursesPriceRulesVO();
+            coursesPriceRulesVO.setId(priceRules.getId());
+            coursesPriceRulesVO.setCoursesId(priceRules.getCoursesId());
+            coursesPriceRulesVO.setName(priceRules.getName());
+            coursesPriceRulesVO.setStartTime(priceRules.getStartTime());
+            coursesPriceRulesVO.setEndTime(priceRules.getEndTime());
+            coursesPriceRulesVO.setCoursesType(priceRules.getCoursesType());
+
+            List<AppCoursesVerificationRecord> verificationRecordList = appCoursesVerificationRecordMapper
+                    .selectList(Wrappers.<AppCoursesVerificationRecord>lambdaQuery().eq(AppCoursesVerificationRecord::getCoursesPriceRuleId, priceRules.getId()));
+            //共计
+            coursesPriceRulesVO.setTotalNum(verificationRecordList.size());
+            //延期
+            long postponeNum = verificationRecordList.stream().filter(e -> e.getOrPostpone() == 1).count();
+            coursesPriceRulesVO.setPostponeNum((int) postponeNum);
+            //已核验
+            long writtenOffNum = verificationRecordList.stream().filter(e -> e.getVerifyStatus() == 1).count();
+            coursesPriceRulesVO.setWrittenOffNum((int) writtenOffNum);
+            //未核验
+            long unwrittenOffNum = verificationRecordList.stream().filter(e -> e.getVerifyStatus() == 0 && e.getOrPostpone() == 0).count();
+            coursesPriceRulesVO.setUnwrittenOffNum((int) unwrittenOffNum);
+
+            //判断是否为当日数据
+            LocalDate today = LocalDate.now();
+            LocalDate localDate = priceRules.getStartTime().toInstant()
+                    .atZone(ZoneId.systemDefault())
+                    .toLocalDate();
+            if (today.isAfter(localDate)) {
+                verifyCourseInfoVO.setPriceRulesVO(coursesPriceRulesVO);
+            } else {
+                voList.add(coursesPriceRulesVO);
+            }
+        }
+        Map<Integer, List<CoursesPriceRulesVO>> map = voList.stream().collect(Collectors.groupingBy(CoursesPriceRulesVO::getCoursesType));
+        if (!map.isEmpty()) {
+            map.keySet().forEach(key -> {
+                VerifyCourseInfoDTO verifyCourseInfoDTO = new VerifyCourseInfoDTO();
+                verifyCourseInfoDTO.setCourseType(key).setVoList(map.get(key));
+
+                verifyCourseInfoDTOList.add(verifyCourseInfoDTO);
+            });
+        }
+        verifyCourseInfoVO.setVerifyCourseInfoVOList(verifyCourseInfoDTOList);
+        return verifyCourseInfoVO;
+    }
+
+    /**
+     * 临时约课
+     *
+     * @param coursePriceRulesId
+     * @param familyMemberId
+     * @return
+     */
+    @Override
+    public Boolean temporaryCourse(String coursePriceRulesId, String familyMemberId) {
+
+        AppCoursesPriceRules appCoursesPriceRules = priceRulesMapper.selectById(coursePriceRulesId);
+
+        FamilyMembers familyMembers = familyMembersMapper.selectById(familyMemberId);
+
+        if (ObjUtil.isEmpty(familyMembers)) {
+            throw new JeecgBootException("当前用户不存在,请确认后重新提交");
+        }
+
+        AppCoursesVerificationRecord appCoursesVerificationRecord = new AppCoursesVerificationRecord();
+        appCoursesVerificationRecord.setCoursesId(appCoursesPriceRules.getCoursesId());
+        appCoursesVerificationRecord.setCoursesPriceRuleId(appCoursesPriceRules.getId());
+        appCoursesVerificationRecord.setCoursesName(appCoursesPriceRules.getName());
+        appCoursesVerificationRecord.setCoursesStartTime(appCoursesPriceRules.getStartTime());
+        appCoursesVerificationRecord.setCoursesEndTime(appCoursesPriceRules.getEndTime());
+        appCoursesVerificationRecord.setUseUserId(familyMemberId);
+        appCoursesVerificationRecord.setUseUserName(familyMembers.getFullName());
+        appCoursesVerificationRecord.setVerifyStatus(0);
+        appCoursesVerificationRecord.setOrPostpone(0);
+        appCoursesVerificationRecord.setCoursesType(0);
+
+        int insert = appCoursesVerificationRecordMapper.insert(appCoursesVerificationRecord);
+        if (insert < 1) throw new JeecgBootException("临时约课创建失败", SC_INTERNAL_SERVER_ERROR_500);
+        return Boolean.TRUE;
+    }
+
     /**
-     *  校验权限
+     * 校验权限
+     *
      * @param loginUser
      * @param course
      */
     private void checkPermission(LoginUser loginUser, AppCourses course) {
-        if (!loginUser.getOrgCode().equals(course.getOrgCode())) throw new JeecgBootException("无权限操作", SC_INTERNAL_SERVER_ERROR_500);
+        if (!loginUser.getOrgCode().equals(course.getOrgCode()))
+            throw new JeecgBootException("无权限操作", SC_INTERNAL_SERVER_ERROR_500);
     }
 }

+ 44 - 0
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/system/app/service/impl/AppCoursesVerificationRecordServiceImpl.java

@@ -0,0 +1,44 @@
+package org.jeecg.modules.system.app.service.impl;
+
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.apache.commons.lang3.ObjectUtils;
+import org.apache.shiro.SecurityUtils;
+import org.jeecg.common.constant.CommonConstant;
+import org.jeecg.common.system.vo.LoginUser;
+import org.jeecg.modules.system.app.entity.AppCoursesVerificationRecord;
+import org.jeecg.modules.system.app.form.CoursesVerificationRecordForm;
+import org.jeecg.modules.system.app.mapper.AppCoursesVerificationRecordMapper;
+import org.jeecg.modules.system.app.service.IAppCoursesVerificationRecordService;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * @Description: nm_courses_verification_record
+ * @Author: jeecg-boot
+ * @Date: 2025-08-04
+ * @Version: V1.0
+ */
+@Service
+public class AppCoursesVerificationRecordServiceImpl extends ServiceImpl<AppCoursesVerificationRecordMapper, AppCoursesVerificationRecord> implements IAppCoursesVerificationRecordService {
+
+    @Override
+    public Boolean courseUploadImage(List<CoursesVerificationRecordForm> formList) {
+
+        //获取登录用户信息
+        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
+
+        for (CoursesVerificationRecordForm coursesVerificationRecordForm : formList) {
+            AppCoursesVerificationRecord appCoursesVerificationRecord = baseMapper.selectById(coursesVerificationRecordForm.getId());
+            if (ObjectUtils.isEmpty(appCoursesVerificationRecord)) {
+                appCoursesVerificationRecord.setVerifyStatus(CommonConstant.STATUS_1_INT);
+                appCoursesVerificationRecord.setVerifyUserId(sysUser.getId());
+                appCoursesVerificationRecord.setVerifyUserName(sysUser.getRealname());
+                appCoursesVerificationRecord.setVerifyImage(coursesVerificationRecordForm.getVerifyImage());
+                baseMapper.updateById(appCoursesVerificationRecord);
+            }
+        }
+        return Boolean.TRUE;
+    }
+}

+ 128 - 8
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/system/app/service/impl/AppOrderServiceImpl.java

@@ -1,31 +1,61 @@
 package org.jeecg.modules.system.app.service.impl;
 
-import cn.hutool.core.util.ObjectUtil;
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.metadata.IPage;
+import cn.hutool.core.collection.CollUtil;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import org.apache.shiro.SecurityUtils;
 import org.jeecg.common.system.vo.LoginUser;
 import org.jeecg.modules.system.app.dto.AppOrderDTO;
-import org.jeecg.modules.system.app.entity.AppOrder;
+import org.jeecg.modules.system.app.dto.IsinUserInfoDTO;
+import org.jeecg.modules.system.app.dto.VerificationRecordDTO;
+import org.jeecg.modules.system.app.entity.*;
 import org.jeecg.modules.system.app.form.AppOrderPageForm;
-import org.jeecg.modules.system.app.mapper.AppOrderMapper;
+import org.jeecg.modules.system.app.mapper.*;
 import org.jeecg.modules.system.app.service.IAppOrderService;
+import org.jeecg.modules.system.app.vo.AppIsinVO;
+import org.jeecg.modules.system.app.vo.AppOrderInfoVO;
 import org.jeecg.modules.system.app.vo.OrderPageVO;
+import org.jeecg.modules.system.entity.SysUser;
+import org.jeecg.modules.system.mapper.SysUserMapper;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
+import javax.annotation.Resource;
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
 /**
  * @Description: 订单表
  * @Author: jeecg-boot
- * @Date:   2025-07-03
+ * @Date: 2025-07-03
  * @Version: V1.0
  */
 @Service
 public class AppOrderServiceImpl extends ServiceImpl<AppOrderMapper, AppOrder> implements IAppOrderService {
 
+    @Resource
+    private AppOrderProInfoMapper appOrderProInfoMapper;
+
+    @Resource
+    private AppOrderMapper appOrderMapper;
+
+    @Resource
+    private AppSiteMapper appSiteMapper;
+
+    @Resource
+    private SysUserMapper sysUserMapper;
+
+    @Resource
+    private AppIsinMapper appIsinMapper;
+
+    @Resource
+    private AppCoursesVerificationRecordMapper appCoursesVerificationRecordMapper;
+
+
     @Override
     @Transactional(rollbackFor = Exception.class)
     public Boolean saveWitchProduct(AppOrderDTO appOrderDTO) {
@@ -53,7 +83,97 @@ public class AppOrderServiceImpl extends ServiceImpl<AppOrderMapper, AppOrder> i
     public Page<OrderPageVO> queryPage(AppOrderPageForm appOrderPageForm) {
         Page<OrderPageVO> page = new Page<>(appOrderPageForm.getPageNum(), appOrderPageForm.getPageSize());
 
-        Page<OrderPageVO> voPage = baseMapper.queryPage(page,appOrderPageForm);
-        return null;
+        Page<OrderPageVO> voPage = baseMapper.queryPage(page, appOrderPageForm);
+
+        voPage.getRecords().forEach(vo -> {
+            List<AppOrderProInfo> proInfoList = appOrderProInfoMapper.selectList(Wrappers.<AppOrderProInfo>lambdaQuery().eq(AppOrderProInfo::getOrderId, vo.getId()));
+            vo.setOrderProInfoList(proInfoList);
+        });
+        return voPage;
+    }
+
+    @Override
+    public AppOrderInfoVO queryInfoById(String orderId) {
+        //订单
+        AppOrder appOrder = appOrderMapper.selectById(orderId);
+        AppSite site = appSiteMapper.selectOne(Wrappers.lambdaQuery(AppSite.class).eq(AppSite::getOrgCode, appOrder.getOrgCode()));
+        //构建返回对象
+        AppOrderInfoVO appOrderInfoVO = new AppOrderInfoVO();
+        //订单编号
+        appOrderInfoVO.setOrderCode(appOrder.getOrderCode());
+        //下单时间
+        appOrderInfoVO.setCreateTime(appOrder.getCreateTime());
+        //使用地信息
+        appOrderInfoVO.setSiteName(site.getName());
+        appOrderInfoVO.setAddress(site.getAddress());
+        //付款信息
+        if (appOrder.getOrderStatus() > 0) {
+            appOrderInfoVO.setPayTime(appOrder.getPayTime());
+            appOrderInfoVO.setPrice(appOrder.getPrice());
+        }
+        //子订单信息
+        List<AppOrderProInfo> proInfoList = appOrderProInfoMapper.selectList(Wrappers.<AppOrderProInfo>lambdaQuery().eq(AppOrderProInfo::getOrderId, orderId));
+        appOrderInfoVO.setProInfoList(proInfoList);
+        //买家信息
+        SysUser sysUser = sysUserMapper.selectById(appOrder.getUserId());
+        appOrderInfoVO.setNikeName(sysUser.getUsername());
+        appOrderInfoVO.setPhoneNumber(sysUser.getPhone());
+        //费用信息
+        appOrderInfoVO.setTotalPrice(appOrder.getOriginalPrice());
+        appOrderInfoVO.setPrice(appOrder.getPrice());
+        //使用记录
+        List<AppIsinVO> appIsinVOList = new ArrayList<>();
+        //核销记录
+        List<VerificationRecordDTO> verificationRecordDTOList = new ArrayList<>();
+
+        List<AppIsin> appIsinList = appIsinMapper.selectList(Wrappers.<AppIsin>lambdaQuery().eq(AppIsin::getOrderId, orderId).eq(AppIsin::getIsinStatus, 2));
+        if (CollUtil.isNotEmpty(appIsinList)) {
+            Map<IsinUserInfoDTO, List<AppIsin>> map =
+                    appIsinList.stream()
+                            .collect(Collectors.groupingBy(
+                                    x -> new IsinUserInfoDTO(x.getFamilyId(), x.getFamilyUserName(), x.getUserPhone(), x.getIsinCode()),
+                                    Collectors.mapping(AppIsin -> AppIsin, Collectors.toCollection(ArrayList::new))));
+            map.keySet().forEach(p -> {
+                AppIsinVO isinVO = new AppIsinVO();
+                isinVO.setFamilyId(p.getFamilyId());
+                isinVO.setFamilyUserName(p.getFamilyUserName());
+                isinVO.setIsinCode(p.getIsinCode());
+                isinVO.setIsinList(map.get(p));
+                appIsinVOList.add(isinVO);
+            });
+            appOrderInfoVO.setIsinList(appIsinVOList);
+        }
+        //课程才有核销记录和优惠信息
+        if (appOrder.getType() == 2) {
+            BigDecimal sDiscounts = BigDecimal.ZERO;
+            BigDecimal tDiscounts = BigDecimal.ZERO;
+            for (AppOrderProInfo proInfo : proInfoList) {
+                if (proInfo.getOrFreePro() == 1) {
+                    sDiscounts = sDiscounts.add(proInfo.getOriginalPrice());
+                }
+                BigDecimal discounts = proInfo.getOriginalPrice().subtract(proInfo.getPrice());
+                tDiscounts = tDiscounts.add(discounts);
+            }
+            //优惠信息
+            if (sDiscounts.compareTo(BigDecimal.ZERO) != 0) {
+                appOrderInfoVO.setSDiscounts(sDiscounts);
+            }
+            if (tDiscounts.compareTo(BigDecimal.ZERO) != 0) {
+                appOrderInfoVO.setTDiscounts(tDiscounts);
+            }
+            //核销记录
+            List<AppCoursesVerificationRecord> verificationRecords =
+                    appCoursesVerificationRecordMapper.selectList(Wrappers.<AppCoursesVerificationRecord>lambdaQuery().eq(AppCoursesVerificationRecord::getOrderId, orderId));
+            if (CollUtil.isNotEmpty(verificationRecords)) {
+                Map<Integer, List<AppCoursesVerificationRecord>> listMap = verificationRecords.stream().collect(Collectors.groupingBy(AppCoursesVerificationRecord::getCoursesType));
+                listMap.keySet().forEach(p -> {
+                    VerificationRecordDTO verificationRecordDTO = new VerificationRecordDTO();
+                    verificationRecordDTO.setCoursesType(p).setVerificationRecordList(listMap.get(p));
+                    verificationRecordDTOList.add(new VerificationRecordDTO());
+                });
+                appOrderInfoVO.setVerificationRecordDTOList(verificationRecordDTOList);
+            }
+        }
+        return appOrderInfoVO;
     }
 }

+ 42 - 0
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/system/app/vo/AppIsinVO.java

@@ -0,0 +1,42 @@
+package org.jeecg.modules.system.app.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+import org.jeecg.modules.system.app.entity.AppIsin;
+import org.jeecgframework.poi.excel.annotation.Excel;
+
+import java.io.Serializable;
+import java.util.List;
+
+@Data
+@Accessors(chain = true)
+@EqualsAndHashCode(callSuper = false)
+@AllArgsConstructor
+@NoArgsConstructor
+@Schema(description = "订单详情使用记录响应对象")
+public class AppIsinVO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    @Excel(name = "用户ID(关联家庭用户表)", width = 15)
+    @Schema(description = "用户ID(关联家庭用户表)")
+    private String familyId;
+
+    @Excel(name = "用户名", width = 15)
+    @Schema(description = "用户名")
+    private String familyUserName;
+
+    @Excel(name = "手机号码", width = 15)
+    @Schema(description = "手机号码")
+    private String UserPhone;
+
+    @Excel(name = "券码号", width = 15)
+    @Schema(description = "券码号")
+    private String isinCode;
+
+    @Schema(description = "使用记录")
+    private List<AppIsin> isinList;
+}

+ 79 - 0
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/system/app/vo/AppOrderInfoVO.java

@@ -0,0 +1,79 @@
+package org.jeecg.modules.system.app.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+import org.jeecg.modules.system.app.dto.VerificationRecordDTO;
+import org.jeecg.modules.system.app.entity.AppOrderProInfo;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.List;
+
+@Data
+@Accessors(chain = true)
+@EqualsAndHashCode(callSuper = false)
+@AllArgsConstructor
+@NoArgsConstructor
+@Schema(description = "订单详情响应对象")
+public class AppOrderInfoVO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    @Schema(description = "ID")
+    private String id;
+
+    @Schema(description = "订单号")
+    private String orderCode;
+
+    @Schema(description = "订单状态")
+    private Integer orderStatus;
+
+    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @Schema(description = "下单时间")
+    private Date createTime;
+
+    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @Schema(description = "付款时间")
+    private Date payTime;
+
+    @Schema(description = "地点")
+    private String siteName;
+
+    @Schema(description = "地址")
+    private String address;
+
+    @Schema(description = "买家昵称")
+    private String nikeName;
+
+    @Schema(description = "买家电话")
+    private String phoneNumber;
+
+    @Schema(description = "商品总额")
+    private BigDecimal totalPrice;
+
+    @Schema(description = "试听优惠金额")
+    private BigDecimal sDiscounts;
+
+    @Schema(description = "团购优惠金额")
+    private BigDecimal tDiscounts;
+
+    @Schema(description = "实际付款")
+    private BigDecimal price;
+
+    @Schema(description = "订单信息")
+    private List<AppOrderProInfo> proInfoList;
+
+    @Schema(description = "使用记录")
+    private List<AppIsinVO> isinList;
+
+    @Schema(description = "核销记录")
+    private List<VerificationRecordDTO> verificationRecordDTOList;
+}

+ 7 - 2
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/system/app/vo/OrderPageVO.java

@@ -7,11 +7,13 @@ import lombok.Data;
 import lombok.EqualsAndHashCode;
 import lombok.NoArgsConstructor;
 import lombok.experimental.Accessors;
+import org.jeecg.modules.system.app.entity.AppOrderProInfo;
 import org.springframework.format.annotation.DateTimeFormat;
 
 import java.io.Serializable;
 import java.math.BigDecimal;
 import java.util.Date;
+import java.util.List;
 
 @Data
 @Accessors(chain = true)
@@ -30,8 +32,8 @@ public class OrderPageVO implements Serializable {
 
     @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
     @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
-    @Schema(description = "支付时间;支付时间")
-    private Date payTime;
+    @Schema(description = "创建时间")
+    private Date createTime;
 
     @Schema(description = "店铺名称")
     private String siteName;
@@ -41,4 +43,7 @@ public class OrderPageVO implements Serializable {
 
     @Schema(description = "实际支付价")
     private BigDecimal price;
+
+    @Schema(description = "子订单信息")
+    private List<AppOrderProInfo> orderProInfoList;
 }