Procházet zdrojové kódy

[短信][修复]:使用最新的会员筛选器接口

release_toaliyun_real
hupeng před 7 roky
rodič
revize
c5b3cf7925
12 změnil soubory, kde provedl 75 přidání a 95 odebrání
  1. +27
    -45
      mallinkAdmin/src/main/java/com/iformall/controller/WxMsgController.java
  2. +2
    -0
      mallinkAdmin/src/main/resources/db/migration/V201904181120__ADD_TAGS_COLUMN.sql
  3. +25
    -2
      mallinkService/src/main/java/com/iformall/domain/po/msg/WxMsg.java
  4. +2
    -2
      mallinkService/src/main/java/com/iformall/enums/EnumTag.java
  5. +0
    -2
      mallinkService/src/main/java/com/iformall/mapper/WxCUserTagsMapper.java
  6. +2
    -0
      mallinkService/src/main/java/com/iformall/service/WxCUserBasicInfoService.java
  7. +0
    -3
      mallinkService/src/main/java/com/iformall/service/WxCUserTagsService.java
  8. +12
    -0
      mallinkService/src/main/java/com/iformall/service/impl/WxCUserBasicInfoServiceImpl.java
  9. +0
    -20
      mallinkService/src/main/java/com/iformall/service/impl/WxCUserTagsServiceImpl.java
  10. +2
    -8
      mallinkService/src/main/java/com/iformall/service/impl/WxCouponInjectServiceImpl.java
  11. +0
    -7
      mallinkService/src/main/resources/mapper/WxCUserTagsMapper.xml
  12. +3
    -6
      mallinkService/src/main/resources/mapper/WxMsgMapper.xml

+ 27
- 45
mallinkAdmin/src/main/java/com/iformall/controller/WxMsgController.java Zobrazit soubor

@@ -1,10 +1,12 @@
package com.iformall.controller; package com.iformall.controller;


import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageInfo; import com.github.pagehelper.PageInfo;
import com.iformall.annotation.SystemControllerLog; import com.iformall.annotation.SystemControllerLog;
import com.iformall.common.ErrorCode; import com.iformall.common.ErrorCode;
import com.iformall.common.Result; import com.iformall.common.Result;
import com.iformall.common.ResultData; import com.iformall.common.ResultData;
import com.iformall.domain.dto.WxCUserBasicInfoFilterListDto;
import com.iformall.domain.po.PushLimit; import com.iformall.domain.po.PushLimit;
import com.iformall.domain.po.WxCUserBasicInfo; import com.iformall.domain.po.WxCUserBasicInfo;
import com.iformall.domain.po.msg.WxMsg; import com.iformall.domain.po.msg.WxMsg;
@@ -14,14 +16,17 @@ import com.iformall.enums.EnumMsgStatus;
import com.iformall.exception.MallinkException; import com.iformall.exception.MallinkException;
import com.iformall.mapper.WxMsgConfigMapper; import com.iformall.mapper.WxMsgConfigMapper;
import com.iformall.service.PushLimitService; import com.iformall.service.PushLimitService;
import com.iformall.service.WxCUserBasicInfoService;
import com.iformall.service.WxCUserTagsService; import com.iformall.service.WxCUserTagsService;
import com.iformall.service.WxMsgService; import com.iformall.service.WxMsgService;
import com.iformall.utils.Constant; import com.iformall.utils.Constant;
import com.iformall.utils.DateUtils; import com.iformall.utils.DateUtils;
import io.netty.util.internal.StringUtil;
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.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@@ -31,6 +36,7 @@ import org.springframework.web.multipart.MultipartFile;
import java.io.File; import java.io.File;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.util.*; import java.util.*;
import java.util.stream.Collectors;


