田源
2024-09-29 d8f51c40544ae278095e991ed00ec297842d4332
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
package com.vci.ubcs.code.service.impl;
 
import com.alibaba.cloud.commons.lang.StringUtils;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
 
import com.vci.ubcs.code.dto.CodeBasicSecDTO;
import com.vci.ubcs.code.dto.CodeOrderDTO;
import com.vci.ubcs.code.dto.CodeOrderSecDTO;
import com.vci.ubcs.code.entity.*;
import com.vci.ubcs.code.enumpack.*;
import com.vci.ubcs.code.lifecycle.CodeRuleLC;
import com.vci.ubcs.code.mapper.CodeBasicSecMapper;
import com.vci.ubcs.code.mapper.CodeClassifyValueMapper;
import com.vci.ubcs.code.mapper.CodeFixedValueMapper;
import com.vci.ubcs.code.mapper.CodeSerialValueMapper;
import com.vci.ubcs.code.service.*;
import com.vci.ubcs.code.vo.CodeReferConfigVO;
import com.vci.ubcs.code.vo.pagemodel.*;
import com.vci.ubcs.code.wrapper.CodeBasicSecWrapper;
import com.vci.ubcs.omd.cache.EnumCache;
import com.vci.ubcs.omd.enums.EnumEnum;
import com.vci.ubcs.starter.enumpack.CodeTableNameEnum;
import com.vci.ubcs.starter.exception.VciBaseException;
import com.vci.ubcs.starter.revision.model.BaseModel;
import com.vci.ubcs.starter.revision.service.RevisionModelUtil;
import com.vci.ubcs.starter.util.DefaultAttrAssimtUtil;
import com.vci.ubcs.starter.util.MdmBtmTypeConstant;
import com.vci.ubcs.starter.util.UBCSCondition;
import com.vci.ubcs.starter.util.UBCSSqlKeyword;
import com.vci.ubcs.starter.web.enumpck.OsCodeFillTypeEnum;
import com.vci.ubcs.starter.web.pagemodel.*;
import com.vci.ubcs.starter.web.util.BeanUtilForVCI;
import com.vci.ubcs.starter.web.util.VciBaseUtil;
import com.vci.ubcs.starter.web.util.VciDateUtil;
import com.vci.ubcs.starter.web.util.WebUtil;
import com.vci.ubcs.system.entity.DictBiz;
import com.vci.ubcs.system.feign.IDictBizClient;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.mp.support.Query;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.BeanUtil;
import org.springblade.core.tool.utils.Func;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
 
import javax.annotation.Resource;
import java.rmi.ServerException;
import java.util.*;
import java.util.stream.Collectors;
 
import static com.vci.ubcs.code.constant.FrameWorkLangCodeConstant.*;
import static com.vci.ubcs.code.constant.MdmEngineConstant.EMPTY_SERIAL_UNIT;
import static com.vci.ubcs.code.constant.MdmEngineConstant.SERIAL_UNIT_SPACE;
 
/**
 * 码段基础信息服务接口
 *
 * @author weidy
 * @date 2022-01-24
 */
@Service
public class CodeBasicSecServiceImpl extends ServiceImpl<CodeBasicSecMapper, CodeBasicSec> implements ICodeBasicSecService {
 
    @Resource
    private CodeBasicSecMapper codeBasicSecMapper;
 
    /**
     * 固定码段的码值数据操作层
     */
    @Resource
    private CodeFixedValueMapper fixedValueMapper;
 
    /**
     * 分类码段的码值数据操作层
     */
    @Resource
    private CodeClassifyValueMapper codeClassifyValueMapper;
 
    @Resource
    private RevisionModelUtil revisionModelUtil;
 
    @Resource
    @Lazy
    private ICodeRuleService codeRuleService;
 
    @Resource
    private ICodeClassifyValueService codeClassifyValueService;
 
    @Resource
    private ICodeReferConfigService codeReferConfigService;
 
    @Resource
    private IDictBizClient iDictBizClient;
 
    /**
     * 固定码段的码值的服务
     */
    @Resource
    private ICodeFixedValueService fixedValueService;
 
    /**
     * 流水号的相关的信息
     */
    @Resource
    private CodeSerialValueMapper serialValueMapper;
 
    /**
     * 上层分类码段的属性名称
     */
    private static  final String PARENT_FIELD_NAME = "parentClassifySecOid";
 
    /**
     * 上级分类码值的属性名称
     */
    private static final String PARENT_CLASSIFY_VALUE_FIELD_NAME = "parentClassifyValueOid";
 
    /**
     * 查询所有的码段基础信息
     * @param conditionMap 查询条件
     * @param query 分页对象
     * @return 执行结果
     * @throws VciBaseException 查询条件和分页出错的时候会抛出异常
     */
    @Override
    public IPage<CodeBasicSecVO> gridCodeBasicSec(Query query, Map<String,Object> conditionMap) throws ServiceException {
        if(Func.isEmpty(Func.isEmpty(conditionMap.get(CodeTableNameEnum.PL_CODE_BASICSEC.getText()+".pkCodeRule")))){
            return null;
        }
        // 联表查询 ,设置表别名,表别名默认就采用表名小写,配置高级查询的时候就需要根据这个来对where条件进行配置
        MPJLambdaWrapper<CodeBasicSec> mpjLambdaWrapper = new MPJLambdaWrapper<>(CodeBasicSec.class, CodeTableNameEnum.PL_CODE_BASICSEC.getText())
            .selectAll(CodeBasicSec.class)
            .selectAs(CodeClassify::getName, CodeBasicSec::getReferCodeClassifyOidName)
            .leftJoin(CodeClassify.class, CodeTableNameEnum.PL_CODE_CLASSIFY.getText(), CodeClassify::getOid, CodeBasicSec::getReferCodeClassifyOid)
            .leftJoin(CodeBasicSec.class,CodeTableNameEnum.PL_CODE_BASICSEC.getText()+1,CodeBasicSec::getOid,CodeBasicSec::getParentClassifySecOid
                ,ext->ext.selectAs(CodeBasicSec::getName,CodeBasicSec::getParentClassifySecText));
        // 添加where条件
        UBCSSqlKeyword.buildConditionByAs(conditionMap,mpjLambdaWrapper,CodeTableNameEnum.PL_CODE_BASICSEC.getText());
        IPage<CodeBasicSec> codeBasicSecIPage = codeBasicSecMapper.selectPage(UBCSCondition.getPage(query), mpjLambdaWrapper);
        return CodeBasicSecWrapper.build().pageVO(codeBasicSecIPage);
    }
 
