erp同步玻璃饼订单

liweidong
sugy 3 months ago
parent 11205e61c6
commit f8d196a853
  1. 3
      blade-ops/blade-job/src/main/java/org/springblade/job/processor/erp/SynCloseProdPlanProcessor.java
  2. 27
      blade-ops/blade-job/src/main/java/org/springblade/job/processor/erp/SynPurchaseProcessor.java
  3. 3
      blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/order/feign/IApsOrderClient.java
  4. 14
      blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/order/pojo/vo/LineMemoVo.java
  5. 7
      blade-service-api/blade-erpdata-api/src/main/java/org/springblade/erpdata/feign/IErpMesRbWoClient.java
  6. 11
      blade-service-api/blade-erpdata-api/src/main/java/org/springblade/erpdata/feign/IErpMesRbWoClientFallback.java
  7. 21
      blade-service/blade-desk/src/main/java/org/springblade/desk/order/feign/ApsOrderClient.java
  8. 27
      blade-service/blade-desk/src/main/java/org/springblade/desk/order/mapper/YieldPlanMapper.java
  9. 46
      blade-service/blade-desk/src/main/java/org/springblade/desk/order/mapper/YieldPlanMapper.xml
  10. 1
      blade-service/blade-desk/src/main/java/org/springblade/desk/order/service/IYieldOrderService.java
  11. 55
      blade-service/blade-desk/src/main/java/org/springblade/desk/order/service/impl/YieldPlanServiceImpl.java
  12. 12
      blade-service/blade-erpdata/src/main/java/org/springblade/erpdata/feign/ErpMesRbWoClient.java
  13. 14
      blade-service/blade-erpdata/src/main/java/org/springblade/erpdata/mapper/ErpPrtbasdefMapper.java
  14. 5
      blade-service/blade-erpdata/src/main/java/org/springblade/erpdata/mapper/ErpPrtbasdefMapper.xml
  15. 6
      blade-service/blade-erpdata/src/main/java/org/springblade/erpdata/service/IErpMesRbWoService.java
  16. 12
      blade-service/blade-erpdata/src/main/java/org/springblade/erpdata/service/IErpPrtbasdefService.java
  17. 17
      blade-service/blade-erpdata/src/main/java/org/springblade/erpdata/service/impl/ErpMesRbWoServiceImpl.java
  18. 20
      blade-service/blade-erpdata/src/main/java/org/springblade/erpdata/service/impl/ErpPrtbasdefServiceImpl.java

