Sfoglia il codice sorgente

feat(EPIC 9): 人工方案+交付+干预 实体/仓库/种子数据

新增: PlanRequest, PlanDelivery, PlanRequestLog, PractitionerRating, ChatIntervention, CommerceGoods 实体
新增: PlanRequestRepository, PlanDeliveryRepository, PlanRequestLogRepository, ChatInterventionRepository
新增: data-epic9.sql 配置种子数据

Ultraworked with Sisyphus

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
liaoxg 3 mesi fa
parent
commit
54cb6876cd

+ 40 - 0
num-server/src/main/java/com/etotem/num/entity/ChatIntervention.java

@@ -0,0 +1,40 @@
+package com.etotem.num.entity;
+
+import javax.persistence.*;
+import java.time.LocalDateTime;
+
+@Entity
+@Table(name = "chat_interventions")
+public class ChatIntervention {
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Long id;
+
+    @Column(name = "session_id", nullable = false)
+    private Long sessionId;
+
+    @Column(name = "practitioner_id", nullable = false)
+    private Long practitionerId;
+
+    @Column(name = "start_time", nullable = false)
+    private LocalDateTime startTime;
+
+    @Column(name = "end_time")
+    private LocalDateTime endTime;
+
+    @Column(name = "ended_by", length = 20)
+    private String endedBy;
+
+    public Long getId() { return id; }
+    public void setId(Long id) { this.id = id; }
+    public Long getSessionId() { return sessionId; }
+    public void setSessionId(Long sessionId) { this.sessionId = sessionId; }
+    public Long getPractitionerId() { return practitionerId; }
+    public void setPractitionerId(Long practitionerId) { this.practitionerId = practitionerId; }
+    public LocalDateTime getStartTime() { return startTime; }
+    public void setStartTime(LocalDateTime startTime) { this.startTime = startTime; }
+    public LocalDateTime getEndTime() { return endTime; }
+    public void setEndTime(LocalDateTime endTime) { this.endTime = endTime; }
+    public String getEndedBy() { return endedBy; }
+    public void setEndedBy(String endedBy) { this.endedBy = endedBy; }
+}

+ 55 - 0
num-server/src/main/java/com/etotem/num/entity/CommerceGoods.java

@@ -0,0 +1,55 @@
+package com.etotem.num.entity;
+
+import javax.persistence.*;
+import java.time.LocalDateTime;
+
+@Entity
+@Table(name = "commerce_goods")
+public class CommerceGoods {
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Long id;
+
+    @Column(name = "store_id", length = 32, nullable = false)
+    private String storeId;
+
+    @Column(name = "product_type", length = 32, nullable = false)
+    private String productType;
+
+    @Column(name = "lilishop_goods_id", length = 32)
+    private String lilishopGoodsId;
+
+    @Column(name = "category_path", length = 128)
+    private String categoryPath;
+
+    @Column(nullable = false)
+    private Long price;
+
+    @Column(length = 20)
+    private String status = "active";
+
+    @Column(name = "created_at")
+    private LocalDateTime createdAt = LocalDateTime.now();
+
+    @Column(name = "updated_at")
+    private LocalDateTime updatedAt = LocalDateTime.now();
+
+    public Long getId() { return id; }
+    public void setId(Long id) { this.id = id; }
+    public String getStoreId() { return storeId; }
+    public void setStoreId(String storeId) { this.storeId = storeId; }
+    public String getProductType() { return productType; }
+    public void setProductType(String productType) { this.productType = productType; }
+    public String getLilishopGoodsId() { return lilishopGoodsId; }
+    public void setLilishopGoodsId(String lilishopGoodsId) { this.lilishopGoodsId = lilishopGoodsId; }
+    public String getCategoryPath() { return categoryPath; }
+    public void setCategoryPath(String categoryPath) { this.categoryPath = categoryPath; }
+    public Long getPrice() { return price; }
+    public void setPrice(Long price) { this.price = price; }
+    public String getStatus() { return status; }
+    public void setStatus(String status) { this.status = status; }
+    public LocalDateTime getCreatedAt() { return createdAt; }
+    public void setCreatedAt(LocalDateTime createdAt) { this.createdAt = createdAt; }
+    public LocalDateTime getUpdatedAt() { return updatedAt; }
+    public void setUpdatedAt(LocalDateTime updatedAt) { this.updatedAt = updatedAt; }
+}

