Commit 96f32069d680fba31dd5171c8a0bfc7ab20a184c

Authored by 徐烜
1 parent d525d33c

嘉定公交调度系统计划调度功能优化3

1、完成前置排班规则信息验证,编写相关测试用例
2、重要:修改Personnel.java实体,添加destroy字段
Showing 21 changed files with 1190 additions and 326 deletions
src/main/java/com/bsth/entity/Personnel.java
... ... @@ -7,17 +7,17 @@ import org.hibernate.annotations.Formula;
7 7 import javax.persistence.*;
8 8  
9 9 /**
10   - *
  10 + *
11 11 * @ClassName : Personnel(人员实体类)
12   - *
  12 + *
13 13 * @Author : bsth@lq
14   - *
  14 + *
15 15 * @Description : TODO(人员)
16   - *
  16 + *
17 17 * @Data :2016-04-27
18 18 *
19 19 * @Version 公交调度系统BS版 0.1
20   - *
  20 + *
21 21 */
22 22  
23 23 @Entity
... ... @@ -66,6 +66,10 @@ public class Personnel extends BEntity {
66 66 /** 身份证 */
67 67 private String card;
68 68  
  69 + /**
  70 + * 0为在职,1为停用
  71 + */
  72 + private Integer destroy;
69 73  
70 74 /** 备注 */
71 75 private String remark;
... ... @@ -254,4 +258,12 @@ public class Personnel extends BEntity {
254 258 public void setRemark(String remark) {
255 259 this.remark = remark;
256 260 }
  261 +
  262 + public Integer getDestroy() {
  263 + return destroy;
  264 + }
  265 +
  266 + public void setDestroy(Integer destroy) {
  267 + this.destroy = destroy;
  268 + }
257 269 }
... ...
src/main/java/com/bsth/service/schedule/plan/PlanConfig.java
... ... @@ -40,13 +40,25 @@ public class PlanConfig {
40 40 public KieBase kBaseValidateTimetable() {
41 41 KieBase kieBase = this.generateKieBase(
42 42 "kBaseValidateTimetable",
43   - new String[] {this.planConfigProperties.getValidateTimetable()}
44   - );
  43 + new String[] {this.planConfigProperties.getValidateTimetable()});
45 44 LOGGER.info("初始化 KieBase[{}]成功", "前置验证相关时刻表信息");
46 45 return kieBase;
47 46 }
48 47  
49 48 /**
  49 + * 验证规则kieBase。
  50 + * @return
  51 + */
  52 + @Bean(name = "kBaseValidateRule")
  53 + public KieBase kBaseValidateRule() {
  54 + KieBase kieBase = this.generateKieBase(
  55 + "kBaseValidateRule",
  56 + new String[] {this.planConfigProperties.getValidateRule()});
  57 + LOGGER.info("初始化 KieBase[{}]成功", "前置验证相关规则信息");
  58 + return kieBase;
  59 + }
  60 +
  61 + /**
50 62 * 生成KieBase。
51 63 * @param kBaseName kBase名字
52 64 * @param drlClasspaths 规则类路径
... ...
src/main/java/com/bsth/service/schedule/plan/PlanConfigProperties.java
... ... @@ -18,6 +18,10 @@ public class PlanConfigProperties {
18 18 @NotNull
19 19 private String validateTimetable;
20 20  
  21 + /** 排班前置验证规则(规则)*/
  22 + @NotNull
  23 + private String validateRule;
  24 +
21 25 public String getValidateTimetable() {
22 26 return validateTimetable;
23 27 }
... ... @@ -25,4 +29,12 @@ public class PlanConfigProperties {
25 29 public void setValidateTimetable(String validateTimetable) {
26 30 this.validateTimetable = validateTimetable;
27 31 }
  32 +
  33 + public String getValidateRule() {
  34 + return validateRule;
  35 + }
  36 +
  37 + public void setValidateRule(String validateRule) {
  38 + this.validateRule = validateRule;
  39 + }
28 40 }
... ...
src/main/java/com/bsth/service/schedule/plan/process/_1_validate/_1_timetable/PlanProcessValidateTimetableServiceDroolsImpl.java
... ... @@ -22,7 +22,7 @@ public class PlanProcessValidateTimetableServiceDroolsImpl implements PlanProces
22 22 private static final Logger LOGGER = LoggerFactory.getLogger(PlanProcessValidateTimetableServiceDroolsImpl.class);
23 23  
24 24 /** 验证时刻表drools kbase */
25   - private KieBase validateTimetableKBase;
  25 + private KieBase kBaseValidateTimetable;
26 26  
27 27 /** 使用的jdbc服务 */
28 28 private JdbcTemplate jdbcTemplate;
... ... @@ -48,7 +48,7 @@ public class PlanProcessValidateTimetableServiceDroolsImpl implements PlanProces
48 48  
49 49 // 构造drools session->载入数据->启动规则->计算->销毁session
50 50 // 创建session,内部配置的是stateful
51   - KieSession session = validateTimetableKBase.newKieSession();
  51 + KieSession session = kBaseValidateTimetable.newKieSession();
52 52 // 设置gloable对象,在drl中通过别名使用
53 53 session.setGlobal("LOGGER", LOGGER);
54 54  
... ... @@ -147,7 +147,7 @@ public class PlanProcessValidateTimetableServiceDroolsImpl implements PlanProces
147 147  
148 148 private PlanProcessValidateTimetableServiceDroolsImpl() {}
149 149 private PlanProcessValidateTimetableServiceDroolsImpl(Builder builder) {
150   - this.validateTimetableKBase = builder.validateTimetableKBase;
  150 + this.kBaseValidateTimetable = builder.kBaseValidateTimetable;
151 151 this.jdbcTemplate = builder.jdbcTemplate;
152 152  
153 153 }
... ... @@ -158,13 +158,13 @@ public class PlanProcessValidateTimetableServiceDroolsImpl implements PlanProces
158 158  
159 159 public static class Builder {
160 160 /** 验证时刻表drools kbase */
161   - private KieBase validateTimetableKBase;
  161 + private KieBase kBaseValidateTimetable;
162 162  
163 163 /** 使用的jdbc服务 */
164 164 private JdbcTemplate jdbcTemplate;
165 165  
166   - public Builder setValidateTimetableKBase(KieBase validateTimetableKBase) {
167   - this.validateTimetableKBase = validateTimetableKBase;
  166 + public Builder setkBaseValidateTimetable(KieBase kBaseValidateTimetable) {
  167 + this.kBaseValidateTimetable = kBaseValidateTimetable;
168 168 return this;
169 169 }
170 170  
... ...
src/main/java/com/bsth/service/schedule/plan/process/_1_validate/_2_rule/PlanProcessValidateRuleService.java 0 → 100644
  1 +package com.bsth.service.schedule.plan.process._1_validate._2_rule;
  2 +
  3 +import java.io.Serializable;
  4 +import java.util.ArrayList;
  5 +import java.util.Date;
  6 +import java.util.List;
  7 +
  8 +/**
  9 + * 验证规则服务。
  10 + */
  11 +public interface PlanProcessValidateRuleService {
  12 + /**
  13 + * 验证关联的规则信息。
  14 + * @param xlId 线路Id
  15 + * @param from 排班计划开始时间
  16 + * @param to 排班计划结束时间
  17 + * @return 验证输出
  18 + */
  19 + Result validateRule(Integer xlId, Date from, Date to);
  20 +
  21 + /**
  22 + * 排班,验证规则结果。
  23 + */
  24 + class Result implements Serializable {
  25 + /**
  26 + *
  27 + */
  28 + private static final long serialVersionUID = 1L;
  29 +
  30 + /** 线路id */
  31 + private Integer xlId;
  32 + /** 规则总数量 */
  33 + private Integer count;
  34 + /** 启用的规则数量 */
  35 + private Integer qyCount;
  36 + /** 启用规则中的错误数量 */
  37 + private Integer qyErrorCount;
  38 + /** 错误列表 */
  39 + private List<ErrorInfo> errorInfos = new ArrayList<>();
  40 +
  41 + public Integer getXlId() {
  42 + return xlId;
  43 + }
  44 +
  45 + public void setXlId(Integer xlId) {
  46 + this.xlId = xlId;
  47 + }
  48 +
  49 + public Integer getCount() {
  50 + return count;
  51 + }
  52 +
  53 + public void setCount(Integer count) {
  54 + this.count = count;
  55 + }
  56 +
  57 + public Integer getQyCount() {
  58 + return qyCount;
  59 + }
  60 +
  61 + public void setQyCount(Integer qyCount) {
  62 + this.qyCount = qyCount;
  63 + }
  64 +
  65 + public Integer getQyErrorCount() {
  66 + return qyErrorCount;
  67 + }
  68 +
  69 + public void setQyErrorCount(Integer qyErrorCount) {
  70 + this.qyErrorCount = qyErrorCount;
  71 + }
  72 +
  73 + public List<ErrorInfo> getErrorInfos() {
  74 + return errorInfos;
  75 + }
  76 +
  77 + public void setErrorInfos(List<ErrorInfo> errorInfos) {
  78 + this.errorInfos = errorInfos;
  79 + }
  80 + }
  81 +
  82 + class ErrorInfo implements Serializable {
  83 + /**
  84 + *
  85 + */
  86 + private static final long serialVersionUID = 1L;
  87 +
  88 + /** 规则id */
  89 + private Long ruleId;
  90 + /** 车辆自编号 */
  91 + private String clZbh;
  92 + /** 启用日期 */
  93 + private Date qyrq;
  94 + /** 错误描述 */
  95 + private List<String> errorDescList = new ArrayList<>();
  96 +
  97 + public Long getRuleId() {
  98 + return ruleId;
  99 + }
  100 +
  101 + public void setRuleId(Long ruleId) {
  102 + this.ruleId = ruleId;
  103 + }
  104 +
  105 + public String getClZbh() {
  106 + return clZbh;
  107 + }
  108 +
  109 + public void setClZbh(String clZbh) {
  110 + this.clZbh = clZbh;
  111 + }
  112 +
  113 + public Date getQyrq() {
  114 + return qyrq;
  115 + }
  116 +
  117 + public void setQyrq(Date qyrq) {
  118 + this.qyrq = qyrq;
  119 + }
  120 +
  121 + public List<String> getErrorDescList() {
  122 + return errorDescList;
  123 + }
  124 +
  125 + public void setErrorDescList(List<String> errorDescList) {
  126 + this.errorDescList = errorDescList;
  127 + }
  128 + }
  129 +
  130 +
  131 +}
... ...
src/main/java/com/bsth/service/schedule/plan/process/_1_validate/_2_rule/PlanProcessValidateRuleServiceDroolsImpl.java 0 → 100644
  1 +package com.bsth.service.schedule.plan.process._1_validate._2_rule;
  2 +
  3 +import com.bsth.service.schedule.plan.process._1_validate._2_rule.drools.*;
  4 +import org.joda.time.DateTime;
  5 +import org.kie.api.KieBase;
  6 +import org.kie.api.runtime.KieSession;
  7 +import org.slf4j.Logger;
  8 +import org.slf4j.LoggerFactory;
  9 +import org.springframework.jdbc.core.JdbcTemplate;
  10 +import org.springframework.jdbc.core.RowMapper;
  11 +
  12 +import java.sql.ResultSet;
  13 +import java.sql.SQLException;
  14 +import java.util.Date;
  15 +import java.util.List;
  16 +
  17 +/**
  18 + * 验证规则服务。
  19 + */
  20 +public class PlanProcessValidateRuleServiceDroolsImpl implements PlanProcessValidateRuleService {
  21 + /** 日志记录器 */
  22 + private static final Logger LOGGER = LoggerFactory.getLogger(PlanProcessValidateRuleServiceDroolsImpl.class);
  23 +
  24 + private KieBase kBaseValidateRule;
  25 +
  26 + private JdbcTemplate jdbcTemplate;
  27 +
  28 + /** 车辆配置信息查询SQL */
  29 + private static final String CC_QUERY_SQL =
  30 + "select ccinfo.xl, ccinfo.cl, car.inside_code, ccinfo.id " +
  31 + "from bsth_c_s_ccinfo ccinfo left join bsth_c_cars car on ccinfo.cl = car.id " +
  32 + "where ccinfo.is_cancel = 0 and ccinfo.xl = ? ";
  33 + /** 路牌配置信息查询SQL */
  34 + private static final String LP_QUERY_SQL =
  35 + "select id, lp_name, xl " +
  36 + "from bsth_c_s_gbi " +
  37 + "where is_cancel = 0 and xl = ? ";
  38 + /** 人员配置信息查询SQL */
  39 + private static final String EC_QUERY_SQL =
  40 + "select ec.id as id, xl, dbbm, " +
  41 + "ec.jsy as jsy_id, p1.personnel_name as jsy_name, p1.job_codeori as jsy_code, p1.destroy as jsy_destroy, " +
  42 + "ec.spy as spy_id, p2.personnel_name as spy_name, p2.job_codeori as spy_code, p2.destroy as spy_destroy " +
  43 + "from bsth_c_s_ecinfo ec left join bsth_c_personnel p1 on ec.jsy = p1.id left join bsth_c_personnel p2 on ec.spy = p2.id " +
  44 + "where is_cancel = 0 and xl = ? ";
  45 +
  46 + /** 规则信息查询SQL */
  47 + private static final String FLAT_RULE_SQUERY_SQL =
  48 + "select rule.id, cc.xl, rule.qyrq, car_config_info, " +
  49 + "lp_ids, lp_names, lp_start, " +
  50 + "ry_config_ids, ry_dbbms, ry_start, " +
  51 + "car.inside_code " +
  52 + "from bsth_c_s_sr1_flat rule left join bsth_c_s_ccinfo cc on rule.car_config_info = cc.id left join bsth_c_cars car on cc.cl = car.id " +
  53 + "where cc.xl = ? ";
  54 +
  55 + @Override
  56 + public Result validateRule(Integer xlId, Date from, Date to) {
  57 + LOGGER.info("KieBase[{}],线路id={},开始日期={},结束日期={} 开始验证",
  58 + "前置验证相关规则", xlId, from, to);
  59 +
  60 + // 构造drools session->载入数据->启动规则->计算->销毁session
  61 + // 创建session,内部配置的是stateful
  62 + KieSession session = kBaseValidateRule.newKieSession();
  63 + // 设置gloable对象,在drl中通过别名使用
  64 + session.setGlobal("LOGGER", LOGGER);
  65 +
  66 + Result rs = new Result(); // 输出gloable对象
  67 + session.setGlobal("rs", rs);
  68 +
  69 + // 载入参数数据
  70 + KBaseValidateRule_Fact_CalcuParam calcuParam = KBaseValidateRule_Fact_CalcuParam.builder()
  71 + .fromDate(new DateTime(from))
  72 + .toDate(new DateTime(to))
  73 + .xlId(xlId)
  74 + .build();
  75 + session.insert(calcuParam);
  76 +
  77 + // 载入车辆配置信息
  78 + List<KBaseValidateRule_Fact_VehicleConfig> vehicleConfigDtoList = jdbcTemplate.query(
  79 + CC_QUERY_SQL,
  80 + new Object[]{xlId},
  81 + new RowMapper<KBaseValidateRule_Fact_VehicleConfig>() {
  82 + @Override
  83 + public KBaseValidateRule_Fact_VehicleConfig mapRow(ResultSet rs, int rowNum) throws SQLException {
  84 + return KBaseValidateRule_Fact_VehicleConfig.builder()
  85 + .id(rs.getLong("id"))
  86 + .cl(KBaseValidateRule_Fact_Car.builder()
  87 + .id(rs.getInt("cl"))
  88 + .insideCode(rs.getString("inside_code"))
  89 + .build())
  90 + .xl(KBaseValidateRule_Fact_Line.builder()
  91 + .id(rs.getInt("xl"))
  92 + .build())
  93 + .build();
  94 + }
  95 + });
  96 + for (KBaseValidateRule_Fact_VehicleConfig vehicleConfigDto : vehicleConfigDtoList) {
  97 + session.insert(vehicleConfigDto);
  98 + }
  99 +
  100 + // 载入路牌配置信息
  101 + List<KBaseValidateRule_Fact_LpConfig> lpConfigDtoList = jdbcTemplate.query(
  102 + LP_QUERY_SQL,
  103 + new Object[]{xlId},
  104 + new RowMapper<KBaseValidateRule_Fact_LpConfig>() {
  105 + @Override
  106 + public KBaseValidateRule_Fact_LpConfig mapRow(ResultSet rs, int rowNum) throws SQLException {
  107 + return KBaseValidateRule_Fact_LpConfig.builder()
  108 + .id(rs.getLong("id"))
  109 + .lpName(rs.getString("lp_name"))
  110 + .xl(KBaseValidateRule_Fact_Line.builder()
  111 + .id(rs.getInt("xl"))
  112 + .build())
  113 + .build();
  114 + }
  115 + });
  116 + for (KBaseValidateRule_Fact_LpConfig lpConfigDto : lpConfigDtoList) {
  117 + session.insert(lpConfigDto);
  118 + }
  119 +
  120 + // 载入人员配置信息
  121 + List<KBaseValidateRule_Fact_EmployeeConfig> employeeConfigDtoList = jdbcTemplate.query(
  122 + EC_QUERY_SQL,
  123 + new Object[]{xlId},
  124 + new RowMapper<KBaseValidateRule_Fact_EmployeeConfig>() {
  125 + @Override
  126 + public KBaseValidateRule_Fact_EmployeeConfig mapRow(ResultSet rs, int rowNum) throws SQLException {
  127 + return KBaseValidateRule_Fact_EmployeeConfig.builder()
  128 + .id(rs.getLong("id"))
  129 + .dbbm(rs.getString("dbbm"))
  130 + .xl(KBaseValidateRule_Fact_Line.builder()
  131 + .id(rs.getInt("xl"))
  132 + .build())
  133 + .jsy(rs.getString("jsy_name") == null ? null :
  134 + KBaseValidateRule_Fact_Personnel.builder()
  135 + .id(rs.getInt("jsy_id"))
  136 + .personnelName(rs.getString("jsy_name"))
  137 + .jobCodeori(rs.getString("jsy_code"))
  138 + .destroy(rs.getInt("jsy_destroy"))
  139 + .build())
  140 + .spy(rs.getString("spy_name") == null ? null :
  141 + KBaseValidateRule_Fact_Personnel.builder()
  142 + .id(rs.getInt("spy_id"))
  143 + .personnelName(rs.getString("spy_name"))
  144 + .jobCodeori(rs.getString("spy_code"))
  145 + .destroy(rs.getInt("spy_destroy"))
  146 + .build())
  147 + .build();
  148 + }
  149 + });
  150 + for (KBaseValidateRule_Fact_EmployeeConfig employeeConfigDto : employeeConfigDtoList) {
  151 + session.insert(employeeConfigDto);
  152 + }
  153 +
  154 + // 载入规则信息
  155 + List<KBaseValidateRule_Fact_Rule> flatRuleDtoList = jdbcTemplate.query(
  156 + FLAT_RULE_SQUERY_SQL,
  157 + new Object[]{xlId},
  158 + new RowMapper<KBaseValidateRule_Fact_Rule>() {
  159 + @Override
  160 + public KBaseValidateRule_Fact_Rule mapRow(ResultSet rs, int rowNum) throws SQLException {
  161 + return KBaseValidateRule_Fact_Rule.builder()
  162 + .id(rs.getLong("id"))
  163 + .qyrq(rs.getDate("qyrq"))
  164 + .lpIds(rs.getString("lp_ids"))
  165 + .lpNames(rs.getString("lp_names"))
  166 + .lpStart(rs.getInt("lp_start"))
  167 + .ryConfigIds(rs.getString("ry_config_ids"))
  168 + .ryDbbms(rs.getString("ry_dbbms"))
  169 + .ryStart(rs.getInt("ry_start"))
  170 + .carConfigInfo(KBaseValidateRule_Fact_VehicleConfig.builder()
  171 + .id(rs.getLong("car_config_info"))
  172 + .cl(KBaseValidateRule_Fact_Car.builder()
  173 + .insideCode(rs.getString("inside_code"))
  174 + .build())
  175 + .build())
  176 + .xl(KBaseValidateRule_Fact_Line.builder()
  177 + .id(rs.getInt("xl"))
  178 + .build())
  179 + .build();
  180 + }
  181 + });
  182 + for (KBaseValidateRule_Fact_Rule flatRuleDto : flatRuleDtoList) {
  183 + session.insert(flatRuleDto);
  184 + }
  185 +
  186 + // 执行rule
  187 + session.fireAllRules();
  188 +
  189 + // 执行完毕销毁,有日志的也要关闭
  190 + session.dispose();
  191 +
  192 +
  193 + LOGGER.info("KieBase[{}],线路id={},开始日期={},结束日期={} 完成验证",
  194 + "前置验证相关规则", xlId, from, to);
  195 +
  196 + return rs;
  197 + }
  198 +
  199 + private PlanProcessValidateRuleServiceDroolsImpl() {}
  200 + private PlanProcessValidateRuleServiceDroolsImpl(Builder builder) {
  201 + this.jdbcTemplate = builder.jdbcTemplate;
  202 + this.kBaseValidateRule = builder.kBaseValidateRule;
  203 + }
  204 + public static Builder getBuilder() {
  205 + return new Builder();
  206 + }
  207 +
  208 + public static class Builder {
  209 + private KieBase kBaseValidateRule;
  210 +
  211 + private JdbcTemplate jdbcTemplate;
  212 +
  213 + public Builder setkBaseValidateRule(KieBase kBaseValidateRule) {
  214 + this.kBaseValidateRule = kBaseValidateRule;
  215 + return this;
  216 + }
  217 +
  218 + public Builder setJdbcTemplate(JdbcTemplate jdbcTemplate) {
  219 + this.jdbcTemplate = jdbcTemplate;
  220 + return this;
  221 + }
  222 +
  223 + public PlanProcessValidateRuleServiceDroolsImpl build() {
  224 + return new PlanProcessValidateRuleServiceDroolsImpl(this);
  225 + }
  226 + }
  227 +}
... ...
src/main/java/com/bsth/service/schedule/plan/process/_1_validate/_2_rule/drools/KBaseValidateRule_Fact_CalcuParam.java 0 → 100644
  1 +package com.bsth.service.schedule.plan.process._1_validate._2_rule.drools;
  2 +
  3 +import lombok.AllArgsConstructor;
  4 +import lombok.Builder;
  5 +import lombok.Data;
  6 +import org.joda.time.DateTime;
  7 +
  8 +/**
  9 + * drools验证规则使用的参数fact对象。
  10 + */
  11 +@Data
  12 +@Builder
  13 +@AllArgsConstructor
  14 +public class KBaseValidateRule_Fact_CalcuParam {
  15 + /** 线路Id */
  16 + private Integer xlId;
  17 +
  18 + /** 计划开始计算日期 */
  19 + private DateTime fromDate;
  20 + /** 计划结束计算日期 */
  21 + private DateTime toDate;
  22 +}
... ...
src/main/java/com/bsth/service/schedule/plan/process/_1_validate/_2_rule/drools/KBaseValidateRule_Fact_Car.java 0 → 100644
  1 +package com.bsth.service.schedule.plan.process._1_validate._2_rule.drools;
  2 +
  3 +import lombok.AllArgsConstructor;
  4 +import lombok.Builder;
  5 +import lombok.Data;
  6 +
  7 +/**
  8 + * drools验证规则使用的车辆fact对象。
  9 + */
  10 +@Data
  11 +@Builder
  12 +@AllArgsConstructor
  13 +public class KBaseValidateRule_Fact_Car {
  14 + /** 主键Id */
  15 + private Integer id;
  16 + /** 自编号/内部编号 */
  17 + private String insideCode;
  18 +}
... ...
src/main/java/com/bsth/service/schedule/plan/process/_1_validate/_2_rule/drools/KBaseValidateRule_Fact_EmployeeConfig.java 0 → 100644
  1 +package com.bsth.service.schedule.plan.process._1_validate._2_rule.drools;
  2 +
  3 +import lombok.AllArgsConstructor;
  4 +import lombok.Builder;
  5 +import lombok.Data;
  6 +
  7 +/**
  8 + * drools验证规则使用的人员配置fact对象。
  9 + */
  10 +@Data
  11 +@Builder
  12 +@AllArgsConstructor
  13 +public class KBaseValidateRule_Fact_EmployeeConfig {
  14 + /** 主键Id */
  15 + private Long id;
  16 + /** 搭班编码(是售票员和驾驶员搭配时使用,同一条线路搭班编码不能重复) */
  17 + private String dbbm;
  18 + /** 线路关联 */
  19 + private KBaseValidateRule_Fact_Line xl;
  20 + /** 人员关联(驾驶员) */
  21 + private KBaseValidateRule_Fact_Personnel jsy;
  22 + /** 人员关联(售票员) */
  23 + private KBaseValidateRule_Fact_Personnel spy;
  24 +}
... ...
src/main/java/com/bsth/service/schedule/plan/process/_1_validate/_2_rule/drools/KBaseValidateRule_Fact_Line.java 0 → 100644
  1 +package com.bsth.service.schedule.plan.process._1_validate._2_rule.drools;
  2 +
  3 +import lombok.AllArgsConstructor;
  4 +import lombok.Builder;
  5 +import lombok.Data;
  6 +
  7 +/**
  8 + * drools验证规则使用的线路fact对象。
  9 + */
  10 +@Data
  11 +@Builder
  12 +@AllArgsConstructor
  13 +public class KBaseValidateRule_Fact_Line {
  14 + /** 主键id */
  15 + private Integer id;
  16 +}
... ...
src/main/java/com/bsth/service/schedule/plan/process/_1_validate/_2_rule/drools/KBaseValidateRule_Fact_LpConfig.java 0 → 100644
  1 +package com.bsth.service.schedule.plan.process._1_validate._2_rule.drools;
  2 +
  3 +import lombok.AllArgsConstructor;
  4 +import lombok.Builder;
  5 +import lombok.Data;
  6 +
  7 +/**
  8 + * drools验证规则使用的路牌配置fact对象。
  9 + */
  10 +@Data
  11 +@Builder
  12 +@AllArgsConstructor
  13 +public class KBaseValidateRule_Fact_LpConfig {
  14 + /** 主键Id */
  15 + private Long id;
  16 + /** 路牌名称 */
  17 + private String lpName;
  18 + /** 线路 */
  19 + private KBaseValidateRule_Fact_Line xl;
  20 +}
... ...
src/main/java/com/bsth/service/schedule/plan/process/_1_validate/_2_rule/drools/KBaseValidateRule_Fact_Personnel.java 0 → 100644
  1 +package com.bsth.service.schedule.plan.process._1_validate._2_rule.drools;
  2 +
  3 +import lombok.AllArgsConstructor;
  4 +import lombok.Builder;
  5 +import lombok.Data;
  6 +
  7 +/**
  8 + * drools验证规则使用的人员fact对象。
  9 + */
  10 +@Data
  11 +@Builder
  12 +@AllArgsConstructor
  13 +public class KBaseValidateRule_Fact_Personnel {
  14 + /** 主键Id */
  15 + private Integer id;
  16 + /** 姓名 */
  17 + private String personnelName;
  18 + /** 工号 */
  19 + private String jobCodeori;
  20 + /**
  21 + * 0为在职,1为停用
  22 + */
  23 + private Integer destroy;
  24 +}
... ...
src/main/java/com/bsth/service/schedule/plan/process/_1_validate/_2_rule/drools/KBaseValidateRule_Fact_Rule.java 0 → 100644
  1 +package com.bsth.service.schedule.plan.process._1_validate._2_rule.drools;
  2 +
  3 +import lombok.AllArgsConstructor;
  4 +import lombok.Builder;
  5 +import lombok.Data;
  6 +
  7 +import java.util.Date;
  8 +
  9 +/**
  10 + * drools验证规则使用的规则fact对象。
  11 + */
  12 +@Data
  13 +@Builder
  14 +@AllArgsConstructor
  15 +public class KBaseValidateRule_Fact_Rule {
  16 + /** 主键Id */
  17 + private Long id;
  18 + /** 启用日期 */
  19 + private Date qyrq;
  20 + /** 对应的路牌ids(用逗号隔开) */
  21 + private String lpIds;
  22 + /** 路牌名称s(用逗号隔开) */
  23 + private String lpNames;
  24 + /** 起始路牌(从0开始) */
  25 + private Integer lpStart;
  26 + /** 对应的人员配置ids(用逗号隔开,如果分班,就先-隔开再逗号隔开) */
  27 + private String ryConfigIds;
  28 + /** 人员搭班编码s(用逗号隔开,如果分班,就先-隔开再逗号隔开) */
  29 + private String ryDbbms;
  30 + /** 起始人员(从0开始) */
  31 + private Integer ryStart;
  32 +
  33 + /** 关联车辆配置 */
  34 + private KBaseValidateRule_Fact_VehicleConfig carConfigInfo;
  35 + /** 关联线路 */
  36 + private KBaseValidateRule_Fact_Line xl;
  37 +}
... ...
src/main/java/com/bsth/service/schedule/plan/process/_1_validate/_2_rule/drools/KBaseValidateRule_Fact_VehicleConfig.java 0 → 100644
  1 +package com.bsth.service.schedule.plan.process._1_validate._2_rule.drools;
  2 +
  3 +import lombok.AllArgsConstructor;
  4 +import lombok.Builder;
  5 +import lombok.Data;
  6 +
  7 +/**
  8 + * drools验证规则使用的车辆配置fact对象。
  9 + */
  10 +@Data
  11 +@Builder
  12 +@AllArgsConstructor
  13 +public class KBaseValidateRule_Fact_VehicleConfig {
  14 + /** 主健Id */
  15 + private Long id;
  16 + /** 线路 */
  17 + private KBaseValidateRule_Fact_Line xl;
  18 + /** 车辆 */
  19 + private KBaseValidateRule_Fact_Car cl;
  20 +}
... ...
src/main/java/com/bsth/service/schedule/plan/process/_1_validate/_2_rule/drools/KBaseValidateRule_Function_ErrorInfo.java 0 → 100644
  1 +package com.bsth.service.schedule.plan.process._1_validate._2_rule.drools;
  2 +
  3 +import com.bsth.service.schedule.plan.process._1_validate._2_rule.PlanProcessValidateRuleService.ErrorInfo;
  4 +import org.apache.commons.lang3.StringUtils;
  5 +import org.apache.commons.lang3.math.NumberUtils;
  6 +import org.kie.api.runtime.rule.AccumulateFunction;
  7 +
  8 +import java.io.IOException;
  9 +import java.io.ObjectInput;
  10 +import java.io.ObjectOutput;
  11 +import java.io.Serializable;
  12 +import java.util.HashMap;
  13 +import java.util.List;
  14 +import java.util.Map;
  15 +
  16 +/**
  17 + * drools验证规则用的函数(计算规则错误)
  18 + */
  19 +public class KBaseValidateRule_Function_ErrorInfo implements AccumulateFunction {
  20 + @Override
  21 + public void writeExternal(ObjectOutput out) throws IOException {}
  22 +
  23 + @Override
  24 + public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {}
  25 +
  26 + /**
  27 + * 规则包装类。
  28 + */
  29 + public static class WrapRule {
  30 + /** 规则 */
  31 + public KBaseValidateRule_Fact_Rule rule;
  32 + /** 对应线路的车辆配置,key=车辆配置Id */
  33 + public Map<Long, KBaseValidateRule_Fact_VehicleConfig> ccInfos;
  34 + /** 对应线路的人员配置,key=人员配置Id */
  35 + public Map<Long, KBaseValidateRule_Fact_EmployeeConfig> ecInfos;
  36 + /** 对应线路的路牌配置,key=路牌配置Id */
  37 + public Map<Long, KBaseValidateRule_Fact_LpConfig> lpInfos;
  38 +
  39 + public WrapRule() {
  40 + this.ccInfos = new HashMap<>();
  41 + this.ecInfos = new HashMap<>();
  42 + this.lpInfos = new HashMap<>();
  43 + }
  44 +
  45 + public void addCcInfoList(List<KBaseValidateRule_Fact_VehicleConfig> list) {
  46 + for (KBaseValidateRule_Fact_VehicleConfig config : list) {
  47 + this.ccInfos.put(config.getId(), config);
  48 + }
  49 + }
  50 + public void addEcInfoList(List<KBaseValidateRule_Fact_EmployeeConfig> list) {
  51 + for (KBaseValidateRule_Fact_EmployeeConfig config : list) {
  52 + this.ecInfos.put(config.getId(), config);
  53 + }
  54 + }
  55 + public void addLpInfoList(List<KBaseValidateRule_Fact_LpConfig> list) {
  56 + for (KBaseValidateRule_Fact_LpConfig config : list) {
  57 + this.lpInfos.put(config.getId(), config);
  58 + }
  59 + }
  60 +
  61 + }
  62 +
  63 + protected static class ErrorInfoContext implements Serializable {
  64 + /** 规则错误数量 */
  65 + private Integer errorCount = 0;
  66 + /** 错误Map, key=规则Id */
  67 + private Map<Long, ErrorInfo> errorInfoMap = new HashMap<>();
  68 +
  69 + void remove(Long ruleId) {
  70 + if (ruleId != null) {
  71 + this.errorInfoMap.remove(ruleId);
  72 + this.errorCount --;
  73 + }
  74 + }
  75 +
  76 + void add(WrapRule wrapRule) {
  77 + ErrorInfo errorInfo = new ErrorInfo();
  78 + errorInfo.setRuleId(wrapRule.rule.getId());
  79 + errorInfo.setQyrq(wrapRule.rule.getQyrq());
  80 +
  81 + // 1、车辆配置验证
  82 + String clZbh = wrapRule.rule.getCarConfigInfo().getCl().getInsideCode();
  83 + Long ccInfoId = wrapRule.rule.getCarConfigInfo().getId();
  84 + errorInfo.setClZbh(clZbh);
  85 +
  86 + if (StringUtils.isNotEmpty(clZbh)) { // 自编号不能为空
  87 + if (wrapRule.ccInfos.get(ccInfoId) == null) { // 车辆配置不在当前线路上
  88 + errorInfo.getErrorDescList().add("车辆配置不在当前线路,请重新编辑保存!");
  89 + }
  90 + } else {
  91 + errorInfo.getErrorDescList().add("自编号不能为空,请重新编辑保存!");
  92 + }
  93 +
  94 + // 2、路牌id,路牌名字,路牌起始索引验证
  95 + String lpIds_str = wrapRule.rule.getLpIds();
  96 + String lpNames_str = wrapRule.rule.getLpNames();
  97 + Integer lpStart = wrapRule.rule.getLpStart();
  98 +
  99 + if (StringUtils.isNotEmpty(lpIds_str) &&
  100 + StringUtils.isNotEmpty(lpNames_str)) { // 冗余的路牌id和路牌名字都不能为空
  101 + String[] lpIds = lpIds_str.split(",");
  102 + String[] lpNames = lpNames_str.split(",");
  103 + if (lpIds.length == lpNames.length) { // 路牌id和路牌名字个数一致
  104 + for (int i = 0; i < lpIds.length; i++) {
  105 + if (!NumberUtils.isDigits(lpIds[i])) { // 冗余路牌id必须是数字
  106 + errorInfo.getErrorDescList().add("冗余路牌id必须是数字,请重新编辑保存!");
  107 + break;
  108 + }
  109 +
  110 + KBaseValidateRule_Fact_LpConfig lpInfo = wrapRule.lpInfos.get(NumberUtils.toLong(lpIds[i]));
  111 + if (lpInfo == null) { // 路牌不在当前线路上
  112 + errorInfo.getErrorDescList().add("路牌不在当前线路上,请重新编辑保存!");
  113 + } else {
  114 + if (StringUtils.isEmpty(lpNames[i]) ||
  115 + !(lpNames[i].equals(lpInfo.getLpName()))) { // 路牌id和路牌名字不对应
  116 + errorInfo.getErrorDescList().add("路牌id和路牌名字不对应,请重新编辑保存!");
  117 + break;
  118 + }
  119 + }
  120 + }
  121 +
  122 + if (lpStart < 1 || lpStart > lpIds.length) { // 路牌起始索引溢出
  123 + errorInfo.getErrorDescList().add("路牌起始索引溢出,请重新编辑保存!");
  124 + }
  125 + } else {
  126 + errorInfo.getErrorDescList().add("路牌id和路牌名字个数不一致,请重新编辑保存!");
  127 + }
  128 + } else {
  129 + errorInfo.getErrorDescList().add("冗余的路牌id和路牌名字都不能为空,请重新编辑保存!");
  130 + }
  131 +
  132 + // 3、人员配置,搭班编码,人员起始索引验证,配置人员停用验证
  133 + String ecIds_str = wrapRule.rule.getRyConfigIds();
  134 + String ecDbbms_str = wrapRule.rule.getRyDbbms();
  135 + Integer ryStart = wrapRule.rule.getRyStart();
  136 +
  137 + if (StringUtils.isNotEmpty(ecIds_str) &&
  138 + StringUtils.isNotEmpty(ecDbbms_str)) { // 冗余的人员配置id和人员搭班编码都不能为空
  139 + String[] ecIds = ecIds_str.split(",");
  140 + String[] ecDbbms = ecDbbms_str.split(",");
  141 + if (ecIds.length == ecDbbms.length) { // 人员配置id和搭班编码个数一致
  142 + for (int i = 0; i < ecIds.length; i++) {
  143 + if (ecIds[i].contains("-")) { // 分班标识
  144 + String[] fb_ecIds = ecIds[i].split("-");
  145 + String[] fb_ecDbbms = ecDbbms[i].split("-");
  146 + if (fb_ecIds.length != 2 || fb_ecDbbms.length != 2) { // 只能早晚分班
  147 + errorInfo.getErrorDescList().add("只能早晚分班,请重新编辑保存!");
  148 + break;
  149 + } else {
  150 + KBaseValidateRule_Fact_EmployeeConfig fb_ecInfo1 =
  151 + wrapRule.ecInfos.get(NumberUtils.toLong(fb_ecIds[0]));
  152 + KBaseValidateRule_Fact_EmployeeConfig fb_ecInfo2 =
  153 + wrapRule.ecInfos.get(NumberUtils.toLong(fb_ecIds[1]));
  154 + if (fb_ecInfo1 == null || fb_ecInfo2 == null) { // 分班的人员配置不在当前线路
  155 + errorInfo.getErrorDescList().add("分班的人员配置不在当前线路,请重新编辑保存!");
  156 + break;
  157 + } else {
  158 + if (StringUtils.isEmpty(fb_ecDbbms[0]) ||
  159 + StringUtils.isEmpty(fb_ecDbbms[1]) ||
  160 + !(fb_ecDbbms[0].equals(fb_ecInfo1.getDbbm())) ||
  161 + !(fb_ecDbbms[1].equals(fb_ecInfo2.getDbbm()))) { // 分班人员配置id和搭班编码不对应
  162 + errorInfo.getErrorDescList().add("分班人员配置id和搭班编码不对应,请重新编辑保存!");
  163 + break;
  164 + }
  165 + }
  166 +
  167 + // 验证fb_ecInfo1
  168 + String dbbm = fb_ecInfo1.getDbbm();
  169 + KBaseValidateRule_Fact_Personnel jsy = fb_ecInfo1.getJsy();
  170 + KBaseValidateRule_Fact_Personnel spy = fb_ecInfo1.getSpy();
  171 + if (jsy != null && jsy.getDestroy() != null && jsy.getDestroy() == 1) {
  172 + errorInfo.getErrorDescList().add(
  173 + String.format("搭班编码=%s,驾驶员=%s,工号=%s,人员已经停用!",
  174 + dbbm, jsy.getPersonnelName(), jsy.getJobCodeori()));
  175 + break;
  176 + }
  177 + if (spy != null && spy.getDestroy() != null && spy.getDestroy() == 1) {
  178 + errorInfo.getErrorDescList().add(
  179 + String.format("搭班编码=%s,售票员=%s,工号=%s,人员已经停用!",
  180 + dbbm, spy.getPersonnelName(), spy.getJobCodeori()));
  181 + break;
  182 + }
  183 + // 验证fb_ecInfo2
  184 + dbbm = fb_ecInfo2.getDbbm();
  185 + jsy = fb_ecInfo2.getJsy();
  186 + spy = fb_ecInfo2.getSpy();
  187 + if (jsy != null && jsy.getDestroy() != null && jsy.getDestroy() == 1) {
  188 + errorInfo.getErrorDescList().add(
  189 + String.format("搭班编码=%s,驾驶员=%s,工号=%s,人员已经停用!",
  190 + dbbm, jsy.getPersonnelName(), jsy.getJobCodeori()));
  191 + break;
  192 + }
  193 + if (spy != null && spy.getDestroy() != null && spy.getDestroy() == 1) {
  194 + errorInfo.getErrorDescList().add(
  195 + String.format("搭班编码=%s,售票员=%s,工号=%s,人员已经停用!",
  196 + dbbm, spy.getPersonnelName(), spy.getJobCodeori()));
  197 + break;
  198 + }
  199 + }
  200 +
  201 + } else {
  202 + if (!NumberUtils.isDigits(ecIds[i])) { // 冗余的人员配置id必须是数字
  203 + errorInfo.getErrorDescList().add("冗余的人员配置id必须是数字,请重新编辑保存!");
  204 + break;
  205 + }
  206 +
  207 + KBaseValidateRule_Fact_EmployeeConfig ecInfo = wrapRule.ecInfos.get(NumberUtils.toLong(ecIds[i]));
  208 + if (ecInfo == null) { // 人员配置不在当前线路
  209 + errorInfo.getErrorDescList().add("人员配置不在当前线路,请重新编辑保存!");
  210 + break;
  211 + } else {
  212 + if (StringUtils.isEmpty(ecDbbms[i]) ||
  213 + !(ecDbbms[i].equals(ecInfo.getDbbm()))) { // 人员配置id和搭班编码不对应
  214 + errorInfo.getErrorDescList().add("人员配置id和搭班编码不对应,请重新编辑保存!");
  215 + break;
  216 + }
  217 + }
  218 +
  219 + // 验证ecInfo
  220 + String dbbm = ecInfo.getDbbm();
  221 + KBaseValidateRule_Fact_Personnel jsy = ecInfo.getJsy();
  222 + KBaseValidateRule_Fact_Personnel spy = ecInfo.getSpy();
  223 + if (jsy != null && jsy.getDestroy() != null && jsy.getDestroy() == 1) {
  224 + errorInfo.getErrorDescList().add(
  225 + String.format("搭班编码=%s,驾驶员=%s,工号=%s,人员已经停用!",
  226 + dbbm, jsy.getPersonnelName(), jsy.getJobCodeori()));
  227 + break;
  228 + }
  229 + if (spy != null && spy.getDestroy() != null && spy.getDestroy() == 1) {
  230 + errorInfo.getErrorDescList().add(
  231 + String.format("搭班编码=%s,售票员=%s,工号=%s,人员已经停用!",
  232 + dbbm, spy.getPersonnelName(), spy.getJobCodeori()));
  233 + break;
  234 + }
  235 + }
  236 + }
  237 +
  238 + if (ryStart < 1 || ryStart > ecIds.length) { // 人员起始索引溢出
  239 + errorInfo.getErrorDescList().add("人员起始索引溢出,请重新编辑保存!");
  240 + }
  241 + } else {
  242 + errorInfo.getErrorDescList().add("人员配置id和搭班编码个数不一致,请重新编辑保存!");
  243 + }
  244 + }
  245 +
  246 + if (errorInfo.getErrorDescList().size() > 0) {
  247 + this.errorCount ++;
  248 + this.errorInfoMap.put(wrapRule.rule.getId(), errorInfo);
  249 + }
  250 + }
  251 +
  252 + ErrorInfoContext() {
  253 + this.errorCount = 0;
  254 + this.errorInfoMap = new HashMap<>();
  255 + }
  256 +
  257 + Map<Long, ErrorInfo> result() {
  258 + return this.errorInfoMap;
  259 + }
  260 +
  261 + }
  262 +
  263 + @Override
  264 + public Serializable createContext() {
  265 + return new ErrorInfoContext();
  266 + }
  267 +
  268 + @Override
  269 + public void init(Serializable context) throws Exception {}
  270 +
  271 + @Override
  272 + public void accumulate(Serializable context, Object value) {
  273 + ErrorInfoContext errorInfoContext = (ErrorInfoContext) context;
  274 + WrapRule wrapRule = (WrapRule) value;
  275 + errorInfoContext.add(wrapRule);
  276 + }
  277 +
  278 + @Override
  279 + public boolean supportsReverse() {
  280 + return true;
  281 + }
  282 +
  283 + @Override
  284 + public void reverse(Serializable context, Object value) throws Exception {
  285 + ErrorInfoContext errorInfoContext = (ErrorInfoContext) context;
  286 + WrapRule wrapRule = (WrapRule) value;
  287 + errorInfoContext.remove(wrapRule.rule.getId());
  288 + }
  289 +
  290 + @Override
  291 + public Class<?> getResultType() {
  292 + return Map.class;
  293 + }
  294 +
  295 + @Override
  296 + public Object getResult(Serializable context) throws Exception {
  297 + ErrorInfoContext errorInfoContext = (ErrorInfoContext) context;
  298 + return errorInfoContext.result();
  299 + }
  300 +}
... ...
src/main/resources/drools/KBase/validate/rule/KBase_validate_rule.drl 0 → 100644
  1 +package com.bsth.service.schedule.plan.process._1_validate._2_rule.drools;
  2 +
  3 +import org.joda.time.*;
  4 +import org.joda.time.format.DateTimeFormat;
  5 +import java.util.*;
  6 +import org.apache.commons.lang3.StringUtils;
  7 +
  8 +import com.bsth.service.schedule.plan.process._1_validate._2_rule.drools.KBaseValidateRule_Fact_CalcuParam;
  9 +
  10 +import com.bsth.service.schedule.plan.process._1_validate._2_rule.drools.KBaseValidateRule_Fact_VehicleConfig;
  11 +import com.bsth.service.schedule.plan.process._1_validate._2_rule.drools.KBaseValidateRule_Fact_EmployeeConfig;
  12 +import com.bsth.service.schedule.plan.process._1_validate._2_rule.drools.KBaseValidateRule_Fact_LpConfig;
  13 +import com.bsth.service.schedule.plan.process._1_validate._2_rule.drools.KBaseValidateRule_Fact_Rule;
  14 +
  15 +import com.bsth.service.schedule.plan.process._1_validate._2_rule.PlanProcessValidateRuleService.Result;
  16 +import com.bsth.service.schedule.plan.process._1_validate._2_rule.drools.KBaseValidateRule_Function_ErrorInfo.WrapRule;
  17 +
  18 +import org.slf4j.Logger;
  19 +
  20 +// 全局日志类(使用PlanPreValidateServiceImpl里定义的LOGGER)
  21 +global Logger LOGGER;
  22 +
  23 +// 输出
  24 +global Result rs;
  25 +
  26 +//------------------ 第一阶段、计算wrapRule -----------------//
  27 +rule "calcu_Wrap_rule"
  28 + salience 400
  29 + when
  30 + $param: KBaseValidateRule_Fact_CalcuParam($xlId: xlId, $fd: fromDate, $td: toDate)
  31 + $qy_rule: KBaseValidateRule_Fact_Rule(xl.id == $xlId, qyrq.getTime() <= $td.getMillis(), $rid: id)
  32 + $ccInfos : ArrayList() from collect (KBaseValidateRule_Fact_VehicleConfig(xl.id == $xlId)) // 线路车辆配置
  33 + $ecInfos : ArrayList() from collect (KBaseValidateRule_Fact_EmployeeConfig(xl.id == $xlId)) // 线路人员配置
  34 + $lpInfos : ArrayList() from collect (KBaseValidateRule_Fact_LpConfig(xl.id == $xlId)) // 线路路牌配置
  35 + then
  36 + LOGGER.debug("线路Id={},开始时间={},结束时间={},启用规则Id={},线路车辆配置数={},线路人员配置数={},线路路牌配置数={}",
  37 + $xlId, $fd, $td, $rid, $ccInfos.size(), $ecInfos.size(), $lpInfos.size());
  38 +
  39 + WrapRule wrapRule = new WrapRule();
  40 + wrapRule.rule = $qy_rule;
  41 + wrapRule.addCcInfoList($ccInfos);
  42 + wrapRule.addEcInfoList($ecInfos);
  43 + wrapRule.addLpInfoList($lpInfos);
  44 +
  45 + insert(wrapRule);
  46 +
  47 +
  48 +end
  49 +
  50 +//------------------ 第二阶段、验证规则 -----------------//
  51 +rule "calcu_error_info"
  52 + salience 300
  53 + when
  54 + $param: KBaseValidateRule_Fact_CalcuParam($xlId: xlId, $fd: fromDate, $td: toDate)
  55 + $allRuleList: ArrayList() from collect(KBaseValidateRule_Fact_Rule(xl.id == $xlId))
  56 + $allWrapRuleList: ArrayList() from collect(WrapRule(rule.xl.id == $xlId))
  57 + $errorMap: Map() from accumulate ($wr: WrapRule(rule.xl.id == $xlId), srif($wr))
  58 + then
  59 + rs.setXlId($xlId);
  60 + rs.setCount($allRuleList.size());
  61 + rs.setQyCount($allWrapRuleList.size());
  62 +
  63 + rs.setQyErrorCount($errorMap.size());
  64 + rs.getErrorInfos().addAll($errorMap.values());
  65 +
  66 + LOGGER.info("线路Id={},开始时间={},结束时间={},规则总数={},启用规则数={},错误的启用规则数={}",
  67 + $xlId, $fd, $td, $allRuleList.size(), $allWrapRuleList.size(), $errorMap.size());
  68 +
  69 +end
  70 +
  71 +
... ...
src/main/resources/drools/KBase/validate/timetable/KBase_validate_timetable_old.drl deleted 100644 → 0
1   -package com.bsth.service.schedule.plan.process._1_validate._1_timetable.drools;
2   -
3   -import org.joda.time.*;
4   -import org.joda.time.format.DateTimeFormat;
5   -import java.util.*;
6   -import org.apache.commons.lang3.StringUtils;
7   -
8   -import com.bsth.service.schedule.plan.process._1_validate._1_timetable.drools.KBaseValidateTimeTable_Fact_CalcuParam;
9   -import com.bsth.service.schedule.plan.process._1_validate._1_timetable.drools.KBaseValidateTimeTable_Result;
10   -import com.bsth.service.schedule.plan.process._1_validate._1_timetable.drools.KBaseValidateTimeTable_Result.StatInfo;
11   -
12   -import com.bsth.service.schedule.plan.process._1_validate._1_timetable.drools.KBaseValidateTimeTable_Fact_Line;
13   -import com.bsth.service.schedule.plan.process._1_validate._1_timetable.drools.KBaseValidateTimeTable_Fact_TTInfo;
14   -import com.bsth.service.schedule.plan.process._1_validate._1_timetable.drools.KBaseValidateTimeTable_Fact_TTInfoDetail;
15   -
16   -import org.slf4j.Logger;
17   -
18   -// 全局日志类(使用PlanPreValidateServiceImpl里定义的LOGGER)
19   -global Logger LOGGER;
20   -
21   -// 输出
22   -global KBaseValidateTimeTable_Result rs;
23   -
24   -/*
25   - 规则说明:
26   - 1、找出指定线路,指定时间范围的时刻表
27   - 2、统计这些时刻表班次数据的情况
28   -*/
29   -
30   -//-------------- 第一阶段、计算规则迭代数据(天数) ------------//
31   -declare Calcu_iter_days_result
32   - xlId: Integer // 线路Id
33   - xlName: String // 线路名字
34   -
35   - // 迭代数据
36   - calcu_day: Integer // 准备计算第几天
37   - calcu_weekday: Integer // 准备计算星期几(1到7)
38   - calcu_date: DateTime // 准备计算的具体日期
39   -
40   - // 范围数据
41   - calcu_days: Integer // 总共需要计算的天数
42   - calcu_start_date: DateTime // 开始计算日期
43   - calcu_end_date: DateTime // 结束计算日期
44   -
45   - // 时刻表映射数据
46   - ttinfomap: Map // 指定时间段内,用的时刻表id映射 Map<Long, Long>
47   -end
48   -
49   -rule "calcu_iter_days"
50   - salience 1900
51   - when
52   - KBaseValidateTimeTable_Fact_CalcuParam(
53   - $xlId: xlId,
54   - $fromDate: fromDate,
55   - $toDate: toDate,
56   - $fromDate.isBefore($toDate) || $fromDate.isEqual($toDate)
57   - )
58   - $line: KBaseValidateTimeTable_Fact_Line(id == $xlId)
59   - then
60   - // 构造Calcu_iter_days_result对象,进行下一步计算
61   - Calcu_iter_days_result cidr = new Calcu_iter_days_result();
62   - Period p = new Period($fromDate, $toDate, PeriodType.days());
63   -
64   - cidr.setXlId($xlId);
65   - cidr.setXlName($line.getName());
66   -
67   - cidr.setCalcu_day(new Integer(1));
68   - cidr.setCalcu_weekday(Integer.valueOf($fromDate.getDayOfWeek()));
69   - cidr.setCalcu_date($fromDate);
70   -
71   - cidr.setCalcu_days(Integer.valueOf(p.getDays() + 1));
72   - cidr.setCalcu_start_date($fromDate);
73   - cidr.setCalcu_end_date($toDate);
74   -
75   - cidr.setTtinfomap(new HashMap());
76   -
77   - LOGGER.info(
78   - "线路={}-id={},开始时间={},结束时间={},总共计算的天数={},将从开始时间迭代",
79   - cidr.getXlName(),
80   - cidr.getXlId(),
81   - cidr.getCalcu_start_date(),
82   - cidr.getCalcu_end_date(),
83   - cidr.getCalcu_days()
84   - );
85   -
86   - insert(cidr);
87   -end
88   -
89   -//-------------- 第二阶段、时刻表的日期匹配 ------------//
90   -declare TTInfoDetails_wrap
91   - ttInfoId: Long // 时刻表id
92   - lineVersion: Integer // 线路版本
93   - bcInfoList: List // 班次信息列表 List<KBaseValidateTimeTable_Fact_TTInfoDetail>
94   -end
95   -
96   -rule "Calcu_iter_days_special_day" // 特殊日期匹配(并且不在StatInfo中)
97   - salience 800
98   - when
99   - $cid : Calcu_iter_days_result(
100   - $calcu_date: calcu_date,
101   - $calcu_day: calcu_day,
102   - calcu_day <= calcu_days
103   - )
104   - KBaseValidateTimeTable_Fact_TTInfo(
105   - $tid: id,
106   - $tname: name,
107   - $lineVersion: lineVersion,
108   - specialDayList contains $calcu_date
109   - )
110   - not StatInfo(ttid == $tid)
111   - $bcInfoList : ArrayList() from collect (KBaseValidateTimeTable_Fact_TTInfoDetail(ttinfo.id == $tid))
112   - then
113   - // 更新迭代对象
114   - Integer new_calcu_day = Integer.valueOf($calcu_day + 1);
115   - $cid.setCalcu_day(new_calcu_day);
116   - DateTime new_calcu_date = $calcu_date.plusDays(1);
117   - $cid.setCalcu_date(new_calcu_date);
118   - $cid.setCalcu_weekday(Integer.valueOf(new_calcu_date.getDayOfWeek()));
119   -
120   - LOGGER.debug("启用特殊日期时刻表(设置StatInfo):" +
121   - "时刻表id={} 特殊日期={}",
122   - $tid, $calcu_date);
123   -
124   - StatInfo statInfo = new StatInfo();
125   - statInfo.setTtid($tid);
126   - statInfo.setTtname($tname);
127   - insert(statInfo);
128   -
129   - TTInfoDetails_wrap ttInfoDetails_wrap = new TTInfoDetails_wrap();
130   - ttInfoDetails_wrap.setTtInfoId($tid);
131   - ttInfoDetails_wrap.setBcInfoList($bcInfoList);
132   - ttInfoDetails_wrap.setLineVersion($lineVersion);
133   - insert(ttInfoDetails_wrap);
134   -
135   - update($cid);
136   -
137   -end
138   -
139   -rule "Calcu_iter_days_special_day_exist" // 特殊日期匹配(已经在StatInfo中)
140   - salience 800
141   - when
142   - $cid : Calcu_iter_days_result(
143   - $calcu_date: calcu_date,
144   - $calcu_day: calcu_day,
145   - calcu_day <= calcu_days
146   - )
147   - KBaseValidateTimeTable_Fact_TTInfo(
148   - $tid: id,
149   - $tname: name,
150   - $lineVersion: lineVersion,
151   - specialDayList contains $calcu_date
152   - )
153   - StatInfo(ttid == $tid)
154   - then
155   - // 更新迭代对象
156   - Integer new_calcu_day = Integer.valueOf($calcu_day + 1);
157   - $cid.setCalcu_day(new_calcu_day);
158   - DateTime new_calcu_date = $calcu_date.plusDays(1);
159   - $cid.setCalcu_date(new_calcu_date);
160   - $cid.setCalcu_weekday(Integer.valueOf(new_calcu_date.getDayOfWeek()));
161   -
162   - LOGGER.debug("启用特殊日期时刻表(已经设置过StatInfo):" +
163   - "时刻表id={} 特殊日期={}",
164   - $tid, $calcu_date);
165   -
166   - update($cid);
167   -
168   -end
169   -
170   -rule "Calcu_iter_days_normal_day" // 平日匹配(并且不在StatInfo中)
171   - salience 700
172   - when
173   - $cid : Calcu_iter_days_result(
174   - $calcu_date: calcu_date,
175   - $calcu_weekday: calcu_weekday,
176   - $calcu_day: calcu_day,
177   - calcu_day <= calcu_days
178   - )
179   - KBaseValidateTimeTable_Fact_TTInfo(
180   - $tid: id,
181   - $tname: name,
182   - $lineVersion: lineVersion,
183   - specialDayList not contains $calcu_date,
184   - weekdayList[$calcu_weekday - 1] == Boolean.TRUE
185   - )
186   - not StatInfo(ttid == $tid)
187   - $bcInfoList : ArrayList() from collect (KBaseValidateTimeTable_Fact_TTInfoDetail(ttinfo.id == $tid))
188   - then
189   - // 更新迭代对象
190   - Integer new_calcu_day = Integer.valueOf($calcu_day + 1);
191   - $cid.setCalcu_day(new_calcu_day);
192   - DateTime new_calcu_date = $calcu_date.plusDays(1);
193   - $cid.setCalcu_date(new_calcu_date);
194   - $cid.setCalcu_weekday(Integer.valueOf(new_calcu_date.getDayOfWeek()));
195   -
196   -
197   - LOGGER.debug("启用常规日期时刻表(设置StatInfo):" +
198   - "时刻表id={} 常规日期={} 星期几={}",
199   - $tid, $calcu_date, $calcu_weekday);
200   -
201   - StatInfo statInfo = new StatInfo();
202   - statInfo.setTtid($tid);
203   - statInfo.setTtname($tname);
204   - insert(statInfo);
205   -
206   - TTInfoDetails_wrap ttInfoDetails_wrap = new TTInfoDetails_wrap();
207   - ttInfoDetails_wrap.setTtInfoId($tid);
208   - ttInfoDetails_wrap.setBcInfoList($bcInfoList);
209   - ttInfoDetails_wrap.setLineVersion($lineVersion);
210   - insert(ttInfoDetails_wrap);
211   -
212   - update($cid);
213   -
214   -end
215   -
216   -rule "Calcu_iter_days_normal_day_exist" // 平日匹配(已经在StatInfo中)
217   - salience 700
218   - when
219   - $cid : Calcu_iter_days_result(
220   - $calcu_date: calcu_date,
221   - $calcu_weekday: calcu_weekday,
222   - $calcu_day: calcu_day,
223   - calcu_day <= calcu_days
224   - )
225   - KBaseValidateTimeTable_Fact_TTInfo(
226   - $tid: id,
227   - $tname: name,
228   - $lineVersion: lineVersion,
229   - specialDayList not contains $calcu_date,
230   - weekdayList[$calcu_weekday - 1] == Boolean.TRUE
231   - )
232   - StatInfo(ttid == $tid)
233   - then
234   - // 更新迭代对象
235   - Integer new_calcu_day = Integer.valueOf($calcu_day + 1);
236   - $cid.setCalcu_day(new_calcu_day);
237   - DateTime new_calcu_date = $calcu_date.plusDays(1);
238   - $cid.setCalcu_date(new_calcu_date);
239   - $cid.setCalcu_weekday(Integer.valueOf(new_calcu_date.getDayOfWeek()));
240   -
241   - LOGGER.debug("启用常规日期时刻表(已经设置过StatInfo):" +
242   - "时刻表id={} 常规日期={} 星期几={}",
243   - $tid, $calcu_date, $calcu_weekday);
244   -
245   - update($cid);
246   -
247   -end
248   -
249   -rule "Calcu_iter_days_other_day" // 都没有的情况下,匹配
250   - salience 500
251   - when
252   - $cid : Calcu_iter_days_result(
253   - $calcu_date: calcu_date,
254   - $calcu_weekday: calcu_weekday,
255   - $calcu_day: calcu_day,
256   - calcu_day <= calcu_days
257   - )
258   - not KBaseValidateTimeTable_Fact_TTInfo(
259   - (specialDayList contains $calcu_date) ||
260   - (weekdayList[$calcu_weekday - 1] == Boolean.TRUE)
261   - )
262   - then
263   - // 更新迭代对象
264   - Integer new_calcu_day = Integer.valueOf($calcu_day + 1);
265   - $cid.setCalcu_day(new_calcu_day);
266   - DateTime new_calcu_date = $calcu_date.plusDays(1);
267   - $cid.setCalcu_date(new_calcu_date);
268   - $cid.setCalcu_weekday(Integer.valueOf(new_calcu_date.getDayOfWeek()));
269   -
270   - LOGGER.debug("当前日期没有匹配的时刻表:日期={} 星期几={}", $calcu_date, $calcu_weekday);
271   -
272   - update($cid);
273   -
274   -end
275   -
276   -//-------------- 第三阶段、时刻表明细统计值 ------------//
277   -
278   -rule "statinfo_result" // 统计计算结果
279   - salience 300
280   - no-loop
281   - when
282   - $statInfo: StatInfo($tid: ttid)
283   - $ttInfoDetails_wrap: TTInfoDetails_wrap(ttInfoId == $tid)
284   - $allbc: Long() from accumulate (KBaseValidateTimeTable_Fact_TTInfoDetail() from $ttInfoDetails_wrap.getBcInfoList(), count())
285   - $inbc: Long() from accumulate (KBaseValidateTimeTable_Fact_TTInfoDetail(bcType == "in") from $ttInfoDetails_wrap.getBcInfoList(), count())
286   - $outbc: Long() from accumulate (KBaseValidateTimeTable_Fact_TTInfoDetail(bcType == "out") from $ttInfoDetails_wrap.getBcInfoList(), count())
287   - $yybc: Long() from accumulate (KBaseValidateTimeTable_Fact_TTInfoDetail(bcType != "out", bcType != "in") from $ttInfoDetails_wrap.getBcInfoList(), count())
288   - $errorbc: Long() from accumulate ($ttd: KBaseValidateTimeTable_Fact_TTInfoDetail() from $ttInfoDetails_wrap.getBcInfoList(), ecount($ttd))
289   - then
290   - LOGGER.info("时刻表={},id={},班次数={},进场={},出场={},营运={},错误={}", $statInfo.getTtname(), $statInfo.getTtid(), $allbc, $inbc, $outbc, $yybc, $errorbc);
291   -
292   - $statInfo.setAllbc($allbc);
293   - $statInfo.setInbc($inbc);
294   - $statInfo.setOutbc($outbc);
295   - $statInfo.setYybc($yybc);
296   - $statInfo.setErrorbc($errorbc);
297   -
298   - int lineVersion = $ttInfoDetails_wrap.getLineVersion();
299   - $statInfo.setLineVersion(lineVersion);
300   -
301   - rs.getInfos().add($statInfo);
302   -
303   -end
304   -
305   -
306   -
307   -
src/main/resources/drools/config.properties
... ... @@ -20,5 +20,7 @@
20 20 # 排班前置验证规则
21 21 # 时刻表验证
22 22 drools.KBase.validate_timetable=drools/KBase/validate/timetable/KBase_validate_timetable.drl
  23 +# 规则验证
  24 +drools.KBase.validate_rule=drools/KBase/validate/rule/KBase_validate_rule.drl
23 25  
24 26  
... ...
src/test/java/com/bsth/service/schedule/Plan_0_validateTimetableTest.java renamed to src/test/java/com/bsth/service/schedule/PlanValidateTest.java
... ... @@ -2,9 +2,12 @@ package com.bsth.service.schedule;
2 2  
3 3 import com.bsth.BaseTest_junit4;
4 4 import com.bsth.TestApplication;
  5 +import com.bsth.control_v2.plan_module.common.service.schedule.validate.ValidateRuleResult;
5 6 import com.bsth.service.schedule.plan.process._1_validate._1_timetable.PlanProcessValidateTimetableService;
6 7 import com.bsth.service.schedule.plan.process._1_validate._1_timetable.PlanProcessValidateTimetableServiceDroolsImpl;
7 8 import com.bsth.service.schedule.plan.process._1_validate._1_timetable.drools.KBaseValidateTimeTable_Result;
  9 +import com.bsth.service.schedule.plan.process._1_validate._2_rule.PlanProcessValidateRuleService;
  10 +import com.bsth.service.schedule.plan.process._1_validate._2_rule.PlanProcessValidateRuleServiceDroolsImpl;
8 11 import org.joda.time.format.DateTimeFormat;
9 12 import org.junit.Assert;
10 13 import org.junit.Test;
... ... @@ -20,34 +23,39 @@ import java.util.HashMap;
20 23 import java.util.Map;
21 24  
22 25 /**
23   - * 排班计划,验证时刻表测试。
  26 + * 排班计划,前置验证测试。
24 27 */
25 28 @RunWith(SpringJUnit4ClassRunner.class)
26 29 @SpringApplicationConfiguration(classes = {TestApplication.class})
27   -public class Plan_0_validateTimetableTest extends BaseTest_junit4 {
  30 +public class PlanValidateTest extends BaseTest_junit4 {
28 31 @Override
29 32 public Map<String, String> getDbunitTestDbFileClassPathMap() {
30 33 Map<String, String> dbFileMap = new HashMap<>();
31   - dbFileMap.put("testCase1", "testdata/_0_validate_timetable.xml");
  34 + dbFileMap.put("_0_validate_timetable_test_case1", "testdata/_0_validate_timetable.xml");
  35 + dbFileMap.put("_1_validate_rule_test_case1", "testdata/_1_validate_rule.xml");
32 36 return dbFileMap;
33 37 }
34 38  
35 39 @Autowired
36 40 @Qualifier("kBaseValidateTimetable")
37   - private KieBase validateTimetableKBase;
  41 + private KieBase kBaseValidateTimetable;
  42 +
  43 + @Autowired
  44 + @Qualifier("kBaseValidateRule")
  45 + private KieBase kBaseValidateRule;
38 46  
39 47 @Autowired
40 48 private JdbcTemplate jdbcTemplate;
41 49  
42 50  
43 51 @Test
44   - public void testCase1() {
  52 + public void _0_validate_timetable_test_case1() {
45 53 LOG.info("---------------时刻表验证测试--------------");
46 54  
47 55 // 使用builder创建服务
48 56 PlanProcessValidateTimetableService planProcessValidateTimetableService =
49 57 PlanProcessValidateTimetableServiceDroolsImpl.getBuilder()
50   - .setValidateTimetableKBase(validateTimetableKBase)
  58 + .setkBaseValidateTimetable(kBaseValidateTimetable)
51 59 .setJdbcTemplate(jdbcTemplate)
52 60 .build();
53 61  
... ... @@ -67,4 +75,39 @@ public class Plan_0_validateTimetableTest extends BaseTest_junit4 {
67 75 new Object[] {4},
68 76 new Object[] {result.getInfos().size()});
69 77 }
  78 +
  79 + @Test
  80 + public void _1_validate_rule_test_case1() {
  81 + LOG.info("---------------规则验证测试--------------");
  82 +
  83 + // 使用builder创建服务
  84 + PlanProcessValidateRuleService planProcessValidateRuleService =
  85 + PlanProcessValidateRuleServiceDroolsImpl.getBuilder()
  86 + .setkBaseValidateRule(kBaseValidateRule)
  87 + .setJdbcTemplate(jdbcTemplate)
  88 + .build();
  89 +
  90 + PlanProcessValidateRuleService.Result validateRuleResult = planProcessValidateRuleService.validateRule(
  91 + 1,
  92 + DateTimeFormat.forPattern("yyyy-MM-dd").parseDateTime("2019-01-01").toDate(),
  93 + DateTimeFormat.forPattern("yyyy-MM-dd").parseDateTime("2019-01-14").toDate()
  94 + );
  95 +
  96 + Assert.assertArrayEquals(
  97 + "验证结果不一致!",
  98 + new Object[] {
  99 + 1,
  100 + 3,
  101 + 3,
  102 + 0,
  103 + 0
  104 + },
  105 + new Object[] {
  106 + validateRuleResult.getXlId(),
  107 + validateRuleResult.getCount(),
  108 + validateRuleResult.getQyCount(),
  109 + validateRuleResult.getQyErrorCount(),
  110 + validateRuleResult.getErrorInfos().size()
  111 + });
  112 + }
70 113 }
... ...
src/test/resources/META-INF/drools.packagebuilder.conf
... ... @@ -3,3 +3,5 @@
3 3 # kBase_validate_timetable.drl使用
4 4 drools.accumulate.function.ecount = com.bsth.service.schedule.plan.process._1_validate._1_timetable.drools.KBaseValidateTimeTable_Function_ErrorBcCount
5 5 drools.accumulate.function.ac = com.bsth.service.schedule.plan.process._1_validate._1_timetable.drools.KBaseValidateTimeTable_Function_AccumulateConflict
  6 +# kBase_validate_rule.drl使用
  7 +drools.accumulate.function.srif = com.bsth.service.schedule.plan.process._1_validate._2_rule.drools.KBaseValidateRule_Function_ErrorInfo
... ...
src/test/resources/testdata/_1_validate_rule.xml 0 → 100644
  1 +<?xml version='1.0' encoding='UTF-8'?>
  2 +<dataset>
  3 + <!-- 用户信息 -->
  4 + <bsth_c_sys_user id="1" user_name="管理员1" name="vip" password="vip" enabled="1" />
  5 + <!-- 角色信息 -->
  6 + <bsth_c_sys_role id="1" role_name="管理员组" enable="1" is_super_admin="1" pic="0" />
  7 + <!-- 用户角色关联信息 -->
  8 + <bsth_c_sys_user_roles users="1" roles="1" />
  9 + <!-- 公司信息(关联角色) -->
  10 + <bsth_c_sys_company_auth id="1" company_code="22" company_name="金高公司"
  11 + sub_company_code="01" sub_company_name="一分公司" />
  12 +
  13 + <!-- 车辆基础信息 -->
  14 + <bsth_c_cars id="1" inside_code="SSS-01"
  15 + business_code="22" company="金高公司" branche_company_code="01" branche_company="一分公司"
  16 + car_code="11111" car_plate="沪88881" supplier_name="bsth" equipment_code="123451"
  17 + hvac_car="1" ticket_type="1" led_screen="1" tv_video_type="1" scrap_state="0" />
  18 + <bsth_c_cars id="2" inside_code="SSS-02"
  19 + business_code="22" company="金高公司" branche_company_code="01" branche_company="一分公司"
  20 + car_code="11112" car_plate="沪88882" supplier_name="bsth" equipment_code="123452"
  21 + hvac_car="1" ticket_type="1" led_screen="1" tv_video_type="1" scrap_state="0" />
  22 + <bsth_c_cars id="3" inside_code="SSS-03"
  23 + business_code="55" company="南汇公司" branche_company_code="01" branche_company="一分公司"
  24 + car_code="11113" car_plate="沪88883" supplier_name="bsth" equipment_code="123453"
  25 + hvac_car="1" ticket_type="1" led_screen="1" tv_video_type="1" scrap_state="0" />
  26 + <bsth_c_cars id="4" inside_code="SSS-04"
  27 + business_code="22" company="金高公司" branche_company_code="02" branche_company="二分公司"
  28 + car_code="11114" car_plate="沪88884" supplier_name="bsth" equipment_code="123454"
  29 + hvac_car="1" ticket_type="1" led_screen="1" tv_video_type="1" scrap_state="0" />
  30 + <bsth_c_cars id="5" inside_code="SSS-05"
  31 + business_code="22" company="金高公司" branche_company_code="01" branche_company="一分公司"
  32 + car_code="11115" car_plate="沪88885" supplier_name="bsth" equipment_code="123455"
  33 + hvac_car="1" ticket_type="1" led_screen="1" tv_video_type="1" scrap_state="0" />
  34 +
  35 + <!-- 人员基础信息 -->
  36 + <bsth_c_personnel id="1" company="金高公司" company_code="22" branche_company="一分公司"
  37 + branche_company_code="01" job_code="05-000001" personnel_name="员工1" job_codeori="000001" />
  38 + <bsth_c_personnel id="2" company="金高公司" company_code="22" branche_company="一分公司"
  39 + branche_company_code="01" job_code="05-000002" personnel_name="员工2" job_codeori="000002" />
  40 + <bsth_c_personnel id="3" company="金高公司" company_code="22" branche_company="一分公司"
  41 + branche_company_code="01" job_code="05-000003" personnel_name="员工3" job_codeori="000003" />
  42 + <bsth_c_personnel id="4" company="金高公司" company_code="22" branche_company="一分公司"
  43 + branche_company_code="01" job_code="05-000004" personnel_name="员工4" job_codeori="000004" />
  44 + <bsth_c_personnel id="5" company="金高公司" company_code="22" branche_company="一分公司"
  45 + branche_company_code="01" job_code="05-000005" personnel_name="员工5" job_codeori="000005" />
  46 + <bsth_c_personnel id="6" company="金高公司" company_code="22" branche_company="一分公司"
  47 + branche_company_code="01" job_code="05-000006" personnel_name="员工6" job_codeori="000006" />
  48 + <bsth_c_personnel id="7" company="金高公司" company_code="22" branche_company="一分公司"
  49 + branche_company_code="01" job_code="05-000007" personnel_name="员工7" job_codeori="000007" />
  50 + <bsth_c_personnel id="8" company="金高公司" company_code="22" branche_company="一分公司"
  51 + branche_company_code="01" job_code="05-000008" personnel_name="员工8" job_codeori="000008" />
  52 +
  53 + <!-- 线路基础信息 -->
  54 + <bsth_c_line id="1" name="线路1" company="22" branche_company="01" length="20" destroy="0" />
  55 +
  56 + <!-- 停车场基础信息 -->
  57 + <bsth_c_car_park id="1" park_name="停车场1" company="05" branche_company="01" area="100" />
  58 +
  59 + <!-- 车辆配置信息(线路1,金高公司,一分公司) -->
  60 + <bsth_c_s_ccinfo id="1" xl="1" cl="1" qyrq="2019-01-01" tcd="停车场1" is_switch="0" is_cancel="0" />
  61 + <bsth_c_s_ccinfo id="2" xl="1" cl="2" qyrq="2019-01-01" tcd="停车场1" is_switch="0" is_cancel="0" />
  62 + <bsth_c_s_ccinfo id="3" xl="1" cl="5" qyrq="2019-01-01" tcd="停车场1" is_switch="0" is_cancel="0" />
  63 +
  64 + <!-- 人员配置信息(线路1,金高公司) -->
  65 + <bsth_c_s_ecinfo id="1" xl="1" jsy="1" dbbm="1" is_cancel="0" />
  66 + <bsth_c_s_ecinfo id="2" xl="1" jsy="2" dbbm="2" is_cancel="0" />
  67 + <bsth_c_s_ecinfo id="3" xl="1" jsy="3" dbbm="3" is_cancel="0" />
  68 + <bsth_c_s_ecinfo id="4" xl="1" jsy="4" dbbm="4" is_cancel="0" />
  69 + <bsth_c_s_ecinfo id="5" xl="1" jsy="5" dbbm="5" is_cancel="0" />
  70 + <bsth_c_s_ecinfo id="6" xl="1" jsy="6" dbbm="6" is_cancel="0" />
  71 + <bsth_c_s_ecinfo id="7" xl="1" jsy="7" spy="8" dbbm="78" is_cancel="0" />
  72 +
  73 + <!-- 排班计划信息 -->
  74 + <bsth_c_s_sp id="1" xl="1" schedule_from_time="2019-01-01" schedule_to_time="2019-01-10"
  75 + create_by="1" create_date="2019-02-01" update_by="1" update_date="2019-02-01"/>
  76 +
  77 + <!-- 路牌信息 -->
  78 + <bsth_c_s_gbi id="1" xl="1" lp_no="1" lp_name="路牌1" lp_type="普通路牌" is_cancel="0"
  79 + create_by="1" create_date="2019-02-01" update_by="1" update_date="2019-02-01"
  80 + />
  81 + <bsth_c_s_gbi id="2" xl="1" lp_no="2" lp_name="路牌2" lp_type="普通路牌" is_cancel="0"
  82 + create_by="1" create_date="2019-02-01" update_by="1" update_date="2019-02-01"
  83 + />
  84 + <bsth_c_s_gbi id="3" xl="1" lp_no="3" lp_name="路牌3" lp_type="普通路牌" is_cancel="0"
  85 + create_by="1" create_date="2019-02-01" update_by="1" update_date="2019-02-01"
  86 + />
  87 + <bsth_c_s_gbi id="4" xl="1" lp_no="4" lp_name="特1" lp_type="普通路牌" is_cancel="0"
  88 + create_by="1" create_date="2019-02-01" update_by="1" update_date="2019-02-01"
  89 + />
  90 +
  91 + <!-- 时刻表1信息(平日) -->
  92 + <bsth_c_s_ttinfo id="1" xl="1" name="时刻表1" xl_dir="2" qyrq="2019-01-01" is_enable_dis_template="1"
  93 + is_cancel="0" line_version="1" lp_count = "10" loop_count = "6"
  94 + rule_days="1,1,1,1,1,0,0"
  95 + create_by="1" create_date="2019-02-01" update_by="1" update_date="2019-02-01"
  96 + />
  97 + <!-- 时刻表2信息(节假日) -->
  98 + <bsth_c_s_ttinfo id="2" xl="1" name="时刻表2" xl_dir="2" qyrq="2019-01-01" is_enable_dis_template="1"
  99 + is_cancel="0" line_version="1" lp_count = "10" loop_count = "6"
  100 + rule_days="0,0,0,0,0,1,1"
  101 + create_by="1" create_date="2019-02-01" update_by="1" update_date="2019-02-01"
  102 + />
  103 + <!-- 时刻表3信息(特殊日期) -->
  104 + <bsth_c_s_ttinfo id="3" xl="1" name="时刻表3" xl_dir="2" qyrq="2019-01-01" is_enable_dis_template="1"
  105 + is_cancel="0" line_version="1" lp_count = "10" loop_count = "6"
  106 + special_days="2019-01-05,2019-01-06,2019-01-07"
  107 + create_by="1" create_date="2019-02-01" update_by="1" update_date="2019-02-01"
  108 + />
  109 + <!-- 时刻表明细1信息(3个路牌,5个班次) -->
  110 + <bsth_c_s_ttinfo_detail id="1" xl="1" ttinfo="1" lp="1" fcno="1" xl_dir="0"
  111 + qdz_code="#1" qdz_name="上行起点站" zdz_code="#2" zdz_name="上行终点站"
  112 + fcsj="08:30" bcs="1" jhlc="30" bcsj="30" bc_type="normal"
  113 + line_version="1"
  114 + create_by="1" create_date="2019-02-01" update_by="1" update_date="2019-02-01"
  115 + />
  116 + <bsth_c_s_ttinfo_detail id="2" xl="1" ttinfo="1" lp="2" fcno="2" xl_dir="0"
  117 + qdz_code="#1" qdz_name="上行起点站" zdz_code="#2" zdz_name="上行终点站"
  118 + fcsj="08:40" bcs="2" jhlc="30" bcsj="30" bc_type="normal"
  119 + line_version="1"
  120 + create_by="1" create_date="2019-02-01" update_by="1" update_date="2019-02-01"
  121 + />
  122 + <bsth_c_s_ttinfo_detail id="3" xl="1" ttinfo="1" lp="3" fcno="3" xl_dir="0"
  123 + qdz_code="#1" qdz_name="上行起点站" zdz_code="#2" zdz_name="上行终点站"
  124 + fcsj="08:50" bcs="3" jhlc="30" bcsj="30" bc_type="normal"
  125 + line_version="1"
  126 + create_by="1" create_date="2019-02-01" update_by="1" update_date="2019-02-01"
  127 + />
  128 + <bsth_c_s_ttinfo_detail id="4" xl="1" ttinfo="1" lp="1" fcno="4" xl_dir="1"
  129 + qdz_code="#3" qdz_name="下行起点站" zdz_code="#4" zdz_name="下行终点站"
  130 + fcsj="09:10" bcs="4" jhlc="30" bcsj="30" bc_type="normal"
  131 + line_version="1"
  132 + create_by="1" create_date="2019-02-01" update_by="1" update_date="2019-02-01"
  133 + />
  134 + <bsth_c_s_ttinfo_detail id="5" xl="1" ttinfo="1" lp="2" fcno="5" xl_dir="1"
  135 + qdz_code="#3" qdz_name="下行起点站" zdz_code="#4" zdz_name="下行终点站"
  136 + fcsj="09:20" bcs="5" jhlc="30" bcsj="30" bc_type="normal"
  137 + line_version="1"
  138 + create_by="1" create_date="2019-02-01" update_by="1" update_date="2019-02-01"
  139 + />
  140 + <!-- 时刻表明细2信息(2个路牌,2个班次) -->
  141 + <bsth_c_s_ttinfo_detail id="6" xl="1" ttinfo="2" lp="1" fcno="1" xl_dir="0"
  142 + qdz_code="#1" qdz_name="上行起点站" zdz_code="#2" zdz_name="上行终点站"
  143 + fcsj="08:30" bcs="1" jhlc="30" bcsj="30" bc_type="normal"
  144 + line_version="1"
  145 + create_by="1" create_date="2019-02-01" update_by="1" update_date="2019-02-01"
  146 + />
  147 + <bsth_c_s_ttinfo_detail id="7" xl="1" ttinfo="2" lp="2" fcno="2" xl_dir="0"
  148 + qdz_code="#1" qdz_name="上行起点站" zdz_code="#2" zdz_name="上行终点站"
  149 + fcsj="08:40" bcs="2" jhlc="30" bcsj="30" bc_type="normal"
  150 + line_version="1"
  151 + create_by="1" create_date="2019-02-01" update_by="1" update_date="2019-02-01"
  152 + />
  153 + <!-- 时刻表明细3信息(1个路牌,1个班次) -->
  154 + <bsth_c_s_ttinfo_detail id="8" xl="1" ttinfo="3" lp="4" fcno="1" xl_dir="0"
  155 + qdz_code="#1" qdz_name="上行起点站" zdz_code="#2" zdz_name="上行终点站"
  156 + fcsj="08:30" bcs="1" jhlc="30" bcsj="30" bc_type="normal"
  157 + line_version="1"
  158 + create_by="1" create_date="2019-02-01" update_by="1" update_date="2019-02-01"
  159 + />
  160 +
  161 + <!-- 线路1规则信息 -->
  162 + <bsth_c_s_sr1_flat id="1" xl="1" car_config_info="1" qyrq="2019-01-01"
  163 + lp_names="路牌1" lp_ids="1" lp_start="1"
  164 + ry_dbbms="1,2" ry_config_ids="1,2" ry_start="1"
  165 + fbtype="0"
  166 + />
  167 + <bsth_c_s_sr1_flat id="2" xl="1" car_config_info="2" qyrq="2019-01-01"
  168 + lp_names="路牌2" lp_ids="2" lp_start="1"
  169 + ry_dbbms="3,4" ry_config_ids="3,4" ry_start="1"
  170 + fbtype="0"
  171 + />
  172 + <bsth_c_s_sr1_flat id="3" xl="1" car_config_info="3" qyrq="2019-01-01"
  173 + lp_names="路牌3" lp_ids="3" lp_start="1"
  174 + ry_dbbms="5-78,6" ry_config_ids="5-7,6" ry_start="1"
  175 + fbtype="0"
  176 + />
  177 +
  178 +</dataset>
... ...