PIBD-22. Denisov V.D. LabWork_4 #5

Closed
kisame wants to merge 2 commits from LabWork_4 into LabWork_3
22 changed files with 287 additions and 139 deletions

View File

@ -1,6 +1,7 @@
using ProjectPolyclinic.Entities.Enums;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
@ -9,17 +10,19 @@ namespace ProjectPolyclinic.Entities;
public class Doctor
{
public int Id { get; private set; }
[DisplayName("Имя")]
public string First_Name { get; private set; } = string.Empty;
[DisplayName("Фамилия")]
public string Last_Name { get; private set; } = string.Empty;
public string FullName => $"{First_Name} {Last_Name}";
[DisplayName("Кабинет")]
public int Room { get; private set; }
public Specialization Specialization { get; private set; }
[DisplayName("Специализация")]
public Specialization Specialization { get; private set; }
[DisplayName("Уровень специализации")]
public SpecializationLevel SpecializationLevel { get; private set; }
public static Doctor CreateEntity(int id, string first_Name, string last_Name, int room, Specialization specialization, SpecializationLevel specializationLevel)

View File

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
@ -8,15 +9,18 @@ namespace ProjectPolyclinic.Entities;
public class DoctorPay
{
public int Id { get; private set; }
[Browsable(false)]
public int IdDoctor { get; private set; }
[DisplayName("Имя врача")]
public string DoctorName { get; private set; } = string.Empty;
[DisplayName("Месяц")]
public string Month { get; private set; } = string.Empty;
[DisplayName("Количество пациентов")]
public int Count_Patient { get; private set; }
[DisplayName("Оплата")]
public int Payment { get; private set; }
public static DoctorPay CreateElement(int id, int idDoctor, string month, int count_patient, int payment)

View File

@ -1,6 +1,7 @@
using ProjectPolyclinic.Entities.Enums;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
@ -11,10 +12,12 @@ public class Drug
{
public int Id { get; private set; }
[DisplayName("Названия лекарств")]
public DrugsNames drugsNames { get; private set; }
[DisplayName("Грамовка")]
public int Grams { get; private set; }
[DisplayName("Рецепт")]
public string Description { get; private set; } = string.Empty;
public static Drug CreateElement(int id, DrugsNames name, int grams, string description)

View File

@ -12,10 +12,15 @@ public class DrugMedHistory
public int DrugId { get; private set; }
public string DrugName { get; private set; } = string.Empty;
public int MedicalHistoryId { get; private set; }
public int Count { get; private set; }
private IEnumerable<DrugMedHistory> _drugMedHistory = new List<DrugMedHistory>();
public static DrugMedHistory CreateEntity(int id, int drugId, int medicalHistoryId, int count)
{
return new DrugMedHistory
@ -26,4 +31,6 @@ public class DrugMedHistory
Count = count
};
}
}

View File

@ -1,6 +1,7 @@
using ProjectPolyclinic.Entities.Enums;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
@ -10,17 +11,25 @@ namespace ProjectPolyclinic.Entities;
public class MedicalHistory
{
public int Id { get; private set; }
[Browsable(false)]
public int PatientId { get; private set; }
[Browsable(false)]
public int DoctorId { get; private set; }
[DisplayName("Имя пациента")]
public string PatientName { get; private set; } = string.Empty;
[DisplayName("Имя врача")]
public string DoctorName { get; private set; } = string.Empty;
[DisplayName("Время визита")]
public DateTime VisitDate { get; private set; }
[DisplayName("Состояние пациента")]
public Status Status { get; private set; }
[Browsable(false)]
public IEnumerable<DrugMedHistory> DrugMedHistory { get; private set; } = [];
[DisplayName("Назначенные лекарства")]
public string DrugsSummary => string.Join(", ", DrugMedHistory
.Select(d => $"Id: {d.DrugId}, Кол-во: {d.Count}"));
public static MedicalHistory CreateEntity(int id, int patientId,
Status status, int doctorId, IEnumerable<DrugMedHistory> drugMedHistory)
{
@ -35,20 +44,12 @@ public class MedicalHistory
};
}
public static MedicalHistory CreateEntity(TempMedicalHistory tempMedicalHistory,
IEnumerable<DrugMedHistory> drugMedHistory)
public void SetDrugMedHistory(IEnumerable<DrugMedHistory> drugMedHistory)
{
return new MedicalHistory
if (drugMedHistory != null)
{
Id = tempMedicalHistory.Id,
PatientId = tempMedicalHistory.PatientId,
DoctorId = tempMedicalHistory.DoctorId,
VisitDate = tempMedicalHistory.VisitDate,
Status = (Status)tempMedicalHistory.Status,
DrugMedHistory = drugMedHistory
};
DrugMedHistory = drugMedHistory;
}
}
}

