Преглед изворни кода

add mall version

release_toaliyun_real
winter пре 3 година
родитељ
комит
30875fd637
13 измењених фајлова са 393 додато и 14 уклоњено
  1. +48
    -9
      mallinkAdmin/src/main/java/com/iformall/controller/basic/TtMerchantPoiController.java
  2. +71
    -0
      mallinkAdmin/src/main/java/com/iformall/controller/mem/AsyncTask.java
  3. +7
    -0
      mallinkAdmin/src/main/resources/db/migration/V2023053000001_douyin.sql
  4. +32
    -0
      mallinkService/src/main/java/com/iformall/domain/po/WxMallVersion.java
  5. +7
    -5
      mallinkService/src/main/java/com/iformall/domain/po/WxMerchant.java
  6. +28
    -0
      mallinkService/src/main/java/com/iformall/domain/vo/MerchantPoiTNew.java
  7. +37
    -0
      mallinkService/src/main/java/com/iformall/enums/EnumDouyinApplicationVersion.java
  8. +16
    -0
      mallinkService/src/main/java/com/iformall/mapper/WxMallVersionMapper.java
  9. +7
    -0
      mallinkService/src/main/java/com/iformall/service/TtMerchantPoiService.java
  10. +3
    -0
      mallinkService/src/main/java/com/iformall/service/WxMallService.java
  11. +63
    -0
      mallinkService/src/main/java/com/iformall/service/impl/TtMerchantPoiServiceImpl.java
  12. +9
    -0
      mallinkService/src/main/java/com/iformall/service/impl/WxMallServiceImpl.java
  13. +65
    -0
      mallinkService/src/main/resources/mapper/WxMallVersionMapper.xml

+ 48
- 9
mallinkAdmin/src/main/java/com/iformall/controller/basic/TtMerchantPoiController.java Прегледај датотеку

