Browse Source

Merge branch 'develop' of https://gitee.com/lmlz_0/manage into develop

develop
bobol 11 months ago
parent
commit
c9a0d890e9
  1. 5
      lzbi-admin/src/main/resources/application-dev.yml
  2. 61
      lzbi-module/src/main/java/com/lzbi/draft/controller/DcBusiParamBillMasterController.java
  3. 45
      lzbi-module/src/main/java/com/lzbi/draft/controller/DcBusiParamCollectBill.java
  4. 2
      lzbi-module/src/main/java/com/lzbi/draft/domain/DcBusiParamBillMaster.java
  5. 10
      lzbi-module/src/main/java/com/lzbi/draft/domain/DcBusiParamBillSub.java
  6. 1
      lzbi-module/src/main/java/com/lzbi/draft/mapper/DcBusiParamBillMasterMapper.java
  7. 5
      lzbi-module/src/main/java/com/lzbi/draft/service/DcBusiParamBillMasterService.java
  8. 24
      lzbi-module/src/main/resources/mapper/asset/DcBusiParamBillMasterMapper.xml

5
lzbi-admin/src/main/resources/application-dev.yml

@ -79,6 +79,9 @@ spring:
url: jdbc:mysql://10.10.10.56:13306/lzdc_bi_db?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&rewriteBatchedStatements=true url: jdbc:mysql://10.10.10.56:13306/lzdc_bi_db?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&rewriteBatchedStatements=true
username: luenmei username: luenmei
password: 123456 password: 123456
#url: jdbc:mysql://localhost:3306/lmlz_dcdb?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&rewriteBatchedStatements=true
#username: root
#password: root123456
# # 计费数据库 # # 计费数据库
# charge: # charge:
# driverClassName: oracle.jdbc.OracleDriver # driverClassName: oracle.jdbc.OracleDriver
@ -93,7 +96,7 @@ spring:
password: 123456 password: 123456
workDB: workDB:
driverClassName: org.postgresql.Driver driverClassName: org.postgresql.Driver
#type: com.alibaba.druid.pool.DruidDataSource type: com.alibaba.druid.pool.DruidDataSource
url: jdbc:postgresql://10.10.10.56:5432/dctestdb?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&serverTimezone=Asia/Shanghai url: jdbc:postgresql://10.10.10.56:5432/dctestdb?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&serverTimezone=Asia/Shanghai
username: postgres username: postgres
password: 123456 password: 123456

61
lzbi-module/src/main/java/com/lzbi/draft/controller/DcBusiParamBillMasterController.java