View File

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
@ -8,15 +9,17 @@ namespace ProjectPolyclinic.Entities;
public class Patient
{
public int Id { get; private set; }
[DisplayName("Имя")]
public string First_Name { get; private set; } = string.Empty;
[DisplayName("Фамилия")]
public string Last_Name { get; private set; } = string.Empty;
public string FullName => $"{First_Name} {Last_Name}";
[DisplayName("Адрес")]
public string Address { get; private set; } = string.Empty;
[DisplayName("Номер телефона")]
public string ContactNumber { get; private set; } = string.Empty;

View File

@ -1,18 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ProjectPolyclinic.Entities;
public class TempMedicalHistory
{
public int Id { get; set; }
public int PatientId { get; set; }
public int DoctorId { get; set; }
public DateTime VisitDate { get; set; }
public int Status { get; set; }
public int DrugId { get; set; }
public int Count { get; set; }
}

View File

@ -26,7 +26,7 @@ public partial class FormDoctorPayment : Form
throw new ArgumentNullException(nameof(doctorPayRepository));
comboBoxDoctor.DataSource = doctorRepository.ReadDoctors();
comboBoxDoctor.DisplayMember = "Last_Name";
comboBoxDoctor.DisplayMember = "FullName";
comboBoxDoctor.ValueMember = "Id";
}

View File

@ -47,10 +47,12 @@ public partial class FormDoctorPayments : Form
}
private void LoadList() => dataGridView.DataSource = _doctorPayRepository.ReadDoctorPayments();
private void LoadList()
{
dataGridView.DataSource = _doctorPayRepository.ReadDoctorPayments();
dataGridView.Columns["Id"].Visible = false;
dataGridView.Columns["Month"].DefaultCellStyle.Format = "yyyy-dd";
}
private void buttonAdd_Click(object sender, EventArgs e)

View File

@ -48,7 +48,12 @@ public partial class FormDoctors : Form
}
}
private void LoadList() => dataGridView.DataSource = _doctorRepository.ReadDoctors();
private void LoadList()
{
dataGridView.DataSource = _doctorRepository.ReadDoctors();
dataGridView.Columns["Id"].Visible = false;
dataGridView.Columns["FullName"].Visible = false;
}
private bool TryGetIdentifierFromSelectedRow(out int id)

View File

@ -47,8 +47,11 @@ public partial class FormDrugs : Form
}
private void LoadList() => dataGridView.DataSource = _dragRepository.ReadDrug();
private void LoadList()
{
dataGridView.DataSource = _dragRepository.ReadDrug();
dataGridView.Columns["Id"].Visible = false;
}

View File

