Browse Source

Merge branch 'master' of http://121.42.41.42:7070/r/epmet-cloud into yantai_zhengwu_master

dev
yinzuomei 3 years ago
parent
commit
39bc8f6af7
  1. 10
      epmet-module/epmet-heart/epmet-heart-server/src/main/java/com/epmet/service/impl/ActInfoServiceImpl.java
  2. 19
      epmet-module/epmet-heart/epmet-heart-server/src/main/java/com/epmet/service/impl/IcPartyUnitServiceImpl.java
  3. 6
      epmet-module/epmet-oss/epmet-oss-client/src/main/java/com/epmet/enums/OssTypeEnum.java
  4. 6
      epmet-module/epmet-oss/epmet-oss-server/pom.xml
  5. 39
      epmet-module/epmet-oss/epmet-oss-server/src/main/java/com/epmet/cloud/CloudStorageConfig.java
  6. 106
      epmet-module/epmet-oss/epmet-oss-server/src/main/java/com/epmet/cloud/MinioStorageService.java
  7. 2
      epmet-module/epmet-oss/epmet-oss-server/src/main/java/com/epmet/cloud/OssFactory.java
  8. 51
      epmet-module/oper-crm/oper-crm-client/src/main/java/com/epmet/dto/form/CustomerInitFormDTO.java
  9. 36
      epmet-module/oper-crm/oper-crm-server/src/main/java/com/epmet/controller/CustomerController.java
  10. 5
      epmet-module/oper-crm/oper-crm-server/src/main/java/com/epmet/service/CustomerService.java
  11. 69
      epmet-module/oper-crm/oper-crm-server/src/main/java/com/epmet/service/impl/CustomerServiceImpl.java

10
epmet-module/epmet-heart/epmet-heart-server/src/main/java/com/epmet/service/impl/ActInfoServiceImpl.java

@ -30,6 +30,7 @@ import com.epmet.commons.tools.redis.common.bean.GridInfoCache;
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.SpringContextUtils;
import com.epmet.constant.ActConstant;
import com.epmet.dao.ActInfoDao;
import com.epmet.dao.ActUserRelationDao;
@ -66,16 +67,13 @@ public class ActInfoServiceImpl extends BaseServiceImpl<ActInfoDao, ActInfoEntit
private Logger logger = LogManager.getLogger(ActInfoServiceImpl.class);
@Autowired
private ActUserRelationService relationService;
@Autowired
private ActUserRelationDao actUserRelationDao;
@Autowired
private HeartUserInfoDao heartUserInfoDao;
@Resource
private IcPartyUnitService icPartyUnitService;
// @Resource
// private IcPartyUnitService icPartyUnitService;
@Resource
private IcServiceItemDictService icServiceItemDictService;
@Resource
@ -276,7 +274,7 @@ public class ActInfoServiceImpl extends BaseServiceImpl<ActInfoDao, ActInfoEntit
//获取联建单位
IcPartyUnitDTO unitDTO = new IcPartyUnitDTO();
unitDTO.setAgencyId(dto.getAgencyId());
Map<String, String> option = icPartyUnitService.option(unitDTO).stream().collect(Collectors.toMap(OptionDTO::getValue, OptionDTO::getLabel));
Map<String, String> option = SpringContextUtils.getBean(IcPartyUnitService.class).option(unitDTO).stream().collect(Collectors.toMap(OptionDTO::getValue, OptionDTO::getLabel));
List<String> unitIds = icActivityUnitRelationService.getUnitList(dto.getId());
List<String> unitNames = unitIds.stream().map(option::get).collect(Collectors.toList());
detailResultDTO.setUnitIdList(unitIds);

19
epmet-module/epmet-heart/epmet-heart-server/src/main/java/com/epmet/service/impl/IcPartyUnitServiceImpl.java