    /**
     * 根据编码规则批量删除码段基本信息
     * @param codeRuleOid 编码规则主键
     * @return 执行结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean batchDeleteSecByCodeRuleOid(String codeRuleOid) throws ServiceException {
        VciBaseUtil.alertNotNull(codeRuleOid,"编码规则主键");
        // 1、通过pkcoderule作为条件,先查询要删除基础码段
        List<CodeBasicSec> deleteList = this.codeBasicSecMapper.selectList(Wrappers.<CodeBasicSec>query().eq("pkcoderule", codeRuleOid));
        if (CollectionUtils.isEmpty(deleteList)){
            return true;
        }
        // 2、再删除基础码段
        boolean deletFlag = codeBasicSecMapper.deleteBatchIds(deleteList.stream().map(CodeBasicSec::getOid).collect(Collectors.toSet())) > 0;
        // 3、再根据删除固定码段,丛查询出来的基础码段中过滤出包含固定码段的记录
        List<CodeBasicSec> fixedSecList = deleteList.stream().filter(sec -> {
            return CodeSecTypeEnum.CODE_FIXED_SEC.getValue().equals(sec.getSecType());
        }).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(fixedSecList)){
            // 将要作为删除条件的值放在一个集合里面
            Set<String> fixedSecOidSet = fixedSecList.stream().map(CodeBasicSec::getOid).collect(Collectors.toSet());
            // 通过外键进行查询
            List<CodeFixedValue> fixedValues = fixedValueMapper.selectList(Wrappers.<CodeFixedValue>query().lambda().in(CodeFixedValue::getCodeFixedSecOid,fixedSecOidSet));
            if(!fixedValues.isEmpty()){
                // 根据查询出来的id执行固定码段执行删除
                deletFlag = fixedValueMapper.deleteBatchIds(fixedValues.stream().map(CodeFixedValue::getOid).collect(Collectors.toSet()))>0;
            }
        }
        // 4、再删除分类码段
        List<CodeBasicSec> classifySecList = deleteList.stream().filter(sec -> {
            return CodeSecTypeEnum.CODE_CLASSIFY_SEC.getValue().equals(sec.getSecType());
        }).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(classifySecList)){
            // 将要作为删除条件的值放在一个集合里面
            Set<String> classifySecOidSet = classifySecList.stream().map(CodeBasicSec::getOid).collect(Collectors.toSet());
            // 通过外键进行查询
            List<CodeClassifyValue> codeClassifyValues = codeClassifyValueMapper.selectList(Wrappers.<CodeClassifyValue>query().lambda().in(CodeClassifyValue::getCodeClassifySecOid,classifySecOidSet));
            if(!codeClassifyValues.isEmpty()){
                // 根据查询出来的主键id执行固定码段执行删除
                deletFlag = codeClassifyValueMapper.deleteBatchIds(codeClassifyValues.stream().map(CodeClassifyValue::getOid).collect(Collectors.toSet()))>0;
            }
        }
        return deletFlag;
    }
 
    /**
     * 根据码段分类的类型判断属性是否是空的
     *
     * @param codeBasicSecDTO 码段基础信息数据传输对象
     * @return 有空的则传key-属性名 value-字段含义,没有空的则传 key-success value-true
     */
    @Override
    public KeyValue checkAttrNullableBySecType(CodeBasicSecDTO codeBasicSecDTO) throws ServiceException {
        VciBaseUtil.alertNotNull(codeBasicSecDTO.getSecType(), "码段分类");
        String secType = codeBasicSecDTO.getSecType();
        HashMap<String, String> attrMap = JSONObject.parseObject(JSONObject.toJSONString(codeBasicSecDTO), HashMap.class);
        Map<String, String> notNullableAttr = getNotNullableAttr(secType);
        if (notNullableAttr == null) {
            throw new VciBaseException("码段分类填写出错,请查验后重试");
        }
        for (String key : notNullableAttr.keySet()) {
            if (StringUtils.isBlank(WebUtil.getStringValueFromObject(attrMap.get(key)))) {
                KeyValue kv = new KeyValue();
                kv.setKey(key);
                kv.setValue(notNullableAttr.get(key));
                return kv;
            }
        }
        KeyValue kv = new KeyValue();
        kv.setKey("success");
        kv.setValue("true");
        return kv;
    }
 
    /**
     * 增加码段基础信息
     *
     * @param codeBasicSecDTO 码段基础信息数据传输对象
     * @return 执行结果
     * @throws VciBaseException 参数为空,唯一项,必输项不通过时会抛出异常
     */
     @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean addSave(CodeBasicSecDTO codeBasicSecDTO) throws VciBaseException {
        VciBaseUtil.alertNotNull(codeBasicSecDTO, "需要添加的数据对象",codeBasicSecDTO.getPkCodeRule(),"编码规则的主键");
        CodeRuleVO ruleVO = codeRuleService.getObjectByOid(codeBasicSecDTO.getPkCodeRule());
        if(!CodeRuleLC.EDITING.getValue().equalsIgnoreCase(ruleVO.getLcStatus())){
            throw new VciBaseException("编码规则的状态不是【" + CodeRuleLC.EDITING.getText() + "】!不允许修改");
        }
        KeyValue attrKv = checkAttrNullableBySecType(codeBasicSecDTO);
        if (! "success".equals(attrKv.getKey())){
            throw new VciBaseException(attrKv.getValue() + "不能为空");
        }
        //将DTO转换为DO
        CodeBasicSec codeBasicSecDO = new CodeBasicSec();
        BeanUtilForVCI.copyPropertiesIgnoreCase(codeBasicSecDTO, codeBasicSecDO);
        //text转换
        codeBasicSecDO.setSecTypeText(EnumCache.getValue(EnumEnum.CODE_SEC_TYPE,codeBasicSecDTO.getSecType()));
        codeBasicSecDO.setCodeLevelTypeText(EnumCache.getValue(EnumEnum.CODE_LEVEL_TYPE,codeBasicSecDTO.getCodeLevelType()));
        codeBasicSecDO.setCodeSecLengthTypeText(EnumCache.getValue(EnumEnum.CODE_SEC_LENGTH,codeBasicSecDTO.getCodeSecLengthType()));
        codeBasicSecDO.setValueCutTypeText(EnumCache.getValue(EnumEnum.CODE_CUT_TYPE,codeBasicSecDTO.getValueCutType()));
        codeBasicSecDO.setCodeGetValueTypeText(EnumCache.getValue(EnumEnum.CODE_GET_VALUE_TYPE,codeBasicSecDTO.getCodeGetValueType()));
        //填充一些默认值
        DefaultAttrAssimtUtil.addDefaultAttrAssimt(codeBasicSecDO, MdmBtmTypeConstant.CODE_BASIC_SEC);
        //排序号,默认等于当前已有的数量加1
        Long total = codeBasicSecMapper.selectCount(Wrappers.<CodeBasicSec>query()
            .lambda()
            .eq(CodeBasicSec::getPkCodeRule,codeBasicSecDTO.getPkCodeRule()));
        if(total == null){
            total = 0L;
        }
        codeBasicSecDO.setOrderNum(total.intValue() + 1);
 
        //补位的时候,要控制补位字符
        if((OsCodeFillTypeEnum.LEFT.getValue().equalsIgnoreCase(codeBasicSecDO.getCodeFillType())
            || OsCodeFillTypeEnum.RIGHT.getValue().equalsIgnoreCase(codeBasicSecDO.getCodeFillType()))
            && StringUtils.isBlank(codeBasicSecDO.getCodeFillSeparator())){
            throw new VciBaseException("当补位方式为左补位或者右补位的时候,补位字符不能为空");
        }
        CodeReferConfigVO codeReferConfigVO = null;
        //引用码段的时候,需要判断参照的信息是否正确
        if(CodeSecTypeEnum.CODE_REFER_SEC.getValue().equalsIgnoreCase(codeBasicSecDO.getSecType())){
            if(StringUtils.isBlank(codeBasicSecDO.getReferConfig())){
                throw new VciBaseException("引用码段的时候,需要填写参照配置的内容");
            }
            try{
                //JSONObject.parseObject(codeBasicSecDO.getReferConfig(), UIFormReferVO.class);
                codeReferConfigVO = JSONObject.parseObject(codeBasicSecDO.getReferConfig(), CodeReferConfigVO.class);
                // 将参照配置进行持久化,给用户提供可可选择参照配置的方式
            }catch (Throwable e){
                throw new VciBaseException("引用码段的时候,参照配置的内容的格式不正确,",new String[0],e);
            }
            // 判断是否为引用码段,如果是应用码段的话,为了适配前端组件,这里要对表进行处理一下,按照以前的参照格式进行转换
            codeBasicSecDO.setReferValueInfo(referConfigToUIUiTable(codeReferConfigVO));
            if(Func.toBoolean(codeReferConfigVO.getIsPersistence())){
                codeReferConfigService.insert(codeReferConfigVO);
            }
        }
        boolean resBoolean = codeBasicSecMapper.insert(codeBasicSecDO) > 0;
        //SessionInfo sessionInfo = VciBaseUtil.getCurrentUserSessionInfo();
        if(StringUtils.isNotBlank(codeBasicSecDO.getCodeFillSeparator())){
            DictBiz dictBiz = new DictBiz();
            dictBiz.setCode("codeFillSeparator");
            dictBiz.setDictKey(codeBasicSecDO.getCodeFillSeparator());
            dictBiz.setDictValue(codeBasicSecDO.getCodeFillSeparator());
            //从原来的charService(可输可选)更改为调用omd中的接口来实现
            iDictBizClient.getCheck(dictBiz);
            //charService.save(MdmBtmTypeConstant.CODE_BASIC_SEC,"codefileseparator",codeBasicSecDO.getCodeFillSeparator(),sessionInfo);
        }
        return resBoolean;
    }
 
