From 46dee74c10dec50da88dbf7919fc33d783102d08 Mon Sep 17 00:00:00 2001 From: lichao <326994889@qq.com> Date: Wed, 10 May 2023 17:50:46 +0800 Subject: [PATCH 1/6] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E7=B1=BB=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/impl/IcNeighborHoodServiceImpl.java | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/epmet-module/gov-org/gov-org-server/src/main/java/com/epmet/service/impl/IcNeighborHoodServiceImpl.java b/epmet-module/gov-org/gov-org-server/src/main/java/com/epmet/service/impl/IcNeighborHoodServiceImpl.java index 038ad89a68..f6271ba3b9 100644 --- a/epmet-module/gov-org/gov-org-server/src/main/java/com/epmet/service/impl/IcNeighborHoodServiceImpl.java +++ b/epmet-module/gov-org/gov-org-server/src/main/java/com/epmet/service/impl/IcNeighborHoodServiceImpl.java @@ -629,16 +629,17 @@ public class IcNeighborHoodServiceImpl extends BaseServiceImpl Date: Thu, 11 May 2023 09:24:27 +0800 Subject: [PATCH 2/6] =?UTF-8?q?customerId=E6=96=B0=E5=A2=9E=E6=B3=A8?= =?UTF-8?q?=E8=A7=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/epmet/entity/CommunityBuildingManagerEntity.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/epmet-module/gov-org/gov-org-server/src/main/java/com/epmet/entity/CommunityBuildingManagerEntity.java b/epmet-module/gov-org/gov-org-server/src/main/java/com/epmet/entity/CommunityBuildingManagerEntity.java index dc2e57bd94..1c769d2926 100644 --- a/epmet-module/gov-org/gov-org-server/src/main/java/com/epmet/entity/CommunityBuildingManagerEntity.java +++ b/epmet-module/gov-org/gov-org-server/src/main/java/com/epmet/entity/CommunityBuildingManagerEntity.java @@ -1,5 +1,7 @@ package com.epmet.entity; +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableName; import com.epmet.commons.mybatis.entity.BaseEpmetEntity; import lombok.Data; @@ -21,6 +23,7 @@ public class CommunityBuildingManagerEntity extends BaseEpmetEntity { /** * 客户Id customer.id */ + @TableField(fill = FieldFill.INSERT) private String customerId; /** From 41fe49d895f7f62fe921338934cc7ad76dae1b58 Mon Sep 17 00:00:00 2001 From: lichao <326994889@qq.com> Date: Thu, 11 May 2023 09:48:29 +0800 Subject: [PATCH 3/6] =?UTF-8?q?=E6=A5=BC=E6=B4=9E=E5=AF=BC=E5=85=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../epmet/service/impl/IcNeighborHoodServiceImpl.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/epmet-module/gov-org/gov-org-server/src/main/java/com/epmet/service/impl/IcNeighborHoodServiceImpl.java b/epmet-module/gov-org/gov-org-server/src/main/java/com/epmet/service/impl/IcNeighborHoodServiceImpl.java index f6271ba3b9..f9c10cf973 100644 --- a/epmet-module/gov-org/gov-org-server/src/main/java/com/epmet/service/impl/IcNeighborHoodServiceImpl.java +++ b/epmet-module/gov-org/gov-org-server/src/main/java/com/epmet/service/impl/IcNeighborHoodServiceImpl.java @@ -707,9 +707,10 @@ public class IcNeighborHoodServiceImpl extends BaseServiceImpl agencyIds = new ArrayList<>(Arrays.asList(neighborHood.getAgencyPids().split(":"))); + agencyIds.add(neighborHood.getAgencyId()); LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper().in(CustomerAgencyEntity::getId,agencyIds); List customerAgencyEntities = customerAgencyDao.selectList(queryWrapper); for (CustomerAgencyEntity customerAgencyEntity : customerAgencyEntities) { @@ -764,9 +765,10 @@ public class IcNeighborHoodServiceImpl extends BaseServiceImpl agencyIds = new ArrayList<>(Arrays.asList(neighborHood.getAgencyPids().split(":"))); + agencyIds.add(neighborHood.getAgencyId()); LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper().in(CustomerAgencyEntity::getId,agencyIds); List customerAgencyEntities = customerAgencyDao.selectList(queryWrapper); for (CustomerAgencyEntity customerAgencyEntity : customerAgencyEntities) { From e0c293d21511f090986458506b2e57de7336dd12 Mon Sep 17 00:00:00 2001 From: yinzuomei <576302893@qq.com> Date: Thu, 11 May 2023 10:52:32 +0800 Subject: [PATCH 4/6] =?UTF-8?q?=E5=B1=85=E6=B0=91=E4=BF=A1=E6=81=AF?= =?UTF-8?q?=E6=9F=A5=E8=AF=A2=E6=9D=A1=E4=BB=B6=EF=BC=8C=E5=88=97=E8=A1=A8?= =?UTF-8?q?=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/impl/SysDictDataServiceImpl.java | 9 +- .../commons/tools/enums/DictTypeEnum.java | 3 + .../service/impl/IcResiUserServiceImpl.java | 88 +++++++++++++------ 3 files changed, 71 insertions(+), 29 deletions(-) diff --git a/epmet-admin/epmet-admin-server/src/main/java/com/epmet/service/impl/SysDictDataServiceImpl.java b/epmet-admin/epmet-admin-server/src/main/java/com/epmet/service/impl/SysDictDataServiceImpl.java index 52c44b78f6..8df3d7c5cf 100644 --- a/epmet-admin/epmet-admin-server/src/main/java/com/epmet/service/impl/SysDictDataServiceImpl.java +++ b/epmet-admin/epmet-admin-server/src/main/java/com/epmet/service/impl/SysDictDataServiceImpl.java @@ -24,15 +24,13 @@ import com.epmet.dto.SysDictDataDTO; import com.epmet.entity.SysDictDataEntity; import com.epmet.entity.SysDictTypeEntity; import com.epmet.service.SysDictDataService; +import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.stream.Collectors; /** @@ -223,6 +221,9 @@ public class SysDictDataServiceImpl extends BaseServiceImpl dictMap(String dictType) { List resultDTOList = baseDao.selectDictList(dictType); + if(CollectionUtils.isEmpty(resultDTOList)){ + return new HashMap<>(); + } return resultDTOList.stream().collect(Collectors.toMap(DictListResultDTO::getValue, DictListResultDTO::getLabel)); } diff --git a/epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/enums/DictTypeEnum.java b/epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/enums/DictTypeEnum.java index a07838684d..3790d9e9ba 100644 --- a/epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/enums/DictTypeEnum.java +++ b/epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/enums/DictTypeEnum.java @@ -34,6 +34,9 @@ public enum DictTypeEnum { TRAFFIC_TYPE("traffic_type", "交通方式", 36), SOJOURN_HISTORY("sojourn_history", "7天内旅居史情况", 37), TRIP_DATA_TYPE("trip_data_type", "行程记录类型", 39), + YT_KEY_POINT_USER_TYPE("yt_key_point_user_type","重点人群",40), + YT_POPULATION_TYPE("yt_population_type","人口类型",41), + YT_POLITICS_STATUS("yt_politics_status","政治面貌",42) ; private final String code; diff --git a/epmet-user/epmet-user-server/src/main/java/com/epmet/service/impl/IcResiUserServiceImpl.java b/epmet-user/epmet-user-server/src/main/java/com/epmet/service/impl/IcResiUserServiceImpl.java index 98c22b85ff..fa69d45d32 100644 --- a/epmet-user/epmet-user-server/src/main/java/com/epmet/service/impl/IcResiUserServiceImpl.java +++ b/epmet-user/epmet-user-server/src/main/java/com/epmet/service/impl/IcResiUserServiceImpl.java @@ -796,7 +796,6 @@ public class IcResiUserServiceImpl extends BaseServiceImpl> pageResiMap(IcResiUserPageFormDTO formDTO) { - // 查询列表展示项,如果没有,直接返回 - CustomerFormQueryDTO queryDTO1 = ConvertUtils.sourceToTarget(formDTO,CustomerFormQueryDTO.class); - Result> resultColumnRes = operCustomizeOpenFeignClient.queryConditions(queryDTO1); - if (!resultColumnRes.success() || CollectionUtils.isEmpty(resultColumnRes.getData())) { - log.warn("没有配置列表展示列"); - return new PageData(new ArrayList(), NumConstant.ZERO); - } - List resultColumns = resultColumnRes.getData(); + List resultColumns = queryResultColumns(formDTO); // 查询结果列对应的表: Set resultColumnTables = resultColumns.stream().map(IcFormResColumnDTO::getTableName).collect(Collectors.toSet()); @@ -984,7 +976,7 @@ public class IcResiUserServiceImpl extends BaseServiceImpl> subTablesRes = operCustomizeOpenFeignClient.querySubTables(queryDTO1); + Result> subTablesRes = operCustomizeOpenFeignClient.querySubTables(ConvertUtils.sourceToTarget(formDTO,CustomerFormQueryDTO.class)); List subTables = subTablesRes.getData(); // log.info("1、所有的子表subTables:"+JSON.toJSONString(subTables,true)); @@ -1041,7 +1033,7 @@ public class IcResiUserServiceImpl extends BaseServiceImpl> list = pageInfo.getList(); - //查询网格名称 + //查询网格名称、房屋名称用 List gridIds = new ArrayList<>(); Set houseIds = new HashSet<>(); for (Map map : list) { @@ -1052,25 +1044,47 @@ public class IcResiUserServiceImpl extends BaseServiceImpl> gridInfoRes = govOrgOpenFeignClient.getGridListByGridIds(gridIds); - List gridInfoList = gridInfoRes.success() && !CollectionUtils.isEmpty(gridInfoRes.getData()) ? gridInfoRes.getData() : new ArrayList<>(); - Map gridInfoMap = gridInfoList.stream().collect(Collectors.toMap(AllGridsByUserIdResultDTO::getGridId, Function.identity())); - + Map gridInfoMap =getGridInfoMap(gridIds); //查询房子名称 - Result> houseInfoRes = govOrgOpenFeignClient.queryListHouseInfo(houseIds, formDTO.getCustomerId()); - List houseInfoDTOList = houseInfoRes.success() && !CollectionUtils.isEmpty(houseInfoRes.getData()) ? houseInfoRes.getData() : new ArrayList<>(); - Map houseInfoMap = houseInfoDTOList.stream().collect(Collectors.toMap(HouseInfoDTO::getHomeId, Function.identity())); + Map houseInfoMap =getHouseInfoMap(houseIds,formDTO.getCustomerId()); + handleList(list,gridInfoMap,houseInfoMap,formDTO.getCustomerId()); + pageInfo.setList(list); + if (formDTO.getIsPage()) { + return new PageData<>(pageInfo.getList(), pageInfo.getTotal(), formDTO.getPageSize()); + } + return new PageData<>(pageInfo.getList(), pageInfo.getTotal()); + } + private List queryResultColumns(IcResiUserPageFormDTO formDTO) { + // 查询列表展示项,如果没有,直接返回 + CustomerFormQueryDTO queryDTO1 = ConvertUtils.sourceToTarget(formDTO,CustomerFormQueryDTO.class); + Result> resultColumnRes = operCustomizeOpenFeignClient.queryConditions(queryDTO1); + if (!resultColumnRes.success() || CollectionUtils.isEmpty(resultColumnRes.getData())) { + log.error(formDTO.getCustomerId()+"没有配置列表展示列"); + // return new PageData(new ArrayList(), NumConstant.ZERO); + throw new EpmetException(EpmetErrorCode.EPMET_COMMON_OPERATION_FAIL.getCode(),"居民信息表单未配置列表展示项","居民信息表单未配置列表展示项"); + } + List resultColumns = resultColumnRes.getData(); + return resultColumns; + } + + private void handleList(List> list, Map gridInfoMap, Map houseInfoMap,String customerId) { + if(CollectionUtils.isEmpty(list)){ + return; + } //查询需求分类字典 UserDemandNameQueryFormDTO userDemandNameQueryFormDTO = new UserDemandNameQueryFormDTO(); - userDemandNameQueryFormDTO.setCustomerId(formDTO.getCustomerId()); + userDemandNameQueryFormDTO.setCustomerId(customerId); userDemandNameQueryFormDTO.setCodeSet(new HashSet<>()); Result> demandNameRes = heartOpenFeignClient.queryDemandNames(userDemandNameQueryFormDTO); if (!demandNameRes.success() || CollectionUtils.isEmpty(demandNameRes.getData())) { throw new EpmetException(EpmetErrorCode.SERVER_ERROR.getCode(), "获取需求分类字典表数据异常", EpmetErrorCode.SERVER_ERROR.getMsg()); } Map demandDictMap = demandNameRes.getData().stream().collect(Collectors.toMap(IcResiDemandDictDTO::getCategoryCode, Function.identity())); - + // 重点人群+人口类型+政治面貌需要特殊赋值 + Result> keyPointUserTypeMapRes = epmetAdminOpenFeignClient.dictMap(DictTypeEnum.YT_KEY_POINT_USER_TYPE.getCode()); + Result> populationTypeMapRes = epmetAdminOpenFeignClient.dictMap(DictTypeEnum.YT_POPULATION_TYPE.getCode()); + Result> politicsStatusMapRes = epmetAdminOpenFeignClient.dictMap(DictTypeEnum.YT_POLITICS_STATUS.getCode()); for (Map resultMap : list) { String gridIdValue = null != resultMap.get(UserConstant.GRID_ID) ? resultMap.get(UserConstant.GRID_ID).toString() : StrConstant.EPMETY_STR; resultMap.put("GRID_ID_VALUE", gridIdValue); @@ -1120,12 +1134,36 @@ public class IcResiUserServiceImpl extends BaseServiceImpl(pageInfo.getList(), pageInfo.getTotal(), formDTO.getPageSize()); - } - return new PageData<>(pageInfo.getList(), pageInfo.getTotal()); + } + + private Map getHouseInfoMap(Set houseIds,String customerId) { + //查询房子名称 + Result> houseInfoRes = govOrgOpenFeignClient.queryListHouseInfo(houseIds, customerId); + List houseInfoDTOList = houseInfoRes.success() && !CollectionUtils.isEmpty(houseInfoRes.getData()) ? houseInfoRes.getData() : new ArrayList<>(); + Map houseInfoMap = houseInfoDTOList.stream().collect(Collectors.toMap(HouseInfoDTO::getHomeId, Function.identity())); + return houseInfoMap; + } + + private Map getGridInfoMap(List gridIds) { + Result> gridInfoRes = govOrgOpenFeignClient.getGridListByGridIds(gridIds); + List gridInfoList = gridInfoRes.success() && !CollectionUtils.isEmpty(gridInfoRes.getData()) ? gridInfoRes.getData() : new ArrayList<>(); + Map gridInfoMap = gridInfoList.stream().collect(Collectors.toMap(AllGridsByUserIdResultDTO::getGridId, Function.identity())); + return gridInfoMap; } private String queryUserDemandName(String icResiUserId, Map demandDictMap) { From d5f77e748bdce0b2c49ca574c72cc253b7b1f973 Mon Sep 17 00:00:00 2001 From: yinzuomei <576302893@qq.com> Date: Thu, 11 May 2023 14:06:51 +0800 Subject: [PATCH 5/6] =?UTF-8?q?=E5=B1=85=E6=B0=91=E4=BF=A1=E6=81=AF?= =?UTF-8?q?=E5=88=97=E8=A1=A8=EF=BC=8C=E5=B1=95=E7=A4=BA=E8=AF=81=E4=BB=B6?= =?UTF-8?q?=E7=B1=BB=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../commons/tools/enums/DictTypeEnum.java | 3 ++- .../service/impl/IcResiUserServiceImpl.java | 18 +++++++++++------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/enums/DictTypeEnum.java b/epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/enums/DictTypeEnum.java index 3790d9e9ba..fe487d3631 100644 --- a/epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/enums/DictTypeEnum.java +++ b/epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/enums/DictTypeEnum.java @@ -36,7 +36,8 @@ public enum DictTypeEnum { TRIP_DATA_TYPE("trip_data_type", "行程记录类型", 39), YT_KEY_POINT_USER_TYPE("yt_key_point_user_type","重点人群",40), YT_POPULATION_TYPE("yt_population_type","人口类型",41), - YT_POLITICS_STATUS("yt_politics_status","政治面貌",42) + YT_POLITICS_STATUS("yt_politics_status","政治面貌",42), + YT_ID_CARD_TYPE("yt_id_card_type","证件类型",43), ; private final String code; diff --git a/epmet-user/epmet-user-server/src/main/java/com/epmet/service/impl/IcResiUserServiceImpl.java b/epmet-user/epmet-user-server/src/main/java/com/epmet/service/impl/IcResiUserServiceImpl.java index fa69d45d32..e860f4e38e 100644 --- a/epmet-user/epmet-user-server/src/main/java/com/epmet/service/impl/IcResiUserServiceImpl.java +++ b/epmet-user/epmet-user-server/src/main/java/com/epmet/service/impl/IcResiUserServiceImpl.java @@ -1085,6 +1085,7 @@ public class IcResiUserServiceImpl extends BaseServiceImpl> keyPointUserTypeMapRes = epmetAdminOpenFeignClient.dictMap(DictTypeEnum.YT_KEY_POINT_USER_TYPE.getCode()); Result> populationTypeMapRes = epmetAdminOpenFeignClient.dictMap(DictTypeEnum.YT_POPULATION_TYPE.getCode()); Result> politicsStatusMapRes = epmetAdminOpenFeignClient.dictMap(DictTypeEnum.YT_POLITICS_STATUS.getCode()); + Result> idCardTypeMapRes = epmetAdminOpenFeignClient.dictMap(DictTypeEnum.YT_ID_CARD_TYPE.getCode()); for (Map resultMap : list) { String gridIdValue = null != resultMap.get(UserConstant.GRID_ID) ? resultMap.get(UserConstant.GRID_ID).toString() : StrConstant.EPMETY_STR; resultMap.put("GRID_ID_VALUE", gridIdValue); @@ -1136,18 +1137,21 @@ public class IcResiUserServiceImpl extends BaseServiceImpl Date: Thu, 11 May 2023 14:10:34 +0800 Subject: [PATCH 6/6] =?UTF-8?q?=E5=AE=A2=E6=88=B7=E5=AF=BC=E5=85=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../epmet/constants/ImportTaskConstants.java | 5 + .../com/epmet/controller/StaffController.java | 65 +++++- .../excel/CustomerStaffImportExcelData.java | 68 ++++++ .../handler/CustomerStaffImportListener.java | 178 ++++++++++++++++ .../java/com/epmet/service/StaffService.java | 4 + .../epmet/service/impl/StaffServiceImpl.java | 201 +++++++++++++++++- .../excel/customer_staff_import_template.xlsx | Bin 9722 -> 9594 bytes 7 files changed, 518 insertions(+), 3 deletions(-) create mode 100644 epmet-module/gov-org/gov-org-server/src/main/java/com/epmet/excel/CustomerStaffImportExcelData.java create mode 100644 epmet-module/gov-org/gov-org-server/src/main/java/com/epmet/excel/handler/CustomerStaffImportListener.java diff --git a/epmet-module/epmet-common-service/common-service-client/src/main/java/com/epmet/constants/ImportTaskConstants.java b/epmet-module/epmet-common-service/common-service-client/src/main/java/com/epmet/constants/ImportTaskConstants.java index f25fd4269a..f35891c2a5 100644 --- a/epmet-module/epmet-common-service/common-service-client/src/main/java/com/epmet/constants/ImportTaskConstants.java +++ b/epmet-module/epmet-common-service/common-service-client/src/main/java/com/epmet/constants/ImportTaskConstants.java @@ -93,4 +93,9 @@ public interface ImportTaskConstants { * 楼长单元长 */ String COMMUNITY_BUILDING_MANAGER="community_building_manager"; + + /** + * 客户 + */ + String BIZ_TYPE_CUSTOMER_STAFF="customer_staff"; } diff --git a/epmet-module/gov-org/gov-org-server/src/main/java/com/epmet/controller/StaffController.java b/epmet-module/gov-org/gov-org-server/src/main/java/com/epmet/controller/StaffController.java index d424f60202..23807cd908 100644 --- a/epmet-module/gov-org/gov-org-server/src/main/java/com/epmet/controller/StaffController.java +++ b/epmet-module/gov-org/gov-org-server/src/main/java/com/epmet/controller/StaffController.java @@ -5,27 +5,40 @@ package com.epmet.controller; import com.epmet.commons.tools.annotation.LoginUser; import com.epmet.commons.tools.annotation.RequirePermission; import com.epmet.commons.tools.constant.AppClientConstant; +import com.epmet.commons.tools.constant.ServiceConstant; import com.epmet.commons.tools.enums.RequirePermissionEnum; import com.epmet.commons.tools.exception.EpmetErrorCode; import com.epmet.commons.tools.exception.EpmetException; import com.epmet.commons.tools.exception.ExceptionUtils; +import com.epmet.commons.tools.feign.ResultDataResolver; import com.epmet.commons.tools.security.dto.TokenDto; +import com.epmet.commons.tools.utils.EpmetRequestHolder; +import com.epmet.commons.tools.utils.FileUtils; import com.epmet.commons.tools.utils.Result; import com.epmet.commons.tools.validator.ValidatorUtils; +import com.epmet.constants.ImportTaskConstants; import com.epmet.dto.form.*; import com.epmet.dto.result.*; +import com.epmet.feign.EpmetCommonServiceOpenFeignClient; +import com.epmet.remote.EpmetUserRemoteService; import com.epmet.service.StaffService; +import com.epmet.utils.ImportTaskUtils; import lombok.extern.slf4j.Slf4j; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletResponse; +import java.io.FileOutputStream; +import java.io.IOException; import java.io.InputStream; import java.net.URLEncoder; +import java.nio.file.Path; import java.util.List; +import java.util.UUID; /** * 组织结构-工作人员 @@ -35,9 +48,11 @@ import java.util.List; @Slf4j @RestController @RequestMapping("staff") -public class StaffController { +public class StaffController implements ResultDataResolver { @Autowired private StaffService staffService; + @Autowired + private EpmetCommonServiceOpenFeignClient epmetCommonServiceOpenFeignClient; /** * 组织首页-工作人员列表 * @param fromDTO @@ -233,6 +248,54 @@ public class StaffController { return staffService.addStaffV2(fromDTO); } + @PostMapping("staffimport") + public Result buildingImportExcel(@RequestParam("file") MultipartFile file,@RequestParam("orgType") String orgType,@RequestParam("orgId") String orgId){ + + String userId = EpmetRequestHolder.getHeader(AppClientConstant.USER_ID); + + // 1.暂存文件 + String originalFilename = file.getOriginalFilename(); + String extName = originalFilename.substring(originalFilename.lastIndexOf(".")); + + Path fileSavePath; + try { + Path importPath = FileUtils.getAndCreateDirUnderEpmetFilesDir("ic_nat", "import"); + fileSavePath = importPath.resolve(UUID.randomUUID().toString().concat(extName)); + } catch (IOException e) { + String errorMsg = ExceptionUtils.getErrorStackTrace(e); + log.error("【核酸检测导入】创建临时存储文件失败:{}", errorMsg); + throw new EpmetException(EpmetErrorCode.EPMET_COMMON_OPERATION_FAIL.getCode(), "文件上传失败", "文件上传失败"); + } + + InputStream is = null; + FileOutputStream os = null; + + try { + is = file.getInputStream(); + os = new FileOutputStream(fileSavePath.toString()); + IOUtils.copy(is, os); + } catch (Exception e) { + log.error("method exception", e); + } finally { + org.apache.poi.util.IOUtils.closeQuietly(is); + org.apache.poi.util.IOUtils.closeQuietly(os); + } + + // 2.生成导入任务记录 + ImportTaskCommonResultDTO rstData = getResultDataOrThrowsException( + ImportTaskUtils.createImportTask(originalFilename, ImportTaskConstants.BIZ_TYPE_CUSTOMER_STAFF), + ServiceConstant.EPMET_COMMON_SERVICE, + EpmetErrorCode.EPMET_COMMON_OPERATION_FAIL.getCode(), + "excel导入客户信息错误", + "导入客户信息失败"); + + // 3.执行导入 + staffService.execAsyncExcelImport(fileSavePath, rstData.getTaskId(),orgType,orgId); + + return new Result(); + + } + /** * 【通讯录】人员添加-平阴 * @author zhy diff --git a/epmet-module/gov-org/gov-org-server/src/main/java/com/epmet/excel/CustomerStaffImportExcelData.java b/epmet-module/gov-org/gov-org-server/src/main/java/com/epmet/excel/CustomerStaffImportExcelData.java new file mode 100644 index 0000000000..b5a1b08e1d --- /dev/null +++ b/epmet-module/gov-org/gov-org-server/src/main/java/com/epmet/excel/CustomerStaffImportExcelData.java @@ -0,0 +1,68 @@ +package com.epmet.excel; + +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.write.style.ColumnWidth; +import lombok.Data; +import org.hibernate.validator.constraints.Length; + +import javax.validation.constraints.NotBlank; +import java.util.Date; + +/** + * 核酸检测信息导入excel数据 + */ +@Data +public class CustomerStaffImportExcelData { + + @NotBlank(message = "姓名为必填项") + @ExcelProperty("姓名※") + private String name; + + @NotBlank(message = "手机号为必填项") + @ExcelProperty("联系电话※") + @Length(max = 15, message = "手机号长度不正确,应小于15位") + private String mobile; + + @NotBlank(message = "身份证号为必填项") + @ExcelProperty("身份证号※") + @Length(max = 18, message = "证身份证号长度不正确,应小于18位") + private String idCard; + + @ExcelProperty("村居委员职务") + private Date viliagePosition; + + @ExcelProperty("党组织职务") + private Date partyPosition; + + @NotBlank(message = "居住地址为必填项") + @ExcelProperty("居住地址※") + private String address; + + @NotBlank(message = "文化程度为必填项") + @ExcelProperty("文化程度※") + private String cultureName; + + @NotBlank(message = "性别为必填项") + @ExcelProperty("性别※") + private String genderName; + + @NotBlank(message = "专兼职为必填项") + @ExcelProperty("专兼职※") + private String workTypeName; + + @NotBlank(message = "工作职责为必填项") + @ExcelProperty("工作职责※") + private String duty; + + @ExcelProperty("备注") + private String remark; + + @Data + public static class RowRemarkMessage { + + + @ColumnWidth(60) + @ExcelProperty("错误信息") + private String errorInfo; + } +} diff --git a/epmet-module/gov-org/gov-org-server/src/main/java/com/epmet/excel/handler/CustomerStaffImportListener.java b/epmet-module/gov-org/gov-org-server/src/main/java/com/epmet/excel/handler/CustomerStaffImportListener.java new file mode 100644 index 0000000000..28d91229af --- /dev/null +++ b/epmet-module/gov-org/gov-org-server/src/main/java/com/epmet/excel/handler/CustomerStaffImportListener.java @@ -0,0 +1,178 @@ +package com.epmet.excel.handler; + +import com.alibaba.excel.context.AnalysisContext; +import com.alibaba.excel.read.listener.ReadListener; +import com.epmet.commons.tools.exception.EpmetErrorCode; +import com.epmet.commons.tools.exception.EpmetException; +import com.epmet.commons.tools.exception.ExceptionUtils; +import com.epmet.commons.tools.exception.ValidateException; +import com.epmet.commons.tools.utils.ConvertUtils; +import com.epmet.commons.tools.validator.ValidatorUtils; +import com.epmet.dto.form.AddStaffV2FromDTO; +import com.epmet.excel.CustomerStaffImportExcelData; +import com.epmet.service.impl.StaffServiceImpl; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; + +import java.util.ArrayList; +import java.util.List; + +/** + * 核酸检测excel导入监听器 + */ +@Data +@Slf4j +public class CustomerStaffImportListener implements ReadListener { + + /** + * 最大条数阈值 + */ + public static final int MAX_THRESHOLD = 200; + + private String currentUserId; + + private String currentCustomerId; + + private String currentOrgType; + + private String currentOrgId; + + + /** + * 数据 + */ + private List datas = new ArrayList<>(); + + /** + * 错误项列表 + */ + private List errorRows = new ArrayList<>(); + /** + * 其他被标记出来的列表列表 + */ + private List otherRows = new ArrayList<>(); + + private StaffServiceImpl staffService; + + public CustomerStaffImportListener(String currentUserId, String currentCustomerId, String currentOrgType,String currentOrgId,StaffServiceImpl staffService) { + this.currentUserId = currentUserId; + this.currentCustomerId = currentCustomerId; + this.staffService = staffService; + this.currentOrgType = currentOrgType; + this.currentOrgId = currentOrgId; + } + + @Override + public void invoke(CustomerStaffImportExcelData data, AnalysisContext context) { + + try { + // 先校验数据 + ValidatorUtils.validateEntity(data); + + AddStaffV2FromDTO fromDTO = ConvertUtils.sourceToTarget(data, AddStaffV2FromDTO.class); + + fromDTO.setCustomerId(currentCustomerId); + //因为添加的是工作人员,这里写死吧! + fromDTO.setApp("gov"); + fromDTO.setClient("wxmp"); + //当前登录用户 + fromDTO.setCurrentUserId(currentUserId); + fromDTO.setOrgId(currentOrgId); + fromDTO.setOrgType(currentOrgType); + + if (StringUtils.isNotBlank(data.getWorkTypeName())){ + if (data.getWorkTypeName().equals("专职")){ + fromDTO.setWorkType("fulltime"); + } + if (data.getWorkTypeName().equals("兼职")){ + fromDTO.setWorkType("parttime"); + } + } + + if (StringUtils.isNotBlank(data.getGenderName())){ + if (data.getGenderName().equals("男")){ + fromDTO.setGender(1); + } + if (data.getGenderName().equals("女")){ + fromDTO.setGender(2); + } + if (data.getGenderName().equals("未知")){ + fromDTO.setGender(0); + } + } + //0小学及文盲,1初中,2高中,3大专,4本科,5硕士,6博士,7中专 + if (StringUtils.isNotBlank(data.getCultureName())){ + if (data.getCultureName().equals("小学及文盲")){ + fromDTO.setCulture("0"); + } + if (data.getCultureName().equals("初中")){ + fromDTO.setCulture("1"); + } + if (data.getCultureName().equals("高中")){ + fromDTO.setCulture("2"); + } + if (data.getCultureName().equals("大专")){ + fromDTO.setCulture("3"); + } + if (data.getCultureName().equals("本科")){ + fromDTO.setCulture("4"); + } + if (data.getCultureName().equals("硕士")){ + fromDTO.setCulture("5"); + } + if (data.getCultureName().equals("博士")){ + fromDTO.setCulture("6"); + } + } + + + datas.add(fromDTO); + + if (datas.size() == MAX_THRESHOLD) { + execPersist(); + } + } catch (Exception e) { + String errorMsg = null; + if (e instanceof ValidateException) { + errorMsg = ((ValidateException) e).getMsg(); + } else { + log.error("【客户信息导入】出错:{}", e.getStackTrace()); + errorMsg = ((EpmetException)e).getInternalMsg(); + log.error("【客户信息导入】出错:{}", ExceptionUtils.getErrorStackTrace(e)); + } + + CustomerStaffImportExcelData.RowRemarkMessage errorRow = new CustomerStaffImportExcelData.RowRemarkMessage(); + errorRow.setErrorInfo(errorMsg); + errorRows.add(errorRow); + } + } + + @Override + public void doAfterAllAnalysed(AnalysisContext context) { + // 最后几条达不到阈值,这里必须再调用一次 + execPersist(); + } + + /** + * 执行持久化 + */ + private void execPersist() { + try { + if (datas != null && datas.size() > 0) { +// icNatService.batchPersist(datas, this); + staffService.exportAdd(datas,this); + } + } finally { + datas.clear(); + } + } + + /** + * 获取错误行 + * @return + */ + public List getErrorRows() { + return errorRows; + } +} diff --git a/epmet-module/gov-org/gov-org-server/src/main/java/com/epmet/service/StaffService.java b/epmet-module/gov-org/gov-org-server/src/main/java/com/epmet/service/StaffService.java index 5a4a989166..6bbb42094e 100644 --- a/epmet-module/gov-org/gov-org-server/src/main/java/com/epmet/service/StaffService.java +++ b/epmet-module/gov-org/gov-org-server/src/main/java/com/epmet/service/StaffService.java @@ -4,7 +4,9 @@ import com.epmet.commons.tools.security.dto.TokenDto; import com.epmet.commons.tools.utils.Result; import com.epmet.dto.form.*; import com.epmet.dto.result.*; +import org.springframework.web.bind.annotation.RequestParam; +import java.nio.file.Path; import java.util.List; /** @@ -154,4 +156,6 @@ public interface StaffService { * @Date 2021/9/8 16:57 */ List staffOrgList(TokenDto tokenDto); + + void execAsyncExcelImport(Path fileSavePath, String taskId,String orgType, String orgId); } diff --git a/epmet-module/gov-org/gov-org-server/src/main/java/com/epmet/service/impl/StaffServiceImpl.java b/epmet-module/gov-org/gov-org-server/src/main/java/com/epmet/service/impl/StaffServiceImpl.java index a81f868ac5..7a3e7db3fc 100644 --- a/epmet-module/gov-org/gov-org-server/src/main/java/com/epmet/service/impl/StaffServiceImpl.java +++ b/epmet-module/gov-org/gov-org-server/src/main/java/com/epmet/service/impl/StaffServiceImpl.java @@ -1,18 +1,21 @@ package com.epmet.service.impl; +import com.alibaba.excel.EasyExcel; +import com.epmet.commons.tools.constant.AppClientConstant; import com.epmet.commons.tools.constant.NumConstant; import com.epmet.commons.tools.constant.StrConstant; import com.epmet.commons.tools.dto.result.CustomerStaffInfoCacheResult; import com.epmet.commons.tools.exception.EpmetErrorCode; import com.epmet.commons.tools.exception.EpmetException; +import com.epmet.commons.tools.exception.ExceptionUtils; import com.epmet.commons.tools.exception.RenException; import com.epmet.commons.tools.redis.RedisKeys; import com.epmet.commons.tools.redis.RedisUtils; import com.epmet.commons.tools.redis.common.CustomerStaffRedis; import com.epmet.commons.tools.security.dto.TokenDto; -import com.epmet.commons.tools.utils.ConvertUtils; -import com.epmet.commons.tools.utils.Result; +import com.epmet.commons.tools.utils.*; import com.epmet.constant.OrgInfoConstant; +import com.epmet.constants.ImportTaskConstants; import com.epmet.dao.CustomerStaffAgencyDao; import com.epmet.dao.StaffOrgRelationDao; import com.epmet.dto.*; @@ -20,17 +23,31 @@ import com.epmet.dto.form.*; import com.epmet.dto.form.yantai.YtSyncStaffIdFormDTO; import com.epmet.dto.result.*; import com.epmet.entity.*; +import com.epmet.excel.CustomerStaffImportExcelData; +import com.epmet.excel.handler.CustomerStaffImportListener; import com.epmet.feign.*; +import com.epmet.remote.EpmetUserRemoteService; import com.epmet.service.*; +import com.epmet.utils.ImportTaskUtils; +import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.fileupload.FileItem; +import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.lang3.StringUtils; +import org.apache.http.entity.ContentType; +import org.apache.poi.util.IOUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.commons.CommonsMultipartFile; import javax.annotation.Resource; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -41,6 +58,7 @@ import java.util.stream.Collectors; * @dscription * @date 2020/4/23 18:05 */ +@Slf4j @Service public class StaffServiceImpl implements StaffService { private static final Logger logger = LoggerFactory.getLogger(StaffServiceImpl.class); @@ -80,6 +98,10 @@ public class StaffServiceImpl implements StaffService { private GovAccessFeignClient govAccessFeignClient; @Autowired private EpmetThirdOpenFeignClient epmetThirdOpenFeignClient; + @Autowired + private EpmetUserRemoteService userRemoteService; + @Autowired + private OssFeignClient ossFeignClient; @Override public Result getStaffInfoForHome(StaffsInAgencyFromDTO fromDTO) { @@ -745,5 +767,180 @@ public class StaffServiceImpl implements StaffService { return list; } + @Override + public void execAsyncExcelImport(Path filePath, String importTaskId,String orgType, String orgId) { + + try { + + CustomerStaffImportListener listener = new CustomerStaffImportListener(userRemoteService.getLoginUserDetails().getUserId(), userRemoteService.getLoginUserDetails().getCustomerId(), orgType,orgId,this); + + EasyExcel.read(filePath.toFile(), CustomerStaffImportExcelData.class, listener).headRowNumber(2).sheet(0).doRead(); + + String errorDesFileUrl = null; + + List errorRows = listener.getErrorRows(); + List otherRows = listener.getOtherRows(); + + boolean failed = errorRows.size() > 0; + + // 合并到一起写入 + errorRows.addAll(otherRows); + + // 生成并上传描述文件 + OutputStream os = null; + FileItem fileItem = null; + if (errorRows.size() > 0) { + try { + // 文件生成 + Path errorDescDir = FileUtils.getAndCreateDirUnderEpmetFilesDir("ic_nat", "import", "error_des"); + String timeMillis = String.valueOf(System.currentTimeMillis()); + String fileName = "icnat_import_error_".concat(timeMillis).concat(".xlsx"); + + fileItem = new DiskFileItemFactory(DiskFileItemFactory.DEFAULT_SIZE_THRESHOLD, errorDescDir.toFile()) + .createItem("file", ContentType.APPLICATION_OCTET_STREAM.toString(), false, fileName); + + os = fileItem.getOutputStream(); + + EasyExcel.write(os, CustomerStaffImportExcelData.RowRemarkMessage.class).sheet("信息列表").doWrite(errorRows); + // 文件上传oss + Result errorDesFileUploadResult = ossFeignClient.uploadImportTaskDescFile(new CommonsMultipartFile(fileItem)); + if (errorDesFileUploadResult.success()) { + errorDesFileUrl = errorDesFileUploadResult.getData().getUrl(); + } + } finally { + IOUtils.closeQuietly(os); + try { + fileItem.delete(); + } catch (Exception e){ + log.error("【客户信息导入】删除临时描述文件失败:{}", ExceptionUtils.getErrorStackTrace(e)); + } + } + } + + // 完成导入 + Result result = ImportTaskUtils.finishImportTask(importTaskId, + failed ? ImportTaskConstants.PROCESS_STATUS_FINISHED_FAIL : ImportTaskConstants.PROCESS_STATUS_FINISHED_SUCCESS, + errorDesFileUrl, + ""); + + if (!result.success()) { + log.error("【客户信息导入】导入记录状态修改为'finished_success'失败"); + } + } catch (Exception e) { + String errorMsg = ExceptionUtils.getErrorStackTrace(e); + log.error("【客户信息导入】出错:{}", errorMsg); + + Result result = ImportTaskUtils.finishImportTask(importTaskId, ImportTaskConstants.PROCESS_STATUS_FINISHED_FAIL, null, "导入失败"); + + if (!result.success()) { + log.error("【客户信息导入】导入记录状态修改为'finished_fail'失败"); + } + } finally { + // 删除临时文件 + if (Files.exists(filePath)) { + try { + Files.delete(filePath); + } catch (IOException e) { + log.error("method exception", e); + } + } + } + } + + /** + * 批量持久化 + * @param addStaffV2FromDTOList + */ + public void exportAdd(List addStaffV2FromDTOList, CustomerStaffImportListener listener) { + + addStaffV2FromDTOList.forEach(fromDTO -> { + + //1.根据新增人员类型判断查询机关信息 + OrgResultDTO orgDTO = customerAgencyDao.selectAgencyDetail(fromDTO.getOrgId(), fromDTO.getOrgType()); + if (null == orgDTO) { + logger.warn(String.format("工作人员新增,根据新增人员组织类型未查询到相关组织信息,orgId->%s,orgType->%s", fromDTO.getOrgId(), fromDTO.getOrgType())); + throw new EpmetException(EpmetErrorCode.EPMET_COMMON_OPERATION_FAIL.getCode(),"根据新增人员组织类型未查询到相关组织信息","组织不存在"); + } + + //2.调用user服务,新增用户信息 + StaffSubmitFromDTO submitDTO = ConvertUtils.sourceToTarget(fromDTO, StaffSubmitFromDTO.class); + submitDTO.setAgencyId(orgDTO.getAgencyId()); + Result result = epmetUserFeignClient.addStaff(submitDTO); + if (!result.success()) { + throw new EpmetException(EpmetErrorCode.EPMET_COMMON_OPERATION_FAIL.getCode(),result.getInternalMsg(),result.getMsg()); + } + + //3.人员机关表总人数加一、关系表新增关系数据 + //人员机关关系表 + CustomerStaffAgencyEntity customerStaffAgencyEntity = new CustomerStaffAgencyEntity(); + customerStaffAgencyEntity.setCustomerId(fromDTO.getCustomerId()); + customerStaffAgencyEntity.setUserId(result.getData().getUserId()); + customerStaffAgencyEntity.setAgencyId(orgDTO.getAgencyId()); + customerStaffAgencyService.insert(customerStaffAgencyEntity); + //机关总人数加一 + CustomerAgencyEntity agencyEntity = new CustomerAgencyEntity(); + agencyEntity.setId(orgDTO.getAgencyId()); + agencyEntity.setTotalUser(orgDTO.getTotalUser() + 1); + customerAgencyService.updateById(agencyEntity); + + //4.部门、网格主表、关系表修改、新增数据 + if ("dept".equals(fromDTO.getOrgType())) { + CustomerStaffDepartmentEntity dept = new CustomerStaffDepartmentEntity(); + dept.setCustomerId(fromDTO.getCustomerId()); + dept.setUserId(result.getData().getUserId()); + dept.setDepartmentId(fromDTO.getOrgId()); + customerStaffDepartmentService.insert(dept); + CustomerDepartmentEntity departmentEntity = new CustomerDepartmentEntity(); + departmentEntity.setId(fromDTO.getOrgId()); + departmentEntity.setTotalUser(orgDTO.getDeptTotalUser() + 1); + customerDepartmentService.updateById(departmentEntity); + } + if ("grid".equals(fromDTO.getOrgType())) { + CustomerStaffGridEntity grid = new CustomerStaffGridEntity(); + grid.setCustomerId(fromDTO.getCustomerId()); + grid.setUserId(result.getData().getUserId()); + grid.setGridId(fromDTO.getOrgId()); + customerStaffGridService.insert(grid); + CustomerGridEntity gridEntity = new CustomerGridEntity(); + gridEntity.setId(fromDTO.getOrgId()); + gridEntity.setTotalUser(orgDTO.getGridTotalUser() + 1); + customerGridService.updateById(gridEntity); + } + + //5.工作人员注册组织关系表新增数据 + StaffOrgRelationEntity staffOrgRelationEntity = new StaffOrgRelationEntity(); + staffOrgRelationEntity.setCustomerId(fromDTO.getCustomerId()); + if("agency".equals(fromDTO.getOrgType())){ + staffOrgRelationEntity.setPids(("".equals(orgDTO.getPids()) ? "" : orgDTO.getPids())); + }else { + staffOrgRelationEntity.setPids(("".equals(orgDTO.getPids()) ? "" : orgDTO.getPids() + ":") + orgDTO.getAgencyId()); + } + staffOrgRelationEntity.setStaffId(result.getData().getUserId()); + staffOrgRelationEntity.setOrgId(fromDTO.getOrgId()); + staffOrgRelationEntity.setOrgType(fromDTO.getOrgType()); + staffOrgRelationService.insert(staffOrgRelationEntity); + + if (CollectionUtils.isNotEmpty(fromDTO.getNewRoles())){ + Result roleUserAccess = govAccessFeignClient.roleUser(new RoleUserFormDTO(fromDTO.getNewRoles(), customerStaffAgencyEntity.getUserId(),fromDTO.getCustomerId())); + if (!roleUserAccess.success()){ + throw new EpmetException("save data to gov-role-user failure"); + } + } + //如果是烟台的需要更新 根据手机号+姓名 更新data_sync_user_data置为已创建、记录staffId + // 开发环境默认:45687aa479955f9d06204d415238f7cc + // 测试环境:0c41b272ee9ee95ac6f184ad548a30eb + // 烟台: 1535072605621841922 + if ("1535072605621841922".equals(fromDTO.getCustomerId()) + || "45687aa479955f9d06204d415238f7cc".equals(fromDTO.getCustomerId()) + || "0c41b272ee9ee95ac6f184ad548a30eb".equals(fromDTO.getCustomerId())) { + YtSyncStaffIdFormDTO ytSyncStaffIdFormDTO = ConvertUtils.sourceToTarget(fromDTO,YtSyncStaffIdFormDTO.class); + ytSyncStaffIdFormDTO.setStaffId(result.getData().getUserId()); + ytSyncStaffIdFormDTO.setOperUserId(fromDTO.getCurrentUserId()); + epmetThirdOpenFeignClient.dataSyncUpdateStaff(ytSyncStaffIdFormDTO); + } + + }); + } + } diff --git a/epmet-module/gov-org/gov-org-server/src/main/resources/excel/customer_staff_import_template.xlsx b/epmet-module/gov-org/gov-org-server/src/main/resources/excel/customer_staff_import_template.xlsx index df7f4126472dc1f67d5a60445662f9fa0475343e..75678505187e1fc06269d98c4168f447e4c92451 100644 GIT binary patch delta 5216 zcmZ8lWmFXG)@2BhknTZphGyuYQ)&na>23xPP)P+GLAqfGk?!so5b1Jg7^DS6DM1v0 zq2c=8d)NBb{mxqF{McvzI?s95+WTB;Uurd^0SE%Aj}o3DvjBVuB>F^y2*X?9>#W>R z)J}r-l$Am3(rw0#Sf5S;H+>urnl-p;Xa(-rMI%e@Y1&mbV!#QL6y8ymTW;Z0jn6DHpaqlEioyN(7W)8d-0C7T#6~+x82Pcgbxq;7yuuNJ} zWeCyOR5W|N!P_c7=_v`ST>f%cT533?awWH~lRA?qe;C-bwv|9QM;yvGs1_YZ5oQ=; zNYsZHvaus>eNLZq1diGAOoyl#RgL6HORrx*jwhbp{ekh+IF?aCibHjor`pVDK2aud z;az~|Ai%Q2_lUid~ zpnue?D%m}_Dkgg{cE$i(tl!?f z!4186p)8B0n!nUXhJz#9C(Pg1e6)Pe!Xn&e+_ zY#Rz^SX@AJjqZB641OF4M|3tcUfL|Lphveen$(}_xT<)=o<}8}_}X3NVcaf&KOyLR zf1;O`WkK*D_G>B9Nq}}gUA7Ek4Y94My0r$HdtdJ$P{;PyP}=m^E|~P!6Y7_!ZU^b~?ujLt@^qX|*r- zK7gU4g)>w=2?3V;5PWOND~Ubv&M}?^?GSlra$3s0ufw8uLhRzQqU%gc-Qu|pi>9Kj z(`tmE%)_!GRAvkhfcGfiV~7x!4* z88z$Im)q~%7}d7FSVAtG-%o#?O`JGm#a^Q{$w31rAv4Vs2x0n0Lm@ZQrWTRBXRKUY z92}(M{DE~yECdNA%EfV^dW-hZf*EIxllO)6p!7b{k!6vQW@*pr=!*t_JJk6hnJ<5H zQh%oCKCXC*4{2!~QwO?Gk&ms(WdKBI%Ubx+E4D8sh%3fWfhOci? zQ+Wz*8;Uvb>zi}!V~M+?l#5rl6GE;@3T`-_En;^xY6q~v|>wqGm~5z z(^>a{Uu>u3BUWq^z9ao7uSO=1n5bdjx|$0K+OIF$FVXWuEp{!R{_pzaiwli*`u`YVHNy7@d9rkQjt_@985p z?KIst9P+8e2V?|IrCBI4M&T06wxZq-bT(M~qc$(Iw{@^Posz};OM3r95}~Pd2v~*^ zEQ9M1JNptb*|F2D4_qK8O!Oc5gSX<7O%T#$G%bMIKYbcdZ+_lai?u*>6%g2u{Pbg< zYJDHU$+l^xrNZaz^|(i2qh_NFKyIYJLuCbE)ek&tS78m zo$tQE6w-GeotknVY*r!sw`5K0(!4ypc@!>>mgC78ZY$RA>7OuE&zx7h*qPoScVG@*ivFUtX(>?jlF+=t;CIl}%rY(>xaVv+Lz` zA}>kSWDv=Nl+6bA$u8$6;+>0CU}W*)x>$2>w}+aezS{)!d?Q4>k-)Y#!47E|kMQGW z!_0i;M~)>B-Y9eUKo8Y*P{^cAtJ-F8aa(SxSh^l2uG7`7GcW&u2qX}m6P{KWu=?^a zBt&{oF5NKkK_MNEGW2MAZuxsUpExhUA=mxyj|Iw8OU2@C*sN%-Nd4%E7ly#PvPZb* zuW7mGW5z(3rWc6K7PkaCCoc)(ahstQt@*N_4&sI==RHl>a*G%Y{8UJ6se;(tM8HOk zsn#8QB|07fU^yKk20A3`L?w{gj1gIi+dzVivK{Ro3e;e(t!d1*om4t>Z9o_F;Ag`O z8mgb^j0WHfG)g z+p$)`l<>i(XxK@phsx6G-chSosm%;9vQjeotU0p>B=VUy8;0Qx^6tNu?*COaV}vLE z`P9A32I2kAIRv((YT0w}B|g;!?4=I3sk?^vdZOHGbK^Hx5|N8qp`M)@Ib!w-7*Gs(uw){yi!cjM2A7wLi1-)F@ElR zzv`=nglpOJ+sKNS{UJ zzh;N5HNSth$Hi!Qwom#fss1}XQP5<_VL&CBQACF=frL zDDA4pPjoti$U^&jrD@_CC;?737u!${M655ABPea z;EhFal4h_jTfbN>B=Hu^|FGAPKTbE_#?j_1l@fa4p8FPWXZLELuWk#q2Lo0i2)a7e zu2Ro$5;WhQ&#!dTTYO2*yWtJBuP+2iqxwB1?P8Plz>VBr+4L0B#Xm`NAC8Jzjac;0 zIjVomq_f?9mSTu=$*5IJ8s1=;$_>_iRTq~|^sZ0ih+t>vYl7TTKTAT84wT-SMO@jcF%(u-)sG7zr zGglBCrXR(eXr)niTnRpW=(A$ED~wBQy6qtzo)fM9=wNi!zg=eZA#Xl=lFLcz3+^<} z&T3@wua86v$NQQzUQ*Mcvp^h~0p!xzm=u6{f7y+W$ULFFmYu#LZ%{4EVxx? zuFzf3O=`unDblj~J$A>Vp8yi)&cV0(63Z9Vz1O5m`J7e%!mwSQe9bY>Tijq=N1SZZaKR>#ItWp(pLm0zFS@T~ig%$7iyMtf_j zcz@bBSxOivhmEZ+6tC9tfwo8re9C&6CkSWx9C{=7Ck=6BvQfg`gMJg*8R=SNK@l53gL^P!~{<7IG zP)YsBTP~oq=0X11FhYt&{-y6NTEn&HR_ASFrW(C~st(`D z^fZW`Gls+nG#r5lgqjeT7}9*;X`whNq2qjo#rN~QjshaE*I##UVIWFPN`moaTB-?9 z7eO0Zigrv8Q#@H&OKp?^bR$@4$AD=ER^E)<_&c6j}m{L64p6 zo`7z~6y;fOeq??_1XG|v)LHMM6$C|K$oupuIlg6-J_ue+xzv+pK!DF2x){XE$_!RX7V9$!2G4R={2B26Kirek`QxQwd3^izwmc1Dp!)T~9k;+T?marKF zvYA+`KOBETOFH@Mc5?{Btx`rR`)KcU&?)IH_rR2qgPrdmo#^xw!W|}>_gt~G_b|2b zi|B^H0)(B|?ZVOd;T;Fsi5uTOPo7LMW`1U;eDg}QYJ)9TYp^_E1fjqve}1!j+jTTz zOKicY^?P57*uroiv4;Xgt)^p+9cE?CNBq$c^nXjryl8BKetErjadh>qGpTSlN%69i zg2%C}Xih|gisNDz@Q8*8yxOtGp@HKmMR(wKi9nm>%`F0OE6>4@vWRGvs421a2Z z;z@4p-7T=!$PALn&EQUxN|rPI^WwhTRG+o4skL%7KspBDP`wcHboIBH?ExN5-D!<}(FC_)k1 zoz%Q`-3><#Mop*$-^gDYkq<^A_C2o>=?&@rLFisqB%~wug@gIuaL;ViLr;FXe07zz zY#qivUNNiAZ2RHivQ$+g!DqSRLEGHg+V#aNE#7e7`V+$+Ov(b8pU;mSPC|dg!WnKo zYhA!sbLskZROkE&xh6C=VV4^eif-)<^}bj&tGk{!w`qQ}CVU!G9ajLo%4ael9n`b* zx@G-G-O~Kkw)g+7ZY7ewsR;sba5n$uKWN}nAs@K?3umV%zAxOoTzw#co=^Q|CbR~W zC{K!I)h3R&{0GX9-h-zhIN8#7{ZAqF0F9q%6Lk|(gPk|zn zv(6%JN*<7}p9>yf7$U9V>of^mR;xD?QRh&-sXyWuQRUCuo+{rl-b)ea$y932OoG@S zfxf}-?>G`U33)$^ULVqm>AM!O#758xor%8IG-;ms#b|c@=^X!mCwyg0eT}qbW=5o- z9}fsqME=tJ_;yRy?>!`~3I>MGkW?A*xH{@FRj)b8mVA^)s+KZKPq-j%ch1~HMBfK1 zM~^OrC2BB&?IMt)EX0?$*x=>@5SJHtVNyl8hke%XWk{>LwbW~w0MPx0#sWXB*Jv{u z2?iF8$+ttWt+1~|W6$hn2scFMaS&*DhU-!eW1Yam`(wXZBdhtq8#6J(Z*=iMZ?=iH zMl3Eg$BawG526z8pWUVd=R#)F;4B!V5s}kh|L}nhlE4TqJUUC5mFmiNl6KzumAdjq z4fWGT87Op92dZtFZDrLeW9l$h&>)XmBdK_lJ3YTL#IYZEKwd0~YaRk>6F2SHA7?E7 zX1!WKF+N~uPX&FkN20n85kzY7))4#WS@Mv!PQ|2=E=f53kM D5dOjA delta 5328 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 U@RZ2+aqD@44=`5*BA0g^5J^Z)<=