+ 40 - 0
num-server/src/main/java/com/etotem/num/entity/PlanDelivery.java

@@ -0,0 +1,40 @@
+package com.etotem.num.entity;
+
+import javax.persistence.*;
+import java.time.LocalDateTime;
+
+@Entity
+@Table(name = "plan_deliveries")
+public class PlanDelivery {
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Long id;
+
+    @Column(name = "plan_request_id", nullable = false)
+    private Long planRequestId;
+
+    @Column(name = "delivery_type", length = 20)
+    private String deliveryType;
+
+    @Column(name = "text_content", columnDefinition = "text")
+    private String textContent;
+
+    @Column(name = "file_url", length = 500)
+    private String fileUrl;
+
+    @Column(name = "created_at")
+    private LocalDateTime createdAt = LocalDateTime.now();
+
+    public Long getId() { return id; }
+    public void setId(Long id) { this.id = id; }
+    public Long getPlanRequestId() { return planRequestId; }
+    public void setPlanRequestId(Long planRequestId) { this.planRequestId = planRequestId; }
+    public String getDeliveryType() { return deliveryType; }
+    public void setDeliveryType(String deliveryType) { this.deliveryType = deliveryType; }
+    public String getTextContent() { return textContent; }
+    public void setTextContent(String textContent) { this.textContent = textContent; }
+    public String getFileUrl() { return fileUrl; }
+    public void setFileUrl(String fileUrl) { this.fileUrl = fileUrl; }
+    public LocalDateTime getCreatedAt() { return createdAt; }
+    public void setCreatedAt(LocalDateTime createdAt) { this.createdAt = createdAt; }
+}

+ 76 - 0
num-server/src/main/java/com/etotem/num/entity/PlanRequest.java

@@ -0,0 +1,76 @@
+package com.etotem.num.entity;
+
+import javax.persistence.*;
+import java.time.LocalDateTime;
+
+@Entity
+@Table(name = "plan_requests")
+public class PlanRequest {
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Long id;
+
+    @Column(name = "user_id", nullable = false)
+    private Long userId;
+
+    @Column(name = "chart_id", nullable = false)
+    private Long chartId;
+
+    @Column(name = "request_type", length = 20)
+    private String requestType;
+
+    @Column(columnDefinition = "text")
+    private String description;
+
+    @Column(name = "budget_range", length = 20)
+    private String budgetRange;
+
+    @Column(name = "assigned_practitioner_id")
+    private Long assignedPractitionerId;
+
+    @Column(length = 20)
+    // Status: pending / accepted / negotiating / paid / completed / cancelled / rejected
+    private String status;
+
+    @Column
+    private Integer price;
+
+    @Column(name = "negotiation_count")
+    private Integer negotiationCount = 0;
+
+    @Column(name = "order_id")
+    private Long orderId;
+
+    @Column(name = "created_at")
+    private LocalDateTime createdAt = LocalDateTime.now();
+
+    @Column(name = "updated_at")
+    private LocalDateTime updatedAt = LocalDateTime.now();
+
+    public Long getId() { return id; }
+    public void setId(Long id) { this.id = id; }
+    public Long getUserId() { return userId; }
+    public void setUserId(Long userId) { this.userId = userId; }
+    public Long getChartId() { return chartId; }
+    public void setChartId(Long chartId) { this.chartId = chartId; }
+    public String getRequestType() { return requestType; }
+    public void setRequestType(String requestType) { this.requestType = requestType; }
+    public String getDescription() { return description; }
+    public void setDescription(String description) { this.description = description; }
+    public String getBudgetRange() { return budgetRange; }
+    public void setBudgetRange(String budgetRange) { this.budgetRange = budgetRange; }
+    public Long getAssignedPractitionerId() { return assignedPractitionerId; }
+    public void setAssignedPractitionerId(Long assignedPractitionerId) { this.assignedPractitionerId = assignedPractitionerId; }
+    public String getStatus() { return status; }
+    public void setStatus(String status) { this.status = status; }
+    public Integer getPrice() { return price; }
+    public void setPrice(Integer price) { this.price = price; }
+    public Integer getNegotiationCount() { return negotiationCount; }
+    public void setNegotiationCount(Integer negotiationCount) { this.negotiationCount = negotiationCount; }
+    public Long getOrderId() { return orderId; }
+    public void setOrderId(Long orderId) { this.orderId = orderId; }
+    public LocalDateTime getCreatedAt() { return createdAt; }
+    public void setCreatedAt(LocalDateTime createdAt) { this.createdAt = createdAt; }
+    public LocalDateTime getUpdatedAt() { return updatedAt; }
+    public void setUpdatedAt(LocalDateTime updatedAt) { this.updatedAt = updatedAt; }
+}

