PC原材料调拨出库与PDA签收逻辑完善
This commit is contained in:
@@ -5,6 +5,14 @@
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class CarryMaterialInventoryInput
|
public class CarryMaterialInventoryInput
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 业务类型
|
||||||
|
/// </summary>
|
||||||
|
public string? biz_type { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 来源单据id
|
||||||
|
/// </summary>
|
||||||
|
public string? source_id { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 仓库编码
|
/// 仓库编码
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -24,6 +24,11 @@ namespace Tnb.WarehouseMgr.Entities.Dto
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 载具
|
/// 载具
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<string> carrys { get; set; }
|
public List<RawmatTransferoutstockDetailInput> carrys { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class RawmatTransferoutstockDetailInput
|
||||||
|
{
|
||||||
|
public string carry_code { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,5 +48,10 @@ public partial class WmsCarryCode
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[SugarColumn(IsIgnore = true)]
|
[SugarColumn(IsIgnore = true)]
|
||||||
public string carry_code { get; set; }
|
public string carry_code { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 签收数量
|
||||||
|
/// </summary>
|
||||||
|
[SugarColumn(IsIgnore = true)]
|
||||||
|
public decimal? sign_qty { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,77 @@
|
|||||||
|
using JNPF.Common.Contracts;
|
||||||
|
using JNPF.Common.Security;
|
||||||
|
using SqlSugar;
|
||||||
|
|
||||||
|
namespace Tnb.WarehouseMgr.Entities.Entity;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 原材料调拨出库载具表
|
||||||
|
/// </summary>
|
||||||
|
[SugarTable("wms_rawmat_transferoutstock_c")]
|
||||||
|
public partial class WmsRawmatTransferoutstockC : BaseEntity<string>
|
||||||
|
{
|
||||||
|
public WmsRawmatTransferoutstockC()
|
||||||
|
{
|
||||||
|
id = SnowflakeIdHelper.NextId();
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 原材料调拨出库单id
|
||||||
|
/// </summary>
|
||||||
|
public string? bill_id { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 载具ID
|
||||||
|
/// </summary>
|
||||||
|
public string? carry_id { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 载具编号
|
||||||
|
/// </summary>
|
||||||
|
public string? carry_code { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建用户
|
||||||
|
/// </summary>
|
||||||
|
public string? create_id { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建时间
|
||||||
|
/// </summary>
|
||||||
|
public DateTime? create_time { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 终点库位id
|
||||||
|
/// </summary>
|
||||||
|
public string? endlocation_id { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 终点库位编码
|
||||||
|
/// </summary>
|
||||||
|
public string? endlocation_code { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 起点库位id
|
||||||
|
/// </summary>
|
||||||
|
public string? startlocation_id { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 起点库位编码
|
||||||
|
/// </summary>
|
||||||
|
public string? startlocation_code { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 原材料调拨出库明细id
|
||||||
|
/// </summary>
|
||||||
|
public string? mat_bill_id { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 载具数量
|
||||||
|
/// </summary>
|
||||||
|
public decimal? qty { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 签收数量
|
||||||
|
/// </summary>
|
||||||
|
public decimal? sign_qty { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
@@ -3692,22 +3692,33 @@ namespace Tnb.WarehouseMgr
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
if (string.IsNullOrEmpty(input.biz_type))
|
||||||
|
throw new AppFriendlyException("业务类型不可为空", 500);
|
||||||
|
if (string.IsNullOrEmpty(input.source_id))
|
||||||
|
throw new AppFriendlyException("来源单据id不可为空", 500);
|
||||||
if (string.IsNullOrEmpty(input.warehouse_code))
|
if (string.IsNullOrEmpty(input.warehouse_code))
|
||||||
{
|
|
||||||
throw new AppFriendlyException("出库仓库不可为空", 500);
|
throw new AppFriendlyException("出库仓库不可为空", 500);
|
||||||
}
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(input.material_id))
|
if (string.IsNullOrEmpty(input.material_id))
|
||||||
{
|
|
||||||
throw new AppFriendlyException("物料id不可为空", 500);
|
throw new AppFriendlyException("物料id不可为空", 500);
|
||||||
}
|
|
||||||
if (string.IsNullOrEmpty(input.code_batch))
|
if (string.IsNullOrEmpty(input.code_batch))
|
||||||
{
|
|
||||||
throw new AppFriendlyException("批号不可为空", 500);
|
throw new AppFriendlyException("批号不可为空", 500);
|
||||||
}
|
|
||||||
|
|
||||||
BasWarehouse basWarehouse = await _db.Queryable<BasWarehouse>().Where(r => r.whcode == input.warehouse_code).FirstAsync();
|
BasWarehouse basWarehouse = await _db.Queryable<BasWarehouse>().Where(r => r.whcode == input.warehouse_code).FirstAsync();
|
||||||
|
|
||||||
|
// 下发数量
|
||||||
|
decimal? qty = 0;
|
||||||
|
switch (input.biz_type)
|
||||||
|
{
|
||||||
|
case WmsWareHouseConst.BIZTYPE_WmsRawmatTransferoutstock_ID:
|
||||||
|
{
|
||||||
|
WmsRawmatTransferoutstockD wmsRawmatTransferoutstockD = await _db.Queryable<WmsRawmatTransferoutstockD>().Where(r => r.id == input.source_id).FirstAsync();
|
||||||
|
if (wmsRawmatTransferoutstockD == null)
|
||||||
|
throw new AppFriendlyException($"来源单据{input.source_id}不存在", 500);
|
||||||
|
qty = wmsRawmatTransferoutstockD.qty - wmsRawmatTransferoutstockD.actual_qty;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch (basWarehouse.id)
|
switch (basWarehouse.id)
|
||||||
{
|
{
|
||||||
case WmsWareHouseConst.WAREHOUSE_YCL_ID:
|
case WmsWareHouseConst.WAREHOUSE_YCL_ID:
|
||||||
@@ -3743,23 +3754,58 @@ namespace Tnb.WarehouseMgr
|
|||||||
})
|
})
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
|
||||||
var wmsCarryCodesSum = wmsCarryCodes.GroupBy(r => new { r.carry_id, r.material_id, r.code_batch }).Select(g =>
|
|
||||||
|
var wmsCarryCodesOrderByQty = wmsCarryCodes.GroupBy(r => new { r.carry_id, r.material_id, r.code_batch })
|
||||||
|
.Select(g =>
|
||||||
|
{
|
||||||
|
var list = g.ToList();
|
||||||
|
decimal sumqty = g.Sum(r => r.qty);
|
||||||
|
|
||||||
|
var newg = new
|
||||||
|
{
|
||||||
|
carry_id = list[0].carry_id,
|
||||||
|
carry_code = list[0].carry_code,
|
||||||
|
material_id = list[0].material_id,
|
||||||
|
material_code = list[0].material_code,
|
||||||
|
material_name = list[0].material_name,
|
||||||
|
material_specification = list[0].material_specification,
|
||||||
|
barcode = list[0].barcode,
|
||||||
|
code_batch = list[0].code_batch,
|
||||||
|
qty = sumqty
|
||||||
|
};
|
||||||
|
return newg;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
bool isFindSortCarry = false;
|
||||||
|
var wmsCarryCodesSum = wmsCarryCodesOrderByQty.OrderBy(r => r.qty).Select(g =>
|
||||||
{
|
{
|
||||||
var list = g.ToList();
|
decimal sumqty = g.qty;
|
||||||
|
|
||||||
|
decimal? remainQty = qty - sumqty;
|
||||||
|
|
||||||
|
// 首次小于0则需要分拣
|
||||||
|
if (remainQty < 0 && !isFindSortCarry)
|
||||||
|
isFindSortCarry = true;
|
||||||
|
else
|
||||||
|
isFindSortCarry = false;
|
||||||
|
|
||||||
var newg = new
|
var newg = new
|
||||||
{
|
{
|
||||||
carry_id = list[0].carry_id,
|
carry_id = g.carry_id,
|
||||||
carry_code = list[0].carry_code,
|
carry_code = g.carry_code,
|
||||||
material_id = list[0].material_id,
|
material_id = g.material_id,
|
||||||
material_code = list[0].material_code,
|
material_code = g.material_code,
|
||||||
material_name = list[0].material_name,
|
material_name = g.material_name,
|
||||||
material_specification = list[0].material_specification,
|
material_specification = g.material_specification,
|
||||||
barcode = list[0].barcode,
|
barcode = g.barcode,
|
||||||
code_batch = list[0].code_batch,
|
code_batch = g.code_batch,
|
||||||
qty = g.Sum(r => r.qty)
|
qty = sumqty,
|
||||||
|
sign_qty = isFindSortCarry ? qty : sumqty,
|
||||||
|
isSortCarry = isFindSortCarry, // 是否为分拣载具
|
||||||
|
isSelect = isFindSortCarry || remainQty > 0, // 是否勾选
|
||||||
};
|
};
|
||||||
|
qty -= sumqty;
|
||||||
return newg;
|
return newg;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -379,8 +379,51 @@ namespace Tnb.WarehouseMgr
|
|||||||
throw new AppFriendlyException($"【MaterialByCarry】托盘{input.carry_code}不存在", 500);
|
throw new AppFriendlyException($"【MaterialByCarry】托盘{input.carry_code}不存在", 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WmsDistaskH wmsDistaskH = await _db.Queryable<WmsDistaskH>().Where(r => r.carry_id == wmsCarryH.id).OrderByDescending(r => r.id).FirstAsync();
|
||||||
|
if (wmsDistaskH == null)
|
||||||
|
{
|
||||||
|
throw new AppFriendlyException($"【MaterialSign】无法找到载具{input.carry_code}的执行任务", 500);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(wmsDistaskH.biz_type))
|
||||||
|
{
|
||||||
|
throw new AppFriendlyException($"【MaterialSign】载具{input.carry_code}任务{wmsDistaskH.bill_code}的业务类型异常", 500);
|
||||||
|
}
|
||||||
List<WmsCarryCode> wmsCarryCodes = _db.Queryable<WmsCarryCode>().Where(r => r.carry_id == wmsCarryH.id && r.codeqty > 0).ToList();
|
List<WmsCarryCode> wmsCarryCodes = _db.Queryable<WmsCarryCode>().Where(r => r.carry_id == wmsCarryH.id && r.codeqty > 0).ToList();
|
||||||
|
|
||||||
|
switch (wmsDistaskH.biz_type)
|
||||||
|
{
|
||||||
|
case WmsWareHouseConst.BIZTYPE_WmsRawmatTransferoutstock_ID:
|
||||||
|
{
|
||||||
|
WmsRawmatTransferoutstockC wmsRawmatTransferoutstockC = await _db.Queryable<WmsRawmatTransferoutstockC>()
|
||||||
|
.Where(r => r.mat_bill_id == wmsDistaskH.source_id && r.carry_id == wmsCarryH.id).FirstAsync();
|
||||||
|
if (wmsRawmatTransferoutstockC != null)
|
||||||
|
{
|
||||||
|
// 返回默认签收数量
|
||||||
|
if (wmsRawmatTransferoutstockC.sign_qty > 0)
|
||||||
|
{
|
||||||
|
List<WmsCarryCode> _wmsCarryCodes = wmsCarryCodes.Where(r => r.carry_id == wmsCarryH.id).ToList();
|
||||||
|
foreach (WmsCarryCode wmsCarryCode in _wmsCarryCodes)
|
||||||
|
{
|
||||||
|
wmsCarryCode.carry_code = wmsCarryH.carry_code;
|
||||||
|
if (wmsCarryCode.codeqty < wmsRawmatTransferoutstockC.sign_qty)
|
||||||
|
{
|
||||||
|
wmsCarryCode.sign_qty = wmsCarryCode.codeqty;
|
||||||
|
wmsRawmatTransferoutstockC.sign_qty -= wmsCarryCode.codeqty;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wmsCarryCode.sign_qty = wmsRawmatTransferoutstockC.sign_qty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return await ToApiResult(HttpStatusCode.OK, "成功", wmsCarryCodes);
|
return await ToApiResult(HttpStatusCode.OK, "成功", wmsCarryCodes);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|||||||
@@ -162,6 +162,7 @@ namespace Tnb.WarehouseMgr
|
|||||||
{
|
{
|
||||||
CarryCodeUnbindCodeInput carryCodeUnbindCodeInput = new CarryCodeUnbindCodeInput();
|
CarryCodeUnbindCodeInput carryCodeUnbindCodeInput = new CarryCodeUnbindCodeInput();
|
||||||
await _wmsCarryUnbindService.CarryCodeUnbindCode(carryCodeUnbindCodeInput, _db);
|
await _wmsCarryUnbindService.CarryCodeUnbindCode(carryCodeUnbindCodeInput, _db);
|
||||||
|
await _db.Updateable<WmsCarryH>().SetColumns(r => r.carry_status == "0").Where(r => r.id == wmsCarryH.id).ExecuteCommandAsync();
|
||||||
}
|
}
|
||||||
//await _db.Updateable<WmsTempCode>().SetColumns(r => r.codeqty == wmsCarryCode.codeqty)
|
//await _db.Updateable<WmsTempCode>().SetColumns(r => r.codeqty == wmsCarryCode.codeqty)
|
||||||
// .Where(r => r.barcode == wmsCarryCode.barcode).ExecuteCommandAsync();
|
// .Where(r => r.barcode == wmsCarryCode.barcode).ExecuteCommandAsync();
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ using Tnb.BasicData;
|
|||||||
using Tnb.ProductionMgr.Entities.Entity;
|
using Tnb.ProductionMgr.Entities.Entity;
|
||||||
using Tnb.WarehouseMgr.Entities.Entity;
|
using Tnb.WarehouseMgr.Entities.Entity;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
|
||||||
namespace Tnb.WarehouseMgr
|
namespace Tnb.WarehouseMgr
|
||||||
{
|
{
|
||||||
@@ -390,5 +391,9 @@ namespace Tnb.WarehouseMgr
|
|||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -96,8 +96,18 @@ namespace Tnb.WarehouseMgr
|
|||||||
WmsRawmatTransferoutstockD wmsRawmatTransferoutstockD = await _db.Queryable<WmsRawmatTransferoutstockD>().FirstAsync(it => it.id == input.source_id);
|
WmsRawmatTransferoutstockD wmsRawmatTransferoutstockD = await _db.Queryable<WmsRawmatTransferoutstockD>().FirstAsync(it => it.id == input.source_id);
|
||||||
WmsRawmatTransferoutstockH wmsRawmatTransferoutstockH = await _db.Queryable<WmsRawmatTransferoutstockH>().FirstAsync(it => it.id == wmsRawmatTransferoutstockD.bill_id);
|
WmsRawmatTransferoutstockH wmsRawmatTransferoutstockH = await _db.Queryable<WmsRawmatTransferoutstockH>().FirstAsync(it => it.id == wmsRawmatTransferoutstockD.bill_id);
|
||||||
|
|
||||||
List<WmsCarryH> items = await _db.Queryable<WmsCarryH>().Where(r => input.carrys.Contains(r.carry_code)).ToListAsync();
|
List<WmsCarryH> _items = await _db.Queryable<WmsCarryH>().Where(r => input.carrys.Select(c => c.carry_code).Contains(r.carry_code)).ToListAsync();
|
||||||
|
|
||||||
|
List<WmsCarryCode> wmsCarryCodes = await _db.Queryable<WmsCarryCode>().Where(r => _items.Select(c => c.id).Contains(r.carry_id)
|
||||||
|
&& r.material_id == wmsRawmatTransferoutstockD.matcode_id && r.code_batch == wmsRawmatTransferoutstockD.code_batch).ToListAsync();
|
||||||
|
|
||||||
|
List<WmsCarryH> items = new List<WmsCarryH>();
|
||||||
|
|
||||||
|
foreach (var carry in input.carrys.Select(c => c.carry_code))
|
||||||
|
{
|
||||||
|
items.Add(_items.Where(r => r.carry_code == carry).First());
|
||||||
|
}
|
||||||
|
|
||||||
foreach (var item in items)
|
foreach (var item in items)
|
||||||
{
|
{
|
||||||
if (item.is_lock == 1)
|
if (item.is_lock == 1)
|
||||||
@@ -111,13 +121,20 @@ namespace Tnb.WarehouseMgr
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
List<WmsCarryCode> wmsCarryCodes = await _db.Queryable<WmsCarryCode>().Where(r => items.Select(c => c.id).Contains(r.carry_id)
|
decimal? sign_qty = 0;
|
||||||
&& r.material_id == wmsRawmatTransferoutstockD.matcode_id && r.code_batch == wmsRawmatTransferoutstockD.code_batch).ToListAsync();
|
|
||||||
|
|
||||||
decimal qty = wmsCarryCodes.Sum(c => c.codeqty);
|
decimal qty = wmsCarryCodes.Sum(c => c.codeqty);
|
||||||
if (wmsRawmatTransferoutstockD.actual_qty + qty > wmsRawmatTransferoutstockD.qty)
|
if (wmsRawmatTransferoutstockD.actual_qty + qty > wmsRawmatTransferoutstockD.qty)
|
||||||
{
|
{
|
||||||
throw new AppFriendlyException($"本次出库数量{qty}已超过可出库数量{wmsRawmatTransferoutstockD.qty - wmsRawmatTransferoutstockD.actual_qty}", 500);
|
// 最后一个托盘的数量
|
||||||
|
decimal lastCarryQty = wmsCarryCodes.Where(r => r.carry_id == items[items.Count - 1].id).Sum(r => r.codeqty);
|
||||||
|
// 如果最后一个托盘数量小于超出的出库数量
|
||||||
|
if (lastCarryQty < wmsRawmatTransferoutstockD.actual_qty + qty - wmsRawmatTransferoutstockD.qty)
|
||||||
|
{
|
||||||
|
throw new AppFriendlyException($"本次出库数量{qty}已超过可出库数量{wmsRawmatTransferoutstockD.qty - wmsRawmatTransferoutstockD.actual_qty} 且无需选择{items[items.Count - 1].carry_code}", 500);
|
||||||
|
}
|
||||||
|
// 签收数量
|
||||||
|
sign_qty = lastCarryQty - (wmsRawmatTransferoutstockD.actual_qty + qty - wmsRawmatTransferoutstockD.qty);
|
||||||
}
|
}
|
||||||
|
|
||||||
await _db.Ado.BeginTranAsync();
|
await _db.Ado.BeginTranAsync();
|
||||||
@@ -145,6 +162,23 @@ namespace Tnb.WarehouseMgr
|
|||||||
throw new AppFriendlyException($@"没有可用的终点库位!请检查终点库位的锁定和占用状态", 500);
|
throw new AppFriendlyException($@"没有可用的终点库位!请检查终点库位的锁定和占用状态", 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WmsRawmatTransferoutstockC wmsRawmatTransferoutstockC = new WmsRawmatTransferoutstockC();
|
||||||
|
wmsRawmatTransferoutstockC.bill_id = wmsRawmatTransferoutstockH.id;
|
||||||
|
wmsRawmatTransferoutstockC.mat_bill_id = wmsRawmatTransferoutstockD.id;
|
||||||
|
wmsRawmatTransferoutstockC.carry_id = wmsCarryH.id;
|
||||||
|
wmsRawmatTransferoutstockC.carry_code = wmsCarryH.carry_code;
|
||||||
|
wmsRawmatTransferoutstockC.create_id = input.create_id;
|
||||||
|
wmsRawmatTransferoutstockC.create_time = DateTime.Now;
|
||||||
|
wmsRawmatTransferoutstockC.startlocation_id = startLocation.id;
|
||||||
|
wmsRawmatTransferoutstockC.startlocation_code = startLocation.location_code;
|
||||||
|
wmsRawmatTransferoutstockC.endlocation_id = endLocation.id;
|
||||||
|
wmsRawmatTransferoutstockC.endlocation_code = endLocation.location_code;
|
||||||
|
decimal carryQty = wmsCarryCodes.Where(r => r.carry_id == wmsCarryH.id).Sum(r => r.codeqty);
|
||||||
|
wmsRawmatTransferoutstockC.qty = carryQty;
|
||||||
|
wmsRawmatTransferoutstockC.sign_qty = wmsCarryH.id == items[items.Count - 1].id && sign_qty > 0 ? sign_qty : carryQty;
|
||||||
|
|
||||||
|
await _db.Insertable(wmsRawmatTransferoutstockC).ExecuteCommandAsync();
|
||||||
|
|
||||||
CommonCreatePretaskInput commonCreatePretaskInput = new CommonCreatePretaskInput();
|
CommonCreatePretaskInput commonCreatePretaskInput = new CommonCreatePretaskInput();
|
||||||
commonCreatePretaskInput.startlocation_id = startLocation.id;
|
commonCreatePretaskInput.startlocation_id = startLocation.id;
|
||||||
commonCreatePretaskInput.endlocation_id = endLocation.id;
|
commonCreatePretaskInput.endlocation_id = endLocation.id;
|
||||||
|
|||||||
Reference in New Issue
Block a user