@ -2,6 +2,7 @@ package org.springblade.job.processor.erp;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springblade.desk.order.feign.IApsOrderClient;
import org.springblade.erpdata.feign.IErpMesRbWoClient; import org.springblade.erpdata.feign.IErpMesRbWoClient;
import tech.powerjob.worker.core.processor.ProcessResult; import tech.powerjob.worker.core.processor.ProcessResult;
import tech.powerjob.worker.core.processor.TaskContext; import tech.powerjob.worker.core.processor.TaskContext;
@ -15,6 +16,8 @@ public class SynCloseProdPlanProcessor implements BasicProcessor {
private final IErpMesRbWoClient mesRbWoClient; private final IErpMesRbWoClient mesRbWoClient;
//private final IApsOrderClient orderClient;
@Override @Override

@ -0,0 +1,27 @@
package org.springblade.job.processor.erp;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springblade.erpdata.feign.IErpMesRbWoClient;
import tech.powerjob.worker.core.processor.ProcessResult;
import tech.powerjob.worker.core.processor.TaskContext;
import tech.powerjob.worker.core.processor.sdk.BasicProcessor;
import java.util.concurrent.CompletableFuture;
@RequiredArgsConstructor
@Slf4j
public class SynPurchaseProcessor implements BasicProcessor {
private final IErpMesRbWoClient mesRbWoClient;
@Override
public ProcessResult process(TaskContext taskContext) throws Exception {
log.info("同步采购订单定时任务开始");
CompletableFuture<Void> runFuture = CompletableFuture.runAsync(()-> mesRbWoClient.synPurchase());
log.info("同步采购订单定时任务结束");
return new ProcessResult(true);
}
}

@ -31,6 +31,7 @@ public interface IApsOrderClient {
String CLOSE_PLAN_LIST = API_PREFIX + "/getClosePlanList"; String CLOSE_PLAN_LIST = API_PREFIX + "/getClosePlanList";
String MAX_CARD_NO = API_PREFIX + "/getMaxCardNo"; String MAX_CARD_NO = API_PREFIX + "/getMaxCardNo";
String SYN_GLASS_CAKE = API_PREFIX + "/synGlassCake"; String SYN_GLASS_CAKE = API_PREFIX + "/synGlassCake";
String CLOSE_PROD_PLAN = API_PREFIX + "/synCloseProdPlan";
@PostMapping(SYNC_PLAN_FROM_SAVE) @PostMapping(SYNC_PLAN_FROM_SAVE)
void saveList(List<YieldPlan> yieldOrderList); void saveList(List<YieldPlan> yieldOrderList);
@ -48,4 +49,6 @@ public interface IApsOrderClient {
String getMaxCardNo(); String getMaxCardNo();
@GetMapping(SYN_GLASS_CAKE) @GetMapping(SYN_GLASS_CAKE)
void synGlassCake(); void synGlassCake();
@GetMapping(CLOSE_PROD_PLAN)
void synCloseProdPlan();
} }

@ -0,0 +1,14 @@
package org.springblade.desk.order.pojo.vo;
import lombok.Data;
@Data
public class LineMemoVo {
private Long sum;
private String prodLine;
private String memo;
}

@ -3,8 +3,10 @@ package org.springblade.erpdata.feign;
import org.springblade.core.launch.constant.AppConstant; import org.springblade.core.launch.constant.AppConstant;
import org.springblade.core.tool.api.R; import org.springblade.core.tool.api.R;
import org.springblade.erpdata.pojo.dto.table.Wo;
import org.springblade.erpdata.pojo.dto.view.MesRbWo; import org.springblade.erpdata.pojo.dto.view.MesRbWo;
import org.springframework.cloud.openfeign.FeignClient; import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import java.util.List; import java.util.List;
@ -22,6 +24,7 @@ public interface IErpMesRbWoClient {
String API_PREFIX = "/feign/erpdata/mesrbwo"; String API_PREFIX = "/feign/erpdata/mesrbwo";
String GET_LIST = API_PREFIX + "/getList"; String GET_LIST = API_PREFIX + "/getList";
String GET_WO = API_PREFIX + "/getWoOne";
/** /**
* 查询烧结配套信息 * 查询烧结配套信息
@ -42,4 +45,8 @@ public interface IErpMesRbWoClient {
R<Void> synGlassCake(); R<Void> synGlassCake();
R<Void>synCloseProdPlan(); R<Void>synCloseProdPlan();
@GetMapping(GET_WO)
R<Wo> getWoOne(String ypCode);
R<Void> synPurchase();
} }

@ -1,6 +1,7 @@
package org.springblade.erpdata.feign; package org.springblade.erpdata.feign;
import org.springblade.core.tool.api.R; import org.springblade.core.tool.api.R;
import org.springblade.erpdata.pojo.dto.table.Wo;
import org.springblade.erpdata.pojo.dto.view.MesRbWo; import org.springblade.erpdata.pojo.dto.view.MesRbWo;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -34,4 +35,14 @@ public class IErpMesRbWoClientFallback implements IErpMesRbWoClient {
public R<Void> synCloseProdPlan() { public R<Void> synCloseProdPlan() {
return R.fail("获取数据失败"); return R.fail("获取数据失败");
} }
@Override
public R<Wo> getWoOne(String ypCode) {
return R.fail("获取数据失败");
}
@Override
public R<Void> synPurchase() {
return R.fail("获取数据失败");
}
} }

@ -11,7 +11,6 @@ import org.springblade.desk.dashboard.service.IDsPartService;
import org.springblade.desk.order.pojo.entity.YieldPlan; import org.springblade.desk.order.pojo.entity.YieldPlan;
import org.springblade.desk.order.service.IYieldOrderService; import org.springblade.desk.order.service.IYieldOrderService;
import org.springblade.desk.order.service.IYieldPlanService; import org.springblade.desk.order.service.IYieldPlanService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
@ -36,6 +35,7 @@ public class ApsOrderClient implements IApsOrderClient {
private final IDsPartService dsPartService; private final IDsPartService dsPartService;
//private final IErpMesRbWoClient mesRbWoClient;
@Override @Override
@PostMapping(SYNC_PLAN_FROM_SAVE) @PostMapping(SYNC_PLAN_FROM_SAVE)
public void saveList(List<YieldPlan> yieldPlanList) { public void saveList(List<YieldPlan> yieldPlanList) {
@ -83,4 +83,23 @@ public class ApsOrderClient implements IApsOrderClient {
public void synGlassCake() { public void synGlassCake() {
yieldPlanService.synGlassCake(); yieldPlanService.synGlassCake();
} }
@Override
public void synCloseProdPlan() {
// List<YieldPlan> yieldPlanList=yieldPlanService.list(new QueryWrapper<YieldPlan>().lambda()
// .lt(YieldPlan::getStatus, "10015")
// .orderByAsc(YieldPlan::getCheckCloseTime)
// .last("limit 1000"));
// yieldPlanList.forEach(yieldPlan -> {
// Wo wo=mesRbWoClient.getWoOne(yieldPlan.getYpCode()).getData();
// if(wo!=null){
// yieldPlan.setCheckCloseTime(new Date());
// yieldPlanService.updateById(yieldPlan);
// }else {
// yieldPlan.setStatus(YieldPlanEnum.STATUS_COMPLETED.getCode());
// yieldPlan.setCheckCloseTime(new Date());
// yieldPlanService.updateById(yieldPlan);
// }
// });
}
} }

@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springblade.desk.order.pojo.entity.YieldPlan; import org.springblade.desk.order.pojo.entity.YieldPlan;
import org.springblade.desk.order.pojo.enums.YieldPlanEnum; import org.springblade.desk.order.pojo.enums.YieldPlanEnum;
import org.springblade.desk.order.pojo.vo.LineMemoVo;
import java.util.List; import java.util.List;
@ -25,5 +26,29 @@ public interface YieldPlanMapper extends BaseMapper<YieldPlan> {
*/ */
List<YieldPlan> selectPage(IPage page, YieldPlan entity, List<YieldPlanEnum> planTypeList); List<YieldPlan> selectPage(IPage page, YieldPlan entity, List<YieldPlanEnum> planTypeList);
/**
* 获取最大优先级
* @param ypCode
* @return
*/
Long getMaxPriority(String ypCode);
/**
* 获取数量
* @param ypCode
* @param partCode
* @param bathNo
* @return
*/
Long getCount(String ypCode, String partCode, String bathNo);
/**
* 获取接收人
* @return
*/
Long getReceiveUser();
/**
* 获取线体备注
* @param ypCode
* @return
*/
LineMemoVo getLineMemo(String ypCode);
} }