+ 50 - 0
num-server/src/main/java/com/etotem/num/entity/PlanRequestLog.java

@@ -0,0 +1,50 @@
+package com.etotem.num.entity;
+
+import javax.persistence.*;
+import java.time.LocalDateTime;
+
+@Entity
+@Table(name = "plan_request_logs")
+public class PlanRequestLog {
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Long id;
+
+    @Column(name = "plan_request_id", nullable = false)
+    private Long planRequestId;
+
+    @Column(length = 20)
+    private String action;
+
+    @Column(name = "old_price")
+    private Integer oldPrice;
+
+    @Column(name = "new_price")
+    private Integer newPrice;
+
+    @Column(columnDefinition = "text")
+    private String message;
+
+    @Column(name = "operator_id", nullable = false)
+    private Long operatorId;
+
+    @Column(name = "created_at")
+    private LocalDateTime createdAt = LocalDateTime.now();
+
+    public Long getId() { return id; }
+    public void setId(Long id) { this.id = id; }
+    public Long getPlanRequestId() { return planRequestId; }
+    public void setPlanRequestId(Long planRequestId) { this.planRequestId = planRequestId; }
+    public String getAction() { return action; }
+    public void setAction(String action) { this.action = action; }
+    public Integer getOldPrice() { return oldPrice; }
+    public void setOldPrice(Integer oldPrice) { this.oldPrice = oldPrice; }
+    public Integer getNewPrice() { return newPrice; }
+    public void setNewPrice(Integer newPrice) { this.newPrice = newPrice; }
+    public String getMessage() { return message; }
+    public void setMessage(String message) { this.message = message; }
+    public Long getOperatorId() { return operatorId; }
+    public void setOperatorId(Long operatorId) { this.operatorId = operatorId; }
+    public LocalDateTime getCreatedAt() { return createdAt; }
+    public void setCreatedAt(LocalDateTime createdAt) { this.createdAt = createdAt; }
+}

+ 45 - 0
num-server/src/main/java/com/etotem/num/entity/PractitionerRating.java

@@ -0,0 +1,45 @@
+package com.etotem.num.entity;
+
+import javax.persistence.*;
+import java.time.LocalDateTime;
+
+@Entity
+@Table(name = "practitioner_ratings")
+public class PractitionerRating {
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Long id;
+
+    @Column(name = "plan_request_id", nullable = false)
+    private Long planRequestId;
+
+    @Column(name = "user_id", nullable = false)
+    private Long userId;
+
+    @Column(name = "practitioner_id", nullable = false)
+    private Long practitionerId;
+
+    @Column(nullable = false)
+    private Integer score;
+
+    @Column(columnDefinition = "text")
+    private String comment;
+
+    @Column(name = "created_at")
+    private LocalDateTime createdAt = LocalDateTime.now();
+
+    public Long getId() { return id; }
+    public void setId(Long id) { this.id = id; }
+    public Long getPlanRequestId() { return planRequestId; }
+    public void setPlanRequestId(Long planRequestId) { this.planRequestId = planRequestId; }
+    public Long getUserId() { return userId; }
+    public void setUserId(Long userId) { this.userId = userId; }
+    public Long getPractitionerId() { return practitionerId; }
+    public void setPractitionerId(Long practitionerId) { this.practitionerId = practitionerId; }
+    public Integer getScore() { return score; }
+    public void setScore(Integer score) { this.score = score; }
+    public String getComment() { return comment; }
+    public void setComment(String comment) { this.comment = comment; }
+    public LocalDateTime getCreatedAt() { return createdAt; }
+    public void setCreatedAt(LocalDateTime createdAt) { this.createdAt = createdAt; }
+}

