|
|
|
@ -1018,154 +1018,93 @@ public class BusinDataTaskServiceImpl extends ServiceImpl<BusinDataTaskMapper, B |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
@Transactional(rollbackFor = Exception.class) |
|
|
|
@Transactional(rollbackFor = Exception.class) |
|
|
|
public synchronized BusinTaskExeBo outboundInfo(List<BusinDataTaskGoodsVo> goods, String id) { |
|
|
|
public synchronized BusinTaskExeBo outboundInfo(List<BusinDataTaskGoods> goods, String id,Boolean isAnew) { |
|
|
|
log.info("要出库的保险杠信息:" + JsonUtil.toJSONString(goods)); |
|
|
|
|
|
|
|
//获取任务信息
|
|
|
|
|
|
|
|
BusinDataTask businDataTask = iBusinDataTaskService.getById(id); |
|
|
|
|
|
|
|
List<String> goodsList = new ArrayList<>(); |
|
|
|
|
|
|
|
for (BusinDataTaskGoodsVo businDataTaskGoodsVo : goods) { |
|
|
|
|
|
|
|
goodsList.add(businDataTaskGoodsVo.getGoodsNo()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
//根据物料查询所在仓库
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// TODO: 2024/6/27 出库时查询巷道任务数最少及库存量最多的
|
|
|
|
|
|
|
|
List<BaseLocationVo> tunnelVo = baseLocationService.getTUunnel(goodsList); |
|
|
|
|
|
|
|
if (tunnelVo != null && tunnelVo.size() == 0) { |
|
|
|
|
|
|
|
log.info("要出库的保险杠编号:" + JsonUtil.toJSONString(goodsList)); |
|
|
|
|
|
|
|
return null; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
Map<String, Long> tunnelLocQtyDic = tunnelVo.stream().collect(Collectors.groupingBy(BaseLocationVo::getTunnel, Collectors.counting())); |
|
|
|
|
|
|
|
log.info("保险杠所在的巷道:" + JsonUtil.toJSONString(goodsList)+" "+JsonUtil.toJSONString(tunnelLocQtyDic)); |
|
|
|
|
|
|
|
//排序后的巷道货位数(降序)
|
|
|
|
|
|
|
|
Map<String, Integer> tunnelLocQtyDicSort = new LinkedHashMap<>(); |
|
|
|
|
|
|
|
tunnelLocQtyDic.entrySet().stream().sorted(Map.Entry.<String, Long>comparingByValue().reversed()).forEachOrdered(e -> tunnelLocQtyDicSort.put(e.getKey(), e.getValue().intValue())); |
|
|
|
|
|
|
|
log.info("保险杠所在的排序后的巷道:" + JsonUtil.toJSONString(goodsList)+" "+JsonUtil.toJSONString(tunnelLocQtyDicSort)); |
|
|
|
|
|
|
|
//拿到任务数最少的巷道并且库存量是最大的
|
|
|
|
|
|
|
|
String tunnelone = this.quickSortTaskQty(tunnelLocQtyDicSort); |
|
|
|
|
|
|
|
log.info("保险杠所在的任务数最少的巷道:" +JsonUtil.toJSONString(goodsList)+" "+tunnelone); |
|
|
|
|
|
|
|
List<BaseLocationVo> tunnelLocation = tunnelVo.stream().filter(e -> e.getTunnel().equals(tunnelone)).collect(Collectors.toList()); |
|
|
|
|
|
|
|
List<BaseLocationVo> tunnelLocationSorted = tunnelLocation.stream().sorted(Comparator.comparing(BaseLocationVo::getRoute).thenComparing(BaseLocationVo::getIsDeep)).collect(Collectors.toList()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// List<Long> listlocationId = new ArrayList<>();
|
|
|
|
|
|
|
|
//生成出库明细
|
|
|
|
|
|
|
|
BusinTaskExeBo exeBo = new BusinTaskExeBo(); |
|
|
|
BusinTaskExeBo exeBo = new BusinTaskExeBo(); |
|
|
|
exeBo.setTaskCode(businDataTask.getId()); |
|
|
|
try { |
|
|
|
exeBo.setBusinDataTaskGoodsVo(goods); |
|
|
|
log.info("要出库的保险杠信息,任务编号:" + id +" 保险杠信息"+JsonUtil.toJSONString(goods)); |
|
|
|
exeBo.setTransNo("2"); |
|
|
|
//获取任务信息
|
|
|
|
exeBo.setTransQual("2"); |
|
|
|
BusinDataTask businDataTask = iBusinDataTaskService.getById(id); |
|
|
|
|
|
|
|
//货位已经被占用,重新分配货位
|
|
|
|
if (tunnelLocationSorted.size() == 0) { |
|
|
|
if (isAnew){ |
|
|
|
log.error("没有可出货的货位了:" + JsonUtil.toJSONString(goodsList)); |
|
|
|
businDataTask.setFromLayer(""); |
|
|
|
return exeBo; |
|
|
|
} |
|
|
|
} |
|
|
|
List<String> goodsList = new ArrayList<>(); |
|
|
|
|
|
|
|
for (BusinDataTaskGoods businDataTaskGoods : goods) { |
|
|
|
//根据巷道分配货位
|
|
|
|
goodsList.add(businDataTaskGoods.getGoodsNo()); |
|
|
|
BaseLocationVo baseLocationVo = tunnelLocationSorted.get(0); |
|
|
|
} |
|
|
|
exeBo.setBaseLocationVo(baseLocationVo); |
|
|
|
//根据物料查询所在仓库
|
|
|
|
|
|
|
|
|
|
|
|
// //根据货位拿到库存信息
|
|
|
|
|
|
|
|
// List<SysStockDetail> sysStockDetailList = sysStockDetailMapper.getStockDetailByLocationId(String.valueOf(baseLocationVo.getId()));
|
|
|
|
|
|
|
|
// sysStockDetailList.stream().forEach(e->{
|
|
|
|
|
|
|
|
// e.setOutQty(1);
|
|
|
|
|
|
|
|
// });
|
|
|
|
|
|
|
|
// //给库存添加出货预占
|
|
|
|
|
|
|
|
// iSysStockDetailService.updateBatchById(sysStockDetailList);
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
Long stkPlcId = null; |
|
|
|
|
|
|
|
Long plcId = null; |
|
|
|
|
|
|
|
BasePointDeviceQueryBo pointQueryBo = new BasePointDeviceQueryBo(); |
|
|
|
|
|
|
|
pointQueryBo.setTunnel(baseLocationVo.getTunnel()); |
|
|
|
|
|
|
|
pointQueryBo.setDirection("0"); |
|
|
|
|
|
|
|
List<BasePointDeviceVo> basePointDeviceVos = new ArrayList<>(); |
|
|
|
|
|
|
|
plcId = Long.valueOf(isysParameterService.selectConfigByKey(ParameterConstants.ParameterSystem.LK_plc_id)); |
|
|
|
|
|
|
|
//获取巷道对应的堆垛机信息
|
|
|
|
|
|
|
|
pointQueryBo.setDevType("1"); |
|
|
|
|
|
|
|
BaseDevicePlcVo baseDevicePlcVo = baseLocationPlcMapper.selectBaseDevicePlc(pointQueryBo); |
|
|
|
|
|
|
|
stkPlcId = baseDevicePlcVo.getPlcId(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//回填任务相关数据
|
|
|
|
|
|
|
|
if (ObjectUtils.isEmpty(businDataTask.getFromLayer())) { |
|
|
|
|
|
|
|
businDataTask.setFromColumn(String.valueOf(baseLocationVo.getLocationColumn())); |
|
|
|
|
|
|
|
businDataTask.setFromLayer(baseLocationVo.getLayer()); |
|
|
|
|
|
|
|
businDataTask.setFromRow(baseLocationVo.getLocationRow()); |
|
|
|
|
|
|
|
businDataTask.setDevId(baseLocationVo.getDevId()); |
|
|
|
|
|
|
|
businDataTask.setTunnel(baseLocationVo.getTunnel()); |
|
|
|
|
|
|
|
businDataTask.setDpsNoOne(plcId); |
|
|
|
|
|
|
|
businDataTask.setDpsNoTwo(stkPlcId); |
|
|
|
|
|
|
|
businDataTask.setLocationId(baseLocationVo.getId()); |
|
|
|
|
|
|
|
iBusinDataTaskService.updateById(businDataTask); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// baseLocationVo.setLocationStatus("4");
|
|
|
|
// 2024/6/27 出库时查询巷道任务数最少及库存量最多的
|
|
|
|
// baseLocationService.updateById(BeanUtil.toBean(baseLocationVo, BaseLocation.class));
|
|
|
|
List<BaseLocationVo> tunnelVo = baseLocationService.getTUunnel(goodsList); |
|
|
|
|
|
|
|
if (tunnelVo != null && tunnelVo.size() == 0) { |
|
|
|
|
|
|
|
log.info("要出库的保险杠编号:" + JsonUtil.toJSONString(goodsList)); |
|
|
|
|
|
|
|
return null; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
//TODO 获取redis中的货位,从查询的列表中删除
|
|
|
|
|
|
|
|
String redisKeys=RedisConstant.redisOutLoc+"*"; |
|
|
|
|
|
|
|
Set<String> redisOutLocaList = redisTemplate.keys(redisKeys); |
|
|
|
|
|
|
|
for (BaseLocationVo baseLocationVo : tunnelVo) { |
|
|
|
|
|
|
|
for (String s : redisOutLocaList) { |
|
|
|
|
|
|
|
if (baseLocationVo.getLocationCode().equals(s)){ |
|
|
|
|
|
|
|
tunnelVo.remove(baseLocationVo); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Map<String, Long> tunnelLocQtyDic = tunnelVo.stream().collect(Collectors.groupingBy(BaseLocationVo::getTunnel, Collectors.counting())); |
|
|
|
|
|
|
|
log.info("保险杠所在的巷道:" + JsonUtil.toJSONString(goodsList)+" "+JsonUtil.toJSONString(tunnelLocQtyDic)); |
|
|
|
|
|
|
|
//排序后的巷道货位数(降序)
|
|
|
|
|
|
|
|
Map<String, Integer> tunnelLocQtyDicSort = new LinkedHashMap<>(); |
|
|
|
|
|
|
|
tunnelLocQtyDic.entrySet().stream().sorted(Map.Entry.<String, Long>comparingByValue().reversed()).forEachOrdered(e -> tunnelLocQtyDicSort.put(e.getKey(), e.getValue().intValue())); |
|
|
|
|
|
|
|
log.info("保险杠所在的排序后的巷道:" + JsonUtil.toJSONString(goodsList)+" "+JsonUtil.toJSONString(tunnelLocQtyDicSort)); |
|
|
|
|
|
|
|
//拿到任务数最少的巷道并且库存量是最大的
|
|
|
|
|
|
|
|
String tunnelone = this.quickSortTaskQty(tunnelLocQtyDicSort); |
|
|
|
|
|
|
|
log.info("保险杠所在的任务数最少的巷道:" +JsonUtil.toJSONString(goodsList)+" "+tunnelone); |
|
|
|
|
|
|
|
List<BaseLocationVo> tunnelLocation = tunnelVo.stream().filter(e -> e.getTunnel().equals(tunnelone)).collect(Collectors.toList()); |
|
|
|
|
|
|
|
List<BaseLocationVo> tunnelLocationSorted = tunnelLocation.stream().sorted(Comparator.comparing(BaseLocationVo::getRoute).thenComparing(BaseLocationVo::getIsDeep)).collect(Collectors.toList()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//生成出库明细
|
|
|
|
|
|
|
|
if (tunnelLocationSorted.size() == 0) { |
|
|
|
|
|
|
|
log.error("没有可出货的货位了:" + JsonUtil.toJSONString(goodsList)); |
|
|
|
|
|
|
|
return exeBo; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
List<BusinDataTaskGoods> businDataTaskGoodsList = iBusinDataTaskGoodsService.list(new LambdaQueryWrapper<BusinDataTaskGoods>() |
|
|
|
//根据巷道分配货位
|
|
|
|
.eq(BusinDataTaskGoods::getTaskCode, id)); |
|
|
|
BaseLocationVo baseLocationVo = tunnelLocationSorted.get(0); |
|
|
|
|
|
|
|
log.info("任务号:"+id+"分配到的货位:"+JsonUtil.toJSONString(baseLocationVo)); |
|
|
|
|
|
|
|
//TODO 把分配的货位记录到redis中
|
|
|
|
|
|
|
|
redisTemplate.opsForValue().set(RedisConstant.redisOutLoc, baseLocationVo.getId()); |
|
|
|
|
|
|
|
|
|
|
|
//根据货位查询物料信息
|
|
|
|
exeBo.setBaseLocationVo(baseLocationVo); |
|
|
|
List<SysStockDetail> sysStockDetailList = iSysStockDetailService.list(new LambdaQueryWrapper<SysStockDetail>() |
|
|
|
Long stkPlcId = null; |
|
|
|
.eq(SysStockDetail::getLocationId, baseLocationVo.getId()) |
|
|
|
Long plcId = null; |
|
|
|
.eq(SysStockDetail::getQty, 1) |
|
|
|
BasePointDeviceQueryBo pointQueryBo = new BasePointDeviceQueryBo(); |
|
|
|
.isNull(SysStockDetail::getOutQty)); |
|
|
|
pointQueryBo.setTunnel(baseLocationVo.getTunnel()); |
|
|
|
|
|
|
|
pointQueryBo.setDirection("0"); |
|
|
|
|
|
|
|
|
|
|
|
for (SysStockDetail stockDetail : sysStockDetailList) { |
|
|
|
plcId = Long.valueOf(isysParameterService.selectConfigByKey(ParameterConstants.ParameterSystem.LK_plc_id)); |
|
|
|
businDataTaskGoodsList.stream().forEach( |
|
|
|
//获取巷道对应的堆垛机信息
|
|
|
|
e -> { |
|
|
|
pointQueryBo.setDevType("1"); |
|
|
|
// log.info("内部是否相等:" + e.getGoodsNo().equals(stockDetail.getGoodsNo()) + "任务保险杠编码:" + e.getGoodsNo() + " 库存保险杠条码:" + stockDetail.getGoodsNo());
|
|
|
|
BaseDevicePlcVo baseDevicePlcVo = baseLocationPlcMapper.selectBaseDevicePlc(pointQueryBo); |
|
|
|
if (e.getGoodsNo().equals(stockDetail.getGoodsNo())) { |
|
|
|
stkPlcId = baseDevicePlcVo.getPlcId(); |
|
|
|
e.setQrCode(stockDetail.getQrCode()); |
|
|
|
|
|
|
|
} |
|
|
|
//回填任务相关数据
|
|
|
|
} |
|
|
|
if (ObjectUtils.isEmpty(businDataTask.getFromLayer())) { |
|
|
|
); |
|
|
|
businDataTask.setFromColumn(String.valueOf(baseLocationVo.getLocationColumn())); |
|
|
|
|
|
|
|
businDataTask.setFromLayer(baseLocationVo.getLayer()); |
|
|
|
|
|
|
|
businDataTask.setFromRow(baseLocationVo.getLocationRow()); |
|
|
|
|
|
|
|
businDataTask.setDevId(baseLocationVo.getDevId()); |
|
|
|
|
|
|
|
businDataTask.setTunnel(baseLocationVo.getTunnel()); |
|
|
|
|
|
|
|
businDataTask.setDpsNoOne(plcId); |
|
|
|
|
|
|
|
businDataTask.setDpsNoTwo(stkPlcId); |
|
|
|
|
|
|
|
businDataTask.setLocationId(baseLocationVo.getId()); |
|
|
|
|
|
|
|
iBusinDataTaskService.updateById(businDataTask); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}catch (Exception e){ |
|
|
|
|
|
|
|
log.error(" outboundInfo:"+e.getMessage()); |
|
|
|
} |
|
|
|
} |
|
|
|
//更新任务物料明细
|
|
|
|
|
|
|
|
iBusinDataTaskGoodsService.saveOrUpdateBatch(businDataTaskGoodsList); |
|
|
|
|
|
|
|
// //取待补货区上的货不满足应发任务的货物时
|
|
|
|
|
|
|
|
// if (sysStockDetailList.size()<=businDataTaskGoodsList.size()){
|
|
|
|
|
|
|
|
// sysStockDetailList.stream().forEach(
|
|
|
|
|
|
|
|
// e->{
|
|
|
|
|
|
|
|
// for (int i=0;i<businDataTaskGoodsList.size();i++
|
|
|
|
|
|
|
|
// ) {
|
|
|
|
|
|
|
|
// BusinDataTaskGoods businDataTaskGoods=businDataTaskGoodsList.get(i);
|
|
|
|
|
|
|
|
// if (e.getGoodsNo().equals(businDataTaskGoods.getGoodsNo())){
|
|
|
|
|
|
|
|
// businDataTaskGoodsList.remove(i);
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
// );
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
// if (businDataTaskGoodsList.size()>0){
|
|
|
|
|
|
|
|
// //创建新的任务
|
|
|
|
|
|
|
|
// String taskCode = "TR" + DateUtils.dateTimeNow();
|
|
|
|
|
|
|
|
// String transId = com.shkj.common.utils.uuid.UUID.randomUUID().toString();
|
|
|
|
|
|
|
|
// BusinTaskAddBo businTaskAddBo =new BusinTaskAddBo();
|
|
|
|
|
|
|
|
// businTaskAddBo.setTaskCode(taskCode);
|
|
|
|
|
|
|
|
// businTaskAddBo.setPlcId(businDataTask.getPlcId());
|
|
|
|
|
|
|
|
// businTaskAddBo.setTaskStatus(TaskStatusEnum.wait_put.getValue());
|
|
|
|
|
|
|
|
// businTaskAddBo.setTaskType(businDataTask.getTaskType());
|
|
|
|
|
|
|
|
// businTaskAddBo.setCreateTime(DateUtils.getNowDate());
|
|
|
|
|
|
|
|
// businTaskAddBo.setBatch(DateUtils.getDate());
|
|
|
|
|
|
|
|
// businTaskAddBo.setTransId(transId);
|
|
|
|
|
|
|
|
// businTaskAddBo.setAssociatedTasksId(id);
|
|
|
|
|
|
|
|
//// businTaskAddBo.setContainerId(businDataTask.getContainerId());
|
|
|
|
|
|
|
|
// businTaskAddBo.setTaskPath(businDataTask.getTaskPath());
|
|
|
|
|
|
|
|
// BusinDataTask newbusinDataTask = BeanUtil.toBean(businTaskAddBo, BusinDataTask.class);
|
|
|
|
|
|
|
|
// iBusinDataTaskService.insertBusinTask(newbusinDataTask);
|
|
|
|
|
|
|
|
//// businDataTask.setAssociatedTasksId(newbusinDataTask.getId().toString());
|
|
|
|
|
|
|
|
// iBusinDataTaskService.updateById(businDataTask);
|
|
|
|
|
|
|
|
// //将原任务为出货的物料与新任务绑定
|
|
|
|
|
|
|
|
// businDataTaskGoodsList.stream().forEach(
|
|
|
|
|
|
|
|
// e->{
|
|
|
|
|
|
|
|
// e.setTaskCode(newbusinDataTask.getId());
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
// );
|
|
|
|
|
|
|
|
// iBusinDataTaskGoodsService.updateBatchById(businDataTaskGoodsList);
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// taskList.add(businDataTask);
|
|
|
|
|
|
|
|
return exeBo; |
|
|
|
return exeBo; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@ -1257,7 +1196,7 @@ public class BusinDataTaskServiceImpl extends ServiceImpl<BusinDataTaskMapper, B |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public Result<Boolean> cancelTask(BusinTaskManageDistributeBo bo) { |
|
|
|
public Result<Boolean> cancelTask(BusinTaskManageDistributeBo bo) { |
|
|
|
|
|
|
|
log.info("取消任务:"+JsonUtil.toJSONString(bo)); |
|
|
|
LambdaQueryWrapper<BusinDataTask> wrapper = new LambdaQueryWrapper<BusinDataTask>() |
|
|
|
LambdaQueryWrapper<BusinDataTask> wrapper = new LambdaQueryWrapper<BusinDataTask>() |
|
|
|
.eq(BusinDataTask::getId, bo.getTaskId()).last("limit 1"); |
|
|
|
.eq(BusinDataTask::getId, bo.getTaskId()).last("limit 1"); |
|
|
|
BusinDataTask businDataTask = getOne(wrapper); |
|
|
|
BusinDataTask businDataTask = getOne(wrapper); |
|
|
|
@ -1275,7 +1214,6 @@ public class BusinDataTaskServiceImpl extends ServiceImpl<BusinDataTaskMapper, B |
|
|
|
||taskType.equals(TaskTypeEnum.empty_in.getValue()) |
|
|
|
||taskType.equals(TaskTypeEnum.empty_in.getValue()) |
|
|
|
|| taskType.equals(TaskTypeEnum.emptyCon.getValue()) |
|
|
|
|| taskType.equals(TaskTypeEnum.emptyCon.getValue()) |
|
|
|
){ |
|
|
|
){ |
|
|
|
|
|
|
|
|
|
|
|
if (baseLocation != null){ |
|
|
|
if (baseLocation != null){ |
|
|
|
baseLocation.setLocationStatus("0"); |
|
|
|
baseLocation.setLocationStatus("0"); |
|
|
|
} |
|
|
|
} |
|
|
|
@ -1292,15 +1230,16 @@ public class BusinDataTaskServiceImpl extends ServiceImpl<BusinDataTaskMapper, B |
|
|
|
baseLocation.setLocationStatus("2"); |
|
|
|
baseLocation.setLocationStatus("2"); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
List<SysStockDetail> sysStockDetails = iSysStockDetailService.queryStrockByLocation(baseLocation.getId()); |
|
|
|
|
|
|
|
for (SysStockDetail sysStockDetail : sysStockDetails) { |
|
|
|
|
|
|
|
sysStockDetail.setOutQty(0); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
iSysStockDetailService.updateBatchById(sysStockDetails); |
|
|
|
} |
|
|
|
} |
|
|
|
if (baseLocation != null){ |
|
|
|
if (baseLocation != null){ |
|
|
|
iBaseLocationService.updateById(baseLocation); |
|
|
|
iBaseLocationService.updateById(baseLocation); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return this.updateById(businDataTask) ? Result.ok() : Result.err(); |
|
|
|
return this.updateById(businDataTask) ? Result.ok() : Result.err(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
|