数据统计

This commit is contained in:
Tankaikai
2025-03-19 09:58:05 +08:00
parent 36ddbba45e
commit ddf8a89cb0
9 changed files with 284 additions and 17 deletions

View File

@@ -86,6 +86,7 @@ public class DataSummaryController {
* @param day 天数 * @param day 天数
*/ */
@GetMapping("datePayType") @GetMapping("datePayType")
@OperationLog("支付占比饼图 左下")
@SaStaffCheckPermission("yun_xu_cha_kan_jing_ying_shu_ju") @SaStaffCheckPermission("yun_xu_cha_kan_jing_ying_shu_ju")
//@SaAdminCheckPermission("dataSummary:datePayType") //@SaAdminCheckPermission("dataSummary:datePayType")
public CzgResult<DataSummaryPayTypeVo> shopSummaryPayType(@RequestParam Integer day) { public CzgResult<DataSummaryPayTypeVo> shopSummaryPayType(@RequestParam Integer day) {

View File

@@ -36,5 +36,15 @@ public class DataSummaryProductSaleParam implements Serializable {
*/ */
@JSONField(serialize = false) @JSONField(serialize = false)
private Long shopId; private Long shopId;
/**
* 开始日期
*/
@JSONField(serialize = false)
private String beginDate;
/**
* 结束日期
*/
@JSONField(serialize = false)
private String endDate;
} }

View File

@@ -3,6 +3,11 @@ package com.czg.service.order.mapper;
import com.czg.order.entity.ShopOrderStatistic; import com.czg.order.entity.ShopOrderStatistic;
import com.czg.order.param.DataSummaryTradeParam; import com.czg.order.param.DataSummaryTradeParam;
import com.mybatisflex.core.BaseMapper; import com.mybatisflex.core.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
/** /**
* 映射层。 * 映射层。
@@ -10,9 +15,17 @@ import com.mybatisflex.core.BaseMapper;
* @author zs * @author zs
* @since 2025-03-07 * @since 2025-03-07
*/ */
@Mapper
public interface ShopOrderStatisticMapper extends BaseMapper<ShopOrderStatistic> { public interface ShopOrderStatisticMapper extends BaseMapper<ShopOrderStatistic> {
ShopOrderStatistic getTradeData(DataSummaryTradeParam param); ShopOrderStatistic getTradeData(DataSummaryTradeParam param);
long getNewMemberCount(DataSummaryTradeParam param); long getNewMemberCount(DataSummaryTradeParam param);
List<Map<String, Object>> getPayTypeAmountCount(DataSummaryTradeParam param);
List<Map<String, Object>> getVipRechargeAmountCount(DataSummaryTradeParam param);
BigDecimal getCustomerUnitPrice(DataSummaryTradeParam param);
BigDecimal getTableTurnoverRate(DataSummaryTradeParam param);
} }

View File

@@ -20,8 +20,14 @@ public interface ShopProdStatisticMapper extends BaseMapper<ShopProdStatistic> {
List<DataSummaryProductSaleRankingVo> findProdRandingSummaryPage(DataSummaryProductSaleParam param); List<DataSummaryProductSaleRankingVo> findProdRandingSummaryPage(DataSummaryProductSaleParam param);
List<DataSummaryProductSaleRankingVo> findProdRandingSummaryPage2(DataSummaryProductSaleParam param);
SaleSummaryCountVo getSaleSummaryCount(SaleSummaryCountParam param); SaleSummaryCountVo getSaleSummaryCount(SaleSummaryCountParam param);
SaleSummaryCountVo getSaleSummaryCount2(SaleSummaryCountParam param);
List<SaleSummaryInfoVo> findSaleSummaryList(SaleSummaryCountParam param); List<SaleSummaryInfoVo> findSaleSummaryList(SaleSummaryCountParam param);
List<SaleSummaryInfoVo> findSaleSummaryList2(SaleSummaryCountParam param);
} }

View File

@@ -1,7 +1,10 @@
package com.czg.service.order.service.impl; package com.czg.service.order.service.impl;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DatePattern; import cn.hutool.core.date.DatePattern;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ReflectUtil;
import com.czg.order.entity.OrderInfo; import com.czg.order.entity.OrderInfo;
import com.czg.order.entity.ShopOrderStatistic; import com.czg.order.entity.ShopOrderStatistic;
import com.czg.order.enums.PayEnums; import com.czg.order.enums.PayEnums;
@@ -22,9 +25,13 @@ import com.mybatisflex.core.query.QueryWrapper;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.time.LocalDate; import java.time.LocalDate;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/** /**
* 数据统计Service实现类 * 数据统计Service实现类
@@ -44,15 +51,66 @@ public class DataSummaryServiceImpl implements DataSummaryService {
@Override @Override
public ShopOrderStatistic getTradeData(DataSummaryTradeParam param) { public ShopOrderStatistic getTradeData(DataSummaryTradeParam param) {
ShopOrderStatistic shopOrderStatistic = shopOrderStatisticMapper.getTradeData(param); List<String> funs = Arrays.asList("getPayTypeAmountCount", "getVipRechargeAmountCount", "getNewMemberCount", "getCustomerUnitPrice", "getTableTurnoverRate");
if (shopOrderStatistic == null) { Map<String, Object> collect = funs.parallelStream().collect(Collectors.toMap(fun -> fun, fun ->
shopOrderStatistic = new ShopOrderStatistic(); ReflectUtil.invoke(shopOrderStatisticMapper, fun, param)
));
/*Map<String, Object> collect = new ConcurrentHashMap<>();
for (String fun : funs) {
Object invoke = ReflectUtil.invoke(shopOrderStatisticMapper, fun, param);
collect.put(fun, ObjUtil.defaultIfNull(invoke,BigDecimal.ZERO));
}*/
ShopOrderStatistic data = new ShopOrderStatistic();
//List<Map<String, Object>> list = shopOrderStatisticMapper.getPayTypeAmountCount(param);
List<Map<String, Object>> list = (List<Map<String, Object>>) collect.get("getPayTypeAmountCount");
if (CollUtil.isEmpty(list)) {
return data;
} }
Map<String, BigDecimal> sum = list.stream().collect(Collectors.toMap(item -> Convert.toStr(item.get("payType")), item -> Convert.toBigDecimal(item.get("amount"))));
Map<String, Long> count = list.stream().collect(Collectors.toMap(item -> Convert.toStr(item.get("payType")), item -> Convert.toLong(item.get("count"))));
data.setWechatPayAmount(sum.getOrDefault(PayEnums.WECHAT_MINI.getValue(), BigDecimal.ZERO));
data.setWechatPayCount(count.getOrDefault(PayEnums.WECHAT_MINI.getValue(), 0L));
data.setAliPayAmount(sum.getOrDefault(PayEnums.ALIPAY_MINI.getValue(), BigDecimal.ZERO));
data.setAliPayCount(count.getOrDefault(PayEnums.ALIPAY_MINI.getValue(), 0L));
data.setScanPayAmount(sum.getOrDefault(PayEnums.MAIN_SCAN.getValue(), BigDecimal.ZERO));
data.setScanPayCount(count.getOrDefault(PayEnums.MAIN_SCAN.getValue(), 0L));
data.setCashPayAmount(sum.getOrDefault(PayEnums.CASH_PAY.getValue(), BigDecimal.ZERO));
data.setCashPayCount(count.getOrDefault(PayEnums.CASH_PAY.getValue(), 0L));
data.setCreditPayAmount(sum.getOrDefault(PayEnums.CREDIT_PAY.getValue(), BigDecimal.ZERO));
data.setCreditPayCount(count.getOrDefault(PayEnums.CREDIT_PAY.getValue(), 0L));
//List<Map<String, Object>> list1 = shopOrderStatisticMapper.getVipRechargeAmountCount(param);
List<Map<String, Object>> list1 = (List<Map<String, Object>>) collect.get("getVipRechargeAmountCount");
Map<String, BigDecimal> sum1 = list1.stream().collect(Collectors.toMap(item -> Convert.toStr(item.get("bizCode")), item -> Convert.toBigDecimal(item.get("amount"))));
Map<String, Long> count1 = list1.stream().collect(Collectors.toMap(item -> Convert.toStr(item.get("bizCode")), item -> Convert.toLong(item.get("count"))));
data.setRechargeAmount(NumberUtil.add(sum1.getOrDefault("cashIn", BigDecimal.ZERO), sum1.getOrDefault("wechatIn", BigDecimal.ZERO), sum1.getOrDefault("alipayIn", BigDecimal.ZERO)));
data.setMemberPayAmount(sum1.getOrDefault("orderPay", BigDecimal.ZERO).abs());
data.setMemberPayCount(count1.getOrDefault("orderPay", 0L));
data.setSaleAmount(NumberUtil.add(data.getWechatPayAmount(), data.getAliPayAmount(), data.getScanPayAmount(), data.getCashPayAmount(), data.getCreditPayAmount()));
BigDecimal refundAmount = list.stream().filter(item -> item.get("payType") != null).map(item -> Convert.toBigDecimal(item.get("refund"), BigDecimal.ZERO)).reduce(BigDecimal.ZERO, BigDecimal::add);
data.setRefundAmount(refundAmount);
long refundCount = list.stream().filter(item -> item.get("payType") != null).map(item -> Convert.toLong(item.get("refundCount"), 0L)).reduce(0L, Long::sum);
data.setRefundCount(refundCount);
//long newMemberCount = shopOrderStatisticMapper.getNewMemberCount(param);
long newMemberCount = (long) collect.get("getNewMemberCount");
data.setNewMemberCount(newMemberCount);
//BigDecimal customerUnitPrice = shopOrderStatisticMapper.getCustomerUnitPrice(param);
BigDecimal customerUnitPrice = (BigDecimal) collect.get("getCustomerUnitPrice");
data.setCustomerUnitPrice(NumberUtil.nullToZero(customerUnitPrice).setScale(2, java.math.RoundingMode.HALF_UP));
//BigDecimal tableTurnoverRate = shopOrderStatisticMapper.getTableTurnoverRate(param);
BigDecimal tableTurnoverRate = (BigDecimal) collect.get("getTableTurnoverRate");
data.setTableTurnoverRate(tableTurnoverRate);
BigDecimal discountAmount = list.stream().filter(item -> item.get("payType") != null).map(item -> Convert.toBigDecimal(item.get("discount"), BigDecimal.ZERO)).reduce(BigDecimal.ZERO, BigDecimal::add);
long discountCount = list.stream().filter(item -> item.get("payType") != null).map(item -> Convert.toLong(item.get("discountCount"), 0L)).reduce(0L, Long::sum);
data.setDiscountAmount(discountAmount);
data.setDiscountCount(discountCount);
return data;
/*ShopOrderStatistic shopOrderStatistic = shopOrderStatisticMapper.getTradeData(param);
long newMemberCount = shopOrderStatisticMapper.getNewMemberCount(param);
data.setNewMemberCount(newMemberCount);
shopOrderStatistic.setCustomerUnitPrice(shopOrderStatistic.getCustomerUnitPrice().setScale(2, java.math.RoundingMode.HALF_UP)); shopOrderStatistic.setCustomerUnitPrice(shopOrderStatistic.getCustomerUnitPrice().setScale(2, java.math.RoundingMode.HALF_UP));
shopOrderStatistic.setTableTurnoverRate(shopOrderStatistic.getTableTurnoverRate().setScale(2, java.math.RoundingMode.HALF_UP)); shopOrderStatistic.setTableTurnoverRate(shopOrderStatistic.getTableTurnoverRate().setScale(2, java.math.RoundingMode.HALF_UP));
long newMemberCount = shopOrderStatisticMapper.getNewMemberCount(param); return shopOrderStatistic;*/
shopOrderStatistic.setNewMemberCount(newMemberCount);
return shopOrderStatistic;
} }
@Override @Override
@@ -66,8 +124,10 @@ public class DataSummaryServiceImpl implements DataSummaryService {
days.add(thisDay); days.add(thisDay);
} }
param.setDays(days); param.setDays(days);
param.setBeginDate(days.getFirst() + " 00:00:00");
param.setEndDate(days.getLast() + " 23:59:59");
PageHelper.startPage(PageUtil.buildPageHelp()); PageHelper.startPage(PageUtil.buildPageHelp());
PageInfo<DataSummaryProductSaleRankingVo> pageInfo = new PageInfo<>(shopProdStatisticMapper.findProdRandingSummaryPage(param)); PageInfo<DataSummaryProductSaleRankingVo> pageInfo = new PageInfo<>(shopProdStatisticMapper.findProdRandingSummaryPage2(param));
return PageUtil.convert(pageInfo); return PageUtil.convert(pageInfo);
} }