@ -48,10 +48,13 @@ public partial class FormMedicalHistories : Form
}
}
private void LoadList() => dataGridView.DataSource = _medicalHistoryRepository.ReadMedicalHistory();
private void LoadList()
{
dataGridView.DataSource = _medicalHistoryRepository.ReadMedicalHistory();
dataGridView.Columns["Id"].Visible = false;
dataGridView.Columns["VisitDate"].DefaultCellStyle.Format = "dd MMMM yyyy hh:mm";
}
private void buttonAdd_Click(object sender, EventArgs e)
{
try

View File

@ -33,11 +33,11 @@ public partial class FormMedicalHistory : Form
throw new ArgumentNullException(nameof(medicalHistoryRepository));
comboBoxPacient.DataSource = patientRepository.ReadPatient();
comboBoxPacient.DisplayMember = "First_Name";
comboBoxPacient.DisplayMember = "FullName";
comboBoxPacient.ValueMember = "Id";
comboBoxDoctor.DataSource = doctorRepository.ReadDoctors();
comboBoxDoctor.DisplayMember = "Last_Name";
comboBoxDoctor.DisplayMember = "FullName";
comboBoxDoctor.ValueMember = "Id";
ColumnDrug.DataSource = drugRepository.ReadDrug();

View File

@ -49,7 +49,12 @@ public partial class FormPatients : Form
private void LoadList() => dataGridView.DataSource = _pacientRepository.ReadPatient();
private void LoadList()
{
dataGridView.DataSource = _pacientRepository.ReadPatient();
dataGridView.Columns["Id"].Visible = false;
dataGridView.Columns["FullName"].Visible = false;
}

View File

@ -25,7 +25,7 @@ namespace ProjectPolyclinic.Forms
throw new ArgumentNullException(nameof(container));
comboBoxDoctor.DataSource = doctorRepository.ReadDoctors();
comboBoxDoctor.DisplayMember = "Last_Name";
comboBoxDoctor.DisplayMember = "FullName";
comboBoxDoctor.ValueMember = "Id";
}
private void buttonBuild_Click(object sender, EventArgs e)

View File