@ -1,15 +1,24 @@
package com.lzbi.draft.controller; package com.lzbi.draft.controller;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson2.JSONObject;
import com.lzbi.common.utils.DateUtils; import com.lzbi.common.utils.DateUtils;
import com.lzbi.common.utils.SecurityUtils; import com.lzbi.common.utils.SecurityUtils;
import com.lzbi.common.utils.StringUtils;
import com.lzbi.draft.domain.DcBusiParamBillSub; import com.lzbi.draft.domain.DcBusiParamBillSub;
import com.lzbi.draft.service.DcBusiParamBillSubService; import com.lzbi.draft.service.DcBusiParamBillSubService;
import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams; import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
@ -64,6 +73,41 @@ public class DcBusiParamBillMasterController extends BaseController
List<DcBusiParamBillSub> list = dcBusiParamBillSubService.selectByVo(sub); List<DcBusiParamBillSub> list = dcBusiParamBillSubService.selectByVo(sub);
return AjaxResult.success(list); return AjaxResult.success(list);
} }
@ApiOperation("参数采集单主从详情")
@ApiImplicitParams({
@ApiImplicitParam(name = "billNo", value = "", dataType = "String", dataTypeClass = String.class),
})
@GetMapping("/info/{billNo}")
public AjaxResult getParamInBillInfo(@PathVariable String billNo){
DcBusiParamBillMaster master = dcBusiParamBillMasterService.selectDcBusiParamBillMasterDaoByNo(billNo);
Map<String, List<DcBusiParamBillSub>> map = master.getDcBusiParamBillSubList().stream().collect(Collectors.groupingBy(DcBusiParamBillSub::getCountHourString));
master.setCountTimes(map.keySet().stream().collect(Collectors.joining(",")));
master.setCountDate(master.getBillIncomeDate());
Map<String, JSONObject> mapRow=new HashMap<>();
map.keySet().stream().forEach(key->{
List<DcBusiParamBillSub> sub=map.get(key);
sub.forEach(subItem->{
JSONObject jsb=mapRow.get(subItem.getAssetCode()+subItem.getParamCode());
if(StringUtils.isNull(jsb)){
jsb=new JSONObject();
jsb.put("assetName",subItem.getAssetName());
jsb.put("assetCode",subItem.getAssetCode());
jsb.put("paramCode",subItem.getParamCode());
jsb.put("paramName",subItem.getParamName());
jsb.put("paramUint",subItem.getParamUint());
jsb.put("val_"+key,subItem.getParamValue());
mapRow.put(subItem.getAssetCode()+subItem.getParamCode(),jsb);
master.setFieldCode(subItem.getFieldCode());
master.setFieldName(subItem.getFieldName());
}else{
jsb.put("val_"+key,subItem.getParamValue());
}
});
});
master.setSubRecord(mapRow.values().stream().collect(Collectors.toList()));
return AjaxResult.success(master);
}
@ApiOperation("采集单驳回") @ApiOperation("采集单驳回")
@ApiImplicitParams({ @ApiImplicitParams({
@ApiImplicitParam(name = "billNo", value = "", dataType = "String", dataTypeClass = String.class), @ApiImplicitParam(name = "billNo", value = "", dataType = "String", dataTypeClass = String.class),
@ -88,7 +132,20 @@ public class DcBusiParamBillMasterController extends BaseController
master.setUpdatedBy(SecurityUtils.getUsername()); master.setUpdatedBy(SecurityUtils.getUsername());
master.setCreatedTime(DateUtils.getNowDate()); master.setCreatedTime(DateUtils.getNowDate());
master.setBillNo(billNo); master.setBillNo(billNo);
master.setCheckStatus("1"); master.setCheckStatus("2");
return AjaxResult.success(dcBusiParamBillMasterService.checkBill(master));
}
@ApiOperation("采集单反审核")
@ApiImplicitParams({
@ApiImplicitParam(name = "billNo", value = "", dataType = "String", dataTypeClass = String.class),
})
@GetMapping("/checkRevert/{billNo}")
public AjaxResult checkParamInBillRevert(@PathVariable String billNo){
DcBusiParamBillMaster master=new DcBusiParamBillMaster();
master.setUpdatedBy(SecurityUtils.getUsername());
master.setCreatedTime(DateUtils.getNowDate());
master.setBillNo(billNo);
master.setCheckStatus("0");
return AjaxResult.success(dcBusiParamBillMasterService.checkBill(master)); return AjaxResult.success(dcBusiParamBillMasterService.checkBill(master));
} }

45
lzbi-module/src/main/java/com/lzbi/draft/controller/DcBusiParamCollectBill.java

@ -276,6 +276,51 @@ public class DcBusiParamCollectBill extends BaseController
dcBusiParamBillMaster.setDcBusiParamBillSubList(dcBusiParamBillSubList); dcBusiParamBillMaster.setDcBusiParamBillSubList(dcBusiParamBillSubList);
return AjaxResult.success(dcBusiParamBillMasterService.insertDcBusiParamBillMasterDao(dcBusiParamBillMaster)); return AjaxResult.success(dcBusiParamBillMasterService.insertDcBusiParamBillMasterDao(dcBusiParamBillMaster));
} }
@ApiOperation("更新参数采集数据-subDatas数组方式")
@ApiImplicitParams({
@ApiImplicitParam(name = "dcBusiParamBillMaster", value = "", dataType = "DcBusiParamBillMaster", dataTypeClass = DcBusiParamBillMaster.class),
})
@PostMapping("/updateBillCollectArray")
/*subDatas为动态数据列,值是分开的索要对每个列值进行处理*/
public AjaxResult updateBillCollectBy(@RequestBody DcBusiParamBillMaster dcBusiParamBillMaster){
List<DcBusiParamBillSub> dcBusiParamBillSubList =new ArrayList<>();
dcBusiParamBillMaster.setUpdatedBy(SecurityUtils.getUsername());
JSONObject datasets=Optional.ofNullable(dcBusiParamBillMaster.getSubDatas()).orElse(new JSONObject());
JSONArray dataArray=new JSONArray();
dataArray.addAll(datasets.getJSONArray("insertRecords"));
//dataArray.addAll(datasets.getJSONArray("updateRecords"));
//dataArray.addAll(datasets.getJSONArray("removeRecords"));
String billNo=dcBusiParamBillMaster.getBillNo();
dataArray.forEach(item->{
JSONObject jsb = JSONObject.from(item);
for(int i=1;i<25;i++){
String fname="val_"+String.valueOf(i);
Double value=jsb.getDouble(fname);
if(StringUtils.isNotNull(value)){
DcBusiParamBillSub dcBusiParamBillSub=new DcBusiParamBillSub();
//基本数据
dcBusiParamBillSub.setBillNo(billNo);
dcBusiParamBillSub.setId(null);
dcBusiParamBillSub.setParamCode(jsb.getString("paramCode"));
dcBusiParamBillSub.setAssetCode(jsb.getString("assetCode"));
dcBusiParamBillSub.setAssetName(jsb.getString("assetName"));
//dcBusiParamBillSub.setCountDate(jsb.getString("countDate"));
dcBusiParamBillSub.setCountDate(dcBusiParamBillMaster.getBillIncomeDate());
dcBusiParamBillSub.setParamUint(jsb.getString("paramUint"));
dcBusiParamBillSub.setParamName(jsb.getString("paramName"));
dcBusiParamBillSub.setFieldCode(jsb.getString("fieldCode"));
dcBusiParamBillSub.setFieldName(jsb.getString("fieldName"));
dcBusiParamBillSub.setCountHour(i);
dcBusiParamBillSub.setParamValue(value);
dcBusiParamBillSubList.add(dcBusiParamBillSub);
}
}
});
dcBusiParamBillMaster.setDcBusiParamBillSubList(dcBusiParamBillSubList);
return AjaxResult.success(dcBusiParamBillMasterService.updateDcBusiParamBillMasterDao(dcBusiParamBillMaster));
}
private String getBillModelNo(){ private String getBillModelNo(){
DcBusiCoderuleConfigDao ruleIdByBusicode =Optional.ofNullable(dcBaseCoderuleDefineService.getRuleIdByBusicode("BILL_MODEL_NO")).orElse(new DcBusiCoderuleConfigDao()) ; DcBusiCoderuleConfigDao ruleIdByBusicode =Optional.ofNullable(dcBaseCoderuleDefineService.getRuleIdByBusicode("BILL_MODEL_NO")).orElse(new DcBusiCoderuleConfigDao()) ;

2
lzbi-module/src/main/java/com/lzbi/draft/domain/DcBusiParamBillMaster.java

@ -84,7 +84,7 @@ public class DcBusiParamBillMaster extends BaseModuleEntity
private List<DcBusiParamBillSub> dcBusiParamBillSubList; private List<DcBusiParamBillSub> dcBusiParamBillSubList;
@ApiModelProperty(name = "data数组数据未转换",notes = "") @ApiModelProperty(name = "data数组数据未转换",notes = "")
private JSONObject subDatas; private JSONObject subDatas;
private List<JSONObject> subRecord;
} }