View File

@@ -27,7 +27,7 @@ public class SaleSummaryServiceImpl implements SaleSummaryService {
@Override @Override
public SaleSummaryCountVo summaryCount(SaleSummaryCountParam param) { public SaleSummaryCountVo summaryCount(SaleSummaryCountParam param) {
SaleSummaryCountVo saleSummaryCount = shopProdStatisticMapper.getSaleSummaryCount(param); SaleSummaryCountVo saleSummaryCount = shopProdStatisticMapper.getSaleSummaryCount2(param);
if (saleSummaryCount == null) { if (saleSummaryCount == null) {
saleSummaryCount = new SaleSummaryCountVo(); saleSummaryCount = new SaleSummaryCountVo();
} }
@@ -37,12 +37,12 @@ public class SaleSummaryServiceImpl implements SaleSummaryService {
@Override @Override
public Page<SaleSummaryInfoVo> summaryPage(SaleSummaryCountParam param) { public Page<SaleSummaryInfoVo> summaryPage(SaleSummaryCountParam param) {
PageHelper.startPage(PageUtil.buildPageHelp()); PageHelper.startPage(PageUtil.buildPageHelp());
PageInfo<SaleSummaryInfoVo> pageInfo = new PageInfo<>(shopProdStatisticMapper.findSaleSummaryList(param)); PageInfo<SaleSummaryInfoVo> pageInfo = new PageInfo<>(shopProdStatisticMapper.findSaleSummaryList2(param));
return PageUtil.convert(pageInfo); return PageUtil.convert(pageInfo);
} }
@Override @Override
public List<SaleSummaryInfoVo> summaryList(SaleSummaryCountParam param) { public List<SaleSummaryInfoVo> summaryList(SaleSummaryCountParam param) {
return shopProdStatisticMapper.findSaleSummaryList(param); return shopProdStatisticMapper.findSaleSummaryList2(param);
} }
} }

View File

@@ -50,4 +50,74 @@
]]> ]]>
</if> </if>
</select> </select>
<select id="getPayTypeAmountCount" resultType="java.util.Map">
SELECT
t1.pay_type as payType,
sum(t1.pay_amount) as amount,
sum(t1.refund_amount) as refund,
count(case when t1.refund_amount>0 then 1 end) as refundCount,
sum(t1.discount_amount) as discount,
count(case when t1.discount_amount>0 then 1 end) as discountCount,
count(*) as count
FROM
tb_order_info t1
WHERE t1.shop_id = #{shopId}
and t1.paid_time is not null
<if test="beginDate != null and beginDate != ''">
and t1.create_time >= str_to_date(concat(#{beginDate},' 00:00:00'), '%Y-%m-%d %H:%i:%s')
</if>
<if test="endDate != null and endDate != ''">
<![CDATA[
and t1.create_time <= str_to_date(concat(#{endDate},' 23:59:59'), '%Y-%m-%d %H:%i:%s')
]]>
</if>
group by t1.pay_type
</select>
<select id="getVipRechargeAmountCount" resultType="java.util.Map">
select
t1.biz_code as bizCode,sum(t1.amount) as amount,count(*) as count
from tb_shop_user_flow t1
where t1.shop_id = #{shopId}
<if test="beginDate != null and beginDate != ''">
and t1.create_time >= str_to_date(concat(#{beginDate},' 00:00:00'), '%Y-%m-%d %H:%i:%s')
</if>
<if test="endDate != null and endDate != ''">
<![CDATA[
and t1.create_time <= str_to_date(concat(#{endDate},' 23:59:59'), '%Y-%m-%d %H:%i:%s')
]]>
</if>
group by t1.biz_code
</select>
<select id="getCustomerUnitPrice" resultType="java.math.BigDecimal">
SELECT
ifnull((sum(t1.pay_amount)-sum(t1.refund_amount))/count(ifnull(case t1.seat_num when 0 then 1 end,1)),0.00) as customerUnitPrice
FROM
tb_order_info t1
WHERE t1.shop_id = #{shopId}
and t1.paid_time is not null
<if test="beginDate != null and beginDate != ''">
and t1.create_time >= str_to_date(concat(#{beginDate},' 00:00:00'), '%Y-%m-%d %H:%i:%s')
</if>
<if test="endDate != null and endDate != ''">
<![CDATA[
and t1.create_time <= str_to_date(concat(#{endDate},' 23:59:59'), '%Y-%m-%d %H:%i:%s')
]]>
</if>
</select>
<select id="getTableTurnoverRate" resultType="java.math.BigDecimal">
SELECT
ifnull((count(*)-count(DISTINCT t1.table_code))/count(DISTINCT t1.table_code)*100,0.00)
FROM
tb_order_info t1
WHERE t1.shop_id = #{shopId}
and t1.paid_time is not null
<if test="beginDate != null and beginDate != ''">
and t1.create_time >= str_to_date(concat(#{beginDate},' 00:00:00'), '%Y-%m-%d %H:%i:%s')
</if>
<if test="endDate != null and endDate != ''">
<![CDATA[
and t1.create_time <= str_to_date(concat(#{endDate},' 23:59:59'), '%Y-%m-%d %H:%i:%s')
]]>
</if>
</select>
</mapper> </mapper>

View File

@@ -74,4 +74,88 @@
group by t1.prod_id group by t1.prod_id
ORDER BY sum( t1.sale_count ) DESC,max(t1.id) DESC ORDER BY sum( t1.sale_count ) DESC,max(t1.id) DESC
</select> </select>
<select id="getSaleSummaryCount2" resultType="com.czg.order.vo.SaleSummaryCountVo">
SELECT
sum(t1.pay_amount) as totalAmount,
sum(t1.refund_amount) as refundAmount,
count(*) as saleCount,
count(case when t1.refund_amount > 0 then 1 end) as refundCount
FROM
tb_order_info t1
left join (
SELECT
x1.order_id,
concat( ',', GROUP_CONCAT( x2.category_id ), ',' ) AS category_id,
GROUP_CONCAT( x1.product_name ) AS product_name
FROM
tb_order_detail x1
LEFT JOIN tb_product x2 ON x1.product_id = x2.id
GROUP BY x1.order_id
) t2 on t1.id = t2.order_id
where t1.shop_id = #{shopId}
<if test="productName != null and productName != ''">
and t2.product_name like concat('%', #{productName}, '%')
</if>
<if test="prodCategoryId != null">
and t2.category_id like concat('%,', #{prodCategoryId}, ',%')
</if>
<if test="beginDate != null and beginDate != ''">
and t1.create_time >= str_to_date(#{beginDate}, '%Y-%m-%d')
</if>
<if test="endDate != null and endDate != ''">
<![CDATA[
and t1.create_time <= str_to_date(#{endDate}, '%Y-%m-%d')
]]>
</if>
</select>
<select id="findSaleSummaryList2" resultType="com.czg.order.vo.SaleSummaryInfoVo">
SELECT
t1.product_id,
t1.product_name as productName,
t3.name as category_name,
sum( t1.num ) AS saleCount,
sum( t1.pay_amount ) AS saleAmount,
sum( t1.return_num ) AS refundCount,
sum( t1.return_amount ) AS refundAmount
FROM
tb_order_detail t1
left join tb_product t2 on t1.product_id = t2.id
left join tb_shop_prod_category t3 on t2.category_id = t3.id
where t1.shop_id = #{shopId}
<if test="productName != null and productName != ''">
and t1.product_name like concat('%', #{productName}, '%')
</if>
<if test="prodCategoryId != null">
and t2.category_id = #{prodCategoryId}
</if>
<if test="beginDate != null and beginDate != ''">
and t1.create_time >= str_to_date(#{beginDate}, '%Y-%m-%d')
</if>
<if test="endDate != null and endDate != ''">
<![CDATA[
and t1.create_time <= str_to_date(#{endDate}, '%Y-%m-%d')
]]>
</if>
GROUP BY t1.product_id,t1.product_name
ORDER BY sum( t1.num ) DESC,max(t1.product_id) DESC
</select>
<select id="findProdRandingSummaryPage2" resultType="com.czg.order.vo.DataSummaryProductSaleRankingVo">
select
t1.product_id,
t1.product_name,
sum(t1.num) as number,
sum(t1.pay_amount) as amount
from tb_order_detail t1
where t1.shop_id = #{shopId}
<if test="beginDate != null and beginDate != ''">
and t1.create_time >= str_to_date(#{beginDate}, '%Y-%m-%d')
</if>
<if test="endDate != null and endDate != ''">
<![CDATA[
and t1.create_time <= str_to_date(#{endDate}, '%Y-%m-%d')
]]>
</if>
GROUP BY t1.product_id,t1.product_name
order by sum(t1.num) desc
</select>
</mapper> </mapper>

View File

@@ -352,7 +352,11 @@ public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> impl
} }
prodSku.setIsGrounding(isSale); prodSku.setIsGrounding(isSale);
prodSkuMapper.update(prodSku); prodSkuMapper.update(prodSku);
long normalCount = prodSkuMapper.selectCountByQuery(QueryWrapper.create().eq(ProdSku::getProductId, prodSku.getProductId()).eq(ProdSku::getIsDel, DeleteEnum.NORMAL.value())); long normalCount = prodSkuMapper.selectCountByQuery(QueryWrapper.create()
.eq(ProdSku::getProductId, prodSku.getProductId())
.eq(ProdSku::getIsGrounding, YesNoEnum.NO.value())
.eq(ProdSku::getIsDel, DeleteEnum.NORMAL.value())
);
if (normalCount == 0) { if (normalCount == 0) {
UpdateChain.of(Product.class) UpdateChain.of(Product.class)
.set(Product::getIsSale, isSale) .set(Product::getIsSale, isSale)
@@ -388,17 +392,36 @@ public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> impl
String type = param.getType(); String type = param.getType();
Long id = param.getId(); Long id = param.getId();
Integer isSoldOut = param.getIsSoldOut(); Integer isSoldOut = param.getIsSoldOut();
UpdateChain.of(ProdSku.class) if (ProductIsSaleTypeEnum.SKU.value().equals(type)) {
.set(ProdSku::getIsPauseSale, isSoldOut) ProdSku prodSku = prodSkuMapper.selectOneById(id);
.eq(ProdSku::getId, id) if (prodSku == null) {
.eq(ProdSku::getShopId, shopId) throw new CzgException("SKU不存在");
.update(); }
if (ProductIsSaleTypeEnum.PRODUCT.value().equals(type)) { prodSku.setIsPauseSale(isSoldOut);
prodSkuMapper.update(prodSku);
long normalCount = prodSkuMapper.selectCountByQuery(QueryWrapper.create()
.eq(ProdSku::getProductId, prodSku.getProductId())
.eq(ProdSku::getIsPauseSale, YesNoEnum.NO.value())
.eq(ProdSku::getIsDel, DeleteEnum.NORMAL.value())
);
if (normalCount == 0) {
UpdateChain.of(Product.class)
.set(Product::getIsSoldStock, isSoldOut)
.eq(Product::getId, prodSku.getProductId())
.eq(Product::getShopId, shopId)
.update();
}
} else if (ProductIsSaleTypeEnum.PRODUCT.value().equals(type)) {
UpdateChain.of(Product.class) UpdateChain.of(Product.class)
.set(Product::getIsSoldStock, isSoldOut) .set(Product::getIsSoldStock, isSoldOut)
.eq(Product::getId, id) .eq(Product::getId, id)
.eq(Product::getShopId, shopId) .eq(Product::getShopId, shopId)
.update(); .update();
UpdateChain.of(ProdSku.class)
.set(ProdSku::getIsPauseSale, isSoldOut)
.eq(ProdSku::getProductId, id)
.eq(ProdSku::getShopId, shopId)
.update();
} }
} }