/** /**
* @author gongbiao * @author gongbiao
@@ -49,6 +55,9 @@ public class WxMsgController extends BaseController {
@Autowired @Autowired
WxCUserTagsService wxCUserTagsService; WxCUserTagsService wxCUserTagsService;


@Autowired
WxCUserBasicInfoService wxCUserBasicInfoService;

@Autowired @Autowired
PushLimitService pushLimitService; PushLimitService pushLimitService;


@@ -103,31 +112,31 @@ public class WxMsgController extends BaseController {
//1、手机多条以逗号分隔,直接通过实体得到wxmsg.getphones //1、手机多条以逗号分隔,直接通过实体得到wxmsg.getphones
//2、通过标签 //2、通过标签
String phones = wxMsg.getPhones(); String phones = wxMsg.getPhones();
String label = wxMsg.getLabel();
if (!phones.equals("") && !label.equals("")) {//两种方式只能选其一
List<WxCUserBasicInfoFilterListDto> filter = wxMsg.getFilterList();
if (!phones.isEmpty() && !filter.isEmpty()) {//两种方式只能选其一
return new ResultData(ErrorCode.MSG_SEND_WAY_CHOOSE_ERROR);
}
if (phones.isEmpty() && filter.isEmpty()) {//两种方式必须选其一
return new ResultData(ErrorCode.MSG_SEND_WAY_CHOOSE_ERROR); return new ResultData(ErrorCode.MSG_SEND_WAY_CHOOSE_ERROR);
} }


if (phones.equals("")) {//没有手工输入手机号时解析标签,有,继续流转
phones = parselabel(wxMsg.getTenantId(), wxMsg);
if (phones.equals("")) {//解析之后手机号依然不存在时返回
if (phones.isEmpty()) {//没有手工输入手机号时解析标签,有,继续流转
List<WxCUserBasicInfo> list =
wxCUserBasicInfoService.listByFilterList(wxMsg.getTenantId(),wxMsg.getFilterList());
wxMsg.setExpectSendNumber(list.size());//预计发送数量
phones = list.stream().map(u -> u.getPhone()).collect(Collectors.joining(","));
if (phones==null || phones.isEmpty()) {//解析之后手机号依然不存在时返回
return new ResultData(ErrorCode.MSG_NO_VALID_PHONE); return new ResultData(ErrorCode.MSG_NO_VALID_PHONE);
} }
wxMsg.setPhones(StringUtils.join(phones));
wxMsg.setTags(JSON.toJSONString(wxMsg.getFilterList()));
} else {
String[] phoneSplit = phones.split(",");
Set<String> phoneSet = new HashSet<>(Arrays.asList(phoneSplit));
wxMsg.setExpectSendNumber(phoneSet.size());//预计发送数量
wxMsg.setPhones(StringUtils.join(phoneSet,","));
} }


//保证手机号惟一
String[] phoneSplit = phones.split(",");
Set<String> phoneSet = new HashSet<>();
for (String phone : phoneSplit) {
phoneSet.add(phone);
}
wxMsg.setExpectSendNumber(phoneSet.size());//预计发送数量
StringBuffer sb = new StringBuffer();
for (String phone : phoneSet) {
sb.append(phone).append(",");
}
wxMsg.setPhones(sb.deleteCharAt(sb.length() - 1).toString());

//从短信配置中查询密钥 bid 等信息 //从短信配置中查询密钥 bid 等信息
WxMsgConfig wxMsgConfig = new WxMsgConfig(); WxMsgConfig wxMsgConfig = new WxMsgConfig();
wxMsgConfig.setTenantId(wxMsg.getTenantId()); wxMsgConfig.setTenantId(wxMsg.getTenantId());
@@ -148,24 +157,6 @@ public class WxMsgController extends BaseController {
return new ResultData(); return new ResultData();
} }


private String parselabel(String tenantId, WxMsg wxmsg) {
String label = wxmsg.getLabel();
String[] arys = label.split(",");
List<Long> tagids = new ArrayList<>();
for (int i = 0; i < arys.length; i++) {
tagids.add(Long.parseLong(arys[i]));
}
List<WxCUserBasicInfo> list = wxCUserTagsService.findByTag(tenantId, tagids);

StringBuilder sb = new StringBuilder();
if (list.size() > 0) {
for (WxCUserBasicInfo cUserInfo : list) {
sb.append(cUserInfo.getPhone()).append(",");
}
return sb.toString();
}
return "";
}


@ApiOperation("根据id删除接口") @ApiOperation("根据id删除接口")
@GetMapping("/del") @GetMapping("/del")
@@ -184,15 +175,6 @@ public class WxMsgController extends BaseController {
public ResultData findById(Long id) { public ResultData findById(Long id) {
logger.debug("[" + getIpAddr() + "] WxMsgController::findById"); logger.debug("[" + getIpAddr() + "] WxMsgController::findById");
WxMsg wxMsg = wxMsgService.getById(id); WxMsg wxMsg = wxMsgService.getById(id);
String label = wxMsg.getLabel();
if (label != null && !label.isEmpty()) {
String[] arys = label.split(",");
List<Long> tagids = new ArrayList<>();
for (int i = 0; i < arys.length; i++) {
tagids.add(Long.parseLong(arys[i]));
}
wxMsg.setTagsList(wxCUserTagsService.findTagList(getTenantId(), tagids));
}
return new ResultData(wxMsg); return new ResultData(wxMsg);
} }




+ 2
- 0
mallinkAdmin/src/main/resources/db/migration/V201904181120__ADD_TAGS_COLUMN.sql Zobrazit soubor

@@ -0,0 +1,2 @@
ALTER TABLE `wx_msg`
ADD COLUMN `tags` JSON NULL DEFAULT NULL AFTER `label`;

+ 25
- 2
mallinkService/src/main/java/com/iformall/domain/po/msg/WxMsg.java Zobrazit soubor

@@ -1,5 +1,6 @@
package com.iformall.domain.po.msg; package com.iformall.domain.po.msg;


import com.iformall.domain.dto.WxCUserBasicInfoFilterListDto;
import com.iformall.domain.po.WxCouponInject; import com.iformall.domain.po.WxCouponInject;
import com.iformall.domain.po.WxMsgConfig; import com.iformall.domain.po.WxMsgConfig;
import com.iformall.domain.po.WxTags; import com.iformall.domain.po.WxTags;
@@ -60,6 +61,10 @@ public class WxMsg extends BaseMsg {
@io.swagger.annotations.ApiModelProperty(value = "excelpath", name = "excelpath") @io.swagger.annotations.ApiModelProperty(value = "excelpath", name = "excelpath")
private String excelpath; private String excelpath;


/*发送人群标签**/
@io.swagger.annotations.ApiModelProperty(value="发送人群标签",name="tags")
private String tags;