10
lzbi-module/src/main/java/com/lzbi/draft/domain/DcBusiParamBillSub.java

@ -1,6 +1,7 @@
package com.lzbi.draft.domain; package com.lzbi.draft.domain;
import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.IdType;
import com.lzbi.common.utils.StringUtils;
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
@ -52,6 +53,9 @@ public class DcBusiParamBillSub extends BaseModuleEntity{
/** 指标编码 */ /** 指标编码 */
@ApiModelProperty(name = "指标编码",notes = "") @ApiModelProperty(name = "指标编码",notes = "")
private String paramCode ; private String paramCode ;
/** 指标编码 */
@ApiModelProperty(name = "指标别名",notes = "")
private String assetAlialsName ;
/** 指标单位 */ /** 指标单位 */
@ApiModelProperty(name = "指标单位",notes = "") @ApiModelProperty(name = "指标单位",notes = "")
private String paramUint ; private String paramUint ;
@ -76,4 +80,10 @@ public class DcBusiParamBillSub extends BaseModuleEntity{
public String getFieldCode(){ public String getFieldCode(){
return Optional.ofNullable(this.fieldCode).orElse(""); return Optional.ofNullable(this.fieldCode).orElse("");
} }
public String getCountHourString(){
return String.valueOf(countHour);
}
public String getCountHourStringPad(){
return StringUtils.leftPad(getCountHourString(),2,'0');
}
} }

