Sfoglia il codice sorgente

Merge branch 'feature/service-vpp-20260701' of http://47.111.81.118:3000/uskycloud/usky-modules into fyc-vpp

fuyuchuan 11 ore fa
parent
commit
99f57139b5
47 ha cambiato i file con 1739 aggiunte e 59 eliminazioni
  1. 64 0
      service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/controller/web/DrController.java
  2. 1 1
      service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/domain/VppContract.java
  3. 38 1
      service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/domain/VppContractAuditLog.java
  4. 1 1
      service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/domain/VppContractTemplate.java
  5. 1 1
      service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/domain/VppCustomer.java
  6. 1 1
      service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/domain/VppCustomerAccess.java
  7. 1 1
      service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/domain/VppCustomerContact.java
  8. 2 2
      service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/domain/VppDevice.java
  9. 1 1
      service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/domain/VppDeviceControlLog.java
  10. 1 1
      service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/domain/VppDrEvaluation.java
  11. 1 1
      service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/domain/VppDrEvent.java
  12. 1 1
      service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/domain/VppDrExecution.java
  13. 76 0
      service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/domain/VppDrInvitation.java
  14. 1 1
      service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/domain/VppDrParticipation.java
  15. 1 1
      service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/domain/VppDrStrategy.java
  16. 1 1
      service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/domain/VppDrStrategyResource.java
  17. 1 1
      service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/domain/VppEnergyReadingMonthly.java
  18. 1 1
      service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/domain/VppEnergySummaryDaily.java
  19. 1 1
      service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/domain/VppFileArchive.java
  20. 1 1
      service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/domain/VppPaymentRecord.java
  21. 1 1
      service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/domain/VppRegistration.java
  22. 1 1
      service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/domain/VppReportAuditLog.java
  23. 1 1
      service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/domain/VppReportData.java
  24. 1 1
      service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/domain/VppReportLog.java
  25. 1 1
      service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/domain/VppReportRecord.java
  26. 1 1
      service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/domain/VppReportTask.java
  27. 1 1
      service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/domain/VppResourcePoint.java
  28. 1 1
      service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/domain/VppSettlementBill.java
  29. 1 1
      service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/domain/VppSettlementBillDetail.java
  30. 1 1
      service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/domain/VppSite.java
  31. 1 1
      service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/domain/VppSiteConfig.java
  32. 12 0
      service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/mapper/VppDrInvitationMapper.java
  33. 29 0
      service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/service/VppDrInvitationService.java
  34. 7 0
      service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/service/VppDrService.java
  35. 486 0
      service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/service/impl/VppDrInvitationServiceImpl.java
  36. 133 0
      service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/service/impl/VppDrServiceImpl.java
  37. 26 0
      service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/service/vo/DrEventRequest.java
  38. 13 0
      service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/service/vo/DrInvitationNotifyRequest.java
  39. 16 0
      service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/service/vo/DrInvitationReplyRequest.java
  40. 28 0
      service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/service/vo/DrInvitationRequest.java
  41. 43 0
      service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/service/vo/DrInvitationVO.java
  42. 17 1
      service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/service/vo/DrStrategyRequest.java
  43. 11 0
      service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/util/VppAuditHelper.java
  44. 41 0
      service-vpp/service-vpp-biz/src/main/resources/sql/vpp_dr_invitation_migration.sql
  45. 246 0
      service-vpp/service-vpp-biz/src/main/resources/sql/vpp_id_auto_increment_migration.sql
  46. 362 0
      service-vpp/service-vpp-biz/src/main/resources/sql/vpp_id_reset_from_one_migration.sql
  47. 62 28
      service-vpp/service-vpp-biz/src/main/resources/sql/vpp_schema.sql

+ 64 - 0
service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/controller/web/DrController.java

@@ -5,9 +5,15 @@ import com.usky.common.core.bean.CommonPage;
 import com.usky.vpp.domain.VppDrEvent;
 import com.usky.vpp.domain.VppDrEvaluation;
 import com.usky.vpp.domain.VppDrStrategy;
+import com.usky.vpp.service.VppDrInvitationService;
 import com.usky.vpp.service.VppDrService;
 import com.usky.vpp.service.vo.DrClearingRequest;
+import com.usky.vpp.service.vo.DrEventRequest;
 import com.usky.vpp.service.vo.DrInterveneRequest;
