diff --git a/sql/10-approval-coupon.sql b/sql/10-approval-coupon.sql
new file mode 100644
index 0000000..fea4a98
--- /dev/null
+++ b/sql/10-approval-coupon.sql
@@ -0,0 +1,33 @@
+-- 体验券领用申请单业务表与明细子表(可重复执行)
+-- 目标库:db_gxtyzx(master)
+-- 执行顺序:01-approval.sql -> 02-approval_menu.sql -> 03-approval_orgs_roles.sql
+-- -> 04-approval_role_grants.sql -> 05-approval_phase2.sql -> 10-approval-coupon.sql
+--
+-- 覆盖 ADR 0013(体验券领用):申请事由为唯一业务字段(经办人/经办部门复用实例快照),
+-- 明细按券种每类最多一行(uk_instance_type 兜底),不记券号、不核销、不统计剩余数量。
+
+CREATE TABLE IF NOT EXISTS approval_coupon_form (
+ id BIGINT NOT NULL AUTO_INCREMENT,
+ tenant_id INT NOT NULL DEFAULT 10150,
+ instance_id BIGINT NOT NULL,
+ apply_reason VARCHAR(500) NOT NULL COMMENT '申请事由',
+ create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ PRIMARY KEY (id),
+ UNIQUE KEY uk_instance (instance_id)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='体验券领用申请单';
+
+CREATE TABLE IF NOT EXISTS approval_coupon_item (
+ id BIGINT NOT NULL AUTO_INCREMENT,
+ tenant_id INT NOT NULL DEFAULT 10150,
+ instance_id BIGINT NOT NULL,
+ line_no INT NOT NULL COMMENT '行号,按提交顺序重排为 1..N',
+ coupon_type VARCHAR(40) NOT NULL COMMENT '券种编码:7 类固定编码(ADR 0013)',
+ quantity INT NOT NULL COMMENT '数量,≥1',
+ valid_until DATE NOT NULL COMMENT '有效期至(截止日单点)',
+ create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ PRIMARY KEY (id),
+ UNIQUE KEY uk_instance_line (instance_id, line_no),
+ UNIQUE KEY uk_instance_type (instance_id, coupon_type)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='体验券领用明细';
diff --git a/src/main/java/com/gxwebsoft/approval/doc/coupon/ApprovalCouponForm.java b/src/main/java/com/gxwebsoft/approval/doc/coupon/ApprovalCouponForm.java
new file mode 100644
index 0000000..5de029b
--- /dev/null
+++ b/src/main/java/com/gxwebsoft/approval/doc/coupon/ApprovalCouponForm.java
@@ -0,0 +1,35 @@
+package com.gxwebsoft.approval.doc.coupon;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.annotations.ApiModel;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * 体验券领用申请单(ADR 0013):业务字段只有申请事由;
+ * 经办人复用实例的 reporter_name、经办部门复用 report_org_name,不落本表。
+ */
+@Data
+@ApiModel(description = "体验券领用申请单")
+@TableName("approval_coupon_form")
+public class ApprovalCouponForm implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ @TableId(type = IdType.AUTO)
+ private Long id;
+
+ private Integer tenantId;
+
+ private Long instanceId;
+
+ /** 申请事由,必填,≤500 字。 */
+ private String applyReason;
+
+ private LocalDateTime createTime;
+
+ private LocalDateTime updateTime;
+}
diff --git a/src/main/java/com/gxwebsoft/approval/doc/coupon/ApprovalCouponItem.java b/src/main/java/com/gxwebsoft/approval/doc/coupon/ApprovalCouponItem.java
new file mode 100644
index 0000000..bcd940a
--- /dev/null
+++ b/src/main/java/com/gxwebsoft/approval/doc/coupon/ApprovalCouponItem.java
@@ -0,0 +1,44 @@
+package com.gxwebsoft.approval.doc.coupon;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.annotations.ApiModel;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+/**
+ * 体验券领用明细行(ADR 0013):7 类券固定编码,每类券最多一行(uk_instance_type)。
+ */
+@Data
+@ApiModel(description = "体验券领用明细")
+@TableName("approval_coupon_item")
+public class ApprovalCouponItem implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ @TableId(type = IdType.AUTO)
+ private Long id;
+
+ private Integer tenantId;
+
+ private Long instanceId;
+
+ /** 行号:按提交顺序重排为 1..N。 */
+ private Integer lineNo;
+
+ /** 券种编码,取值见 {@link CouponDocumentType} 的 7 类固定编码。 */
+ private String couponType;
+
+ /** 数量,≥1。 */
+ private Integer quantity;
+
+ /** 有效期至(截止日单点)。 */
+ private LocalDate validUntil;
+
+ private LocalDateTime createTime;
+
+ private LocalDateTime updateTime;
+}
diff --git a/src/main/java/com/gxwebsoft/approval/doc/coupon/ApprovalCouponParam.java b/src/main/java/com/gxwebsoft/approval/doc/coupon/ApprovalCouponParam.java
new file mode 100644
index 0000000..3bdacad
--- /dev/null
+++ b/src/main/java/com/gxwebsoft/approval/doc/coupon/ApprovalCouponParam.java
@@ -0,0 +1,20 @@
+package com.gxwebsoft.approval.doc.coupon;
+
+import com.gxwebsoft.approval.document.ApprovalDocumentParam;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * 体验券领用申请单草稿参数;id 为审批实例id,更新草稿时传入,明细行走基类 lines。
+ *
+ *
经办人/经办部门由服务端按登录态带出,不在参数中接收。
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class ApprovalCouponParam extends ApprovalDocumentParam {
+ private static final long serialVersionUID = 1L;
+
+ @ApiModelProperty("申请事由,必填,最多500字")
+ private String applyReason;
+}
diff --git a/src/main/java/com/gxwebsoft/approval/doc/coupon/CouponDocumentType.java b/src/main/java/com/gxwebsoft/approval/doc/coupon/CouponDocumentType.java
new file mode 100644
index 0000000..b35b7fb
--- /dev/null
+++ b/src/main/java/com/gxwebsoft/approval/doc/coupon/CouponDocumentType.java
@@ -0,0 +1,292 @@
+package com.gxwebsoft.approval.doc.coupon;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.gxwebsoft.approval.constant.ApprovalConstants;
+import com.gxwebsoft.approval.document.AbstractApprovalDocumentType;
+import com.gxwebsoft.approval.document.ApprovalDocumentParam;
+import com.gxwebsoft.approval.document.ApprovalLineSupport;
+import com.gxwebsoft.approval.entity.ApprovalInstance;
+import com.gxwebsoft.approval.mapper.ApprovalCouponFormMapper;
+import com.gxwebsoft.approval.mapper.ApprovalCouponItemMapper;
+import com.gxwebsoft.approval.support.ApprovalLineSpec;
+import com.gxwebsoft.approval.vo.ApprovalDetail;
+import com.gxwebsoft.common.core.exception.BusinessException;
+import com.gxwebsoft.common.system.entity.User;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+import java.time.LocalDate;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 体验券领用申请单(ADR 0013)。
+ *
+ * 节点链:报送人 → 申请部门负责人 → 相关部门(固定租户角色 approval_related_dept)→
+ * 分管领导 → 总经理 → 发放人(通过即表示已发出,可驳回)→ 报送人存档 → 归档。
+ * 领用人即申请人,不占节点,只作存档确认人。
+ *
+ * 明细按券种每类最多一行:同一单内重复直接拒绝并指出券种与行号,数据库另有
+ * {@code uk_instance_type(instance_id, coupon_type)} 兜底。
+ */
+@Component
+public class CouponDocumentType extends AbstractApprovalDocumentType {
+
+ /** 节点链:相关部门为固定角色,不按券种动态生成会签组(ADR 0013)。 */
+ static final String NODES_JSON = "["
+ + "{\"key\":\"reportLeader\",\"type\":\"APPROVE\",\"resolver\":\"reporterOrgLeader\",\"name\":\"申请部门负责人\"},"
+ + "{\"key\":\"relatedDept\",\"type\":\"APPROVE\",\"resolver\":\"roleRelatedDept\",\"name\":\"相关部门\"},"
+ + "{\"key\":\"deputy\",\"type\":\"APPROVE\",\"resolver\":\"reporterOrgDeputy\",\"name\":\"分管领导\"},"
+ + "{\"key\":\"generalManager\",\"type\":\"APPROVE\",\"resolver\":\"roleGeneralManager\",\"name\":\"总经理\"},"
+ + "{\"key\":\"issuer\",\"type\":\"APPROVE\",\"resolver\":\"roleIssuer\",\"name\":\"发放人\"},"
+ + "{\"key\":\"confirm\",\"type\":\"CONFIRM\",\"resolver\":\"reporter\",\"name\":\"存档\"},"
+ + "{\"key\":\"archive\",\"type\":\"ARCHIVE\",\"resolver\":\"archivist\",\"name\":\"归档\"}"
+ + "]";
+
+ /** 7 类固定券种(ADR 0013):顺序即前端下拉顺序。 */
+ private static final Map COUPON_TYPES;
+
+ static {
+ Map types = new LinkedHashMap<>();
+ types.put("SWIMMING_DIVING", "游泳跳水馆单次");
+ types.put("TENNIS_CENTER", "网球中心");
+ types.put("TRAINING_HALL", "综合训练馆");
+ types.put("FIVE_A_SIDE", "五人制足球场单次");
+ types.put("GYM_BIWEEKLY", "威拓普健身馆VIP双周卡");
+ types.put("GYM_WEEKLY", "威拓普健身馆周卡");
+ types.put("GYM_MONTHLY", "威拓普健身馆月卡");
+ COUPON_TYPES = Collections.unmodifiableMap(types);
+ }
+
+ /** 明细列(ADR 0004 / 0013):券种、数量、有效期至。 */
+ private static final List LINE_COLUMNS;
+
+ static {
+ List options = new ArrayList<>();
+ for (Map.Entry entry : COUPON_TYPES.entrySet()) {
+ options.add(new ApprovalLineSpec.Option(entry.getKey(), entry.getValue()));
+ }
+ LINE_COLUMNS = Collections.unmodifiableList(List.of(
+ ApprovalLineSpec.enumOf("couponType", "券种", true, options),
+ ApprovalLineSpec.integer("quantity", "数量", true),
+ ApprovalLineSpec.date("validUntil", "有效期至", true)
+ ));
+ }
+
+ @Resource
+ private ApprovalCouponFormMapper couponFormMapper;
+ @Resource
+ private ApprovalCouponItemMapper couponItemMapper;
+
+ @Override
+ public String flowCode() {
+ return ApprovalConstants.FLOW_COUPON;
+ }
+
+ @Override
+ public String docType() {
+ return ApprovalConstants.FLOW_COUPON;
+ }
+
+ @Override
+ public String flowName() {
+ return "体验券领用申请单";
+ }
+
+ @Override
+ public String nodesJson() {
+ return NODES_JSON;
+ }
+
+ @Override
+ public String noPrefix() {
+ return ApprovalConstants.NO_PREFIX_COUPON;
+ }
+
+ @Override
+ public List lineColumns() {
+ return LINE_COLUMNS;
+ }
+
+ /** 附件不设必传分类,沿用「整单至少一张附件」(ADR 0013)。 */
+ @Override
+ public String requiredAttachmentCategory() {
+ return null;
+ }
+
+ @Override
+ public Class extends ApprovalDocumentParam> paramClass() {
+ return ApprovalCouponParam.class;
+ }
+
+ @Override
+ public void validate(ApprovalDocumentParam param, User user) {
+ ApprovalCouponParam coupon = cast(param);
+ requireText("申请事由", coupon.getApplyReason(), 500);
+ // 明细在持久化前统一校验;这里先做结构校验与业务校验,避免先落业务主表再报错
+ List