    /**
     * 将referconfig转换为JSON格式的UIFormReferVO
     * @param codeReferConfig
     * @return
     */
    private String referConfigToUIUiTable(CodeReferConfigVO codeReferConfig){
        // 拷贝为以前的老对象
        UIReferConfigFormVO uiFormReferVO = new UIReferConfigFormVO();
        BeanUtil.copy(codeReferConfig,uiFormReferVO);
 
        // 表格的自定义定义
        UITableConfigVO uiTableConfigVO = new UITableConfigVO();
        uiTableConfigVO.setPage(new UITablePageVO(codeReferConfig.getLimit(),1));
        // 列表的列的信息转换
        List<TableColVO> uiTableFieldVOs = new ArrayList<>();
        // 快速查询列
        List<TableColVO> queryColumns = new ArrayList<>();
        if(!CollectionUtils.isEmpty(codeReferConfig.getCodeShowFieldConfigVOS())){
            codeReferConfig.getCodeShowFieldConfigVOS().stream().forEach(showField ->{
                TableColVO tableColVO = new TableColVO();
                BeanUtil.copy(showField,tableColVO);
                tableColVO.setSortField(showField.getAttrSortField());
                uiTableFieldVOs.add(tableColVO);
                if(Func.toBoolean(showField.getIsQuery())){
                    TableColVO tableQueryColumns = new TableColVO();
                    BeanUtil.copy(showField,tableQueryColumns);
                    tableColVO.setSortField(showField.getAttrSortField());
                    queryColumns.add(tableQueryColumns);
                }
            });
        }
        // 显示的列
        uiTableConfigVO.setCols(uiTableFieldVOs);
        // 快速查询列
        uiTableConfigVO.setQueryColumns(queryColumns);
        //set给表格配置属性
        uiFormReferVO.setTableConfig(uiTableConfigVO);
        //字段名不一致,需要手动set
        uiFormReferVO.setMuti(Func.toBoolean(codeReferConfig.getIsMuti()));
        uiFormReferVO.setInitSort(new UIFieldSortVO(codeReferConfig.getSortField(),codeReferConfig.getSortType()));
        // 筛选条件
        HashMap<String, String> whereMap = new HashMap<>();
        if(!codeReferConfig.getCodeSrchCondConfigVOS().isEmpty()){
            codeReferConfig.getCodeSrchCondConfigVOS().stream().forEach(srch->{
                whereMap.put(srch.getFilterField()+srch.getFilterType(),srch.getFilterValue());
            });
        }
        uiFormReferVO.setWhere(whereMap);
        return JSONObject.toJSONString(uiFormReferVO);
    }
 
    /**
     * 修改码段基础信息
     *
     * @param codeBasicSecDTO 码段基础信息数据传输对象
     * @return 执行结果
     * @throws VciBaseException 参数为空,唯一项,必输项不通过时会抛出异常
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean editSave(CodeBasicSecDTO codeBasicSecDTO) throws ServerException {
        VciBaseUtil.alertNotNull(codeBasicSecDTO, "需要添加的数据对象");
        KeyValue attrKv = checkAttrNullableBySecType(codeBasicSecDTO);
        if (!"success".equals(attrKv.getKey())){
            throw new VciBaseException(attrKv.getValue() + "不能为空");
        }
        //将DTO转换为DO
        CodeBasicSec codeBasicSecDO = selectByOid(codeBasicSecDTO.getOid());
        DefaultAttrAssimtUtil.updateDefaultAttrAssimt(codeBasicSecDO);
        boolean status = codeRuleService.checkEditDelStatus(codeRuleService.getObjectByOid(codeBasicSecDO.getPkCodeRule()).getLcStatus());
        boolean resBoolean;
        CodeReferConfigVO codeReferConfigVO = null;
        if (!status){
            //返回错误信息
            throw new VciBaseException("编码规则不允许编辑或删除!");
        } else {
            //补位的时候,要控制补位字符
            if((OsCodeFillTypeEnum.LEFT.getValue().equalsIgnoreCase(codeBasicSecDO.getCodeFillType())
                || OsCodeFillTypeEnum.RIGHT.getValue().equalsIgnoreCase(codeBasicSecDO.getCodeFillType()))
                && StringUtils.isBlank(codeBasicSecDO.getCodeFillSeparator())){
                throw new VciBaseException("当补位方式为左补位或者右补位的时候,补位字符不能为空");
            }
            //引用码段的时候,需要判断参照的信息是否正确
            if(CodeSecTypeEnum.CODE_REFER_SEC.getValue().equalsIgnoreCase(codeBasicSecDO.getSecType())){
                if(StringUtils.isBlank(codeBasicSecDTO.getReferConfig())){
                    throw new VciBaseException("引用码段的时候,需要填写参照配置的内容");
                }
                try{
                    // JSONObject.parseObject(codeBasicSecDO.getReferConfig(), UIFormReferVO.class);
                    codeReferConfigVO = JSONObject.parseObject(codeBasicSecDTO.getReferConfig(), CodeReferConfigVO.class);
                }catch (Throwable e){
                    throw new VciBaseException("引用码段的时候,参照配置的内容的格式不正确,",new String[0],e);
                }
                // 判断是否为引用码段,如果是引用码段的话,为了适配前端组件,这里要对表进行处理一下,按照以前的参照格式进行转换
                codeBasicSecDO.setReferValueInfo(referConfigToUIUiTable(codeReferConfigVO));
                if(codeReferConfigVO.getIsPersistence()=="true"){
                    codeReferConfigService.insert(codeReferConfigVO);
                }
            }
            // revisionModelUtil.copyFromDTOIgnore(codeBasicSecDTO, codeBasicSecDO);//此处的拷贝会把referValueInfo的值给覆盖掉,需要重新赋值
            BaseModel tempModel = new BaseModel();
            BeanUtilForVCI.copyPropertiesIgnoreCase(codeBasicSecDO, tempModel);
            BeanUtil.copyProperties(codeBasicSecDTO, codeBasicSecDO,"referValueInfo");
            BeanUtilForVCI.copyPropertiesIgnoreCase(tempModel, codeBasicSecDO);
            codeBasicSecDO.setId(VciBaseUtil.getStringValueFromObject(VciBaseUtil.getValueFromField("id", codeBasicSecDTO)));
            codeBasicSecDO.setName(VciBaseUtil.getStringValueFromObject(VciBaseUtil.getValueFromField("name", codeBasicSecDTO)));
            codeBasicSecDO.setDescription(VciBaseUtil.getStringValueFromObject(VciBaseUtil.getValueFromField("description", codeBasicSecDTO)));
 
            resBoolean = codeBasicSecMapper.updateById(codeBasicSecDO)>0;
            // 从分类码段或固定码段改为其他码段时,判断用户是否选择了清空码值
            if(codeBasicSecDTO.getIsClearValue()){
                // 分类码值清空
                if(codeBasicSecDTO.getSecType().equals(CodeSecTypeEnum.CODE_CLASSIFY_SEC.getValue())){
                    codeClassifyValueService.deleteClassifyValueBySecOid(codeBasicSecDTO.getOid());
                }else {
                    //固定码值清空
                    fixedValueService.deleteFixedValueBySecOid(codeBasicSecDTO.getOid());
                }
            }
            //SessionInfo sessionInfo = VciBaseUtil.getCurrentUserSessionInfo();
            if(StringUtils.isNotBlank(codeBasicSecDO.getCodeFillSeparator())){
                DictBiz dictBiz = new DictBiz();
                dictBiz.setCode("codeFillSeparator");
                dictBiz.setDictKey(codeBasicSecDO.getCodeFillSeparator());
                dictBiz.setDictValue(codeBasicSecDO.getCodeFillSeparator());
                //从原来的charService(可输可选)更改为调用omd中的接口来实现
                iDictBizClient.getCheck(dictBiz);
                //charService.save(MdmBtmTypeConstant.CODE_BASIC_SEC,"codefileseparator",codeBasicSecDO.getCodeFillSeparator(),sessionInfo);
            }
        }
        return resBoolean;
    }
 
    /**
     * 根据码段类型获取不可为空的字段
     *
     * @param secType 码段类型
     * @return 不可为空的字段集合
     */
    private Map<String, String> getNotNullableAttr(String secType) throws ServiceException {
        Map<String, String> attrMap = new HashMap<>();
        if (CodeSecTypeEnum.CODE_ATTR_SEC.getValue().equalsIgnoreCase(secType)) {
            attrMap.put("name", "属性码段名称");
        } else if (CodeSecTypeEnum.CODE_DATE_SEC.getValue().equalsIgnoreCase(secType)) {
            attrMap.put("name", "日期码段名称");
            attrMap.put("codeDateFormatStr", "日期格式");
        } else if (CodeSecTypeEnum.CODE_FIXED_SEC.getValue().equalsIgnoreCase(secType)) {
            attrMap.put("name", "固定码段名称");
            attrMap.put("codeSecLengthType", "码段长度类型");
            attrMap.put("codeSecLength", "码段的长度");
        } else if (CodeSecTypeEnum.CODE_LEVEL_SEC.getValue().equalsIgnoreCase(secType)) {
            attrMap.put("name", "层级码段名称");
            attrMap.put("codeLevelType", "层级类型");
            attrMap.put("valueCutType", "字符截取类型");
        } else if (CodeSecTypeEnum.CODE_REFER_SEC.getValue().equalsIgnoreCase(secType)) {
            attrMap.put("name", "引用码段名称");
        } else if (CodeSecTypeEnum.CODE_SERIAL_SEC.getValue().equalsIgnoreCase(secType)) {
            attrMap.put("name", "流水码段名称");
            attrMap.put("codeSecLength", "码段的长度");
            attrMap.put("codeFillType", "编码补位方式");
            attrMap.put("codeFillLength", "填充长度");
            attrMap.put("codeFillLimit", "流水上限");
            attrMap.put("codeFillFlag", "流水是否补码");
        } else if (CodeSecTypeEnum.CODE_VARIABLE_SEC.getValue().equalsIgnoreCase(secType)) {
            attrMap.put("name", "可变码段名称");
            attrMap.put("codeSecLength", "码段的长度");
            attrMap.put("codeFillType", "编码补位方式");
        } else if (CodeSecTypeEnum.CODE_CLASSIFY_SEC.getValue().equalsIgnoreCase(secType)) {
            attrMap.put("name", "分类码段名称");
            attrMap.put("codeSecLengthType", "码段长度类型");
            attrMap.put("codeSecLength", "码段的长度");
        } else {
            attrMap = null;
        }
        return attrMap;
    }
 