@ -27,4 +27,50 @@
AND status = #{entity.status} AND status = #{entity.status}
</if> </if>
</select> </select>
<select id="getMaxPriority" resultType="java.lang.Long">
select nvl(max(a.priority),1) as vPriority
from mes_priority_rec a
<where>
a.is_deleted = 0
<if test="ypCode != null">
AND a.po_code = #{ypCode}
</if>
</where>
</select>
<select id="getCount" resultType="java.lang.Long">
select count(1) as vCount
from mes_urgent_uphold a
<where>
a.is_deleted = 0
<if test="ypCode != null">
AND a.po_code = #{ypCode}
</if>
<if test="partCode != null">
AND a.part_code = #{partCode}
</if>
<if test="bathNo != null">
AND a.batch_no = #{bathNo}
</if>
</where>
</select>
<select id="getReceiveUser" resultType="java.lang.Long">
select DICT_KEY as v_failure_man
from BLADE_DICT
where code ='BS_BLB_USER' and DICT_KEY = 1
and ROWNUM=1
order by SORT desc
</select>
<select id="getLineMemo" resultType="org.springblade.desk.order.pojo.vo.LineMemoVo">
SELECT
COUNT(*) as sum, -- 统计记录数
MAX(a.PRODUCT_LINE) as prodLine, -- 取prod_line最大值
MAX(memo) as MEMO -- 取memo最大值
FROM MES_YIELD_PLAN a
<where>
a.is_deleted = 0
<if test="ypCode != null">
AND a.YP_CODE = #{ypCode}
</if>
</where>
</select>
</mapper> </mapper>

@ -196,4 +196,5 @@ public interface IYieldOrderService extends BaseService<YieldOrder> {
String getMaxCardNo(); String getMaxCardNo();
} }