@ -14,13 +14,14 @@ public class ChartReport
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
public bool CreateChart(string filePath, DateTime dateTime)
{
try
{
new PdfBuilder(filePath)
.AddHeader("Выписанные лекарства")
.AddPieChart("Выписанные лекарства (Соотношение врачей и количества выписанных лекарств)", GetData(dateTime))
.AddHeader($"Выписанные лекарства на {dateTime:dd.MM.yyyy}")
.AddPieChart("Соотношение выписанных лекарств по врачам", GetData(dateTime))
.Build();
return true;
}
@ -31,6 +32,7 @@ public class ChartReport
}
}
private List<(string Caption, double Value)> GetData(DateTime dateTime)
{
var medicalHistories = _historyRepository.ReadMedicalHistory(null, null, null, null);
@ -39,20 +41,22 @@ public class ChartReport
.Where(mh => mh.VisitDate.Date == dateTime.Date)
.Where(mh => mh.DrugMedHistory != null && mh.DrugMedHistory.Any())
.ToList();
var groupedData = filteredHistories
.GroupBy(
mh => mh.DoctorId,
(key, group) => new
mh => mh.DoctorName,
(doctorName, group) => new
{
DoctorId = key,
DoctorName = doctorName,
TotalDrugs = group
.SelectMany(mh => mh.DrugMedHistory)
.Sum(dmh => dmh.Count)
}
)
.ToList();
var result = groupedData
.Select(x => (x.DoctorId.ToString(), (double)x.TotalDrugs))
.Select(x => (Caption: x.DoctorName, Value: (double)x.TotalDrugs))
.ToList();
return result;

View File

@ -1,6 +1,7 @@
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using ProjectPolyclinic.Repositories;
using ProjectPolyclinic.Repositories.Implementations;
namespace ProjectPolyclinic.Reports;
@ -11,12 +12,15 @@ public class TableReport
private readonly IDoctorPayRepository _doctorPayRepository;
private readonly IDoctorRepository _doctorRepository;
private readonly ILogger<TableReport> _logger;
internal static readonly string[] item = ["Id врача", "Дата", "Количество пациентов", "Выплаты"];
public TableReport(IDoctorPayRepository doctorPayRepository,
IMedicalHistoryRepository medicalHistoryRepository, ILogger<TableReport> logger)
IMedicalHistoryRepository medicalHistoryRepository,
IDoctorRepository doctorRepository, ILogger<TableReport> logger)
{
_doctorPayRepository = doctorPayRepository ??
throw new ArgumentNullException(nameof(IDoctorPayRepository));
@ -24,26 +28,30 @@ public class TableReport
_medicalHistoryRepository = medicalHistoryRepository ??
throw new ArgumentNullException(nameof(IMedicalHistoryRepository));
_doctorRepository = doctorRepository ??
throw new ArgumentNullException(nameof(IMedicalHistoryRepository));
_logger = logger ??
throw new ArgumentNullException(nameof(logger));
}
public bool CreateTable(string filePath, int doctorId, DateTime startDate, DateTime endDate)
{
try
{
// Приведение дат к началу и концу месяцев
var startOfMonth = new DateTime(startDate.Year, startDate.Month, 1);
var endOfMonth = new DateTime(endDate.Year, endDate.Month, 1).AddMonths(1).AddDays(-1);
// Получаем данные для таблицы и имя врача
var (tableData, doctorFullName) = GetData(doctorId, startOfMonth, endOfMonth);
var excelBuilder = new ExcelBuilder(filePath)
.AddHeader("Сводка по оплате", 0, 3)
.AddParagraph($"За период с {startOfMonth:MM.yyyy} по {endOfMonth:MM.yyyy}", 0)
.AddParagraph($"Id врача: {doctorId}", 0)
.AddTable(new[] { 25, 25, 25 }, GetData(doctorId, startOfMonth, endOfMonth));
.AddParagraph($"За период с {startOfMonth:MMMM yyyy} по {endOfMonth:MMMM yyyy}", 0)
.AddParagraph($"Врач: {doctorFullName}", 0)
.AddTable(new[] { 25, 25, 25 }, tableData);
excelBuilder.AddParagraph("", 0);
@ -61,8 +69,7 @@ public class TableReport
}
}
private List<string[]> GetData(int doctorId, DateTime startOfMonth, DateTime endOfMonth)
private (List<string[]>, string) GetData(int doctorId, DateTime startOfMonth, DateTime endOfMonth)
{
var data = _doctorPayRepository
.ReadDoctorPayments()
@ -73,50 +80,54 @@ public class TableReport
})
.Select(x => new
{
DoctorName = x.DoctorName, // Предполагается, что есть поле DoctorName
Date = DateTime.ParseExact(x.Month, "yyyy-MM", System.Globalization.CultureInfo.InvariantCulture),
CountOfPatients = x.Count_Patient,
Payments = x.Payment
})
.OrderBy(x => x.Date);
.OrderBy(x => x.Date)
.ToList();
var result = new List<string[]>
var doctorName = data.FirstOrDefault()?.DoctorName ?? "Неизвестный врач";
var result = new List<string[]>()
{
new[] { "Дата", "Количество пациентов", "Выплаты" }
}
.Union(data.Select(x => new string[]
{
x.Date.ToString("MMMM yyyy"),
x.CountOfPatients.ToString(),
x.Payments.ToString()
}))
.Union(new[]
{
new string[]
{
"Всего",
data.Sum(x => x.CountOfPatients).ToString(),
data.Sum(x => x.Payments).ToString()
}
})
.Union(
data.Select(x => new string[]
{
x.Date.ToString("MMMM yyyy"),
x.CountOfPatients.ToString(),
x.Payments.ToString()
})
)
.Union(
new[]
{
new string[]
{
"Всего",
data.Sum(x => x.CountOfPatients).ToString(),
data.Sum(x => x.Payments).ToString()
}
}
)
.ToList();
return result;
return (result, doctorName);
}
private List<string[]> GetDrugData(int doctorId, DateTime startOfMonth, DateTime endOfMonth)
{
var medicalHistories = _medicalHistoryRepository
.ReadMedicalHistory(startOfMonth, endOfMonth, null, doctorId)
.Where(mh => mh.DoctorId == doctorId && mh.VisitDate >= startOfMonth && mh.VisitDate <= endOfMonth)
.ReadMedicalHistory(startOfMonth, endOfMonth, doctorId, null) // Исправлено
.Where(mh => mh.DrugMedHistory != null && mh.DrugMedHistory.Any())
.ToList();
var result = new List<string[]>
{
new[] { "Дата", "Назначенные лекарства" }
};
_logger.LogDebug("Полученные медицинские истории с лекарствами: {data}", JsonConvert.SerializeObject(medicalHistories));
var sortedDrugData = medicalHistories
.Where(mh => mh.DrugMedHistory != null && mh.DrugMedHistory.Any())
var drugData = medicalHistories
.SelectMany(mh => mh.DrugMedHistory.Select(drug => new
{
Date = mh.VisitDate,
@ -125,17 +136,20 @@ public class TableReport
.OrderBy(x => x.Date)
.ToList();
result.AddRange(sortedDrugData
.Select(item => new string[]
{
item.Date.ToString("dd.MM.yyyy"),
item.Count.ToString()
}));
var result = new List<string[]> { new[] { "Дата", "Назначенные лекарства" } };
var totalDrugs = sortedDrugData.Sum(x => x.Count);
result.AddRange(drugData.Select(item => new string[]
{
item.Date.ToString("dd MMMM yyyy"),
item.Count.ToString()
}));
var totalDrugs = drugData.Sum(x => x.Count);
result.Add(new[] { "Всего", totalDrugs.ToString() });
return result;
}
}

View File

@ -9,7 +9,9 @@ namespace ProjectPolyclinic.Repositories;
public interface IDoctorPayRepository
{
IEnumerable<DoctorPay> ReadDoctorPayments();
//IEnumerable<DoctorPay> ReadDoctorPayments();
Review

Закомментированного кода быть не должно

Закомментированного кода быть не должно
IEnumerable<DoctorPay> ReadDoctorPayments(int? doctorId = null, string month = null);
void CreateDoctorPayments(DoctorPay doctorPayments);
}

View File

@ -9,7 +9,8 @@ namespace ProjectPolyclinic.Repositories;
public interface IMedicalHistoryRepository
{
IEnumerable<MedicalHistory> ReadMedicalHistory(DateTime? dateForm = null, DateTime? dateTo = null, int? DoctorId = null, int? PatientId = null);
IEnumerable<MedicalHistory> ReadMedicalHistory(DateTime? dateForm = null, DateTime? dateTo = null, int? doctorId = null, int? patientId = null);
void CreateMedicalHistory(MedicalHistory medicalHistory);

View File

@ -52,26 +52,42 @@ public class DoctorPayRepository : IDoctorPayRepository
}
}
public IEnumerable<DoctorPay> ReadDoctorPayments()
public IEnumerable<DoctorPay> ReadDoctorPayments(int? doctorId = null, string month = null)
{
_logger.LogInformation("Получение всех объектов");
_logger.LogInformation("Получение данных об оплатах врачам");
try
{
using var connection = new
NpgsqlConnection(_connectionString.ConnectionString);
var querySelect = "SELECT * FROM doctor_pay";
var professionalDevelopments =
connection.Query<DoctorPay>(querySelect);
_logger.LogDebug("Полученные объекты: {json}",
JsonConvert.SerializeObject(professionalDevelopments));
return professionalDevelopments;
var builder = new QueryBuilder();
if (doctorId.HasValue)
{
builder.AddCondition("dp.IdDoctor = @doctorId");
}
if (!string.IsNullOrEmpty(month))
{
builder.AddCondition("dp.Month = @month");
}
using var connection = new NpgsqlConnection(_connectionString.ConnectionString);
var querySelect = $@"
SELECT dp.*,
CONCAT(d.First_Name, ' ', d.Last_Name) as DoctorName
FROM doctor_pay dp
LEFT JOIN Doctors d ON dp.IdDoctor = d.Id
{builder.Build()}";
var doctorPayments = connection.Query<DoctorPay>(querySelect, new { doctorId, month });
_logger.LogDebug("Полученные записи об оплатах: {json}", JsonConvert.SerializeObject(doctorPayments));
return doctorPayments;
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка при чтении объектов");
_logger.LogError(ex, "Ошибка при чтении данных об оплатах врачей");
throw;
}
}
}