@@ -36,6 +36,9 @@ import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
* @author gongbiao
*/
@@ -51,10 +54,7 @@ public class TtMerchantPoiController extends BaseController {
private TtMerchantPoiService ttMerchantPoiService;

@Autowired
private WxCouponChannelService wxCouponChannelService;

@Autowired
private WxCouponService wxCouponService;
private WxMallService wxMallService;

@Autowired
StringRedisTemplate stringRedisTemplate;
@@ -234,18 +234,54 @@ public class TtMerchantPoiController extends BaseController {
// return ttMerchantPoiService.spuStockSync(getTenantInfo(),couponChannelId);
// }

private Integer getCurrentApplicationVersion() {
WxMallVersion mallVersion = wxMallService.getMallVersion(getTenantInfo());
if (null == mallVersion) {
throw new MallinkException(ErrorCode.SYS_SERVER_ERROR.getCode(),"mallVersion未查询到配置");
}
Integer v = mallVersion.getDouyinApplicationVersion() ;
if (v == null) {
return 0;
}
return v;
}
@TenantIgnore
@RequestMapping("/exportTemplate")
public void exportTemplate(HttpServletRequest request, HttpServletResponse response) {
Integer _e = getCurrentApplicationVersion();
if (_e.intValue() == EnumDouyinApplicationVersion.WEB.getCode().intValue()) {
ttMerchantPoiService.exportTemplate(request, response,false);
}else if (_e.intValue() == EnumDouyinApplicationVersion.MINIAPP.getCode().intValue()) {
ttMerchantPoiService.exportTemplate(request, response,true);
}else {
throw new MallinkException(ErrorCode.SYS_SERVER_ERROR.getCode(),"mallVersion[douyinApplicationVersion]配置错误");
}
}
@TenantIgnore
@PostMapping(value = "/importPoi", consumes = "multipart/*")
@SystemControllerLog(description = "poi-导入数据")
public ResultData importPoi(@RequestParam("file") MultipartFile mFile) {
logger.debug("[" + getIpAddr() + "] TtMerchantPoiController::importPoi");
if (mFile.isEmpty()) {
Integer _e = getCurrentApplicationVersion();
if (_e.intValue() == EnumDouyinApplicationVersion.WEB.getCode().intValue()) {
return processImport(mFile,false);
}else if (_e.intValue() == EnumDouyinApplicationVersion.MINIAPP.getCode().intValue()) {
return processImport(mFile,true);
}else {
throw new MallinkException(ErrorCode.SYS_SERVER_ERROR.getCode(),"mallVersion[douyinApplicationVersion]配置错误");
}
}
private ResultData processImport(MultipartFile mFile,boolean isNew) {
logger.debug("[" + getIpAddr() + "] TtMerchantPoiController::importPoi");
if (mFile.isEmpty()) {
throw new MallinkException(Result.ERROR, "上传文件不能为空");
}
//得到当前用户ID
final MallUserInfo user = getUser();
String userId = "" + user.getId();
String importKey = Constant.importMemPrev + userId;
String importKey = Constant.importPoiPrev + userId;

//查询当前用户得到的值是否为空,为空继续,不为空,返回模板正在导入
Boolean allCount = stringRedisTemplate.opsForHash().hasKey(importKey, "allCount");
@@ -312,8 +348,11 @@ public class TtMerchantPoiController extends BaseController {
}
}
}

asyncTask.importExcelPoiData(lFile, user, importKey);
if (isNew) {
asyncTask.importExcelPoiDataForNew(lFile, user, importKey);
}else {
asyncTask.importExcelPoiData(lFile, user, importKey);
}

return new ResultData(Result.SUCCESS, "模板正在导入");
}


+ 71
- 0
mallinkAdmin/src/main/java/com/iformall/controller/mem/AsyncTask.java Прегледај датотеку

@@ -9,6 +9,7 @@ import com.iformall.domain.po.MallUserInfo;
import com.iformall.domain.po.WxTags;
import com.iformall.domain.vo.CUserBaseInfoT;
import com.iformall.domain.vo.MerchantPoiT;
import com.iformall.domain.vo.MerchantPoiTNew;
import com.iformall.domain.vo.WxCardPriceTemplate;
import com.iformall.service.TtMerchantPoiService;
import com.iformall.service.WxCUserBasicInfoService;
@@ -67,6 +68,17 @@ public class AsyncTask {

}
private class PoiNewExcelHandler extends ExcelDataHandlerDefaultImpl<MerchantPoiTNew> {
@Override
public Object importHandler(MerchantPoiTNew obj, String name, Object value) {
if (value == null) {
value = "";
}
return super.importHandler(obj, name, value);
}

}
private class CardPriceExcelHandler extends ExcelDataHandlerDefaultImpl<WxCardPriceTemplate> {
@Override
public Object importHandler(WxCardPriceTemplate obj, String name, Object value) {
@@ -210,6 +222,65 @@ public class AsyncTask {
}
}
@Async
public void importExcelPoiDataForNew(File file, MallUserInfo user, String importKey) {
ImportParams params = new ImportParams();
// 需要验证
params.setImportFields(new String[]{"富茂商户ID", "富茂商户名称", "来客门店名称", "来客门店ID"});
IExcelDataHandler<MerchantPoiTNew> handler = new AsyncTask.PoiNewExcelHandler();
handler.setNeedHandlerFields(new String[]{"富茂商户ID","来客门店ID"});
params.setNeedVerify(true);

ExcelImportResult<MerchantPoiTNew> datalist = null;

try {
datalist = ExcelImportUtil.importExcelMore(file, MerchantPoiTNew.class, params);
} catch (Exception e) {
set_redis_value(importKey, "1", "0", "0", "1", true);
logger.error(e.getMessage());
// 删除缓存文件
file.delete();
return;
}
// 删除缓存文件
file.delete();

if(datalist == null) {
logger.error("导入模板失败: 模板数据解析失败");
set_redis_value(importKey, "1", "0", "0", "1", true);
return;
}

List<MerchantPoiTNew> successList = datalist.getList();
List<MerchantPoiTNew> failList = datalist.getFailList();

logger.info("验证通过的数量: " + successList.size());
logger.info("验证未通过的数量: " + failList.size());

int total = successList.size() + failList.size();
int all_success = successList.size();
int all_fail = failList.size();

//添加到redis里
set_redis_value(importKey, "" + total, "" + all_success, "0", "" + all_fail, total == all_fail);

if(successList.size() > 0) {
try {
successList.parallelStream().forEach(poiBase -> {
try {
ttMerchantPoiService.importOnePoiNew(user,importKey, poiBase);
} catch (UnknownSessionException ue) {
logger.error("session :"+ue.getMessage());
}
});
} catch (Exception e) {
set_redis_value(importKey, "1", "0", "0", "1", true);
e.printStackTrace();
logger.error("导入模板失败:"+e.getMessage());
}
}
}
@Async
public void importCardPriceData(File file, MallUserInfo user, String importKey) {
ImportParams params = new ImportParams();


+ 7
- 0
mallinkAdmin/src/main/resources/db/migration/V2023053000001_douyin.sql Прегледај датотеку

@@ -0,0 +1,7 @@
CREATE TABLE `wx_mall_version` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`tenant_id` varchar(5) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '租户ID',
`parent_tenant_id` varchar(5) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '父租户ID',
`douyin_application_version` int(3) NOT NULL COMMENT '抖音应用版本',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC COMMENT='商场';

+ 32
- 0
mallinkService/src/main/java/com/iformall/domain/po/WxMallVersion.java Прегледај датотеку

@@ -0,0 +1,32 @@
package com.iformall.domain.po;

import com.baomidou.mybatisplus.annotation.IdType;
import com.alibaba.fastjson.annotation.JSONField;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.iformall.domain.po.base.BaseEntity;
import com.iformall.domain.po.base.TenantEntity;
import com.iformall.utils.DateUtils;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.apache.commons.lang3.StringUtils;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

@JsonIgnoreProperties(value = {"handler"})
@TableName(value = "wx_mall_version")
@Data
@EqualsAndHashCode(callSuper = true)
public class WxMallVersion extends TenantEntity {

@TableId(type= IdType.AUTO)
protected Long id;

@io.swagger.annotations.ApiModelProperty(value="抖音应用版本EnumDouyinApplicationVersion",name="douyinApplictionVersion")
private Integer douyinApplicationVersion;
}

+ 7
- 5
mallinkService/src/main/java/com/iformall/domain/po/WxMerchant.java Прегледај датотеку

@@ -26,6 +26,8 @@ import java.util.stream.Collectors;
@EqualsAndHashCode(callSuper = true)
public class WxMerchant extends TenantEntity {

@io.swagger.annotations.ApiModelProperty(value="商户ID",name="id")
@Excel(name="商户ID",width = 20,orderNum = "1")
protected Long id;
@TableField(exist = false)
@@ -55,20 +57,20 @@ public class WxMerchant extends TenantEntity {
@TableField(exist = false)
private Long cUserId;

@io.swagger.annotations.ApiModelProperty(value="商户编码",name="encode")
@Excel(name="商户编码",width = 20,orderNum = "1")
@io.swagger.annotations.ApiModelProperty(value="商户自定义编码",name="encode")
@Excel(name="商户自定义编码",width = 20,orderNum = "2")
private String encode;

@io.swagger.annotations.ApiModelProperty(value="商户名",name="name")
@Excel(name="商户名",width = 20,orderNum = "2")
@Excel(name="商户名",width = 20,orderNum = "3")
private String name;

@io.swagger.annotations.ApiModelProperty(value="联系人",name="linkPerson")
@Excel(name="联系人",width = 20,orderNum = "3")
@Excel(name="联系人",width = 20,orderNum = "4")
private String linkPerson;

@io.swagger.annotations.ApiModelProperty(value="联系方式",name="linkPhone")
@Excel(name="联系方式",width = 20,orderNum = "4")
@Excel(name="联系方式",width = 20,orderNum = "5")
private String linkPhone;

@TableField(exist = false)


+ 28
- 0
mallinkService/src/main/java/com/iformall/domain/vo/MerchantPoiTNew.java Прегледај датотеку

@@ -0,0 +1,28 @@
package com.iformall.domain.vo;

import cn.afterturn.easypoi.excel.annotation.Excel;
import com.baomidou.mybatisplus.annotation.TableField;
import lombok.Data;

import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import java.io.Serializable;
import java.math.BigDecimal;

@Data
public class MerchantPoiTNew implements Serializable {

@NotNull
@Excel(name="富茂商户ID",width = 20,orderNum = "1")
@io.swagger.annotations.ApiModelProperty(value="商户ID",name="merchantId")
private String merchantId;
@Excel(name="商户名称",width = 20,orderNum = "2")
@io.swagger.annotations.ApiModelProperty(value="商户名称",name="merchantName")
private String merchantName;
@Excel(name = "来客门店名称", width = 20, orderNum = "3")
@io.swagger.annotations.ApiModelProperty(value="来客门店名称",name="poiName")
private String poiName;
@Excel(name="来客门店ID",width = 20,orderNum = "4")
@io.swagger.annotations.ApiModelProperty(value="来客门店ID",name="poiId")
private String poiId;
}

+ 37
- 0
mallinkService/src/main/java/com/iformall/enums/EnumDouyinApplicationVersion.java Прегледај датотеку

@@ -0,0 +1,37 @@
package com.iformall.enums;


/**
* @author gongbiao
*/
public enum EnumDouyinApplicationVersion {

WEB(1, "网站应用"),
MINIAPP(2, "小程序应用");

public static EnumDouyinApplicationVersion getEnum(Integer code) {
for (EnumDouyinApplicationVersion value : values()) {
if (value.getCode().equals(code)) {
return value;
}
}
return null;
}

private Integer code;
private String message;

EnumDouyinApplicationVersion(Integer code, String message) {
this.code = code;
this.message = message;
}

public Integer getCode() {
return code;
}

public String getMessage() {
return message;
}
}

+ 16
- 0
mallinkService/src/main/java/com/iformall/mapper/WxMallVersionMapper.java Прегледај датотеку

@@ -0,0 +1,16 @@
package com.iformall.mapper;

import com.iformall.common.CommonMapper;
import com.iformall.domain.po.WxMallVersion;
import com.iformall.domain.po.base.TenantEntity;

import java.util.List;

public interface WxMallVersionMapper extends CommonMapper<WxMallVersion, Long> {

List<WxMallVersion> findList(WxMallVersion wxMall);

WxMallVersion getByTenantId(String tenantId);

WxMallVersion getByTenantInfo(TenantEntity tenantEntity);
}

+ 7
- 0
mallinkService/src/main/java/com/iformall/service/TtMerchantPoiService.java Прегледај датотеку

@@ -6,10 +6,14 @@ import com.iformall.domain.po.MallUserInfo;
import com.iformall.domain.po.TtMerchantPoi;
import com.iformall.domain.po.base.TenantEntity;
import com.iformall.domain.vo.MerchantPoiT;
import com.iformall.domain.vo.MerchantPoiTNew;
import com.iformall.douyin.web.api.TtWebService;

import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
* @author gongbiao
*/
@@ -57,4 +61,7 @@ public interface TtMerchantPoiService {

void importOneMem(MallUserInfo user, String importKey, MerchantPoiT poiBase);

void importOnePoiNew(MallUserInfo user, String importKey, MerchantPoiTNew poiBase);
void exportTemplate(HttpServletRequest request, HttpServletResponse response,boolean isNew);
}

+ 3
- 0
mallinkService/src/main/java/com/iformall/service/WxMallService.java Прегледај датотеку

@@ -5,6 +5,7 @@ import com.iformall.common.ResultData;
import com.iformall.domain.po.WxProjectConfig;
import com.iformall.domain.po.base.TenantEntity;
import com.iformall.domain.po.WxMall;
import com.iformall.domain.po.WxMallVersion;

import java.util.List;
import java.util.Map;
@@ -96,4 +97,6 @@ public interface WxMallService {
boolean isgroupSupport(TenantEntity tenantEntity);

Map<String, WxMall> getMallMap(WxMall mallQ);
WxMallVersion getMallVersion(TenantEntity tenantEntity);
}

+ 63
- 0
mallinkService/src/main/java/com/iformall/service/impl/TtMerchantPoiServiceImpl.java Прегледај датотеку

@@ -11,6 +11,8 @@ import com.iformall.common.ResultData;
import com.iformall.domain.po.*;
import com.iformall.domain.po.base.TenantEntity;
import com.iformall.domain.vo.MerchantPoiT;
import com.iformall.domain.vo.MerchantPoiTNew;
import com.iformall.domain.vo.WxCardPriceTemplate;
import com.iformall.douyin.web.api.TtWebService;
import com.iformall.douyin.web.bean.*;
import com.iformall.enums.*;
@@ -30,6 +32,9 @@ import org.springframework.stereotype.Service;
import java.util.*;
import java.util.concurrent.TimeUnit;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
* @author gongbiao
*/
@@ -70,6 +75,9 @@ public class TtMerchantPoiServiceImpl implements TtMerchantPoiService {

@Autowired
StringRedisTemplate stringRedisTemplate;
@Autowired
ExcelService excelService;

@Override
public PageInfo<TtMerchantPoi> listAsPage(TtMerchantPoi record, Integer pageIndex, Integer pageSize) {
@@ -508,6 +516,17 @@ public class TtMerchantPoiServiceImpl implements TtMerchantPoiService {
return ttWebService;
}

@Override
public void exportTemplate(HttpServletRequest request, HttpServletResponse response, boolean isNew) {
if (isNew) {
List<MerchantPoiTNew> list = new ArrayList<MerchantPoiTNew>();
excelService.exportExcel(list, null, "POI匹配模板", MerchantPoiTNew.class, "POI匹配模板.xlsx", response, true);
}else {
List<MerchantPoiT> list = new ArrayList<MerchantPoiT>();
excelService.exportExcel(list, null, "POI匹配模板", MerchantPoiT.class, "POI匹配模板.xlsx", response, true);
}
}
@Override
public void importOneMem(MallUserInfo user, String importKey, MerchantPoiT poiBase) {
if (StringUtils.isBlank(poiBase.getMerchantId())) {
@@ -561,6 +580,50 @@ public class TtMerchantPoiServiceImpl implements TtMerchantPoiService {
stringRedisTemplate.expire(importKey,10, TimeUnit.SECONDS);

}
@Override
public void importOnePoiNew(MallUserInfo user, String importKey, MerchantPoiTNew poiBase) {
if (StringUtils.isBlank(poiBase.getMerchantId())) {
stringRedisTemplate.opsForHash().increment(importKey, "processCount", 1);
return;
}
if (StringUtils.isBlank(poiBase.getPoiId())) {
stringRedisTemplate.opsForHash().increment(importKey, "processCount", 1);
return;
}

try {
Date now = new Date();
TtMerchantPoi merchantPoi = ttMerchantPoiMapper.selectById(Long.parseLong(poiBase.getMerchantId()));
if(merchantPoi == null){
merchantPoi = new TtMerchantPoi();
}
merchantPoi.updateTenantInfo(user);
merchantPoi.setSupplierExtId(poiBase.getMerchantId());
merchantPoi.setMerchantName(poiBase.getMerchantName());
merchantPoi.setPoiId(poiBase.getPoiId());
merchantPoi.setPoiName(poiBase.getPoiName());
merchantPoi.setMatchStatus(EnumSupplierMathStatus.match_success.getCode());
merchantPoi.setSyncStatus(EnumSupplierSyncStatus.sync_success.getCode());
merchantPoi.setLastSyncStatus(EnumSupplierSyncStatus.sync_success.getCode());
merchantPoi.setUpdateDate(now);
if(merchantPoi.getId() == null){
merchantPoi.setId(Long.parseLong(poiBase.getMerchantId()));
merchantPoi.setCreateDate(now);
ttMerchantPoiMapper.insert(merchantPoi);
}else{
ttMerchantPoiMapper.updateById(merchantPoi);
}
} catch (Exception e) {
stringRedisTemplate.opsForHash().increment(importKey, "processCount", 1);
logger.error(e.getMessage());
return;
}

stringRedisTemplate.opsForHash().increment(importKey,"processCount",1);
stringRedisTemplate.expire(importKey,10, TimeUnit.SECONDS);
}

// @Override
// public ResultData findPoi(TenantEntity tenantInfo, Long couponChannelId) {


+ 9
- 0
mallinkService/src/main/java/com/iformall/service/impl/WxMallServiceImpl.java Прегледај датотеку

@@ -15,6 +15,7 @@ import com.iformall.enums.EnumUserAdmin;
import com.iformall.mapper.WxMallBuildingMapper;
import com.iformall.mapper.WxMallFloorMapper;
import com.iformall.mapper.WxMallMapper;
import com.iformall.mapper.WxMallVersionMapper;
import com.iformall.service.MallUserInfoService;
import com.iformall.service.WxMallService;
import com.iformall.utils.Constant;
@@ -60,6 +61,9 @@ public class WxMallServiceImpl implements WxMallService {
@Autowired
@Qualifier("objectCommonRedisTemplate")
RedisTemplate<String, Object> redisTemplate;
@Autowired
WxMallVersionMapper wxMallVersionMapper;



@@ -408,4 +412,9 @@ public class WxMallServiceImpl implements WxMallService {
return mallMap;
}

@Override
public WxMallVersion getMallVersion(TenantEntity tenantEntity) {
return wxMallVersionMapper.getByTenantInfo(tenantEntity);
}

}

+ 65
- 0
mallinkService/src/main/resources/mapper/WxMallVersionMapper.xml Прегледај датотеку

@@ -0,0 +1,65 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.iformall.mapper.WxMallVersionMapper">
<resultMap id="BaseResultMap" type="com.iformall.domain.po.WxMallVersion">
<id column="id" jdbcType="BIGINT" property="id"/>
<result column="tenant_id" jdbcType="VARCHAR" property="tenantId"/>
<result column="parent_tenant_id" jdbcType="VARCHAR" property="parentTenantId"/>
<result column="douyin_application_version" jdbcType="INTEGER" property="douyinApplicationVersion"/>
</resultMap>

<sql id="allColumns">
`id`,`tenant_id`,`parent_tenant_id`,`douyin_application_version`
</sql>

<sql id="dynamicWhereConditions">
where 1 = 1

<if test=" null != id ">
and `id` = #{id}
</if>

<if test=" null != tenantId and '' != tenantId">
and
</if>
<if test=" null != parentTenantId and '' != parentTenantId">
and `parent_tenant_id` = #{parentTenantId}
</if>

<if test=" null != ids ">
and id in
<foreach collection="ids" index="index" item="idItem" open="(" separator="," close=")">
#{idItem}
</foreach>
</if>
<if test=" null != sortColumns">order by ${sortColumns}</if>
</sql>

<select id="findList" parameterType="com.iformall.domain.po.WxMallVersion" resultMap="BaseResultMap">
select
<include refid="allColumns"/>
from wx_mall_version
<include refid="dynamicWhereConditions"/>
</select>

<select id="getByTenantId" parameterType="string" resultMap="BaseResultMap">
select
<include refid="allColumns"/>
from wx_mall_version
where `tenant_id` = #{value}
</select>
<select id="getByTenantInfo" parameterType="com.iformall.domain.po.base.TenantEntity" resultMap="BaseResultMap">
select
<include refid="allColumns"/>
from wx_mall_version
where 1=1
<if test=" null != tenantId and '' != tenantId">
and `tenant_id` = #{tenantId}
</if>
<if test=" null != parentTenantId and '' != parentTenantId">
and `parent_tenant_id` = #{parentTenantId}
</if>
</select>

</mapper>

Loading…
Откажи
Сачувај