@io.swagger.annotations.ApiModelProperty(value = "标签人群", name = "label") @io.swagger.annotations.ApiModelProperty(value = "标签人群", name = "label")
private String label; private String label;


@@ -72,13 +77,31 @@ public class WxMsg extends BaseMsg {
@io.swagger.annotations.ApiModelProperty(value = "couponInjectId", name = "couponInjectId") @io.swagger.annotations.ApiModelProperty(value = "couponInjectId", name = "couponInjectId")
private Long couponInjectId; private Long couponInjectId;


@Transient
List<WxTags> tagsList;


//用于mq发送消息 //用于mq发送消息
private WxMsgConfig wxMsgConfig; private WxMsgConfig wxMsgConfig;
private WxCouponInject couponInject; private WxCouponInject couponInject;


public String getTags() {
return tags;
}

public void setTags(String tags) {
this.tags = tags;
}


@Transient
List<WxCUserBasicInfoFilterListDto> filterList;

public List<WxCUserBasicInfoFilterListDto> getFilterList() {
return filterList;
}

public void setFilterList(List<WxCUserBasicInfoFilterListDto> filterList) {
this.filterList = filterList;
}



public WxMsgConfig getWxMsgConfig() { public WxMsgConfig getWxMsgConfig() {
return wxMsgConfig; return wxMsgConfig;


+ 2
- 2
mallinkService/src/main/java/com/iformall/enums/EnumTag.java Zobrazit soubor

@@ -182,12 +182,12 @@ public enum EnumTag {
ID_1000(1000L, EnumTagType.ID_50,"一天以内"), ID_1000(1000L, EnumTagType.ID_50,"一天以内"),
ID_1001(1001L, EnumTagType.ID_50,"一周以内"), ID_1001(1001L, EnumTagType.ID_50,"一周以内"),
ID_1002(1002L, EnumTagType.ID_50,"一月以内"), ID_1002(1002L, EnumTagType.ID_50,"一月以内"),
ID_1003(1003L, EnumTagType.ID_50,"一季度以内"),
ID_1003(1003L, EnumTagType.ID_50,"三月以内"),
ID_1004(1004L, EnumTagType.ID_50,"一年以内"), ID_1004(1004L, EnumTagType.ID_50,"一年以内"),
ID_1005(1005L, EnumTagType.ID_50,"五年以内"), ID_1005(1005L, EnumTagType.ID_50,"五年以内"),
ID_1006(1006L, EnumTagType.ID_50,"五年以上"), ID_1006(1006L, EnumTagType.ID_50,"五年以上"),
ID_1007(1007L, EnumTagType.ID_50,"一年以上"), ID_1007(1007L, EnumTagType.ID_50,"一年以上"),
ID_1008(1008L, EnumTagType.ID_50,"一季度以上"),
ID_1008(1008L, EnumTagType.ID_50,"三月以上"),
ID_1009(1009L, EnumTagType.ID_50,"一月以上"), ID_1009(1009L, EnumTagType.ID_50,"一月以上"),
ID_1010(1010L, EnumTagType.ID_50,"一周以上"), ID_1010(1010L, EnumTagType.ID_50,"一周以上"),
ID_1011(1011L, EnumTagType.ID_50,"一天以上"), ID_1011(1011L, EnumTagType.ID_50,"一天以上"),


+ 0
- 2
mallinkService/src/main/java/com/iformall/mapper/WxCUserTagsMapper.java Zobrazit soubor

@@ -12,8 +12,6 @@ public interface WxCUserTagsMapper extends CommonMapper<WxCUserTags, String> {


List<WxCUserTags> findList(WxCUserTags wxCUserTags); List<WxCUserTags> findList(WxCUserTags wxCUserTags);


List<Long> findByTags(@Param("tagIds")String tagIds,@Param("tenantId")String tenantId);

long countUser(@Param("tagIds")String tagIds,@Param("tenantId")String tenantId, long countUser(@Param("tagIds")String tagIds,@Param("tenantId")String tenantId,
@Param("startTime")Date startTime,@Param("endTime")Date endTime); @Param("startTime")Date startTime,@Param("endTime")Date endTime);




+ 2
- 0
mallinkService/src/main/java/com/iformall/service/WxCUserBasicInfoService.java Zobrazit soubor

@@ -3,6 +3,7 @@ package com.iformall.service;
import com.github.pagehelper.PageInfo; import com.github.pagehelper.PageInfo;
import com.iformall.domain.dto.WxCUserBasicInfoDto; import com.iformall.domain.dto.WxCUserBasicInfoDto;
import com.iformall.domain.dto.WxCUserBasicInfoFilterDto; import com.iformall.domain.dto.WxCUserBasicInfoFilterDto;
import com.iformall.domain.dto.WxCUserBasicInfoFilterListDto;
import com.iformall.domain.po.MallUserInfo; import com.iformall.domain.po.MallUserInfo;
import com.iformall.domain.po.WxCUserBasicInfo; import com.iformall.domain.po.WxCUserBasicInfo;
import com.iformall.domain.po.WxCarPayRecord; import com.iformall.domain.po.WxCarPayRecord;
@@ -24,6 +25,7 @@ public interface WxCUserBasicInfoService {
List<WxTagsGroupVo> listFilters(String tenantId); List<WxTagsGroupVo> listFilters(String tenantId);
long countByFilter(String tenantId, List<WxCUserBasicInfoFilterDto> filterList); long countByFilter(String tenantId, List<WxCUserBasicInfoFilterDto> filterList);
List<WxCUserBasicInfo> listByFilter(String tenantId, List<WxCUserBasicInfoFilterDto> filterList); List<WxCUserBasicInfo> listByFilter(String tenantId, List<WxCUserBasicInfoFilterDto> filterList);
List<WxCUserBasicInfo> listByFilterList(String tenantId, List<WxCUserBasicInfoFilterListDto> filterList);
/** /**
* 根据实体查询分页列表 * 根据实体查询分页列表
* *


+ 0
- 3
mallinkService/src/main/java/com/iformall/service/WxCUserTagsService.java Zobrazit soubor

@@ -41,9 +41,6 @@ public interface WxCUserTagsService {
* @param id * @param id
*/ */
void deleteById(Long id); void deleteById(Long id);

List<WxCUserBasicInfo> findByTag(String tenantId, List<Long> tagIds);


long countUser(String tenantId, Long tagId, Date startTime, Date endTime ); long countUser(String tenantId, Long tagId, Date startTime, Date endTime );




+ 12
- 0
mallinkService/src/main/java/com/iformall/service/impl/WxCUserBasicInfoServiceImpl.java Zobrazit soubor

@@ -8,6 +8,7 @@ import com.iformall.common.IdWorker;
import com.iformall.domain.dto.WxCUserBasicInfoDto; import com.iformall.domain.dto.WxCUserBasicInfoDto;


import com.iformall.domain.dto.WxCUserBasicInfoFilterDto; import com.iformall.domain.dto.WxCUserBasicInfoFilterDto;
import com.iformall.domain.dto.WxCUserBasicInfoFilterListDto;
import com.iformall.domain.po.*; import com.iformall.domain.po.*;
import com.iformall.domain.vo.*; import com.iformall.domain.vo.*;
import com.iformall.enums.*; import com.iformall.enums.*;
@@ -317,6 +318,17 @@ public class WxCUserBasicInfoServiceImpl implements WxCUserBasicInfoService {
} }




@Override
public List<WxCUserBasicInfo> listByFilterList(String tenantId, List<WxCUserBasicInfoFilterListDto> filterList) {
HashSet<WxCUserBasicInfo> userSet = new HashSet<>();

filterList.stream().forEach(f->{
userSet.addAll(listByFilter(tenantId,f.getTagList()));
});

return new ArrayList<>(userSet);
}

@Override @Override
public PageInfo<WxCUserBasicInfo> listAsPage(WxCUserBasicInfo record, Integer pageIndex, Integer pageSize) { public PageInfo<WxCUserBasicInfo> listAsPage(WxCUserBasicInfo record, Integer pageIndex, Integer pageSize) {
return PageHelper.startPage(pageIndex, pageSize).doSelectPageInfo(() -> wxCUserBasicInfoMapper.findList(record)); return PageHelper.startPage(pageIndex, pageSize).doSelectPageInfo(() -> wxCUserBasicInfoMapper.findList(record));


+ 0
- 20
mallinkService/src/main/java/com/iformall/service/impl/WxCUserTagsServiceImpl.java Zobrazit soubor

@@ -85,26 +85,6 @@ public class WxCUserTagsServiceImpl implements WxCUserTagsService {
return wxCUserTagsMapper.countUser(str, tenantId, startTime, endTime); return wxCUserTagsMapper.countUser(str, tenantId, startTime, endTime);
} }


@Override
public List<WxCUserBasicInfo> findByTag(String tenantId, List<Long> tagIds) {
if (tagIds == null || tagIds.isEmpty())
return new ArrayList<WxCUserBasicInfo>();
Set<Long> hs = new HashSet<>();

for (Long tagId:tagIds) {
String str = JSON.toJSONString(tagId);
hs.addAll(wxCUserTagsMapper.findByTags(str, tenantId));
}
if (!hs.isEmpty()) {
List<Long> userIds = new ArrayList<>();
userIds.addAll(hs);
WxCUserBasicInfo wxCUserBasicInfo = new WxCUserBasicInfo();
wxCUserBasicInfo.setIds(userIds);
return wxCUserBasicInfoMapper.findList(wxCUserBasicInfo);
}
return new ArrayList<>();
}



@Override @Override
public List<WxTags> findTagList(String tenantId, List<Long> tagIds) { public List<WxTags> findTagList(String tenantId, List<Long> tagIds) {


+ 2
- 8
mallinkService/src/main/java/com/iformall/service/impl/WxCouponInjectServiceImpl.java Zobrazit soubor

@@ -108,13 +108,8 @@ public class WxCouponInjectServiceImpl implements WxCouponInjectService {
return new ResultData(ErrorCode.COUPON_TYPE_IS_NOT_PASSIVE); return new ResultData(ErrorCode.COUPON_TYPE_IS_NOT_PASSIVE);
} }


HashSet<WxCUserBasicInfo> userSet = new HashSet<>();

record.getFilterList().stream().forEach(f->{
userSet.addAll(wxCUserBasicInfoService.listByFilter(record.getTenantId(),f.getTagList()));
});

List<WxCUserBasicInfo>userList = new ArrayList<>(userSet);
List<WxCUserBasicInfo> userList =
wxCUserBasicInfoService.listByFilterList(record.getTenantId(),record.getFilterList());


if(userList.isEmpty()){ if(userList.isEmpty()){
return new ResultData(ErrorCode.TAGS_MATCHED_NULL); return new ResultData(ErrorCode.TAGS_MATCHED_NULL);
@@ -195,7 +190,6 @@ public class WxCouponInjectServiceImpl implements WxCouponInjectService {
} }
} }
wxmsg.setPhones(sb.deleteCharAt(sb.length()-1).toString()); wxmsg.setPhones(sb.deleteCharAt(sb.length()-1).toString());
wxmsg.setLabel("");
if(wxmsg.getPhones().equals("")){ if(wxmsg.getPhones().equals("")){
return new ResultData(ErrorCode.MSG_NO_VALID_PHONE); return new ResultData(ErrorCode.MSG_NO_VALID_PHONE);
} }


+ 0
- 7
mallinkService/src/main/resources/mapper/WxCUserTagsMapper.xml Zobrazit soubor

@@ -62,13 +62,6 @@
<include refid="dynamicWhereConditions"/> <include refid="dynamicWhereConditions"/>
</select> </select>



<select id="findByTags" resultType="java.lang.Long">
select user_id from wx_c_user_tags cut
where JSON_CONTAINS(tags,#{tagIds} )
and cut.tenant_id = #{tenantId};
</select>

<update id="updateNewId" parameterType="com.iformall.domain.vo.CUserTagVo"> <update id="updateNewId" parameterType="com.iformall.domain.vo.CUserTagVo">
update wx_c_user_tags update wx_c_user_tags
set user_id=#{newUserId} set user_id=#{newUserId}


+ 3
- 6
mallinkService/src/main/resources/mapper/WxMsgMapper.xml Zobrazit soubor

@@ -19,13 +19,14 @@
<result column="sendstatus" jdbcType="INTEGER" property="sendstatus" /> <result column="sendstatus" jdbcType="INTEGER" property="sendstatus" />
<result column="excelpath" jdbcType="VARCHAR" property="excelpath" /> <result column="excelpath" jdbcType="VARCHAR" property="excelpath" />
<result column="label" jdbcType="VARCHAR" property="label" /> <result column="label" jdbcType="VARCHAR" property="label" />
<result column="tags" jdbcType="VARCHAR" property="tags" />
<result column="status" jdbcType="INTEGER" property="status" /> <result column="status" jdbcType="INTEGER" property="status" />
<result column="way" jdbcType="INTEGER" property="way" /> <result column="way" jdbcType="INTEGER" property="way" />
<result column="coupon_inject_id" jdbcType="BIGINT" property="couponInjectId" /> <result column="coupon_inject_id" jdbcType="BIGINT" property="couponInjectId" />
</resultMap> </resultMap>
<sql id="allColumns"> <sql id="allColumns">
`id`,`tenant_id`,`model_id`,`msg`,`sendtime`,`createtime`,`expect_send_number`,`success_number`,`error_number`,`return_result`,`phones`,`signature`,`isright`,`name`,`sendstatus`,`excelpath`,`label`,`status`,`way`,`coupon_inject_id`
`id`,`tenant_id`,`model_id`,`msg`,`sendtime`,`createtime`,`expect_send_number`,`success_number`,`error_number`,`return_result`,`phones`,`signature`,`isright`,`name`,`sendstatus`,`excelpath`,`label`,`tags`,`status`,`way`,`coupon_inject_id`
</sql> </sql>


<sql id="dynamicWhereConditions"> <sql id="dynamicWhereConditions">
@@ -130,9 +131,5 @@
<include refid="dynamicWhereConditions" /> <include refid="dynamicWhereConditions" />
</select> </select>

</mapper> </mapper>

Načítá se…
Zrušit
Uložit