ПИбд-23. Гуторов И.А. Лабораторная работа 4 #4

Closed
vasmaae wants to merge 7 commits from LabWork_4 into LabWork_3
20 changed files with 223 additions and 83 deletions

View File

@ -1,4 +1,5 @@
using PIbd_23_Gutorov_I.A._IT_Company.Entities.Enums;
using System.ComponentModel;
namespace PIbd_23_Gutorov_I.A._IT_Company.Entities;
@ -6,18 +7,40 @@ public class Contract
{
public int Id { get; private set; }
[Browsable(false)]
public int CustomerID { get; private set; }
[Browsable(false)]
public int ExecutorID { get; private set; }
[DisplayName("Заказчик")]
public string CustomerName { get; private set; } = string.Empty;
[Browsable(false)]
public ExecutorPost ExecutorPost { get; private set; }
[Browsable(false)]
public string ExecutorName { get; private set; } = string.Empty;
[DisplayName("Исполнитель")]
public string ExecutorFullName => $"{ExecutorPost} {ExecutorName}";
[DisplayName("Тип контракта")]
public ContractCategory Category { get; private set; }
[DisplayName("Дата заключения")]
public DateTime ConclusionDate { get; private set; }
[DisplayName("Дата окончания")]
public DateTime Deadline { get; private set; }
[DisplayName("Сумма платежа")]
public int PaymentAmount { get; private set; }
[DisplayName("Услуги")]
public string Service => Services != null ? string.Join(", ", Services.Select(x => $"{x.Description}")) : string.Empty;
[Browsable(false)]
public IEnumerable<Service> Services { get; private set; } = [];
public static Contract CreateEntity(int id, int customerID, int executorID,
@ -37,18 +60,9 @@ public class Contract
};
}
public static Contract CreateEntity(TempServiceContract tempServiceContract, IEnumerable<Service> services)
public void SetServices(IEnumerable<Service> services)
{
return new Contract
{
Id = tempServiceContract.Id,
CustomerID = tempServiceContract.CustomerID,
ExecutorID = tempServiceContract.ExecutorID,
Category = tempServiceContract.Category,
ConclusionDate = tempServiceContract.ConclusionDate,
Deadline = tempServiceContract.Deadline,
PaymentAmount = tempServiceContract.PaymentAmount,
Services = services
};
if (services != null && services.Any())
Services = services;
}
}

View File