@ -7,13 +7,16 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.mp.base.BaseServiceImpl; import org.springblade.core.mp.base.BaseServiceImpl;
import org.springblade.core.tool.utils.ObjectUtil; import org.springblade.core.tool.utils.ObjectUtil;
import org.springblade.desk.dashboard.pojo.entity.DsPartEntity; import org.springblade.desk.dashboard.pojo.entity.DsPartEntity;
import org.springblade.desk.dashboard.service.IDsPartService; import org.springblade.desk.dashboard.service.IDsPartService;
import org.springblade.desk.order.mapper.YieldPlanMapper; import org.springblade.desk.order.mapper.YieldPlanMapper;
import org.springblade.desk.order.pojo.entity.YieldOrder;
import org.springblade.desk.order.pojo.entity.YieldPlan; import org.springblade.desk.order.pojo.entity.YieldPlan;
import org.springblade.desk.order.pojo.enums.YieldPlanEnum; import org.springblade.desk.order.pojo.enums.YieldPlanEnum;
import org.springblade.desk.order.pojo.vo.LineMemoVo;
import org.springblade.desk.order.service.IYieldOrderService; import org.springblade.desk.order.service.IYieldOrderService;
import org.springblade.desk.order.service.IYieldPlanService; import org.springblade.desk.order.service.IYieldPlanService;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -146,6 +149,58 @@ public class YieldPlanServiceImpl extends BaseServiceImpl<YieldPlanMapper, Yield
cardNo="RB"+new SimpleDateFormat("yyMMdd").format(new Date())+String.format("%05d", num); cardNo="RB"+new SimpleDateFormat("yyMMdd").format(new Date())+String.format("%05d", num);
String bathNo="Y"+new SimpleDateFormat("yyMMdd").format(new Date())+String.format("%05d", num); String bathNo="Y"+new SimpleDateFormat("yyMMdd").format(new Date())+String.format("%05d", num);
//调用公共保存方法 todo //调用公共保存方法 todo
//查询order订单
for (int i = 0; i < dsPartList.size(); i++) {
DsPartEntity dsPart = dsPartList.get(i);
List<YieldOrder> yieldOrderList=yieldOrderService.list(new QueryWrapper<YieldOrder>()
.lambda().eq(YieldOrder::getYpCode, yieldPlan.getYpCode())
.eq(YieldOrder::getCardNo, cardNo)
.eq(YieldOrder::getBatchNo, bathNo)
.eq(YieldOrder::getRoamNo, yieldPlan.getRoamNo()));
if(yieldOrderList.size()>0){
new ServiceException("'零件号【' "+dsPart.getPartCode()+" '】,批号【'\n" +
" "+bathNo+" '】工单已转交,请勿重复转交!!'");
}
DsPartEntity zPartEntity = dsPartService.getOne(new QueryWrapper<DsPartEntity>().lambda()
.eq(DsPartEntity::getPartCode, yieldPlan.getPartCode()).last("limit 1"));
if(zPartEntity.getArea()==null){
yieldPlan.setYpArea(0.0);
}
Long vPriority=baseMapper.getMaxPriority(yieldPlan.getYpCode());
//7. 厂内生产急件标识赋值
Long vCount=baseMapper.getCount(yieldPlan.getYpCode(),yieldPlan.getPartCode(),bathNo);
YieldOrder yieldOrder=new YieldOrder();
vPriority=vPriority+14000;
yieldOrder.setPriorityErp(Integer.parseInt(vPriority.toString()));
if(vCount>0){
yieldOrder.setSiteWork(true);
yieldOrder.setPriorityErp(5);
}
if("2".equals(yieldOrder.getYieldType())||"3".equals(yieldOrder.getYieldType())){
yieldOrder.setSiteWork( true);
yieldOrder.setReceiveStatus(11000);
}
if("3".equals(yieldOrder.getYieldType())){
yieldOrder.setStatus(11001);
}
//对接受人赋值
Long receiveUser=baseMapper.getReceiveUser();
yieldOrder.setReceiveUser(receiveUser);
//对接收时间进行赋值
yieldOrder.setReceiveTime(new Date());
LineMemoVo lineMemoVo = baseMapper.getLineMemo(yieldPlan.getYpCode());
if(lineMemoVo!=null&&lineMemoVo.getSum()==0){
yieldOrder.setMemo("");
yieldOrder.setYpProductLine("");
}else {
yieldOrder.setMemo(lineMemoVo.getMemo());
yieldOrder.setYpProductLine(lineMemoVo.getProdLine());
}
//保存订单
yieldOrderService.saveOrUpdate(yieldOrder);
}
// dsPartList.forEach(dsPart -> { // dsPartList.forEach(dsPart -> {
// List<StRealtimeStock> stockList=stRealtimeStockService.getGoodsByPartCode(dsPart.getPartCode()); // List<StRealtimeStock> stockList=stRealtimeStockService.getGoodsByPartCode(dsPart.getPartCode());
// StGoodStatisVO statisVO=stRealtimeStockService.getGoodsByCode(dsPart.getPartCode()); // StGoodStatisVO statisVO=stRealtimeStockService.getGoodsByCode(dsPart.getPartCode());

