Update
This commit is contained in:
parent
8890cba87e
commit
45afdec610
@ -66,7 +66,6 @@
|
|||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<h3 class="card-title">Report Inquiry</h3>
|
<h3 class="card-title">Report Inquiry</h3>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div v-if="reportData">
|
<div v-if="reportData">
|
||||||
<div class="row justify-content-center">
|
<div class="row justify-content-center">
|
||||||
@ -86,13 +85,6 @@
|
|||||||
<div class=""><button class="btn btn-danger" v-on:click="selectedMonth = null">Clear</button></div>
|
<div class=""><button class="btn btn-danger" v-on:click="selectedMonth = null">Clear</button></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-3">
|
|
||||||
<div class="row col-10">
|
|
||||||
<h4>Position Filter</h4>
|
|
||||||
<multiselect v-model="selectedPosition" :options="positionList" :multiple="false" placeholder="Search Position" track-by="positionId" label="positionName"></multiselect>
|
|
||||||
<div class=""><button class="btn btn-danger" v-on:click="selectedPosition = []">Clear</button></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<button class="btn btn-primary" v-on:click="generateReport">Generate Report</button>
|
<button class="btn btn-primary" v-on:click="generateReport">Generate Report</button>
|
||||||
</div>
|
</div>
|
||||||
@ -104,9 +96,15 @@
|
|||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<button :class="['nav-link', {active: activeTab === 'userTab'}]" v-on:click="activeTab = 'userTab'">User</button>
|
<button :class="['nav-link', {active: activeTab === 'userTab'}]" v-on:click="activeTab = 'userTab'">User</button>
|
||||||
</li>
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<button :class="['nav-link', {active: activeTab === 'stationTab'}]" v-on:click="activeTab = 'stationTab'">Station</button>
|
||||||
|
</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<button :class="['nav-link', {active: activeTab === 'storeTab'}]" v-on:click="activeTab = 'storeTab'">Store</button>
|
<button :class="['nav-link', {active: activeTab === 'storeTab'}]" v-on:click="activeTab = 'storeTab'">Store</button>
|
||||||
</li>
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<button :class="['nav-link', {active: activeTab === 'allStoreTab'}]" v-on:click="activeTab = 'allStoreTab'">All Item</button>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<hr />
|
<hr />
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
@ -118,7 +116,15 @@
|
|||||||
<multiselect v-model="selectedUser" :options="formResponse.userItemBalance" :multiple="false" placeholder="Select User" track-by="userId" label="userFullName"></multiselect>
|
<multiselect v-model="selectedUser" :options="formResponse.userItemBalance" :multiple="false" placeholder="Select User" track-by="userId" label="userFullName"></multiselect>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-9">
|
<div class="col-9">
|
||||||
<table id="userItemsTable" class="display table table-bordered"></table>
|
<table id="userItemsTable" class="display table table-bordered table-hover"></table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-if="formResponse" v-show="activeTab === 'stationTab'">
|
||||||
|
<div class="col-3">
|
||||||
|
<h4>Store</h4>
|
||||||
|
</div>
|
||||||
|
<div class="col-9">
|
||||||
|
<table id="stationItemsTable" class="display table table-bordered table-hover"></table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="formResponse" v-show="activeTab === 'storeTab'">
|
<div v-if="formResponse" v-show="activeTab === 'storeTab'">
|
||||||
@ -126,7 +132,16 @@
|
|||||||
<h4>Store</h4>
|
<h4>Store</h4>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-9">
|
<div class="col-9">
|
||||||
<table id="itemsTable" class="display table table-bordered"></table>
|
<table id="storeItemsTable" class="display table table-bordered table-hover"></table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-if="formResponse" v-show="activeTab === 'allStoreTab'">
|
||||||
|
<div class="col-3">
|
||||||
|
<h4>Store</h4>
|
||||||
|
</div>
|
||||||
|
<div class="col-9">
|
||||||
|
<table id="storeAllItemsTable" class="display table table-bordered table-hover"></table>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -173,13 +188,14 @@
|
|||||||
selectedSingleDepartment: [],
|
selectedSingleDepartment: [],
|
||||||
selectedItem: [],
|
selectedItem: [],
|
||||||
selectedCategory: [],
|
selectedCategory: [],
|
||||||
selectedPosition: [],
|
|
||||||
usersInfo: [],
|
usersInfo: [],
|
||||||
submitBody: null,
|
submitBody: null,
|
||||||
formResponse: null,
|
formResponse: null,
|
||||||
selectedUser: [],
|
selectedUser: [],
|
||||||
userItemsTable: null,
|
userItemsTable: null,
|
||||||
itemsTable: null,
|
stationItemsTable: null,
|
||||||
|
storeItemsTable: null,
|
||||||
|
storeAllItemsTable: null,
|
||||||
activeTab: "userTab"
|
activeTab: "userTab"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -202,6 +218,7 @@
|
|||||||
}
|
}
|
||||||
// if (newVal && newVal.items) {
|
// if (newVal && newVal.items) {
|
||||||
const tableData = newVal?.items ? newVal.items : [];
|
const tableData = newVal?.items ? newVal.items : [];
|
||||||
|
var app = this;
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.userItemsTable = $('#userItemsTable').DataTable({
|
this.userItemsTable = $('#userItemsTable').DataTable({
|
||||||
data: tableData ,
|
data: tableData ,
|
||||||
@ -223,13 +240,18 @@
|
|||||||
</tr>`
|
</tr>`
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
"createdRow": function (row, data, dataIndex) {
|
||||||
|
$(row).on('click', function () {
|
||||||
|
app.fetchItemMovement(data.uniqueID);
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async generateReport(){
|
async generateReport(){
|
||||||
if(this.selectedMonth == null || this.selectedSingleDepartment.length == 0 || this.selectedPosition.length == 0)
|
if(this.selectedMonth == null || this.selectedSingleDepartment.length == 0)
|
||||||
{
|
{
|
||||||
var msg = [];
|
var msg = [];
|
||||||
if(this.selectedMonth == null)
|
if(this.selectedMonth == null)
|
||||||
@ -240,10 +262,6 @@
|
|||||||
{
|
{
|
||||||
msg.push("Department");
|
msg.push("Department");
|
||||||
}
|
}
|
||||||
if(this.selectedPosition.length == 0)
|
|
||||||
{
|
|
||||||
msg.push("Position");
|
|
||||||
}
|
|
||||||
alert(msg.length > 1 ? msg.join(" & ") + " cannot be empty" : msg[0] + " cannot be empty");
|
alert(msg.length > 1 ? msg.join(" & ") + " cannot be empty" : msg[0] + " cannot be empty");
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
@ -251,9 +269,6 @@
|
|||||||
formDate: new Date(this.selectedMonth.year, this.selectedMonth.month + 1, 0, 23, 59, 59).toISOString().slice(0, 19),
|
formDate: new Date(this.selectedMonth.year, this.selectedMonth.month + 1, 0, 23, 59, 59).toISOString().slice(0, 19),
|
||||||
// selectedCategory: this.selectedCategory,
|
// selectedCategory: this.selectedCategory,
|
||||||
deptId: this.selectedSingleDepartment.departmentCode,
|
deptId: this.selectedSingleDepartment.departmentCode,
|
||||||
toUser: this.selectedPosition.positionId == 1 ? 1 : 0,
|
|
||||||
toStation: this.selectedPosition.positionId == 2 ? 1 : 0,
|
|
||||||
toStore: this.selectedPosition.positionId == 3 ? 1 : 0,
|
|
||||||
}
|
}
|
||||||
this.fetchCurrentReport();
|
this.fetchCurrentReport();
|
||||||
}
|
}
|
||||||
@ -276,11 +291,14 @@
|
|||||||
this.userItemsTable = null;
|
this.userItemsTable = null;
|
||||||
this.selectedUser = null;
|
this.selectedUser = null;
|
||||||
}
|
}
|
||||||
if (this.itemsTable) {
|
if (this.stationItemsTable) {
|
||||||
this.itemsTable.clear().destroy();
|
this.stationItemsTable.clear().destroy();
|
||||||
this.itemsTable = null;
|
this.stationItemsTable = null;
|
||||||
|
}
|
||||||
|
if (this.storeItemsTable) {
|
||||||
|
this.storeItemsTable.clear().destroy();
|
||||||
|
this.storeItemsTable = null;
|
||||||
}
|
}
|
||||||
console.log(data);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
console.error(`Failed to fetch user: ${response.statusText}`);
|
console.error(`Failed to fetch user: ${response.statusText}`);
|
||||||
@ -397,10 +415,54 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
initTable() {
|
initTable() {
|
||||||
this.userItemsTable = $('#userItemsTable').DataTable();
|
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.itemsTable = $('#itemsTable').DataTable({
|
this.userItemsTable = $('#userItemsTable').DataTable();
|
||||||
data: this.formResponse.allProductInStore ,
|
const stationTableData = this.formResponse.stationItemBalance ? this.formResponse.stationItemBalance : [];
|
||||||
|
this.stationItemsTable = $('#stationItemsTable').DataTable({
|
||||||
|
data: stationTableData.items,
|
||||||
|
columns: [
|
||||||
|
{ data: 'itemName', title: 'Item Name' },
|
||||||
|
{ data: 'uniqueID', title: 'Unique ID' },
|
||||||
|
{ data: 'quantity', title: 'Quantity' },
|
||||||
|
{ data: 'itemPrice', title: 'Item Price' },
|
||||||
|
],
|
||||||
|
destroy: true,
|
||||||
|
drawCallback: function () {
|
||||||
|
const total = stationTableData.totalItemPrice;
|
||||||
|
$(this.api().table().node()).find('tbody tr.total-row').remove();
|
||||||
|
$(this.api().table().node()).find('tbody').append(
|
||||||
|
`<tr class="total-row">
|
||||||
|
<td colspan="3"><strong>Total</strong></td>
|
||||||
|
<td class="text-end"><strong>${total}</strong></td>
|
||||||
|
</tr>`
|
||||||
|
);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const storeTableData = this.formResponse.storeItemBalance ? this.formResponse.storeItemBalance : [];
|
||||||
|
this.storeItemsTable = $('#storeItemsTable').DataTable({
|
||||||
|
data: storeTableData.items,
|
||||||
|
columns: [
|
||||||
|
{ data: 'itemName', title: 'Item Name' },
|
||||||
|
{ data: 'uniqueID', title: 'Unique ID' },
|
||||||
|
{ data: 'quantity', title: 'Quantity' },
|
||||||
|
{ data: 'itemPrice', title: 'Item Price' },
|
||||||
|
|
||||||
|
],
|
||||||
|
destroy: true,
|
||||||
|
drawCallback: function () {
|
||||||
|
const total = storeTableData.totalItemPrice;
|
||||||
|
$(this.api().table().node()).find('tbody tr.total-row').remove();
|
||||||
|
$(this.api().table().node()).find('tbody').append(
|
||||||
|
`<tr class="total-row">
|
||||||
|
<td colspan="3"><strong>Total</strong></td>
|
||||||
|
<td class="text-end"><strong>${total}</strong></td>
|
||||||
|
</tr>`
|
||||||
|
);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const storeAllTableData = this.formResponse.allProductInStore ? this.formResponse.allProductInStore : [];
|
||||||
|
this.storeAllItemsTable = $('#storeAllItemsTable').DataTable({
|
||||||
|
data: storeAllTableData ,
|
||||||
columns: [
|
columns: [
|
||||||
{ data: 'productName', title: 'Item Name' },
|
{ data: 'productName', title: 'Item Name' },
|
||||||
{ data: 'quantity', title: 'Quantity' },
|
{ data: 'quantity', title: 'Quantity' },
|
||||||
@ -411,6 +473,27 @@
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
async fetchItemMovement(data){
|
||||||
|
try {
|
||||||
|
const response = await fetch(`/ReportingAPI/GetItemMovement/`, {
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
body: JSON.stringify(data),
|
||||||
|
method: 'POST',
|
||||||
|
});
|
||||||
|
if (response.ok) {
|
||||||
|
const data = await response.json();
|
||||||
|
this.itemMovement = data;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.error(`Failed to fetch item movement: ${response.statusText}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
console.error('There was a problem with the fetch operation:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
// selectedUserFunc() {
|
// selectedUserFunc() {
|
||||||
// if (this.userItemsTable) {
|
// if (this.userItemsTable) {
|
||||||
// this.userItemsTable.destroy();
|
// this.userItemsTable.destroy();
|
||||||
|
|||||||
@ -1920,8 +1920,10 @@ namespace PSTW_CentralSystem.Controllers.API.Inventory
|
|||||||
[HttpPost("UserList")]
|
[HttpPost("UserList")]
|
||||||
public async Task<IActionResult> UserList()
|
public async Task<IActionResult> UserList()
|
||||||
{
|
{
|
||||||
|
//get current user
|
||||||
var userList = await _centralDbContext.Users.Include(i => i.Department).ToListAsync();
|
var thisUser = await _userManager.GetUserAsync(User);
|
||||||
|
var thisUserDept = thisUser!.departmentId;
|
||||||
|
var userList = await _centralDbContext.Users.Include(i => i.Department).Where(i => i.departmentId == thisUserDept).ToListAsync();
|
||||||
return Json(userList.Select(i => new
|
return Json(userList.Select(i => new
|
||||||
{
|
{
|
||||||
i.Id,
|
i.Id,
|
||||||
|
|||||||
@ -38,9 +38,6 @@ namespace PSTW_CentralSystem.Controllers.API
|
|||||||
{
|
{
|
||||||
public string? FormDate { get; set; }
|
public string? FormDate { get; set; }
|
||||||
public string? DeptId { get; set; }
|
public string? DeptId { get; set; }
|
||||||
public int ToUser { get; set; }
|
|
||||||
public int ToStation { get; set; }
|
|
||||||
public int ToStore { get; set; }
|
|
||||||
}
|
}
|
||||||
#region ItemReport
|
#region ItemReport
|
||||||
|
|
||||||
@ -142,9 +139,6 @@ namespace PSTW_CentralSystem.Controllers.API
|
|||||||
{
|
{
|
||||||
string FormDate = reportQuery.FormDate!;
|
string FormDate = reportQuery.FormDate!;
|
||||||
string DeptId = reportQuery.DeptId!;
|
string DeptId = reportQuery.DeptId!;
|
||||||
int ToUser = reportQuery.ToUser;
|
|
||||||
int ToStation = reportQuery.ToStation;
|
|
||||||
int ToStore = reportQuery.ToStore;
|
|
||||||
var currentProductBalance = new List<ProductReport>();
|
var currentProductBalance = new List<ProductReport>();
|
||||||
var result = await _centralDbContext.Products
|
var result = await _centralDbContext.Products
|
||||||
.Include(p => p.Items)
|
.Include(p => p.Items)
|
||||||
@ -226,9 +220,9 @@ namespace PSTW_CentralSystem.Controllers.API
|
|||||||
.Where(s => s.Department!.DepartmentCode == DeptId)
|
.Where(s => s.Department!.DepartmentCode == DeptId)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
|
||||||
var departmentStores = await _centralDbContext.Stores
|
var departmentStores = await _centralDbContext.Departments
|
||||||
.Include(s => s.Company)
|
.Include(s => s.Company)
|
||||||
.Where(s => s.Department!.DepartmentCode == DeptId)
|
.Where(s => s.DepartmentCode == DeptId)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
|
||||||
var latestItemMovements = await _centralDbContext.ItemMovements
|
var latestItemMovements = await _centralDbContext.ItemMovements
|
||||||
@ -237,6 +231,7 @@ namespace PSTW_CentralSystem.Controllers.API
|
|||||||
.Include(m => m.NextUser)
|
.Include(m => m.NextUser)
|
||||||
.Include(m => m.NextStation)
|
.Include(m => m.NextStation)
|
||||||
.Include(m => m.NextStore)
|
.Include(m => m.NextStore)
|
||||||
|
.Where(m => m.MovementComplete == true)
|
||||||
.GroupBy(m => m.ItemId)
|
.GroupBy(m => m.ItemId)
|
||||||
.Select(g => g
|
.Select(g => g
|
||||||
.Where(m => m.Date <= parsedDate)
|
.Where(m => m.Date <= parsedDate)
|
||||||
@ -269,7 +264,7 @@ namespace PSTW_CentralSystem.Controllers.API
|
|||||||
UniqueID = m.Item.UniqueID,
|
UniqueID = m.Item.UniqueID,
|
||||||
})
|
})
|
||||||
.ToList(),
|
.ToList(),
|
||||||
TotalItemPrice = latestItemMovements.Where(m => m != null && m.ToUser == u.Id).Sum(m => m!.Item!.ConvertPrice * m.Quantity),
|
TotalItemPrice = latestItemMovements.Where(m => m != null && m.ToUser == u.Id).Select(m => m!.Item!.ConvertPrice).Sum(),
|
||||||
})
|
})
|
||||||
.Where(u => u.Items.Count > 0).ToList();
|
.Where(u => u.Items.Count > 0).ToList();
|
||||||
|
|
||||||
@ -292,15 +287,39 @@ namespace PSTW_CentralSystem.Controllers.API
|
|||||||
UniqueID = m.Item.UniqueID,
|
UniqueID = m.Item.UniqueID,
|
||||||
})
|
})
|
||||||
.ToList(),
|
.ToList(),
|
||||||
TotalItemPrice = latestItemMovements.Where(m => m != null && m.ToStation == u.StationId).Sum(m => m!.Item!.ConvertPrice * m.Quantity),
|
TotalItemPrice = latestItemMovements.Where(m => m != null && m.ToStation == u.StationId).Select(m => m!.Item!.ConvertPrice).Sum(),
|
||||||
})
|
})
|
||||||
.Where(u => u.Items.Count > 0).ToList();
|
.Where(u => u.Items.Count > 0).FirstOrDefault();
|
||||||
|
|
||||||
|
var storeItemMovements = departmentStores
|
||||||
|
.Select(u => new
|
||||||
|
{
|
||||||
|
Department = u.DepartmentName,
|
||||||
|
Items = latestStationItemMovements
|
||||||
|
.Where(m => m != null && m.ToStore > 0 && m.NextStore!.StoreName.Contains(u.DepartmentName))
|
||||||
|
.Select(m => new
|
||||||
|
{
|
||||||
|
ItemId = m!.ItemId,
|
||||||
|
ItemName = m.Item!.Product!.ProductName,
|
||||||
|
Quantity = m.Quantity,
|
||||||
|
ItemPrice = m.Item!.ConvertPrice,
|
||||||
|
PO = m.Item!.PONo,
|
||||||
|
DO = m.Item!.DONo,
|
||||||
|
SerialNumber = m.Item.SerialNumber,
|
||||||
|
UniqueID = m.Item.UniqueID,
|
||||||
|
})
|
||||||
|
.ToList(),
|
||||||
|
TotalItemPrice = latestStationItemMovements.Where(m => m != null && m.ToStore > 0 && m.NextStore!.StoreName.Contains(u.DepartmentName)).Select(m => m!.Item!.ConvertPrice).Sum(),
|
||||||
|
|
||||||
|
})
|
||||||
|
.Where(u => u.Items.Count > 0).FirstOrDefault();
|
||||||
|
|
||||||
var report = new
|
var report = new
|
||||||
{
|
{
|
||||||
allProductInStore = currentProductBalance,
|
allProductInStore = currentProductBalance,
|
||||||
userItemBalance = usersItemMovements,
|
userItemBalance = usersItemMovements,
|
||||||
stationItemBalance = stationItemMovements,
|
stationItemBalance = stationItemMovements,
|
||||||
|
storeItemBalance = storeItemMovements,
|
||||||
};
|
};
|
||||||
|
|
||||||
return Json(report);
|
return Json(report);
|
||||||
@ -311,7 +330,37 @@ namespace PSTW_CentralSystem.Controllers.API
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
#region Item Movement report
|
||||||
|
[HttpPost("GetItemMovement")]
|
||||||
|
public async Task<IActionResult> GetItemMovement([FromBody] String data)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(data))
|
||||||
|
{
|
||||||
|
return BadRequest("Invalid Unique ID");
|
||||||
|
}
|
||||||
|
|
||||||
|
var itemMovement = await _centralDbContext.ItemMovements
|
||||||
|
.Include(im => im.Item)
|
||||||
|
.Where(im => im.Item!.UniqueID == data)
|
||||||
|
.OrderByDescending(im => im.Id)
|
||||||
|
.Select(im => new
|
||||||
|
{
|
||||||
|
From = im.LastUser != null ? im.FromUser!.FullName : im.LastStation != null ? im.FromStation!.StationName : im.LastStore != null ? im.FromStore!.StoreName : null,
|
||||||
|
To = im.ToUser != null ? im.NextUser!.FullName : im.ToStation != null ? im.NextStation!.StationName : im.ToStore != null ? im.NextStore!.StoreName : null,
|
||||||
|
Date = im.Date,
|
||||||
|
MovementStatus = im.MovementComplete
|
||||||
|
})
|
||||||
|
.ToListAsync();
|
||||||
|
return Json(itemMovement);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return BadRequest(ex.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
#region Report Inventory ii
|
#region Report Inventory ii
|
||||||
[HttpPost("GetInventoryReport")]
|
[HttpPost("GetInventoryReport")]
|
||||||
public async Task<IActionResult> GetInventoryReport([FromBody] ReportFilterDTO filter)
|
public async Task<IActionResult> GetInventoryReport([FromBody] ReportFilterDTO filter)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user