@ -1,13 +1,20 @@
namespace PIbd_23_Gutorov_I.A._IT_Company.Entities;
using System.ComponentModel;
namespace PIbd_23_Gutorov_I.A._IT_Company.Entities;
public class Customer
{
public int Id { get; private set; }
[DisplayName("Имя")]
public string Name { get; private set; } = string.Empty;
[DisplayName("Контакты")]
public string Contact { get; private set; } = string.Empty;
public string FullName => $"{Name} {Contact}";
[DisplayName("Адрес")]
public string Address { get; private set; } = string.Empty;
public static Customer CreateEntity(int id, string name, string contact, string address)

View File

@ -1,15 +1,34 @@
namespace PIbd_23_Gutorov_I.A._IT_Company.Entities;
using PIbd_23_Gutorov_I.A._IT_Company.Entities.Enums;
using System.ComponentModel;
namespace PIbd_23_Gutorov_I.A._IT_Company.Entities;
public class CustomerExecutorReview
{
public int Id { get; private set; }
[Browsable(false)]
public int CustomerId { get; private set; }
[Browsable(false)]
public int ExecutorId { get; private set; }
[DisplayName("Заказчик")]
public string CustomerName { get; private set; } = string.Empty;
[Browsable(false)]
public ExecutorPost ExecutorPost { get; private set; }
[Browsable(false)]
public string ExecutorName { get; private set; } = string.Empty;
[DisplayName("Исполнитель")]
public string ExecutorFullName => $"{ExecutorPost} {ExecutorName}";
[DisplayName("Отзыв")]
public string Review { get; private set; } = string.Empty;
[DisplayName("Оценка")]
public int Grade { get; private set; }
public static CustomerExecutorReview CreateElement(int id, int customerId, int executorId, string review, int grade)

View File

@ -1,4 +1,5 @@
using PIbd_23_Gutorov_I.A._IT_Company.Entities.Enums;
using System.ComponentModel;
namespace PIbd_23_Gutorov_I.A._IT_Company.Entities;
@ -6,10 +7,14 @@ public class Executor
{
public int Id { get; private set; }
[DisplayName("Имя")]
public string Name { get; private set; } = string.Empty;
[DisplayName("Должность")]
public ExecutorPost Post { get; private set; }
public string FullName => $"{Post} {Name}";
public static Executor CreateEntity(int id, string name, ExecutorPost post)
{
return new Executor

View File

@ -1,9 +1,12 @@
namespace PIbd_23_Gutorov_I.A._IT_Company.Entities;
using System.ComponentModel;
namespace PIbd_23_Gutorov_I.A._IT_Company.Entities;
public class Service
{
public int Id { get; private set; }
[DisplayName("Описание услуги")]
public string Description { get; private set; } = string.Empty;
public static Service CreateEntity(int id, string description)

View File

@ -1,13 +1,20 @@
namespace PIbd_23_Gutorov_I.A._IT_Company.Entities;
using System.ComponentModel;
namespace PIbd_23_Gutorov_I.A._IT_Company.Entities;
public class ServiceContract
{
public int Id { get; private set; }
[Browsable(false)]
public int ServiceId { get; private set; }
[Browsable(false)]
public int ContractId { get; private set; }
[DisplayName("Описание услуги")]
public string ServiceDescription { get; private set; } = string.Empty;
public static ServiceContract CreateElement(int id, int serviceId, int contractId)
{
return new ServiceContract

View File

@ -1,24 +0,0 @@
using PIbd_23_Gutorov_I.A._IT_Company.Entities.Enums;
namespace PIbd_23_Gutorov_I.A._IT_Company.Entities;
public class TempServiceContract
{
public int Id { get; private set; }
public int CustomerID { get; private set; }
public int ExecutorID { get; private set; }
public ContractCategory Category { get; private set; }
public DateTime ConclusionDate { get; private set; }
public DateTime Deadline { get; private set; }
public int PaymentAmount { get; private set; }
public int ServiceId { get; private set; }
public string Description { get; private set; } = string.Empty;
}

View File

@ -15,11 +15,11 @@ namespace PIbd_23_Gutorov_I.A._IT_Company.Forms
_contractRepository = contractRepository ?? throw new ArgumentNullException(nameof(contractRepository));
comboBoxContractCustomerId.DataSource = customerRepository.ReadCustomers();
comboBoxContractCustomerId.DisplayMember = "Name";
comboBoxContractCustomerId.DisplayMember = "FullName";
comboBoxContractCustomerId.ValueMember = "Id";
comboBoxContractExecutorId.DataSource = executorRepository.ReadExecutors();
comboBoxContractExecutorId.DisplayMember = "Name";
comboBoxContractExecutorId.DisplayMember = "FullName";
comboBoxContractExecutorId.ValueMember = "Id";
ColumnServiceDescription.DataSource = serviceRepository.ReadServices();

View File

@ -14,7 +14,7 @@ namespace PIbd_23_Gutorov_I.A._IT_Company.Forms
_container = container ?? throw new ArgumentNullException(nameof(container));
comboBoxCutomerId.DataSource = customerRepository.ReadCustomers();
comboBoxCutomerId.DisplayMember = "Name";
comboBoxCutomerId.DisplayMember = "FullName";
comboBoxCutomerId.ValueMember = "Id";
}

View File

@ -60,7 +60,13 @@ namespace PIbd_23_Gutorov_I.A._IT_Company.Forms
}
}
private void LoadList() => dataGridViewData.DataSource = _contractRepository.ReadContracts();
private void LoadList()
{
dataGridViewData.DataSource = _contractRepository.ReadContracts();
dataGridViewData.Columns["Id"].Visible = false;
dataGridViewData.Columns["ConclusionDate"].DefaultCellStyle.Format = "dd MMMM yyyy hh:mm";
dataGridViewData.Columns["Deadline"].DefaultCellStyle.Format = "dd MMMM yyyy hh:mm";
}
private bool TryGetIdentifierFromSelectedRow(out int id)
{

View File

@ -15,11 +15,11 @@ namespace PIbd_23_Gutorov_I.A._IT_Company.Forms
throw new ArgumentNullException(nameof(customerExecutorReviewRepository));
comboBoxCustomerExecutorReviewCustomerId.DataSource = customerRepository.ReadCustomers();
comboBoxCustomerExecutorReviewCustomerId.DisplayMember = "Name";
comboBoxCustomerExecutorReviewCustomerId.DisplayMember = "FullName";
comboBoxCustomerExecutorReviewCustomerId.ValueMember = "Id";
comboBoxCustomerExecutorReviewExecutorId.DataSource = executorRepository.ReadExecutors();
comboBoxCustomerExecutorReviewExecutorId.DisplayMember = "Name";
comboBoxCustomerExecutorReviewExecutorId.DisplayMember = "FullName";
comboBoxCustomerExecutorReviewExecutorId.ValueMember = "Id";
}

View File

@ -41,6 +41,10 @@ namespace PIbd_23_Gutorov_I.A._IT_Company.Forms
}
}
private void LoadList() => dataGridViewData.DataSource = _customerExecutorReviewRepository.ReadCustomerExecutorReviews();
private void LoadList()
{
dataGridViewData.DataSource = _customerExecutorReviewRepository.ReadCustomerExecutorReviews();
dataGridViewData.Columns["Id"].Visible = false;
}
}
}