View File

@ -92,32 +92,88 @@ public class MedicalHistoryRepository : IMedicalHistoryRepository
throw;
}
}
public IEnumerable<MedicalHistory> ReadMedicalHistory(DateTime? dateForm = null, DateTime? dateTo = null, int? patientId = null, int? doctorId = null)
public IEnumerable<MedicalHistory> ReadMedicalHistory(DateTime? dateForm = null, DateTime? dateTo = null, int? doctorId = null, int? patientId = null)
{
_logger.LogInformation("Получение всех объектов");
try
{
var builder = new QueryBuilder();
if (dateForm.HasValue)
{
builder.AddCondition("mh.VisitDate >= @dateForm");
}
if (dateTo.HasValue)
{
builder.AddCondition("mh.VisitDate <= @dateTo");
}
if (doctorId.HasValue)
{
builder.AddCondition("mh.DoctorId = @doctorId");
}
if (patientId.HasValue)
{
builder.AddCondition("mh.PatientId = @patientId");
}
using var connection = new NpgsqlConnection(_connectionString.ConnectionString);
var querySelect = @"
SELECT mh.*, dmh.drug_id AS DrugId, dmh.count AS Count
var querySelect = $@"
SELECT mh.*,
CONCAT(p.First_Name, ' ', p.Last_Name) AS PatientName,
CONCAT(d.First_Name, ' ', d.Last_Name) AS DoctorName, -- Исправлено
dmh.Id AS Id, dmh.drug_id AS DrugId, dmh.medical_history_id AS MedicalHistoryId, dmh.Count
FROM medical_history mh
LEFT JOIN drug_med_history dmh ON mh.id = dmh.medical_history_id";
LEFT JOIN drug_med_history dmh ON dmh.medical_history_id = mh.Id
LEFT JOIN patients p ON p.Id = mh.PatientId
LEFT JOIN doctors d ON d.Id = mh.DoctorId
{builder.Build()}";
var tempHistories = connection.Query<TempMedicalHistory>(querySelect);
_logger.LogDebug("SQL запрос: {query}", querySelect);
_logger.LogDebug("Параметры: dateForm = {dateForm}, dateTo = {dateTo}, doctorId = {doctorId}, patientId = {patientId}",
dateForm, dateTo, doctorId, patientId);
_logger.LogDebug("Полученные объекты: {json}", JsonConvert.SerializeObject(tempHistories));
var medicalHistoryDict = new Dictionary<int, List<DrugMedHistory>>();
return tempHistories.GroupBy(x => x.Id)
.Select(group => MedicalHistory.CreateEntity(
group.First(),
group.Select(d => DrugMedHistory.CreateEntity(0, d.DrugId, d.Id, d.Count))
)).ToList();
var medicalHistories = connection.Query<MedicalHistory, DrugMedHistory, MedicalHistory>(
querySelect,
(history, drug) =>
{
if (!medicalHistoryDict.TryGetValue(history.Id, out var drugs))
{
drugs = new List<DrugMedHistory>();
medicalHistoryDict.Add(history.Id, drugs);
}
if (drug != null && drug.Id > 0)
{
drugs.Add(DrugMedHistory.CreateEntity(drug.Id, drug.DrugId, drug.MedicalHistoryId, drug.Count));
}
return history;
},
splitOn: "Id",
param: new { dateForm, dateTo, doctorId, patientId });
return medicalHistoryDict.Select(x =>
{
var mh = medicalHistories.First(y => y.Id == x.Key);
mh.SetDrugMedHistory(x.Value);
return mh;
}).ToArray();
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка при чтении объектов");
_logger.LogError(ex, "Ошибка при чтении медицинских историй");
throw;
}
}
Review

Много пустых строк

Много пустых строк
}

View File

@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ProjectPolyclinic.Repositories.Implementations;
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}";
}
}