+import com.usky.vpp.service.vo.DrInvitationNotifyRequest;
+import com.usky.vpp.service.vo.DrInvitationReplyRequest;
+import com.usky.vpp.service.vo.DrInvitationRequest;
+import com.usky.vpp.service.vo.DrInvitationVO;
 import com.usky.vpp.service.vo.DrParticipateRequest;
 import com.usky.vpp.service.vo.DrStrategyRequest;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -25,6 +31,8 @@ public class DrController {
 
     @Autowired
     private VppDrService vppDrService;
+    @Autowired
+    private VppDrInvitationService vppDrInvitationService;
 
     @GetMapping(value = "/event")
     public ApiResult<CommonPage<VppDrEvent>> pageEvent(@RequestParam(required = false) Map<String, Object> params) {
@@ -36,6 +44,23 @@ public class DrController {
         return ApiResult.success(vppDrService.getEvent(id));
     }
 
+    @PostMapping(value = "/event")
+    public ApiResult<VppDrEvent> createEvent(@RequestBody DrEventRequest body) {
+        return ApiResult.success(vppDrService.createEvent(body));
+    }
+
+    @PutMapping(value = "/event/{id}")
+    public ApiResult<Void> updateEvent(@PathVariable("id") Long id, @RequestBody DrEventRequest body) {
+        vppDrService.updateEvent(id, body);
+        return ApiResult.success();
+    }
+
+    @DeleteMapping(value = "/event/{id}")
+    public ApiResult<Void> deleteEvent(@PathVariable("id") Long id) {
+        vppDrService.deleteEvent(id);
+        return ApiResult.success();
+    }
+
     @GetMapping(value = "/event/{id}/capability")
     public ApiResult<Object> assessCapability(@PathVariable("id") Long id) {
         return ApiResult.success(vppDrService.assessCapability(id));
@@ -102,4 +127,43 @@ public class DrController {
         vppDrService.deleteStrategy(id);
         return ApiResult.success();
     }
+
+    @GetMapping(value = "/invitation")
+    public ApiResult<CommonPage<DrInvitationVO>> pageInvitation(@RequestParam(required = false) Map<String, Object> params) {
+        return ApiResult.success(vppDrInvitationService.pageInvitation(params));
+    }
+
+    @GetMapping(value = "/invitation/{id}")
+    public ApiResult<DrInvitationVO> getInvitation(@PathVariable("id") Long id) {
+        return ApiResult.success(vppDrInvitationService.getInvitation(id));
+    }
+
+    @PostMapping(value = "/invitation")
+    public ApiResult<DrInvitationVO> createInvitation(@RequestBody DrInvitationRequest body) {
+        return ApiResult.success(vppDrInvitationService.createInvitation(body));
+    }
+
+    @PutMapping(value = "/invitation/{id}")
+    public ApiResult<Void> updateInvitation(@PathVariable("id") Long id, @RequestBody DrInvitationRequest body) {
+        vppDrInvitationService.updateInvitation(id, body);
+        return ApiResult.success();
+    }
+
+    @DeleteMapping(value = "/invitation/{id}")
+    public ApiResult<Void> deleteInvitation(@PathVariable("id") Long id) {
+        vppDrInvitationService.deleteInvitation(id);
+        return ApiResult.success();
+    }
+
+    @PostMapping(value = "/invitation/{id}/notify-sms")
+    public ApiResult<DrInvitationVO> notifyInvitationSms(@PathVariable("id") Long id,
+                                                         @RequestBody(required = false) DrInvitationNotifyRequest body) {
+        return ApiResult.success(vppDrInvitationService.notifySms(id, body));
+    }
+
+    @PostMapping(value = "/invitation/{id}/reply")
+    public ApiResult<DrInvitationVO> replyInvitation(@PathVariable("id") Long id,
+                                                       @RequestBody DrInvitationReplyRequest body) {
+        return ApiResult.success(vppDrInvitationService.replyInvitation(id, body));
+    }
 }

+ 1 - 1
service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/domain/VppContract.java

@@ -25,7 +25,7 @@ public class VppContract implements Serializable {
 
     private static final long serialVersionUID = 1L;
 
-    @TableId(value = "id", type = IdType.ASSIGN_ID)
+    @TableId(value = "id", type = IdType.AUTO)
     private Long id;
 
     @TableField("contract_no")

+ 38 - 1
service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/domain/VppContractAuditLog.java

@@ -1 +1,38 @@
-package com.usky.vpp.domain;



import com.baomidou.mybatisplus.annotation.IdType;

import com.baomidou.mybatisplus.annotation.TableField;

import com.baomidou.mybatisplus.annotation.TableId;

import com.baomidou.mybatisplus.annotation.TableName;

import lombok.Data;

import lombok.EqualsAndHashCode;

import java.io.Serializable;

import java.time.LocalDateTime;



/**

 * vpp_contract_audit_log

 */

@Data

@EqualsAndHashCode(callSuper = false)

@TableName("vpp_contract_audit_log")

public class VppContractAuditLog implements Serializable {



    private static final long serialVersionUID = 1L;



    @TableId(value = "id", type = IdType.ASSIGN_ID)

    private Long id;

    @TableField("contract_id")

    private Long contractId;

    private Integer action;

    private String opinion;

    @TableField("tenant_id")

    private Integer tenantId;

    @TableField("create_time")

    private LocalDateTime createTime;

    @TableField("created_by")

    private String createdBy;

}

+<<<<<<< Updated upstream
+package com.usky.vpp.domain;



import com.baomidou.mybatisplus.annotation.IdType;

import com.baomidou.mybatisplus.annotation.TableField;

import com.baomidou.mybatisplus.annotation.TableId;

import com.baomidou.mybatisplus.annotation.TableName;

import lombok.Data;

import lombok.EqualsAndHashCode;

import java.io.Serializable;

import java.time.LocalDateTime;



/**

 * vpp_contract_audit_log

 */

@Data

@EqualsAndHashCode(callSuper = false)

@TableName("vpp_contract_audit_log")

public class VppContractAuditLog implements Serializable {



    private static final long serialVersionUID = 1L;



    @TableId(value = "id", type = IdType.ASSIGN_ID)

    private Long id;

    @TableField("contract_id")

    private Long contractId;

    private Integer action;

    private String opinion;

    @TableField("tenant_id")

    private Integer tenantId;

    @TableField("create_time")

    private LocalDateTime createTime;

    @TableField("created_by")

    private String createdBy;

}


+=======
+package com.usky.vpp.domain;

+

+import com.baomidou.mybatisplus.annotation.IdType;

+import com.baomidou.mybatisplus.annotation.TableField;

+import com.baomidou.mybatisplus.annotation.TableId;

+import com.baomidou.mybatisplus.annotation.TableName;

+import lombok.Data;

+import lombok.EqualsAndHashCode;

+import java.io.Serializable;

+import java.time.LocalDateTime;

+

+/**

+ * vpp_contract_audit_log

+ */

+@Data

+@EqualsAndHashCode(callSuper = false)

+@TableName("vpp_contract_audit_log")

+public class VppContractAuditLog implements Serializable {

+

+    private static final long serialVersionUID = 1L;

+

+    @TableId(value = "id", type = IdType.AUTO)

+    private Long id;

+    @TableField("contract_id")

+    private Long contractId;

+    private Integer action;

+    private String opinion;

+    @TableField("tenant_id")

+    private Integer tenantId;

+    @TableField("create_time")

+    private LocalDateTime createTime;

+    @TableField("created_by")

+    private String createdBy;

+}

+>>>>>>> Stashed changes

+ 1 - 1
service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/domain/VppContractTemplate.java

@@ -23,7 +23,7 @@ public class VppContractTemplate implements Serializable {
 
     private static final long serialVersionUID = 1L;
 
-    @TableId(value = "id", type = IdType.ASSIGN_ID)
+    @TableId(value = "id", type = IdType.AUTO)
     private Long id;
     @TableField("template_code")
     @NotBlank(message = "模板编码不能为空!")

+ 1 - 1
service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/domain/VppCustomer.java

@@ -20,7 +20,7 @@ public class VppCustomer implements Serializable {
 
     private static final long serialVersionUID = 1L;
 
-    @TableId(value = "id", type = IdType.ASSIGN_ID)
+    @TableId(value = "id", type = IdType.AUTO)
     private Long id;
     @TableField("account_no")
     private String accountNo;

+ 1 - 1
service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/domain/VppCustomerAccess.java

@@ -20,7 +20,7 @@ public class VppCustomerAccess implements Serializable {
 
     private static final long serialVersionUID = 1L;
 
-    @TableId(value = "id", type = IdType.ASSIGN_ID)
+    @TableId(value = "id", type = IdType.AUTO)
     private Long id;
     @TableField("apply_no")
     private String applyNo;

+ 1 - 1
service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/domain/VppCustomerContact.java

@@ -19,7 +19,7 @@ public class VppCustomerContact implements Serializable {
 
     private static final long serialVersionUID = 1L;
 
-    @TableId(value = "id", type = IdType.ASSIGN_ID)
+    @TableId(value = "id", type = IdType.AUTO)
     private Long id;
     @TableField("customer_id")
     private Long customerId;

+ 2 - 2
service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/domain/VppDevice.java

@@ -20,7 +20,7 @@ public class VppDevice implements Serializable {
 
     private static final long serialVersionUID = 1L;
 
-    @TableId(value = "id", type = IdType.ASSIGN_ID)
+    @TableId(value = "id", type = IdType.AUTO)
     private Long id;
     @TableField("device_code")
     private String deviceCode;
@@ -28,7 +28,7 @@ public class VppDevice implements Serializable {
     private String deviceUuid;
     @TableField("device_name")
     private String deviceName;
-    /** 所属站点ID,关è�vpp_site.id */
+    /** 所属站点ID,关�vpp_site.id */
     @TableField("site_id")
     private Long siteId;
     @TableField("device_type")

+ 1 - 1
service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/domain/VppDeviceControlLog.java

@@ -19,7 +19,7 @@ public class VppDeviceControlLog implements Serializable {
 

     private static final long serialVersionUID = 1L;

 

-    @TableId(value = "id", type = IdType.ASSIGN_ID)

+    @TableId(value = "id", type = IdType.AUTO)

     private Long id;

     @TableField("device_id")

     private Long deviceId;


+ 1 - 1
service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/domain/VppDrEvaluation.java

@@ -20,7 +20,7 @@ public class VppDrEvaluation implements Serializable {
 
     private static final long serialVersionUID = 1L;
 
-    @TableId(value = "id", type = IdType.ASSIGN_ID)
+    @TableId(value = "id", type = IdType.AUTO)
     private Long id;
     @TableField("event_id")
     private Long eventId;

+ 1 - 1
service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/domain/VppDrEvent.java

@@ -20,7 +20,7 @@ public class VppDrEvent implements Serializable {
 
     private static final long serialVersionUID = 1L;
 
-    @TableId(value = "id", type = IdType.ASSIGN_ID)
+    @TableId(value = "id", type = IdType.AUTO)
     private Long id;
     @TableField("event_id")
     private String eventId;

+ 1 - 1
service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/domain/VppDrExecution.java

@@ -20,7 +20,7 @@ public class VppDrExecution implements Serializable {
 
     private static final long serialVersionUID = 1L;
 
-    @TableId(value = "id", type = IdType.ASSIGN_ID)
+    @TableId(value = "id", type = IdType.AUTO)
     private Long id;
     @TableField("event_id")
     private Long eventId;

+ 76 - 0
service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/domain/VppDrInvitation.java

@@ -0,0 +1,76 @@
+package com.usky.vpp.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+/**
+ * vpp_dr_invitation
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@TableName("vpp_dr_invitation")
+public class VppDrInvitation implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+    @TableField("invitation_no")
+    private String invitationNo;
+    @TableField("dr_event_id")
+    private Long drEventId;
+    @TableField("customer_id")
+    private Long customerId;
+    @TableField("execute_start_date")
+    private LocalDate executeStartDate;
+    @TableField("execute_end_date")
+    private LocalDate executeEndDate;
+    @TableField("reply_deadline")
+    private LocalDateTime replyDeadline;
+    @TableField("issue_time")
+    private LocalDateTime issueTime;
+    @TableField("transaction_type")
+    private Integer transactionType;
+    @TableField("response_type")
+    private Integer responseType;
+    @TableField("demand_capacity_kw")
+    private BigDecimal demandCapacityKw;
+    @TableField("declared_capacity_kw")
+    private BigDecimal declaredCapacityKw;
+    @TableField("reply_status")
+    private Integer replyStatus;
+    @TableField("response_status")
+    private Integer responseStatus;
+    @TableField("sms_notify_status")
+    private Integer smsNotifyStatus;
+    @TableField("sms_notify_at")
+    private LocalDateTime smsNotifyAt;
+    @TableField("sms_contact_id")
+    private Long smsContactId;
+    @TableField("participation_id")
+    private Long participationId;
+    private String remark;
+    @TableField("tenant_id")
+    private Integer tenantId;
+    @TableField("create_time")
+    private LocalDateTime createTime;
+    @TableField("update_time")
+    private LocalDateTime updateTime;
+    @TableField("created_by")
+    private String createdBy;
+    @TableField("updated_by")
+    private String updatedBy;
+    @TableField("delete_flag")
+    private Integer deleteFlag;
+    @TableField("deleted_at")
+    private LocalDateTime deletedAt;
+}

+ 1 - 1
service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/domain/VppDrParticipation.java

@@ -20,7 +20,7 @@ public class VppDrParticipation implements Serializable {
 
     private static final long serialVersionUID = 1L;
 
-    @TableId(value = "id", type = IdType.ASSIGN_ID)
+    @TableId(value = "id", type = IdType.AUTO)
     private Long id;
     @TableField("event_id")
     private Long eventId;

+ 1 - 1
service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/domain/VppDrStrategy.java

@@ -20,7 +20,7 @@ public class VppDrStrategy implements Serializable {
 
     private static final long serialVersionUID = 1L;
 
-    @TableId(value = "id", type = IdType.ASSIGN_ID)
+    @TableId(value = "id", type = IdType.AUTO)
     private Long id;
     @TableField("strategy_code")
     private String strategyCode;

+ 1 - 1
service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/domain/VppDrStrategyResource.java

@@ -19,7 +19,7 @@ public class VppDrStrategyResource implements Serializable {
 
     private static final long serialVersionUID = 1L;
 
-    @TableId(value = "id", type = IdType.ASSIGN_ID)
+    @TableId(value = "id", type = IdType.AUTO)
     private Long id;
     @TableField("strategy_id")
     private Long strategyId;

+ 1 - 1
service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/domain/VppEnergyReadingMonthly.java

@@ -20,7 +20,7 @@ public class VppEnergyReadingMonthly implements Serializable {
 
     private static final long serialVersionUID = 1L;
 
-    @TableId(value = "id", type = IdType.ASSIGN_ID)
+    @TableId(value = "id", type = IdType.AUTO)
     private Long id;
     @TableField("customer_id")
     private Long customerId;

+ 1 - 1
service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/domain/VppEnergySummaryDaily.java

@@ -21,7 +21,7 @@ public class VppEnergySummaryDaily implements Serializable {
 
     private static final long serialVersionUID = 1L;
 
-    @TableId(value = "id", type = IdType.ASSIGN_ID)
+    @TableId(value = "id", type = IdType.AUTO)
     private Long id;
     @TableField("summary_date")
     private LocalDate summaryDate;

+ 1 - 1
service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/domain/VppFileArchive.java

@@ -129,4 +129,4 @@ public class VppFileArchive implements Serializable {
      */
     @TableField("tenant_id")
     private Integer tenantId;
-}
+}

+ 1 - 1
service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/domain/VppPaymentRecord.java

@@ -21,7 +21,7 @@ public class VppPaymentRecord implements Serializable {
 

     private static final long serialVersionUID = 1L;

 

-    @TableId(value = "id", type = IdType.ASSIGN_ID)

+    @TableId(value = "id", type = IdType.AUTO)

     private Long id;

     @TableField("bill_id")

     private Long billId;


+ 1 - 1
service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/domain/VppRegistration.java

@@ -19,7 +19,7 @@ public class VppRegistration implements Serializable {
 
     private static final long serialVersionUID = 1L;
 
-    @TableId(value = "id", type = IdType.ASSIGN_ID)
+    @TableId(value = "id", type = IdType.AUTO)
     private Long id;
     @TableField("dn_id")
     private String dnId;

+ 1 - 1
service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/domain/VppReportAuditLog.java

@@ -19,7 +19,7 @@ public class VppReportAuditLog implements Serializable {
 

     private static final long serialVersionUID = 1L;

 

-    @TableId(value = "id", type = IdType.ASSIGN_ID)

+    @TableId(value = "id", type = IdType.AUTO)

     private Long id;

     @TableField("record_id")

     private Long recordId;


+ 1 - 1
service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/domain/VppReportData.java

@@ -19,7 +19,7 @@ public class VppReportData implements Serializable {
 
     private static final long serialVersionUID = 1L;
 
-    @TableId(value = "id", type = IdType.ASSIGN_ID)
+    @TableId(value = "id", type = IdType.AUTO)
     private Long id;
     @TableField("record_id")
     private Long recordId;

+ 1 - 1
service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/domain/VppReportLog.java

@@ -19,7 +19,7 @@ public class VppReportLog implements Serializable {
 
     private static final long serialVersionUID = 1L;
 
-    @TableId(value = "id", type = IdType.ASSIGN_ID)
+    @TableId(value = "id", type = IdType.AUTO)
     private Long id;
     @TableField("report_type")
     private String reportType;

+ 1 - 1
service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/domain/VppReportRecord.java

@@ -19,7 +19,7 @@ public class VppReportRecord implements Serializable {
 
     private static final long serialVersionUID = 1L;
 
-    @TableId(value = "id", type = IdType.ASSIGN_ID)
+    @TableId(value = "id", type = IdType.AUTO)
     private Long id;
     @TableField("task_id")
     private Long taskId;

+ 1 - 1
service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/domain/VppReportTask.java

@@ -19,7 +19,7 @@ public class VppReportTask implements Serializable {
 
     private static final long serialVersionUID = 1L;
 
-    @TableId(value = "id", type = IdType.ASSIGN_ID)
+    @TableId(value = "id", type = IdType.AUTO)
     private Long id;
     @TableField("task_no")
     private String taskNo;

+ 1 - 1
service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/domain/VppResourcePoint.java

@@ -21,7 +21,7 @@ public class VppResourcePoint implements Serializable {
 
     private static final long serialVersionUID = 1L;
 
-    @TableId(value = "id", type = IdType.ASSIGN_ID)
+    @TableId(value = "id", type = IdType.AUTO)
     private Long id;
     @TableField("resource_code")
     private String resourceCode;

+ 1 - 1
service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/domain/VppSettlementBill.java

@@ -21,7 +21,7 @@ public class VppSettlementBill implements Serializable {
 
     private static final long serialVersionUID = 1L;
 
-    @TableId(value = "id", type = IdType.ASSIGN_ID)
+    @TableId(value = "id", type = IdType.AUTO)
     private Long id;
     @TableField("bill_no")
     private String billNo;

+ 1 - 1
service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/domain/VppSettlementBillDetail.java

@@ -19,7 +19,7 @@ public class VppSettlementBillDetail implements Serializable {
 
     private static final long serialVersionUID = 1L;
 
-    @TableId(value = "id", type = IdType.ASSIGN_ID)
+    @TableId(value = "id", type = IdType.AUTO)
     private Long id;
     @TableField("bill_id")
     private Long billId;

+ 1 - 1
service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/domain/VppSite.java

@@ -21,7 +21,7 @@ public class VppSite implements Serializable {
 
     private static final long serialVersionUID = 1L;
 
-    @TableId(value = "id", type = IdType.ASSIGN_ID)
+    @TableId(value = "id", type = IdType.AUTO)
     private Long id;
     @TableField("site_code")
     private String siteCode;

+ 1 - 1
service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/domain/VppSiteConfig.java

@@ -21,7 +21,7 @@ public class VppSiteConfig implements Serializable {
 
     private static final long serialVersionUID = 1L;
 
-    @TableId(value = "id", type = IdType.ASSIGN_ID)
+    @TableId(value = "id", type = IdType.AUTO)
     private Long id;
     @TableField("site_id")
     private Long siteId;

+ 12 - 0
service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/mapper/VppDrInvitationMapper.java

@@ -0,0 +1,12 @@
+package com.usky.vpp.mapper;
+
+import com.usky.common.mybatis.core.CrudMapper;
+import com.usky.vpp.domain.VppDrInvitation;
+import org.springframework.stereotype.Repository;
+
+/**
+ * vpp_dr_invitation Mapper
+ */
+@Repository
+public interface VppDrInvitationMapper extends CrudMapper<VppDrInvitation> {
+}

+ 29 - 0
service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/service/VppDrInvitationService.java

@@ -0,0 +1,29 @@
+package com.usky.vpp.service;
+
+import com.usky.common.core.bean.CommonPage;
+import com.usky.vpp.service.vo.DrInvitationNotifyRequest;
+import com.usky.vpp.service.vo.DrInvitationReplyRequest;
+import com.usky.vpp.service.vo.DrInvitationRequest;
+import com.usky.vpp.service.vo.DrInvitationVO;
+
+import java.util.Map;
+
+/**
+ * 需求响应邀约业务接口
+ */
+public interface VppDrInvitationService {
+
+    CommonPage<DrInvitationVO> pageInvitation(Map<String, Object> params);
+
+    DrInvitationVO getInvitation(Long id);
+
+    DrInvitationVO createInvitation(DrInvitationRequest request);
+
+    void updateInvitation(Long id, DrInvitationRequest request);
+
+    void deleteInvitation(Long id);
+
+    DrInvitationVO notifySms(Long id, DrInvitationNotifyRequest request);
+
+    DrInvitationVO replyInvitation(Long id, DrInvitationReplyRequest request);
+}

+ 7 - 0
service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/service/VppDrService.java

@@ -5,6 +5,7 @@ import com.usky.vpp.domain.VppDrEvent;
 import com.usky.vpp.domain.VppDrEvaluation;
 import com.usky.vpp.domain.VppDrStrategy;
 import com.usky.vpp.service.vo.DrClearingRequest;
+import com.usky.vpp.service.vo.DrEventRequest;
 import com.usky.vpp.service.vo.DrInterveneRequest;
 import com.usky.vpp.service.vo.DrParticipateRequest;
 import com.usky.vpp.service.vo.DrStrategyRequest;
@@ -20,6 +21,12 @@ public interface VppDrService {
 
     VppDrEvent getEvent(Long id);
 
+    VppDrEvent createEvent(DrEventRequest request);
+
+    void updateEvent(Long id, DrEventRequest request);
+
+    void deleteEvent(Long id);
+
     Object assessCapability(Long eventId);
 
     void participate(Long eventId, DrParticipateRequest request);

+ 486 - 0
service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/service/impl/VppDrInvitationServiceImpl.java

@@ -0,0 +1,486 @@
+package com.usky.vpp.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.usky.common.core.bean.CommonPage;
+import com.usky.common.core.exception.BusinessException;
+import com.usky.vpp.domain.VppCustomer;
+import com.usky.vpp.domain.VppCustomerContact;
+import com.usky.vpp.domain.VppDrEvent;
+import com.usky.vpp.domain.VppDrInvitation;
+import com.usky.vpp.domain.VppDrParticipation;
+import com.usky.vpp.mapper.VppCustomerContactMapper;
+import com.usky.vpp.mapper.VppCustomerMapper;
+import com.usky.vpp.mapper.VppDrEventMapper;
+import com.usky.vpp.mapper.VppDrInvitationMapper;
+import com.usky.vpp.mapper.VppDrParticipationMapper;
+import com.usky.vpp.service.VppDrInvitationService;
+import com.usky.vpp.service.VppUnIntegrationService;
+import com.usky.vpp.service.vo.DrInvitationNotifyRequest;
+import com.usky.vpp.service.vo.DrInvitationReplyRequest;
+import com.usky.vpp.service.vo.DrInvitationRequest;
+import com.usky.vpp.service.vo.DrInvitationVO;
+import com.usky.vpp.util.VppAuditHelper;
+import com.usky.vpp.util.VppPageHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.CollectionUtils;
+import org.springframework.util.StringUtils;
+
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+@Service
+public class VppDrInvitationServiceImpl implements VppDrInvitationService {
+
+    private static final Logger log = LoggerFactory.getLogger(VppDrInvitationServiceImpl.class);
+
+    private static final int REPLY_PENDING = 0;
+    private static final int REPLY_ACCEPT = 1;
+    private static final int REPLY_REJECT = 2;
+    private static final int REPLY_TIMEOUT = 3;
+
+    private static final int RESPONSE_PENDING = 0;
+    private static final int RESPONSE_DECLARED = 1;
+    private static final int RESPONSE_CANCELLED = 4;
+
+    private static final int SMS_NOT_SENT = 0;
+    private static final int SMS_SENT = 1;
+    private static final int SMS_FAILED = 2;
+
+    private static final int PARTICIPATE_ACCEPT = 1;
+
+    @Autowired
+    private VppDrInvitationMapper invitationMapper;
+    @Autowired
+    private VppDrEventMapper eventMapper;
+    @Autowired
+    private VppCustomerMapper customerMapper;
+    @Autowired
+    private VppCustomerContactMapper contactMapper;
+    @Autowired
+    private VppDrParticipationMapper participationMapper;
+    @Autowired
+    private VppUnIntegrationService unIntegrationService;
+
+    @Override
+    public CommonPage<DrInvitationVO> pageInvitation(Map<String, Object> params) {
+        Page<VppDrInvitation> page = VppPageHelper.of(params);
+        LambdaQueryWrapper<VppDrInvitation> wrapper = new LambdaQueryWrapper<VppDrInvitation>()
+                .eq(VppDrInvitation::getDeleteFlag, VppAuditHelper.NOT_DELETED)
+                .orderByDesc(VppDrInvitation::getIssueTime);
+
+        applyListFilters(wrapper, params);
+
+        Page<VppDrInvitation> result = invitationMapper.selectPage(page, wrapper);
+        List<DrInvitationVO> records = toVoList(result.getRecords());
+        return new CommonPage<>(records, result.getTotal(), result.getCurrent(), result.getSize());
+    }
+
+    @Override
+    public DrInvitationVO getInvitation(Long id) {
+        return toVo(requireInvitation(id));
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public DrInvitationVO createInvitation(DrInvitationRequest request) {
+        validateCreateRequest(request);
+
+        VppDrEvent event = requireEvent(request.getDrEventId());
+        VppCustomer customer = requireCustomer(request.getCustomerId());
+        ensureInvitationUnique(request.getDrEventId(), request.getCustomerId(), null);
+
+        VppDrInvitation invitation = new VppDrInvitation();
+        invitation.setInvitationNo(VppAuditHelper.nextInvitationNo());
+        invitation.setDrEventId(request.getDrEventId());
+        invitation.setCustomerId(request.getCustomerId());
+        invitation.setExecuteStartDate(request.getExecuteStartDate());
+        invitation.setExecuteEndDate(request.getExecuteEndDate());
+        invitation.setReplyDeadline(request.getReplyDeadline());
+        invitation.setIssueTime(LocalDateTime.now());
+        invitation.setTransactionType(request.getTransactionType() != null ? request.getTransactionType() : event.getEventType());
+        invitation.setResponseType(request.getResponseType() != null ? request.getResponseType() : event.getResponseType());
+        invitation.setDemandCapacityKw(request.getDemandCapacityKw());
+        invitation.setDeclaredCapacityKw(request.getDeclaredCapacityKw() != null ? request.getDeclaredCapacityKw() : BigDecimal.ZERO);
+        invitation.setReplyStatus(REPLY_PENDING);
+        invitation.setResponseStatus(RESPONSE_PENDING);
+        invitation.setSmsNotifyStatus(SMS_NOT_SENT);
+        invitation.setSmsContactId(resolveSmsContactId(request.getSmsContactId(), customer.getId()));
+        invitation.setRemark(request.getRemark());
+        VppAuditHelper.fillCreate(invitation);
+        invitationMapper.insert(invitation);
+        return toVo(invitation);
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void updateInvitation(Long id, DrInvitationRequest request) {
+        VppDrInvitation invitation = requireInvitation(id);
+        if (invitation.getReplyStatus() != REPLY_PENDING || invitation.getResponseStatus() != RESPONSE_PENDING) {
+            throw new BusinessException("仅待回复状态的邀约可修改");
+        }
+        if (request == null) {
+            throw new BusinessException("请求不能为空");
+        }
+        if (request.getExecuteStartDate() == null || request.getExecuteEndDate() == null) {
+            throw new BusinessException("执行日期不能为空");
+        }
+        if (request.getReplyDeadline() == null) {
+            throw new BusinessException("邀约回复截止日期不能为空");
+        }
+        if (request.getDemandCapacityKw() == null || request.getDemandCapacityKw().compareTo(BigDecimal.ZERO) <= 0) {
+            throw new BusinessException("需求容量必须大于0");
+        }
+        validateDateRange(request.getExecuteStartDate(), request.getExecuteEndDate());
+
+        invitation.setExecuteStartDate(request.getExecuteStartDate());
+        invitation.setExecuteEndDate(request.getExecuteEndDate());
+        invitation.setReplyDeadline(request.getReplyDeadline());
+        invitation.setDemandCapacityKw(request.getDemandCapacityKw());
+        if (request.getDeclaredCapacityKw() != null) {
+            invitation.setDeclaredCapacityKw(request.getDeclaredCapacityKw());
+        }
+        if (request.getTransactionType() != null) {
+            invitation.setTransactionType(request.getTransactionType());
+        }
+        if (request.getResponseType() != null) {
+            invitation.setResponseType(request.getResponseType());
+        }
+        if (request.getSmsContactId() != null) {
+            requireContact(request.getSmsContactId(), invitation.getCustomerId());
+            invitation.setSmsContactId(request.getSmsContactId());
+        }
+        if (request.getRemark() != null) {
+            invitation.setRemark(request.getRemark());
+        }
+        VppAuditHelper.fillUpdate(invitation);
+        invitationMapper.updateById(invitation);
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void deleteInvitation(Long id) {
+        VppDrInvitation invitation = requireInvitation(id);
+        if (invitation.getReplyStatus() == REPLY_ACCEPT) {
+            throw new BusinessException("已参与的邀约不可删除");
+        }
+        if (invitation.getResponseStatus() != RESPONSE_PENDING) {
+            throw new BusinessException("仅待响应状态的邀约可删除");
+        }
+        if (invitation.getParticipationId() != null) {
+            throw new BusinessException("邀约已关联参与记录,不可删除");
+        }
+
+        VppAuditHelper.fillSoftDelete(invitation);
+        invitationMapper.updateById(invitation);
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public DrInvitationVO notifySms(Long id, DrInvitationNotifyRequest request) {
+        VppDrInvitation invitation = requireInvitation(id);
+        Long contactId = request != null && request.getContactId() != null
+                ? request.getContactId()
+                : invitation.getSmsContactId();
+        if (contactId == null) {
+            contactId = resolveSmsContactId(null, invitation.getCustomerId());
+            invitation.setSmsContactId(contactId);
+        }
+        VppCustomerContact contact = requireContact(contactId, invitation.getCustomerId());
+        String templateCode = request != null && StringUtils.hasText(request.getTemplateCode())
+                ? request.getTemplateCode()
+                : "vpp_dr_invitation";
+
+        try {
+            log.info("发送邀约短信 invitationNo={} contact={} phone={} template={}",
+                    invitation.getInvitationNo(), contact.getContactName(), contact.getContactPhone(), templateCode);
+            invitation.setSmsNotifyStatus(SMS_SENT);
+            invitation.setSmsNotifyAt(LocalDateTime.now());
+        } catch (Exception ex) {
+            log.warn("邀约短信发送失败 invitationId={}: {}", id, ex.getMessage());
+            invitation.setSmsNotifyStatus(SMS_FAILED);
+            throw new BusinessException("短信发送失败: " + ex.getMessage());
+        }
+
+        VppAuditHelper.fillUpdate(invitation);
+        invitationMapper.updateById(invitation);
+        return toVo(invitation);
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public DrInvitationVO replyInvitation(Long id, DrInvitationReplyRequest request) {
+        VppDrInvitation invitation = requireInvitation(id);
+        if (invitation.getReplyStatus() != REPLY_PENDING) {
+            throw new BusinessException("当前邀约已回复");
+        }
+        if (invitation.getReplyDeadline() != null && LocalDateTime.now().isAfter(invitation.getReplyDeadline())) {
+            throw new BusinessException("已超过邀约回复截止时间");
+        }
+        if (request == null || request.getParticipate() == null) {
+            throw new BusinessException("回复结果不能为空");
+        }
+
+        if (Boolean.TRUE.equals(request.getParticipate())) {
+            BigDecimal declared = request.getDeclaredCapacityKw() != null
+                    ? request.getDeclaredCapacityKw()
+                    : invitation.getDeclaredCapacityKw();
+            if (declared == null || declared.compareTo(BigDecimal.ZERO) <= 0) {
+                throw new BusinessException("申报容量必须大于0");
+            }
+
+            VppDrParticipation participation = findOrCreateParticipation(invitation, declared);
+            invitation.setParticipationId(participation.getId());
+            invitation.setDeclaredCapacityKw(declared);
+            invitation.setReplyStatus(REPLY_ACCEPT);
+            invitation.setResponseStatus(RESPONSE_DECLARED);
+            syncParticipationToUn(invitation.getDrEventId(), true);
+        } else {
+            if (!StringUtils.hasText(request.getReason())) {
+                throw new BusinessException("拒绝原因不能为空");
+            }
+            invitation.setReplyStatus(REPLY_REJECT);
+            invitation.setResponseStatus(RESPONSE_CANCELLED);
+            invitation.setRemark(appendRemark(invitation.getRemark(), "拒绝原因: " + request.getReason()));
+            syncParticipationToUn(invitation.getDrEventId(), false);
+        }
+
+        VppAuditHelper.fillUpdate(invitation);
+        invitationMapper.updateById(invitation);
+        return toVo(invitation);
+    }
+
+    private void applyListFilters(LambdaQueryWrapper<VppDrInvitation> wrapper, Map<String, Object> params) {
+        if (params == null) {
+            return;
+        }
+        if (params.get("drEventId") != null) {
+            wrapper.eq(VppDrInvitation::getDrEventId, Long.parseLong(params.get("drEventId").toString()));
+        }
+        if (params.get("responseType") != null) {
+            wrapper.eq(VppDrInvitation::getResponseType, Integer.parseInt(params.get("responseType").toString()));
+        }
+        if (params.get("replyStatus") != null) {
+            wrapper.eq(VppDrInvitation::getReplyStatus, Integer.parseInt(params.get("replyStatus").toString()));
+        }
+        if (params.get("responseStatus") != null) {
+            wrapper.eq(VppDrInvitation::getResponseStatus, Integer.parseInt(params.get("responseStatus").toString()));
+        }
+        if (params.get("customerId") != null) {
+            wrapper.eq(VppDrInvitation::getCustomerId, Long.parseLong(params.get("customerId").toString()));
+        }
+        if (params.get("customerName") != null && StringUtils.hasText(params.get("customerName").toString())) {
+            List<Long> customerIds = customerMapper.selectList(new LambdaQueryWrapper<VppCustomer>()
+                            .eq(VppCustomer::getDeleteFlag, VppAuditHelper.NOT_DELETED)
+                            .like(VppCustomer::getCustomerName, params.get("customerName").toString()))
+                    .stream()
+                    .map(VppCustomer::getId)
+                    .collect(Collectors.toList());
+            if (customerIds.isEmpty()) {
+                wrapper.eq(VppDrInvitation::getCustomerId, -1L);
+            } else {
+                wrapper.in(VppDrInvitation::getCustomerId, customerIds);
+            }
+        }
+        if (params.get("issueDateStart") != null && StringUtils.hasText(params.get("issueDateStart").toString())) {
+            LocalDate start = LocalDate.parse(params.get("issueDateStart").toString());
+            wrapper.ge(VppDrInvitation::getIssueTime, start.atStartOfDay());
+        }
+        if (params.get("issueDateEnd") != null && StringUtils.hasText(params.get("issueDateEnd").toString())) {
+            LocalDate end = LocalDate.parse(params.get("issueDateEnd").toString());
+            wrapper.le(VppDrInvitation::getIssueTime, end.atTime(LocalTime.MAX));
+        }
+    }
+
+    private VppDrParticipation findOrCreateParticipation(VppDrInvitation invitation, BigDecimal declaredCapacityKw) {
+        VppDrParticipation existing = participationMapper.selectOne(new LambdaQueryWrapper<VppDrParticipation>()
+                .eq(VppDrParticipation::getEventId, invitation.getDrEventId())
+                .eq(VppDrParticipation::getCustomerId, invitation.getCustomerId())
+                .isNull(VppDrParticipation::getResourceId)
+                .eq(VppDrParticipation::getDeleteFlag, VppAuditHelper.NOT_DELETED)
+                .last("LIMIT 1"));
+        if (existing != null) {
+            existing.setParticipateStatus(PARTICIPATE_ACCEPT);
+            existing.setDeclaredCapacityKw(declaredCapacityKw);
+            existing.setDeclaredAt(LocalDateTime.now());
+            VppAuditHelper.fillUpdate(existing);
+            participationMapper.updateById(existing);
+            return existing;
+        }
+
+        VppDrParticipation participation = new VppDrParticipation();
+        participation.setEventId(invitation.getDrEventId());
+        participation.setCustomerId(invitation.getCustomerId());
+        participation.setParticipateStatus(PARTICIPATE_ACCEPT);
+        participation.setDeclaredCapacityKw(declaredCapacityKw);
+        participation.setDeclaredAt(LocalDateTime.now());
+        VppAuditHelper.fillCreate(participation);
+        participationMapper.insert(participation);
+        return participation;
+    }
+
+    private void syncParticipationToUn(Long eventId, boolean participate) {
+        try {
+            unIntegrationService.submitParticipation(eventId, participate);
+        } catch (Exception ex) {
+            log.warn("同步 UN 邀约回复失败 eventId={}: {}", eventId, ex.getMessage());
+        }
+    }
+
+    private VppDrInvitation requireInvitation(Long id) {
+        VppDrInvitation invitation = invitationMapper.selectById(id);
+        if (invitation == null || VppAuditHelper.isDeleted(invitation.getDeleteFlag())) {
+            throw new BusinessException("邀约记录不存在");
+        }
+        return invitation;
+    }
+
+    private VppDrEvent requireEvent(Long id) {
+        VppDrEvent event = eventMapper.selectById(id);
+        if (event == null || VppAuditHelper.isDeleted(event.getDeleteFlag())) {
+            throw new BusinessException("需求响应事件不存在");
+        }
+        return event;
+    }
+
+    private VppCustomer requireCustomer(Long id) {
+        VppCustomer customer = customerMapper.selectById(id);
+        if (customer == null || VppAuditHelper.isDeleted(customer.getDeleteFlag())) {
+            throw new BusinessException("客户不存在");
+        }
+        return customer;
+    }
+
+    private VppCustomerContact requireContact(Long contactId, Long customerId) {
+        VppCustomerContact contact = contactMapper.selectById(contactId);
+        if (contact == null || VppAuditHelper.isDeleted(contact.getDeleteFlag())) {
+            throw new BusinessException("联系人不存在");
+        }
+        if (!Objects.equals(contact.getCustomerId(), customerId)) {
+            throw new BusinessException("联系人不属于该客户");
+        }
+        return contact;
+    }
+
+    private Long resolveSmsContactId(Long contactId, Long customerId) {
+        if (contactId != null) {
+            return requireContact(contactId, customerId).getId();
+        }
+        VppCustomerContact primary = contactMapper.selectOne(new LambdaQueryWrapper<VppCustomerContact>()
+                .eq(VppCustomerContact::getCustomerId, customerId)
+                .eq(VppCustomerContact::getIsPrimary, 1)
+                .eq(VppCustomerContact::getDeleteFlag, VppAuditHelper.NOT_DELETED)
+                .last("LIMIT 1"));
+        if (primary != null) {
+            return primary.getId();
+        }
+        VppCustomerContact any = contactMapper.selectOne(new LambdaQueryWrapper<VppCustomerContact>()
+                .eq(VppCustomerContact::getCustomerId, customerId)
+                .eq(VppCustomerContact::getDeleteFlag, VppAuditHelper.NOT_DELETED)
+                .last("LIMIT 1"));
+        return any != null ? any.getId() : null;
+    }
+
+    private void ensureInvitationUnique(Long drEventId, Long customerId, Long excludeId) {
+        LambdaQueryWrapper<VppDrInvitation> wrapper = new LambdaQueryWrapper<VppDrInvitation>()
+                .eq(VppDrInvitation::getDrEventId, drEventId)
+                .eq(VppDrInvitation::getCustomerId, customerId)
+                .eq(VppDrInvitation::getDeleteFlag, VppAuditHelper.NOT_DELETED);
+        if (excludeId != null) {
+            wrapper.ne(VppDrInvitation::getId, excludeId);
+        }
+        if (invitationMapper.selectCount(wrapper) > 0) {
+            throw new BusinessException("该事件已存在该企业的邀约记录");
+        }
+    }
+
+    private void validateCreateRequest(DrInvitationRequest request) {
+        if (request == null) {
+            throw new BusinessException("请求不能为空");
+        }
+        if (request.getDrEventId() == null) {
+            throw new BusinessException("需求响应事件不能为空");
+        }
+        if (request.getCustomerId() == null) {
+            throw new BusinessException("企业不能为空");
+        }
+        if (request.getExecuteStartDate() == null || request.getExecuteEndDate() == null) {
+            throw new BusinessException("执行日期不能为空");
+        }
+        if (request.getReplyDeadline() == null) {
+            throw new BusinessException("邀约回复截止日期不能为空");
+        }
+        if (request.getDemandCapacityKw() == null || request.getDemandCapacityKw().compareTo(BigDecimal.ZERO) <= 0) {
+            throw new BusinessException("需求容量必须大于0");
+        }
+        validateDateRange(request.getExecuteStartDate(), request.getExecuteEndDate());
+    }
+
+    private void validateDateRange(LocalDate start, LocalDate end) {
+        if (start.isAfter(end)) {
+            throw new BusinessException("执行开始日期不能晚于结束日期");
+        }
+    }
+
+    private String appendRemark(String original, String addition) {
+        if (!StringUtils.hasText(original)) {
+            return addition;
+        }
+        return original + "; " + addition;
+    }
+
+    private List<DrInvitationVO> toVoList(List<VppDrInvitation> invitations) {
+        if (CollectionUtils.isEmpty(invitations)) {
+            return Collections.emptyList();
+        }
+        Set<Long> eventIds = invitations.stream().map(VppDrInvitation::getDrEventId).collect(Collectors.toSet());
+        Set<Long> customerIds = invitations.stream().map(VppDrInvitation::getCustomerId).collect(Collectors.toSet());
+
+        Map<Long, VppDrEvent> eventMap = eventMapper.selectBatchIds(eventIds).stream()
+                .collect(Collectors.toMap(VppDrEvent::getId, e -> e, (a, b) -> a));
+        Map<Long, VppCustomer> customerMap = customerMapper.selectBatchIds(customerIds).stream()
+                .collect(Collectors.toMap(VppCustomer::getId, c -> c, (a, b) -> a));
+
+        return invitations.stream()
+                .map(inv -> toVo(inv, eventMap.get(inv.getDrEventId()), customerMap.get(inv.getCustomerId()), null))
+                .collect(Collectors.toList());
+    }
+
+    private DrInvitationVO toVo(VppDrInvitation invitation) {
+        VppDrEvent event = eventMapper.selectById(invitation.getDrEventId());
+        VppCustomer customer = customerMapper.selectById(invitation.getCustomerId());
+        VppCustomerContact contact = invitation.getSmsContactId() != null
+                ? contactMapper.selectById(invitation.getSmsContactId())
+                : null;
+        return toVo(invitation, event, customer, contact);
+    }
+
+    private DrInvitationVO toVo(VppDrInvitation invitation, VppDrEvent event, VppCustomer customer, VppCustomerContact contact) {
+        DrInvitationVO vo = new DrInvitationVO();
+        BeanUtils.copyProperties(invitation, vo);
+        if (event != null) {
+            vo.setDrEventCode(event.getEventId());
+        }
+        if (customer != null) {
+            vo.setCustomerName(customer.getCustomerName());
+        }
+        if (contact != null) {
+            vo.setSmsContactName(contact.getContactName());
+            vo.setSmsContactPhone(contact.getContactPhone());
+        }
+        return vo;
+    }
+}

+ 133 - 0
service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/service/impl/VppDrServiceImpl.java

@@ -21,6 +21,7 @@ import com.usky.vpp.mapper.VppResourcePointMapper;
 import com.usky.vpp.service.VppDrService;
 import com.usky.vpp.service.VppUnIntegrationService;
 import com.usky.vpp.service.vo.DrClearingRequest;
+import com.usky.vpp.service.vo.DrEventRequest;
 import com.usky.vpp.service.vo.DrInterveneRequest;
 import com.usky.vpp.service.vo.DrParticipateRequest;
 import com.usky.vpp.service.vo.DrStrategyRequest;
@@ -114,6 +115,72 @@ public class VppDrServiceImpl implements VppDrService {
         return event;
     }
 
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public VppDrEvent createEvent(DrEventRequest request) {
+        validateEventRequest(request);
+
+        String eventId = StringUtils.hasText(request.getEventId())
+                ? request.getEventId().trim()
+                : VppAuditHelper.nextEventId();
+        ensureEventIdUnique(eventId, null);
+
+        VppDrEvent event = new VppDrEvent();
+        event.setEventId(eventId);
+        event.setEventName(StringUtils.hasText(request.getEventName()) ? request.getEventName() : eventId);
+        event.setResponseType(request.getResponseType());
+        event.setEventType(request.getEventType());
+        event.setStartTime(request.getStartTime());
+        event.setEndTime(request.getEndTime());
+        event.setTargetCapacityKw(request.getTargetCapacityKw());
+        event.setClearedCapacityKw(request.getClearedCapacityKw());
+        event.setSubsidyPrice(request.getSubsidyPrice());
+        event.setEventStatus(EVENT_STATUS_PENDING);
+        VppAuditHelper.fillCreate(event);
+        eventMapper.insert(event);
+        return event;
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void updateEvent(Long id, DrEventRequest request) {
+        VppDrEvent event = getEvent(id);
+        if (event.getEventStatus() != EVENT_STATUS_PENDING) {
+            throw new BusinessException("仅待参与状态的事件可修改");
+        }
+        if (hasEventRelatedData(id)) {
+            throw new BusinessException("事件已有关联参与记录,不可修改");
+        }
+
+        validateEventRequest(request);
+
+        event.setEventName(StringUtils.hasText(request.getEventName()) ? request.getEventName() : event.getEventId());
+        event.setResponseType(request.getResponseType());
+        event.setEventType(request.getEventType());
+        event.setStartTime(request.getStartTime());
+        event.setEndTime(request.getEndTime());
+        event.setTargetCapacityKw(request.getTargetCapacityKw());
+        event.setClearedCapacityKw(request.getClearedCapacityKw());
+        event.setSubsidyPrice(request.getSubsidyPrice());
+        VppAuditHelper.fillUpdate(event);
+        eventMapper.updateById(event);
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void deleteEvent(Long id) {
+        VppDrEvent event = getEvent(id);
+        if (event.getEventStatus() != EVENT_STATUS_PENDING && event.getEventStatus() != EVENT_STATUS_CANCELLED) {
+            throw new BusinessException("仅待参与或已取消状态的事件可删除");
+        }
+        if (hasEventRelatedData(id)) {
+            throw new BusinessException("事件已有关联业务数据,不可删除");
+        }
+
+        VppAuditHelper.fillSoftDelete(event);
+        eventMapper.updateById(event);
+    }
+
     @Override
     public Object assessCapability(Long eventId) {
         VppDrEvent event = getEvent(eventId);
@@ -684,6 +751,72 @@ public class VppDrServiceImpl implements VppDrService {
                 .eq(VppDrStrategyResource::getStrategyId, id));
     }
 
+    private void validateEventRequest(DrEventRequest request) {
+        if (request == null) {
+            throw new BusinessException("请求不能为空");
+        }
+        if (request.getResponseType() == null) {
+            throw new BusinessException("响应类型不能为空");
+        }
+        if (request.getResponseType() < 1 || request.getResponseType() > 3) {
+            throw new BusinessException("响应类型无效,取值 1日前 2日内 3秒级");
+        }
+        if (request.getEventType() != null && (request.getEventType() < 1 || request.getEventType() > 2)) {
+            throw new BusinessException("事件类型无效,取值 1削峰 2填谷");
+        }
+        if (request.getStartTime() == null) {
+            throw new BusinessException("响应开始时间不能为空");
+        }
+        if (request.getEndTime() == null) {
+            throw new BusinessException("响应结束时间不能为空");
+        }
+        if (request.getEndTime().isBefore(request.getStartTime())) {
+            throw new BusinessException("响应结束时间不能早于开始时间");
+        }
+        if (request.getTargetCapacityKw() == null || request.getTargetCapacityKw().compareTo(BigDecimal.ZERO) <= 0) {
+            throw new BusinessException("目标容量必须大于0");
+        }
+        if (request.getClearedCapacityKw() != null && request.getClearedCapacityKw().compareTo(BigDecimal.ZERO) < 0) {
+            throw new BusinessException("出清容量不能为负数");
+        }
+        if (request.getSubsidyPrice() != null && request.getSubsidyPrice().compareTo(BigDecimal.ZERO) < 0) {
+            throw new BusinessException("补贴标准不能为负数");
+        }
+    }
+
+    private void ensureEventIdUnique(String eventId, Long excludeId) {
+        LambdaQueryWrapper<VppDrEvent> wrapper = new LambdaQueryWrapper<VppDrEvent>()
+                .eq(VppDrEvent::getEventId, eventId)
+                .eq(VppDrEvent::getDeleteFlag, VppAuditHelper.NOT_DELETED);
+        if (excludeId != null) {
+            wrapper.ne(VppDrEvent::getId, excludeId);
+        }
+        if (eventMapper.selectCount(wrapper) > 0) {
+            throw new BusinessException("事件ID已存在");
+        }
+    }
+
+    private boolean hasEventRelatedData(Long eventId) {
+        long participationCount = participationMapper.selectCount(
+                new LambdaQueryWrapper<VppDrParticipation>()
+                        .eq(VppDrParticipation::getEventId, eventId)
+                        .eq(VppDrParticipation::getDeleteFlag, VppAuditHelper.NOT_DELETED));
+        if (participationCount > 0) {
+            return true;
+        }
+        long executionCount = executionMapper.selectCount(
+                new LambdaQueryWrapper<VppDrExecution>()
+                        .eq(VppDrExecution::getEventId, eventId)
+                        .eq(VppDrExecution::getDeleteFlag, VppAuditHelper.NOT_DELETED));
+        if (executionCount > 0) {
+            return true;
+        }
+        return evaluationMapper.selectCount(
+                new LambdaQueryWrapper<VppDrEvaluation>()
+                        .eq(VppDrEvaluation::getEventId, eventId)
+                        .eq(VppDrEvaluation::getDeleteFlag, VppAuditHelper.NOT_DELETED)) > 0;
+    }
+
     private void validateStrategyRequest(DrStrategyRequest request) {
         if (request == null) {
             throw new BusinessException("请求不能为空");

+ 26 - 0
service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/service/vo/DrEventRequest.java

@@ -0,0 +1,26 @@
+package com.usky.vpp.service.vo;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+/**
+ * 需求响应事件创建/更新请求(手工录入,非 UN 同步)
+ */
+@Data
+public class DrEventRequest {
+
+    /** 运管平台事件 ID,创建时可选,不传则自动生成 */
+    private String eventId;
+    private String eventName;
+    /** 1日前 2日内 3秒级 */
+    private Integer responseType;
+    /** 1削峰 2填谷 */
+    private Integer eventType;
+    private LocalDateTime startTime;
+    private LocalDateTime endTime;
+    private BigDecimal targetCapacityKw;
+    private BigDecimal clearedCapacityKw;
+    private BigDecimal subsidyPrice;
+}

+ 13 - 0
service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/service/vo/DrInvitationNotifyRequest.java

@@ -0,0 +1,13 @@
+package com.usky.vpp.service.vo;
+
+import lombok.Data;
+
+/**
+ * 邀约短信通知请求
+ */
+@Data
+public class DrInvitationNotifyRequest {
+
+    private Long contactId;
+    private String templateCode;
+}

+ 16 - 0
service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/service/vo/DrInvitationReplyRequest.java

@@ -0,0 +1,16 @@
+package com.usky.vpp.service.vo;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+/**
+ * 企业回复邀约请求
+ */
+@Data
+public class DrInvitationReplyRequest {
+
+    private Boolean participate;
+    private BigDecimal declaredCapacityKw;
+    private String reason;
+}

+ 28 - 0
service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/service/vo/DrInvitationRequest.java

@@ -0,0 +1,28 @@
+package com.usky.vpp.service.vo;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+/**
+ * 需求响应邀约创建/更新请求
+ */
+@Data
+public class DrInvitationRequest {
+
+    private Long drEventId;
+    private Long customerId;
+    private LocalDate executeStartDate;
+    private LocalDate executeEndDate;
+    private LocalDateTime replyDeadline;
+    private BigDecimal demandCapacityKw;
+    private BigDecimal declaredCapacityKw;
+    /** 1削峰 2填谷 */
+    private Integer transactionType;
+    /** 1日前 2日内 3秒级 */
+    private Integer responseType;
+    private Long smsContactId;
+    private String remark;
+}

+ 43 - 0
service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/service/vo/DrInvitationVO.java

@@ -0,0 +1,43 @@
+package com.usky.vpp.service.vo;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+/**
+ * 需求响应邀约展示对象
+ */
+@Data
+public class DrInvitationVO {
+
+    private Long id;
+    private String invitationNo;
+    private Long drEventId;
+    private String drEventCode;
+    private Long customerId;
+    private String customerName;
+    private LocalDate executeStartDate;
+    private LocalDate executeEndDate;
+    private LocalDateTime replyDeadline;
+    private LocalDateTime issueTime;
+    private Integer transactionType;
+    private Integer responseType;
+    private BigDecimal demandCapacityKw;
+    private BigDecimal declaredCapacityKw;
+    private Integer replyStatus;
+    private Integer responseStatus;
+    private Integer smsNotifyStatus;
+    private LocalDateTime smsNotifyAt;
+    private Long smsContactId;
+    private String smsContactName;
+    private String smsContactPhone;
+    private Long participationId;
+    private String remark;
+    private Integer tenantId;
+    private LocalDateTime createTime;
+    private LocalDateTime updateTime;
+    private String createdBy;
+    private String updatedBy;
+}

+ 17 - 1
service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/service/vo/DrStrategyRequest.java

@@ -1,5 +1,7 @@
 package com.usky.vpp.service.vo;
 
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.databind.JsonNode;
 import lombok.Data;
 
 import java.math.BigDecimal;
@@ -16,11 +18,25 @@ public class DrStrategyRequest {
     private Integer responseType;
     private BigDecimal adjustStepKw;
     private Integer executeMode;
-    private String strategyConfig;
+    @JsonProperty("strategyConfig")
+    private JsonNode strategyConfigJson;
     private Integer isDefault;
     private Integer isEnabled;
     private List<DrStrategyResource> resources;
 
+    /**
+     * 策略扩展配置 JSON 字符串(兼容对象或字符串入参)
+     */
+    public String getStrategyConfig() {
+        if (strategyConfigJson == null || strategyConfigJson.isNull()) {
+            return null;
+        }
+        if (strategyConfigJson.isTextual()) {
+            return strategyConfigJson.asText();
+        }
+        return strategyConfigJson.toString();
+    }
+
     @Data
     public static class DrStrategyResource {
         private Long resourceId;

+ 11 - 0
service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/util/VppAuditHelper.java

@@ -5,6 +5,7 @@ import org.springframework.util.StringUtils;
 
 import java.lang.reflect.Method;
 import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
 import java.util.UUID;
 
 /**
@@ -68,6 +69,16 @@ public final class VppAuditHelper {
         return "ACC" + System.currentTimeMillis() + UUID.randomUUID().toString().substring(0, 4).toUpperCase();
     }
 
+    public static String nextEventId() {
+        return "EVE_" + DateTimeFormatter.ofPattern("yyyyMMddHHmmss").format(LocalDateTime.now())
+                + UUID.randomUUID().toString().substring(0, 4).toUpperCase();
+    }
+
+    public static String nextInvitationNo() {
+        return "INV_" + DateTimeFormatter.ofPattern("yyyyMMddHHmmss").format(LocalDateTime.now())
+                + UUID.randomUUID().toString().substring(0, 4).toUpperCase();
+    }
+
     private static String currentUsername() {
         try {
             return SecurityUtils.getUsername();

+ 41 - 0
service-vpp/service-vpp-biz/src/main/resources/sql/vpp_dr_invitation_migration.sql

@@ -0,0 +1,41 @@
+-- VPP 需求响应企业邀约表(已有库执行,可重复执行)
+-- 对应 Web「邀约管理」界面,详见 虚拟电厂平台数据库设计文档 V1.1 §5.23
+
+SET @sql = IF(
+    (SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = 'vpp_dr_invitation') = 0,
+    'CREATE TABLE `vpp_dr_invitation` (
+        `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT ''主键'',
+        `invitation_no` VARCHAR(32) NOT NULL COMMENT ''邀约编号'',
+        `dr_event_id` BIGINT NOT NULL COMMENT ''需求响应事件ID'',
+        `customer_id` BIGINT NOT NULL COMMENT ''客户ID'',
+        `execute_start_date` DATE NOT NULL COMMENT ''执行开始日期'',
+        `execute_end_date` DATE NOT NULL COMMENT ''执行结束日期'',
+        `reply_deadline` DATETIME(3) NOT NULL COMMENT ''邀约回复截止日期'',
+        `issue_time` DATETIME(3) NOT NULL COMMENT ''下发时间'',
+        `transaction_type` TINYINT NULL COMMENT ''交易类型 1削峰 2填谷'',
+        `response_type` TINYINT NOT NULL COMMENT ''1日前 2日内 3秒级'',
+        `demand_capacity_kw` DECIMAL(12,4) NOT NULL COMMENT ''需求容量 kW'',
+        `declared_capacity_kw` DECIMAL(12,4) NULL COMMENT ''已申报容量 kW'',
+        `reply_status` TINYINT NOT NULL COMMENT ''0待回复 1参与 2拒绝 3超时'',
+        `response_status` TINYINT NOT NULL COMMENT ''0待响应 1已申报 2执行中 3已结束 4已取消'',
+        `sms_notify_status` TINYINT NOT NULL DEFAULT 0 COMMENT ''0未发送 1已发送 2发送失败'',
+        `sms_notify_at` DATETIME(3) NULL COMMENT ''短信通知时间'',
+        `sms_contact_id` BIGINT NULL COMMENT ''通知联系人ID'',
+        `participation_id` BIGINT NULL COMMENT ''关联参与记录ID'',
+        `remark` VARCHAR(500) NULL COMMENT ''备注'',
+        `tenant_id` INT NULL COMMENT ''租户ID'',
+        `create_time` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT ''创建时间'',
+        `update_time` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT ''更新时间'',
+        `created_by` VARCHAR(30) NULL COMMENT ''创建人'',
+        `updated_by` VARCHAR(30) NULL COMMENT ''更新人'',
+        `delete_flag` INT(1) NOT NULL DEFAULT 0 COMMENT ''删除标识 0未删除 1已删除'',
+        `deleted_at` DATETIME(3) NULL COMMENT ''软删除时间'',
+        PRIMARY KEY (`id`),
+        UNIQUE KEY `uk_dr_invitation_no` (`invitation_no`),
+        UNIQUE KEY `uk_dr_invitation_event_customer` (`dr_event_id`, `customer_id`),
+        KEY `idx_dr_invitation_customer` (`customer_id`, `reply_status`),
+        KEY `idx_dr_invitation_issue` (`issue_time`, `response_type`)
+    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT=''需求响应企业邀约''',
+    'SELECT ''skip: vpp_dr_invitation already exists'''
+);
+PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

+ 246 - 0
service-vpp/service-vpp-biz/src/main/resources/sql/vpp_id_auto_increment_migration.sql

@@ -0,0 +1,246 @@
+-- VPP 主键自增迁移(已有库执行,可重复执行)
+-- 将各表 id 列改为 BIGINT AUTO_INCREMENT,与 MyBatis-Plus IdType.AUTO 对齐
+
+-- vpp_customer
+SET @sql = IF(
+    (SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'vpp_customer' AND column_name = 'id' AND EXTRA LIKE '%auto_increment%') = 0,
+    'ALTER TABLE `vpp_customer` MODIFY COLUMN `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT ''主键''',
+    'SELECT ''skip: vpp_customer.id already auto_increment'''
+);
+PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+
+-- vpp_customer_access
+SET @sql = IF(
+    (SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'vpp_customer_access' AND column_name = 'id' AND EXTRA LIKE '%auto_increment%') = 0,
+    'ALTER TABLE `vpp_customer_access` MODIFY COLUMN `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT ''主键''',
+    'SELECT ''skip: vpp_customer_access.id already auto_increment'''
+);
+PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+
+-- vpp_customer_contact
+SET @sql = IF(
+    (SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'vpp_customer_contact' AND column_name = 'id' AND EXTRA LIKE '%auto_increment%') = 0,
+    'ALTER TABLE `vpp_customer_contact` MODIFY COLUMN `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT ''主键''',
+    'SELECT ''skip: vpp_customer_contact.id already auto_increment'''
+);
+PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+
+-- vpp_contract
+SET @sql = IF(
+    (SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'vpp_contract' AND column_name = 'id' AND EXTRA LIKE '%auto_increment%') = 0,
+    'ALTER TABLE `vpp_contract` MODIFY COLUMN `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT ''主键''',
+    'SELECT ''skip: vpp_contract.id already auto_increment'''
+);
+PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+
+-- vpp_contract_template
+SET @sql = IF(
+    (SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'vpp_contract_template' AND column_name = 'id' AND EXTRA LIKE '%auto_increment%') = 0,
+    'ALTER TABLE `vpp_contract_template` MODIFY COLUMN `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT ''主键''',
+    'SELECT ''skip: vpp_contract_template.id already auto_increment'''
+);
+PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+
+-- vpp_contract_audit_log
+SET @sql = IF(
+    (SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'vpp_contract_audit_log' AND column_name = 'id' AND EXTRA LIKE '%auto_increment%') = 0,
+    'ALTER TABLE `vpp_contract_audit_log` MODIFY COLUMN `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT ''主键''',
+    'SELECT ''skip: vpp_contract_audit_log.id already auto_increment'''
+);
+PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+
+-- vpp_site
+SET @sql = IF(
+    (SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = 'vpp_site') > 0
+    AND (SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'vpp_site' AND column_name = 'id' AND EXTRA LIKE '%auto_increment%') = 0,
+    'ALTER TABLE `vpp_site` MODIFY COLUMN `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT ''主键''',
+    'SELECT ''skip: vpp_site.id already auto_increment or table missing'''
+);
+PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+
+-- vpp_site_config
+SET @sql = IF(
+    (SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = 'vpp_site_config') > 0
+    AND (SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'vpp_site_config' AND column_name = 'id' AND EXTRA LIKE '%auto_increment%') = 0,
+    'ALTER TABLE `vpp_site_config` MODIFY COLUMN `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT ''主键''',
+    'SELECT ''skip: vpp_site_config.id already auto_increment or table missing'''
+);
+PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+
+-- vpp_resource_point
+SET @sql = IF(
+    (SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'vpp_resource_point' AND column_name = 'id' AND EXTRA LIKE '%auto_increment%') = 0,
+    'ALTER TABLE `vpp_resource_point` MODIFY COLUMN `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT ''主键''',
+    'SELECT ''skip: vpp_resource_point.id already auto_increment'''
+);
+PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+
+-- vpp_resource_point_config
+SET @sql = IF(
+    (SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'vpp_resource_point_config' AND column_name = 'id' AND EXTRA LIKE '%auto_increment%') = 0,
+    'ALTER TABLE `vpp_resource_point_config` MODIFY COLUMN `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT ''主键''',
+    'SELECT ''skip: vpp_resource_point_config.id already auto_increment'''
+);
+PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+
+-- vpp_device
+SET @sql = IF(
+    (SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'vpp_device' AND column_name = 'id' AND EXTRA LIKE '%auto_increment%') = 0,
+    'ALTER TABLE `vpp_device` MODIFY COLUMN `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT ''主键''',
+    'SELECT ''skip: vpp_device.id already auto_increment'''
+);
+PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+
+-- vpp_device_control_log
+SET @sql = IF(
+    (SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'vpp_device_control_log' AND column_name = 'id' AND EXTRA LIKE '%auto_increment%') = 0,
+    'ALTER TABLE `vpp_device_control_log` MODIFY COLUMN `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT ''主键''',
+    'SELECT ''skip: vpp_device_control_log.id already auto_increment'''
+);
+PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+
+-- vpp_energy_reading_monthly
+SET @sql = IF(
+    (SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'vpp_energy_reading_monthly' AND column_name = 'id' AND EXTRA LIKE '%auto_increment%') = 0,
+    'ALTER TABLE `vpp_energy_reading_monthly` MODIFY COLUMN `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT ''主键''',
+    'SELECT ''skip: vpp_energy_reading_monthly.id already auto_increment'''
+);
+PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+
+-- vpp_energy_summary_daily
+SET @sql = IF(
+    (SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'vpp_energy_summary_daily' AND column_name = 'id' AND EXTRA LIKE '%auto_increment%') = 0,
+    'ALTER TABLE `vpp_energy_summary_daily` MODIFY COLUMN `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT ''主键''',
+    'SELECT ''skip: vpp_energy_summary_daily.id already auto_increment'''
+);
+PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+
+-- vpp_settlement_bill
+SET @sql = IF(
+    (SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'vpp_settlement_bill' AND column_name = 'id' AND EXTRA LIKE '%auto_increment%') = 0,
+    'ALTER TABLE `vpp_settlement_bill` MODIFY COLUMN `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT ''主键''',
+    'SELECT ''skip: vpp_settlement_bill.id already auto_increment'''
+);
+PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+
+-- vpp_settlement_bill_detail
+SET @sql = IF(
+    (SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'vpp_settlement_bill_detail' AND column_name = 'id' AND EXTRA LIKE '%auto_increment%') = 0,
+    'ALTER TABLE `vpp_settlement_bill_detail` MODIFY COLUMN `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT ''主键''',
+    'SELECT ''skip: vpp_settlement_bill_detail.id already auto_increment'''
+);
+PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+
+-- vpp_payment_record
+SET @sql = IF(
+    (SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'vpp_payment_record' AND column_name = 'id' AND EXTRA LIKE '%auto_increment%') = 0,
+    'ALTER TABLE `vpp_payment_record` MODIFY COLUMN `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT ''主键''',
+    'SELECT ''skip: vpp_payment_record.id already auto_increment'''
+);
+PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+
+-- vpp_report_task
+SET @sql = IF(
+    (SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'vpp_report_task' AND column_name = 'id' AND EXTRA LIKE '%auto_increment%') = 0,
+    'ALTER TABLE `vpp_report_task` MODIFY COLUMN `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT ''主键''',
+    'SELECT ''skip: vpp_report_task.id already auto_increment'''
+);
+PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+
+-- vpp_report_record
+SET @sql = IF(
+    (SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'vpp_report_record' AND column_name = 'id' AND EXTRA LIKE '%auto_increment%') = 0,
+    'ALTER TABLE `vpp_report_record` MODIFY COLUMN `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT ''主键''',
+    'SELECT ''skip: vpp_report_record.id already auto_increment'''
+);
+PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+
+-- vpp_report_data
+SET @sql = IF(
+    (SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'vpp_report_data' AND column_name = 'id' AND EXTRA LIKE '%auto_increment%') = 0,
+    'ALTER TABLE `vpp_report_data` MODIFY COLUMN `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT ''主键''',
+    'SELECT ''skip: vpp_report_data.id already auto_increment'''
+);
+PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+
+-- vpp_report_audit_log
+SET @sql = IF(
+    (SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'vpp_report_audit_log' AND column_name = 'id' AND EXTRA LIKE '%auto_increment%') = 0,
+    'ALTER TABLE `vpp_report_audit_log` MODIFY COLUMN `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT ''主键''',
+    'SELECT ''skip: vpp_report_audit_log.id already auto_increment'''
+);
+PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+
+-- vpp_dr_event
+SET @sql = IF(
+    (SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'vpp_dr_event' AND column_name = 'id' AND EXTRA LIKE '%auto_increment%') = 0,
+    'ALTER TABLE `vpp_dr_event` MODIFY COLUMN `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT ''主键''',
+    'SELECT ''skip: vpp_dr_event.id already auto_increment'''
+);
+PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+
+-- vpp_dr_participation
+SET @sql = IF(
+    (SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'vpp_dr_participation' AND column_name = 'id' AND EXTRA LIKE '%auto_increment%') = 0,
+    'ALTER TABLE `vpp_dr_participation` MODIFY COLUMN `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT ''主键''',
+    'SELECT ''skip: vpp_dr_participation.id already auto_increment'''
+);
+PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+
+-- vpp_dr_strategy
+SET @sql = IF(
+    (SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'vpp_dr_strategy' AND column_name = 'id' AND EXTRA LIKE '%auto_increment%') = 0,
+    'ALTER TABLE `vpp_dr_strategy` MODIFY COLUMN `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT ''主键''',
+    'SELECT ''skip: vpp_dr_strategy.id already auto_increment'''
+);
+PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+
+-- vpp_dr_strategy_resource
+SET @sql = IF(
+    (SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'vpp_dr_strategy_resource' AND column_name = 'id' AND EXTRA LIKE '%auto_increment%') = 0,
+    'ALTER TABLE `vpp_dr_strategy_resource` MODIFY COLUMN `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT ''主键''',
+    'SELECT ''skip: vpp_dr_strategy_resource.id already auto_increment'''
+);
+PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+
+-- vpp_dr_execution
+SET @sql = IF(
+    (SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'vpp_dr_execution' AND column_name = 'id' AND EXTRA LIKE '%auto_increment%') = 0,
+    'ALTER TABLE `vpp_dr_execution` MODIFY COLUMN `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT ''主键''',
+    'SELECT ''skip: vpp_dr_execution.id already auto_increment'''
+);
+PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+
+-- vpp_dr_evaluation
+SET @sql = IF(
+    (SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'vpp_dr_evaluation' AND column_name = 'id' AND EXTRA LIKE '%auto_increment%') = 0,
+    'ALTER TABLE `vpp_dr_evaluation` MODIFY COLUMN `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT ''主键''',
+    'SELECT ''skip: vpp_dr_evaluation.id already auto_increment'''
+);
+PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+
+-- vpp_registration
+SET @sql = IF(
+    (SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'vpp_registration' AND column_name = 'id' AND EXTRA LIKE '%auto_increment%') = 0,
+    'ALTER TABLE `vpp_registration` MODIFY COLUMN `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT ''主键''',
+    'SELECT ''skip: vpp_registration.id already auto_increment'''
+);
+PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+
+-- vpp_report_log
+SET @sql = IF(
+    (SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'vpp_report_log' AND column_name = 'id' AND EXTRA LIKE '%auto_increment%') = 0,
+    'ALTER TABLE `vpp_report_log` MODIFY COLUMN `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT ''主键''',
+    'SELECT ''skip: vpp_report_log.id already auto_increment'''
+);
+PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+
+-- vpp_file_archive
+SET @sql = IF(
+    (SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'vpp_file_archive' AND column_name = 'id' AND EXTRA LIKE '%auto_increment%') = 0,
+    'ALTER TABLE `vpp_file_archive` MODIFY COLUMN `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT ''主键''',
+    'SELECT ''skip: vpp_file_archive.id already auto_increment'''
+);
+PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+
+-- 若需将自增计数与数据 ID 均重置为从 1 开始,请执行 vpp_id_reset_from_one_migration.sql

+ 362 - 0
service-vpp/service-vpp-biz/src/main/resources/sql/vpp_id_reset_from_one_migration.sql

@@ -0,0 +1,362 @@
+-- VPP 主键 ID 重置为从 1 开始
+-- 执行前请备份数据库!
+--
+-- 提供两种方案(二选一执行,不要同时执行):
+--   方案一:清空全部 vpp_* 数据,TRUNCATE 后自增从 1 开始(开发/联调推荐)
+--   方案二:保留现有数据,按依赖关系重编号为 1..n(需 MySQL 8.0+,支持 ROW_NUMBER)
+
+-- =============================================================================
+-- 方案一:清空数据并重置自增(会删除所有 vpp_* 业务数据)
+-- 仅 TRUNCATE 当前库中已存在的表,可重复执行
+-- =============================================================================
+
+SET FOREIGN_KEY_CHECKS = 0;
+
+-- vpp_payment_record
+SET @sql = IF((SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = 'vpp_payment_record') > 0, 'TRUNCATE TABLE `vpp_payment_record`', 'SELECT 1');
+PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+-- vpp_settlement_bill_detail
+SET @sql = IF((SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = 'vpp_settlement_bill_detail') > 0, 'TRUNCATE TABLE `vpp_settlement_bill_detail`', 'SELECT 1');
+PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+-- vpp_device_control_log
+SET @sql = IF((SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = 'vpp_device_control_log') > 0, 'TRUNCATE TABLE `vpp_device_control_log`', 'SELECT 1');
+PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+-- vpp_contract_audit_log
+SET @sql = IF((SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = 'vpp_contract_audit_log') > 0, 'TRUNCATE TABLE `vpp_contract_audit_log`', 'SELECT 1');
+PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+-- vpp_customer_contact
+SET @sql = IF((SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = 'vpp_customer_contact') > 0, 'TRUNCATE TABLE `vpp_customer_contact`', 'SELECT 1');
+PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+-- vpp_resource_point_config
+SET @sql = IF((SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = 'vpp_resource_point_config') > 0, 'TRUNCATE TABLE `vpp_resource_point_config`', 'SELECT 1');
+PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+-- vpp_site_config
+SET @sql = IF((SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = 'vpp_site_config') > 0, 'TRUNCATE TABLE `vpp_site_config`', 'SELECT 1');
+PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+-- vpp_dr_participation
+SET @sql = IF((SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = 'vpp_dr_participation') > 0, 'TRUNCATE TABLE `vpp_dr_participation`', 'SELECT 1');
+PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+-- vpp_dr_strategy_resource
+SET @sql = IF((SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = 'vpp_dr_strategy_resource') > 0, 'TRUNCATE TABLE `vpp_dr_strategy_resource`', 'SELECT 1');
+PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+-- vpp_dr_execution
+SET @sql = IF((SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = 'vpp_dr_execution') > 0, 'TRUNCATE TABLE `vpp_dr_execution`', 'SELECT 1');
+PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+-- vpp_dr_evaluation
+SET @sql = IF((SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = 'vpp_dr_evaluation') > 0, 'TRUNCATE TABLE `vpp_dr_evaluation`', 'SELECT 1');
+PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+-- vpp_report_audit_log
+SET @sql = IF((SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = 'vpp_report_audit_log') > 0, 'TRUNCATE TABLE `vpp_report_audit_log`', 'SELECT 1');
+PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+-- vpp_report_data
+SET @sql = IF((SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = 'vpp_report_data') > 0, 'TRUNCATE TABLE `vpp_report_data`', 'SELECT 1');
+PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+-- vpp_energy_reading_monthly
+SET @sql = IF((SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = 'vpp_energy_reading_monthly') > 0, 'TRUNCATE TABLE `vpp_energy_reading_monthly`', 'SELECT 1');
+PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+-- vpp_energy_summary_daily
+SET @sql = IF((SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = 'vpp_energy_summary_daily') > 0, 'TRUNCATE TABLE `vpp_energy_summary_daily`', 'SELECT 1');
+PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+-- vpp_file_archive
+SET @sql = IF((SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = 'vpp_file_archive') > 0, 'TRUNCATE TABLE `vpp_file_archive`', 'SELECT 1');
+PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+-- vpp_device
+SET @sql = IF((SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = 'vpp_device') > 0, 'TRUNCATE TABLE `vpp_device`', 'SELECT 1');
+PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+-- vpp_resource_point
+SET @sql = IF((SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = 'vpp_resource_point') > 0, 'TRUNCATE TABLE `vpp_resource_point`', 'SELECT 1');
+PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+-- vpp_site
+SET @sql = IF((SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = 'vpp_site') > 0, 'TRUNCATE TABLE `vpp_site`', 'SELECT 1');
+PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+-- vpp_contract
+SET @sql = IF((SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = 'vpp_contract') > 0, 'TRUNCATE TABLE `vpp_contract`', 'SELECT 1');
+PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+-- vpp_settlement_bill
+SET @sql = IF((SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = 'vpp_settlement_bill') > 0, 'TRUNCATE TABLE `vpp_settlement_bill`', 'SELECT 1');
+PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+-- vpp_report_record
+SET @sql = IF((SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = 'vpp_report_record') > 0, 'TRUNCATE TABLE `vpp_report_record`', 'SELECT 1');
+PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+-- vpp_customer_access
+SET @sql = IF((SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = 'vpp_customer_access') > 0, 'TRUNCATE TABLE `vpp_customer_access`', 'SELECT 1');
+PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+-- vpp_dr_invitation
+SET @sql = IF((SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = 'vpp_dr_invitation') > 0, 'TRUNCATE TABLE `vpp_dr_invitation`', 'SELECT 1');
+PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+-- vpp_dr_invitation
+SET @sql = IF((SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = 'vpp_dr_invitation') > 0, 'TRUNCATE TABLE `vpp_dr_invitation`', 'SELECT 1');
+PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+-- vpp_dr_event
+SET @sql = IF((SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = 'vpp_dr_event') > 0, 'TRUNCATE TABLE `vpp_dr_event`', 'SELECT 1');
+PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+-- vpp_dr_strategy
+SET @sql = IF((SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = 'vpp_dr_strategy') > 0, 'TRUNCATE TABLE `vpp_dr_strategy`', 'SELECT 1');
+PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+-- vpp_contract_template
+SET @sql = IF((SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = 'vpp_contract_template') > 0, 'TRUNCATE TABLE `vpp_contract_template`', 'SELECT 1');
+PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+-- vpp_report_task
+SET @sql = IF((SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = 'vpp_report_task') > 0, 'TRUNCATE TABLE `vpp_report_task`', 'SELECT 1');
+PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+-- vpp_registration
+SET @sql = IF((SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = 'vpp_registration') > 0, 'TRUNCATE TABLE `vpp_registration`', 'SELECT 1');
+PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+-- vpp_report_log
+SET @sql = IF((SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = 'vpp_report_log') > 0, 'TRUNCATE TABLE `vpp_report_log`', 'SELECT 1');
+PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+-- vpp_customer
+SET @sql = IF((SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = 'vpp_customer') > 0, 'TRUNCATE TABLE `vpp_customer`', 'SELECT 1');
+PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
+
+SET FOREIGN_KEY_CHECKS = 1;
+
+-- TRUNCATE 后 InnoDB 自增值已自动重置为 1,无需再 ALTER AUTO_INCREMENT
+
+-- =============================================================================
+-- 方案二:保留数据,重编号为 1..n(若需使用,请注释掉上方方案一后执行本段)
+-- 要求:MySQL 8.0+;assignee_id 等指向 sys_user 的字段不在此脚本范围内
+-- =============================================================================
+
+/*
+SET FOREIGN_KEY_CHECKS = 0;
+SET UNIQUE_CHECKS = 0;
+
+-- 1. 生成 ID 映射(old_id -> new_id)
+DROP TEMPORARY TABLE IF EXISTS tmp_map_vpp_contract_template;
+CREATE TEMPORARY TABLE tmp_map_vpp_contract_template AS
+SELECT `id` AS old_id, ROW_NUMBER() OVER (ORDER BY `id`) AS new_id FROM `vpp_contract_template`;
+
+DROP TEMPORARY TABLE IF EXISTS tmp_map_vpp_customer;
+CREATE TEMPORARY TABLE tmp_map_vpp_customer AS
+SELECT `id` AS old_id, ROW_NUMBER() OVER (ORDER BY `id`) AS new_id FROM `vpp_customer`;
+
+DROP TEMPORARY TABLE IF EXISTS tmp_map_vpp_dr_event;
+CREATE TEMPORARY TABLE tmp_map_vpp_dr_event AS
+SELECT `id` AS old_id, ROW_NUMBER() OVER (ORDER BY `id`) AS new_id FROM `vpp_dr_event`;
+
+DROP TEMPORARY TABLE IF EXISTS tmp_map_vpp_dr_strategy;
+CREATE TEMPORARY TABLE tmp_map_vpp_dr_strategy AS
+SELECT `id` AS old_id, ROW_NUMBER() OVER (ORDER BY `id`) AS new_id FROM `vpp_dr_strategy`;
+
+DROP TEMPORARY TABLE IF EXISTS tmp_map_vpp_registration;
+CREATE TEMPORARY TABLE tmp_map_vpp_registration AS
+SELECT `id` AS old_id, ROW_NUMBER() OVER (ORDER BY `id`) AS new_id FROM `vpp_registration`;
+
+DROP TEMPORARY TABLE IF EXISTS tmp_map_vpp_report_task;
+CREATE TEMPORARY TABLE tmp_map_vpp_report_task AS
+SELECT `id` AS old_id, ROW_NUMBER() OVER (ORDER BY `id`) AS new_id FROM `vpp_report_task`;
+
+DROP TEMPORARY TABLE IF EXISTS tmp_map_vpp_report_log;
+CREATE TEMPORARY TABLE tmp_map_vpp_report_log AS
+SELECT `id` AS old_id, ROW_NUMBER() OVER (ORDER BY `id`) AS new_id FROM `vpp_report_log`;
+
+DROP TEMPORARY TABLE IF EXISTS tmp_map_vpp_customer_access;
+CREATE TEMPORARY TABLE tmp_map_vpp_customer_access AS
+SELECT `id` AS old_id, ROW_NUMBER() OVER (ORDER BY `id`) AS new_id FROM `vpp_customer_access`;
+
+DROP TEMPORARY TABLE IF EXISTS tmp_map_vpp_customer_contact;
+CREATE TEMPORARY TABLE tmp_map_vpp_customer_contact AS
+SELECT `id` AS old_id, ROW_NUMBER() OVER (ORDER BY `id`) AS new_id FROM `vpp_customer_contact`;
+
+DROP TEMPORARY TABLE IF EXISTS tmp_map_vpp_contract;
+CREATE TEMPORARY TABLE tmp_map_vpp_contract AS
+SELECT `id` AS old_id, ROW_NUMBER() OVER (ORDER BY `id`) AS new_id FROM `vpp_contract`;
+
+DROP TEMPORARY TABLE IF EXISTS tmp_map_vpp_resource_point;
+CREATE TEMPORARY TABLE tmp_map_vpp_resource_point AS
+SELECT `id` AS old_id, ROW_NUMBER() OVER (ORDER BY `id`) AS new_id FROM `vpp_resource_point`;
+
+DROP TEMPORARY TABLE IF EXISTS tmp_map_vpp_report_record;
+CREATE TEMPORARY TABLE tmp_map_vpp_report_record AS
+SELECT `id` AS old_id, ROW_NUMBER() OVER (ORDER BY `id`) AS new_id FROM `vpp_report_record`;
+
+DROP TEMPORARY TABLE IF EXISTS tmp_map_vpp_contract_audit_log;
+CREATE TEMPORARY TABLE tmp_map_vpp_contract_audit_log AS
+SELECT `id` AS old_id, ROW_NUMBER() OVER (ORDER BY `id`) AS new_id FROM `vpp_contract_audit_log`;
+
+DROP TEMPORARY TABLE IF EXISTS tmp_map_vpp_resource_point_config;
+CREATE TEMPORARY TABLE tmp_map_vpp_resource_point_config AS
+SELECT `id` AS old_id, ROW_NUMBER() OVER (ORDER BY `id`) AS new_id FROM `vpp_resource_point_config`;
+
+DROP TEMPORARY TABLE IF EXISTS tmp_map_vpp_device;
+CREATE TEMPORARY TABLE tmp_map_vpp_device AS
+SELECT `id` AS old_id, ROW_NUMBER() OVER (ORDER BY `id`) AS new_id FROM `vpp_device`;
+
+DROP TEMPORARY TABLE IF EXISTS tmp_map_vpp_energy_reading_monthly;
+CREATE TEMPORARY TABLE tmp_map_vpp_energy_reading_monthly AS
+SELECT `id` AS old_id, ROW_NUMBER() OVER (ORDER BY `id`) AS new_id FROM `vpp_energy_reading_monthly`;
+
+DROP TEMPORARY TABLE IF EXISTS tmp_map_vpp_energy_summary_daily;
+CREATE TEMPORARY TABLE tmp_map_vpp_energy_summary_daily AS
+SELECT `id` AS old_id, ROW_NUMBER() OVER (ORDER BY `id`) AS new_id FROM `vpp_energy_summary_daily`;
+
+DROP TEMPORARY TABLE IF EXISTS tmp_map_vpp_settlement_bill;
+CREATE TEMPORARY TABLE tmp_map_vpp_settlement_bill AS
+SELECT `id` AS old_id, ROW_NUMBER() OVER (ORDER BY `id`) AS new_id FROM `vpp_settlement_bill`;
+
+DROP TEMPORARY TABLE IF EXISTS tmp_map_vpp_dr_participation;
+CREATE TEMPORARY TABLE tmp_map_vpp_dr_participation AS
+SELECT `id` AS old_id, ROW_NUMBER() OVER (ORDER BY `id`) AS new_id FROM `vpp_dr_participation`;
+
+DROP TEMPORARY TABLE IF EXISTS tmp_map_vpp_dr_strategy_resource;
+CREATE TEMPORARY TABLE tmp_map_vpp_dr_strategy_resource AS
+SELECT `id` AS old_id, ROW_NUMBER() OVER (ORDER BY `id`) AS new_id FROM `vpp_dr_strategy_resource`;
+
+DROP TEMPORARY TABLE IF EXISTS tmp_map_vpp_report_data;
+CREATE TEMPORARY TABLE tmp_map_vpp_report_data AS
+SELECT `id` AS old_id, ROW_NUMBER() OVER (ORDER BY `id`) AS new_id FROM `vpp_report_data`;
+
+DROP TEMPORARY TABLE IF EXISTS tmp_map_vpp_report_audit_log;
+CREATE TEMPORARY TABLE tmp_map_vpp_report_audit_log AS
+SELECT `id` AS old_id, ROW_NUMBER() OVER (ORDER BY `id`) AS new_id FROM `vpp_report_audit_log`;
+
+DROP TEMPORARY TABLE IF EXISTS tmp_map_vpp_device_control_log;
+CREATE TEMPORARY TABLE tmp_map_vpp_device_control_log AS
+SELECT `id` AS old_id, ROW_NUMBER() OVER (ORDER BY `id`) AS new_id FROM `vpp_device_control_log`;
+
+DROP TEMPORARY TABLE IF EXISTS tmp_map_vpp_settlement_bill_detail;
+CREATE TEMPORARY TABLE tmp_map_vpp_settlement_bill_detail AS
+SELECT `id` AS old_id, ROW_NUMBER() OVER (ORDER BY `id`) AS new_id FROM `vpp_settlement_bill_detail`;
+
+DROP TEMPORARY TABLE IF EXISTS tmp_map_vpp_payment_record;
+CREATE TEMPORARY TABLE tmp_map_vpp_payment_record AS
+SELECT `id` AS old_id, ROW_NUMBER() OVER (ORDER BY `id`) AS new_id FROM `vpp_payment_record`;
+
+DROP TEMPORARY TABLE IF EXISTS tmp_map_vpp_dr_execution;
+CREATE TEMPORARY TABLE tmp_map_vpp_dr_execution AS
+SELECT `id` AS old_id, ROW_NUMBER() OVER (ORDER BY `id`) AS new_id FROM `vpp_dr_execution`;
+
+DROP TEMPORARY TABLE IF EXISTS tmp_map_vpp_dr_evaluation;
+CREATE TEMPORARY TABLE tmp_map_vpp_dr_evaluation AS
+SELECT `id` AS old_id, ROW_NUMBER() OVER (ORDER BY `id`) AS new_id FROM `vpp_dr_evaluation`;
+
+DROP TEMPORARY TABLE IF EXISTS tmp_map_vpp_file_archive;
+CREATE TEMPORARY TABLE tmp_map_vpp_file_archive AS
+SELECT `id` AS old_id, ROW_NUMBER() OVER (ORDER BY `id`) AS new_id FROM `vpp_file_archive`;
+
+-- 2. 更新外键引用
+UPDATE `vpp_customer_access` t JOIN tmp_map_vpp_customer m ON t.`customer_id` = m.old_id SET t.`customer_id` = m.new_id;
+UPDATE `vpp_customer_contact` t JOIN tmp_map_vpp_customer m ON t.`customer_id` = m.old_id SET t.`customer_id` = m.new_id;
+UPDATE `vpp_contract` t JOIN tmp_map_vpp_customer m ON t.`customer_id` = m.old_id SET t.`customer_id` = m.new_id;
+UPDATE `vpp_contract` t JOIN tmp_map_vpp_contract_template m ON t.`template_id` = m.old_id SET t.`template_id` = m.new_id;
+UPDATE `vpp_resource_point` t JOIN tmp_map_vpp_customer m ON t.`customer_id` = m.old_id SET t.`customer_id` = m.new_id;
+UPDATE `vpp_energy_reading_monthly` t JOIN tmp_map_vpp_customer m ON t.`customer_id` = m.old_id SET t.`customer_id` = m.new_id;
+UPDATE `vpp_energy_reading_monthly` t JOIN tmp_map_vpp_resource_point m ON t.`resource_id` = m.old_id SET t.`resource_id` = m.new_id;
+UPDATE `vpp_energy_summary_daily` t JOIN tmp_map_vpp_resource_point m ON t.`resource_id` = m.old_id SET t.`resource_id` = m.new_id;
+UPDATE `vpp_settlement_bill` t JOIN tmp_map_vpp_customer m ON t.`customer_id` = m.old_id SET t.`customer_id` = m.new_id;
+UPDATE `vpp_contract_audit_log` t JOIN tmp_map_vpp_contract m ON t.`contract_id` = m.old_id SET t.`contract_id` = m.new_id;
+UPDATE `vpp_resource_point_config` t JOIN tmp_map_vpp_resource_point m ON t.`resource_id` = m.old_id SET t.`resource_id` = m.new_id;
+UPDATE `vpp_device` t JOIN tmp_map_vpp_resource_point m ON t.`resource_id` = m.old_id SET t.`resource_id` = m.new_id;
+UPDATE `vpp_device_control_log` t JOIN tmp_map_vpp_device m ON t.`device_id` = m.old_id SET t.`device_id` = m.new_id;
+UPDATE `vpp_settlement_bill_detail` t JOIN tmp_map_vpp_settlement_bill m ON t.`bill_id` = m.old_id SET t.`bill_id` = m.new_id;
+UPDATE `vpp_payment_record` t JOIN tmp_map_vpp_settlement_bill m ON t.`bill_id` = m.old_id SET t.`bill_id` = m.new_id;
+UPDATE `vpp_report_record` t JOIN tmp_map_vpp_report_task m ON t.`task_id` = m.old_id SET t.`task_id` = m.new_id;
+UPDATE `vpp_report_data` t JOIN tmp_map_vpp_report_record m ON t.`record_id` = m.old_id SET t.`record_id` = m.new_id;
+UPDATE `vpp_report_audit_log` t JOIN tmp_map_vpp_report_record m ON t.`record_id` = m.old_id SET t.`record_id` = m.new_id;
+UPDATE `vpp_dr_participation` t JOIN tmp_map_vpp_dr_event m ON t.`event_id` = m.old_id SET t.`event_id` = m.new_id;
+UPDATE `vpp_dr_participation` t JOIN tmp_map_vpp_customer m ON t.`customer_id` = m.old_id SET t.`customer_id` = m.new_id;
+UPDATE `vpp_dr_participation` t JOIN tmp_map_vpp_resource_point m ON t.`resource_id` = m.old_id SET t.`resource_id` = m.new_id;
+UPDATE `vpp_dr_strategy_resource` t JOIN tmp_map_vpp_dr_strategy m ON t.`strategy_id` = m.old_id SET t.`strategy_id` = m.new_id;
+UPDATE `vpp_dr_strategy_resource` t JOIN tmp_map_vpp_resource_point m ON t.`resource_id` = m.old_id SET t.`resource_id` = m.new_id;
+UPDATE `vpp_dr_execution` t JOIN tmp_map_vpp_dr_event m ON t.`event_id` = m.old_id SET t.`event_id` = m.new_id;
+UPDATE `vpp_dr_execution` t JOIN tmp_map_vpp_resource_point m ON t.`resource_id` = m.old_id SET t.`resource_id` = m.new_id;
+UPDATE `vpp_dr_evaluation` t JOIN tmp_map_vpp_dr_event m ON t.`event_id` = m.old_id SET t.`event_id` = m.new_id;
+
+-- 电子档案 biz_id(按业务类型映射)
+UPDATE `vpp_file_archive` t JOIN tmp_map_vpp_contract m ON t.`biz_type` = 'CONTRACT' AND t.`biz_id` = m.old_id SET t.`biz_id` = m.new_id;
+UPDATE `vpp_file_archive` t JOIN tmp_map_vpp_customer m ON t.`biz_type` = 'CUSTOMER' AND t.`biz_id` = m.old_id SET t.`biz_id` = m.new_id;
+UPDATE `vpp_file_archive` t JOIN tmp_map_vpp_resource_point m ON t.`biz_type` = 'RESOURCE' AND t.`biz_id` = m.old_id SET t.`biz_id` = m.new_id;
+
+-- 3. 重编号主键(先置负避免冲突,再转正)
+UPDATE `vpp_contract_template` t JOIN tmp_map_vpp_contract_template m ON t.`id` = m.old_id SET t.`id` = -m.new_id;
+UPDATE `vpp_customer` t JOIN tmp_map_vpp_customer m ON t.`id` = m.old_id SET t.`id` = -m.new_id;
+UPDATE `vpp_dr_event` t JOIN tmp_map_vpp_dr_event m ON t.`id` = m.old_id SET t.`id` = -m.new_id;
+UPDATE `vpp_dr_strategy` t JOIN tmp_map_vpp_dr_strategy m ON t.`id` = m.old_id SET t.`id` = -m.new_id;
+UPDATE `vpp_registration` t JOIN tmp_map_vpp_registration m ON t.`id` = m.old_id SET t.`id` = -m.new_id;
+UPDATE `vpp_report_task` t JOIN tmp_map_vpp_report_task m ON t.`id` = m.old_id SET t.`id` = -m.new_id;
+UPDATE `vpp_report_log` t JOIN tmp_map_vpp_report_log m ON t.`id` = m.old_id SET t.`id` = -m.new_id;
+UPDATE `vpp_customer_access` t JOIN tmp_map_vpp_customer_access m ON t.`id` = m.old_id SET t.`id` = -m.new_id;
+UPDATE `vpp_customer_contact` t JOIN tmp_map_vpp_customer_contact m ON t.`id` = m.old_id SET t.`id` = -m.new_id;
+UPDATE `vpp_contract` t JOIN tmp_map_vpp_contract m ON t.`id` = m.old_id SET t.`id` = -m.new_id;
+UPDATE `vpp_resource_point` t JOIN tmp_map_vpp_resource_point m ON t.`id` = m.old_id SET t.`id` = -m.new_id;
+UPDATE `vpp_report_record` t JOIN tmp_map_vpp_report_record m ON t.`id` = m.old_id SET t.`id` = -m.new_id;
+UPDATE `vpp_contract_audit_log` t JOIN tmp_map_vpp_contract_audit_log m ON t.`id` = m.old_id SET t.`id` = -m.new_id;
+UPDATE `vpp_resource_point_config` t JOIN tmp_map_vpp_resource_point_config m ON t.`id` = m.old_id SET t.`id` = -m.new_id;
+UPDATE `vpp_device` t JOIN tmp_map_vpp_device m ON t.`id` = m.old_id SET t.`id` = -m.new_id;
+UPDATE `vpp_energy_reading_monthly` t JOIN tmp_map_vpp_energy_reading_monthly m ON t.`id` = m.old_id SET t.`id` = -m.new_id;
+UPDATE `vpp_energy_summary_daily` t JOIN tmp_map_vpp_energy_summary_daily m ON t.`id` = m.old_id SET t.`id` = -m.new_id;
+UPDATE `vpp_settlement_bill` t JOIN tmp_map_vpp_settlement_bill m ON t.`id` = m.old_id SET t.`id` = -m.new_id;
+UPDATE `vpp_dr_participation` t JOIN tmp_map_vpp_dr_participation m ON t.`id` = m.old_id SET t.`id` = -m.new_id;
+UPDATE `vpp_dr_strategy_resource` t JOIN tmp_map_vpp_dr_strategy_resource m ON t.`id` = m.old_id SET t.`id` = -m.new_id;
+UPDATE `vpp_report_data` t JOIN tmp_map_vpp_report_data m ON t.`id` = m.old_id SET t.`id` = -m.new_id;
+UPDATE `vpp_report_audit_log` t JOIN tmp_map_vpp_report_audit_log m ON t.`id` = m.old_id SET t.`id` = -m.new_id;
+UPDATE `vpp_device_control_log` t JOIN tmp_map_vpp_device_control_log m ON t.`id` = m.old_id SET t.`id` = -m.new_id;
+UPDATE `vpp_settlement_bill_detail` t JOIN tmp_map_vpp_settlement_bill_detail m ON t.`id` = m.old_id SET t.`id` = -m.new_id;
+UPDATE `vpp_payment_record` t JOIN tmp_map_vpp_payment_record m ON t.`id` = m.old_id SET t.`id` = -m.new_id;
+UPDATE `vpp_dr_execution` t JOIN tmp_map_vpp_dr_execution m ON t.`id` = m.old_id SET t.`id` = -m.new_id;
+UPDATE `vpp_dr_evaluation` t JOIN tmp_map_vpp_dr_evaluation m ON t.`id` = m.old_id SET t.`id` = -m.new_id;
+UPDATE `vpp_file_archive` t JOIN tmp_map_vpp_file_archive m ON t.`id` = m.old_id SET t.`id` = -m.new_id;
+
+UPDATE `vpp_contract_template` SET `id` = -`id`;
+UPDATE `vpp_customer` SET `id` = -`id`;
+UPDATE `vpp_dr_event` SET `id` = -`id`;
+UPDATE `vpp_dr_strategy` SET `id` = -`id`;
+UPDATE `vpp_registration` SET `id` = -`id`;
+UPDATE `vpp_report_task` SET `id` = -`id`;
+UPDATE `vpp_report_log` SET `id` = -`id`;
+UPDATE `vpp_customer_access` SET `id` = -`id`;
+UPDATE `vpp_customer_contact` SET `id` = -`id`;
+UPDATE `vpp_contract` SET `id` = -`id`;
+UPDATE `vpp_resource_point` SET `id` = -`id`;
+UPDATE `vpp_report_record` SET `id` = -`id`;
+UPDATE `vpp_contract_audit_log` SET `id` = -`id`;
+UPDATE `vpp_resource_point_config` SET `id` = -`id`;
+UPDATE `vpp_device` SET `id` = -`id`;
+UPDATE `vpp_energy_reading_monthly` SET `id` = -`id`;
+UPDATE `vpp_energy_summary_daily` SET `id` = -`id`;
+UPDATE `vpp_settlement_bill` SET `id` = -`id`;
+UPDATE `vpp_dr_participation` SET `id` = -`id`;
+UPDATE `vpp_dr_strategy_resource` SET `id` = -`id`;
+UPDATE `vpp_report_data` SET `id` = -`id`;
+UPDATE `vpp_report_audit_log` SET `id` = -`id`;
+UPDATE `vpp_device_control_log` SET `id` = -`id`;
+UPDATE `vpp_settlement_bill_detail` SET `id` = -`id`;
+UPDATE `vpp_payment_record` SET `id` = -`id`;
+UPDATE `vpp_dr_execution` SET `id` = -`id`;
+UPDATE `vpp_dr_evaluation` SET `id` = -`id`;
+UPDATE `vpp_file_archive` SET `id` = -`id`;
+
+-- 4. 重置自增计数(下一条插入从 max(id)+1,空表则为 1)
+ALTER TABLE `vpp_contract_template` AUTO_INCREMENT = 1;
+ALTER TABLE `vpp_customer` AUTO_INCREMENT = 1;
+ALTER TABLE `vpp_dr_event` AUTO_INCREMENT = 1;
+ALTER TABLE `vpp_dr_strategy` AUTO_INCREMENT = 1;
+ALTER TABLE `vpp_registration` AUTO_INCREMENT = 1;
+ALTER TABLE `vpp_report_task` AUTO_INCREMENT = 1;
+ALTER TABLE `vpp_report_log` AUTO_INCREMENT = 1;
+ALTER TABLE `vpp_customer_access` AUTO_INCREMENT = 1;
+ALTER TABLE `vpp_customer_contact` AUTO_INCREMENT = 1;
+ALTER TABLE `vpp_contract` AUTO_INCREMENT = 1;
+ALTER TABLE `vpp_resource_point` AUTO_INCREMENT = 1;
+ALTER TABLE `vpp_report_record` AUTO_INCREMENT = 1;
+ALTER TABLE `vpp_contract_audit_log` AUTO_INCREMENT = 1;
+ALTER TABLE `vpp_resource_point_config` AUTO_INCREMENT = 1;
+ALTER TABLE `vpp_device` AUTO_INCREMENT = 1;
+ALTER TABLE `vpp_energy_reading_monthly` AUTO_INCREMENT = 1;
+ALTER TABLE `vpp_energy_summary_daily` AUTO_INCREMENT = 1;
+ALTER TABLE `vpp_settlement_bill` AUTO_INCREMENT = 1;
+ALTER TABLE `vpp_dr_participation` AUTO_INCREMENT = 1;
+ALTER TABLE `vpp_dr_strategy_resource` AUTO_INCREMENT = 1;
+ALTER TABLE `vpp_report_data` AUTO_INCREMENT = 1;
+ALTER TABLE `vpp_report_audit_log` AUTO_INCREMENT = 1;
+ALTER TABLE `vpp_device_control_log` AUTO_INCREMENT = 1;
+ALTER TABLE `vpp_settlement_bill_detail` AUTO_INCREMENT = 1;
+ALTER TABLE `vpp_payment_record` AUTO_INCREMENT = 1;
+ALTER TABLE `vpp_dr_execution` AUTO_INCREMENT = 1;
+ALTER TABLE `vpp_dr_evaluation` AUTO_INCREMENT = 1;
+ALTER TABLE `vpp_file_archive` AUTO_INCREMENT = 1;
+
+SET UNIQUE_CHECKS = 1;
+SET FOREIGN_KEY_CHECKS = 1;
+*/

+ 62 - 28
service-vpp/service-vpp-biz/src/main/resources/sql/vpp_schema.sql

@@ -2,7 +2,7 @@
 -- 来源: 虚拟电厂平台数据库设计文档 V1.0
 
 CREATE TABLE `vpp_customer` (
-    `id` BIGINT NOT NULL COMMENT '主键',
+    `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
     `account_no` VARCHAR(32) NOT NULL COMMENT '电力户号,全局唯一',
     `customer_name` VARCHAR(200) NOT NULL COMMENT '客户名称',
     `customer_type` TINYINT NOT NULL COMMENT '1高压 2低压商用 3居民充电桩 4自有资产',
@@ -33,7 +33,7 @@ CREATE TABLE `vpp_customer` (
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='客户档案';
 
 CREATE TABLE `vpp_customer_access` (
-    `id` BIGINT NOT NULL COMMENT '主键',
+    `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
     `apply_no` VARCHAR(32) NOT NULL COMMENT '申请编号',
     `account_no` VARCHAR(32) NOT NULL COMMENT '电力户号',
     `customer_name` VARCHAR(200) NOT NULL COMMENT '客户名称',
@@ -60,7 +60,7 @@ CREATE TABLE `vpp_customer_access` (
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='准入申请';
 
 CREATE TABLE `vpp_customer_contact` (
-    `id` BIGINT NOT NULL COMMENT '主键',
+    `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
     `customer_id` BIGINT NOT NULL COMMENT '客户ID',
     `contact_name` VARCHAR(100) NOT NULL COMMENT '联系人姓名',
     `contact_phone` VARCHAR(20) NOT NULL COMMENT '联系电话',
@@ -79,7 +79,7 @@ CREATE TABLE `vpp_customer_contact` (
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='客户联系人';
 
 CREATE TABLE `vpp_contract` (
-    `id` BIGINT NOT NULL COMMENT '主键',
+    `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
     `contract_no` VARCHAR(64) NOT NULL COMMENT '合同编号',
     `customer_id` BIGINT NOT NULL COMMENT '客户ID',
     `template_id` BIGINT NULL COMMENT '模板ID',
@@ -108,7 +108,7 @@ CREATE TABLE `vpp_contract` (
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='合同';
 
 CREATE TABLE `vpp_contract_template` (
-    `id` BIGINT NOT NULL COMMENT '主键',
+    `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
     `template_code` VARCHAR(32) NOT NULL COMMENT '模板编码',
     `template_name` VARCHAR(200) NOT NULL COMMENT '模板名称',
     `contract_type` TINYINT NOT NULL COMMENT '合同类型',
@@ -128,7 +128,7 @@ CREATE TABLE `vpp_contract_template` (
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='合同模板';
 
 CREATE TABLE `vpp_contract_audit_log` (
-    `id` BIGINT NOT NULL COMMENT '主键',
+    `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
     `contract_id` BIGINT NOT NULL COMMENT '合同ID',
     `action` TINYINT NOT NULL COMMENT '1提交 2通过 3驳回 4归档',
     `opinion` VARCHAR(500) NULL COMMENT '意见',
@@ -140,7 +140,7 @@ CREATE TABLE `vpp_contract_audit_log` (
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='合同审核流水';
 
 CREATE TABLE `vpp_resource_point` (
-    `id` BIGINT NOT NULL COMMENT '主键',
+    `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
     `resource_code` VARCHAR(64) NOT NULL COMMENT '资源编号',
     `resource_name` VARCHAR(200) NOT NULL COMMENT '资源名称',
     `customer_id` BIGINT NOT NULL COMMENT '所属客户ID',
@@ -174,7 +174,7 @@ CREATE TABLE `vpp_resource_point` (
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='资源点';
 
 CREATE TABLE `vpp_resource_point_config` (
-    `id` BIGINT NOT NULL COMMENT '主键',
+    `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
     `resource_id` BIGINT NOT NULL COMMENT '资源点ID',
     `collect_interval_sec` INT NOT NULL COMMENT '采集频率秒 60/300/900',
     `power_upper_limit` DECIMAL(12,4) NULL COMMENT '功率上限告警',
@@ -195,7 +195,7 @@ CREATE TABLE `vpp_resource_point_config` (
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='资源点运行参数';
 
 CREATE TABLE `vpp_device` (
-    `id` BIGINT NOT NULL COMMENT '主键',
+    `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
     `device_code` VARCHAR(64) NOT NULL COMMENT '设备编号',
     `device_name` VARCHAR(200) NOT NULL COMMENT '设备名称',
     `resource_id` BIGINT NOT NULL COMMENT '所属资源点ID',
@@ -223,7 +223,7 @@ CREATE TABLE `vpp_device` (
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='设备';
 
 CREATE TABLE `vpp_device_control_log` (
-    `id` BIGINT NOT NULL COMMENT '主键',
+    `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
     `device_id` BIGINT NOT NULL COMMENT '设备ID',
     `control_type` VARCHAR(32) NOT NULL COMMENT 'START/STOP/CONFIG/OTA',
     `control_params` JSON NULL COMMENT '控制参数',
@@ -237,7 +237,7 @@ CREATE TABLE `vpp_device_control_log` (
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='设备远程控制日志';
 
 CREATE TABLE `vpp_energy_reading_monthly` (
-    `id` BIGINT NOT NULL COMMENT '主键',
+    `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
     `customer_id` BIGINT NOT NULL COMMENT '客户ID',
     `resource_id` BIGINT NULL COMMENT '资源点ID,可空表示户号级',
     `settle_year` SMALLINT NOT NULL COMMENT '结算年',
@@ -263,7 +263,7 @@ CREATE TABLE `vpp_energy_reading_monthly` (
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='月度电量核算';
 
 CREATE TABLE `vpp_energy_summary_daily` (
-    `id` BIGINT NOT NULL COMMENT '主键',
+    `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
     `summary_date` DATE NOT NULL COMMENT '汇总日期',
     `resource_id` BIGINT NULL COMMENT '资源点ID,NULL表示全站',
     `resource_type` VARCHAR(16) NULL COMMENT '资源类型',
@@ -285,7 +285,7 @@ CREATE TABLE `vpp_energy_summary_daily` (
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='日度能源汇总';
 
 CREATE TABLE `vpp_settlement_bill` (
-    `id` BIGINT NOT NULL COMMENT '主键',
+    `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
     `bill_no` VARCHAR(64) NOT NULL COMMENT '账单编号',
     `customer_id` BIGINT NOT NULL COMMENT '客户ID',
     `settle_year` SMALLINT NOT NULL COMMENT '结算年',
@@ -311,7 +311,7 @@ CREATE TABLE `vpp_settlement_bill` (
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='电费账单';
 
 CREATE TABLE `vpp_settlement_bill_detail` (
-    `id` BIGINT NOT NULL COMMENT '主键',
+    `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
     `bill_id` BIGINT NOT NULL COMMENT '账单ID',
     `time_period` TINYINT NOT NULL COMMENT '1尖 2峰 3平 4谷',
     `energy_kwh` DECIMAL(18,4) NOT NULL COMMENT '时段电量',
@@ -323,7 +323,7 @@ CREATE TABLE `vpp_settlement_bill_detail` (
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='账单分时明细';
 
 CREATE TABLE `vpp_payment_record` (
-    `id` BIGINT NOT NULL COMMENT '主键',
+    `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
     `bill_id` BIGINT NOT NULL COMMENT '账单ID',
     `payment_amount` DECIMAL(18,4) NOT NULL COMMENT '缴费金额',
     `payment_method` TINYINT NOT NULL COMMENT '1线下转账 2电费抵扣 3其他',
@@ -338,7 +338,7 @@ CREATE TABLE `vpp_payment_record` (
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='缴费记录';
 
 CREATE TABLE `vpp_report_task` (
-    `id` BIGINT NOT NULL COMMENT '主键',
+    `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
     `task_no` VARCHAR(64) NOT NULL COMMENT '任务编号',
     `task_name` VARCHAR(200) NOT NULL COMMENT '任务名称',
     `report_org` TINYINT NOT NULL COMMENT '1交易中心 2能监局 3经信委 4国网上海',
@@ -361,7 +361,7 @@ CREATE TABLE `vpp_report_task` (
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='报送任务';
 
 CREATE TABLE `vpp_report_record` (
-    `id` BIGINT NOT NULL COMMENT '主键',
+    `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
     `task_id` BIGINT NOT NULL COMMENT '任务ID',
     `record_no` VARCHAR(64) NOT NULL COMMENT '报送记录编号',
     `report_period` VARCHAR(32) NOT NULL COMMENT '报送周期标识 如2026-05',
@@ -386,7 +386,7 @@ CREATE TABLE `vpp_report_record` (
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='报送记录';
 
 CREATE TABLE `vpp_report_data` (
-    `id` BIGINT NOT NULL COMMENT '主键',
+    `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
     `record_id` BIGINT NOT NULL COMMENT '报送记录ID',
     `form_data` JSON NOT NULL COMMENT '填报表单JSON',
     `validation_errors` JSON NULL COMMENT '校验异常项',
@@ -403,7 +403,7 @@ CREATE TABLE `vpp_report_data` (
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='报送填报数据';
 
 CREATE TABLE `vpp_report_audit_log` (
-    `id` BIGINT NOT NULL COMMENT '主键',
+    `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
     `record_id` BIGINT NOT NULL COMMENT '报送记录ID',
     `audit_level` TINYINT NOT NULL COMMENT '1填报 2复核 3审批',
     `action` TINYINT NOT NULL COMMENT '1提交 2通过 3驳回',
@@ -417,7 +417,7 @@ CREATE TABLE `vpp_report_audit_log` (
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='报送审核流水';
 
 CREATE TABLE `vpp_dr_event` (
-    `id` BIGINT NOT NULL COMMENT '主键',
+    `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
     `event_id` VARCHAR(64) NOT NULL COMMENT '运管平台事件ID',
     `event_name` VARCHAR(200) NULL COMMENT '事件名称',
     `response_type` TINYINT NOT NULL COMMENT '1日前 2日内 3秒级',
@@ -442,7 +442,7 @@ CREATE TABLE `vpp_dr_event` (
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='需求响应事件';
 
 CREATE TABLE `vpp_dr_participation` (
-    `id` BIGINT NOT NULL COMMENT '主键',
+    `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
     `event_id` BIGINT NOT NULL COMMENT '事件ID',
     `customer_id` BIGINT NOT NULL COMMENT '客户ID',
     `resource_id` BIGINT NULL COMMENT '资源点ID',
@@ -462,8 +462,42 @@ CREATE TABLE `vpp_dr_participation` (
     UNIQUE KEY `uk_dr_part` (event_id, customer_id, resource_id)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='事件参与记录';
 
+CREATE TABLE `vpp_dr_invitation` (
+    `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
+    `invitation_no` VARCHAR(32) NOT NULL COMMENT '邀约编号',
+    `dr_event_id` BIGINT NOT NULL COMMENT '需求响应事件ID',
+    `customer_id` BIGINT NOT NULL COMMENT '客户ID',
+    `execute_start_date` DATE NOT NULL COMMENT '执行开始日期',
+    `execute_end_date` DATE NOT NULL COMMENT '执行结束日期',
+    `reply_deadline` DATETIME(3) NOT NULL COMMENT '邀约回复截止日期',
+    `issue_time` DATETIME(3) NOT NULL COMMENT '下发时间',
+    `transaction_type` TINYINT NULL COMMENT '交易类型 1削峰 2填谷',
+    `response_type` TINYINT NOT NULL COMMENT '1日前 2日内 3秒级',
+    `demand_capacity_kw` DECIMAL(12,4) NOT NULL COMMENT '需求容量 kW',
+    `declared_capacity_kw` DECIMAL(12,4) NULL COMMENT '已申报容量 kW',
+    `reply_status` TINYINT NOT NULL COMMENT '0待回复 1参与 2拒绝 3超时',
+    `response_status` TINYINT NOT NULL COMMENT '0待响应 1已申报 2执行中 3已结束 4已取消',
+    `sms_notify_status` TINYINT NOT NULL DEFAULT 0 COMMENT '0未发送 1已发送 2发送失败',
+    `sms_notify_at` DATETIME(3) NULL COMMENT '短信通知时间',
+    `sms_contact_id` BIGINT NULL COMMENT '通知联系人ID',
+    `participation_id` BIGINT NULL COMMENT '关联参与记录ID',
+    `remark` VARCHAR(500) NULL COMMENT '备注',
+    `tenant_id` INT NULL COMMENT '租户ID',
+    `create_time` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
+    `update_time` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',
+    `created_by` VARCHAR(30) NULL COMMENT '创建人',
+    `updated_by` VARCHAR(30) NULL COMMENT '更新人',
+    `delete_flag` INT(1) NOT NULL DEFAULT 0 COMMENT '删除标识 0未删除 1已删除',
+    `deleted_at` DATETIME(3) NULL COMMENT '软删除时间',
+    PRIMARY KEY (`id`),
+    UNIQUE KEY `uk_dr_invitation_no` (invitation_no),
+    UNIQUE KEY `uk_dr_invitation_event_customer` (dr_event_id, customer_id),
+    KEY `idx_dr_invitation_customer` (customer_id, reply_status),
+    KEY `idx_dr_invitation_issue` (issue_time, response_type)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='需求响应企业邀约';
+
 CREATE TABLE `vpp_dr_strategy` (
-    `id` BIGINT NOT NULL COMMENT '主键',
+    `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
     `strategy_code` VARCHAR(64) NOT NULL COMMENT '策略编码',
     `strategy_name` VARCHAR(200) NOT NULL COMMENT '策略名称',
     `response_type` TINYINT NOT NULL COMMENT '适用响应类型',
@@ -484,7 +518,7 @@ CREATE TABLE `vpp_dr_strategy` (
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='响应策略';
 
 CREATE TABLE `vpp_dr_strategy_resource` (
-    `id` BIGINT NOT NULL COMMENT '主键',
+    `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
     `strategy_id` BIGINT NOT NULL COMMENT '策略ID',
     `resource_id` BIGINT NOT NULL COMMENT '资源点ID',
     `priority` TINYINT NOT NULL COMMENT '优先级序号',
@@ -496,7 +530,7 @@ CREATE TABLE `vpp_dr_strategy_resource` (
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='策略-资源关联';
 
 CREATE TABLE `vpp_dr_execution` (
-    `id` BIGINT NOT NULL COMMENT '主键',
+    `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
     `event_id` BIGINT NOT NULL COMMENT '事件ID',
     `resource_id` BIGINT NOT NULL COMMENT '资源点ID',
     `target_kw` DECIMAL(12,4) NOT NULL COMMENT '目标调节量',
@@ -517,7 +551,7 @@ CREATE TABLE `vpp_dr_execution` (
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='响应执行明细';
 
 CREATE TABLE `vpp_dr_evaluation` (
-    `id` BIGINT NOT NULL COMMENT '主键',
+    `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
     `event_id` BIGINT NOT NULL COMMENT '事件ID',
     `actual_capacity_kw` DECIMAL(12,4) NULL COMMENT '实际响应容量',
     `response_duration_min` INT NULL COMMENT '响应时长分钟',
@@ -537,7 +571,7 @@ CREATE TABLE `vpp_dr_evaluation` (
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='响应效果评估';
 
 CREATE TABLE `vpp_registration` (
-    `id` BIGINT NOT NULL COMMENT '主键',
+    `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
     `dn_id` VARCHAR(64) NOT NULL COMMENT '虚拟电厂运营商ID',
     `registration_id` VARCHAR(128) NOT NULL COMMENT '运管平台registrationID',
     `reg_status` TINYINT NOT NULL COMMENT '0未注册 1已注册 2需重新注册',
@@ -555,7 +589,7 @@ CREATE TABLE `vpp_registration` (
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='运管平台注册信息';
 
 CREATE TABLE `vpp_report_log` (
-    `id` BIGINT NOT NULL COMMENT '主键',
+    `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
     `report_type` VARCHAR(64) NOT NULL COMMENT 'MomentData/IntervalData/RegisterReport等',
     `request_id` VARCHAR(64) NULL COMMENT '请求ID',
     `report_status` TINYINT NOT NULL COMMENT '0失败 1成功',
@@ -569,7 +603,7 @@ CREATE TABLE `vpp_report_log` (
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='数据上报日志';
 
 CREATE TABLE vpp_file_archive (
-    id          BIGINT         NOT NULL COMMENT '主键',
+    id          BIGINT         NOT NULL AUTO_INCREMENT COMMENT '主键',
     file_name   VARCHAR(255)   NOT NULL COMMENT '原始文件名',
     file_url    VARCHAR(500)   NOT NULL COMMENT '存储路径',
     file_type   VARCHAR(32)    NOT NULL COMMENT '文件类型',