完善代码
This commit is contained in:
@@ -1,11 +1,9 @@
|
||||
package org.nl.wms.ext.acs.service.impl;
|
||||
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@@ -17,7 +15,6 @@ import org.nl.utils.SpringContextHolder;
|
||||
import org.nl.wms.ext.acs.service.AcsToWmsService;
|
||||
import org.nl.wms.pdm.service.DeviceService;
|
||||
import org.nl.wms.pdm.service.dto.DeviceDto;
|
||||
import org.nl.wms.sch.manage.AbstractAcsTask;
|
||||
import org.nl.wms.sch.manage.TaskStatusEnum;
|
||||
import org.nl.wms.sch.service.PointService;
|
||||
import org.nl.wms.sch.service.TaskService;
|
||||
|
||||
@@ -13,6 +13,7 @@ import org.nl.wms.basedata.master.service.StoragevehicleinfoService;
|
||||
import org.nl.wms.basedata.master.service.dto.StoragevehicleinfoDto;
|
||||
import org.nl.wms.ext.acs.service.AcsToWmsService;
|
||||
import org.nl.wms.pda.emptyandqty.service.EmptyAndQtyService;
|
||||
import org.nl.wms.sch.manage.TaskStatusEnum;
|
||||
import org.nl.wql.core.bean.WQLObject;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
@@ -53,9 +54,16 @@ public class EmptyAndQtyServiceImpl implements EmptyAndQtyService {
|
||||
JSONObject point = pointTable
|
||||
.query("point_id = " + pointId)
|
||||
.uniqueResult(0);
|
||||
if (!StrUtil.equals(point.getString("lock_type"), "00")) {
|
||||
|
||||
// 判断点位是否有为完成的指令
|
||||
String pointCode = point.getString("point_code");
|
||||
JSONObject task = WQLObject
|
||||
.getWQLObject("sch_base_task")
|
||||
.query("(start_point_code = '" + pointCode + "' OR next_point_code = '" + pointCode + "') AND is_delete = '0' AND task_status <> '" + TaskStatusEnum.FINISHED.getCode() + "'")
|
||||
.uniqueResult(0);
|
||||
if (ObjectUtil.isNotEmpty(task)) {
|
||||
resultJSON.put("code", "0");
|
||||
resultJSON.put("desc", "当前点位已被锁定,请等待AGV任务完成");
|
||||
resultJSON.put("desc", "当前点位存在未完成的指令");
|
||||
return resultJSON;
|
||||
}
|
||||
|
||||
@@ -63,13 +71,28 @@ public class EmptyAndQtyServiceImpl implements EmptyAndQtyService {
|
||||
point.put("point_status", pointStatus);
|
||||
pointTable.update(point);
|
||||
|
||||
if (StrUtil.equals(pointStatus, "03")) {
|
||||
// 如果是有料桶,则需要修改库存表
|
||||
JSONObject struct = new JSONObject();
|
||||
struct.put("quality_scode", qualityScode);
|
||||
WQLObject
|
||||
.getWQLObject("st_ivt_structivt")
|
||||
.update(struct, "struct_id = " + pointId);
|
||||
if (StrUtil.equals(pointStatus, "03") && StrUtil.equals(point.getString("point_type"), "01")) {
|
||||
// 如果是有料桶且是仓位(待检区),则需要修改库存表
|
||||
WQLObject structTable = WQLObject.getWQLObject("st_ivt_structivt");
|
||||
JSONObject struct = structTable
|
||||
.query("struct_id = " + pointId)
|
||||
.uniqueResult(0);
|
||||
|
||||
if (ObjectUtil.isEmpty(struct)) {
|
||||
// 当前库存为空,则添加库存
|
||||
struct = new JSONObject();
|
||||
struct.put("stockrecord_id", IdUtil.getSnowflake(1L, 1L).nextId());
|
||||
struct.put("struct_id", pointId);
|
||||
struct.put("struct_code", point.get("point_code"));
|
||||
struct.put("struct_name", point.get("point_name"));
|
||||
struct.put("region_id", point.get("region_id"));
|
||||
struct.put("quality_scode", qualityScode);
|
||||
structTable.insert(struct);
|
||||
} else {
|
||||
// 当前存在库存,则更新库存
|
||||
struct.put("quality_scode", qualityScode);
|
||||
structTable.update(struct);
|
||||
}
|
||||
}
|
||||
|
||||
// 返回
|
||||
|
||||
@@ -23,17 +23,22 @@ public class SendMaterialController {
|
||||
|
||||
private final SendMaterialService sendMaterialService;
|
||||
|
||||
/**
|
||||
* 查询区域点位
|
||||
*
|
||||
* @return 双层数组,外层区域,内层点位
|
||||
*/
|
||||
@PostMapping("/queryPoint")
|
||||
@Log("查询区域点位")
|
||||
@ApiOperation("查询区域点位")
|
||||
public ResponseEntity<Object> queryPoint() {
|
||||
public ResponseEntity<JSONObject> queryPoint() {
|
||||
return new ResponseEntity<>(sendMaterialService.queryPoint(), HttpStatus.OK);
|
||||
}
|
||||
|
||||
@PostMapping("/confirm")
|
||||
@Log("送料确定")
|
||||
@ApiOperation("送料确定")
|
||||
public ResponseEntity<Object> confirm(@RequestBody JSONObject whereJson) {
|
||||
public ResponseEntity<JSONObject> confirm(@RequestBody JSONObject whereJson) {
|
||||
return new ResponseEntity<>(sendMaterialService.confirm(whereJson), HttpStatus.OK);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,13 +5,15 @@ import com.alibaba.fastjson.JSONObject;
|
||||
public interface SendMaterialService {
|
||||
|
||||
/**
|
||||
* 查询区域点位
|
||||
* @return JSONObject
|
||||
* 查询区域点位
|
||||
*
|
||||
* @return 双层数组,外层区域,内层点位
|
||||
*/
|
||||
JSONObject queryPoint();
|
||||
|
||||
/**
|
||||
* 送料确定
|
||||
* 送料确定
|
||||
*
|
||||
* @param whereJson /
|
||||
* @return JSONObject
|
||||
*/
|
||||
|
||||
@@ -9,6 +9,7 @@ import org.nl.wms.ext.acs.service.AcsToWmsService;
|
||||
import org.nl.wms.pda.sendmaterial.service.SendMaterialService;
|
||||
import org.nl.wql.WQL;
|
||||
import org.nl.wql.core.bean.WQLObject;
|
||||
import org.nl.wql.core.engine.object.WO;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@@ -21,21 +22,31 @@ public class SendMaterialServiceImpl implements SendMaterialService {
|
||||
|
||||
@Override
|
||||
public JSONObject queryPoint() {
|
||||
JSONObject result = new JSONObject();
|
||||
// 1.查询区域:豪凯区域 HKQY01、共挤区域 GJQY01
|
||||
JSONArray regionArr = WQL.getWO("PDA_SENDMATERIAL_01").addParam("flag", "1").process().getResultJSONArray(0);
|
||||
// 2.根据区域查询对应的物料上料位
|
||||
JSONObject resultJson = new JSONObject();
|
||||
for (int i = 0; i < regionArr.size(); i++) {
|
||||
JSONObject jsonRegion = regionArr.getJSONObject(i);
|
||||
JSONArray pointArr = WQL.getWO("PDA_SENDMATERIAL_01").addParam("flag", "2").addParam("region_id", jsonRegion.getString("region_id")).process().getResultJSONArray(0);
|
||||
jsonRegion.put("pointArr", pointArr);
|
||||
// 返回值
|
||||
JSONObject resultJSON = new JSONObject();
|
||||
|
||||
// 查询所有区域
|
||||
WO wo = WQL.getWO("PDA_SENDMATERIAL_01");
|
||||
JSONArray result = wo
|
||||
.addParam("flag", "1")
|
||||
.process()
|
||||
.getResultJSONArray(0);
|
||||
|
||||
// 遍历所有区域查询区域下的点位
|
||||
for (Object r : result) {
|
||||
JSONObject region = (JSONObject) r;
|
||||
JSONArray pointArr = wo
|
||||
.addParam("flag", "2")
|
||||
.addParam("region_id", region.getString("region_id"))
|
||||
.process()
|
||||
.getResultJSONArray(0);
|
||||
region.put("pointArr", pointArr);
|
||||
}
|
||||
resultJson.put("regionja", regionArr);
|
||||
result.put("result", resultJson);
|
||||
result.put("code", "1");
|
||||
result.put("desc", "查询成功");
|
||||
return result;
|
||||
|
||||
resultJSON.put("result", result);
|
||||
resultJSON.put("code", "1");
|
||||
resultJSON.put("desc", "查询成功");
|
||||
return resultJSON;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -40,38 +40,32 @@
|
||||
|
||||
IF 输入.flag = "1"
|
||||
QUERY
|
||||
SELECT
|
||||
region_id,
|
||||
region_code,
|
||||
region_name
|
||||
FROM
|
||||
sch_base_region
|
||||
WHERE
|
||||
is_used = '1'
|
||||
AND region_code in ('HKQY01','GJQY01')
|
||||
|
||||
SELECT
|
||||
region_id,
|
||||
region_code,
|
||||
region_name
|
||||
FROM
|
||||
sch_base_region
|
||||
WHERE
|
||||
is_used = '1'
|
||||
ENDSELECT
|
||||
ENDQUERY
|
||||
ENDIF
|
||||
|
||||
IF 输入.flag = "2"
|
||||
QUERY
|
||||
SELECT
|
||||
point_id,
|
||||
point_code,
|
||||
point_name
|
||||
FROM
|
||||
sch_base_point
|
||||
WHERE
|
||||
is_used = '1'
|
||||
AND is_delete = '0'
|
||||
AND is_host = '0'
|
||||
AND device_point_type = '2'
|
||||
|
||||
SELECT
|
||||
point_id,
|
||||
point_code,
|
||||
point_name
|
||||
FROM
|
||||
sch_base_point
|
||||
WHERE
|
||||
is_used = '1'
|
||||
AND is_delete = '0'
|
||||
OPTION 输入.region_id <> ""
|
||||
region_id = 输入.region_id
|
||||
ENDOPTION
|
||||
|
||||
ENDSELECT
|
||||
ENDQUERY
|
||||
ENDIF
|
||||
@@ -188,10 +188,11 @@ public class TaskServiceImpl implements TaskService {
|
||||
JSONObject result = (JSONObject) m.invoke(obj, task_id);
|
||||
if (ObjectUtil.isEmpty(result)) return;
|
||||
|
||||
// 路由不通的情况
|
||||
if (result.getInteger("status") != 200) {
|
||||
log.error(result.getString("message"));
|
||||
throw new BadRequestException("该起点不能送到该终点!");
|
||||
// 报错的情况
|
||||
if (!StrUtil.equals(result.getString("status"), "200")) {
|
||||
String resultMessage = result.getString("message");
|
||||
log.error(resultMessage);
|
||||
throw new BadRequestException(resultMessage);
|
||||
}
|
||||
|
||||
JSONArray arr = result.getJSONArray("errArr");
|
||||
|
||||
@@ -60,12 +60,12 @@ public class SendMaterialTask extends AbstractAcsTask {
|
||||
jsonTask.put("update_time", DateUtil.now());
|
||||
jsonTask.put("car_no", taskObj.getString("car_no"));
|
||||
taskTab.update(jsonTask);
|
||||
HashMap map = new HashMap();
|
||||
map.put("update_optid", SecurityUtils.getCurrentUserId());
|
||||
map.put("update_optname", SecurityUtils.getNickName());
|
||||
map.put("update_time", DateUtil.now());
|
||||
map.put("bill_status", "40");
|
||||
WQLObject.getWQLObject("ST_IVT_regionIO").update(map, "task_id='" + jsonTask.getString("task_id") + "'");
|
||||
// HashMap map = new HashMap();
|
||||
// map.put("update_optid", SecurityUtils.getCurrentUserId());
|
||||
// map.put("update_optname", SecurityUtils.getNickName());
|
||||
// map.put("update_time", DateUtil.now());
|
||||
// map.put("bill_status", "40");
|
||||
// WQLObject.getWQLObject("ST_IVT_regionIO").update(map, "task_id='" + jsonTask.getString("task_id") + "'");
|
||||
}
|
||||
|
||||
if (TaskStatusEnum.FINISHED.getCode().equals(status)) {
|
||||
@@ -75,15 +75,15 @@ public class SendMaterialTask extends AbstractAcsTask {
|
||||
jsonTask.put("update_time", DateUtil.now());
|
||||
jsonTask.put("remark", "任务执行完成");
|
||||
///审核单据 增加库存 改变出入库表的状态
|
||||
WQLObject mstTab = WQLObject.getWQLObject("ST_IVT_regionIO");
|
||||
JSONObject mstObj = mstTab.query("task_id='" + task_id + "' and is_delete='0'").uniqueResult(0);
|
||||
// WQLObject mstTab = WQLObject.getWQLObject("ST_IVT_regionIO");
|
||||
// JSONObject mstObj = mstTab.query("task_id='" + task_id + "' and is_delete='0'").uniqueResult(0);
|
||||
//审核 加库存可和用数量
|
||||
// StoreIvtServiceImpl ivtService = new StoreIvtServiceImpl();
|
||||
mstObj.put("bill_status", "50");
|
||||
mstObj.put("confirm_optid", SecurityUtils.getCurrentUserId());
|
||||
mstObj.put("confirm_optname", SecurityUtils.getNickName());
|
||||
mstObj.put("confirm_time", DateUtil.now());
|
||||
mstTab.update(mstObj);
|
||||
// mstObj.put("bill_status", "50");
|
||||
// mstObj.put("confirm_optid", SecurityUtils.getCurrentUserId());
|
||||
// mstObj.put("confirm_optname", SecurityUtils.getNickName());
|
||||
// mstObj.put("confirm_time", DateUtil.now());
|
||||
// mstTab.update(mstObj);
|
||||
|
||||
// String iostorinv_id = mstObj.getString("iostorinv_id");
|
||||
// String bill_code = mstObj.getString("bill_code");
|
||||
@@ -115,8 +115,13 @@ public class SendMaterialTask extends AbstractAcsTask {
|
||||
throw new BadRequestException("未找到可用点位:" + start_point_code);
|
||||
}
|
||||
|
||||
// 如果终点区域为待检区,则需要添加库存
|
||||
if (nextPointDto.getRegion_id().equals(1572481855792484352L)) {
|
||||
// 如果起点是仓位(待检区),则需要删除库存
|
||||
if (StrUtil.equals(startPointDto.getPoint_type(), "01")) {
|
||||
WQLObject.getWQLObject("st_ivt_structivt").delete("struct_id = " + startPointDto.getPoint_id());
|
||||
}
|
||||
|
||||
// 如果终点为仓位(待检区),则需要添加库存
|
||||
if (StrUtil.equals(nextPointDto.getPoint_type(), "01")) {
|
||||
JSONObject struct = new JSONObject();
|
||||
struct.put("stockrecord_id", IdUtil.getSnowflake(1, 1).nextId());
|
||||
struct.put("struct_id", nextPointDto.getPoint_id());
|
||||
@@ -130,15 +135,13 @@ public class SendMaterialTask extends AbstractAcsTask {
|
||||
|
||||
// param.put("struct_id", nextPointDto.getPoint_id());
|
||||
// ivtService.addIvtFlow(param, IvtChangeTypeEnum.ADD_IVT_AND_CAN_USE);
|
||||
// 解锁点位 将起点的点位状态写给终点
|
||||
// 将起点的点位状态写给终点
|
||||
WQLObject pointTab = WQLObject.getWQLObject("sch_base_point");
|
||||
JSONObject startPointObj = pointTab.query("point_code='" + start_point_code + "'").uniqueResult(0);
|
||||
JSONObject endPointObj = pointTab.query("point_code='" + next_point_code + "'").uniqueResult(0);
|
||||
|
||||
// 起点写给终点
|
||||
endPointObj.put("lock_type", "00");
|
||||
String pointStatus = startPointObj.getString("point_status");
|
||||
endPointObj.put("point_status", pointStatus);
|
||||
endPointObj.put("point_status", startPointObj.getString("point_status"));
|
||||
pointTab.update(endPointObj);
|
||||
|
||||
// 起点置空
|
||||
@@ -147,6 +150,9 @@ public class SendMaterialTask extends AbstractAcsTask {
|
||||
pointTab.update(startPointObj);
|
||||
|
||||
// 更新任务
|
||||
jsonTask.put("update_optid", SecurityUtils.getCurrentUserId());
|
||||
jsonTask.put("update_optname", SecurityUtils.getNickName());
|
||||
jsonTask.put("update_time", DateUtil.now());
|
||||
taskTab.update(jsonTask);
|
||||
}
|
||||
|
||||
@@ -202,54 +208,76 @@ public class SendMaterialTask extends AbstractAcsTask {
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public String createTask(JSONObject form) {
|
||||
//请求参数 载具、起点、终点
|
||||
// 参数校验
|
||||
String start_point_code = form.getString("start_point_code");
|
||||
String next_point_code = form.getString("next_point_code");;
|
||||
|
||||
WQLObject taskTable = WQLObject.getWQLObject("SCH_BASE_Task");
|
||||
|
||||
|
||||
if (StrUtil.isEmpty(start_point_code)) {
|
||||
throw new BadRequestException("起点不能为空!");
|
||||
}
|
||||
String next_point_code = form.getString("next_point_code");
|
||||
if (StrUtil.isEmpty(next_point_code)) {
|
||||
throw new BadRequestException("终点不能为空!");
|
||||
}
|
||||
|
||||
WQLObject taskTable = WQLObject.getWQLObject("SCH_BASE_Task");
|
||||
|
||||
PointService pointService = SpringContextHolder.getBean(PointService.class);
|
||||
|
||||
// 起点是空位不能搬
|
||||
PointDto startPoint = pointService.findByCode(start_point_code);
|
||||
if (StrUtil.equals(startPoint.getPoint_status(), "00")) {
|
||||
throw new BadRequestException("起点是空位!");
|
||||
}
|
||||
|
||||
// 终点不是不合格品区且不是空位不能搬
|
||||
// 终点不是空位不能搬
|
||||
PointDto nextPoint = pointService.findByCode(next_point_code);
|
||||
if (!nextPoint.getRegion_id().equals(1572481902244401152L) && !StrUtil.equals(nextPoint.getPoint_status(), "00")) {
|
||||
if (!StrUtil.equals(nextPoint.getPoint_status(), "00")) {
|
||||
throw new BadRequestException("终点不是空位!");
|
||||
}
|
||||
|
||||
//判断起点有没有未完成的指令
|
||||
JSONObject beforTaskObj = taskTable.
|
||||
query("is_delete='0' and start_point_code='" + start_point_code + "' and task_status <>'" + TaskStatusEnum.FINISHED.getCode() + "'")
|
||||
// 判断起点有没有未完成的指令
|
||||
JSONObject startPointTask = taskTable
|
||||
.query("(start_point_code = '" + start_point_code + "' OR next_point_code = '" + start_point_code + "') AND is_delete = '0' AND task_status <> '" + TaskStatusEnum.FINISHED.getCode() + "'")
|
||||
.uniqueResult(0);
|
||||
if (ObjectUtil.isNotEmpty(beforTaskObj)) {
|
||||
throw new BadRequestException("起点存在指令号为'" + beforTaskObj.getString("task_code") + "' 未完成!");
|
||||
if (ObjectUtil.isNotEmpty(startPointTask)) {
|
||||
throw new BadRequestException("起点存在指令号为'" + startPointTask.getString("task_code") + "'未完成!");
|
||||
}
|
||||
|
||||
WQLObject pointTable = WQLObject.getWQLObject("sch_base_point");
|
||||
// 判断起点有没有未完成的指令
|
||||
JSONObject nextPointTask = taskTable
|
||||
.query("(start_point_code = '" + next_point_code + "' OR next_point_code = '" + next_point_code + "') AND is_delete = '0' AND task_status <> '" + TaskStatusEnum.FINISHED.getCode() + "'")
|
||||
.uniqueResult(0);
|
||||
if (ObjectUtil.isNotEmpty(nextPointTask)) {
|
||||
throw new BadRequestException("终点存在指令号为'" + nextPointTask.getString("task_code") + "'未完成!");
|
||||
}
|
||||
|
||||
//终点点加锁
|
||||
JSONObject endPointObj = pointTable.query("point_code='" + next_point_code + "'").uniqueResult(0);
|
||||
endPointObj.put("lock_type", "01");
|
||||
pointTable.update(endPointObj);
|
||||
if (StrUtil.equals(startPoint.getPoint_status(), "03") && StrUtil.equals(startPoint.getPoint_type(), "01")) {
|
||||
// 如果起点有料桶且是仓位(待检区),需要判断质量
|
||||
String qualityScode = WQLObject
|
||||
.getWQLObject("st_ivt_structivt")
|
||||
.query("struct_id = " + startPoint.getPoint_id())
|
||||
.uniqueResult(0)
|
||||
.getString("quality_scode");
|
||||
|
||||
if (StrUtil.equals(qualityScode, "00")) {
|
||||
// 未检品不能送
|
||||
throw new BadRequestException("待检品不能搬运");
|
||||
}
|
||||
if (StrUtil.equals(qualityScode, "01") && nextPoint.getPoint_code().startsWith("BHG")) {
|
||||
// 合格品不能送到不合格品间
|
||||
throw new BadRequestException("合格品不能送到不合格品间");
|
||||
}
|
||||
if (StrUtil.equals(qualityScode, "02") && nextPoint.getPoint_code().startsWith("TL")) {
|
||||
// 不合格品不能送到投料站
|
||||
throw new BadRequestException("不合格品不能送到投料站");
|
||||
}
|
||||
}
|
||||
|
||||
// 创建任务
|
||||
JSONObject taskObj = new JSONObject();
|
||||
CodeUtil.getNewCode("TASK_CODE");
|
||||
String task_id = IdUtil.getSnowflake(1, 1).nextId() + "";
|
||||
taskObj.put("task_id", task_id);
|
||||
taskObj.put("taskdtl_id", task_id);
|
||||
String taskId = IdUtil.getSnowflake(1, 1).nextId() + "";
|
||||
taskObj.put("task_id", taskId);
|
||||
taskObj.put("taskdtl_id", taskId);
|
||||
taskObj.put("task_code", CodeUtil.getNewCode("TASK_CODE"));
|
||||
taskObj.put("task_type", "01");
|
||||
taskObj.put("taskdtl_type", "01");
|
||||
@@ -267,7 +295,19 @@ public class SendMaterialTask extends AbstractAcsTask {
|
||||
taskObj.put("create_time", DateUtil.now());
|
||||
taskObj.put("is_delete", "0");
|
||||
taskTable.insert(taskObj);
|
||||
return task_id;
|
||||
|
||||
// 下发任务
|
||||
JSONObject ACSResult = renotifyAcs(taskId);
|
||||
|
||||
if (!StrUtil.equals(ACSResult.getString("status"), "200")) {
|
||||
// 报错后删除任务
|
||||
taskTable.delete("task_id = " + taskId);
|
||||
|
||||
String resultMessage = ACSResult.getString("message");
|
||||
throw new BadRequestException(resultMessage);
|
||||
}
|
||||
|
||||
return taskId;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -192,7 +192,6 @@ public class RegionioInServiceImpl implements RegionioInService {
|
||||
String iostorinv_id = jsonObject.getString("iostorinv_id");
|
||||
|
||||
WQLObject wo = WQLObject.getWQLObject("ST_IVT_regionIO");
|
||||
WQLObject orderTab = WQLObject.getWQLObject("mps_bd_produceshiftorder");
|
||||
|
||||
JSONObject jsonIn = wo.query("iostorinv_id = '" + iostorinv_id + "'").uniqueResult(0);
|
||||
String start_point_code = jsonIn.getString("start_point_code");
|
||||
|
||||
Reference in New Issue
Block a user