|
|
|
@ -1,27 +1,20 @@
|
|
|
|
|
package com.op.system.service.impl;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import java.text.ParseException;
|
|
|
|
|
import java.text.SimpleDateFormat;
|
|
|
|
|
import java.time.LocalDate;
|
|
|
|
|
import java.util.*;
|
|
|
|
|
import java.util.ArrayList;
|
|
|
|
|
import java.util.Arrays;
|
|
|
|
|
import java.util.Calendar;
|
|
|
|
|
import java.util.Date;
|
|
|
|
|
import java.util.HashMap;
|
|
|
|
|
import java.util.List;
|
|
|
|
|
import java.util.Map;
|
|
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
|
|
|
|
import javax.servlet.http.HttpServletRequest;
|
|
|
|
|
import javax.validation.Validator;
|
|
|
|
|
|
|
|
|
|
import com.alibaba.fastjson2.JSONArray;
|
|
|
|
|
import com.alibaba.fastjson2.JSONObject;
|
|
|
|
|
|
|
|
|
|
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
|
|
|
|
|
import com.op.common.core.domain.R;
|
|
|
|
|
import com.op.common.core.utils.DateUtils;
|
|
|
|
|
import com.op.common.core.utils.http.HttpUtils;
|
|
|
|
|
import com.op.common.core.web.domain.AjaxResult;
|
|
|
|
|
import com.op.system.api.RemoteOpenService;
|
|
|
|
|
import com.op.system.api.domain.quality.HRInfo;
|
|
|
|
|
|
|
|
|
|
import com.op.system.domain.*;
|
|
|
|
|
import com.op.system.mapper.*;
|
|
|
|
|
import org.apache.commons.lang3.time.DateFormatUtils;
|
|
|
|
|
import org.apache.ibatis.session.ExecutorType;
|
|
|
|
|
import org.apache.ibatis.session.SqlSession;
|
|
|
|
@ -33,20 +26,41 @@ import org.springframework.beans.factory.annotation.Value;
|
|
|
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
|
|
|
import org.springframework.util.CollectionUtils;
|
|
|
|
|
import com.op.common.core.constant.UserConstants;
|
|
|
|
|
import com.op.common.core.exception.ServiceException;
|
|
|
|
|
import com.op.common.core.utils.SpringUtils;
|
|
|
|
|
import com.op.common.core.utils.StringUtils;
|
|
|
|
|
import com.op.common.core.utils.bean.BeanValidators;
|
|
|
|
|
import com.op.common.datascope.annotation.DataScope;
|
|
|
|
|
import com.op.common.security.utils.SecurityUtils;
|
|
|
|
|
import com.op.system.api.domain.SysRole;
|
|
|
|
|
import com.op.system.api.domain.SysUser;
|
|
|
|
|
import com.op.system.service.ISysConfigService;
|
|
|
|
|
import com.op.system.service.ISysUserService;
|
|
|
|
|
import org.springframework.web.context.request.RequestContextHolder;
|
|
|
|
|
import org.springframework.web.context.request.ServletRequestAttributes;
|
|
|
|
|
|
|
|
|
|
import com.alibaba.fastjson2.JSONArray;
|
|
|
|
|
import com.alibaba.fastjson2.JSONObject;
|
|
|
|
|
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
|
|
|
|
|
import com.op.common.core.constant.UserConstants;
|
|
|
|
|
import com.op.common.core.domain.R;
|
|
|
|
|
import com.op.common.core.exception.ServiceException;
|
|
|
|
|
import com.op.common.core.utils.DateUtils;
|
|
|
|
|
import com.op.common.core.utils.SpringUtils;
|
|
|
|
|
import com.op.common.core.utils.StringUtils;
|
|
|
|
|
import com.op.common.core.utils.bean.BeanValidators;
|
|
|
|
|
import com.op.common.core.utils.http.HttpUtils;
|
|
|
|
|
import com.op.common.core.web.domain.AjaxResult;
|
|
|
|
|
import com.op.common.datascope.annotation.DataScope;
|
|
|
|
|
import com.op.common.security.utils.SecurityUtils;
|
|
|
|
|
import com.op.system.api.RemoteOpenService;
|
|
|
|
|
import com.op.system.api.domain.SysRole;
|
|
|
|
|
import com.op.system.api.domain.SysUser;
|
|
|
|
|
import com.op.system.api.domain.quality.HRInfo;
|
|
|
|
|
import com.op.system.domain.MesClockRecord;
|
|
|
|
|
import com.op.system.domain.SysDatasource;
|
|
|
|
|
import com.op.system.domain.SysPost;
|
|
|
|
|
import com.op.system.domain.SysUserPost;
|
|
|
|
|
import com.op.system.domain.SysUserRole;
|
|
|
|
|
import com.op.system.mapper.MesClockRecordMapper;
|
|
|
|
|
import com.op.system.mapper.SysDatasourceMapper;
|
|
|
|
|
import com.op.system.mapper.SysPostMapper;
|
|
|
|
|
import com.op.system.mapper.SysRoleMapper;
|
|
|
|
|
import com.op.system.mapper.SysUserMapper;
|
|
|
|
|
import com.op.system.mapper.SysUserPostMapper;
|
|
|
|
|
import com.op.system.mapper.SysUserRoleMapper;
|
|
|
|
|
import com.op.system.service.ISysConfigService;
|
|
|
|
|
import com.op.system.service.ISysUserService;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 用户 业务层处理
|
|
|
|
@ -270,21 +284,23 @@ public class SysUserServiceImpl implements ISysUserService {
|
|
|
|
|
// 新增用户与角色管理
|
|
|
|
|
insertUserRole(user);
|
|
|
|
|
// 加工厂数据权限
|
|
|
|
|
//工厂号
|
|
|
|
|
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
|
|
|
|
|
// 工厂号
|
|
|
|
|
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
|
|
|
|
|
.getRequest();
|
|
|
|
|
String key = "#header.poolName";
|
|
|
|
|
user.setDeptId(Long.parseLong(request.getHeader(key.substring(8)).replace("ds_","")));
|
|
|
|
|
user.setDeptId(Long.parseLong(request.getHeader(key.substring(8)).replace("ds_", "")));
|
|
|
|
|
insertUserDB(user);
|
|
|
|
|
return rows;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void insertUserDB(SysUser user) {
|
|
|
|
|
// 新增用户与园区数据源
|
|
|
|
|
SysDatasource qo = new SysDatasource();
|
|
|
|
|
qo.setDeptId(user.getDeptId());
|
|
|
|
|
|
|
|
|
|
//先删掉
|
|
|
|
|
// 先删掉
|
|
|
|
|
sysDatasourceMapper.deletUserDB(user.getUserId().toString());
|
|
|
|
|
//再添加
|
|
|
|
|
// 再添加
|
|
|
|
|
List<SysDatasource> dbs = sysDatasourceMapper.selectDBListByDept(qo);
|
|
|
|
|
List<SysDatasource> list = new ArrayList<SysDatasource>();
|
|
|
|
|
for (SysDatasource db : dbs) {
|
|
|
|
@ -295,6 +311,7 @@ public class SysUserServiceImpl implements ISysUserService {
|
|
|
|
|
}
|
|
|
|
|
sysDatasourceMapper.batchUserDB(list);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 注册用户信息
|
|
|
|
|
*
|
|
|
|
@ -544,6 +561,7 @@ public class SysUserServiceImpl implements ISysUserService {
|
|
|
|
|
}
|
|
|
|
|
return successMsg.toString();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public List<Map<String, String>> getPoolNameList(SysUser user) {
|
|
|
|
|
return userMapper.getPoolNameList(user);
|
|
|
|
@ -552,44 +570,42 @@ public class SysUserServiceImpl implements ISysUserService {
|
|
|
|
|
@Override
|
|
|
|
|
public R syncUserInfoTask() {
|
|
|
|
|
DynamicDataSourceContextHolder.push("master");// 这是数据源的key
|
|
|
|
|
try{
|
|
|
|
|
//Date maxTime0 = userMapper.getMaxTime();
|
|
|
|
|
//if(maxTime0 != null){
|
|
|
|
|
try {
|
|
|
|
|
// Date maxTime0 = userMapper.getMaxTime();
|
|
|
|
|
// if(maxTime0 != null){
|
|
|
|
|
Calendar calendar = Calendar.getInstance();
|
|
|
|
|
//calendar.setTime(maxTime0);
|
|
|
|
|
// calendar.setTime(maxTime0);
|
|
|
|
|
calendar.add(Calendar.DAY_OF_YEAR, -1);
|
|
|
|
|
Date maxTime = calendar.getTime();
|
|
|
|
|
//Date maxTime = DateUtils.getNowDate();
|
|
|
|
|
String ymd = DateFormatUtils.format(maxTime, "yyyy-MM-dd");//yyyy-MM-dd
|
|
|
|
|
log.info("更新人力-参数:"+ ymd);
|
|
|
|
|
//AjaxResult hrR = remoteOpenService.GetHrUserInfo("2024-05-01");
|
|
|
|
|
// Date maxTime = DateUtils.getNowDate();
|
|
|
|
|
String ymd = DateFormatUtils.format(maxTime, "yyyy-MM-dd");// yyyy-MM-dd
|
|
|
|
|
log.info("更新人力-参数:" + ymd);
|
|
|
|
|
// AjaxResult hrR = remoteOpenService.GetHrUserInfo("2024-05-01");
|
|
|
|
|
AjaxResult hrR = remoteOpenService.GetHrUserInfo(ymd);
|
|
|
|
|
|
|
|
|
|
List<HRInfo> infoList = new ArrayList<>();
|
|
|
|
|
if((int)hrR.get("code")==200 && hrR.get("data")!=null){
|
|
|
|
|
infoList=JSONArray.parseArray(JSONObject.toJSONString(hrR.get("data")),HRInfo.class);
|
|
|
|
|
log.info("更新人力-结果:"+ JSONObject.toJSONString(infoList));
|
|
|
|
|
if(!CollectionUtils.isEmpty(infoList)){
|
|
|
|
|
if ((int) hrR.get("code") == 200 && hrR.get("data") != null) {
|
|
|
|
|
infoList = JSONArray.parseArray(JSONObject.toJSONString(hrR.get("data")), HRInfo.class);
|
|
|
|
|
log.info("更新人力-结果:" + JSONObject.toJSONString(infoList));
|
|
|
|
|
if (!CollectionUtils.isEmpty(infoList)) {
|
|
|
|
|
this.syncUserInfoFunc(infoList);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}else{
|
|
|
|
|
} else {
|
|
|
|
|
return R.fail("无最新需要更新的人力数据");
|
|
|
|
|
}
|
|
|
|
|
}finally {
|
|
|
|
|
} finally {
|
|
|
|
|
DynamicDataSourceContextHolder.poll();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return R.ok();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
protected int syncUserInfoFunc(List<HRInfo> dtos){
|
|
|
|
|
log.info("人力信息同步:"+ JSONObject.toJSONString(dtos));
|
|
|
|
|
protected int syncUserInfoFunc(List<HRInfo> dtos) {
|
|
|
|
|
log.info("人力信息同步:" + JSONObject.toJSONString(dtos));
|
|
|
|
|
Date nowDate = DateUtils.getNowDate();
|
|
|
|
|
String createBy = "job";
|
|
|
|
|
for(HRInfo dto:dtos){
|
|
|
|
|
for (HRInfo dto : dtos) {
|
|
|
|
|
dto.setCreateTime(nowDate);
|
|
|
|
|
dto.setCreateBy(createBy);
|
|
|
|
|
dto.setUpdateBy(createBy);
|
|
|
|
@ -597,76 +613,76 @@ public class SysUserServiceImpl implements ISysUserService {
|
|
|
|
|
|
|
|
|
|
dto.setUserName(dto.getPeWorkID());
|
|
|
|
|
dto.setNickName(dto.getPeName());
|
|
|
|
|
dto.setSex(dto.getPeSex().equals("F")?"1":"0");//1女
|
|
|
|
|
dto.setSex(dto.getPeSex().equals("F") ? "1" : "0");// 1女
|
|
|
|
|
dto.setStatus("0");
|
|
|
|
|
dto.setPeSnr(dto.getWorkCard());
|
|
|
|
|
String[] delArrays = {"30","31","32","33","99"};
|
|
|
|
|
if(Arrays.asList(delArrays).contains(dto.getPeDocStatus())){
|
|
|
|
|
String[] delArrays = { "30", "31", "32", "33", "99" };
|
|
|
|
|
if (Arrays.asList(delArrays).contains(dto.getPeDocStatus())) {
|
|
|
|
|
dto.setDelFlag("1");
|
|
|
|
|
}else{
|
|
|
|
|
} else {
|
|
|
|
|
dto.setDelFlag("0");
|
|
|
|
|
}
|
|
|
|
|
dto.setPhonenumber(dto.getPeMobilePhone());
|
|
|
|
|
dto.setPost(dto.getPoscd());
|
|
|
|
|
if(StringUtils.isNotBlank(dto.getOucod())){
|
|
|
|
|
if (StringUtils.isNotBlank(dto.getOucod())) {
|
|
|
|
|
dto.setDeptId(Long.parseLong(dto.getOucod()));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//sap返回的编码
|
|
|
|
|
// sap返回的编码
|
|
|
|
|
List<String> codes = dtos.stream().map(HRInfo::getUserName).collect(Collectors.toList());
|
|
|
|
|
//sap返回的工作中心编码-本地已存在
|
|
|
|
|
// sap返回的工作中心编码-本地已存在
|
|
|
|
|
List<String> exsitCodes = userMapper.getExsitCodes(codes);
|
|
|
|
|
//sap返回的工作中心编码-本地不存在// 差集 (list2 - list1)
|
|
|
|
|
List<String> noExsitCodes = codes.stream().filter(item -> !exsitCodes.contains(item)).collect(Collectors.toList());
|
|
|
|
|
|
|
|
|
|
List<HRInfo> updates = dtos.stream()
|
|
|
|
|
.filter(item -> exsitCodes.contains(item.getUserName()))
|
|
|
|
|
// sap返回的工作中心编码-本地不存在// 差集 (list2 - list1)
|
|
|
|
|
List<String> noExsitCodes = codes.stream().filter(item -> !exsitCodes.contains(item))
|
|
|
|
|
.collect(Collectors.toList());
|
|
|
|
|
|
|
|
|
|
if(!CollectionUtils.isEmpty(updates)){
|
|
|
|
|
List<HRInfo> updates = dtos.stream().filter(item -> exsitCodes.contains(item.getUserName()))
|
|
|
|
|
.collect(Collectors.toList());
|
|
|
|
|
|
|
|
|
|
if (!CollectionUtils.isEmpty(updates)) {
|
|
|
|
|
int allsize = updates.size();
|
|
|
|
|
int inserttimes = allsize/100+1;
|
|
|
|
|
for(int m=0;m<inserttimes;m++){
|
|
|
|
|
int inserttimes = allsize / 100 + 1;
|
|
|
|
|
for (int m = 0; m < inserttimes; m++) {
|
|
|
|
|
List<HRInfo> everyList;
|
|
|
|
|
if(m<(inserttimes-1)){
|
|
|
|
|
everyList = updates.subList(m*100,(m+1)*100);
|
|
|
|
|
}else{
|
|
|
|
|
everyList = updates.subList(m*100,allsize);
|
|
|
|
|
if (m < (inserttimes - 1)) {
|
|
|
|
|
everyList = updates.subList(m * 100, (m + 1) * 100);
|
|
|
|
|
} else {
|
|
|
|
|
everyList = updates.subList(m * 100, allsize);
|
|
|
|
|
}
|
|
|
|
|
if(everyList.size()>0){
|
|
|
|
|
if (everyList.size() > 0) {
|
|
|
|
|
int snum = userMapper.updateUserBatchs(everyList);
|
|
|
|
|
if(snum == 1){
|
|
|
|
|
log.info("人员编辑成功条数:"+ everyList.size());
|
|
|
|
|
}else{
|
|
|
|
|
log.info("人员编辑失败条数:"+ everyList.size());
|
|
|
|
|
if (snum == 1) {
|
|
|
|
|
log.info("人员编辑成功条数:" + everyList.size());
|
|
|
|
|
} else {
|
|
|
|
|
log.info("人员编辑失败条数:" + everyList.size());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
List<HRInfo> adds = dtos.stream()
|
|
|
|
|
.filter(item -> noExsitCodes.contains(item.getUserName()))
|
|
|
|
|
List<HRInfo> adds = dtos.stream().filter(item -> noExsitCodes.contains(item.getUserName()))
|
|
|
|
|
.collect(Collectors.toList());
|
|
|
|
|
|
|
|
|
|
if(!CollectionUtils.isEmpty(adds)){
|
|
|
|
|
if (!CollectionUtils.isEmpty(adds)) {
|
|
|
|
|
int allsize = adds.size();
|
|
|
|
|
int inserttimes = allsize/100+1;
|
|
|
|
|
for(int m=0;m<inserttimes;m++){
|
|
|
|
|
int inserttimes = allsize / 100 + 1;
|
|
|
|
|
for (int m = 0; m < inserttimes; m++) {
|
|
|
|
|
List<HRInfo> everyList;
|
|
|
|
|
if(m<(inserttimes-1)){
|
|
|
|
|
everyList = adds.subList(m*100,(m+1)*100);
|
|
|
|
|
}else{
|
|
|
|
|
everyList = adds.subList(m*100,allsize);
|
|
|
|
|
if (m < (inserttimes - 1)) {
|
|
|
|
|
everyList = adds.subList(m * 100, (m + 1) * 100);
|
|
|
|
|
} else {
|
|
|
|
|
everyList = adds.subList(m * 100, allsize);
|
|
|
|
|
}
|
|
|
|
|
if(everyList.size()>0){
|
|
|
|
|
if (everyList.size() > 0) {
|
|
|
|
|
int nnum = userMapper.addUserBatchs(everyList);
|
|
|
|
|
log.info("人员新增成功条数:"+ nnum);
|
|
|
|
|
log.info("人员新增成功条数:" + nnum);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public R syncClockInRecord() {
|
|
|
|
|
|
|
|
|
@ -674,14 +690,14 @@ public class SysUserServiceImpl implements ISysUserService {
|
|
|
|
|
|
|
|
|
|
DynamicDataSourceContextHolder.push("ds_1000");
|
|
|
|
|
// 调用 sendPost 方法(确保此方法内部使用 POST 方法发送数据)
|
|
|
|
|
Map param=new HashMap();
|
|
|
|
|
Map param = new HashMap();
|
|
|
|
|
LocalDate yesterdayDate = LocalDate.now().minusDays(1);
|
|
|
|
|
param.put("day",yesterdayDate);
|
|
|
|
|
param.put("day", yesterdayDate);
|
|
|
|
|
String result = HttpUtils.sendPostForm(attendanceRecordUrl, param);
|
|
|
|
|
List<MesClockRecord> mesClockRecordList =JSONArray.parseArray(result,MesClockRecord.class);
|
|
|
|
|
List<MesClockRecord> mesClockRecordList = JSONArray.parseArray(result, MesClockRecord.class);
|
|
|
|
|
SimpleDateFormat sdfs = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
|
|
|
|
List<MesClockRecord> clockRecordList = mesClockRecordList.stream().map(mesClockRecord -> {
|
|
|
|
|
String ClockTime=mesClockRecord.getDay()+ " " +mesClockRecord.getTime();
|
|
|
|
|
String ClockTime = mesClockRecord.getDay() + " " + mesClockRecord.getTime();
|
|
|
|
|
try {
|
|
|
|
|
Date clockTime = sdfs.parse(ClockTime);
|
|
|
|
|
mesClockRecord.setClockTime(clockTime);
|
|
|
|
@ -694,39 +710,36 @@ public class SysUserServiceImpl implements ISysUserService {
|
|
|
|
|
batchInsert(clockRecordList);
|
|
|
|
|
System.out.println("服务器响应: " + clockRecordList);
|
|
|
|
|
return R.ok(result);
|
|
|
|
|
}catch (Exception e) {
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
return R.fail(e.getMessage());
|
|
|
|
|
}finally {
|
|
|
|
|
} finally {
|
|
|
|
|
DynamicDataSourceContextHolder.poll();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Autowired // 关键:注入 SqlSessionFactory
|
|
|
|
|
private SqlSessionFactory sqlSessionFactory;
|
|
|
|
|
|
|
|
|
|
public void batchInsert(List<MesClockRecord> records) {
|
|
|
|
|
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
|
|
|
|
|
try {
|
|
|
|
|
MesClockRecordMapper mapper = sqlSession.getMapper(MesClockRecordMapper.class);
|
|
|
|
|
int batchSize = 500;
|
|
|
|
|
for (int i = 0; i < records.size(); i += batchSize) {
|
|
|
|
|
int end = Math.min(i + batchSize, records.size());
|
|
|
|
|
List<MesClockRecord> subList = records.subList(i, end);
|
|
|
|
|
mapper.insertMesClockRecordList(subList);
|
|
|
|
|
sqlSession.flushStatements(); // 批处理执行
|
|
|
|
|
}
|
|
|
|
|
sqlSession.commit(); // 提交事务
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
sqlSession.rollback();
|
|
|
|
|
throw new RuntimeException("批量插入失败", e);
|
|
|
|
|
} finally {
|
|
|
|
|
sqlSession.close();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void batchInsert(List<MesClockRecord> records) {
|
|
|
|
|
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
|
|
|
|
|
try {
|
|
|
|
|
MesClockRecordMapper mapper = sqlSession.getMapper(MesClockRecordMapper.class);
|
|
|
|
|
int batchSize = 500;
|
|
|
|
|
for (int i = 0; i < records.size(); i += batchSize) {
|
|
|
|
|
int end = Math.min(i + batchSize, records.size());
|
|
|
|
|
List<MesClockRecord> subList = records.subList(i, end);
|
|
|
|
|
mapper.insertMesClockRecordList(subList);
|
|
|
|
|
sqlSession.flushStatements(); // 批处理执行
|
|
|
|
|
}
|
|
|
|
|
sqlSession.commit(); // 提交事务
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
sqlSession.rollback();
|
|
|
|
|
throw new RuntimeException("批量插入失败", e);
|
|
|
|
|
} finally {
|
|
|
|
|
sqlSession.close();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|