@ -4,6 +4,7 @@ import io.swagger.v3.oas.annotations.Hidden;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import org.springblade.core.tenant.annotation.NonDS; import org.springblade.core.tenant.annotation.NonDS;
import org.springblade.core.tool.api.R; import org.springblade.core.tool.api.R;
import org.springblade.erpdata.pojo.dto.table.Wo;
import org.springblade.erpdata.pojo.dto.view.MesRbWo; import org.springblade.erpdata.pojo.dto.view.MesRbWo;
import org.springblade.erpdata.service.IErpMesRbWoService; import org.springblade.erpdata.service.IErpMesRbWoService;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
@ -47,4 +48,15 @@ public class ErpMesRbWoClient implements IErpMesRbWoClient {
erpMesRbWoService.synCloseProdPlan(); erpMesRbWoService.synCloseProdPlan();
return R.success(); return R.success();
} }
@Override
public R<Wo> getWoOne(String ypCode) {
return erpMesRbWoService.getWoOne(ypCode);
}
@Override
public R<Void> synPurchase() {
erpMesRbWoService.synPurchase();
return R.success();
}
} }

@ -0,0 +1,14 @@
package org.springblade.erpdata.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.springblade.erpdata.pojo.dto.table.Prtbasdef;
/**
* Mapper 接口
*
* @author lqk
*/
public interface ErpPrtbasdefMapper extends BaseMapper<Prtbasdef> {
}

@ -0,0 +1,5 @@
<?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 = "org.springblade.erpdata.mapper.ErpPrtbasdefMapper">
</mapper>

@ -1,5 +1,7 @@
package org.springblade.erpdata.service; package org.springblade.erpdata.service;
import org.springblade.core.tool.api.R;
import org.springblade.erpdata.pojo.dto.table.Wo;
import org.springblade.erpdata.pojo.dto.view.MesRbWo; import org.springblade.erpdata.pojo.dto.view.MesRbWo;
import java.util.List; import java.util.List;
@ -26,4 +28,8 @@ public interface IErpMesRbWoService {
void synGlassCake(); void synGlassCake();
void synCloseProdPlan(); void synCloseProdPlan();
R<Wo> getWoOne(String ypCode);
void synPurchase();
} }

@ -0,0 +1,12 @@
package org.springblade.erpdata.service;
import org.springblade.core.mp.base.BaseService;
import org.springblade.erpdata.pojo.dto.table.Prtbasdef;
/**
* ERP数据查询service
*
* @author lqk
*/
public interface IErpPrtbasdefService extends BaseService<Prtbasdef> {
}

@ -3,7 +3,7 @@ package org.springblade.erpdata.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils; import org.springblade.core.tool.api.R;
import org.springblade.desk.dashboard.pojo.entity.DsCraftEntity; import org.springblade.desk.dashboard.pojo.entity.DsCraftEntity;
import org.springblade.desk.dashboard.pojo.entity.DsPartEntity; import org.springblade.desk.dashboard.pojo.entity.DsPartEntity;
import org.springblade.desk.order.feign.IApsOrderClient; import org.springblade.desk.order.feign.IApsOrderClient;
@ -18,11 +18,9 @@ import org.springblade.erpdata.service.IErpRrbwoerptomesService;
import org.springblade.erpdata.service.IErpWoService; import org.springblade.erpdata.service.IErpWoService;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.text.SimpleDateFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.logging.SimpleFormatter;
/** /**
* @author lqk * @author lqk
@ -165,4 +163,17 @@ public class ErpMesRbWoServiceImpl implements IErpMesRbWoService {
} }
}); });
} }
@Override
public R<Wo> getWoOne(String ypCode) {
Wo wo=woService.getOne(new QueryWrapper<Wo>()
.eq("WONO",ypCode));
return R.data(wo);
}
@Override
public void synPurchase() {
}
} }

@ -0,0 +1,20 @@
package org.springblade.erpdata.service.impl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springblade.core.mp.base.BaseServiceImpl;
import org.springblade.erpdata.mapper.ErpPrtbasdefMapper;
import org.springblade.erpdata.pojo.dto.table.Prtbasdef;
import org.springblade.erpdata.service.IErpPrtbasdefService;
import org.springframework.stereotype.Service;
/**
* @author lqk
* @date 2025-11-26 9:39
*/
@Slf4j
@RequiredArgsConstructor
@Service
public class ErpPrtbasdefServiceImpl extends BaseServiceImpl<ErpPrtbasdefMapper, Prtbasdef> implements IErpPrtbasdefService {
}
Loading…
Cancel
Save