    /**
     * 删除码段基础信息
     * @param codeBasicSecDTO 码段基础信息数据传输对象,oid和ts需要传输
     * @return 删除结果反馈::success:成功,fail:失败
     * @throws VciBaseException 参数为空,被引用时抛出异常
     */
    @Override
    public R deleteCodeBasicSec(CodeBasicSecDTO codeBasicSecDTO) throws VciBaseException {
        VciBaseUtil.alertNotNull(codeBasicSecDTO, "码段基础信息数据对象", codeBasicSecDTO.getOid(), "码段基础信息的主键");
        return this.deleteCodeBasicSecByPrimaryKey(codeBasicSecDTO.getOid());
    }
 
    /**
     * 主键删除码段基础信息
     *
     * @param oid 码段基础信息主键
     * @return 删除结果反馈::success:成功,fail:失败
     * @throws VciBaseException 参数为空,被引用时抛出异常
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R deleteCodeBasicSecByPrimaryKey(String oid) throws VciBaseException {
        CodeBasicSec codeBasicSecDO = selectByOid(oid);
        boolean isLinked = checkIsLinked(codeBasicSecDO.getPkCodeRule(), oid);
        if (isLinked) {
            return R.fail("编码规则已被引用,不允许编辑或删除");
        }
        //执行删除操作
        boolean eftDeleteBasic = codeBasicSecMapper.deleteById(oid) > 0;
        if (CodeSecTypeEnum.CODE_FIXED_SEC.getValue().equals(codeBasicSecDO.getSecType())){
            List<CodeFixedValue> fixedValueDOS = fixedValueMapper.selectList(Wrappers.<CodeFixedValue>query()
                .lambda().eq(CodeFixedValue::getCodeFixedSecOid,codeBasicSecDO.getOid())
            );
            if(!CollectionUtils.isEmpty(fixedValueDOS)){
                fixedValueMapper.deleteBatchIds(fixedValueDOS.stream().map(CodeFixedValue::getOid).collect(Collectors.toSet()));
            }
        }
        if (CodeSecTypeEnum.CODE_CLASSIFY_SEC.getValue().equals(codeBasicSecDO.getSecType())){
            List<CodeClassifyValue> classifyValueDOS = codeClassifyValueMapper.selectList(Wrappers.<CodeClassifyValue>query()
                .lambda().eq(CodeClassifyValue::getCodeClassifySecOid,codeBasicSecDO.getOid())
            );
            if(!CollectionUtils.isEmpty(classifyValueDOS)) {
                codeClassifyValueMapper.deleteBatchIds(classifyValueDOS.stream().map(CodeClassifyValue::getOid).collect(Collectors.toSet()));
            }
        }
 
        return eftDeleteBasic ? R.success(DELETE_SUCCESS) : R.fail(DELETE_FAIL);
    }
 
    /**
     * 主键获取码段基础信息
     *
     * @param oid 主键
     * @return 码段基础信息显示对象
     * @throws VciBaseException 参数为空,数据不存在时会抛出异常
     */
    @Override
    public CodeBasicSecVO getObjectByOid(String oid) throws VciBaseException {
        return CodeBasicSecWrapper.build().entityVO(selectByOid(oid));
    }
 
    /**
     * 主键批量获取码段基础信息
     *
     * @param oidCollections 主键集合,但是受性能影响,建议一次查询不超过10000个
     * @return 码段基础信息显示对象
     * @throws VciBaseException 查询出现异常时会抛出
     */
    @Override
    public Collection<CodeBasicSecVO> listCodeBasicSecByOids(Collection<String> oidCollections) throws VciBaseException {
        VciBaseUtil.alertNotNull(oidCollections, "数据对象主键集合");
        List<CodeBasicSec> codeBasicSecDOList = listCodeBasicSecDOByOidCollections(oidCollections);
        return CodeBasicSecWrapper.build().listVO(codeBasicSecDOList);
    }
 
    /**
     * 参照码段基础信息列表
     *
     * @param conditionMap 查询条件
     * @param query 分页和排序
     * @return 码段基础信息显示对象列表,生效的内容
     * @throws VciBaseException 查询条件和分页出错的时候会抛出异常
     */
    @Override
    public IPage<CodeBasicSecVO> refDataGridCodeBasicSec(Query query ,Map<String,Object> conditionMap) throws VciBaseException {
        return gridCodeBasicSec(query,conditionMap);
    }
 
    /**
     * 参照分类的码段
     * @param conditionMap 查询条件
     * @param query 分页和排序
     * @return 码段的内容
     */
    @Override
    public IPage<CodeBasicSecVO> refDataGridClassifySec(Query query ,Map<String,Object> conditionMap) throws VciBaseException {
        if(Func.isEmpty(conditionMap.get("pkCodeRule"))){
            return null;
        }
        conditionMap.put("secType",(CodeSecTypeEnum.CODE_CLASSIFY_SEC.getValue()));
        return refDataGridCodeBasicSec(query.setAscs("orderNum"),conditionMap);
    }
 