1
lzbi-module/src/main/java/com/lzbi/draft/mapper/DcBusiParamBillMasterMapper.java

@ -22,6 +22,7 @@ public interface DcBusiParamBillMasterMapper extends BaseMapper<DcBusiParamBillM
* @return 参数采集录入单据主 * @return 参数采集录入单据主
*/ */
public DcBusiParamBillMaster selectDcBusiParamBillMasterDaoById(Long id); public DcBusiParamBillMaster selectDcBusiParamBillMasterDaoById(Long id);
public DcBusiParamBillMaster selectDcBusiParamBillMasterDaoByNo(String billNo);
/** /**
* 查询参数采集录入单据主列表 * 查询参数采集录入单据主列表

5
lzbi-module/src/main/java/com/lzbi/draft/service/DcBusiParamBillMasterService.java

@ -32,7 +32,10 @@ public class DcBusiParamBillMasterService extends ServiceImpl<DcBusiParamBillMas
{ {
return baseMapper.selectDcBusiParamBillMasterDaoById(id); return baseMapper.selectDcBusiParamBillMasterDaoById(id);
} }
public DcBusiParamBillMaster selectDcBusiParamBillMasterDaoByNo(String billNo)
{
return baseMapper.selectDcBusiParamBillMasterDaoByNo(billNo);
}
/** /**
* 查询参数采集录入单据主列表 * 查询参数采集录入单据主列表
* *

24
lzbi-module/src/main/resources/mapper/asset/DcBusiParamBillMasterMapper.xml

@ -47,6 +47,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="countDate" column="sub_count_date" /> <result property="countDate" column="sub_count_date" />
<result property="countHour" column="sub_count_hour" /> <result property="countHour" column="sub_count_hour" />
<result property="paramCode" column="sub_param_code" /> <result property="paramCode" column="sub_param_code" />
<result property="paramName" column="sub_param_name" />
<result property="paramUint" column="sub_param_uint" /> <result property="paramUint" column="sub_param_uint" />
<result property="paramValue" column="sub_param_value" /> <result property="paramValue" column="sub_param_value" />
</resultMap> </resultMap>
@ -73,12 +74,19 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</select> </select>
<select id="selectDcBusiParamBillMasterDaoById" parameterType="Long" resultMap="DcBusiParamBillMasterDcBusiParamBillSubResult"> <select id="selectDcBusiParamBillMasterDaoById" parameterType="Long" resultMap="DcBusiParamBillMasterDcBusiParamBillSubResult">
select a.TENANT_ID, a.REVISION, a.CREATED_BY, a.CREATED_TIME, a.UPDATED_BY, a.UPDATED_TIME, a.DELETE_BY, a.DELETE_TIME, a.id, a.bill_no, a.bill_income_date, a.bill_type, a.check_type, a.check_status, select a.TENANT_ID, a.REVISION, a.CREATED_BY, a.CREATED_TIME, a.UPDATED_BY, a.UPDATED_TIME, a.DELETE_BY, a.DELETE_TIME, a.id, a.bill_no, a.bill_income_date, a.bill_type, a.check_type, a.check_status,a.company_id,a.company_name,a.organize_name,a.oragnize_id,
b.TENANT_ID as sub_TENANT_ID, b.CREATED_BY as sub_CREATED_BY, b.CREATED_TIME as sub_CREATED_TIME, b.UPDATED_BY as sub_UPDATED_BY, b.UPDATED_TIME as sub_UPDATED_TIME, b.DELETE_BY as sub_DELETE_BY, b.DELETE_TIME as sub_DELETE_TIME, b.id as sub_id, b.bill_no as sub_bill_no,b.asset_code as sub_asset_code,b.asset_name as sub_asset_name, b.field_code as sub_field_code, b.field_name as sub_field_name, b.param_code as sub_param_code, b.param_value as sub_param_value, b.count_date as sub_count_date, b.count_hour as sub_count_hour b.TENANT_ID as sub_TENANT_ID, b.CREATED_BY as sub_CREATED_BY, b.CREATED_TIME as sub_CREATED_TIME, b.UPDATED_BY as sub_UPDATED_BY, b.UPDATED_TIME as sub_UPDATED_TIME, b.DELETE_BY as sub_DELETE_BY, b.DELETE_TIME as sub_DELETE_TIME, b.id as sub_id, b.bill_no as sub_bill_no,b.asset_code as sub_asset_code,b.asset_name as sub_asset_name, b.field_code as sub_field_code, b.field_name as sub_field_name, b.param_code as sub_param_code,b.param_name as sub_param_name, b.param_value as sub_param_value, b.count_date as sub_count_date, b.count_hour as sub_count_hour, b.param_uint as sub_param_uint
from dc_busi_param_bill_master a from dc_busi_param_bill_master a
left join dc_busi_param_bill_sub b on b.bill_no = a.bill_no left join dc_busi_param_bill_sub b on b.bill_no = a.bill_no
where a.id = #{id} where a.id = #{id}
</select> </select>
<select id="selectDcBusiParamBillMasterDaoByNo" parameterType="String" resultMap="DcBusiParamBillMasterDcBusiParamBillSubResult">
select a.TENANT_ID, a.REVISION, a.CREATED_BY, a.CREATED_TIME, a.UPDATED_BY, a.UPDATED_TIME, a.DELETE_BY, a.DELETE_TIME, a.id, a.bill_no, a.bill_income_date, a.bill_type, a.check_type, a.check_status,a.company_id,a.company_name,a.organize_name,a.oragnize_id,
b.TENANT_ID as sub_TENANT_ID, b.CREATED_BY as sub_CREATED_BY, b.CREATED_TIME as sub_CREATED_TIME, b.UPDATED_BY as sub_UPDATED_BY, b.UPDATED_TIME as sub_UPDATED_TIME, b.DELETE_BY as sub_DELETE_BY, b.DELETE_TIME as sub_DELETE_TIME, b.id as sub_id, b.bill_no as sub_bill_no,b.asset_code as sub_asset_code,b.asset_name as sub_asset_name, b.field_code as sub_field_code, b.field_name as sub_field_name, b.param_code as sub_param_code,b.param_name as sub_param_name, b.param_value as sub_param_value, b.count_date as sub_count_date, b.count_hour as sub_count_hour, b.param_uint as sub_param_uint
from dc_busi_param_bill_master a
left join dc_busi_param_bill_sub b on b.bill_no = a.bill_no
where a.bill_no = #{billNo}
</select>
<insert id="insertDcBusiParamBillMasterDao" parameterType="DcBusiParamBillMaster" useGeneratedKeys="true" keyProperty="id"> <insert id="insertDcBusiParamBillMasterDao" parameterType="DcBusiParamBillMaster" useGeneratedKeys="true" keyProperty="id">
insert into dc_busi_param_bill_master insert into dc_busi_param_bill_master
@ -138,6 +146,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="billType != null">bill_type = #{billType},</if> <if test="billType != null">bill_type = #{billType},</if>
<if test="checkType != null">check_type = #{checkType},</if> <if test="checkType != null">check_type = #{checkType},</if>
<if test="checkStatus != null">check_status = #{checkStatus},</if> <if test="checkStatus != null">check_status = #{checkStatus},</if>
<if test="companyId != null">company_id=#{companyId},</if>
<if test="companyName != null">company_name=#{companyName},</if>
<if test="organizeName != null">organize_name=#{organizeName},</if>
<if test="oragnizeId != null">oragnize_id=#{oragnizeId},</if>
</trim> </trim>
where id = #{id} where id = #{id}
</update> </update>
@ -156,6 +168,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="billType != null">bill_type = #{billType},</if> <if test="billType != null">bill_type = #{billType},</if>
<if test="checkType != null">check_type = #{checkType},</if> <if test="checkType != null">check_type = #{checkType},</if>
<if test="checkStatus != null">check_status = #{checkStatus},</if> <if test="checkStatus != null">check_status = #{checkStatus},</if>
<if test="companyId != null">company_id=#{companyId},</if>
<if test="companyName != null">company_name=#{companyName},</if>
<if test="organizeName != null">organize_name=#{organizeName},</if>
<if test="oragnizeId != null">oragnize_id=#{oragnizeId},</if>
</trim> </trim>
where bill_no = #{billNo} where bill_no = #{billNo}
</update> </update>
@ -182,9 +198,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</delete> </delete>
<insert id="batchDcBusiParamBillSubDao"> <insert id="batchDcBusiParamBillSubDao">
insert into dc_busi_param_bill_sub( TENANT_ID, CREATED_BY, CREATED_TIME, UPDATED_BY, UPDATED_TIME, DELETE_BY, DELETE_TIME, id, bill_no, asset_code,asset_name, field_code, field_name, param_code, param_value,count_date,count_hour,param_name) values insert into dc_busi_param_bill_sub( TENANT_ID, CREATED_BY, CREATED_TIME, UPDATED_BY, UPDATED_TIME, DELETE_BY, DELETE_TIME, id, bill_no, asset_code,asset_name, field_code, field_name, param_code, param_value,count_date,count_hour,param_name,param_uint) values
<foreach item="item" index="index" collection="list" separator=","> <foreach item="item" index="index" collection="list" separator=",">
( #{item.tenantId}, #{item.createdBy}, #{item.createdTime}, #{item.updatedBy}, #{item.updatedTime}, #{item.deleteBy}, #{item.deleteTime}, #{item.id}, #{item.billNo}, #{item.assetCode}, #{item.assetName}, #{item.fieldCode}, #{item.fieldName},#{item.paramCode}, #{item.paramValue}, #{item.countDate}, #{item.countHour},#{item.paramName}) ( #{item.tenantId}, #{item.createdBy}, #{item.createdTime}, #{item.updatedBy}, #{item.updatedTime}, #{item.deleteBy}, #{item.deleteTime}, #{item.id}, #{item.billNo}, #{item.assetCode}, #{item.assetName}, #{item.fieldCode}, #{item.fieldName},#{item.paramCode}, #{item.paramValue}, #{item.countDate}, #{item.countHour},#{item.paramName},#{item.paramUint})
</foreach> </foreach>
</insert> </insert>
</mapper> </mapper>
Loading…
Cancel
Save