is done
This commit is contained in:
parent
85551918e3
commit
8afd4dd83d
@ -87,7 +87,7 @@ namespace ServiceStationBusinessLogic.BusinessLogic {
|
|||||||
throw new ArgumentNullException("Нет ФИО клиента", nameof(model.FIO));
|
throw new ArgumentNullException("Нет ФИО клиента", nameof(model.FIO));
|
||||||
}
|
}
|
||||||
|
|
||||||
_logger.LogInformation($"Client.Id:{model.Id}.FIO:{model.FIO}.TotalPoints:{model.TotalPoints}");
|
_logger.LogInformation($"Client.Id:{model.Id}.FIO:{model.FIO}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,12 @@ namespace ServiceStationBusinessLogic.OfficePackage
|
|||||||
StyleInfo = ExcelStyleInfoType.Text
|
StyleInfo = ExcelStyleInfoType.Text
|
||||||
});
|
});
|
||||||
|
|
||||||
|
InsertCellInWorksheet(new ExcelCellParameters {
|
||||||
|
ColumnName = "B",
|
||||||
|
RowIndex = rowIndex,
|
||||||
|
StyleInfo = ExcelStyleInfoType.Text
|
||||||
|
});
|
||||||
|
|
||||||
MergeCells(new ExcelMergeParameters {
|
MergeCells(new ExcelMergeParameters {
|
||||||
CellFromName = $"A{rowIndex}",
|
CellFromName = $"A{rowIndex}",
|
||||||
CellToName = $"B{rowIndex}"
|
CellToName = $"B{rowIndex}"
|
||||||
@ -45,6 +51,12 @@ namespace ServiceStationBusinessLogic.OfficePackage
|
|||||||
StyleInfo = ExcelStyleInfoType.Text
|
StyleInfo = ExcelStyleInfoType.Text
|
||||||
});
|
});
|
||||||
|
|
||||||
|
InsertCellInWorksheet(new ExcelCellParameters {
|
||||||
|
ColumnName = "D",
|
||||||
|
RowIndex = rowIndex,
|
||||||
|
StyleInfo = ExcelStyleInfoType.Text
|
||||||
|
});
|
||||||
|
|
||||||
MergeCells(new ExcelMergeParameters {
|
MergeCells(new ExcelMergeParameters {
|
||||||
CellFromName = $"C{rowIndex}",
|
CellFromName = $"C{rowIndex}",
|
||||||
CellToName = $"D{rowIndex}"
|
CellToName = $"D{rowIndex}"
|
||||||
@ -57,6 +69,12 @@ namespace ServiceStationBusinessLogic.OfficePackage
|
|||||||
StyleInfo = ExcelStyleInfoType.Text
|
StyleInfo = ExcelStyleInfoType.Text
|
||||||
});
|
});
|
||||||
|
|
||||||
|
InsertCellInWorksheet(new ExcelCellParameters {
|
||||||
|
ColumnName = "F",
|
||||||
|
RowIndex = rowIndex,
|
||||||
|
StyleInfo = ExcelStyleInfoType.Text
|
||||||
|
});
|
||||||
|
|
||||||
MergeCells(new ExcelMergeParameters {
|
MergeCells(new ExcelMergeParameters {
|
||||||
CellFromName = $"E{rowIndex}",
|
CellFromName = $"E{rowIndex}",
|
||||||
CellToName = $"F{rowIndex}"
|
CellToName = $"F{rowIndex}"
|
||||||
@ -71,6 +89,12 @@ namespace ServiceStationBusinessLogic.OfficePackage
|
|||||||
StyleInfo = ExcelStyleInfoType.TextWithBorder
|
StyleInfo = ExcelStyleInfoType.TextWithBorder
|
||||||
});
|
});
|
||||||
|
|
||||||
|
InsertCellInWorksheet(new ExcelCellParameters {
|
||||||
|
ColumnName = "C",
|
||||||
|
RowIndex = rowIndex,
|
||||||
|
StyleInfo = ExcelStyleInfoType.TextWithBorder
|
||||||
|
});
|
||||||
|
|
||||||
MergeCells(new ExcelMergeParameters {
|
MergeCells(new ExcelMergeParameters {
|
||||||
CellFromName = $"B{rowIndex}",
|
CellFromName = $"B{rowIndex}",
|
||||||
CellToName = $"C{rowIndex}"
|
CellToName = $"C{rowIndex}"
|
||||||
@ -83,6 +107,11 @@ namespace ServiceStationBusinessLogic.OfficePackage
|
|||||||
StyleInfo = ExcelStyleInfoType.TextWithBorder
|
StyleInfo = ExcelStyleInfoType.TextWithBorder
|
||||||
});
|
});
|
||||||
|
|
||||||
|
InsertCellInWorksheet(new ExcelCellParameters {
|
||||||
|
ColumnName = "E",
|
||||||
|
RowIndex = rowIndex,
|
||||||
|
StyleInfo = ExcelStyleInfoType.TextWithBorder
|
||||||
|
});
|
||||||
|
|
||||||
MergeCells(new ExcelMergeParameters {
|
MergeCells(new ExcelMergeParameters {
|
||||||
CellFromName = $"D{rowIndex}",
|
CellFromName = $"D{rowIndex}",
|
||||||
|
@ -10,6 +10,9 @@ namespace ServiceStationBusinessLogic.OfficePackage {
|
|||||||
public abstract class AbstractSaveToWord {
|
public abstract class AbstractSaveToWord {
|
||||||
|
|
||||||
public byte[]? CreateDoc(WordInfo info) {
|
public byte[]? CreateDoc(WordInfo info) {
|
||||||
|
|
||||||
|
CreateWord(info);
|
||||||
|
|
||||||
CreateParagraph(new WordParagraph {
|
CreateParagraph(new WordParagraph {
|
||||||
Texts = new List<(string, WordTextProperties)> { (info.Title, new WordTextProperties { Bold = true, Size = "24"})},
|
Texts = new List<(string, WordTextProperties)> { (info.Title, new WordTextProperties { Bold = true, Size = "24"})},
|
||||||
TextProperties = new WordTextProperties {
|
TextProperties = new WordTextProperties {
|
||||||
|
@ -6,6 +6,5 @@ namespace ServiceStationContracts.BindingModels
|
|||||||
|
|
||||||
public int Id { get; set; }
|
public int Id { get; set; }
|
||||||
public string FIO { get; set; } = string.Empty;
|
public string FIO { get; set; } = string.Empty;
|
||||||
public int TotalPoints { get; set; }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,9 +10,6 @@ namespace ServiceStationContracts.ViewModels
|
|||||||
[DisplayName("ФИО")]
|
[DisplayName("ФИО")]
|
||||||
public string FIO { get; set; } = string.Empty;
|
public string FIO { get; set; } = string.Empty;
|
||||||
|
|
||||||
[DisplayName("Всего баллов")]
|
|
||||||
public int TotalPoints { get; set; }
|
|
||||||
|
|
||||||
public bool Equals(ClientViewModel? other) {
|
public bool Equals(ClientViewModel? other) {
|
||||||
if (other is null) {
|
if (other is null) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -5,6 +5,5 @@ namespace ServiceStationDataModels.Models
|
|||||||
public interface IClientModel : IId
|
public interface IClientModel : IId
|
||||||
{
|
{
|
||||||
string FIO { get; }
|
string FIO { get; }
|
||||||
int TotalPoints { get; }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -229,5 +229,62 @@ namespace ServiceSourceClientApp.Controllers {
|
|||||||
}
|
}
|
||||||
return new JsonResult(works);
|
return new JsonResult(works);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpGet]
|
||||||
|
public IActionResult Report() {
|
||||||
|
if (APIClient.executor == null) {
|
||||||
|
return Redirect("~/Home/Enter");
|
||||||
|
}
|
||||||
|
var view = APIClient.GetRequest<List<WorkViewModel>>($"api/Main/GetWorks?_executorId={APIClient.executor.Id}");
|
||||||
|
return View(view);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
public void Report(DateTime DateFrom, DateTime DateTo) {
|
||||||
|
if (DateTo == DateTime.MinValue || DateFrom > DateTo) {
|
||||||
|
throw new Exception("Íåêîðåêòíî óêàçàí âðåìåííîé èíòåðâàë");
|
||||||
|
}
|
||||||
|
Response.Redirect($"ReportSearchDate?_datefrom={DateFrom}&_dateto={DateTo + DateTime.Now.TimeOfDay}");
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet]
|
||||||
|
public IActionResult ReportSearchDate(string _datefrom, string _dateto) {
|
||||||
|
var reports = APIClient.GetRequest<List<WorkViewModel>>($"api/Main/GerWorksDate?_start={_datefrom}&_end={_dateto}");
|
||||||
|
(DateTime, DateTime, List<WorkViewModel>?) tuple = (DateTime.Parse(_datefrom), DateTime.Parse(_dateto), reports);
|
||||||
|
return View(tuple);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet]
|
||||||
|
public IActionResult CreatePdfReport(string DateFrom, string DateTo) {
|
||||||
|
APIClient.PostRequest("api/Main/SendReportPdfMail", new ReportBindeingModel {
|
||||||
|
EmailAddress = APIClient.executor?.Email ?? throw new Exception("Îøèáêà ïîëó÷åíèÿ àäðåñà"),
|
||||||
|
DateFrom = DateTime.Parse(DateFrom),
|
||||||
|
DateTo = DateTime.Parse(DateTo)
|
||||||
|
});
|
||||||
|
return Redirect("Report");
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet]
|
||||||
|
public IActionResult CreateWordReport(string ids) {
|
||||||
|
|
||||||
|
var fileMemStream = APIClient.GetRequest<byte[]>($"api/Main/CreateWordReport?_ids={ids}");
|
||||||
|
|
||||||
|
if (fileMemStream == null) {
|
||||||
|
throw new Exception("Îøèáêà ñîçäàíèÿ îò÷åòà");
|
||||||
|
}
|
||||||
|
|
||||||
|
return File(fileMemStream, "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "Report.docx");
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet]
|
||||||
|
public IActionResult CreateExcelReport(string ids) {
|
||||||
|
var fileMemStream = APIClient.GetRequest<byte[]>($"api/Main/CreateXlsxReport?_ids={ids}");
|
||||||
|
|
||||||
|
if (fileMemStream == null) {
|
||||||
|
throw new Exception("Îøèáêà ñîçäàíèÿ îò÷åòà");
|
||||||
|
}
|
||||||
|
|
||||||
|
return File(fileMemStream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "Report.xlsx");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,151 @@
|
|||||||
|
@using ServiceStationContracts.ViewModels
|
||||||
|
@model List<WorkViewModel>
|
||||||
|
@{
|
||||||
|
ViewData["Title"] = "Report";
|
||||||
|
}
|
||||||
|
|
||||||
|
<script src="~/lib/jquery/dist/jquery.min.js"></script>
|
||||||
|
|
||||||
|
<div class="text-center">
|
||||||
|
<h1 class="display-4">Отчёты</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="text-start">
|
||||||
|
<h2 class="display-5">Отчёт за период</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form method="post">
|
||||||
|
<div class="align-content-center row mb-3">
|
||||||
|
<div class="col-sm-auto">
|
||||||
|
<label>С:</label>
|
||||||
|
</div>
|
||||||
|
<div class="col-3">
|
||||||
|
<input name="DateFrom" id="datefrom" type="date" />
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-auto">
|
||||||
|
<label>По:</label>
|
||||||
|
</div>
|
||||||
|
<div class="col-3">
|
||||||
|
<input name="DateTo" id="dateto" type="date" />
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-8"></div>
|
||||||
|
<div class="col-4"><input type="submit" value="Cформировать отчет" class="btn btn-sm btn-outline-danger m-2 p-2" /></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<div class="text-start">
|
||||||
|
<h2 class="display-5">Выбрать оплаты в отечет</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="text-center">
|
||||||
|
@{
|
||||||
|
if (Model == null) {
|
||||||
|
<h3 class="display-4">Авторизируйтесь</h3>
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
<div class="text-end">
|
||||||
|
<button class="btn btn-sm btn-outline-danger m-2 p-2" id="btnFix">Cформировать отчет</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="text-end">
|
||||||
|
<button class="btn btn-primary btn-sm" id="SaveWord" style="background-color:#335a95;">Экспорт отчета в .docx</button>
|
||||||
|
<button class="btn btn-primary btn-sm 2" id="SaveExcel" style="background-color:#04713A;">Экспорт отчета в .xlsx</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<table class="table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>
|
||||||
|
Номер
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
Дата работы
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
Стоимость работы
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
Номер задания
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
Задание
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
<input type="checkbox" class="form-check-input" id="Select_all" name="Select_all" /> Выбрать все
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
@foreach (var item in Model) {
|
||||||
|
<tr>
|
||||||
|
<th>
|
||||||
|
@Html.DisplayFor(modelItem => item.Id)
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
@Html.DisplayFor(modelItem => item.Date)
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
@Html.DisplayFor(modelItem => item.Price)
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
@Html.DisplayFor(modelItem => item.TaskByWorkId)
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
@Html.DisplayFor(modelItem => item.TaskName)
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
<input type="checkbox" class="form-check-input" id="Select_rec" name="Select_rec" value="@item.Id" />
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
$('#Select_all').on('click', function () {
|
||||||
|
let checkboxes = document.getElementsByTagName('input');
|
||||||
|
let val = null;
|
||||||
|
|
||||||
|
for (var i = 0; i < checkboxes.length; i++) {
|
||||||
|
if (checkboxes[i].type === 'checkbox') {
|
||||||
|
if (val == null) {
|
||||||
|
val = checkboxes[i].checked;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
checkboxes[i].checked = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#SaveWord').on('click', function () {
|
||||||
|
let val = [];
|
||||||
|
$("input[name='Select_rec']:checked").each(function () {
|
||||||
|
val.push($(this).val());
|
||||||
|
});
|
||||||
|
|
||||||
|
var str = '';
|
||||||
|
for (let i = 0; i < val.length; i++) {
|
||||||
|
str += val[i] + '_'
|
||||||
|
}
|
||||||
|
location.href = '/Home/CreateWordReport?ids=' + str
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#SaveExcel').on('click', function () {
|
||||||
|
debugger
|
||||||
|
let val = [];
|
||||||
|
$("input[name='Select_rec']:checked").each(function () {
|
||||||
|
val.push($(this).val());
|
||||||
|
});
|
||||||
|
|
||||||
|
var str = '';
|
||||||
|
for (let i = 0; i < val.length; i++) {
|
||||||
|
str += val[i] + '_'
|
||||||
|
}
|
||||||
|
location.href = '/Home/CreateExcelReport?ids=' + str
|
||||||
|
});
|
||||||
|
</script>
|
@ -0,0 +1,82 @@
|
|||||||
|
@using ServiceStationContracts.ViewModels
|
||||||
|
@model (DateTime, DateTime, List<WorkViewModel>)
|
||||||
|
|
||||||
|
@{
|
||||||
|
ViewData["Title"] = "ReportSearchDate";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
<script src="~/lib/jquery/dist/jquery.min.js"></script>
|
||||||
|
|
||||||
|
<div class="text-center">
|
||||||
|
<h1 class="row align-items-center mb-3">
|
||||||
|
<div class="text-center">
|
||||||
|
<label>Предпросмотр отчета:</label>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-auto">
|
||||||
|
<label>С:</label>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-auto">
|
||||||
|
<input name="DateFrom" id="datefrom" type="text" value="@Model.Item1.Date.ToString("d")" readonly />
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-auto">
|
||||||
|
<label>По:</label>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-auto">
|
||||||
|
<input name="DateTo" id="dateto" type="text" value="@Model.Item2.Date.ToString("d")" readonly />
|
||||||
|
</div>
|
||||||
|
<div class="text-end">
|
||||||
|
<a class="btn btn-primary btn-sm" asp-action="CreatePdfReport" asp-route-DateFrom="@Model.Item1"
|
||||||
|
asp-route-DateTo="@Model.Item2" style="background-color:#ad0d09;">отправить на Email отчет в .pdf</a>
|
||||||
|
</div>
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="text-center">
|
||||||
|
@{
|
||||||
|
<table class="table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>
|
||||||
|
Номер
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
Дата работы
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
Стоимость работы
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
Номер задания
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
Задание
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
@foreach (var item in Model.Item3) {
|
||||||
|
<tr>
|
||||||
|
<th>
|
||||||
|
@Html.DisplayFor(modelItem => item.Id)
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
@Html.DisplayFor(modelItem => item.Date)
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
@Html.DisplayFor(modelItem => item.Price)
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
@Html.DisplayFor(modelItem => item.TaskByWorkId)
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
@Html.DisplayFor(modelItem => item.TaskName)
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
}
|
||||||
|
</div>
|
@ -138,6 +138,21 @@ namespace ServiceStationRestAPI.Controllers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpGet]
|
||||||
|
public List<WorkViewModel>? GerWorksDate(string _start, string _end) {
|
||||||
|
try {
|
||||||
|
var data = _workLogic.ReadList(new WorkSearchModel {
|
||||||
|
DateFrom = DateTime.Parse(_start),
|
||||||
|
DateTo = DateTime.Parse(_end)
|
||||||
|
});
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
_logger.LogError(ex, "Ошибка получения данных");
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
public List<List<string>> GetWork(int _workId) {
|
public List<List<string>> GetWork(int _workId) {
|
||||||
try {
|
try {
|
||||||
@ -150,7 +165,6 @@ namespace ServiceStationRestAPI.Controllers
|
|||||||
var record = new ClientViewModel {
|
var record = new ClientViewModel {
|
||||||
Id = client.Key,
|
Id = client.Key,
|
||||||
FIO = client.Value.FIO,
|
FIO = client.Value.FIO,
|
||||||
TotalPoints = client.Value.TotalPoints,
|
|
||||||
};
|
};
|
||||||
string jsRec = JsonConvert.SerializeObject(record);
|
string jsRec = JsonConvert.SerializeObject(record);
|
||||||
client_list.Add(jsRec);
|
client_list.Add(jsRec);
|
||||||
|
@ -18,8 +18,6 @@ namespace ServiceStationsDataBaseImplement.Models
|
|||||||
[Required]
|
[Required]
|
||||||
public string FIO { get; set; } = string.Empty;
|
public string FIO { get; set; } = string.Empty;
|
||||||
|
|
||||||
public int TotalPoints { get; set; }
|
|
||||||
|
|
||||||
[ForeignKey("ClientId")]
|
[ForeignKey("ClientId")]
|
||||||
public virtual List<WorkClient> WorkClients { get; set; } = new();
|
public virtual List<WorkClient> WorkClients { get; set; } = new();
|
||||||
|
|
||||||
@ -30,7 +28,6 @@ namespace ServiceStationsDataBaseImplement.Models
|
|||||||
return new Client() {
|
return new Client() {
|
||||||
Id = model.Id,
|
Id = model.Id,
|
||||||
FIO = model.FIO,
|
FIO = model.FIO,
|
||||||
TotalPoints = model.TotalPoints,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,13 +36,11 @@ namespace ServiceStationsDataBaseImplement.Models
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
FIO = model.FIO;
|
FIO = model.FIO;
|
||||||
TotalPoints = model.TotalPoints;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ClientViewModel GetViewModel => new() {
|
public ClientViewModel GetViewModel => new() {
|
||||||
Id = Id,
|
Id = Id,
|
||||||
FIO = FIO,
|
FIO = FIO
|
||||||
TotalPoints = TotalPoints
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user