View File

@ -78,7 +78,12 @@ namespace PIbd_23_Gutorov_I.A._IT_Company.Forms
}
}
private void LoadList() => dataGridViewData.DataSource = _customerRepository.ReadCustomers();
private void LoadList()
{
dataGridViewData.DataSource = _customerRepository.ReadCustomers();
dataGridViewData.Columns["Id"].Visible = false;
dataGridViewData.Columns["FullName"].Visible = false;
}
private bool TryGetIdentifierFromSelectedRow(out int id)
{

View File

@ -78,7 +78,12 @@ namespace PIbd_23_Gutorov_I.A._IT_Company.Forms
}
}
private void LoadList() => dataGridViewData.DataSource = _executorRepository.ReadExecutors();
private void LoadList()
{
dataGridViewData.DataSource = _executorRepository.ReadExecutors();
dataGridViewData.Columns["Id"].Visible = false;
dataGridViewData.Columns["FullName"].Visible = false;
}
private bool TryGetIdentifierFromSelectedRow(out int id)
{

View File

@ -78,7 +78,11 @@ namespace PIbd_23_Gutorov_I.A._IT_Company.Forms
}
}
private void LoadList() => dataGridViewData.DataSource = _serviceRepository.ReadServices();
private void LoadList()
{
dataGridViewData.DataSource = _serviceRepository.ReadServices();
dataGridViewData.Columns["Id"].Visible = false;
}
private bool TryGetIdentifierFromSelectedRow(out int id)
{

View File

@ -23,7 +23,7 @@ internal class ChartReport
{
new PdfBuilder(filePath)
.AddHeader("Заключение контрактов")
.AddPieChart("Услуги", GetData(dateTime))
.AddPieChart($"Оказанные услуги на {dateTime: dd MMMM yyyy}", GetData(dateTime))
.Build();
return true;
@ -38,9 +38,8 @@ internal class ChartReport
private List<(string Caption, double Value)> GetData(DateTime dateTime)
{
return _contractRepository
.ReadContracts()
.Where(x => x.ConclusionDate.Date == dateTime.Date)
.GroupBy(x => x.CustomerID, (key, group) => new
.ReadContracts(dateFrom: dateTime.Date, dateTo: dateTime.Date.AddDays(1))
.GroupBy(x => x.CustomerName, (key, group) => new
{
Id = key,
Count = group.Sum(x => x.Services.Count())

View File

@ -26,7 +26,7 @@ internal class TableReport
{
new ExcelBuilder(filePath)
.AddHeader("Сводка по заключениям контрактов", 0, 4)
.AddParagraph("за период", 0)
.AddParagraph($"за период с {startDate:dd.MM.yyyy} по {endDate:dd.MM.yyyy}", 0)
.AddTable([10, 10, 15, 15], GetData(customerId, startDate, endDate))
.Build();
@ -42,28 +42,22 @@ internal class TableReport
private List<string[]> GetData(int customerId, DateTime startDate, DateTime endDate)
{
var data = _contractRepository
.ReadContracts()
.Where(x => x.ConclusionDate >= startDate
&& x.ConclusionDate <= endDate
&& x.CustomerID == customerId)
.GroupBy(x => x.ConclusionDate)
.ReadContracts(customerId: customerId, dateFrom: startDate, dateTo: endDate)
.GroupBy(x => x.ExecutorFullName)
.Select(x => new
{
x.First().ExecutorID,
x.First().ExecutorFullName,
Date = x.First().ConclusionDate,
CountIn = (int?)x.Count(),
CountOut = (int?)null
})
.Union(
_contractRepository
.ReadContracts()
.Where(x => x.Deadline >= startDate
&& x.Deadline <= endDate
&& x.CustomerID == customerId)
.GroupBy(x => x.Deadline)
.ReadContracts(customerId: customerId, dateFrom: startDate, dateTo: endDate)
.GroupBy(x => x.ExecutorFullName)
.Select(x => new
{
x.First().ExecutorID,
x.First().ExecutorFullName,
Date = x.First().Deadline,
CountIn = (int?)null,
CountOut = (int?)x.Count()
@ -74,13 +68,13 @@ internal class TableReport
return new List<string[]>() { item }
.Union(data.Select(x => new string[] {
x.ExecutorID.ToString(),
x.Date.ToString(),
x.CountIn?.ToString() ?? string.Empty,
x.CountOut?.ToString() ?? string.Empty
x.ExecutorFullName,
x.Date.ToString("dd.MM.yyyy"),
x.CountIn?.ToString("N0") ?? string.Empty,
x.CountOut?.ToString("N0") ?? string.Empty
}))
.Union(
[["Всего", "", data.Sum(x => x.CountIn ?? 0).ToString(), data.Sum(x => x.CountOut ?? 0).ToString()]])
[["Всего", "", data.Sum(x => x.CountIn ?? 0).ToString("N0"), data.Sum(x => x.CountOut ?? 0).ToString("N0")]])
.ToList();
}
}

View File

@ -83,19 +83,65 @@ public class ContractRepository : IContractRepository
try
{
var builder = new QueryBuilder();
if (dateFrom.HasValue)
{
builder.AddCondition("c.ConclusionDate >= @dateFrom");
builder.AddCondition("c.Deadline >= @dateFrom");
}
if (dateTo.HasValue)
{
builder.AddCondition("c.ConclusionDate <= @dateTo");
builder.AddCondition("c.Deadline <= @dateTo");
}
if (customerId.HasValue)
builder.AddCondition("c.CustomerId >= @customerId");
if (executorId.HasValue)
builder.AddCondition("c.ExecutorId >= @executorId");
using var connection = new NpgsqlConnection(_connectionString.ConnectionString);
var querySelect = @"
SELECT c.*, sc.ServiceId, s.Description
var querySelect = @$"
SELECT c.*,
CONCAT(cu.Name, ' ', cu.Contact) as CustomerName,
e.Post as ExecutorPost,
e.Name as ExecutorName,
sc.ServiceId,
s.Description as ServiceDescription
FROM Contracts c
INNER JOIN ServiceContract sc ON sc.ContractId = c.Id
INNER JOIN Services s ON sc.ServiceId = s.Id
LEFT JOIN Services s ON sc.ServiceId = s.Id
LEFT JOIN Customers cu ON cu.Id = c.CustomerId
LEFT JOIN Executors e ON e.Id = c.ExecutorId
{builder.Build()};
";
var contracts = connection.Query<TempServiceContract>(querySelect);
var contractsDict = new Dictionary<int, List<ServiceContract>>();
var contracts = connection.Query<Contract, ServiceContract, Contract>(querySelect, (contract, serviceContract) =>
{
if (!contractsDict.TryGetValue(contract.Id, out var sc))
{
sc = [];
contractsDict.Add(contract.Id, sc);
}
sc.Add(serviceContract);
return contract;
}, splitOn: "ServiceId", param: new
{
dateFrom,
dateTo,
customerId,
executorId
});
_logger.LogDebug("Полученные объекты: {json}", JsonConvert.SerializeObject(contracts));
return contracts
.GroupBy(x => x.Id, y => y, (key, value) =>
Contract.CreateEntity(value.First(), value.Select(z => Service.CreateEntity(z.ServiceId, z.Description))))
.ToList();
return contractsDict.Select(x =>
{
var c = contracts.First(y => y.Id == x.Key);
c.SetServices(x.Value.Select(x => Service.CreateEntity(x.ServiceId, x.ServiceDescription)));
return c;
}).ToArray();
}
catch (Exception ex)
{

View File

@ -66,11 +66,24 @@ public class CustomerExecutorReviewRepository : ICustomerExecutorReviewRepositor
try
{
var builder = new QueryBuilder();
if (customerId.HasValue)
builder.AddCondition("cer.CustomerId = @customerId");
if (executorId.HasValue)
builder.AddCondition("cer.ExecutorId = @executorId");
using var connection = new NpgsqlConnection(_connectionString.ConnectionString);
var querySelect = @"
SELECT * FROM CustomerExecutorReviews;
var querySelect = @$"
SELECT cer.*,
CONCAT(c.Name, ' ', c.Contact) as CustomerName,
e.Post as ExecutorPost,
e.Name as ExecutorName
FROM CustomerExecutorReviews cer
LEFT JOIN Customers c ON c.Id = cer.CustomerId
LEFT JOIN Executors e ON e.Id = cer.ExecutorId
{builder.Build()};
";
var customerExecutorReviews = connection.Query<CustomerExecutorReview>(querySelect);
var customerExecutorReviews = connection.Query<CustomerExecutorReview>(querySelect, new { customerId, executorId });
_logger.LogDebug("Полученные объекты: {json}", JsonConvert.SerializeObject(customerExecutorReviews));
return customerExecutorReviews;
}

View File

@ -0,0 +1,33 @@
using System.Text;
internal class QueryBuilder
{
private readonly StringBuilder _builder;
public QueryBuilder()
{
_builder = new();
}
public QueryBuilder AddCondition(string condition)
{
if (_builder.Length > 0)
{
_builder.Append(" AND ");
}
_builder.Append(condition);
return this;
}
public string Build()
{
if (_builder.Length == 0)
{
return string.Empty;
}
return $"WHERE {_builder}";
}
}