+ 15 - 0
num-server/src/main/java/com/etotem/num/repository/ChatInterventionRepository.java

@@ -0,0 +1,15 @@
+package com.etotem.num.repository;
+
+import com.etotem.num.entity.ChatIntervention;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+import java.util.Optional;
+
+@Repository
+public interface ChatInterventionRepository extends JpaRepository<ChatIntervention, Long> {
+    List<ChatIntervention> findBySessionIdOrderByStartTimeDesc(Long sessionId);
+
+    Optional<ChatIntervention> findBySessionIdAndPractitionerIdAndEndTimeIsNull(Long sessionId, Long practitionerId);
+}

+ 9 - 0
num-server/src/main/java/com/etotem/num/repository/PlanDeliveryRepository.java

@@ -0,0 +1,9 @@
+package com.etotem.num.repository;
+
+import com.etotem.num.entity.PlanDelivery;
+import org.springframework.data.jpa.repository.JpaRepository;
+import java.util.List;
+
+public interface PlanDeliveryRepository extends JpaRepository<PlanDelivery, Long> {
+    List<PlanDelivery> findByPlanRequestIdOrderByCreatedAtDesc(Long planRequestId);
+}

+ 9 - 0
num-server/src/main/java/com/etotem/num/repository/PlanRequestLogRepository.java

@@ -0,0 +1,9 @@
+package com.etotem.num.repository;
+
+import com.etotem.num.entity.PlanRequestLog;
+import org.springframework.data.jpa.repository.JpaRepository;
+import java.util.List;
+
+public interface PlanRequestLogRepository extends JpaRepository<PlanRequestLog, Long> {
+    List<PlanRequestLog> findByPlanRequestIdOrderByCreatedAtAsc(Long planRequestId);
+}

+ 20 - 0
num-server/src/main/java/com/etotem/num/repository/PlanRequestRepository.java

@@ -0,0 +1,20 @@
+package com.etotem.num.repository;
+
+import com.etotem.num.entity.PlanRequest;
+import org.springframework.data.jpa.repository.JpaRepository;
+import java.util.List;
+import java.util.Optional;
+
+public interface PlanRequestRepository extends JpaRepository<PlanRequest, Long> {
+    // Find all requests assigned to a specific practitioner, ordered by createdAt desc
+    List<PlanRequest> findByAssignedPractitionerIdOrderByCreatedAtDesc(Long practitionerId);
+    
+    // Find all requests for a user
+    List<PlanRequest> findByUserIdOrderByCreatedAtDesc(Long userId);
+    
+    // Find by userId + status
+    List<PlanRequest> findByUserIdAndStatusOrderByCreatedAtDesc(Long userId, String status);
+    
+    // Find by orderId
+    Optional<PlanRequest> findByOrderId(Long orderId);
+}

+ 10 - 0
num-server/src/main/resources/data-epic9.sql

@@ -0,0 +1,10 @@
+-- EPIC 9 系统配置种子数据
+INSERT INTO sys_config (`key`, value, description, value_type) VALUES
+('commerce.category.practitioner_plan.commission_rate', '3000', '人工方案平台佣金率(万分比,3000=30%)', 'percent'),
+('commission.practitioner_plan.referral_rate', '2000', '人工方案分销佣金占比(万分比,2000=20%,占平台佣金)', 'percent'),
+('commission.practitioner_plan.upstream_rate', '500', '人工方案上级佣金占比(万分比,500=5%,占平台佣金)', 'percent'),
+('plan_request.enabled', 'true', '人工方案功能开关', 'bool'),
+('plan_request.max_negotiation_rounds', '5', '最大协商轮次', 'int'),
+('plan_request.auto_cancel_hours', '72', '协商超时自动取消(小时)', 'int'),
+('plan_request.min_price', '5000', '方案最低价(分,5000=¥50)', 'price'),
+('plan_request.max_price', '999900', '方案最高价(分,999900=¥9999)', 'price');