    /**
     * 克隆码段信息
     *
     * @param oidList 源码段信息主键集合
     * @param pkCodeRule 目标编码规则
     * @return 克隆结果反馈::success:成功,fail:失败
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R cloneCodeBasicSec(List<String> oidList, String pkCodeRule) throws ServiceException, ServerException {
        boolean isLinked = checkIsLinked(pkCodeRule,null);
        if (isLinked) {
            return R.fail("编码规则已被引用,不允许编辑或删除");
        }
        List<CodeBasicSec> createList = new ArrayList<>();
        List<CodeBasicSec> basicSecDOS = codeBasicSecMapper.selectBatchIds(oidList);
        /* 需要注意的是克隆过来的码段需要对orderNum进行排序,否则会出现排序乱跳的情况
        实现方式是查询出该规则下根据orderNum排序后的最后一个码段    */
        LambdaQueryWrapper<CodeBasicSec> lastBasicWrapper = Wrappers.<CodeBasicSec>query()
            .lambda().orderByDesc(CodeBasicSec::getOrderNum)
            .eq(CodeBasicSec::getPkCodeRule,pkCodeRule)
            .last("limit 1");
        CodeBasicSec lastCodeBasicSec = codeBasicSecMapper.selectOne(lastBasicWrapper);
        // 排序号从这儿开始排
        int orderNum = Func.isEmpty(lastCodeBasicSec) || Func.isEmpty(lastCodeBasicSec.getOrderNum()) ? -1 : lastCodeBasicSec.getOrderNum();
        if(basicSecDOS.isEmpty()){
            return R.fail("克隆的码段信息不存在!");
        }
        List<CodeBasicSec> codeClassifySec = new ArrayList<>();
        Map<String,List<CodeFixedValue>> codeFixedValueMaps = new HashMap<>();
        for (CodeBasicSec sec : basicSecDOS) {
            CodeBasicSec newSecDO = new CodeBasicSec();
            BeanUtilForVCI.copyPropertiesIgnoreCase(sec,newSecDO);
            String oldBasicOid = newSecDO.getOid();
            newSecDO.setId(newSecDO.getId());
            newSecDO.setName(newSecDO.getName());
            orderNum++;
            newSecDO.setOrderNum(orderNum);
            newSecDO.setPkCodeRule(pkCodeRule);
            // 判断是否是分类码段,业务逻辑稍微复杂一点所以需要先提出来单独处理
            if(newSecDO.getSecType().equals(CodeSecTypeEnum.CODE_CLASSIFY_SEC.getValue())){
                // 存储旧的码段oid和新的码段的oid的关联关系
                codeClassifySec.add(newSecDO);
                continue;
            }
            // 更改创建时间,修改时间等默认值
            DefaultAttrAssimtUtil.addDefaultAttrAssimt(newSecDO,MdmBtmTypeConstant.CODE_BASIC_SEC);
            //固定码段
            if(newSecDO.getSecType().equals(CodeSecTypeEnum.CODE_FIXED_SEC.getValue())){
                // 固定码段存储好oid和码值的关联关系
                codeFixedValueMaps.put(newSecDO.getOid(),fixedValueService.list(Wrappers.<CodeFixedValue>query()
                    .lambda().eq(CodeFixedValue::getCodeFixedSecOid, oldBasicOid)
                ));
            }
            createList.add(newSecDO);
        }
        // 处理分类码段的oid,因为oid关联parentClassifyOid,与码值codeClassifyOid,码值又需要通过旧的码段oid来查询,所以不能直接改变oid
        changeParentOidAssnOid(codeClassifySec);
        // 将处理过的分类码段也添加进要做新增处理的码段集合中
        createList.addAll(codeClassifySec);
        boolean resBoolean = true;
        if(!createList.isEmpty()){
            resBoolean = saveBatch(createList);
        }
        // 最终要存入码值表中的,码值对象
        List<CodeFixedValue> codeFixedDOValues = new ArrayList<>();
        // 构造码值对象,与码段主键关联关系,以及改变固定码值的oid
        codeFixedValueMaps.forEach((key, value) -> {
            value.stream().forEach(item -> {
                item.setOid("");
                item.setCodeFixedSecOid(key);
                DefaultAttrAssimtUtil.updateDefaultAttrAssimt(item);
                codeFixedDOValues.add(item);
            });
        });
        boolean resFixed = true;
        if(!codeFixedValueMaps.isEmpty()){
            // 克隆固定码值
            resFixed = fixedValueService.saveBatch(codeFixedDOValues);
        }
        return (resBoolean&&resFixed) ? R.data(resBoolean,"克隆码段信息成功"):R.fail("克隆码段信息失败!");
    }
 
    /**
     * 改变码段中父分类码段和子分类码段之间的关联oid为新的oid,并且不破坏分类码值的关联关系
     * @param basicSecs
     * @return
     * @throws ServerException
     */
    @Override
    public boolean changeParentOidAssnOid(List<CodeBasicSec> basicSecs) throws ServerException {
        Map<String, List<CodeClassifyValue>> codeClassValues = new HashMap<>();
        List<CodeClassifyValue> codeClassifyDOValues = new ArrayList<>();
        HashMap<String, String> oidMap = new HashMap<>();
        boolean resClone = false;
        try {
            // 遍历对象数组,为每个对象生成新的oid,并将原始oid和新oid的映射关系存储到Map中
            for (CodeBasicSec obj : basicSecs) {
                String originalOid = obj.getOid();
                String newOid = VciBaseUtil.getPk();
                oidMap.put(originalOid, newOid);
            }
            // 遍历对象数组,更新每个对象的oid和codeClassifySecOid属性值
            for (CodeBasicSec obj : basicSecs) {
                String originalOid = obj.getOid();
                String newOid = oidMap.get(originalOid);
                // 新的oid关联要克隆码值
                codeClassValues.put(newOid,codeClassifyValueService.list(Wrappers.<CodeClassifyValue>query()
                    .lambda().eq(CodeClassifyValue::getCodeClassifySecOid, originalOid)));
                obj.setOid(newOid);
                String originalParentClassifyValueOid = obj.getParentClassifySecOid();
                String newParentClassifyValueOid = oidMap.get(originalParentClassifyValueOid);
                obj.setParentClassifySecOid(newParentClassifyValueOid);
            }
            codeClassValues.forEach((key, value) -> {
                value.stream().forEach(item -> {
                    DefaultAttrAssimtUtil.updateDefaultAttrAssimt(item);
                    item.setCodeClassifySecOid(key);
                    codeClassifyDOValues.add(item);
                });
            });
            resClone = codeClassifyValueService.cloneCodeClassifyVaue(codeClassifyDOValues);
        }catch (Exception e){
            throw new ServerException("父分类码段和子分类码段clone转换oid时出错:"+e.getCause());
        }
        return resClone;
    }
 
    /**
     * 查询目标分类码段所在的树结构
     *
     * @param oid 目标分类码段主键
     * @return 分类码段树结构
     */
    /*@Override
    public List<Tree> gridCodeClassifySecTree(String oid) {
        VciParentQueryOption queryOption = new VciParentQueryOption(PARENT_FIELD_NAME);
        queryOption.setfOid(oid);
        queryOption.setLinkTypeFlag(false);
        queryOption.setHasSelf(true);
        VciQueryWrapperForDO wrapper = new VciQueryWrapperForDO(CodeBasicSec.class);
        wrapper.childQueryParent(queryOption);
        List<CodeBasicSec> doList = codeBasicSecMapper.selectByWrapper(wrapper);
        List<String> secOid = new ArrayList<>();
        doList.forEach(o -> secOid.add(o.getOid()));
        List<CodeClassifyValueVO> valueVOs = (List<CodeClassifyValueVO>) codeClassifyValueService.listCodeClassifyValueByOids(secOid);
        TreeQueryObject treeQueryObject = new TreeQueryObject();
        treeQueryObject.setMultipleSelect(false);
        treeQueryObject.setShowCheckBox(false);
        treeQueryObject.setQueryAllLevel(false);
        treeQueryObject.setValueField("oid");
        treeQueryObject.setTextField("name");
        treeQueryObject.setQueryAllRev(false);
        TreeWrapperOptions treeWrapperOptions = new TreeWrapperOptions(PARENT_CLASSIFY_VALUE_FIELD_NAME);
        treeWrapperOptions.copyFromTreeQuery(treeQueryObject);
        return revisionModelUtil.doList2Trees(valueVOs,treeWrapperOptions,(CodeClassifyValueVO s) ->{
            //可以在这里处理树节点的显示
            return s.getId() + " " + s.getName() + (FrameworkDataLCStatus.DISABLED.getValue().equalsIgnoreCase(s
                .getLcStatus()) ? (" 【停用】 ") : "");
        });
    }*/
 
    /**
     * 上移
     *
     * @param oid 主键
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean upOrderNum(String oid) throws ServiceException{
        CodeBasicSec secDO = selectByOid(oid);
        if(secDO.getOrderNum() > 1){
            //等于1的时候不能上移了
            //找比自己小的
            List<CodeBasicSec> lastSecDOs = codeBasicSecMapper.selectList(Wrappers.<CodeBasicSec>query()
                .lambda().eq(CodeBasicSec::getPkCodeRule,secDO.getPkCodeRule())
                .eq(CodeBasicSec::getOrderNum,String.valueOf(secDO.getOrderNum()-1))
            );
            if(!CollectionUtils.isEmpty(lastSecDOs)){
                CodeBasicSec lastSec = lastSecDOs.get(0);
                codeBasicSecMapper.update(null, Wrappers.<CodeBasicSec>update()
                    .lambda().set(CodeBasicSec::getOrderNum, lastSec.getOrderNum() + 1)
                    .eq(CodeBasicSec::getOid, lastSec.getOid())
                );
            }
            codeBasicSecMapper.update(null, Wrappers.<CodeBasicSec>update()
                .lambda().set(CodeBasicSec::getOrderNum, secDO.getOrderNum() - 1)
                .eq(CodeBasicSec::getOid, secDO.getOid())
            );
        }
        return true;
    }
 
    /**
     * 下移
     *
     * @param oid 主键
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean downOrderNum(String oid) throws ServiceException {
        CodeBasicSec secDO = selectByOid(oid);
        Long total = codeBasicSecMapper.selectCount(Wrappers.<CodeBasicSec>query()
            .lambda().eq(CodeBasicSec::getPkCodeRule,secDO.getPkCodeRule())
        );
        if(secDO.getOrderNum() < total){
            //小于总数的时候才下移
            List<CodeBasicSec> lastSecDOs = codeBasicSecMapper.selectList(Wrappers.<CodeBasicSec>query()
                .lambda().eq(CodeBasicSec::getOrderNum,secDO.getOrderNum()+1)
                .eq(CodeBasicSec::getPkCodeRule,secDO.getPkCodeRule())
            );
            if(!CollectionUtils.isEmpty(lastSecDOs)){
                CodeBasicSec lastSec = lastSecDOs.get(0);
                codeBasicSecMapper.update(null, Wrappers.<CodeBasicSec>update()
                    .lambda().set(CodeBasicSec::getOrderNum, lastSec.getOrderNum() - 1)
                    .eq(CodeBasicSec::getOid, lastSec.getOid())
                );
            }
            codeBasicSecMapper.update(null, Wrappers.<CodeBasicSec>update()
                .lambda().set(CodeBasicSec::getOrderNum, secDO.getOrderNum() + 1)
                .eq(CodeBasicSec::getOid, secDO.getOid())
            );
        }
        return true;
    }
 
    /**
     * 树形结构查询oid
     * @param codeClassifySecOid
     * @return
     */
    @Override
    public List<String> getOidByCodeclassifysecOid(String codeClassifySecOid)throws ServiceException {
        return codeBasicSecMapper.getOidByCodeclassifysecOid(codeClassifySecOid.trim());
    }
 
    /**
     * 校验是否被引用
     *
     * @param codeRuleOid     编码规则主键
     * @param codeBasicSecOid 编码基础信息主键
     * @return true表示已被引用,false表示未被引用
     * @throws VciBaseException 被引用的时候会抛出异常
     */
    private boolean checkIsLinked(String codeRuleOid, String codeBasicSecOid) throws VciBaseException {
        boolean flag = true;
        if (StringUtils.isNotBlank(codeRuleOid)) {
            boolean status = codeRuleService.checkEditDelStatus(codeRuleService.getObjectByOid(codeRuleOid).getLcStatus());
            if (!status){
                return true;
            }
            boolean alreadyInUse = codeRuleService.isAlreadyInUse(codeRuleOid);
            if (!alreadyInUse){
                flag = false;
            }
        } else {
            boolean status = codeRuleService.checkEditDelStatus(codeRuleService.getObjectByOid(codeBasicSecMapper.selectById(codeBasicSecOid).getPkCodeRule()).getLcStatus());
            if (!status){
                return true;
            }
            boolean alreadyInUse = codeRuleService.isAlreadyInUse(codeBasicSecMapper.selectById(codeBasicSecOid).getPkCodeRule());
            if (!alreadyInUse){
                flag = false;
            }
        }
        return flag;
    }
 
    /**
     * 使用主键集合查询数据对象
     *
     * @param oidCollections 主键的集合
     * @return 数据对象列表
     */
    private List<CodeBasicSec> listCodeBasicSecDOByOidCollections(Collection<String> oidCollections) {
        List<CodeBasicSec> codeBasicSecDOList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(oidCollections)) {
            Collection<Collection<String>> oidCollectionsList = VciBaseUtil.switchCollectionForOracleIn(oidCollections);
            for (Collection<String> oids : oidCollectionsList) {
                List<CodeBasicSec> tempDOList = codeBasicSecMapper.selectBatchIds(oids);
                if (!CollectionUtils.isEmpty(tempDOList)) {
                    codeBasicSecDOList.addAll(tempDOList);
                }
            }
        }
        return codeBasicSecDOList;
    }
 
    /**
     * 主键查询数据对象
     *
     * @param oid 主键
     * @return 数据对象
     * @throws VciBaseException 参数为空,并且数据不存在的时候会抛出异常
     */
    private CodeBasicSec selectByOid(String oid) throws VciBaseException {
        VciBaseUtil.alertNotNull(oid, "主键");
        CodeBasicSec codeBasicSecDO = codeBasicSecMapper.selectById(oid.trim());
        if (codeBasicSecDO == null || StringUtils.isBlank(codeBasicSecDO.getOid())) {
            throw new VciBaseException(DATA_OID_NOT_EXIST);
        }
        return codeBasicSecDO;
    }
 
    /**
     * 使用规则的主键获取对应的码段内容
     *
     * @param ruleOid 规则的内容
     * @return 码段的内容
     */
    @Override
    public List<CodeBasicSecVO> listCodeBasicSecByRuleOid(String ruleOid)throws ServiceException {
        if(StringUtils.isBlank(ruleOid)){
            return new ArrayList<>();
        }
        LambdaQueryWrapper<CodeBasicSec> wrapper = Wrappers.<CodeBasicSec>query().lambda()
            .eq(CodeBasicSec::getPkCodeRule, ruleOid)
            .orderByAsc(CodeBasicSec::getOrderNum);
        List<CodeBasicSec> secDOList = baseMapper.selectList(wrapper);//
        return codeBasicSecDO2VOs(secDOList,true);
    }
 
    /**
     * 批量数据对象转换为显示对象
     *
     * @param codeBasicSecDOs 数据对象列表
     * @param hasFixedValue 是否有固定值
     * @return 显示对象
     * @throws VciBaseException 参数为空或者不存在的时候会抛出异常
     */
    @Override
    public List<CodeBasicSecVO> codeBasicSecDO2VOs(Collection<CodeBasicSec> codeBasicSecDOs, boolean hasFixedValue) throws VciBaseException {
        List<CodeBasicSecVO> voList = new ArrayList<CodeBasicSecVO>();
        if (!CollectionUtils.isEmpty(codeBasicSecDOs)) {
            for (CodeBasicSec s : codeBasicSecDOs) {
                CodeBasicSecVO vo = codeBasicSecDO2VO(s);
                if (vo != null) {
                    voList.add(vo);
                }
            }
        }
        if(hasFixedValue && !CollectionUtils.isEmpty(voList)){
            List<CodeBasicSecVO> fixedSecVOList = voList.stream().filter(s -> CodeSecTypeEnum.CODE_FIXED_SEC.getValue().equalsIgnoreCase(s.getSecType())).collect(Collectors.toList());
            if(!CollectionUtils.isEmpty(fixedSecVOList)){
                //查询固定码的码值
                Map<String, List<CodeFixedValueVO>> secValueMap = fixedValueService.listCodeFixedValueBySecOids(fixedSecVOList.stream().map(CodeBasicSecVO::getOid).collect(Collectors.toList()));
                voList.stream().forEach(vo->{
                    vo.setFixedValueVOList(secValueMap.getOrDefault(vo.getOid(),null));
                });
            }
        }
        return voList;
    }
 
    /**
     * 批量数据对象转换为显示对象
     *
     * @param codeBasicSecDOs 数据对象列表
     * @return 显示对象
     * @throws VciBaseException 参数为空或者不存在的时候会抛出异常
     */
    @Override
    public List<CodeBasicSecVO> codeBasicSecDO2VOs(Collection<CodeBasicSec> codeBasicSecDOs) throws VciBaseException {
        List<CodeBasicSecVO> voList = new ArrayList<CodeBasicSecVO>();
        if (!CollectionUtils.isEmpty(codeBasicSecDOs)) {
            for (CodeBasicSec s : codeBasicSecDOs) {
                CodeBasicSecVO vo = codeBasicSecDO2VO(s);
                if (vo != null) {
                    voList.add(vo);
                }
            }
        }
        return voList;
    }
 
    /**
     * 数据对象转换为显示对象
     *
     * @param codeBasicSecDO 数据对象
     * @return 显示对象
     * @throws VciBaseException 拷贝属性出错的时候会抛出异常
     */
    @Override
    public CodeBasicSecVO codeBasicSecDO2VO(CodeBasicSec codeBasicSecDO) throws VciBaseException {
        CodeBasicSecVO codeBasicSecVO = new CodeBasicSecVO();
        if (codeBasicSecDO != null) {
            BeanUtilForVCI.copyPropertiesIgnoreCase(codeBasicSecDO, codeBasicSecVO);
            if(StringUtils.isNotBlank(codeBasicSecDO.getSecType())){
                codeBasicSecVO.setSecTypeText(EnumCache.getValue(EnumEnum.CODE_SEC_TYPE,codeBasicSecDO.getSecType()));
            }
            if(StringUtils.isNotBlank(codeBasicSecDO.getCodeLevelType())){
                codeBasicSecVO.setCodeLevelTypeText(EnumCache.getValue(EnumEnum.CODE_LEVEL_TYPE,codeBasicSecDO.getCodeLevelType()));
            }
            if(StringUtils.isNotBlank(codeBasicSecDO.getCodeSecLengthType())){
                codeBasicSecVO.setCodeSecLengthTypeText(EnumCache.getValue(EnumEnum.CODE_SEC_LENGTH,codeBasicSecDO.getCodeSecLengthType()));
            }
            if(StringUtils.isNotBlank(codeBasicSecDO.getValueCutType())){
                codeBasicSecVO.setValueCutTypeText(EnumCache.getValue(EnumEnum.CODE_CUT_TYPE,codeBasicSecDO.getValueCutType()));
            }
            if(StringUtils.isNotBlank(codeBasicSecDO.getCodeGetValueType())){
                codeBasicSecVO.setCodeGetValueTypeText(EnumCache.getValue(EnumEnum.CODE_GET_VALUE_TYPE,codeBasicSecDO.getCodeGetValueType()));
            }
            // 如果是分类码段需要查询所属分类的中文名称
            if(codeBasicSecDO.getSecType().equals("codeclassifysec") && Func.isNotEmpty(codeBasicSecDO.getParentClassifySecOid())){
                CodeBasicSec codeBasicSec = codeBasicSecMapper.selectOne(Wrappers.<CodeBasicSec>query().lambda()
                    .eq(CodeBasicSec::getOid, codeBasicSecDO.getParentClassifySecOid())
                    .eq(CodeBasicSec::getSecType, codeBasicSecDO.getSecType()));
                if(Func.isNotEmpty(codeBasicSec)){
                    codeBasicSecVO.setParentClassifySecOid(codeBasicSec.getOid());
                    codeBasicSecVO.setParentClassifySecText(codeBasicSec.getName());
                }
            }
            //如果有lcstatus的类的话
            if (true) {
                //vo.setLcStatusText({lcStatusFullClassName}.getTextByValue(vo.getLcStatus()));
            }
        }
        return codeBasicSecVO;
    }
 
    /**
     * 根据编码规则主键获取编码下的流水依赖码段
     *
     * @param oid 编码规则主键
     * @return
     * @throws VciBaseException
     */
    @Override
    public CodeRuleVO getSerialNumberDepend(String oid) throws VciBaseException {
        VciBaseUtil.alertNotNull(oid,"编码规则主键");
        CodeRuleVO codeRuleVO = codeRuleService.getObjectByOid(oid);
        if (codeRuleVO != null) {
            //如果有lcstatus的类的话
            codeRuleVO.setLcStatusText(CodeRuleLC.getTextByValue(codeRuleVO.getLcStatus()));
 
            LambdaQueryWrapper<CodeBasicSec> wrapper = Wrappers.<CodeBasicSec>query().lambda()
                .eq(CodeBasicSec::getPkCodeRule, codeRuleVO.getOid())
                .eq(CodeBasicSec::getSecType,CodeSecTypeEnum.CODE_SERIAL_SEC.getValue());
            CodeBasicSec codeBasicSec = this.getOne(wrapper);
            if(codeBasicSec != null && VciBaseUtil.isNotNull(codeBasicSec.getOid())){
                wrapper = Wrappers.<CodeBasicSec>query().lambda()
                    .eq(CodeBasicSec::getPkCodeRule,codeRuleVO.getOid())
                    .eq(CodeBasicSec::getSerialDependFlag,"true")
                    .orderByAsc(CodeBasicSec::getOrderNum);
                    //.orderByAsc(CodeBasicSec::getSerialDependOrder);
                List<CodeBasicSec> codeBasicSecList = this.list(wrapper);
                if(!CollectionUtils.isEmpty(codeBasicSecList)){
                    List<CodeBasicSecVO> codeBasicSecVOS = codeBasicSecDO2VOs(codeBasicSecList);
                    //查询固定码的码值
                    Map<String, List<CodeFixedValueVO>> secValueMap = fixedValueService.listCodeFixedValueBySecOids(codeBasicSecList.stream().map(CodeBasicSec::getOid).collect(Collectors.toList()));
                    codeBasicSecVOS.stream().forEach(vo->{
                        vo.setFixedValueVOList(secValueMap.getOrDefault(vo.getOid(),null));
                    });
                    codeRuleVO.setSecVOList(codeBasicSecVOS);
                }
            }else{
                throw new VciBaseException(codeRuleVO.getName()+"编码规则下无流水码段,无法设置最大流水号!");
            }
        }
        return codeRuleVO;
    }
 
    /**
     * 设置最大流水号
     *
     * @param codeOrderDTO 编码申请传输对象
     * @return
     * @throws VciBaseException
     */
    @Override
    public String setMaxSerialNumberForCodeRule(CodeOrderDTO codeOrderDTO) throws VciBaseException {
        VciBaseUtil.alertNotNull(codeOrderDTO.getCodeRuleOid(),"编码规则主键",codeOrderDTO.getMaxSecNum(),"最大流水号");
        List<CodeOrderSecDTO> codeOrderSecDTOList = codeOrderDTO.getSecDTOList();
        if(CollectionUtils.isEmpty(codeOrderSecDTOList)){
            throw new VciBaseException("最大流水号的流水依赖不能为空!");
        }
 
        String codeRuleOid = codeOrderDTO.getCodeRuleOid();
        int maxSecNum = codeOrderDTO.getMaxSecNum();
 
        Map<String/**码段主键*/,CodeOrderSecDTO/**码段相关信息*/> codeOrderSecDTOMap = codeOrderSecDTOList.stream().collect(Collectors.toMap(s -> s.getSecOid(), t -> t));
        List<String> codeBasicSecOidList = codeOrderSecDTOList.stream().map(s->s.getSecOid()).collect(Collectors.toList());//流水依赖码段的主键集合
 
        //获取流水依赖码段
        LambdaQueryWrapper<CodeBasicSec> wrapper = Wrappers.<CodeBasicSec>query().lambda()
            .eq(CodeBasicSec::getPkCodeRule,codeRuleOid)
            .in(CodeBasicSec::getOid,codeBasicSecOidList)
            .eq(CodeBasicSec::getSerialDependFlag,"true")
            //TODO: SerialDependOrder本来是用来流水排序的,但是现在的逻辑是按照orderuNum排序的
            .orderByAsc(CodeBasicSec::getOrderNum); //.orderByAsc(CodeBasicSec::getSerialDependOrder);
        List<CodeBasicSec> codeBasicSecList = this.list(wrapper);
 
        //按流水依赖顺序,处理流水依赖码段的值
        List<String> serialDependValueList = new ArrayList<>();
        codeBasicSecList.stream().forEach(s->{
            CodeOrderSecDTO codeOrderSecDTO = codeOrderSecDTOMap.get(s.getOid());
            String serialDependValue = codeOrderSecDTO.getSecValue();
            if(s.getSecType().equals(CodeSecTypeEnum.CODE_DATE_SEC.getValue())){
                try {
                    Date date = VciDateUtil.str2Date(codeOrderSecDTO.getSecValue(),s.getCodeDateFormatStr());
                    serialDependValue = VciDateUtil.date2Str(date,s.getCodeDateFormatStr());
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }
            serialDependValueList.add(serialDependValue);
        });
 
        //获取流水码段
        wrapper = Wrappers.<CodeBasicSec>query().lambda()
            .eq(CodeBasicSec::getPkCodeRule,codeRuleOid)
            .eq(CodeBasicSec::getSecType,CodeSecTypeEnum.CODE_SERIAL_SEC.getValue())
            .orderByAsc(CodeBasicSec::getSerialDependOrder);
        CodeBasicSec codeBasicSec = this.getOne(wrapper);
 
        //根据编码规则和流水依赖,获取最大流水号
        String serialUnitString = serialDependValueList.size() == 0 ? EMPTY_SERIAL_UNIT : serialDependValueList.stream().collect(Collectors.joining(SERIAL_UNIT_SPACE));
        LambdaQueryWrapper<CodeSerialValue> codeSerialWrapper = new LambdaQueryWrapper<>();
        codeSerialWrapper.eq(CodeSerialValue::getCodeRuleOid, codeRuleOid);
        codeSerialWrapper.eq(CodeSerialValue::getSerialUnit, serialUnitString);
        codeSerialWrapper.eq(CodeSerialValue::getCodeSecOid,codeBasicSec.getOid());
        codeSerialWrapper.orderByDesc(CodeSerialValue::getCreateTime);
        List<CodeSerialValue> codeSerialValueList = serialValueMapper.selectList(codeSerialWrapper);
 
        //如果最大流水号不为空,说明已有最好流水号,更新最大流水号
        if(!CollectionUtils.isEmpty(codeSerialValueList)){
            CodeSerialValue codeSerialValue = codeSerialValueList.get(0);
            int maxSerial = Double.valueOf(codeSerialValue.getMaxSerial()).intValue();
            //已有的最大流水号,小于设置的最大流水号,更新最大流水号
            if(maxSerial < maxSecNum){
                codeSerialValue.setMaxSerial(String.valueOf(maxSecNum));
                serialValueMapper.updateById(codeSerialValue);
            }else{
                maxSecNum = maxSerial;
            }
        }else{
            //如果最大流水号不为空,说明无最好流水号,新增最大流水号
            CodeSerialValue codeSerialValue = new CodeSerialValue();
            DefaultAttrAssimtUtil.addDefaultAttrAssimt(codeSerialValue, MdmBtmTypeConstant.CODE_SERIAL_VALUE);
            codeSerialValue.setCodeRuleOid(codeRuleOid);
            codeSerialValue.setSerialUnit(serialUnitString);
            codeSerialValue.setCodeSecOid(codeBasicSec.getOid());
            codeSerialValue.setMaxSerial(String.valueOf(maxSecNum));
            serialValueMapper.insert(codeSerialValue);
        }
        return String.valueOf(maxSecNum);
    }
 
    /***
     * 根据流水依赖获取最大流水号
     * @param codeOrderDTO 编码申请传输对象
     * @return
     */
    @Override
    public Double getMaxSerialNumberForCodeRule(CodeOrderDTO codeOrderDTO) {
        Double maxSerialNumber=0.0;
        VciBaseUtil.alertNotNull(codeOrderDTO.getCodeRuleOid(),"编码规则主键");
        List<CodeOrderSecDTO>  codeOrderSecDTOList=codeOrderDTO.getSecDTOList();
        if(CollectionUtils.isEmpty(codeOrderSecDTOList)){
            throw new VciBaseException("最大流水号的流水依赖不能为空!");
        }
        String codeRuleOid = codeOrderDTO.getCodeRuleOid();
        Map<String/**码段主键*/,CodeOrderSecDTO/**码段相关信息*/> codeOrderSecDTOMap = codeOrderSecDTOList.stream().collect(Collectors.toMap(s -> s.getSecOid(), t -> t));
        List<String> codeBasicSecOidList = codeOrderSecDTOList.stream().map(s->s.getSecOid()).collect(Collectors.toList());//流水依赖码段的主键集合
        //获取流水依赖码段
        LambdaQueryWrapper<CodeBasicSec> wrapper = Wrappers.<CodeBasicSec>query().lambda()
            .eq(CodeBasicSec::getPkCodeRule,codeRuleOid)
            .in(CodeBasicSec::getOid,codeBasicSecOidList)
            .eq(CodeBasicSec::getSerialDependFlag,"true")
            .orderByAsc(CodeBasicSec::getOrderNum); //.orderByAsc(CodeBasicSec::getSerialDependOrder);
 
        List<CodeBasicSec> codeBasicSecList = this.list(wrapper);
        //按流水依赖顺序,处理流水依赖码段的值
        List<String> serialDependValueList = new ArrayList<>();
        codeBasicSecList.stream().forEach(s->{
            CodeOrderSecDTO codeOrderSecDTO = codeOrderSecDTOMap.get(s.getOid());
            String serialDependValue = codeOrderSecDTO.getSecValue();
            if(s.getSecType().equals(CodeSecTypeEnum.CODE_DATE_SEC.getValue())){
                try {
                    Date date = VciDateUtil.str2Date(codeOrderSecDTO.getSecValue(),s.getCodeDateFormatStr());
                    serialDependValue = VciDateUtil.date2Str(date,s.getCodeDateFormatStr());
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }
            serialDependValueList.add(serialDependValue);
        });
 
        //获取流水码段
        wrapper = Wrappers.<CodeBasicSec>query().lambda()
            .eq(CodeBasicSec::getPkCodeRule,codeRuleOid)
            .eq(CodeBasicSec::getSecType,CodeSecTypeEnum.CODE_SERIAL_SEC.getValue())
            .orderByAsc(CodeBasicSec::getSerialDependOrder);
        CodeBasicSec codeBasicSec = this.getOne(wrapper);
        //根据编码规则和流水依赖,获取最大流水号
        String serialUnitString = serialDependValueList.size() == 0 ? EMPTY_SERIAL_UNIT : serialDependValueList.stream().collect(Collectors.joining(SERIAL_UNIT_SPACE));
        LambdaQueryWrapper<CodeSerialValue> codeSerialWrapper = new LambdaQueryWrapper<>();
        codeSerialWrapper.eq(CodeSerialValue::getCodeRuleOid, codeRuleOid);
        codeSerialWrapper.eq(CodeSerialValue::getSerialUnit, serialUnitString);
        codeSerialWrapper.eq(CodeSerialValue::getCodeSecOid,codeBasicSec.getOid());
        codeSerialWrapper.orderByDesc(CodeSerialValue::getCreateTime);
        List<CodeSerialValue> codeSerialValueList = serialValueMapper.selectList(codeSerialWrapper);
        if(!CollectionUtils.isEmpty(codeSerialValueList)){
            maxSerialNumber=StringUtils.isBlank(codeSerialValueList.get(0).getMaxSerial())?0:Double.parseDouble(codeSerialValueList.get(0).getMaxSerial());
        }
        return maxSerialNumber;
    }
}