@ -44,6 +44,7 @@ import com.epmet.commons.tools.security.user.LoginUserUtil;
import com.epmet.commons.tools.utils.ConvertUtils;
import com.epmet.commons.tools.utils.FileUtils;
import com.epmet.commons.tools.utils.Result;
import com.epmet.commons.tools.utils.SpringContextUtils;
import com.epmet.constant.UserDemandConstant;
import com.epmet.constants.ImportTaskConstants;
import com.epmet.dao.IcPartyUnitDao;
@ -99,16 +100,16 @@ public class IcPartyUnitServiceImpl extends BaseServiceImpl<IcPartyUnitDao, IcPa
@Resource
private EpmetAdminOpenFeignClient epmetAdminOpenFeignClient;
@Resource
private IcUserDemandRecService icUserDemandRecService;
// @Resource
// private IcUserDemandRecService icUserDemandRecService;
@Resource
private IcServiceItemDictService icServiceItemDictService;
@Resource
private OssFeignClient ossFeignClient;
@Resource
private EpmetCommonServiceOpenFeignClient commonServiceOpenFeignClient;
@Resource
private EpmetHeartOpenFeignClient heartOpenFeignClient;
// @Resource
// private EpmetHeartOpenFeignClient heartOpenFeignClient;
@Resource
private IcCommunitySelfOrganizationService icCommunitySelfOrganizationService;
@Resource
@ -140,7 +141,7 @@ public class IcPartyUnitServiceImpl extends BaseServiceImpl<IcPartyUnitDao, IcPa
List<OptionDTO> serviceItemList = icServiceItemDictService.queryDictList(formDTO.getCustomerId());
Map<String, String> categoryMap = serviceItemList.stream().collect(Collectors.toMap(OptionDTO::getValue, OptionDTO::getLabel));
//获取单位积分
Map<String, Integer> pointMap = icUserDemandRecService.getServicePoint(formDTO.getCustomerId(), UserDemandConstant.PARTY_UNIT);
Map<String, Integer> pointMap = SpringContextUtils.getBean(IcUserDemandRecService.class).getServicePoint(formDTO.getCustomerId(), UserDemandConstant.PARTY_UNIT);
dtoList.forEach(item -> {
item.setTypeName(unitTypeMap.getData().get(item.getType()));
//这是错误的,应该是赋值type,遗留bug, 先不改了....
@ -180,7 +181,7 @@ public class IcPartyUnitServiceImpl extends BaseServiceImpl<IcPartyUnitDao, IcPa
List<OptionDTO> serviceItemList = icServiceItemDictService.queryDictList(formDTO.getCustomerId());
Map<String, String> categoryMap = serviceItemList.stream().collect(Collectors.toMap(OptionDTO::getValue, OptionDTO::getLabel));
//获取单位积分
Map<String, Integer> pointMap = icUserDemandRecService.getServicePoint(formDTO.getCustomerId(), UserDemandConstant.PARTY_UNIT);
Map<String, Integer> pointMap = SpringContextUtils.getBean(IcUserDemandRecService.class).getServicePoint(formDTO.getCustomerId(), UserDemandConstant.PARTY_UNIT);
dtoList.forEach(item -> {
item.setTypeName(unitTypeMap.getData().get(item.getType()));
//这是错误的,应该是赋值type,遗留bug, 先不改了....
@ -211,7 +212,7 @@ public class IcPartyUnitServiceImpl extends BaseServiceImpl<IcPartyUnitDao, IcPa
IcPartyUnitDTO dto = ConvertUtils.sourceToTarget(entity, IcPartyUnitDTO.class);
if (StringUtils.isNotBlank(dto.getServiceMatter())) {
//获取单位积分
Map<String, Integer> pointMap = icUserDemandRecService.getServicePoint(entity.getCustomerId(), UserDemandConstant.PARTY_UNIT);
Map<String, Integer> pointMap = SpringContextUtils.getBean(IcUserDemandRecService.class).getServicePoint(entity.getCustomerId(), UserDemandConstant.PARTY_UNIT);
dto.setServiceMatterList(Arrays.asList(dto.getServiceMatter().split(StrConstant.COMMA)));
dto.setScore(null == pointMap.get(id) ? NumConstant.ZERO : pointMap.get(id));
// 分类名称
@ -271,7 +272,7 @@ public class IcPartyUnitServiceImpl extends BaseServiceImpl<IcPartyUnitDao, IcPa
@Transactional(rollbackFor = Exception.class)
public void delete(String id) {
//存在未完成的需求,不能删除
if (icUserDemandRecService.selectCountByServerId(id) > NumConstant.ZERO) {
if (SpringContextUtils.getBean(IcUserDemandRecService.class).selectCountByServerId(id) > NumConstant.ZERO) {
throw new EpmetException(EpmetErrorCode.EPMET_COMMON_OPERATION_FAIL.getCode(), "存在未完成的服务", "存在未完成的服务,不能删除");
}
//校验是否有同步到通讯录,是否存在工作人员下有未处理项目数据【联建单位被同步到通讯录部门的,如果部门下人员存在未办结项目则不允许删除】
@ -438,7 +439,7 @@ public class IcPartyUnitServiceImpl extends BaseServiceImpl<IcPartyUnitDao, IcPa
@Override
public void calPartyUnitSatisfation(ServerSatisfactionCalFormDTO formDTO) {
log.info("收到消息内容啦...." + JSON.toJSONString(formDTO));
List<ServiceStatDTO> list = icUserDemandRecService.groupByServer(formDTO.getCustomerId(), formDTO.getServerId(), formDTO.getServiceType());
List<ServiceStatDTO> list = SpringContextUtils.getBean(IcUserDemandRecService.class).groupByServer(formDTO.getCustomerId(), formDTO.getServerId(), formDTO.getServiceType());
for (ServiceStatDTO serviceStatDTO : list) {
if (0 != serviceStatDTO.getDemandCount()) {
BigDecimal result = serviceStatDTO.getTotalScore().divide(new BigDecimal(serviceStatDTO.getDemandCount()), 4, BigDecimal.ROUND_HALF_UP);

6
epmet-module/epmet-oss/epmet-oss-client/src/main/java/com/epmet/enums/OssTypeEnum.java

@ -34,7 +34,11 @@ public enum OssTypeEnum {
/**
* 本地
*/
LOCAL(5);
LOCAL(5),
/**
* minio
*/
MINIO(6);
private int value;

6
epmet-module/epmet-oss/epmet-oss-server/pom.xml

@ -90,6 +90,12 @@
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
</dependency>
<!--minio-->
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>8.4.2</version>
</dependency>
</dependencies>
<build>

39
epmet-module/epmet-oss/epmet-oss-server/src/main/java/com/epmet/cloud/CloudStorageConfig.java

@ -11,9 +11,11 @@ package com.epmet.cloud;
import com.epmet.commons.tools.validator.group.AliyunGroup;
import com.epmet.commons.tools.validator.group.QcloudGroup;
import com.epmet.commons.tools.validator.group.QiniuGroup;
import com.epmet.constants.PrivacyType;
import com.epmet.validator.group.FastDFSGroup;
import com.epmet.validator.group.LocalGroup;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.validator.constraints.Range;
import org.hibernate.validator.constraints.URL;
@ -101,6 +103,9 @@ public class CloudStorageConfig implements Serializable {
private String localPath;
private AliyunCloudStorageConfig aliyun;
private MinioStorageConfig minio;
/**
* 阿里云存储配置
*/
@ -110,6 +115,20 @@ public class CloudStorageConfig implements Serializable {
private AliyunCloudStorageConfigProps external;
}
@Data
public static class MinioStorageConfig {
private MinioStorageConfigProps internal;
private MinioStorageConfigProps external;
public MinioStorageConfigProps getConfigByPrivacy(String privacy) {
if (StringUtils.isNotBlank(privacy) && PrivacyType.INTERNAL.equals(privacy)) {
return internal;
} else {
return external;
}
}
}
/**
* 阿里云存储配置属性
*/
@ -134,4 +153,24 @@ public class CloudStorageConfig implements Serializable {
private String aliyunBucketName;
}
/**
* minio存储配置属性
*/
@Data
public static class MinioStorageConfigProps {
/**
* 外部访问域名用于用户直接访问minio服务
*/
private String minioExternalDomain;
/**
* 内部访问域名用于服务集群内部使用
*/
private String minioInternalDomain;
private String minioEndPoint;
private String minioAccessKey;
private String minioSecretKey;
private String minioPrefix;
private String minioBucketName;
}
}

106
epmet-module/epmet-oss/epmet-oss-server/src/main/java/com/epmet/cloud/MinioStorageService.java

@ -0,0 +1,106 @@
package com.epmet.cloud;
import com.epmet.commons.tools.exception.EpmetErrorCode;
import com.epmet.commons.tools.exception.EpmetException;
import com.epmet.commons.tools.exception.ExceptionUtils;
import io.minio.MinioClient;
import io.minio.ObjectWriteResponse;
import io.minio.PutObjectArgs;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.http.MediaTypeFactory;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Paths;
/**
* minio 文件服务
*/
@Slf4j
public class MinioStorageService extends AbstractCloudStorageService {
private MinioClient minioClient;
public MinioStorageService(CloudStorageConfig config) {
this.config = config;
CloudStorageConfig.MinioStorageConfigProps props = config.getMinio().getConfigByPrivacy(null);
log.info("Minio客户端连接所用的域名:{}", props.getMinioInternalDomain());
/**
* minio和服务在同一个局域网则可以使用内网域名上传速度更快更稳定
*/
minioClient = MinioClient.builder()
.endpoint(props.getMinioInternalDomain()) // 保证和nginx的proxy_set_header Host 一致
.credentials(props.getMinioAccessKey(), props.getMinioSecretKey())
.build();
}
@Override
public String getOssDomain(String privacy) {
return this.config.getMinio().getConfigByPrivacy(privacy).getMinioExternalDomain();
}
@Override
public String getOssPrefix(String privacy) {
return this.config.getMinio().getConfigByPrivacy(privacy).getMinioPrefix();
}
@Override
public String upload(byte[] data, String path, String privacyType) {
return upload(new ByteArrayInputStream(data), path, privacyType);
}
@Override
public String uploadSuffix(byte[] data, String suffix, String privacyType) {
return uploadSuffix(new ByteArrayInputStream(data), suffix, privacyType);
}
/**
* 此处bucket已经做为path
* @param inputStream 字节流
* @param path 文件路径包含文件名
* @param privacyType
* @return
*/
@Override
public String upload(InputStream inputStream, String path, String privacyType) {
CloudStorageConfig.MinioStorageConfigProps props = this.config.getMinio().getConfigByPrivacy(privacyType);
String contentType = MediaTypeFactory.getMediaType(path).orElse(MediaType.APPLICATION_OCTET_STREAM).toString();
try {
ObjectWriteResponse resp = minioClient.putObject(PutObjectArgs.builder()
.bucket(props.getMinioBucketName())
.object(path)
.stream(inputStream, inputStream.available(), -1)
.contentType(contentType)
.build());
log.debug("minio上传文件成功。bucket:{}, object:{}, privacyType:{}", resp.bucket(), resp.object(), privacyType);
// 返回值要存储到数据库,供用户访问,因此使用外网域名
return props.getMinioExternalDomain() + "/" + Paths.get(resp.bucket()).resolve(resp.object()).toString();
} catch (Exception e) {
String errorMsg = ExceptionUtils.getErrorStackTrace(e);
throw new EpmetException(EpmetErrorCode.SERVER_ERROR.getCode(), errorMsg);
}
}
@Override
public String uploadSuffix(InputStream inputStream, String suffix, String privacyType) {
CloudStorageConfig.MinioStorageConfigProps props = this.config.getMinio().getConfigByPrivacy(privacyType);
return upload(inputStream, getPath(props.getMinioPrefix(), suffix, privacyType), privacyType);
}
@Override
public void down(String privacyType) throws IOException {
}
@Override
public boolean delete(String objectName, String privacyType) {
return false;
}
}

2
epmet-module/epmet-oss/epmet-oss-server/src/main/java/com/epmet/cloud/OssFactory.java

@ -40,6 +40,8 @@ public final class OssFactory {
abstractCloudStorageService = new FastDFSCloudStorageService(config);
}else if(config.getType() == OssTypeEnum.LOCAL.value()){
abstractCloudStorageService = new LocalCloudStorageService(config);
}else if(config.getType() == OssTypeEnum.MINIO.value()){
abstractCloudStorageService = new MinioStorageService(config);
}
}
return abstractCloudStorageService;

51
epmet-module/oper-crm/oper-crm-client/src/main/java/com/epmet/dto/form/CustomerInitFormDTO.java

@ -3,6 +3,7 @@ package com.epmet.dto.form;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
/**
@ -12,11 +13,55 @@ import java.io.Serializable;
@Data
public class CustomerInitFormDTO implements Serializable {
public interface GetCustomerDetailGroup {
}
/**
* 初始化带小程序的客户
*/
public interface InitMiniAppCustomerGroup {}
/**
* 初始化本地客户
*/
public interface InitLocalCustomerGroup {}
@NotBlank(message = "客户Id不能为空", groups = {GetCustomerDetailGroup.class})
@NotBlank(message = "客户Id不能为空", groups = {InitMiniAppCustomerGroup.class})
private String customerId;
@NotNull(message = "缺少paCustomer信息", groups = InitLocalCustomerGroup.class)
private PaCustomer paCustomer;
@NotNull(message = "缺少paCustomerAgency信息", groups = InitLocalCustomerGroup.class)
private PaCustomerAgency paAgency;
@NotNull(message = "缺少paUser信息", groups = InitLocalCustomerGroup.class)
private PaUser paUser;
@Data
public static class PaCustomer {
private String customerName;
private String isInitialize;
private String source;
private String type;
}
@Data
public static class PaCustomerAgency {
private String id;
private String agencyName;
private String areaCode;
private String city;
private String customerId;
private String district;
private String level;
private String levelNum;
private Integer partybranchnum;
private String province;
}
@Data
public static class PaUser {
private String gender;
private String phone;
private String realName;
}
}

36
epmet-module/oper-crm/oper-crm-server/src/main/java/com/epmet/controller/CustomerController.java

@ -257,11 +257,45 @@ public class CustomerController {
**/
@PostMapping("init")
public Result init(@RequestBody CustomerInitFormDTO formDTO) {
ValidatorUtils.validateEntity(formDTO, CustomerInitFormDTO.GetCustomerDetailGroup.class);
ValidatorUtils.validateEntity(formDTO, CustomerInitFormDTO.InitMiniAppCustomerGroup.class);
customerService.init(formDTO);
return new Result();
}
/**
* 本地初始化客户不经过小程序
* curl --location 'http://localhost:8090/oper/crm/customer/initLocally' \
* --header 'Content-Type: application/json' \
* --data '{
* "paAgency": {
* "agencyName": "wxz测试001",
* "areaCode": "370666",
* "city": "青岛市",
* "district": "海马脑区",
* "level": "district",
* "levelNum": "2",
* "partybranchnum": 50,
* "province": "山东省"
* },
* "paCustomer": {
* "customerName": "海马脑区"
* },
* "paUser": {
* "gender": "1",
* "phone": "18560677960",
* "realName": "wang"
* }
* }'
* @param formDTO
* @return
*/
@PostMapping("initLocally")
public Result initLocally(@RequestBody CustomerInitFormDTO formDTO) {
ValidatorUtils.validateEntity(formDTO, CustomerInitFormDTO.InitLocalCustomerGroup.class);
customerService.initLocal(formDTO);
return new Result();
}
/**
* desc:获取所有未删除的客户
* @return

5
epmet-module/oper-crm/oper-crm-server/src/main/java/com/epmet/service/CustomerService.java

@ -166,6 +166,11 @@ public interface CustomerService extends BaseService<CustomerEntity> {
**/
void init(CustomerInitFormDTO formDTO);
/**
* 本地初始化(不走小程序)
*/
void initLocal(CustomerInitFormDTO input);
/**
* desc获取所有客户列表
* @return

69
epmet-module/oper-crm/oper-crm-server/src/main/java/com/epmet/service/impl/CustomerServiceImpl.java

@ -22,6 +22,7 @@ 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.IdWorker;
import com.epmet.commons.mybatis.service.impl.BaseServiceImpl;
import com.epmet.commons.rocketmq.messages.InitCustomerMQMsg;
import com.epmet.commons.tools.constant.FieldConstant;
@ -585,6 +586,74 @@ public class CustomerServiceImpl extends BaseServiceImpl<CustomerDao, CustomerEn
}
@Override
public void initLocal(CustomerInitFormDTO input) {
//1.调用epmet-third服务,根据客户Id查询第三方服务中的客户、组织、管理员等信息
//PaUserDTO paUser = ConvertUtils.mapToEntity(map3, PaUserDTO.class);
String customerId = IdWorker.getIdStr();
String agencyId = IdWorker.getIdStr();
//2.校验当前客户是否已初始化,不存在则初始客户信息
CustomerEntity entity = baseDao.selectById(customerId);
if (null != entity) {
throw new RenException(EpmetErrorCode.OPER_CUSTOMER_EXISTS.getCode());
}
CustomerInitFormDTO.PaCustomer paCustomer = input.getPaCustomer();
CustomerInitFormDTO.PaCustomerAgency paCustomerAgency = input.getPaAgency();
CustomerInitFormDTO.PaUser paUser = input.getPaUser();
paCustomerAgency.setId(agencyId);
//2-1.新增客户信息
CustomerEntity customerEntity = new CustomerEntity();
customerEntity.setId(customerId);
customerEntity.setCustomerName(paCustomer.getCustomerName());
customerEntity.setTitle("");
customerEntity.setOrganizationNumber("");
customerEntity.setOrganizationImg("");
customerEntity.setValidityTime(getValidityTime());
customerEntity.setOrganizationLevel(paCustomerAgency.getLevel());
customerEntity.setLogo("");
//新客户默认可以创建三个网格
customerEntity.setGridNumber(NumConstant.THREE);
if (baseDao.insert(customerEntity) < NumConstant.ONE) {
throw new RenException(EpmetErrorCode.OPER_ADD_CUSTOMER_ERROR.getCode());
}
// *.发送初始化客户信息到mq,让监听者完成初始化操作
InitCustomerMQMsg msgContent = new InitCustomerMQMsg();
msgContent.setCustomerId(customerId);
msgContent.setAgency(constructAgencyInfo4CustomerInit(ConvertUtils.sourceToTarget(paCustomerAgency, PaCustomerAgencyDTO.class)));
msgContent.setStaff(constructStaffInfo4CustomerInit(agencyId, ConvertUtils.sourceToTarget(paUser, PaUserDTO.class)));
SystemMsgFormDTO systemMsgFormDTO = new SystemMsgFormDTO();
systemMsgFormDTO.setMessageType(SystemMessageType.INIT_CUSTOMER);
systemMsgFormDTO.setContent(msgContent);
Result sendMsgResult = epmetMessageOpenFeignClient.sendSystemMsgByMQ(systemMsgFormDTO);
if (! sendMsgResult.success()) {
throw new RenException("发送(初始化客户信息)系统消息到message服务失败:{}", sendMsgResult.getInternalMsg());
}
//2021.1.25 sun 新增初始化客户积分规则和评价指标权重 start
//8.客户初始化已有的积分规则
Result<InitPointRuleResultDTO> resultPoint = epmetPointOpenFeignClient.initPointRule(customerId);
if (!resultPoint.success()) {
throw new RenException(resultPoint.getCode(), resultPoint.getInternalMsg());
}
//9.新客户初始化评价指标 权重
InitCustomerIndexForm indexForm = new InitCustomerIndexForm();
indexForm.setCustomerId(customerId);
Result<Boolean> resultData = dataStatisticalOpenFeignClient.initCustomerIndex(indexForm);
if (!resultData.success()) {
throw new RenException(resultData.getCode(), resultData.getInternalMsg());
}
//2021.1.25 end
}
private InitCustomerMQMsg.InitCustomerStaff constructStaffInfo4CustomerInit(String agencyId, PaUserDTO paUser) {
InitCustomerMQMsg.InitCustomerStaff staff = new InitCustomerMQMsg.InitCustomerStaff();
staff.setAgencyId(agencyId);

Loading…
Cancel
Save