Commit a1b5ec14 authored by Tong Li's avatar Tong Li

Merge remote-tracking branch 'origin/master'

# Conflicts:
#	src/main/java/com/aps/macroplanner/data/MacroPlannerDataConverter.java
parents aaf66e2d bb3dce7b
package com.aps.config;
import com.aps.macroplanner.scene.MacroSceneDataPermissionHandler;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.DataPermissionInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(
new DataPermissionInterceptor(new MacroSceneDataPermissionHandler()));
return interceptor;
}
}
package com.aps.controller;
import com.aps.common.util.R;
import com.aps.entity.MacroSceneConfig;
import com.aps.macroplanner.scene.MacroSceneCreateRequest;
import com.aps.macroplanner.scene.MacroSceneService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequestMapping("/macroScene")
@Tag(name = "主计划场景管理", description = "主计划场景的创建、查询和删除")
@RequiredArgsConstructor
public class MacroSceneController {
private final MacroSceneService macroSceneService;
@PostMapping
@Operation(summary = "创建主计划场景", description = "从原始数据或已有主计划场景复制创建新场景")
public R<MacroSceneConfig> create(@RequestBody MacroSceneCreateRequest request) {
return R.ok(macroSceneService.createScene(request));
}
@GetMapping
@Operation(summary = "查询主计划场景列表")
public R<List<MacroSceneConfig>> list() {
return R.ok(macroSceneService.listScenes());
}
@GetMapping("/{sceneId}")
@Operation(summary = "查询主计划场景详情")
public R<MacroSceneConfig> get(@PathVariable String sceneId) {
return R.ok(macroSceneService.getScene(sceneId));
}
@DeleteMapping("/{sceneId}")
@Operation(summary = "删除主计划场景", description = "删除场景配置及该场景下复制的数据")
public R<Boolean> delete(@PathVariable String sceneId) {
macroSceneService.deleteScene(sceneId);
return R.ok(true);
}
}
package com.aps.entity; package com.aps.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data; import lombok.Data;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable; import java.io.Serializable;
import java.math.BigDecimal; import java.math.BigDecimal;
...@@ -8,6 +13,7 @@ import lombok.Data; ...@@ -8,6 +13,7 @@ import lombok.Data;
@Data @Data
public class ApsDemandOrder { public class ApsDemandOrder {
@TableId(value = "id", type = IdType.INPUT)
private String id; private String id;
private Long sourceType; private Long sourceType;
private String exp1; private String exp1;
...@@ -61,4 +67,6 @@ private Long lastmodifieruserid; ...@@ -61,4 +67,6 @@ private Long lastmodifieruserid;
private Short isdeleted; private Short isdeleted;
private LocalDateTime deletiontime; private LocalDateTime deletiontime;
private Long deleteruserid; private Long deleteruserid;
} @TableField(value = "MP_SCENE_ID", fill = FieldFill.INSERT)
\ No newline at end of file private String mpSceneId;
}
package com.aps.entity; package com.aps.entity;
import lombok.Data; import lombok.Data;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable; import java.io.Serializable;
...@@ -21,5 +22,6 @@ public class ApsTimeConfig { ...@@ -21,5 +22,6 @@ public class ApsTimeConfig {
/** 周期维度: DAY(天) / WEEK(周) / MONTH(月), 默认 DAY */ /** 周期维度: DAY(天) / WEEK(周) / MONTH(月), 默认 DAY */
private String periodDimension; private String periodDimension;
private String MpSceneId; @TableField(value = "MP_SCENE_ID", fill = FieldFill.INSERT)
} private String mpSceneId;
\ No newline at end of file }
package com.aps.entity; package com.aps.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import lombok.Data; import lombok.Data;
import java.time.LocalDateTime; import java.time.LocalDateTime;
...@@ -8,6 +13,7 @@ import java.time.LocalDateTime; ...@@ -8,6 +13,7 @@ import java.time.LocalDateTime;
@Data @Data
@TableName("MES.EQUIP_SHIFT_CAPACITY") @TableName("MES.EQUIP_SHIFT_CAPACITY")
public class EquipShiftCapacity { public class EquipShiftCapacity {
@TableId(value = "id", type = IdType.INPUT)
private Long id; private Long id;
private Long creatorUserId; private Long creatorUserId;
private LocalDateTime creationTime; private LocalDateTime creationTime;
...@@ -34,4 +40,6 @@ public class EquipShiftCapacity { ...@@ -34,4 +40,6 @@ public class EquipShiftCapacity {
private String holidayTimePeriods; private String holidayTimePeriods;
private String specialTimePeriods; private String specialTimePeriods;
private String validTimePeriods; private String validTimePeriods;
@TableField(value = "MP_SCENE_ID", fill = FieldFill.INSERT)
private String mpSceneId;
} }
package com.aps.entity; package com.aps.entity;
import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableId;
import java.io.Serializable; import java.io.Serializable;
import java.math.BigDecimal; import java.math.BigDecimal;
...@@ -22,7 +24,7 @@ public class Equipinfo implements Serializable { ...@@ -22,7 +24,7 @@ public class Equipinfo implements Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.AUTO) @TableId(value = "id", type = IdType.INPUT)
private Integer id; private Integer id;
private Integer shopId; private Integer shopId;
...@@ -136,4 +138,7 @@ public class Equipinfo implements Serializable { ...@@ -136,4 +138,7 @@ public class Equipinfo implements Serializable {
private BigDecimal maxDurationTime; private BigDecimal maxDurationTime;
private BigDecimal jpExpecationTime; private BigDecimal jpExpecationTime;
@TableField(value = "MP_SCENE_ID", fill = FieldFill.INSERT)
private String mpSceneId;
} }
package com.aps.entity; package com.aps.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data; import lombok.Data;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.time.LocalDateTime; import java.time.LocalDateTime;
@Data @Data
public class ErpPurchaseOrder { public class ErpPurchaseOrder {
@TableId(value = "id", type = IdType.INPUT)
private Long id; private Long id;
private LocalDateTime creationtime; private LocalDateTime creationtime;
private Long creatoruserid; private Long creatoruserid;
...@@ -32,4 +38,6 @@ private Long manufacturerId; ...@@ -32,4 +38,6 @@ private Long manufacturerId;
private String manufacturerCode; private String manufacturerCode;
private String manufacturerName; private String manufacturerName;
private LocalDateTime arrivalDate; private LocalDateTime arrivalDate;
} @TableField(value = "MP_SCENE_ID", fill = FieldFill.INSERT)
\ No newline at end of file private String mpSceneId;
}
package com.aps.entity.Gantt;
import lombok.Data;
/**
* 供给关系项
*/
@Data
public class SupplyRelationItem {
private String taskIdFrom;
private String taskIdTo;
private String fromTime;
private String toTime;
private String fromIdFrom;
private Integer toIdTo;
}
\ No newline at end of file
package com.aps.entity.Gantt;
import lombok.Data;
import java.time.LocalDateTime;
/**
* 供给关系查询请求参数类
*/
@Data
public class SupplyRelationRequest {
private String id;
private String planId;
private String productId;
private Integer quantity;
private String start;
private String end;
private Integer setup;
private Integer teardown;
private Integer equipChange;
private Integer equipCooling;
private String equipName;
private Integer duration;
private Integer equipId;
private Integer shopId;
private Integer status;
private Integer detailId;
private Integer headerId;
private Integer seq;
private String seqName;
private Integer processingTime;
private Integer absolutePreparationTime;
private Boolean locked;
}
\ No newline at end of file
package com.aps.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
@Data
@TableName("MP_SCENE_CONFIG")
@Schema(description = "主计划场景配置")
public class MacroSceneConfig {
@TableId(value = "SCENE_ID", type = IdType.INPUT)
@Schema(description = "场景 ID")
private String sceneId;
@Schema(description = "场景名称")
private String sceneName;
@Schema(description = "场景描述")
private String sceneDesc;
@Schema(description = "来源场景 ID")
private String sourceSceneId;
@Schema(description = "场景状态,例如 COPYING、READY")
private String sceneStatus;
@Schema(description = "创建人")
private String createUser;
@Schema(description = "创建时间")
private LocalDateTime createTime;
@Schema(description = "更新人")
private String updateUser;
@Schema(description = "更新时间")
private LocalDateTime updateTime;
}
package com.aps.entity; package com.aps.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
...@@ -25,6 +29,7 @@ public class MaterialInfo implements Serializable { ...@@ -25,6 +29,7 @@ public class MaterialInfo implements Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.INPUT)
private String id; private String id;
...@@ -402,4 +407,7 @@ public class MaterialInfo implements Serializable { ...@@ -402,4 +407,7 @@ public class MaterialInfo implements Serializable {
* 不可见性(外贸删除的物料) * 不可见性(外贸删除的物料)
*/ */
private Long invisable; private Long invisable;
}
\ No newline at end of file @TableField(value = "MP_SCENE_ID", fill = FieldFill.INSERT)
private String mpSceneId;
}
package com.aps.entity; package com.aps.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data; import lombok.Data;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable; import java.io.Serializable;
import java.math.BigDecimal; import java.math.BigDecimal;
...@@ -26,5 +31,8 @@ private String supplyCode; ...@@ -26,5 +31,8 @@ private String supplyCode;
private BigDecimal price; private BigDecimal price;
private Integer purchaseCycle; private Integer purchaseCycle;
private Integer inspectionCycle; private Integer inspectionCycle;
@TableId(value = "id", type = IdType.INPUT)
private Long id; private Long id;
} @TableField(value = "MP_SCENE_ID", fill = FieldFill.INSERT)
\ No newline at end of file private String mpSceneId;
}
package com.aps.entity; package com.aps.entity;
import lombok.Data; import lombok.Data;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
...@@ -10,6 +12,7 @@ import lombok.Data; ...@@ -10,6 +12,7 @@ import lombok.Data;
@Data @Data
public class PlanResource { public class PlanResource {
@TableId(value = "id", type = IdType.INPUT)
private Integer id; private Integer id;
private String title; private String title;
private String code; private String code;
...@@ -38,4 +41,6 @@ private Long nrofunitsopen; ...@@ -38,4 +41,6 @@ private Long nrofunitsopen;
private Integer isstop; private Integer isstop;
private LocalDate stoptime; private LocalDate stoptime;
private LocalDate stopendtime; private LocalDate stopendtime;
@TableField(value = "MP_SCENE_ID", fill = FieldFill.INSERT)
private String mpSceneId;
} }
package com.aps.entity; package com.aps.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data; import lombok.Data;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.time.LocalDateTime; import java.time.LocalDateTime;
@Data @Data
public class PurchaseReceipt { public class PurchaseReceipt {
@TableId(value = "id", type = IdType.INPUT)
private Long id; private Long id;
private LocalDateTime creationtime; private LocalDateTime creationtime;
private Long creatoruserid; private Long creatoruserid;
...@@ -48,4 +54,6 @@ private String nof; ...@@ -48,4 +54,6 @@ private String nof;
private String scdwbm; private String scdwbm;
private String ylzd4; private String ylzd4;
private String ylzd5; private String ylzd5;
} @TableField(value = "MP_SCENE_ID", fill = FieldFill.INSERT)
\ No newline at end of file private String mpSceneId;
}
package com.aps.entity; package com.aps.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data; import lombok.Data;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable; import java.io.Serializable;
import java.math.BigDecimal; import java.math.BigDecimal;
...@@ -8,6 +13,7 @@ import java.time.LocalDateTime; ...@@ -8,6 +13,7 @@ import java.time.LocalDateTime;
@Data @Data
public class RoutingDetail { public class RoutingDetail {
@TableId(value = "id", type = IdType.INPUT)
private Long id; private Long id;
private LocalDateTime creationTime; private LocalDateTime creationTime;
private BigDecimal creatorUserId; private BigDecimal creatorUserId;
...@@ -61,4 +67,7 @@ public class RoutingDetail { ...@@ -61,4 +67,7 @@ public class RoutingDetail {
private BigDecimal incrementQty; private BigDecimal incrementQty;
} @TableField(value = "MP_SCENE_ID", fill = FieldFill.INSERT)
\ No newline at end of file private String mpSceneId;
}
package com.aps.entity; package com.aps.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data; import lombok.Data;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import java.time.LocalDateTime; import java.time.LocalDateTime;
@Data @Data
public class RoutingDetailConnect { public class RoutingDetailConnect {
@TableId(value = "id", type = IdType.INPUT)
private Long id; private Long id;
private LocalDateTime creationtime; private LocalDateTime creationtime;
private Long creatoruserid; private Long creatoruserid;
...@@ -24,4 +30,6 @@ private String exp3; ...@@ -24,4 +30,6 @@ private String exp3;
private String exp4; private String exp4;
private Long routingHeaderId; private Long routingHeaderId;
private String strId; private String strId;
} @TableField(value = "MP_SCENE_ID", fill = FieldFill.INSERT)
\ No newline at end of file private String mpSceneId;
}
package com.aps.entity; package com.aps.entity;
import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable; import java.io.Serializable;
...@@ -24,7 +26,7 @@ public class RoutingDetailEquip implements Serializable { ...@@ -24,7 +26,7 @@ public class RoutingDetailEquip implements Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.AUTO) @TableId(value = "id", type = IdType.INPUT)
private Integer id; private Integer id;
/** /**
...@@ -138,4 +140,7 @@ public class RoutingDetailEquip implements Serializable { ...@@ -138,4 +140,7 @@ public class RoutingDetailEquip implements Serializable {
* 准备时间 * 准备时间
*/ */
private int setupTime; private int setupTime;
}
\ No newline at end of file @TableField(value = "MP_SCENE_ID", fill = FieldFill.INSERT)
private String mpSceneId;
}
package com.aps.entity; package com.aps.entity;
import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable; import java.io.Serializable;
...@@ -24,7 +26,7 @@ public class RoutingHeader implements Serializable { ...@@ -24,7 +26,7 @@ public class RoutingHeader implements Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.AUTO) @TableId(value = "id", type = IdType.INPUT)
private Integer id; private Integer id;
private LocalDate creationTime; private LocalDate creationTime;
...@@ -144,4 +146,7 @@ public class RoutingHeader implements Serializable { ...@@ -144,4 +146,7 @@ public class RoutingHeader implements Serializable {
private BigDecimal pcost; private BigDecimal pcost;
private Integer invisable; private Integer invisable;
@TableField(value = "MP_SCENE_ID", fill = FieldFill.INSERT)
private String mpSceneId;
} }
package com.aps.entity; package com.aps.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data; import lombok.Data;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import java.io.Serializable; import java.io.Serializable;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.time.LocalDateTime; import java.time.LocalDateTime;
@Data @Data
public class Routingsupporting { public class Routingsupporting {
@TableId(value = "id", type = IdType.INPUT)
private Long id; private Long id;
private LocalDateTime creationtime; private LocalDateTime creationtime;
private Long creatoruserid; private Long creatoruserid;
...@@ -35,4 +41,6 @@ private Long spentMeasureUnit; ...@@ -35,4 +41,6 @@ private Long spentMeasureUnit;
private String spentMeasureUnitName; private String spentMeasureUnitName;
private String strId; private String strId;
private String drawNum; private String drawNum;
} @TableField(value = "MP_SCENE_ID", fill = FieldFill.INSERT)
\ No newline at end of file private String mpSceneId;
}
package com.aps.entity; package com.aps.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data; import lombok.Data;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.time.LocalDateTime; import java.time.LocalDateTime;
@Data @Data
public class SjzPfWhStock { public class SjzPfWhStock {
@TableId(value = "id", type = IdType.INPUT)
private Long id; private Long id;
private LocalDateTime creationtime; private LocalDateTime creationtime;
private Long creatoruserid; private Long creatoruserid;
...@@ -41,4 +47,6 @@ private String jkdwmc; ...@@ -41,4 +47,6 @@ private String jkdwmc;
private String ifsl; private String ifsl;
private Long checkstatus; private Long checkstatus;
private BigDecimal checkquantity; private BigDecimal checkquantity;
} @TableField(value = "MP_SCENE_ID", fill = FieldFill.INSERT)
\ No newline at end of file private String mpSceneId;
}
package com.aps.entity; package com.aps.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.FieldFill;
import lombok.Data; import lombok.Data;
import java.math.BigDecimal; import java.math.BigDecimal;
...@@ -8,6 +12,7 @@ import java.time.LocalDateTime; ...@@ -8,6 +12,7 @@ import java.time.LocalDateTime;
@Data @Data
public class Stock { public class Stock {
@TableId(value = "id", type = IdType.INPUT)
private Long id; private Long id;
private LocalDateTime creationtime; private LocalDateTime creationtime;
private Long creatoruserid; private Long creatoruserid;
...@@ -50,4 +55,7 @@ private String warehousingUnitName; ...@@ -50,4 +55,7 @@ private String warehousingUnitName;
public double getAvailableInventory(){ public double getAvailableInventory(){
return total-totalLock-usedInventory; return total-totalLock-usedInventory;
}; };
}
\ No newline at end of file @TableField(value = "MP_SCENE_ID", fill = FieldFill.INSERT)
private String mpSceneId;
}
...@@ -2,6 +2,7 @@ package com.aps.macroplanner.data; ...@@ -2,6 +2,7 @@ package com.aps.macroplanner.data;
import com.aps.common.util.ParamValidator; import com.aps.common.util.ParamValidator;
import com.aps.entity.*; import com.aps.entity.*;
import com.aps.macroplanner.scene.MacroSceneContext;
import com.aps.entity.basic.Material; import com.aps.entity.basic.Material;
import com.aps.entity.basic.MaterialSupply; import com.aps.entity.basic.MaterialSupply;
import com.aps.mapper.EquipShiftCapacityMapper; import com.aps.mapper.EquipShiftCapacityMapper;
...@@ -134,6 +135,10 @@ public class MacroPlannerDataConverter { ...@@ -134,6 +135,10 @@ public class MacroPlannerDataConverter {
* @return 填充好的 TestDataBuilder, 可直接传给 MacroPlannerOptimizer * @return 填充好的 TestDataBuilder, 可直接传给 MacroPlannerOptimizer
*/ */
public TestDataBuilder convert(String sceneId) { public TestDataBuilder convert(String sceneId) {
return MacroSceneContext.execute(sceneId, () -> convertScoped(sceneId));
}
private TestDataBuilder convertScoped(String sceneId) {
log.info("开始转换场景数据到 macroplanner: sceneId={}", sceneId); log.info("开始转换场景数据到 macroplanner: sceneId={}", sceneId);
ConvertContext ctx = loadRawData(sceneId); ConvertContext ctx = loadRawData(sceneId);
...@@ -160,15 +165,10 @@ public class MacroPlannerDataConverter { ...@@ -160,15 +165,10 @@ public class MacroPlannerDataConverter {
// 0. 读取时间配置, 计算 horizonEnd // 0. 读取时间配置, 计算 horizonEnd
// endCount = 期数 (与 periodDimension 结合决定实际天数) // endCount = 期数 (与 periodDimension 结合决定实际天数)
LambdaQueryWrapper<ApsTimeConfig> wrapper= new LambdaQueryWrapper<ApsTimeConfig>(); ApsTimeConfig timeConfig = apsTimeConfigService.getOne(
if(!sceneId.isEmpty()) new LambdaQueryWrapper<ApsTimeConfig>()
{ .eq(ApsTimeConfig::getMpSceneId, "172f545f-f94c-4143-86af-bd65e787e8e6"));
// wrapper.eq(ApsTimeConfig::getMpSceneId,sceneId); ctx.baseTime = LocalDateTime.of(2026, 9, 28, 0, 0, 0);
}
ApsTimeConfig timeConfig = apsTimeConfigService.getOne(wrapper);
ctx.baseTime = LocalDateTime.of(2026,9,28,0,0,0);
// ctx.baseTime = (timeConfig != null && timeConfig.getBaseTime() != null)
// ? timeConfig.getBaseTime() : LocalDateTime.now();
ctx.periodDimension = "DAY"; ctx.periodDimension = "DAY";
if (timeConfig != null && timeConfig.getPeriodDimension() != null if (timeConfig != null && timeConfig.getPeriodDimension() != null
...@@ -192,19 +192,10 @@ public class MacroPlannerDataConverter { ...@@ -192,19 +192,10 @@ public class MacroPlannerDataConverter {
ctx.periodDimension, periodCount, ctx.baseTime, ctx.horizonEnd); ctx.periodDimension, periodCount, ctx.baseTime, ctx.horizonEnd);
// 1. 需求订单 (ApsDemandOrder, 按 deliverytime 时间范围过滤) // 1. 需求订单 (ApsDemandOrder, 按 deliverytime 时间范围过滤)
// ctx.apsDemandOrders = apsDemandOrderMapper.selectList( ctx.apsDemandOrders = apsDemandOrderMapper.selectList(
// new LambdaQueryWrapper<ApsDemandOrder>().eq(ApsDemandOrder::getIsdeleted, 0)
// .ge(ApsDemandOrder::getDeliverytime, ctx.baseTime)
// .lt(ApsDemandOrder::getDeliverytime, horizonEndDateTime));
ctx.apsDemandOrders = apsDemandOrderMapper.selectList(
new LambdaQueryWrapper<ApsDemandOrder>() new LambdaQueryWrapper<ApsDemandOrder>()
.ge(ApsDemandOrder::getDeliverytime, ctx.baseTime) .ge(ApsDemandOrder::getDeliverytime, ctx.baseTime)
.eq(ApsDemandOrder::getCode,"XQDD_20260812_6") .lt(ApsDemandOrder::getDeliverytime, horizonEndDateTime));
.lt(ApsDemandOrder::getDeliverytime, horizonEndDateTime)
);
log.info("加载需求订单: {} 条 (时间范围过滤)", ctx.apsDemandOrders.size()); log.info("加载需求订单: {} 条 (时间范围过滤)", ctx.apsDemandOrders.size());
...@@ -214,7 +205,7 @@ public class MacroPlannerDataConverter { ...@@ -214,7 +205,7 @@ public class MacroPlannerDataConverter {
.filter(Objects::nonNull) .filter(Objects::nonNull)
.distinct() .distinct()
.collect(Collectors.toSet()); .collect(Collectors.toSet());
List<Integer> routingIds=null; List<Integer> routingIds = Collections.emptyList();
// 3. 工艺路线头表 // 3. 工艺路线头表
if (!materialIds.isEmpty()) { if (!materialIds.isEmpty()) {
ctx.routingHeaders = routingHeaderMapper.selectList( ctx.routingHeaders = routingHeaderMapper.selectList(
...@@ -1353,7 +1344,7 @@ public class MacroPlannerDataConverter { ...@@ -1353,7 +1344,7 @@ public class MacroPlannerDataConverter {
String key = m.getProduct().getId() + "_" + m.getStockingPoint().getId() + "_" + p.getIndex(); String key = m.getProduct().getId() + "_" + m.getStockingPoint().getId() + "_" + p.getIndex();
if (invSpecKeys.add(key)) { if (invSpecKeys.add(key)) {
inventorySpecs.add(new InventorySpec(m.getProduct(), m.getStockingPoint(), p, inventorySpecs.add(new InventorySpec(m.getProduct(), m.getStockingPoint(), p,
0.0, 0.0, 0, false, true, false)); 0.0, 0.0, LOOSE_MAX, false, true, true));
} }
} }
} }
...@@ -1366,12 +1357,12 @@ public class MacroPlannerDataConverter { ...@@ -1366,12 +1357,12 @@ public class MacroPlannerDataConverter {
} }
Operation lastOp = ops.get(ops.size() - 1); Operation lastOp = ops.get(ops.size() - 1);
supplySpecs.add(new SupplySpec("Supply-" + r.getId(), supplySpecs.add(new SupplySpec("Supply-" + r.getId(),
0.0, 0.0, 0, false, Collections.singletonList(lastOp))); 0.0, 0.0, LOOSE_MAX, false, Collections.singletonList(lastOp)));
} }
for (Operation op : operations) { for (Operation op : operations) {
if (op.getId().startsWith("OP_PROCURE_")) { if (op.getId().startsWith("OP_PROCURE_")) {
supplySpecs.add(new SupplySpec("Supply-" + op.getId(), supplySpecs.add(new SupplySpec("Supply-" + op.getId(),
0.0, 0.0, 0, false, Collections.singletonList(op))); 0.0, 0.0, LOOSE_MAX, true, Collections.singletonList(op)));
} }
} }
log.info("构建 InventorySpec: {}, SupplySpec: {}", inventorySpecs.size(), supplySpecs.size()); log.info("构建 InventorySpec: {}, SupplySpec: {}", inventorySpecs.size(), supplySpecs.size());
......
package com.aps.macroplanner.scene;
import java.util.function.Supplier;
/** Holds the macro-planning scene selected for the current request or operation. */
public final class MacroSceneContext {
private static final ThreadLocal<String> CURRENT_SCENE = new ThreadLocal<>();
private MacroSceneContext() {
}
public static String getSceneId() {
return CURRENT_SCENE.get();
}
public static void setSceneId(String sceneId) {
String normalized = normalize(sceneId);
if (normalized == null) {
CURRENT_SCENE.remove();
} else {
CURRENT_SCENE.set(normalized);
}
}
public static void clear() {
CURRENT_SCENE.remove();
}
public static <T> T execute(String sceneId, Supplier<T> action) {
String previous = getSceneId();
try {
setSceneId(sceneId);
return action.get();
} finally {
setSceneId(previous);
}
}
public static void execute(String sceneId, Runnable action) {
execute(sceneId, () -> {
action.run();
return null;
});
}
private static String normalize(String sceneId) {
if (sceneId == null || sceneId.trim().isEmpty()) {
return null;
}
return sceneId.trim();
}
}
package com.aps.macroplanner.scene;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
public class MacroSceneCreateRequest {
@Schema(description = "场景名称", required = true, example = "主计划场景001")
private String sceneName;
@Schema(description = "场景描述", example = "场景描述")
private String sceneDesc;
@Schema(description = "来源场景 ID,不传表示从原始数据创建", nullable = true)
private String sourceSceneId;
@Schema(description = "用户 ID", required = true, example = "1111")
private String userId;
}
package com.aps.macroplanner.scene;
import com.baomidou.mybatisplus.extension.plugins.handler.MultiDataPermissionHandler;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.StringValue;
import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
import net.sf.jsqlparser.expression.operators.relational.IsNullExpression;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.schema.Table;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;
public class MacroSceneDataPermissionHandler implements MultiDataPermissionHandler {
private static final Set<String> SCENE_TABLES = new HashSet<>(Arrays.asList(
"APS_DEMAND_ORDER",
"MATERIAL_INFO",
"ROUTING_HEADER",
"ROUTING_DETAIL",
"ROUTING_DETAIL_CONNECT",
"ROUTINGSUPPORTING",
"ROUTING_DETAIL_EQUIP",
"STOCK",
"MATERIAL_PURCHASE",
"ERP_PURCHASE_ORDER",
"PURCHASE_RECEIPT",
"SJZ_PF_WH_STOCK",
"PLAN_RESOURCE",
"EQUIPINFO",
"EQUIP_SHIFT_CAPACITY",
"APS_TIME_CONFIG"
));
@Override
public Expression getSqlSegment(Table table, Expression where, String mappedStatementId) {
if (!isSceneTable(table)) {
return null;
}
Column sceneColumn = new Column(columnPrefix(table) + ".MP_SCENE_ID");
String sceneId = MacroSceneContext.getSceneId();
if (sceneId == null) {
IsNullExpression isNull = new IsNullExpression();
isNull.setLeftExpression(sceneColumn);
return isNull;
}
return new EqualsTo(sceneColumn, new StringValue(sceneId));
}
private boolean isSceneTable(Table table) {
return table != null
&& table.getName() != null
&& SCENE_TABLES.contains(table.getName().toUpperCase(Locale.ROOT));
}
private String columnPrefix(Table table) {
if (table.getAlias() != null && table.getAlias().getName() != null) {
return table.getAlias().getName();
}
return table.getFullyQualifiedName();
}
}
package com.aps.macroplanner.scene;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
@Component
public class MacroSceneMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
String sceneId = MacroSceneContext.getSceneId();
if (sceneId != null && metaObject.hasSetter("mpSceneId")
&& getFieldValByName("mpSceneId", metaObject) == null) {
setFieldValByName("mpSceneId", sceneId, metaObject);
}
}
@Override
public void updateFill(MetaObject metaObject) {
// Scene ownership is immutable after insertion.
}
}
package com.aps.macroplanner.scene;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Component
public class MacroSceneRequestFilter extends OncePerRequestFilter {
public static final String HEADER_NAME = "X-MP-Scene-Id";
@Override
protected boolean shouldNotFilter(HttpServletRequest request) {
String path = request.getRequestURI();
return path.startsWith("/lanuch")
|| path.startsWith("/schedule")
|| path.startsWith("/ganttest")
|| path.startsWith("/gantt")
|| path.startsWith("/Gantt");
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
String sceneId = request.getHeader(HEADER_NAME);
if (sceneId == null || sceneId.trim().isEmpty()) {
sceneId = request.getParameter("mpSceneId");
}
if ((sceneId == null || sceneId.trim().isEmpty())
&& request.getRequestURI().startsWith("/macroResult")) {
sceneId = request.getParameter("sceneId");
}
try {
MacroSceneContext.setSceneId(sceneId);
filterChain.doFilter(request, response);
} finally {
MacroSceneContext.clear();
}
}
}
package com.aps.macroplanner.scene;
import com.aps.entity.*;
import com.aps.mapper.*;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.jdbc.datasource.DataSourceUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import lombok.extern.slf4j.Slf4j;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import javax.sql.DataSource;
import java.sql.Clob;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.LinkedHashMap;
import java.util.UUID;
import java.util.function.Consumer;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.Locale;
@Service
@RequiredArgsConstructor
@Slf4j
public class MacroSceneService {
private static final int SCENE_COPY_PAGE_SIZE = 2000;
private static final int JDBC_BATCH_SIZE = 2000;
private static final int JSON_REMAP_BATCH_SIZE = 500;
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
private final DataSource dataSource;
private final MacroSceneConfigMapper sceneConfigMapper;
private final MacroSceneSequenceMapper sequenceMapper;
private final ApsDemandOrderMapper apsDemandOrderMapper;
private final MaterialInfoMapper materialInfoMapper;
private final RoutingHeaderMapper routingHeaderMapper;
private final RoutingDetailMapper routingDetailMapper;
private final RoutingDetailConnectMapper routingDetailConnectMapper;
private final RoutingsupportingMapper routingsupportingMapper;
private final RoutingDetailEquipMapper routingDetailEquipMapper;
private final StockMapper stockMapper;
private final MaterialPurchaseMapper materialPurchaseMapper;
private final ErpPurchaseOrderMapper erpPurchaseOrderMapper;
private final PurchaseReceiptMapper purchaseReceiptMapper;
private final SjzPfWhStockMapper sjzPfWhStockMapper;
private final PlanResourceMapper planResourceMapper;
private final EquipinfoMapper equipinfoMapper;
private final EquipShiftCapacityMapper equipShiftCapacityMapper;
private final ApsTimeConfigMapper apsTimeConfigMapper;
public List<MacroSceneConfig> listScenes() {
return sceneConfigMapper.selectList(null);
}
public MacroSceneConfig getScene(String sceneId) {
return sceneConfigMapper.selectById(requireText(sceneId, "sceneId"));
}
public synchronized MacroSceneConfig createScene(MacroSceneCreateRequest request) {
long createStartNanos = System.nanoTime();
if (request == null) {
throw new IllegalArgumentException("request cannot be null");
}
String sceneName = requireText(request.getSceneName(), "sceneName");
String userId = requireText(request.getUserId(), "userId");
String sourceSceneId = normalize(request.getSourceSceneId());
if (sourceSceneId != null && sceneConfigMapper.selectById(sourceSceneId) == null) {
throw new IllegalArgumentException("source macro scene does not exist: " + sourceSceneId);
}
Long duplicateCount = sceneConfigMapper.selectCount(
new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<MacroSceneConfig>()
.eq(MacroSceneConfig::getSceneName, sceneName));
if (duplicateCount != null && duplicateCount > 0) {
throw new IllegalArgumentException("macro scene name already exists: " + sceneName);
}
String sceneId = UUID.randomUUID().toString();
LocalDateTime now = LocalDateTime.now();
MacroSceneConfig config = new MacroSceneConfig();
config.setSceneId(sceneId);
config.setSceneName(sceneName);
config.setSceneDesc(request.getSceneDesc());
config.setSourceSceneId(sourceSceneId);
config.setSceneStatus("COPYING");
config.setCreateUser(userId);
config.setCreateTime(now);
config.setUpdateUser(userId);
config.setUpdateTime(now);
sceneConfigMapper.insert(config);
try {
cloneSceneData(sourceSceneId, sceneId);
config.setSceneStatus("READY");
config.setUpdateTime(LocalDateTime.now());
sceneConfigMapper.updateById(config);
long durationMs = elapsedMillis(createStartNanos);
log.info("主计划场景创建完成,场景ID:{},场景名称:{},耗时:{}毫秒",
sceneId, sceneName, durationMs);
return config;
} catch (RuntimeException ex) {
log.error("主计划场景创建失败,场景ID:{},场景名称:{},耗时:{}毫秒",
sceneId, sceneName, elapsedMillis(createStartNanos), ex);
try {
cleanupSceneData(sceneId);
config.setSceneStatus("FAILED");
config.setUpdateTime(LocalDateTime.now());
sceneConfigMapper.updateById(config);
} catch (RuntimeException cleanupEx) {
log.error("Macro scene cleanup failed: sceneId={}", sceneId, cleanupEx);
}
throw ex;
}
}
@Transactional(rollbackFor = Exception.class)
public void deleteScene(String sceneId) {
String normalizedSceneId = requireText(sceneId, "sceneId");
if (sceneConfigMapper.selectById(normalizedSceneId) == null) {
return;
}
cleanupSceneData(normalizedSceneId);
sceneConfigMapper.deleteById(normalizedSceneId);
}
private void cleanupSceneData(String sceneId) {
MacroSceneContext.execute(sceneId, () -> {
apsDemandOrderMapper.delete(null);
routingDetailEquipMapper.delete(null);
routingDetailConnectMapper.delete(null);
routingsupportingMapper.delete(null);
routingDetailMapper.delete(null);
routingHeaderMapper.delete(null);
equipShiftCapacityMapper.delete(null);
planResourceMapper.delete(null);
equipinfoMapper.delete(null);
stockMapper.delete(null);
materialPurchaseMapper.delete(null);
erpPurchaseOrderMapper.delete(null);
purchaseReceiptMapper.delete(null);
sjzPfWhStockMapper.delete(null);
materialInfoMapper.delete(null);
apsTimeConfigMapper.delete(null);
});
}
private void cloneSceneData(String sourceSceneId, String targetSceneId) {
Map<Integer, Integer> equipIds = copyEquipinfo(sourceSceneId, targetSceneId);
Map<Integer, Integer> resourceIds = copyPlanResources(sourceSceneId, targetSceneId, equipIds);
MaterialCopyResult materialCopy = copyMaterials(sourceSceneId, targetSceneId, equipIds, resourceIds);
Map<String, String> materialIds = materialCopy.idMap;
RoutingHeaderCopyResult routingCopy = copyRoutingHeaders(sourceSceneId, targetSceneId);
Map<Integer, Integer> routingIds = routingCopy.idMap;
RoutingDetailCopyResult detailCopy = copyRoutingDetails(sourceSceneId, targetSceneId, routingIds);
Map<Long, Long> detailIds = detailCopy.idMap;
copyRoutingsupporting(sourceSceneId, targetSceneId, materialIds, routingIds, detailIds);
copyRoutingConnections(sourceSceneId, targetSceneId, routingIds, detailIds);
copyRoutingEquipment(sourceSceneId, targetSceneId, routingIds, detailIds, resourceIds);
restoreRoutingDetailPredecessor(targetSceneId, detailCopy.sourceRows, detailIds);
restoreRoutingHeaderRelations(targetSceneId, routingCopy.sourceRows, routingIds, detailIds);
restoreMaterialMatchRelations(targetSceneId, materialCopy.sourceRows, materialIds);
copyDemandOrders(sourceSceneId, targetSceneId, materialIds, routingIds);
copyStocksAndSupplies(sourceSceneId, targetSceneId, materialIds, routingIds);
copyEquipCapacity(sourceSceneId, targetSceneId, equipIds, resourceIds);
copySimpleRows(sourceSceneId, targetSceneId, apsTimeConfigMapper, ApsTimeConfig.class, null);
}
private Map<Integer, Integer> copyEquipinfo(String source, String target) {
List<Equipinfo> sourceRows = loadRows(source, equipinfoMapper);
List<Integer> newIds = sequenceMapper.nextEquipinfoIds(sourceRows.size());
Map<Integer, Integer> idMap = new HashMap<>();
List<Equipinfo> copies = new ArrayList<>(sourceRows.size());
for (int i = 0; i < sourceRows.size(); i++) {
Equipinfo row = sourceRows.get(i);
Integer oldId = row.getId();
Equipinfo copy = copyOf(row, Equipinfo.class);
copy.setId(newIds.get(i));
idMap.put(oldId, copy.getId());
copies.add(copy);
}
batchInsert(target, equipinfoMapper, copies);
return idMap;
}
private Map<Integer, Integer> copyPlanResources(String source, String target,
Map<Integer, Integer> equipIds) {
List<PlanResource> sourceRows = loadRows(source, planResourceMapper);
List<Integer> newIds = sequenceMapper.nextPlanResourceIds(sourceRows.size());
Map<Integer, Integer> idMap = new HashMap<>();
List<PlanResource> copies = new ArrayList<>(sourceRows.size());
for (int i = 0; i < sourceRows.size(); i++) {
PlanResource row = sourceRows.get(i);
Integer oldId = row.getId();
PlanResource copy = copyOf(row, PlanResource.class);
copy.setId(newIds.get(i));
copy.setReferenceId(remap(row.getReferenceId(), equipIds));
idMap.put(oldId, copy.getId());
copies.add(copy);
}
batchInsert(target, planResourceMapper, copies);
return idMap;
}
private MaterialCopyResult copyMaterials(String source, String target,
Map<Integer, Integer> equipIds,
Map<Integer, Integer> resourceIds) {
List<MaterialReference> sourceRows = loadMaterialReferences(source);
copyMaterialsInDatabase(source, target, equipIds, resourceIds);
Map<String, String> idMap = loadMaterialIdMap(target);
return new MaterialCopyResult(idMap, sourceRows);
}
private RoutingHeaderCopyResult copyRoutingHeaders(String source, String target) {
List<RoutingHeaderReference> sourceRows = loadRoutingHeaderReferences(source);
copyRoutingHeadersInDatabase(source, target);
Map<Integer, Integer> idMap = loadRoutingHeaderIdMap(target);
return new RoutingHeaderCopyResult(idMap, sourceRows);
}
private void copyMaterialsInDatabase(String source, String target,
Map<Integer, Integer> equipIds,
Map<Integer, Integer> resourceIds) {
TableInfo tableInfo = requiredTableInfo(MaterialInfo.class);
List<String> columns = new ArrayList<>();
List<String> values = new ArrayList<>();
columns.add(tableInfo.getKeyColumn());
values.add("LOWER(REGEXP_REPLACE(RAWTOHEX(SYS_GUID()), "
+ "'(.{8})(.{4})(.{4})(.{4})(.{12})', '\\1-\\2-\\3-\\4-\\5'))");
for (TableFieldInfo field : tableInfo.getFieldList()) {
String column = field.getColumn();
if ("MP_SCENE_ID".equalsIgnoreCase(column)) {
continue;
}
columns.add(column);
if ("MATCH_BIGPRO_ID".equalsIgnoreCase(column)) {
values.add("src.ID");
} else if ("MATCH_SMALLPRO_ID".equalsIgnoreCase(column)) {
values.add("NULL");
} else if ("EQUIP_ID".equalsIgnoreCase(column)) {
values.add("NVL(resource_map.NEW_ID, NVL(equip_map.NEW_ID, src.EQUIP_ID))");
} else {
values.add("src." + column);
}
}
columns.add("MP_SCENE_ID");
values.add("?");
List<Long> parameters = new ArrayList<>();
String equipMapSql = mapCte("equip_map", equipIds, parameters);
String resourceMapSql = mapCte("resource_map", resourceIds, parameters);
String sourcePredicate = source == null ? "src.MP_SCENE_ID IS NULL" : "src.MP_SCENE_ID = ?";
String sql = "INSERT INTO " + tableInfo.getTableName() + " (" + String.join(", ", columns) + ") "
+ "WITH " + equipMapSql + ", " + resourceMapSql + " "
+ "SELECT " + String.join(", ", values) + " FROM " + tableInfo.getTableName() + " src "
+ "LEFT JOIN equip_map ON equip_map.OLD_ID = src.EQUIP_ID "
+ "LEFT JOIN resource_map ON resource_map.OLD_ID = src.EQUIP_ID "
+ "WHERE src.ISDELETED = 0 AND " + sourcePredicate;
Connection connection = DataSourceUtils.getConnection(dataSource);
try (PreparedStatement statement = connection.prepareStatement(sql)) {
int index = 1;
for (Long parameter : parameters) {
statement.setLong(index++, parameter);
}
statement.setString(index++, target);
if (source != null) {
statement.setString(index, source);
}
int copiedRows = statement.executeUpdate();
log.info("Macro scene database copy: target=MaterialInfo, rows={}", copiedRows);
} catch (SQLException ex) {
throw new IllegalStateException("Failed to copy MaterialInfo in database", ex);
} finally {
DataSourceUtils.releaseConnection(connection, dataSource);
}
}
private long elapsedMillis(long startNanos) {
return java.util.concurrent.TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startNanos);
}
private Map<String, String> loadMaterialIdMap(String target) {
Map<String, String> idMap = new HashMap<>();
String sql = "SELECT ID, MATCH_BIGPRO_ID FROM MATERIAL_INFO WHERE MP_SCENE_ID = ?";
Connection connection = DataSourceUtils.getConnection(dataSource);
try (PreparedStatement statement = connection.prepareStatement(sql)) {
statement.setString(1, target);
try (ResultSet resultSet = statement.executeQuery()) {
while (resultSet.next()) {
idMap.put(resultSet.getString("MATCH_BIGPRO_ID"), resultSet.getString("ID"));
}
}
return idMap;
} catch (SQLException ex) {
throw new IllegalStateException("Failed to load MaterialInfo ID mapping", ex);
} finally {
DataSourceUtils.releaseConnection(connection, dataSource);
}
}
private void copyRoutingHeadersInDatabase(String source, String target) {
TableInfo tableInfo = requiredTableInfo(RoutingHeader.class);
List<String> columns = new ArrayList<>();
List<String> values = new ArrayList<>();
columns.add(tableInfo.getKeyColumn());
values.add("SEQ_ROUTING_HEADERS.NEXTVAL");
for (TableFieldInfo field : tableInfo.getFieldList()) {
String column = field.getColumn();
if ("MP_SCENE_ID".equalsIgnoreCase(column)) {
continue;
}
columns.add(column);
if ("UP_DETAIL_ID".equalsIgnoreCase(column)) {
values.add("src.ID");
} else if ("MATERIAL_ID".equalsIgnoreCase(column)) {
values.add("NVL(target_material.ID, src.MATERIAL_ID)");
} else {
values.add("src." + column);
}
}
columns.add("MP_SCENE_ID");
values.add("?");
String sourcePredicate = source == null ? "src.MP_SCENE_ID IS NULL" : "src.MP_SCENE_ID = ?";
String sql = "INSERT INTO " + tableInfo.getTableName() + " (" + String.join(", ", columns) + ") "
+ "SELECT " + String.join(", ", values) + " FROM " + tableInfo.getTableName() + " src "
+ "LEFT JOIN MATERIAL_INFO target_material ON target_material.MP_SCENE_ID = ? "
+ "AND target_material.MATCH_BIGPRO_ID = src.MATERIAL_ID WHERE " + sourcePredicate;
Connection connection = DataSourceUtils.getConnection(dataSource);
try (PreparedStatement statement = connection.prepareStatement(sql)) {
int index = 1;
statement.setString(index++, target);
statement.setString(index++, target);
if (source != null) {
statement.setString(index, source);
}
int copiedRows = statement.executeUpdate();
log.info("Macro scene database copy: target=RoutingHeader, rows={}", copiedRows);
} catch (SQLException ex) {
throw new IllegalStateException("Failed to copy RoutingHeader in database", ex);
} finally {
DataSourceUtils.releaseConnection(connection, dataSource);
}
}
private Map<Integer, Integer> loadRoutingHeaderIdMap(String target) {
Map<Integer, Integer> idMap = new HashMap<>();
String sql = "SELECT ID, UP_DETAIL_ID FROM ROUTING_HEADER WHERE MP_SCENE_ID = ?";
Connection connection = DataSourceUtils.getConnection(dataSource);
try (PreparedStatement statement = connection.prepareStatement(sql)) {
statement.setString(1, target);
try (ResultSet resultSet = statement.executeQuery()) {
while (resultSet.next()) {
idMap.put(resultSet.getInt("UP_DETAIL_ID"), resultSet.getInt("ID"));
}
}
return idMap;
} catch (SQLException ex) {
throw new IllegalStateException("Failed to load RoutingHeader ID mapping", ex);
} finally {
DataSourceUtils.releaseConnection(connection, dataSource);
}
}
private List<MaterialReference> loadMaterialReferences(String source) {
String predicate = source == null ? "MP_SCENE_ID IS NULL" : "MP_SCENE_ID = ?";
String sql = "SELECT ID, LINKMATERIALID, MATCH_BIGPRO_ID, MATCH_SMALLPRO_ID FROM MATERIAL_INFO "
+ "WHERE ISDELETED = 0 AND " + predicate;
List<MaterialReference> rows = new ArrayList<>();
Connection connection = DataSourceUtils.getConnection(dataSource);
try (PreparedStatement statement = connection.prepareStatement(sql)) {
if (source != null) {
statement.setString(1, source);
}
try (ResultSet resultSet = statement.executeQuery()) {
while (resultSet.next()) {
rows.add(new MaterialReference(resultSet.getString("ID"),
resultSet.getString("LINKMATERIALID"),
resultSet.getString("MATCH_BIGPRO_ID"),
resultSet.getString("MATCH_SMALLPRO_ID")));
}
}
log.info("Macro scene reference rows: target=MaterialInfo, rows={}", rows.size());
return rows;
} catch (SQLException ex) {
throw new IllegalStateException("Failed to load MaterialInfo references", ex);
} finally {
DataSourceUtils.releaseConnection(connection, dataSource);
}
}
private List<RoutingHeaderReference> loadRoutingHeaderReferences(String source) {
String predicate = source == null ? "MP_SCENE_ID IS NULL" : "MP_SCENE_ID = ?";
String sql = "SELECT ID, LINKROUTINGID, ROUTING_CHANGEHEADER_ID, UP_ID, UP_DETAIL_ID "
+ "FROM ROUTING_HEADER WHERE " + predicate;
List<RoutingHeaderReference> rows = new ArrayList<>();
Connection connection = DataSourceUtils.getConnection(dataSource);
try (PreparedStatement statement = connection.prepareStatement(sql)) {
if (source != null) {
statement.setString(1, source);
}
try (ResultSet resultSet = statement.executeQuery()) {
while (resultSet.next()) {
rows.add(new RoutingHeaderReference(resultSet.getInt("ID"),
getNullableInteger(resultSet, "LINKROUTINGID"),
getNullableInteger(resultSet, "ROUTING_CHANGEHEADER_ID"),
getNullableInteger(resultSet, "UP_ID"),
getNullableInteger(resultSet, "UP_DETAIL_ID")));
}
}
log.info("Macro scene reference rows: target=RoutingHeader, rows={}", rows.size());
return rows;
} catch (SQLException ex) {
throw new IllegalStateException("Failed to load RoutingHeader references", ex);
} finally {
DataSourceUtils.releaseConnection(connection, dataSource);
}
}
private List<RoutingDetailReference> loadRoutingDetailReferences(String source) {
String predicate = source == null ? "MP_SCENE_ID IS NULL" : "MP_SCENE_ID = ?";
String sql = "SELECT ID, PRE_DETAIL_ID FROM ROUTING_DETAIL WHERE IS_DELETED = 0 AND " + predicate;
List<RoutingDetailReference> rows = new ArrayList<>();
Connection connection = DataSourceUtils.getConnection(dataSource);
try (PreparedStatement statement = connection.prepareStatement(sql)) {
if (source != null) {
statement.setString(1, source);
}
try (ResultSet resultSet = statement.executeQuery()) {
while (resultSet.next()) {
rows.add(new RoutingDetailReference(resultSet.getLong("ID"),
getNullableLong(resultSet, "PRE_DETAIL_ID")));
}
}
log.info("Macro scene reference rows: target=RoutingDetail, rows={}", rows.size());
return rows;
} catch (SQLException ex) {
throw new IllegalStateException("Failed to load RoutingDetail references", ex);
} finally {
DataSourceUtils.releaseConnection(connection, dataSource);
}
}
private Integer getNullableInteger(ResultSet resultSet, String column) throws SQLException {
int value = resultSet.getInt(column);
return resultSet.wasNull() ? null : value;
}
private Long getNullableLong(ResultSet resultSet, String column) throws SQLException {
long value = resultSet.getLong(column);
return resultSet.wasNull() ? null : value;
}
private void remapRoutingHierarchy(String source, String target,
Map<Integer, Integer> routingIds,
Map<Long, Long> detailIds) {
List<RoutingHeader> sourceRows = loadRows(source, routingHeaderMapper);
jdbcClearRoutingHierarchyMarker(target);
jdbcBatchUpdateRoutingHierarchy(target, sourceRows, routingIds, detailIds);
}
private RoutingDetailCopyResult copyRoutingDetails(String source, String target,
Map<Integer, Integer> routingIds) {
TableInfo tableInfo = TableInfoHelper.getTableInfo(RoutingDetail.class);
if (tableInfo == null) {
throw new IllegalStateException("No MyBatis-Plus table metadata for RoutingDetail");
}
List<String> columns = new ArrayList<>();
List<String> values = new ArrayList<>();
columns.add(tableInfo.getKeyColumn());
values.add("SEQ_ROUTING_DETAILS.NEXTVAL");
for (TableFieldInfo field : tableInfo.getFieldList()) {
if ("MP_SCENE_ID".equalsIgnoreCase(field.getColumn())) {
continue;
}
columns.add(field.getColumn());
if ("ROUTING_HEADER_ID".equalsIgnoreCase(field.getColumn())) {
values.add("NVL(target_header.ID, src.ROUTING_HEADER_ID)");
} else if ("PRE_DETAIL_ID".equalsIgnoreCase(field.getColumn())) {
// Keep the original row ID briefly so the old/new map can be read without a helper table.
values.add("src.ID");
} else {
values.add("src." + field.getColumn());
}
}
columns.add("MP_SCENE_ID");
values.add("?");
String sourcePredicate = source == null ? "src.MP_SCENE_ID IS NULL" : "src.MP_SCENE_ID = ?";
String sql = "INSERT INTO " + tableInfo.getTableName() + " (" + String.join(", ", columns) + ") "
+ "SELECT " + String.join(", ", values) + " FROM " + tableInfo.getTableName() + " src "
+ "LEFT JOIN ROUTING_HEADER target_header ON target_header.MP_SCENE_ID = ? "
+ "AND target_header.UP_DETAIL_ID = src.ROUTING_HEADER_ID "
+ "WHERE src.IS_DELETED = 0 AND " + sourcePredicate;
Connection connection = DataSourceUtils.getConnection(dataSource);
try (PreparedStatement statement = connection.prepareStatement(sql)) {
int index = 1;
statement.setString(index++, target);
statement.setString(index++, target);
if (source != null) {
statement.setString(index, source);
}
int copiedRows = statement.executeUpdate();
log.info("Macro scene database copy: target=RoutingDetail, rows={}", copiedRows);
} catch (SQLException ex) {
throw new IllegalStateException("Failed to copy RoutingDetail in database", ex);
} finally {
DataSourceUtils.releaseConnection(connection, dataSource);
}
Map<Long, Long> idMap = loadRoutingDetailIdMap(target, tableInfo.getTableName());
List<RoutingDetailReference> sourceRows = loadRoutingDetailReferences(source);
return new RoutingDetailCopyResult(idMap, sourceRows);
}
private Map<Long, Long> loadRoutingDetailIdMap(String sceneId, String tableName) {
Map<Long, Long> idMap = new HashMap<>();
String sql = "SELECT ID, PRE_DETAIL_ID FROM " + tableName + " WHERE MP_SCENE_ID = ?";
Connection connection = DataSourceUtils.getConnection(dataSource);
try (PreparedStatement statement = connection.prepareStatement(sql)) {
statement.setString(1, sceneId);
try (ResultSet resultSet = statement.executeQuery()) {
while (resultSet.next()) {
idMap.put(resultSet.getLong("PRE_DETAIL_ID"), resultSet.getLong("ID"));
}
}
return idMap;
} catch (SQLException ex) {
throw new IllegalStateException("Failed to load RoutingDetail ID mapping", ex);
} finally {
DataSourceUtils.releaseConnection(connection, dataSource);
}
}
private void restoreRoutingDetailPredecessor(String target,
List<RoutingDetailReference> sourceRows,
Map<Long, Long> detailIds) {
String sql = "MERGE INTO ROUTING_DETAIL target_detail USING ("
+ "SELECT mapped.TARGET_ID, mapped.PRE_ID FROM JSON_TABLE(?, '$[*]' COLUMNS ("
+ "TARGET_ID NUMBER PATH '$.targetId', PRE_ID NUMBER PATH '$.preId')) mapped) source_map "
+ "ON (target_detail.ID = source_map.TARGET_ID AND target_detail.MP_SCENE_ID = ?) "
+ "WHEN MATCHED THEN UPDATE SET target_detail.PRE_DETAIL_ID = source_map.PRE_ID";
Connection connection = DataSourceUtils.getConnection(dataSource);
try (PreparedStatement statement = connection.prepareStatement(sql)) {
List<Map<String, Object>> batch = new ArrayList<>(JSON_REMAP_BATCH_SIZE);
int updatedRows = 0;
for (RoutingDetailReference row : sourceRows) {
Long copiedId = detailIds.get(row.id);
if (copiedId == null) {
continue;
}
Long copiedPredecessorId = row.preDetailId == null
? null : detailIds.get(row.preDetailId);
Map<String, Object> mapping = new LinkedHashMap<>();
mapping.put("targetId", copiedId);
mapping.put("preId", copiedPredecessorId);
batch.add(mapping);
if (batch.size() == JSON_REMAP_BATCH_SIZE) {
updatedRows += executeJsonMerge(statement, target, batch);
batch.clear();
}
}
if (!batch.isEmpty()) {
updatedRows += executeJsonMerge(statement, target, batch);
}
log.info("Macro scene JSON remap: target=RoutingDetailPredecessor, rows={}", updatedRows);
} catch (SQLException ex) {
throw new IllegalStateException("Failed to restore RoutingDetail predecessor", ex);
} finally {
DataSourceUtils.releaseConnection(connection, dataSource);
}
}
private void restoreMaterialMatchRelations(String target, List<MaterialReference> sourceRows,
Map<String, String> materialIds) {
String sql = "MERGE INTO MATERIAL_INFO target_material USING ("
+ "SELECT mapped.TARGET_ID, mapped.LINK_ID, mapped.MATCH_BIG_ID, mapped.MATCH_SMALL_ID "
+ "FROM JSON_TABLE(?, '$[*]' COLUMNS ("
+ "TARGET_ID VARCHAR2(128) PATH '$.targetId', "
+ "LINK_ID VARCHAR2(128) PATH '$.linkId', "
+ "MATCH_BIG_ID VARCHAR2(128) PATH '$.matchBigId', "
+ "MATCH_SMALL_ID VARCHAR2(128) PATH '$.matchSmallId')) mapped) source_map "
+ "ON (target_material.ID = source_map.TARGET_ID AND target_material.MP_SCENE_ID = ?) "
+ "WHEN MATCHED THEN UPDATE SET target_material.LINKMATERIALID = source_map.LINK_ID, "
+ "target_material.MATCH_BIGPRO_ID = source_map.MATCH_BIG_ID, "
+ "target_material.MATCH_SMALLPRO_ID = source_map.MATCH_SMALL_ID";
Connection connection = DataSourceUtils.getConnection(dataSource);
try (PreparedStatement statement = connection.prepareStatement(sql)) {
List<Map<String, Object>> batch = new ArrayList<>(JSON_REMAP_BATCH_SIZE);
int updatedRows = 0;
for (MaterialReference row : sourceRows) {
String copiedId = materialIds.get(row.id);
if (copiedId == null) {
continue;
}
Map<String, Object> mapping = new LinkedHashMap<>();
mapping.put("targetId", copiedId);
mapping.put("linkId", remap(row.linkMaterialId, materialIds));
mapping.put("matchBigId", remap(row.matchBigproId, materialIds));
mapping.put("matchSmallId", remap(row.matchSmallproId, materialIds));
batch.add(mapping);
if (batch.size() == JSON_REMAP_BATCH_SIZE) {
updatedRows += executeJsonMerge(statement, target, batch);
batch.clear();
}
}
if (!batch.isEmpty()) {
updatedRows += executeJsonMerge(statement, target, batch);
}
log.info("Macro scene JSON remap: target=MaterialInfoMatchRelations, rows={}", updatedRows);
} catch (SQLException ex) {
throw new IllegalStateException("Failed to restore MaterialInfo match relations", ex);
} finally {
DataSourceUtils.releaseConnection(connection, dataSource);
}
}
private void restoreRoutingHeaderRelations(String target, List<RoutingHeaderReference> sourceRows,
Map<Integer, Integer> routingIds,
Map<Long, Long> detailIds) {
String sql = "MERGE INTO ROUTING_HEADER target_header USING ("
+ "SELECT mapped.TARGET_ID, mapped.LINK_ID, mapped.CHANGE_ID, mapped.UP_ID, mapped.UP_DETAIL_ID "
+ "FROM JSON_TABLE(?, '$[*]' COLUMNS ("
+ "TARGET_ID NUMBER PATH '$.targetId', LINK_ID NUMBER PATH '$.linkId', "
+ "CHANGE_ID NUMBER PATH '$.changeId', UP_ID NUMBER PATH '$.upId', "
+ "UP_DETAIL_ID NUMBER PATH '$.upDetailId')) mapped) source_map "
+ "ON (target_header.ID = source_map.TARGET_ID AND target_header.MP_SCENE_ID = ?) "
+ "WHEN MATCHED THEN UPDATE SET target_header.LINKROUTINGID = source_map.LINK_ID, "
+ "target_header.ROUTING_CHANGEHEADER_ID = source_map.CHANGE_ID, "
+ "target_header.UP_ID = source_map.UP_ID, target_header.UP_DETAIL_ID = source_map.UP_DETAIL_ID";
Connection connection = DataSourceUtils.getConnection(dataSource);
try (PreparedStatement statement = connection.prepareStatement(sql)) {
List<Map<String, Object>> batch = new ArrayList<>(JSON_REMAP_BATCH_SIZE);
int updatedRows = 0;
for (RoutingHeaderReference row : sourceRows) {
Integer copiedId = routingIds.get(row.id);
if (copiedId == null) {
continue;
}
Map<String, Object> mapping = new LinkedHashMap<>();
mapping.put("targetId", copiedId);
mapping.put("linkId", remap(row.linkRoutingId, routingIds));
mapping.put("changeId", remap(row.routingChangeHeaderId, routingIds));
mapping.put("upId", remap(row.upId, routingIds));
mapping.put("upDetailId", row.upDetailId == null
? null : detailIds.get(row.upDetailId.longValue()));
batch.add(mapping);
if (batch.size() == JSON_REMAP_BATCH_SIZE) {
updatedRows += executeJsonMerge(statement, target, batch);
batch.clear();
}
}
if (!batch.isEmpty()) {
updatedRows += executeJsonMerge(statement, target, batch);
}
log.info("Macro scene JSON remap: target=RoutingHeaderRelations, rows={}", updatedRows);
} catch (SQLException ex) {
throw new IllegalStateException("Failed to restore RoutingHeader relations", ex);
} finally {
DataSourceUtils.releaseConnection(connection, dataSource);
}
}
private int executeJsonMerge(PreparedStatement statement, String target,
List<Map<String, Object>> mappings) throws SQLException {
String json;
try {
json = OBJECT_MAPPER.writeValueAsString(mappings);
} catch (JsonProcessingException ex) {
throw new IllegalStateException("Failed to serialize scene ID mappings", ex);
}
Clob clob = statement.getConnection().createClob();
try {
clob.setString(1, json);
statement.setClob(1, clob);
statement.setString(2, target);
return statement.executeUpdate();
} finally {
clob.free();
}
}
private void copyRoutingsupporting(String source, String target, Map<String, String> materialIds,
Map<Integer, Integer> routingIds, Map<Long, Long> detailIds) {
Map<String, String> values = new HashMap<>();
values.put("ROUTING_HEADER_ID", "NVL(target_header.ID, src.ROUTING_HEADER_ID)");
values.put("ROUTING_DETAIL_ID", "NVL(target_detail.ID, src.ROUTING_DETAIL_ID)");
values.put("MATERIAL_ID", "NVL(target_material.ID, src.MATERIAL_ID)");
values.put("STR_ID", "TO_CHAR(SEQ_ROUTINGSUPPORTINGS.CURRVAL)");
String joins = " LEFT JOIN ROUTING_HEADER target_header ON target_header.MP_SCENE_ID = ? "
+ "AND target_header.UP_DETAIL_ID = src.ROUTING_HEADER_ID "
+ "LEFT JOIN ROUTING_DETAIL target_detail ON target_detail.MP_SCENE_ID = ? "
+ "AND target_detail.PRE_DETAIL_ID = src.ROUTING_DETAIL_ID "
+ "LEFT JOIN MATERIAL_INFO target_material ON target_material.MP_SCENE_ID = ? "
+ "AND target_material.MATCH_BIGPRO_ID = src.MATERIAL_ID ";
executeMappedDatabaseCopy(Routingsupporting.class, "SEQ_ROUTINGSUPPORTINGS", source, target,
values, joins, java.util.Arrays.asList(target, target, target), null, null);
}
private void copyRoutingConnections(String source, String target, Map<Integer, Integer> routingIds,
Map<Long, Long> detailIds) {
Map<String, String> values = new HashMap<>();
values.put("ROUTING_HEADER_ID", "NVL(target_header.ID, src.ROUTING_HEADER_ID)");
values.put("SOURCEOPERATIONID", "NVL(source_detail.ID, src.SOURCEOPERATIONID)");
values.put("DESTOPERATIONID", "NVL(dest_detail.ID, src.DESTOPERATIONID)");
values.put("STR_ID", "TO_CHAR(SEQ_ROUTING_DETAIL_CONNECTS.CURRVAL)");
String joins = " LEFT JOIN ROUTING_HEADER target_header ON target_header.MP_SCENE_ID = ? "
+ "AND target_header.UP_DETAIL_ID = src.ROUTING_HEADER_ID "
+ "LEFT JOIN ROUTING_DETAIL source_detail ON source_detail.MP_SCENE_ID = ? "
+ "AND source_detail.PRE_DETAIL_ID = src.SOURCEOPERATIONID "
+ "LEFT JOIN ROUTING_DETAIL dest_detail ON dest_detail.MP_SCENE_ID = ? "
+ "AND dest_detail.PRE_DETAIL_ID = src.DESTOPERATIONID ";
executeMappedDatabaseCopy(RoutingDetailConnect.class, "SEQ_ROUTING_DETAIL_CONNECTS", source, target,
values, joins, java.util.Arrays.asList(target, target, target), null, null);
}
private void copyRoutingEquipment(String source, String target, Map<Integer, Integer> routingIds,
Map<Long, Long> detailIds, Map<Integer, Integer> resourceIds) {
List<Long> mapParameters = new ArrayList<>();
String withClause = "WITH " + mapCte("resource_map", resourceIds, mapParameters) + " ";
Map<String, String> values = new HashMap<>();
values.put("ROUTING_HEADER_ID", "NVL(target_header.ID, src.ROUTING_HEADER_ID)");
values.put("ROUTING_DETAIL_ID", "NVL(target_detail.ID, src.ROUTING_DETAIL_ID)");
values.put("EQUIP_ID", "NVL(resource_map.NEW_ID, src.EQUIP_ID)");
values.put("STR_ID", "TO_CHAR(SEQ_ROUTING_DETAIL_EQUIPS.CURRVAL)");
String joins = " LEFT JOIN ROUTING_HEADER target_header ON target_header.MP_SCENE_ID = ? "
+ "AND target_header.UP_DETAIL_ID = src.ROUTING_HEADER_ID "
+ "LEFT JOIN ROUTING_DETAIL target_detail ON target_detail.MP_SCENE_ID = ? "
+ "AND target_detail.PRE_DETAIL_ID = src.ROUTING_DETAIL_ID "
+ "LEFT JOIN resource_map ON resource_map.OLD_ID = src.EQUIP_ID ";
executeMappedDatabaseCopy(RoutingDetailEquip.class, "SEQ_ROUTING_DETAIL_EQUIPS", source, target,
values, joins, java.util.Arrays.asList(target, target), withClause, mapParameters);
}
private void executeMappedDatabaseCopy(Class<?> entityType, String sequenceName,
String source, String target,
Map<String, String> mappedValues,
String joins, List<?> joinParameters,
String withClause, List<?> prefixParameters) {
TableInfo tableInfo = TableInfoHelper.getTableInfo(entityType);
if (tableInfo == null) {
throw new IllegalStateException("No MyBatis-Plus table metadata for " + entityType.getName());
}
List<String> columns = new ArrayList<>();
List<String> values = new ArrayList<>();
columns.add(tableInfo.getKeyColumn());
values.add(sequenceName + ".NEXTVAL");
for (TableFieldInfo field : tableInfo.getFieldList()) {
String column = field.getColumn();
if ("MP_SCENE_ID".equalsIgnoreCase(column)) {
continue;
}
columns.add(column);
String mappedValue = mappedValues.get(column.toUpperCase(Locale.ROOT));
values.add(mappedValue == null ? "src." + column : mappedValue);
}
columns.add("MP_SCENE_ID");
values.add("?");
String sourcePredicate = source == null ? "src.MP_SCENE_ID IS NULL" : "src.MP_SCENE_ID = ?";
String sql = "INSERT INTO " + tableInfo.getTableName() + " (" + String.join(", ", columns) + ") "
+ (withClause == null ? "" : withClause)
+ "SELECT " + String.join(", ", values) + " FROM " + tableInfo.getTableName() + " src "
+ joins + "WHERE src.ISDELETED = 0 AND " + sourcePredicate;
Connection connection = DataSourceUtils.getConnection(dataSource);
try (PreparedStatement statement = connection.prepareStatement(sql)) {
int index = 1;
if (prefixParameters != null) {
for (Object parameter : prefixParameters) {
statement.setObject(index++, parameter);
}
}
statement.setString(index++, target);
for (Object parameter : joinParameters) {
statement.setObject(index++, parameter);
}
if (source != null) {
statement.setString(index, source);
}
int copiedRows = statement.executeUpdate();
log.info("Macro scene database copy: target={}, rows={}", entityType.getSimpleName(), copiedRows);
} catch (SQLException ex) {
throw new IllegalStateException("Failed to copy " + entityType.getSimpleName() + " in database", ex);
} finally {
DataSourceUtils.releaseConnection(connection, dataSource);
}
}
private TableInfo requiredTableInfo(Class<?> entityType) {
TableInfo tableInfo = TableInfoHelper.getTableInfo(entityType);
if (tableInfo == null) {
throw new IllegalStateException("No MyBatis-Plus table metadata for " + entityType.getName());
}
return tableInfo;
}
private void copyDemandOrders(String source, String target, Map<String, String> materialIds,
Map<Integer, Integer> routingIds) {
List<ApsDemandOrder> copies = new ArrayList<>();
for (ApsDemandOrder row : loadRows(source, apsDemandOrderMapper)) {
ApsDemandOrder copy = copyOf(row, ApsDemandOrder.class);
copy.setId(UUID.randomUUID().toString());
copy.setMmid(remap(row.getMmid(), materialIds));
copy.setRoutingid(remapLong(row.getRoutingid(), routingIds));
copies.add(copy);
}
batchInsert(target, apsDemandOrderMapper, copies);
}
private void copyStocksAndSupplies(String source, String target, Map<String, String> materialIds,
Map<Integer, Integer> routingIds) {
List<Stock> stocks = loadRows(source, stockMapper);
List<Long> stockIds = sequenceMapper.nextStockIds(stocks.size());
for (int i = 0; i < stocks.size(); i++) {
Stock row = copyOf(stocks.get(i), Stock.class);
row.setId(stockIds.get(i));
row.setMaterialId(remap(row.getMaterialId(), materialIds));
stocks.set(i, row);
}
batchInsert(target, stockMapper, stocks);
List<MaterialPurchase> purchases = loadRows(source, materialPurchaseMapper);
List<Long> purchaseIds = sequenceMapper.nextMaterialPurchaseIds(purchases.size());
for (int i = 0; i < purchases.size(); i++) {
MaterialPurchase row = copyOf(purchases.get(i), MaterialPurchase.class);
row.setId(purchaseIds.get(i));
row.setMaterialId(remap(row.getMaterialId(), materialIds));
purchases.set(i, row);
}
batchInsert(target, materialPurchaseMapper, purchases);
List<ErpPurchaseOrder> orders = loadRows(source, erpPurchaseOrderMapper);
List<Long> orderIds = sequenceMapper.nextErpPurchaseOrderIds(orders.size());
for (int i = 0; i < orders.size(); i++) {
ErpPurchaseOrder row = copyOf(orders.get(i), ErpPurchaseOrder.class);
row.setId(orderIds.get(i));
row.setMaterialId(remap(row.getMaterialId(), materialIds));
orders.set(i, row);
}
batchInsert(target, erpPurchaseOrderMapper, orders);
List<PurchaseReceipt> receipts = loadRows(source, purchaseReceiptMapper);
List<Long> receiptIds = sequenceMapper.nextPurchaseReceiptIds(receipts.size());
for (int i = 0; i < receipts.size(); i++) {
PurchaseReceipt row = copyOf(receipts.get(i), PurchaseReceipt.class);
row.setId(receiptIds.get(i));
row.setMaterialid(remap(row.getMaterialid(), materialIds));
receipts.set(i, row);
}
batchInsert(target, purchaseReceiptMapper, receipts);
List<SjzPfWhStock> sjzStocks = loadRows(source, sjzPfWhStockMapper);
List<Long> sjzIds = sequenceMapper.nextSjzPfWhStockIds(sjzStocks.size());
for (int i = 0; i < sjzStocks.size(); i++) {
SjzPfWhStock row = copyOf(sjzStocks.get(i), SjzPfWhStock.class);
row.setId(sjzIds.get(i));
row.setMaterialid(remap(row.getMaterialid(), materialIds));
if (row.getRoutingid() != null) {
try {
Integer newRoutingId = routingIds.get(Integer.valueOf(row.getRoutingid()));
if (newRoutingId != null) row.setRoutingid(String.valueOf(newRoutingId));
} catch (NumberFormatException ignored) {
// Some records use a business routing code instead of a numeric ID.
}
}
sjzStocks.set(i, row);
}
batchInsert(target, sjzPfWhStockMapper, sjzStocks);
}
private void copyEquipCapacity(String source, String target, Map<Integer, Integer> equipIds,
Map<Integer, Integer> resourceIds) {
TableInfo tableInfo = TableInfoHelper.getTableInfo(EquipShiftCapacity.class);
if (tableInfo == null) {
throw new IllegalStateException("No MyBatis-Plus table metadata for EquipShiftCapacity");
}
List<String> columns = new ArrayList<>();
List<String> values = new ArrayList<>();
columns.add(tableInfo.getKeyColumn());
values.add("SEQ_EQUIP_SHIFT_CAPACITYS.NEXTVAL");
for (TableFieldInfo field : tableInfo.getFieldList()) {
if ("MP_SCENE_ID".equalsIgnoreCase(field.getColumn())) {
continue;
}
columns.add(field.getColumn());
if ("EQUIP_ID".equalsIgnoreCase(field.getColumn())) {
values.add("NVL(equip_map.NEW_ID, src.EQUIP_ID)");
} else if ("PLAN_RESOURCE_ID".equalsIgnoreCase(field.getColumn())) {
values.add("NVL(resource_map.NEW_ID, src.PLAN_RESOURCE_ID)");
} else {
values.add("src." + field.getColumn());
}
}
columns.add("MP_SCENE_ID");
values.add("?");
List<Long> parameters = new ArrayList<>();
String equipMapSql = mapCte("equip_map", equipIds, parameters);
String resourceMapSql = mapCte("resource_map", resourceIds, parameters);
String sourcePredicate = source == null ? "src.MP_SCENE_ID IS NULL" : "src.MP_SCENE_ID = ?";
String sql = "INSERT INTO " + tableInfo.getTableName() + " (" + String.join(", ", columns) + ") "
+ "WITH " + equipMapSql + ", " + resourceMapSql + " "
+ "SELECT " + String.join(", ", values) + " FROM " + tableInfo.getTableName() + " src "
+ "LEFT JOIN equip_map ON equip_map.OLD_ID = src.EQUIP_ID "
+ "LEFT JOIN resource_map ON resource_map.OLD_ID = src.PLAN_RESOURCE_ID "
+ "WHERE src.IS_DELETED = 0 AND " + sourcePredicate;
Connection connection = DataSourceUtils.getConnection(dataSource);
try (PreparedStatement statement = connection.prepareStatement(sql)) {
int index = 1;
for (Long parameter : parameters) {
statement.setLong(index++, parameter);
}
statement.setString(index++, target);
if (source != null) {
statement.setString(index, source);
}
int copiedRows = statement.executeUpdate();
log.info("Macro scene database copy: target=EquipShiftCapacity, rows={}", copiedRows);
} catch (SQLException ex) {
throw new IllegalStateException("Failed to copy EquipShiftCapacity in database", ex);
} finally {
DataSourceUtils.releaseConnection(connection, dataSource);
}
}
private String mapCte(String name, Map<Integer, Integer> idMap, List<Long> parameters) {
List<String> rows = new ArrayList<>();
for (Map.Entry<Integer, Integer> entry : idMap.entrySet()) {
if (entry.getKey() == null || entry.getValue() == null) {
continue;
}
rows.add("SELECT ? AS OLD_ID, ? AS NEW_ID FROM DUAL");
parameters.add(entry.getKey().longValue());
parameters.add(entry.getValue().longValue());
}
String emptySet = "SELECT CAST(NULL AS NUMBER) AS OLD_ID, CAST(NULL AS NUMBER) AS NEW_ID FROM DUAL WHERE 1 = 0";
return name + " (OLD_ID, NEW_ID) AS (" + (rows.isEmpty() ? emptySet : String.join(" UNION ALL ", rows)) + ")";
}
private <T> void copySimpleRows(String source, String target, BaseMapper<T> mapper,
Class<T> type, Consumer<T> mutator) {
List<T> copies = new ArrayList<>();
for (T row : loadRows(source, mapper)) {
T copy = copyOf(row, type);
if (mutator != null) {
mutator.accept(copy);
}
copies.add(copy);
}
log.info("Macro scene batch insert: target={}, rows={}", type.getSimpleName(), copies.size());
batchInsert(target, mapper, copies);
}
private <T> List<T> loadRows(String sceneId, BaseMapper<T> mapper) {
return MacroSceneContext.execute(sceneId, () -> {
QueryWrapper<T> wrapper = new QueryWrapper<>();
String deletedColumn = deletedColumn(mapper);
if (deletedColumn != null) {
wrapper.eq(deletedColumn, 0);
}
List<T> rows = new ArrayList<>(mapper.selectList(wrapper));
log.info("Macro scene source rows: mapper={}, sceneId={}, activeRows={}",
mapper.getClass().getSimpleName(), sceneId, rows.size());
return rows;
});
}
private String deletedColumn(BaseMapper<?> mapper) {
if (mapper == apsDemandOrderMapper || mapper == materialInfoMapper
|| mapper == routingsupportingMapper || mapper == routingDetailConnectMapper
|| mapper == routingDetailEquipMapper || mapper == stockMapper
|| mapper == materialPurchaseMapper || mapper == erpPurchaseOrderMapper
|| mapper == purchaseReceiptMapper || mapper == sjzPfWhStockMapper
|| mapper == planResourceMapper || mapper == equipinfoMapper) {
return "ISDELETED";
}
if (mapper == routingDetailMapper || mapper == equipShiftCapacityMapper) {
return "IS_DELETED";
}
return null;
}
private <T> void insert(String sceneId, BaseMapper<T> mapper, T row) {
MacroSceneContext.execute(sceneId, () -> mapper.insert(row));
}
private <T> void batchInsert(String sceneId, BaseMapper<T> mapper, List<T> rows) {
if (rows == null || rows.isEmpty()) {
return;
}
MacroSceneContext.execute(sceneId, () -> jdbcBatchInsert(sceneId, rows));
}
private <T> void jdbcSingleInsert(String sceneId, List<T> rows) {
Class<?> entityType = rows.get(0).getClass();
TableInfo tableInfo = TableInfoHelper.getTableInfo(entityType);
if (tableInfo == null) {
throw new IllegalStateException("No MyBatis-Plus table metadata for " + entityType.getName());
}
List<String> columns = new ArrayList<>();
List<String> properties = new ArrayList<>();
if (tableInfo.getKeyColumn() != null && tableInfo.getKeyProperty() != null) {
columns.add(tableInfo.getKeyColumn());
properties.add(tableInfo.getKeyProperty());
}
for (TableFieldInfo field : tableInfo.getFieldList()) {
if (!"MP_SCENE_ID".equalsIgnoreCase(field.getColumn())) {
columns.add(field.getColumn());
properties.add(field.getProperty());
}
}
columns.add("MP_SCENE_ID");
String sql = "INSERT INTO " + tableInfo.getTableName() + " (" + String.join(", ", columns)
+ ") VALUES (" + String.join(", ", java.util.Collections.nCopies(columns.size(), "?")) + ")";
Connection connection = DataSourceUtils.getConnection(dataSource);
try (PreparedStatement statement = connection.prepareStatement(sql)) {
List<Integer> jdbcTypes = loadJdbcTypes(connection, tableInfo.getTableName(), columns);
for (T row : rows) {
BeanWrapperImpl bean = new BeanWrapperImpl(row);
int index = 1;
for (String property : properties) {
bindValue(statement, index, bean.getPropertyValue(property), jdbcTypes.get(index - 1));
index++;
}
bindValue(statement, index, sceneId, jdbcTypes.get(index - 1));
statement.executeUpdate();
}
} catch (SQLException e) {
throw new IllegalStateException("Failed to insert " + tableInfo.getTableName(), e);
} finally {
DataSourceUtils.releaseConnection(connection, dataSource);
}
}
private <T> void jdbcBatchInsert(String sceneId, List<T> rows) {
Class<?> entityType = rows.get(0).getClass();
TableInfo tableInfo = TableInfoHelper.getTableInfo(entityType);
if (tableInfo == null) {
throw new IllegalStateException("No MyBatis-Plus table metadata for " + entityType.getName());
}
Connection connection = DataSourceUtils.getConnection(dataSource);
try {
Map<String, Integer> typeByColumn = loadJdbcTypeMap(connection, tableInfo.getTableName());
List<String> columns = new ArrayList<>();
List<String> properties = new ArrayList<>();
List<Integer> jdbcTypes = new ArrayList<>();
List<TableFieldInfo> largeTextFields = new ArrayList<>();
if (tableInfo.getKeyColumn() != null && tableInfo.getKeyProperty() != null) {
columns.add(tableInfo.getKeyColumn());
properties.add(tableInfo.getKeyProperty());
jdbcTypes.add(requiredJdbcType(typeByColumn, tableInfo.getTableName(), tableInfo.getKeyColumn()));
}
for (TableFieldInfo field : tableInfo.getFieldList()) {
if ("MP_SCENE_ID".equalsIgnoreCase(field.getColumn())) {
continue;
}
int jdbcType = requiredJdbcType(typeByColumn, tableInfo.getTableName(), field.getColumn());
if ((isLargeTextType(jdbcType) && containsNonNullValue(rows, field.getProperty()))
|| containsLongString(rows, field.getProperty())) {
largeTextFields.add(field);
} else {
columns.add(field.getColumn());
properties.add(field.getProperty());
jdbcTypes.add(jdbcType);
}
}
columns.add("MP_SCENE_ID");
jdbcTypes.add(requiredJdbcType(typeByColumn, tableInfo.getTableName(), "MP_SCENE_ID"));
String sql = "INSERT INTO " + tableInfo.getTableName() + " (" + String.join(", ", columns)
+ ") VALUES (" + String.join(", ",
java.util.Collections.nCopies(columns.size(), "?")) + ")";
try (PreparedStatement statement = connection.prepareStatement(sql)) {
int pending = 0;
for (T row : rows) {
BeanWrapperImpl bean = new BeanWrapperImpl(row);
int index = 1;
for (String property : properties) {
bindValue(statement, index, bean.getPropertyValue(property), jdbcTypes.get(index - 1));
index++;
}
bindValue(statement, index, sceneId, jdbcTypes.get(index - 1));
statement.addBatch();
if (++pending == JDBC_BATCH_SIZE) {
statement.executeBatch();
pending = 0;
}
}
if (pending > 0) {
statement.executeBatch();
}
}
updateLargeTextFields(connection, sceneId, tableInfo, rows, largeTextFields, typeByColumn);
} catch (SQLException e) {
throw new IllegalStateException("Failed to batch insert " + tableInfo.getTableName(), e);
} finally {
DataSourceUtils.releaseConnection(connection, dataSource);
}
}
private <T> void updateLargeTextFields(Connection connection, String sceneId, TableInfo tableInfo,
List<T> rows, List<TableFieldInfo> fields,
Map<String, Integer> typeByColumn) throws SQLException {
if (fields.isEmpty()) {
return;
}
if (tableInfo.getKeyColumn() == null || tableInfo.getKeyProperty() == null) {
throw new IllegalStateException("Large text update requires a primary key: "
+ tableInfo.getTableName());
}
int keyType = requiredJdbcType(typeByColumn, tableInfo.getTableName(), tableInfo.getKeyColumn());
int sceneType = requiredJdbcType(typeByColumn, tableInfo.getTableName(), "MP_SCENE_ID");
for (TableFieldInfo field : fields) {
int fieldType = requiredJdbcType(typeByColumn, tableInfo.getTableName(), field.getColumn());
String sql = "UPDATE " + tableInfo.getTableName() + " SET " + field.getColumn()
+ " = ? WHERE " + tableInfo.getKeyColumn() + " = ? AND MP_SCENE_ID = ?";
try (PreparedStatement statement = connection.prepareStatement(sql)) {
int pending = 0;
for (T row : rows) {
BeanWrapperImpl bean = new BeanWrapperImpl(row);
Object value = bean.getPropertyValue(field.getProperty());
if (value == null) {
continue;
}
bindValue(statement, 1, value, fieldType);
bindValue(statement, 2, bean.getPropertyValue(tableInfo.getKeyProperty()), keyType);
bindValue(statement, 3, sceneId, sceneType);
statement.addBatch();
if (++pending == JDBC_BATCH_SIZE) {
statement.executeBatch();
pending = 0;
}
}
if (pending > 0) {
statement.executeBatch();
}
}
}
}
private <T> boolean containsLongString(List<T> rows, String property) {
for (T row : rows) {
Object value = new BeanWrapperImpl(row).getPropertyValue(property);
if (value instanceof String && ((String) value).length() > 2000) {
return true;
}
}
return false;
}
private <T> boolean containsNonNullValue(List<T> rows, String property) {
for (T row : rows) {
if (new BeanWrapperImpl(row).getPropertyValue(property) != null) {
return true;
}
}
return false;
}
private List<Integer> loadJdbcTypes(Connection connection, String tableName, List<String> columns)
throws SQLException {
Map<String, Integer> typeByColumn = loadJdbcTypeMap(connection, tableName);
List<Integer> jdbcTypes = new ArrayList<>(columns.size());
for (String column : columns) {
jdbcTypes.add(requiredJdbcType(typeByColumn, tableName, column));
}
return jdbcTypes;
}
private Map<String, Integer> loadJdbcTypeMap(Connection connection, String tableName)
throws SQLException {
Map<String, Integer> typeByColumn = new HashMap<>();
DatabaseMetaData metaData = connection.getMetaData();
String schema = metaData.getUserName();
String metadataTableName = tableName;
int separator = tableName.indexOf('.');
if (separator > 0 && separator < tableName.length() - 1) {
schema = tableName.substring(0, separator);
metadataTableName = tableName.substring(separator + 1);
}
try (ResultSet resultSet = metaData.getColumns(null, schema,
metadataTableName.toUpperCase(Locale.ROOT), null)) {
while (resultSet.next()) {
typeByColumn.put(resultSet.getString("COLUMN_NAME").toUpperCase(Locale.ROOT),
resultSet.getInt("DATA_TYPE"));
}
}
return typeByColumn;
}
private int requiredJdbcType(Map<String, Integer> typeByColumn, String tableName, String column) {
Integer jdbcType = typeByColumn.get(column.toUpperCase(Locale.ROOT));
if (jdbcType == null) {
throw new IllegalStateException("Column metadata not found: " + tableName + "." + column);
}
return jdbcType;
}
private void jdbcBatchUpdateRoutingHierarchy(String sceneId, List<RoutingHeader> sourceRows,
Map<Integer, Integer> routingIds,
Map<Long, Long> detailIds) {
String sql = "UPDATE ROUTING_HEADER SET UP_DETAIL_ID = ? WHERE ID = ? AND MP_SCENE_ID = ?";
Connection connection = DataSourceUtils.getConnection(dataSource);
try (PreparedStatement statement = connection.prepareStatement(sql)) {
int pending = 0;
for (RoutingHeader row : sourceRows) {
if (row.getUpDetailId() == null) {
continue;
}
Integer copiedRoutingId = routingIds.get(row.getId());
Long copiedDetailId = detailIds.get(row.getUpDetailId().longValue());
if (copiedRoutingId == null || copiedDetailId == null) {
continue;
}
statement.setLong(1, copiedDetailId);
statement.setInt(2, copiedRoutingId);
statement.setString(3, sceneId);
statement.addBatch();
if (++pending == 500) {
statement.executeBatch();
pending = 0;
}
}
if (pending > 0) {
statement.executeBatch();
}
} catch (SQLException e) {
throw new IllegalStateException("Failed to update routing hierarchy", e);
} finally {
DataSourceUtils.releaseConnection(connection, dataSource);
}
}
private void jdbcClearRoutingHierarchyMarker(String sceneId) {
String sql = "UPDATE ROUTING_HEADER SET UP_DETAIL_ID = NULL WHERE MP_SCENE_ID = ?";
Connection connection = DataSourceUtils.getConnection(dataSource);
try (PreparedStatement statement = connection.prepareStatement(sql)) {
statement.setString(1, sceneId);
statement.executeUpdate();
} catch (SQLException e) {
throw new IllegalStateException("Failed to clear routing hierarchy marker", e);
} finally {
DataSourceUtils.releaseConnection(connection, dataSource);
}
}
private void bindValue(PreparedStatement statement, int index, Object value, int jdbcType)
throws SQLException {
if (value == null) {
statement.setNull(index, jdbcType);
} else if (value instanceof String && isNationalLargeTextType(jdbcType)) {
String text = (String) value;
statement.setNCharacterStream(index, new java.io.StringReader(text), text.length());
} else if (value instanceof String && isLargeTextType(jdbcType)) {
String text = (String) value;
statement.setCharacterStream(index, new java.io.StringReader(text), text.length());
} else if (value instanceof String && isNationalTextType(jdbcType)) {
statement.setNString(index, (String) value);
} else if (value instanceof String) {
statement.setString(index, (String) value);
} else if (value instanceof java.time.LocalDate) {
statement.setDate(index, java.sql.Date.valueOf((java.time.LocalDate) value));
} else if (value instanceof java.time.LocalDateTime) {
statement.setTimestamp(index, java.sql.Timestamp.valueOf((java.time.LocalDateTime) value));
} else if (value instanceof Boolean) {
statement.setInt(index, (Boolean) value ? 1 : 0);
} else {
statement.setObject(index, value);
}
}
private boolean isLargeTextType(int jdbcType) {
return jdbcType == Types.LONGVARCHAR || jdbcType == Types.LONGNVARCHAR
|| jdbcType == Types.CLOB || jdbcType == Types.NCLOB;
}
private boolean isNationalLargeTextType(int jdbcType) {
return jdbcType == Types.LONGNVARCHAR || jdbcType == Types.NCLOB;
}
private boolean isNationalTextType(int jdbcType) {
return jdbcType == Types.NCHAR || jdbcType == Types.NVARCHAR;
}
private <T> void update(String sceneId, BaseMapper<T> mapper, T row) {
MacroSceneContext.execute(sceneId, () -> mapper.updateById(row));
}
private <T> T copyOf(T source, Class<T> type) {
try {
T target = type.getDeclaredConstructor().newInstance();
BeanUtils.copyProperties(source, target, "mpSceneId");
return target;
} catch (ReflectiveOperationException e) {
throw new IllegalStateException("Cannot copy " + type.getSimpleName(), e);
}
}
private <K, V> V remap(K oldId, Map<K, V> idMap) {
if (oldId == null) {
return null;
}
V newId = idMap.get(oldId);
return newId == null ? castSameType(oldId) : newId;
}
@SuppressWarnings("unchecked")
private <K, V> V castSameType(K value) {
return (V) value;
}
private Long remapLong(Long oldId, Map<Integer, Integer> idMap) {
if (oldId == null) {
return null;
}
Integer newId = idMap.get(oldId.intValue());
return newId == null ? oldId : newId.longValue();
}
private static final class MaterialCopyResult {
private final Map<String, String> idMap;
private final List<MaterialReference> sourceRows;
private MaterialCopyResult(Map<String, String> idMap, List<MaterialReference> sourceRows) {
this.idMap = idMap;
this.sourceRows = sourceRows;
}
}
private static final class RoutingDetailCopyResult {
private final Map<Long, Long> idMap;
private final List<RoutingDetailReference> sourceRows;
private RoutingDetailCopyResult(Map<Long, Long> idMap, List<RoutingDetailReference> sourceRows) {
this.idMap = idMap;
this.sourceRows = sourceRows;
}
}
private static final class RoutingHeaderCopyResult {
private final Map<Integer, Integer> idMap;
private final List<RoutingHeaderReference> sourceRows;
private RoutingHeaderCopyResult(Map<Integer, Integer> idMap, List<RoutingHeaderReference> sourceRows) {
this.idMap = idMap;
this.sourceRows = sourceRows;
}
}
private static final class MaterialReference {
private final String id;
private final String linkMaterialId;
private final String matchBigproId;
private final String matchSmallproId;
private MaterialReference(String id, String linkMaterialId,
String matchBigproId, String matchSmallproId) {
this.id = id;
this.linkMaterialId = linkMaterialId;
this.matchBigproId = matchBigproId;
this.matchSmallproId = matchSmallproId;
}
}
private static final class RoutingHeaderReference {
private final Integer id;
private final Integer linkRoutingId;
private final Integer routingChangeHeaderId;
private final Integer upId;
private final Integer upDetailId;
private RoutingHeaderReference(Integer id, Integer linkRoutingId,
Integer routingChangeHeaderId, Integer upId,
Integer upDetailId) {
this.id = id;
this.linkRoutingId = linkRoutingId;
this.routingChangeHeaderId = routingChangeHeaderId;
this.upId = upId;
this.upDetailId = upDetailId;
}
}
private static final class RoutingDetailReference {
private final Long id;
private final Long preDetailId;
private RoutingDetailReference(Long id, Long preDetailId) {
this.id = id;
this.preDetailId = preDetailId;
}
}
private void requireGeneratedId(Object id, String table) {
if (id == null) {
throw new IllegalStateException("Database did not return generated ID for " + table);
}
}
private String requireText(String value, String field) {
String normalized = normalize(value);
if (normalized == null) {
throw new IllegalArgumentException(field + " cannot be blank");
}
return normalized;
}
private String normalize(String value) {
return value == null || value.trim().isEmpty() ? null : value.trim();
}
}
package com.aps.mapper;
import com.aps.entity.MacroSceneConfig;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
public interface MacroSceneConfigMapper extends BaseMapper<MacroSceneConfig> {
}
package com.aps.mapper;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface MacroSceneSequenceMapper {
@Select("SELECT SEQ_EQUIPINFOS.NEXTVAL FROM DUAL")
Integer nextEquipinfoId();
@Select("SELECT SEQ_EQUIPINFOS.NEXTVAL FROM DUAL CONNECT BY LEVEL <= #{count}")
List<Integer> nextEquipinfoIds(@Param("count") int count);
@Select("SELECT SEQ_PLAN_RESOURCES.NEXTVAL FROM DUAL")
Integer nextPlanResourceId();
@Select("SELECT SEQ_PLAN_RESOURCES.NEXTVAL FROM DUAL CONNECT BY LEVEL <= #{count}")
List<Integer> nextPlanResourceIds(@Param("count") int count);
@Select("SELECT SEQ_ROUTING_HEADERS.NEXTVAL FROM DUAL")
Integer nextRoutingHeaderId();
@Select("SELECT SEQ_ROUTING_HEADERS.NEXTVAL FROM DUAL CONNECT BY LEVEL <= #{count}")
List<Integer> nextRoutingHeaderIds(@Param("count") int count);
@Select("SELECT SEQ_ROUTING_DETAILS.NEXTVAL FROM DUAL CONNECT BY LEVEL <= #{count}")
List<Long> nextRoutingDetailIds(@Param("count") int count);
@Select("SELECT SEQ_ROUTING_DETAILS.NEXTVAL FROM DUAL")
Long nextRoutingDetailId();
@Select("SELECT SEQ_ROUTINGSUPPORTINGS.NEXTVAL FROM DUAL CONNECT BY LEVEL <= #{count}")
List<Long> nextRoutingsupportingIds(@Param("count") int count);
@Select("SELECT SEQ_ROUTINGSUPPORTINGS.NEXTVAL FROM DUAL")
Long nextRoutingsupportingId();
@Select("SELECT SEQ_ROUTING_DETAIL_CONNECTS.NEXTVAL FROM DUAL")
Long nextRoutingDetailConnectId();
@Select("SELECT SEQ_ROUTING_DETAIL_CONNECTS.NEXTVAL FROM DUAL CONNECT BY LEVEL <= #{count}")
List<Long> nextRoutingDetailConnectIds(@Param("count") int count);
@Select("SELECT SEQ_ROUTING_DETAIL_EQUIPS.NEXTVAL FROM DUAL")
Integer nextRoutingDetailEquipId();
@Select("SELECT SEQ_ROUTING_DETAIL_EQUIPS.NEXTVAL FROM DUAL CONNECT BY LEVEL <= #{count}")
List<Integer> nextRoutingDetailEquipIds(@Param("count") int count);
@Select("SELECT SEQ_STOCKS.NEXTVAL FROM DUAL")
Long nextStockId();
@Select("SELECT SEQ_STOCKS.NEXTVAL FROM DUAL CONNECT BY LEVEL <= #{count}")
List<Long> nextStockIds(@Param("count") int count);
@Select("SELECT SEQ_MATERIAL_PURCHASES.NEXTVAL FROM DUAL")
Long nextMaterialPurchaseId();
@Select("SELECT SEQ_MATERIAL_PURCHASES.NEXTVAL FROM DUAL CONNECT BY LEVEL <= #{count}")
List<Long> nextMaterialPurchaseIds(@Param("count") int count);
@Select("SELECT SEQ_ERP_PURCHASE_ORDERS.NEXTVAL FROM DUAL")
Long nextErpPurchaseOrderId();
@Select("SELECT SEQ_ERP_PURCHASE_ORDERS.NEXTVAL FROM DUAL CONNECT BY LEVEL <= #{count}")
List<Long> nextErpPurchaseOrderIds(@Param("count") int count);
@Select("SELECT SEQ_PURCHASE_RECEIPTS.NEXTVAL FROM DUAL")
Long nextPurchaseReceiptId();
@Select("SELECT SEQ_PURCHASE_RECEIPTS.NEXTVAL FROM DUAL CONNECT BY LEVEL <= #{count}")
List<Long> nextPurchaseReceiptIds(@Param("count") int count);
@Select("SELECT SEQ_SJZ_PF_WH_STOCKS.NEXTVAL FROM DUAL")
Long nextSjzPfWhStockId();
@Select("SELECT SEQ_SJZ_PF_WH_STOCKS.NEXTVAL FROM DUAL CONNECT BY LEVEL <= #{count}")
List<Long> nextSjzPfWhStockIds(@Param("count") int count);
@Select("SELECT SEQ_EQUIP_SHIFT_CAPACITYS.NEXTVAL FROM DUAL")
Long nextEquipShiftCapacityId();
@Select("SELECT SEQ_EQUIP_SHIFT_CAPACITYS.NEXTVAL FROM DUAL CONNECT BY LEVEL <= #{count}")
List<Long> nextEquipShiftCapacityIds(@Param("count") int count);
}
...@@ -814,6 +814,20 @@ public class LanuchServiceImpl implements LanuchService { ...@@ -814,6 +814,20 @@ public class LanuchServiceImpl implements LanuchService {
for (ProdLaunchOrder prodOrderMain : order) { for (ProdLaunchOrder prodOrderMain : order) {
RoutingHeader routingHeader = routingHeaderMap.get(prodOrderMain.getRoutingId()); RoutingHeader routingHeader = routingHeaderMap.get(prodOrderMain.getRoutingId());
if (routingHeader == null) {
RoutingHeader fallbackRouting = resolveValidRoutingHeader(prodOrderMain);
if (fallbackRouting != null) {
log.warn("routing id {} is deleted, fallback to valid routing id {} by code {}",
prodOrderMain.getRoutingId(), fallbackRouting.getId(), prodOrderMain.getRoutingCode());
prodOrderMain.setRoutingId(fallbackRouting.getId());
routingHeader = fallbackRouting;
routingHeaderMap.put(fallbackRouting.getId(), fallbackRouting);
routingDetailsByHeaderId.put(fallbackRouting.getId().longValue(),
getRoutingDetails(fallbackRouting.getId()));
routingDetailEquipByHeaderId.put(fallbackRouting.getId().longValue(),
getRoutingDetailEquip(fallbackRouting.getId(), fallbackRouting.getCode()));
}
}
if (routingHeader == null) { if (routingHeader == null) {
log.error("未找到对应工艺: {}", prodOrderMain.getRoutingId()); log.error("未找到对应工艺: {}", prodOrderMain.getRoutingId());
throw new RuntimeException("未找到对应工艺: " + prodOrderMain.getRoutingId()); throw new RuntimeException("未找到对应工艺: " + prodOrderMain.getRoutingId());
...@@ -828,8 +842,9 @@ public class LanuchServiceImpl implements LanuchService { ...@@ -828,8 +842,9 @@ public class LanuchServiceImpl implements LanuchService {
List<RoutingDetailEquip> routingDetailEquip = routingDetailEquipByHeaderId.getOrDefault( List<RoutingDetailEquip> routingDetailEquip = routingDetailEquipByHeaderId.getOrDefault(
routingHeader.getId().longValue(), routingHeader.getId().longValue(),
Collections.emptyList()); Collections.emptyList());
final RoutingHeader currentRoutingHeader = routingHeader;
List<ProdProcessExec> processExecList = routingDetails.stream() List<ProdProcessExec> processExecList = routingDetails.stream()
.map(detail -> createProcessExec(prodOrderMain, detail, sceneId, routingDetailEquip, routingHeader, equipTypeMap)) .map(detail -> createProcessExec(prodOrderMain, detail, sceneId, routingDetailEquip, currentRoutingHeader, equipTypeMap))
.collect(Collectors.toList()); .collect(Collectors.toList());
allProcessExecList.addAll(processExecList); allProcessExecList.addAll(processExecList);
...@@ -851,6 +866,21 @@ public class LanuchServiceImpl implements LanuchService { ...@@ -851,6 +866,21 @@ public class LanuchServiceImpl implements LanuchService {
log.info("完成{}个工单的工序转换",order.size()); log.info("完成{}个工单的工序转换",order.size());
} }
private RoutingHeader resolveValidRoutingHeader(ProdLaunchOrder order) {
if (order == null || order.getRoutingCode() == null || order.getRoutingCode().trim().isEmpty()) {
return null;
}
LambdaQueryWrapper<RoutingHeader> wrapper = new LambdaQueryWrapper<RoutingHeader>()
.eq(RoutingHeader::getCode, order.getRoutingCode().trim())
.eq(RoutingHeader::getIsDeleted, 0);
if (order.getMaterialId() != null && !order.getMaterialId().trim().isEmpty()) {
wrapper.eq(RoutingHeader::getMaterialId, order.getMaterialId().trim());
}
return routingHeaderMapper.selectList(wrapper).stream()
.max(Comparator.comparing(RoutingHeader::getId))
.orElse(null);
}
/** /**
◦ 转换工单到工序执行表 ◦ 转换工单到工序执行表
...@@ -1611,8 +1641,9 @@ public class LanuchServiceImpl implements LanuchService { ...@@ -1611,8 +1641,9 @@ public class LanuchServiceImpl implements LanuchService {
Map<Integer, PlanResource> planResourceMap = list.stream() Map<Integer, PlanResource> planResourceMap = list.stream()
.collect(Collectors.toMap(PlanResource::getId, Function.identity())); .collect(Collectors.toMap(PlanResource::getId, Function.identity()));
Map<Integer, PlanResource> planResourceByReferenceIdMap = list.stream() Map<Integer, PlanResource> planResourceByReferenceIdMap = list.stream()
.filter(pr -> pr.getReferenceId() != null) .filter(pr -> pr.getReferenceId() != null && "0".equals(pr.getType1()))
.collect(Collectors.toMap(PlanResource::getReferenceId, Function.identity())); .collect(Collectors.toMap(PlanResource::getReferenceId, Function.identity(),
(left, right) -> left.getId() <= right.getId() ? left : right));
// 转换equipinfo为Map // 转换equipinfo为Map
Map<Integer, Equipinfo> equipinfoMap = equipinfo.stream() Map<Integer, Equipinfo> equipinfoMap = equipinfo.stream()
......
package com.aps.service.schedule;
import com.aps.entity.ApsTimeConfig;
import com.aps.entity.Dispatch;
import com.aps.entity.Algorithm.Chromosome;
import com.aps.entity.Algorithm.GAScheduleResult;
import com.aps.entity.basic.Entry;
import com.aps.entity.basic.Order;
import com.aps.service.ApsTimeConfigService;
import com.aps.service.DispatchService;
import com.aps.service.plan.SceneService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Collectors;
/**
* 场景继承服务
* 负责在创建新场景时,从Dispatch表中读取冻结期内的工单,并继承到新场景
*/
@Service
@Slf4j
public class SceneInheritanceService {
@Autowired
private DispatchService dispatchService;
@Autowired
private ApsTimeConfigService apsTimeConfigService;
@Autowired
private SceneService sceneService;
/**
* 继承冻结期内的工单到新场景
* 从Dispatch表读取冻结期工单,转换为Chromosome格式并保存到文件
*
* @param newSceneId 新场景ID
* @param newBaseTime 新基准时间
* @return 是否成功继承
*/
public boolean inheritFrozenOrdersToChromosome(String newSceneId, LocalDateTime newBaseTime) {
log.info("开始继承冻结期内的工单到Chromosome,新场景ID: {}, 新基准时间: {}", newSceneId, newBaseTime);
try {
// 1. 获取时间配置
ApsTimeConfig timeConfig = apsTimeConfigService.getOne(new LambdaQueryWrapper<>());
if (timeConfig == null) {
log.warn("未找到ApsTimeConfig配置,无法继承冻结期工单");
return false;
}
LocalDateTime baseTime = timeConfig.getBaseTime();
if (baseTime == null) {
log.warn("ApsTimeConfig中baseTime为空,无法继承冻结期工单");
return false;
}
// 2. 计算冻结期范围
long freezeDays = timeConfig.getFreezeDate() != null ? timeConfig.getFreezeDate().longValue() : 0;
LocalDateTime freezeEndTime = baseTime.plusDays(freezeDays);
log.info("冻结期范围: {} 到 {}", baseTime, freezeEndTime);
// 3. 从Dispatch表查询冻结期内的所有工序
// 查询条件:beginTime >= baseTime AND beginTime <= freezeEndTime
List<Dispatch> frozenDispatches = dispatchService.lambdaQuery()
.ge(Dispatch::getBeginTime, baseTime)
.le(Dispatch::getBeginTime, freezeEndTime)
.eq(Dispatch::getIsDeleted, 0L)
.orderBy(true, true, Dispatch::getMesCode, Dispatch::getTaskSeq)
.list();
log.info("查询到冻结期内的工序数: {}", frozenDispatches.size());
if (frozenDispatches.isEmpty()) {
log.info("冻结期内没有工单需要继承");
return false;
}
// 4. 按订单分组,筛选出第一道工序在冻结期内的订单
Map<String, List<Dispatch>> orderDispatchMap = frozenDispatches.stream()
.collect(Collectors.groupingBy(Dispatch::getMesCode));
// 筛选:只保留第一道工序在冻结期内的订单的所有工序
List<Dispatch> validDispatches = new ArrayList<>();
for (Map.Entry<String, List<Dispatch>> entry : orderDispatchMap.entrySet()) {
List<Dispatch> orderDispatches = entry.getValue();
// 按taskSeq排序
orderDispatches.sort((d1, d2) -> {
Long seq1 = d1.getTaskSeq() != null ? d1.getTaskSeq() : 0L;
Long seq2 = d2.getTaskSeq() != null ? d2.getTaskSeq() : 0L;
return seq1.compareTo(seq2);
});
// 检查第一道工序是否在冻结期内
if (!orderDispatches.isEmpty()) {
Dispatch firstDispatch = orderDispatches.get(0);
if (firstDispatch.getBeginTime() != null &&
!firstDispatch.getBeginTime().isBefore(baseTime) &&
!firstDispatch.getBeginTime().isAfter(freezeEndTime)) {
// 第一道工序在冻结期内,保留该订单的所有工序
validDispatches.addAll(orderDispatches);
}
}
}
log.info("筛选后的冻结期工序数: {}", validDispatches.size());
if (validDispatches.isEmpty()) {
log.info("没有符合条件的冻结期工单");
return false;
}
// 5. 转换为Chromosome对象
Chromosome frozenChromosome = convertDispatchesToChromosome(validDispatches, newSceneId, newBaseTime, baseTime);
// 6. 保存到文件
boolean saved = sceneService.saveChromosomeToFile(frozenChromosome, newSceneId);
if (saved) {
log.info("成功继承 {} 个冻结期工序到新场景,涉及 {} 个订单",
validDispatches.size(), orderDispatchMap.size());
} else {
log.error("保存冻结期Chromosome文件失败");
}
return saved;
} catch (Exception e) {
log.error("继承冻结期工单时发生错误", e);
return false;
}
}
/**
* 将Dispatch列表转换为Chromosome对象
*
* @param dispatches Dispatch列表
* @param sceneId 场景ID
* @param newBaseTime 新基准时间
* @param oldBaseTime 旧基准时间
* @return Chromosome对象
*/
private Chromosome convertDispatchesToChromosome(List<Dispatch> dispatches, String sceneId,
LocalDateTime newBaseTime, LocalDateTime oldBaseTime) {
Chromosome chromosome = new Chromosome();
chromosome.setScenarioID(sceneId);
chromosome.setBaseTime(newBaseTime);
// 创建Result列表(GAScheduleResult)
CopyOnWriteArrayList<GAScheduleResult> results = new CopyOnWriteArrayList<>();
// 创建Entry列表
CopyOnWriteArrayList<Entry> entries = new CopyOnWriteArrayList<>();
// 创建Order列表(去重)
Map<String, Order> orderMap = new HashMap<>();
int entryId = 0;
for (Dispatch dispatch : dispatches) {
// 创建GAScheduleResult
GAScheduleResult result = new GAScheduleResult();
result.setOrderId(dispatch.getMesCode());
result.setExecId(dispatch.getRoutingDetailId() != null ? dispatch.getRoutingDetailId().toString() : "");
result.setQuantity(dispatch.getQuantity() != null ? dispatch.getQuantity() : 0);
// 计算相对时间(相对于新基准时间)
if (dispatch.getBeginTime() != null && dispatch.getEndTime() != null) {
long startSeconds = java.time.temporal.ChronoUnit.SECONDS.between(newBaseTime, dispatch.getBeginTime());
long endSeconds = java.time.temporal.ChronoUnit.SECONDS.between(newBaseTime, dispatch.getEndTime());
result.setStartTime((int) startSeconds);
result.setEndTime((int) endSeconds);
}
results.add(result);
// 创建Entry
Entry entry = new Entry();
entry.setId(entryId++);
entry.setOrderId(dispatch.getMesCode());
entry.setSceneId(sceneId);
entry.setExecId(dispatch.getRoutingDetailId() != null ? dispatch.getRoutingDetailId().toString() : "");
entry.setRoutingDetailId(dispatch.getRoutingDetailId());
entry.setRoutingDetailName(dispatch.getOpe());
entry.setTaskSeq(dispatch.getTaskSeq());
entry.setDepartmentId(dispatch.getShopid());
entry.setQuantity(dispatch.getQuantity() != null ? dispatch.getQuantity() : 0);
// 设置指定开始时间(保持原来的绝对时间)
entry.setDesignatedStartTime(dispatch.getBeginTime());
entries.add(entry);
// 创建Order(如果还没有)
if (!orderMap.containsKey(dispatch.getMesCode())) {
Order order = new Order();
order.setOrderId(dispatch.getMesCode());
order.setQuantity(dispatch.getQuantity() != null ? dispatch.getQuantity() : 0);
// 可以从Dispatch中获取更多信息填充Order
orderMap.put(dispatch.getMesCode(), order);
}
}
chromosome.setResult(results);
chromosome.setAllOperations(entries);
chromosome.setOrders(new CopyOnWriteArrayList<>(orderMap.values()));
log.info("转换完成:Result数={}, Entry数={}, Order数={}",
results.size(), entries.size(), orderMap.size());
return chromosome;
}
/**
* 从场景加载冻结期工单的Entry列表
* 用于在排产时获取冻结期工单
*
* @param sceneId 场景ID
* @return 冻结期工单的Entry列表
*/
public List<Entry> loadFrozenEntriesFromScene(String sceneId) {
try {
Chromosome chromosome = sceneService.loadChromosomeFromFile(sceneId);
if (chromosome == null || chromosome.getAllOperations() == null) {
log.info("场景 {} 没有冻结期工单", sceneId);
return new ArrayList<>();
}
List<Entry> frozenEntries = new ArrayList<>(chromosome.getAllOperations());
log.info("从场景 {} 加载了 {} 个冻结期工序", sceneId, frozenEntries.size());
return frozenEntries;
} catch (Exception e) {
log.error("加载冻结期工单失败,场景ID: {}", sceneId, e);
return new ArrayList<>();
}
}
/**
* 获取冻结期配置信息
*
* @return 冻结期配置
*/
public FrozenPeriodConfig getFrozenPeriodConfig() {
ApsTimeConfig timeConfig = apsTimeConfigService.getOne(new LambdaQueryWrapper<>());
if (timeConfig == null) {
return null;
}
FrozenPeriodConfig config = new FrozenPeriodConfig();
config.setBaseTime(timeConfig.getBaseTime());
config.setFreezeDate(timeConfig.getFreezeDate() != null ? timeConfig.getFreezeDate().longValue() : 0);
if (timeConfig.getBaseTime() != null && timeConfig.getFreezeDate() != null) {
config.setFreezeEndTime(timeConfig.getBaseTime().plusDays(timeConfig.getFreezeDate().longValue()));
}
return config;
}
/**
* 冻结期配置信息
*/
public static class FrozenPeriodConfig {
private LocalDateTime baseTime;
private long freezeDate;
private LocalDateTime freezeEndTime;
public LocalDateTime getBaseTime() {
return baseTime;
}
public void setBaseTime(LocalDateTime baseTime) {
this.baseTime = baseTime;
}
public long getFreezeDate() {
return freezeDate;
}
public void setFreezeDate(long freezeDate) {
this.freezeDate = freezeDate;
}
public LocalDateTime getFreezeEndTime() {
return freezeEndTime;
}
public void setFreezeEndTime(LocalDateTime freezeEndTime) {
this.freezeEndTime = freezeEndTime;
}
}
}
...@@ -57,10 +57,12 @@ ...@@ -57,10 +57,12 @@
<result column="ISDELETED" property="isdeleted" /> <result column="ISDELETED" property="isdeleted" />
<result column="DELETIONTIME" property="deletiontime" /> <result column="DELETIONTIME" property="deletiontime" />
<result column="DELETERUSERID" property="deleteruserid" /> <result column="DELETERUSERID" property="deleteruserid" />
<result column="MP_SCENE_ID" property="mpSceneId" />
</resultMap> </resultMap>
<!-- 通用查询结果列 --> <!-- 通用查询结果列 -->
<sql id="Base_Column_List"> <sql id="Base_Column_List">
MP_SCENE_ID,
ID, SOURCE_TYPE, EXP1, EXP2, EXP3, EXP4, EXP5, EXP6, ZONEID, ZONE, CUSTOMERID, CUSTOMER, CODE, MMID, MMCODE, MMNAME, UNIT, QUANTITY, MEETQUANTITY, MEETGOAL, MEETRATE, PRICE, DELIVERYTIME, STOCKID, STOCK, PRIORITRY, SERIES, SERIES_ID, SERIES_NAME, ISINSERT, ISLOCK, PART, DELAY, SETTLE, ISCONSUME, REMARK, UNITID, BEGINTIME, ENDTIME, ROUTINGID, ROUTINGNAME, ROUTINGCODE, ROUTINGSTATUS, STATUS, SCHEDULESTATUS, IS_SCHEDULED, CREATIONTIME, CREATORUSERID, LASTMODIFICATIONTIME, LASTMODIFIERUSERID, ISDELETED, DELETIONTIME, DELETERUSERID ID, SOURCE_TYPE, EXP1, EXP2, EXP3, EXP4, EXP5, EXP6, ZONEID, ZONE, CUSTOMERID, CUSTOMER, CODE, MMID, MMCODE, MMNAME, UNIT, QUANTITY, MEETQUANTITY, MEETGOAL, MEETRATE, PRICE, DELIVERYTIME, STOCKID, STOCK, PRIORITRY, SERIES, SERIES_ID, SERIES_NAME, ISINSERT, ISLOCK, PART, DELAY, SETTLE, ISCONSUME, REMARK, UNITID, BEGINTIME, ENDTIME, ROUTINGID, ROUTINGNAME, ROUTINGCODE, ROUTINGSTATUS, STATUS, SCHEDULESTATUS, IS_SCHEDULED, CREATIONTIME, CREATORUSERID, LASTMODIFICATIONTIME, LASTMODIFIERUSERID, ISDELETED, DELETIONTIME, DELETERUSERID
</sql> </sql>
......
...@@ -8,10 +8,12 @@ ...@@ -8,10 +8,12 @@
<result column="FREEZE_DATE" property="freezeDate" /> <result column="FREEZE_DATE" property="freezeDate" />
<result column="START_COUNT" property="startCount" /> <result column="START_COUNT" property="startCount" />
<result column="END_COUNT" property="endCount" /> <result column="END_COUNT" property="endCount" />
<result column="MP_SCENE_ID" property="mpSceneId" />
</resultMap> </resultMap>
<!-- 通用查询结果列 --> <!-- 通用查询结果列 -->
<sql id="Base_Column_List"> <sql id="Base_Column_List">
MP_SCENE_ID,
BASE_TIME, FREEZE_DATE, START_COUNT, END_COUNT BASE_TIME, FREEZE_DATE, START_COUNT, END_COUNT
</sql> </sql>
......
...@@ -61,11 +61,13 @@ ...@@ -61,11 +61,13 @@
<result column="min_duration_time" property="minDurationTime" /> <result column="min_duration_time" property="minDurationTime" />
<result column="max_duration_time" property="maxDurationTime" /> <result column="max_duration_time" property="maxDurationTime" />
<result column="jp_expecation_time" property="jpExpecationTime" /> <result column="jp_expecation_time" property="jpExpecationTime" />
<result column="MP_SCENE_ID" property="mpSceneId" />
</resultMap> </resultMap>
<!-- 通用查询结果列 --> <!-- 通用查询结果列 -->
<sql id="Base_Column_List"> <sql id="Base_Column_List">
MP_SCENE_ID,
id, shop_id, equip_id, equip_type, equip_name, equip_status, location, shaft_qty, capability_value, securityclassid, equip_ip, equipment_sc, operator_id, equip_version, equip_system, equip_pic, locationx, isimportant, filepath, equip_status_updatetime, hot, capacity, standard, usedepartment, installplace, mainnumber, manufacturer, enabledate, equip_winpwd, equip_winname, equip_port, status, property, creationtime, creatoruserid, lastmodificationtime, lastmodifieruserid, isdeleted, deleteruserid, deletiontime, head, runningstatus, system_info, ismdc, work_pattern, work_pattern_name, measure_unit_name, currency_type_name, capacity_type_name, measure_unit, currency_type, capacity_type, fequipid, min_time, min_duration_time, max_duration_time, jp_expecation_time id, shop_id, equip_id, equip_type, equip_name, equip_status, location, shaft_qty, capability_value, securityclassid, equip_ip, equipment_sc, operator_id, equip_version, equip_system, equip_pic, locationx, isimportant, filepath, equip_status_updatetime, hot, capacity, standard, usedepartment, installplace, mainnumber, manufacturer, enabledate, equip_winpwd, equip_winname, equip_port, status, property, creationtime, creatoruserid, lastmodificationtime, lastmodifieruserid, isdeleted, deleteruserid, deletiontime, head, runningstatus, system_info, ismdc, work_pattern, work_pattern_name, measure_unit_name, currency_type_name, capacity_type_name, measure_unit, currency_type, capacity_type, fequipid, min_time, min_duration_time, max_duration_time, jp_expecation_time
</sql> </sql>
</mapper> </mapper>
\ No newline at end of file
...@@ -29,10 +29,12 @@ ...@@ -29,10 +29,12 @@
<result column="MANUFACTURER_CODE" property="manufacturerCode" /> <result column="MANUFACTURER_CODE" property="manufacturerCode" />
<result column="MANUFACTURER_NAME" property="manufacturerName" /> <result column="MANUFACTURER_NAME" property="manufacturerName" />
<result column="ARRIVAL_DATE" property="arrivalDate" /> <result column="ARRIVAL_DATE" property="arrivalDate" />
<result column="MP_SCENE_ID" property="mpSceneId" />
</resultMap> </resultMap>
<!-- 通用查询结果列 --> <!-- 通用查询结果列 -->
<sql id="Base_Column_List"> <sql id="Base_Column_List">
MP_SCENE_ID,
ID, CREATIONTIME, CREATORUSERID, LASTMODIFICATIONTIME, LASTMODIFIERUSERID, ISDELETED, DELETIONTIME, DELETERUSERID, PURCHASE_NO, MATERIAL_ID, MATERIAL_CODE, MATERIAL_NAME, WAREHOUSE_ID, WAREHOUSE_CODE, WAREHOUSE_NAME, PURCHASE_QTY, UNIT_ID, UNIT_NAME, PURCHASE_CYCLE, INSPECTION_CYCLE, PURCHASE_STATUS, MANUFACTURER_ID, MANUFACTURER_CODE, MANUFACTURER_NAME, ARRIVAL_DATE ID, CREATIONTIME, CREATORUSERID, LASTMODIFICATIONTIME, LASTMODIFIERUSERID, ISDELETED, DELETIONTIME, DELETERUSERID, PURCHASE_NO, MATERIAL_ID, MATERIAL_CODE, MATERIAL_NAME, WAREHOUSE_ID, WAREHOUSE_CODE, WAREHOUSE_NAME, PURCHASE_QTY, UNIT_ID, UNIT_NAME, PURCHASE_CYCLE, INSPECTION_CYCLE, PURCHASE_STATUS, MANUFACTURER_ID, MANUFACTURER_CODE, MANUFACTURER_NAME, ARRIVAL_DATE
</sql> </sql>
......
...@@ -101,11 +101,13 @@ ...@@ -101,11 +101,13 @@
<result column="min_production" property="minProduction" /> <result column="min_production" property="minProduction" />
<result column="max_production" property="maxProduction" /> <result column="max_production" property="maxProduction" />
<result column="invisable" property="invisable" /> <result column="invisable" property="invisable" />
<result column="MP_SCENE_ID" property="mpSceneId" />
</resultMap> </resultMap>
<!-- 通用查询结果列 --> <!-- 通用查询结果列 -->
<sql id="Base_Column_List"> <sql id="Base_Column_List">
MP_SCENE_ID,
id, creationtime, creatoruserid, lastmodificationtime, lastmodifieruserid, isdeleted, deletiontime, deleteruserid, name, brand, specifications, batch, unit_price, min_num, tempcode, code, material_type_name, inspect_duration, purchase_duration, first_lot, tail_lot, standard_log, safe_stock_day, safe_stock_quantity, category_name, category_code, category_id, material_property, root_category_id, code_rule_id, code_rule_type, drawing, material_type, measure_unit, measure_unit_name, version, product_type, status, latest, iscreatesupplyrouting, iscreatecheckrouting, description, quintiq_ortems, isync, issend, measure_unit2, measure_unit_name2, linkmaterialid, measure_unit3, measure_unit_name3, zjltofjl1, supply_id, supply_name, supply_code, istrade, ser, iscommon, iscreatepoolrouting, variety, spec, category_id2, utility_material, special_product, bottle_type, bottle_type_str, max_inventory_day, max_inventory_quantity, min_inventory_day, min_inventory_quantity, minimum_supply, start_time, end_time, equip_id, bigpro, smallpro, isthree, is_minus, remark, match_bigpro_id, match_bigpro_code, match_smallpro_id, match_smallpro_code, full_name, is_include_store, is_average_four_week, stocksynctime, inventory_host_cost, beforeplanid, plannum, plancount, new_long_id, new_oldnumber, min_quantity, material_plan_type, min_production, max_production, invisable id, creationtime, creatoruserid, lastmodificationtime, lastmodifieruserid, isdeleted, deletiontime, deleteruserid, name, brand, specifications, batch, unit_price, min_num, tempcode, code, material_type_name, inspect_duration, purchase_duration, first_lot, tail_lot, standard_log, safe_stock_day, safe_stock_quantity, category_name, category_code, category_id, material_property, root_category_id, code_rule_id, code_rule_type, drawing, material_type, measure_unit, measure_unit_name, version, product_type, status, latest, iscreatesupplyrouting, iscreatecheckrouting, description, quintiq_ortems, isync, issend, measure_unit2, measure_unit_name2, linkmaterialid, measure_unit3, measure_unit_name3, zjltofjl1, supply_id, supply_name, supply_code, istrade, ser, iscommon, iscreatepoolrouting, variety, spec, category_id2, utility_material, special_product, bottle_type, bottle_type_str, max_inventory_day, max_inventory_quantity, min_inventory_day, min_inventory_quantity, minimum_supply, start_time, end_time, equip_id, bigpro, smallpro, isthree, is_minus, remark, match_bigpro_id, match_bigpro_code, match_smallpro_id, match_smallpro_code, full_name, is_include_store, is_average_four_week, stocksynctime, inventory_host_cost, beforeplanid, plannum, plancount, new_long_id, new_oldnumber, min_quantity, material_plan_type, min_production, max_production, invisable
</sql> </sql>
</mapper> </mapper>
\ No newline at end of file
...@@ -32,11 +32,13 @@ ...@@ -32,11 +32,13 @@
<result column="isstop" property="isstop" /> <result column="isstop" property="isstop" />
<result column="stoptime" property="stoptime" /> <result column="stoptime" property="stoptime" />
<result column="stopendtime" property="stopendtime" /> <result column="stopendtime" property="stopendtime" />
<result column="MP_SCENE_ID" property="mpSceneId" />
</resultMap> </resultMap>
<!-- 通用查询结果列 --> <!-- 通用查询结果列 -->
<sql id="Base_Column_List"> <sql id="Base_Column_List">
MP_SCENE_ID,
id, title, code, type1, reference_id, depart_id, depart_title, isimportant, capability_value, creationtime, creatoruserid, lastmodificationtime, lastmodifieruserid, isdeleted, deletiontime, deleteruserid, cal_id, cal_name, holiday_cal_id, holiday_cal_name, reference_code, equip_type_id, equip_type, work_sched_id, nrofunitsopen, isstop, stoptime, stopendtime id, title, code, type1, reference_id, depart_id, depart_title, isimportant, capability_value, creationtime, creatoruserid, lastmodificationtime, lastmodifieruserid, isdeleted, deletiontime, deleteruserid, cal_id, cal_name, holiday_cal_id, holiday_cal_name, reference_code, equip_type_id, equip_type, work_sched_id, nrofunitsopen, isstop, stoptime, stopendtime
</sql> </sql>
</mapper> </mapper>
\ No newline at end of file
...@@ -45,10 +45,12 @@ ...@@ -45,10 +45,12 @@
<result column="SCDWBM" property="scdwbm" /> <result column="SCDWBM" property="scdwbm" />
<result column="YLZD4" property="ylzd4" /> <result column="YLZD4" property="ylzd4" />
<result column="YLZD5" property="ylzd5" /> <result column="YLZD5" property="ylzd5" />
<result column="MP_SCENE_ID" property="mpSceneId" />
</resultMap> </resultMap>
<!-- 通用查询结果列 --> <!-- 通用查询结果列 -->
<sql id="Base_Column_List"> <sql id="Base_Column_List">
MP_SCENE_ID,
ID, CREATIONTIME, CREATORUSERID, LASTMODIFICATIONTIME, LASTMODIFIERUSERID, ISDELETED, DELETIONTIME, DELETERUSERID, WLBM, WLBB, ZJL_DW, ZJL_SL, FJL1_SL, SCPC, SCRQ, YXQZ, GYSBM, GYSMC, MBKF, JYBZ, ZT, SENDID, FJL1_DW, EXP1, EXP2, EXP3, EXP4, EXP5, EXP6, SUPPLYID, ORDERID, CHECKSTATUS, CHECKQUANTITY, RKSJ, RCBH, SCDW, MATERIALID, NOF, SCDWBM, YLZD4, YLZD5 ID, CREATIONTIME, CREATORUSERID, LASTMODIFICATIONTIME, LASTMODIFIERUSERID, ISDELETED, DELETIONTIME, DELETERUSERID, WLBM, WLBB, ZJL_DW, ZJL_SL, FJL1_SL, SCPC, SCRQ, YXQZ, GYSBM, GYSMC, MBKF, JYBZ, ZT, SENDID, FJL1_DW, EXP1, EXP2, EXP3, EXP4, EXP5, EXP6, SUPPLYID, ORDERID, CHECKSTATUS, CHECKQUANTITY, RKSJ, RCBH, SCDW, MATERIALID, NOF, SCDWBM, YLZD4, YLZD5
</sql> </sql>
......
...@@ -22,10 +22,12 @@ ...@@ -22,10 +22,12 @@
<result column="EXP4" property="exp4" /> <result column="EXP4" property="exp4" />
<result column="ROUTING_HEADER_ID" property="routingHeaderId" /> <result column="ROUTING_HEADER_ID" property="routingHeaderId" />
<result column="STR_ID" property="strId" /> <result column="STR_ID" property="strId" />
<result column="MP_SCENE_ID" property="mpSceneId" />
</resultMap> </resultMap>
<!-- 通用查询结果列 --> <!-- 通用查询结果列 -->
<sql id="Base_Column_List"> <sql id="Base_Column_List">
MP_SCENE_ID,
ID, CREATIONTIME, CREATORUSERID, LASTMODIFICATIONTIME, LASTMODIFIERUSERID, ISDELETED, DELETIONTIME, DELETERUSERID, DESTOPERATIONID, SOURCEOPERATIONID, DESTOPERATION, SOURCEOPERATION, EXP1, EXP2, EXP3, EXP4, ROUTING_HEADER_ID, STR_ID ID, CREATIONTIME, CREATORUSERID, LASTMODIFICATIONTIME, LASTMODIFIERUSERID, ISDELETED, DELETIONTIME, DELETERUSERID, DESTOPERATIONID, SOURCEOPERATIONID, DESTOPERATION, SOURCEOPERATION, EXP1, EXP2, EXP3, EXP4, ROUTING_HEADER_ID, STR_ID
</sql> </sql>
......
...@@ -28,11 +28,13 @@ ...@@ -28,11 +28,13 @@
<result column="routing_header_id" property="routingHeaderId" /> <result column="routing_header_id" property="routingHeaderId" />
<result column="one_batch_quantity" property="oneBatchQuantity" /> <result column="one_batch_quantity" property="oneBatchQuantity" />
<result column="str_id" property="strId" /> <result column="str_id" property="strId" />
<result column="MP_SCENE_ID" property="mpSceneId" />
</resultMap> </resultMap>
<!-- 通用查询结果列 --> <!-- 通用查询结果列 -->
<sql id="Base_Column_List"> <sql id="Base_Column_List">
MP_SCENE_ID,
id, creationtime, creatoruserid, lastmodificationtime, lastmodifieruserid, isdeleted, deletiontime, deleteruserid, type1, type_name, name, output_quantity, measure_unit, measure_unit_name, duration, exp1, exp2, exp3, exp4, routing_detail_id, equip_id, routing_header_id, one_batch_quantity, str_id id, creationtime, creatoruserid, lastmodificationtime, lastmodifieruserid, isdeleted, deletiontime, deleteruserid, type1, type_name, name, output_quantity, measure_unit, measure_unit_name, duration, exp1, exp2, exp3, exp4, routing_detail_id, equip_id, routing_header_id, one_batch_quantity, str_id
</sql> </sql>
</mapper> </mapper>
\ No newline at end of file
...@@ -54,11 +54,13 @@ ...@@ -54,11 +54,13 @@
<result column="SINGLE_OUT_UNIT_NAME" property="singleOutUnitName" /> <result column="SINGLE_OUT_UNIT_NAME" property="singleOutUnitName" />
<result column="CONNECT_UNIT_ID" property="connectUnitId" /> <result column="CONNECT_UNIT_ID" property="connectUnitId" />
<result column="CONNECT_UNIT_NAME" property="connectUnitName" /> <result column="CONNECT_UNIT_NAME" property="connectUnitName" />
<result column="MP_SCENE_ID" property="mpSceneId" />
</resultMap> </resultMap>
<!-- 通用查询结果列 --> <!-- 通用查询结果列 -->
<sql id="Base_Column_List"> <sql id="Base_Column_List">
MP_SCENE_ID,
ID, CREATION_TIME, CREATOR_USER_ID, LAST_MODIFICATION_TIME, LAST_MODIFIER_USER_ID, IS_DELETED, DELETER_USER_ID, DELETION_TIME, ROUTING_HEADER_ID, NAME, TASK_SEQ, RUNTIME, SETUP_TIME, EFFICIENCY_VALUE, SINGLE_OUT, IS_OUTSIDE, STATUS, REMARK, EXTEND, OUTSIDE_TIME, PERFORMANCE_HOURS, SCHEDULING_WORKING_HOURS, REAL_WORKING_HOURS, REAL_RUNTIME, PERFORMANCE_WORKING_HOURS, EQUIP_TYPE, EQUIP_TYPE_ID, CAN_INTERRUPT, PREVIOUS_START_TIME_BEGIN, CHANGE_LINE_TIME, PRE_DETAIL_ID, CONNECT_TYPE, CONNECT_PROPERTY, CONNECT_TYPE_NAME, CONNECT_PROPERTY_NAME, CONST_TIME,INCREMENT_QTY, BATCH_QTY, MIN_PRODUCTION_QTY, MAX_PRODUCTION_QTY, PRODUCTION_TAKT, PREPROCESSING_TIME, POSTPROCESSING_TIME, SPLIT_MIN_QTY, SPLIT_MAX_QTY, EQUIPMENT_CONNECTIVITY, SINGLE_OUT_UNIT_ID, SINGLE_OUT_UNIT_NAME, CONNECT_UNIT_ID, CONNECT_UNIT_NAME ID, CREATION_TIME, CREATOR_USER_ID, LAST_MODIFICATION_TIME, LAST_MODIFIER_USER_ID, IS_DELETED, DELETER_USER_ID, DELETION_TIME, ROUTING_HEADER_ID, NAME, TASK_SEQ, RUNTIME, SETUP_TIME, EFFICIENCY_VALUE, SINGLE_OUT, IS_OUTSIDE, STATUS, REMARK, EXTEND, OUTSIDE_TIME, PERFORMANCE_HOURS, SCHEDULING_WORKING_HOURS, REAL_WORKING_HOURS, REAL_RUNTIME, PERFORMANCE_WORKING_HOURS, EQUIP_TYPE, EQUIP_TYPE_ID, CAN_INTERRUPT, PREVIOUS_START_TIME_BEGIN, CHANGE_LINE_TIME, PRE_DETAIL_ID, CONNECT_TYPE, CONNECT_PROPERTY, CONNECT_TYPE_NAME, CONNECT_PROPERTY_NAME, CONST_TIME,INCREMENT_QTY, BATCH_QTY, MIN_PRODUCTION_QTY, MAX_PRODUCTION_QTY, PRODUCTION_TAKT, PREPROCESSING_TIME, POSTPROCESSING_TIME, SPLIT_MIN_QTY, SPLIT_MAX_QTY, EQUIPMENT_CONNECTIVITY, SINGLE_OUT_UNIT_ID, SINGLE_OUT_UNIT_NAME, CONNECT_UNIT_ID, CONNECT_UNIT_NAME
</sql> </sql>
......
...@@ -64,11 +64,13 @@ ...@@ -64,11 +64,13 @@
<result column="material_plan_type" property="materialPlanType" /> <result column="material_plan_type" property="materialPlanType" />
<result column="pcost" property="pcost" /> <result column="pcost" property="pcost" />
<result column="invisable" property="invisable" /> <result column="invisable" property="invisable" />
<result column="MP_SCENE_ID" property="mpSceneId" />
</resultMap> </resultMap>
<!-- 通用查询结果列 --> <!-- 通用查询结果列 -->
<sql id="Base_Column_List"> <sql id="Base_Column_List">
MP_SCENE_ID,
id, creation_time, creator_user_id, last_modification_time, last_modifier_user_id, deleter_user_id, deletion_time, class_id, unicode, name, code, product_id, version, author, department_id, is_main, up_id, up_detail_id, routing_type, status, approval_status, remark, approval_status_remark, audit_user_id1, audit_user_id2, is_deleted, platesnum, is_effect, versionnotes, phase, versionid, is_send_ppm, file_id, product_name, department_name, drawing_no, product_bom_id, routing_changeorder_code, routing_changeheader_id, audit_user_id3, material_id, output_quantity, routing_type_name, lead_time, quintiq_ortems, iscreatecheckrouting, iscreateoutbom, issupportingstore, isync, routing_usetype, linkroutingid, effect_end, year, effect_begin, cost, erptag, createoutbomtime, material_plan_type, pcost, invisable id, creation_time, creator_user_id, last_modification_time, last_modifier_user_id, deleter_user_id, deletion_time, class_id, unicode, name, code, product_id, version, author, department_id, is_main, up_id, up_detail_id, routing_type, status, approval_status, remark, approval_status_remark, audit_user_id1, audit_user_id2, is_deleted, platesnum, is_effect, versionnotes, phase, versionid, is_send_ppm, file_id, product_name, department_name, drawing_no, product_bom_id, routing_changeorder_code, routing_changeheader_id, audit_user_id3, material_id, output_quantity, routing_type_name, lead_time, quintiq_ortems, iscreatecheckrouting, iscreateoutbom, issupportingstore, isync, routing_usetype, linkroutingid, effect_end, year, effect_begin, cost, erptag, createoutbomtime, material_plan_type, pcost, invisable
</sql> </sql>
</mapper> </mapper>
\ No newline at end of file
...@@ -32,10 +32,12 @@ ...@@ -32,10 +32,12 @@
<result column="SPENT_MEASURE_UNIT_NAME" property="spentMeasureUnitName" /> <result column="SPENT_MEASURE_UNIT_NAME" property="spentMeasureUnitName" />
<result column="STR_ID" property="strId" /> <result column="STR_ID" property="strId" />
<result column="DRAW_NUM" property="drawNum" /> <result column="DRAW_NUM" property="drawNum" />
<result column="MP_SCENE_ID" property="mpSceneId" />
</resultMap> </resultMap>
<!-- 通用查询结果列 --> <!-- 通用查询结果列 -->
<sql id="Base_Column_List"> <sql id="Base_Column_List">
MP_SCENE_ID,
ID, CREATIONTIME, CREATORUSERID, LASTMODIFICATIONTIME, LASTMODIFIERUSERID, ISDELETED, DELETIONTIME, DELETERUSERID, ROUTING_HEADER_ID, ROUTING_DETAIL_ID, MATERIAL_ID, MATERIAL_TYPE, MATERIAL_NUMBER, MATERIAL_NAME, MATERIAL_VERSION, REMARK, STORE_ID, STORE_NAME, MAIN_QTY, SPENT_QTY, STR_MAIN_QTY, STR_SPENT_QTY, MAIN_MEASURE_UNIT, MAIN_MEASURE_UNIT_NAME, SPENT_MEASURE_UNIT, SPENT_MEASURE_UNIT_NAME, STR_ID, DRAW_NUM ID, CREATIONTIME, CREATORUSERID, LASTMODIFICATIONTIME, LASTMODIFIERUSERID, ISDELETED, DELETIONTIME, DELETERUSERID, ROUTING_HEADER_ID, ROUTING_DETAIL_ID, MATERIAL_ID, MATERIAL_TYPE, MATERIAL_NUMBER, MATERIAL_NAME, MATERIAL_VERSION, REMARK, STORE_ID, STORE_NAME, MAIN_QTY, SPENT_QTY, STR_MAIN_QTY, STR_SPENT_QTY, MAIN_MEASURE_UNIT, MAIN_MEASURE_UNIT_NAME, SPENT_MEASURE_UNIT, SPENT_MEASURE_UNIT_NAME, STR_ID, DRAW_NUM
</sql> </sql>
......
...@@ -38,10 +38,12 @@ ...@@ -38,10 +38,12 @@
<result column="IFSL" property="ifsl" /> <result column="IFSL" property="ifsl" />
<result column="CHECKSTATUS" property="checkstatus" /> <result column="CHECKSTATUS" property="checkstatus" />
<result column="CHECKQUANTITY" property="checkquantity" /> <result column="CHECKQUANTITY" property="checkquantity" />
<result column="MP_SCENE_ID" property="mpSceneId" />
</resultMap> </resultMap>
<!-- 通用查询结果列 --> <!-- 通用查询结果列 -->
<sql id="Base_Column_List"> <sql id="Base_Column_List">
MP_SCENE_ID,
ID, CREATIONTIME, CREATORUSERID, LASTMODIFICATIONTIME, LASTMODIFIERUSERID, ISDELETED, DELETIONTIME, DELETERUSERID, WLBM, WLBB, ZJL_DW, ZJL_SL, FJL1_SL, SCPC, SCRQ, YXQZ, MBKF, ZT, SENDID, FJL1_DW, EXP1, EXP2, EXP3, EXP4, EXP5, EXP6, RKSJ, MATERIALID, JKDWBM, ROUTINGID, JKDWMC, IFSL, CHECKSTATUS, CHECKQUANTITY ID, CREATIONTIME, CREATORUSERID, LASTMODIFICATIONTIME, LASTMODIFIERUSERID, ISDELETED, DELETIONTIME, DELETERUSERID, WLBM, WLBB, ZJL_DW, ZJL_SL, FJL1_SL, SCPC, SCRQ, YXQZ, MBKF, ZT, SENDID, FJL1_DW, EXP1, EXP2, EXP3, EXP4, EXP5, EXP6, RKSJ, MATERIALID, JKDWBM, ROUTINGID, JKDWMC, IFSL, CHECKSTATUS, CHECKQUANTITY
</sql> </sql>
......
...@@ -34,10 +34,12 @@ ...@@ -34,10 +34,12 @@
<result column="SUPPLIER_NAME" property="supplierName" /> <result column="SUPPLIER_NAME" property="supplierName" />
<result column="WAREHOUSING_UNIT_ID" property="warehousingUnitId" /> <result column="WAREHOUSING_UNIT_ID" property="warehousingUnitId" />
<result column="WAREHOUSING_UNIT_NAME" property="warehousingUnitName" /> <result column="WAREHOUSING_UNIT_NAME" property="warehousingUnitName" />
<result column="MP_SCENE_ID" property="mpSceneId" />
</resultMap> </resultMap>
<!-- 通用查询结果列 --> <!-- 通用查询结果列 -->
<sql id="Base_Column_List"> <sql id="Base_Column_List">
MP_SCENE_ID,
ID, CREATIONTIME, CREATORUSERID, LASTMODIFICATIONTIME, LASTMODIFIERUSERID, ISDELETED, DELETIONTIME, DELETERUSERID, MATERIAL_ID, MATERIAL_CODE, MATERIAL_NAME, MATERIAL_VERSION, STORE_ID, STORE_CODE, STORE_NAME, TOTAL, MEASURE_UNIT, TOTAL_LOCK, COST, PRODUCTION_DATE, EXPIRY_DATE, WAREHOUSING_DATE, BATCH, CURRENCY_ID, CURRENCY_NAME, SUPPLIER_ID, SUPPLIER_CODE, SUPPLIER_NAME, WAREHOUSING_UNIT_ID, WAREHOUSING_UNIT_NAME ID, CREATIONTIME, CREATORUSERID, LASTMODIFICATIONTIME, LASTMODIFIERUSERID, ISDELETED, DELETIONTIME, DELETERUSERID, MATERIAL_ID, MATERIAL_CODE, MATERIAL_NAME, MATERIAL_VERSION, STORE_ID, STORE_CODE, STORE_NAME, TOTAL, MEASURE_UNIT, TOTAL_LOCK, COST, PRODUCTION_DATE, EXPIRY_DATE, WAREHOUSING_DATE, BATCH, CURRENCY_ID, CURRENCY_NAME, SUPPLIER_ID, SUPPLIER_CODE, SUPPLIER_NAME, WAREHOUSING_UNIT_ID, WAREHOUSING_UNIT_NAME
</sql> </sql>
......
package com.aps.demo;
import com.aps.entity.Algorithm.Chromosome;
import com.aps.entity.Algorithm.GAScheduleResult;
import com.aps.entity.Algorithm.KpiMetrics;
import com.aps.entity.basic.Machine;
import com.aps.entity.basic.Order;
import com.aps.entity.basic.TimeSegment;
import com.aps.service.Algorithm.KpiCalculator;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.BeforeEach;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
/**
* KpiCalculator类的单元测试
*/
public class KpiCalculatorTest {
private Chromosome chromosome;
private KpiCalculator kpiCalculator;
private LocalDateTime baseTime;
@Test
void testWithRealJsonFile() throws IOException {
// 从本地文件读取实际的染色体数据
String jsonFilePath = "result/chromosome_result_BED5A2136A45439CA18F08B5B953E1E5.json";
String jsonString = new String(Files.readAllBytes(Paths.get(jsonFilePath)));
// 使用FastJSON解析JSON字符串为Chromosome对象
Chromosome realChromosome = JSON.parseObject(jsonString, Chromosome.class);
// 使用实际的染色体数据创建KPI计算器
KpiCalculator realKpiCalculator = new KpiCalculator(realChromosome);
// 执行KPI计算
realKpiCalculator.calculatekpi();
// 验证计算后的KPI指标
assertNotNull(realChromosome.getKpiMetrics());
assertTrue(realChromosome.getKpiMetrics().size() > 0);
System.out.println("从真实JSON文件加载并计算KPI完成,共生成 " + realChromosome.getKpiMetrics().size() + " 个指标");
for (KpiMetrics kpi : realChromosome.getKpiMetrics()) {
System.out.println(kpi.getName() + ": " + kpi.getValue() + " - " + kpi.getTip());
}
System.out.println("wuqianyiwan="+5000/10000);
// 验证特定的KPI指标是否存在
List<KpiMetrics> kpiList = realChromosome.getKpiMetrics();
assertTrue(kpiList.stream().anyMatch(k -> k.getName().equals("最大设备利用率")));
assertTrue(kpiList.stream().anyMatch(k -> k.getName().equals("最小设备利用率")));
assertTrue(kpiList.stream().anyMatch(k -> k.getName().equals("订单按时完成率")));
assertTrue(kpiList.stream().anyMatch(k -> k.getName().equals("最大延迟")));
}
}
\ No newline at end of file
package com.aps.macroplanner.scene;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.schema.Table;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
class MacroSceneDataPermissionHandlerTest {
private final MacroSceneDataPermissionHandler handler =
new MacroSceneDataPermissionHandler();
@AfterEach
void clearContext() {
MacroSceneContext.clear();
}
@Test
void baselineQueriesOnlySeeRowsWithoutMacroScene() {
Table table = new Table("MATERIAL_INFO");
Expression expression = handler.getSqlSegment(table, null, "test.select");
assertEquals("MATERIAL_INFO.MP_SCENE_ID IS NULL", expression.toString());
}
@Test
void macroQueriesUseSelectedSceneAndTableAlias() {
MacroSceneContext.setSceneId("scene-001");
Table table = new Table("ROUTING_HEADER");
table.setAlias(new net.sf.jsqlparser.expression.Alias("rh"));
Expression expression = handler.getSqlSegment(table, null, "test.select");
assertEquals("rh.MP_SCENE_ID = \u0027scene-001\u0027", expression.toString());
}
@Test
void unrelatedTablesAreNotFiltered() {
Expression expression = handler.getSqlSegment(
new Table("PROD_SCENE_CONFIG"), null, "test.select");
assertNull(expression);
}
}
package com.aps.macroplanner.scene;
import com.baomidou.mybatisplus.extension.plugins.inner.DataPermissionInterceptor;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertTrue;
class MacroSceneSqlInterceptorTest {
private final DataPermissionInterceptor interceptor =
new DataPermissionInterceptor(new MacroSceneDataPermissionHandler());
@AfterEach
void clearContext() {
MacroSceneContext.clear();
}
@Test
void injectsBaselineConditionIntoJoinQueries() {
String sql = interceptor.parserSingle(
"SELECT rh.ID FROM ROUTING_HEADER rh JOIN ROUTING_DETAIL rd "
+ "ON rd.ROUTING_HEADER_ID = rh.ID WHERE rh.STATUS = 1",
"test.select");
assertTrue(sql.contains("rh.MP_SCENE_ID IS NULL"));
assertTrue(sql.contains("rd.MP_SCENE_ID IS NULL"));
}
@Test
void injectsMacroConditionIntoUpdateAndDelete() {
MacroSceneContext.setSceneId("scene-002");
String updateSql = interceptor.parserSingle(
"UPDATE MATERIAL_INFO SET NAME = ? WHERE ID = ?", "test.update");
String deleteSql = interceptor.parserSingle(
"DELETE FROM STOCK WHERE ID = ?", "test.delete");
assertTrue(updateSql.contains("MATERIAL_INFO.MP_SCENE_ID = \u0027scene-002\u0027"));
assertTrue(deleteSql.contains("STOCK.MP_SCENE_ID = \u0027scene-002\u0027"));
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment