конец семестра. Проверять не будет.

This commit is contained in:
LivelyPuer 2024-12-25 15:44:54 +04:00
parent aec9869fd5
commit 209c6bfa29
27 changed files with 489 additions and 167 deletions

View File

@ -1,8 +1,12 @@
namespace ProjectOpticsStore.Entities; using System.ComponentModel;
namespace ProjectOpticsStore.Entities;
public class Customer public class Customer
{ {
public int Id { get; private set; } public int Id { get; private set; }
[DisplayName("ФИО заказчика")]
public string FullName { get; private set; } = string.Empty; public string FullName { get; private set; } = string.Empty;
public static Customer CreateEntity(int id, string fullName) public static Customer CreateEntity(int id, string fullName)

View File

@ -1,15 +1,33 @@
using Newtonsoft.Json; using Newtonsoft.Json;
using ProjectOpticsStore.Entities; using ProjectOpticsStore.Entities;
using ProjectOpticsStore.Entities.Enums; using ProjectOpticsStore.Entities.Enums;
using System.ComponentModel;
using System.Linq;
public class Order public class Order
{ {
public int Id { get; private set; } public int Id { get; private set; }
public int CustomerId { get; private set; }
public DateTime DateCreated { get; private set; }
[Browsable(false)]
public int CustomerId { get; private set; }
[DisplayName("Заказчик")]
public string CustomerName { get; private set; } = string.Empty;
[DisplayName("Товары")]
// Объединение строк
public string Product => OrderProducts != null ?
string.Join(", ", OrderProducts.Select(x => $"{x.Type} {x.Quantity}")) :
string.Empty;
[DisplayName("Cтатус")]
public OrderStatusEnum Status { get; private set; } = OrderStatusEnum.Pending; public OrderStatusEnum Status { get; private set; } = OrderStatusEnum.Pending;
[DisplayName("Дата заказа")]
public DateTime DateCreated { get; private set; }
[Browsable(false)]
// Коллекция, описывающая связь "Order_Product" // Коллекция, описывающая связь "Order_Product"
[JsonIgnore] public IEnumerable<Order_Product> OrderProducts { get; private set; } = new List<Order_Product>(); [JsonIgnore] public IEnumerable<Order_Product> OrderProducts { get; private set; } = new List<Order_Product>();
@ -24,16 +42,11 @@ public class Order
OrderProducts = orderProducts OrderProducts = orderProducts
}; };
} }
public void SetOrderProducts(IEnumerable<Order_Product> products)
public static Order CreateOperation(TempOrderProduct tempOrderProduct, IEnumerable<Order_Product> orderProducts)
{ {
return new Order if (products != null && products.Any())
{ {
Id = tempOrderProduct.Id, OrderProducts = products;
CustomerId = tempOrderProduct.CustomerId, }
DateCreated = tempOrderProduct.DateCreated,
Status = tempOrderProduct.Status,
OrderProducts = orderProducts
};
} }
} }

View File

@ -1,18 +1,26 @@
namespace ProjectOpticsStore.Entities; using ProjectOpticsStore.Entities.Enums;
using System.ComponentModel;
namespace ProjectOpticsStore.Entities;
public class Order_Product public class Order_Product
{ {
public int OrderId { get; private set; } public int OrderId { get; private set; }
public int ProductId { get; private set; } public int ProductId { get; private set; }
public ProductTypeEnum Type { get; private set; }
public int Quantity { get; private set; } public int Quantity { get; private set; }
// Создание элемента связи // Создание элемента связи
public static Order_Product CreateElement(int orderId, int productId, int quantity) public static Order_Product CreateElement(int orderId, int productId, ProductTypeEnum type, int quantity)
{ {
return new Order_Product return new Order_Product
{ {
OrderId = orderId, OrderId = orderId,
ProductId = productId, ProductId = productId,
Type = type,
Quantity = quantity Quantity = quantity
}; };
} }

View File

@ -1,15 +1,29 @@
using ProjectOpticsStore.Entities.Enums; using ProjectOpticsStore.Entities.Enums;
using System.ComponentModel;
public class Product public class Product
{ {
public int Id { get; private set; } public int Id { get; private set; }
[DisplayName("Тип Товара")]
public ProductTypeEnum Type { get; private set; } public ProductTypeEnum Type { get; private set; }
[DisplayName("Мощность")]
public double Power { get; private set; } public double Power { get; private set; }
[DisplayName("Цена")]
public int Price { get; private set; } public int Price { get; private set; }
[DisplayName("Магазин")]
public int Store { get; private set; } public int Store { get; private set; }
[DisplayName("Толщина (чево)")]
public float Thickness { get; private set; } public float Thickness { get; private set; }
[DisplayName("Болезнь")]
public string Disease { get; private set; } = string.Empty; public string Disease { get; private set; } = string.Empty;
public static Product CreateEntity(int id, ProductTypeEnum type, double power, int price, int store, float thickness, string disease) public static Product CreateEntity(int id, ProductTypeEnum type, double power, int price, int store, float thickness, string disease)
{ {
return new Product return new Product

View File

@ -1,16 +1,26 @@
namespace ProjectOpticsStore.Entities; using System.ComponentModel;
namespace ProjectOpticsStore.Entities;
public class Store public class Store
{ {
public int Id { get; private set; } public int Id { get; private set; }
[DisplayName("Адрес магазина")]
public string Address { get; private set; } = string.Empty; public string Address { get; private set; } = string.Empty;
public static Store CreateEntity(int id, string address) [DisplayName("Организация")]
public string Organisation { get; private set; } = string.Empty; //Добавил тут новое поле (зря)
public string FullInformation => $"{Address} {Organisation}";
public static Store CreateEntity(int id, string address, string organisation)
{ {
return new Store return new Store
{ {
Id = id, Id = id,
Address = address ?? string.Empty Address = address ?? string.Empty,
Organisation = organisation ?? string.Empty
}; };
} }
} }

View File

@ -1,13 +1,30 @@
namespace ProjectOpticsStore.Entities; using ProjectOpticsStore.Entities.Enums;
using System.ComponentModel;
namespace ProjectOpticsStore.Entities;
public class Supply public class Supply
{ {
public int Id { get; private set; } public int Id { get; private set; }
[Browsable(false)]
public int StoreId { get; private set; } public int StoreId { get; private set; }
public DateTime OperationDate { get; private set; }
[Browsable(false)]
public int ProductId { get; private set; } // Связь многие-к-одному с товарами public int ProductId { get; private set; } // Связь многие-к-одному с товарами
[DisplayName("Магазин")]
public string StoreName { get; private set; } = string.Empty; //Добавил имя магазина
[DisplayName("Товар")]
public string ProductName { get; private set; } = string.Empty;
[DisplayName("Количество")]
public int Quantity { get; private set; } // Количество поставленного товара public int Quantity { get; private set; } // Количество поставленного товара
[DisplayName("Дата спецоперации")]
public DateTime OperationDate { get; private set; }
public static Supply CreateOperation(int id, int storeId, int productId, int quantity) public static Supply CreateOperation(int id, int storeId, int productId, int quantity)
{ {
return new Supply return new Supply

View File

@ -1,16 +0,0 @@
using ProjectOpticsStore.Entities.Enums;
namespace ProjectOpticsStore.Entities;
public class TempOrderProduct
{
public int Id { get; private set; }
public int CustomerId { get; private set; }
public DateTime DateCreated { get; private set; }
public OrderStatusEnum Status { get; private set; }
public int OrderId { get; private set; }
public int ProductId { get; private set; }
public int Quantity { get; private set; }
}

View File

@ -84,6 +84,7 @@ public partial class FormCustomers : Form
private void LoadList() private void LoadList()
{ {
dataGridViewData.DataSource = _customerRepository.ReadCustomers(); dataGridViewData.DataSource = _customerRepository.ReadCustomers();
dataGridViewData.Columns["Id"].Visible = false;
} }
private bool TryGetIdentifierFromSelectedRow(out int id) private bool TryGetIdentifierFromSelectedRow(out int id)

View File

@ -85,7 +85,7 @@
Controls.Add(checkBoxCustomers); Controls.Add(checkBoxCustomers);
Name = "FormDirectoryReport"; Name = "FormDirectoryReport";
StartPosition = FormStartPosition.CenterParent; StartPosition = FormStartPosition.CenterParent;
Text = "FormDirectoryReport"; Text = "Отчет по т.н. справочникам";
ResumeLayout(false); ResumeLayout(false);
PerformLayout(); PerformLayout();
} }

View File

@ -19,12 +19,10 @@ public partial class FormOrder : Form
_customerRepository = customerRepository ?? throw new ArgumentNullException(nameof(customerRepository)); _customerRepository = customerRepository ?? throw new ArgumentNullException(nameof(customerRepository));
_productRepository = productRepository ?? throw new ArgumentNullException(nameof(productRepository)); _productRepository = productRepository ?? throw new ArgumentNullException(nameof(productRepository));
// Настройка ComboBox для выбора клиента // Инициализация ComboBox для магазинов
comboBoxCustomer.DataSource = _customerRepository.ReadCustomers() comboBoxCustomer.DataSource = _customerRepository.ReadCustomers().ToList();
.Select(c => new { c.Id }) comboBoxCustomer.DisplayMember = "FullName"; // Отображаем фио заказчиков
.ToList(); comboBoxCustomer.ValueMember = "Id"; // Значение это идентификатор заказчика
comboBoxCustomer.DisplayMember = "Id";
comboBoxCustomer.ValueMember = "Id";
comboBoxCustomer.DropDownStyle = ComboBoxStyle.DropDownList; comboBoxCustomer.DropDownStyle = ComboBoxStyle.DropDownList;
// Настройка ComboBox для выбора статуса заказа // Настройка ComboBox для выбора статуса заказа
@ -54,9 +52,9 @@ public partial class FormOrder : Form
var productColumn = new DataGridViewComboBoxColumn var productColumn = new DataGridViewComboBoxColumn
{ {
Name = "ColumnProduct", Name = "ColumnProduct",
HeaderText = "Товар", HeaderText = "Товары",
DataSource = _productRepository.ReadProducts() DataSource = _productRepository.ReadProducts()
.Select(p => new { p.Id, p.Type }) // Пример данных: Id и Name .Select(p => new { p.Id, p.Type }) // Пример данных: Id и Type
.ToList(), .ToList(),
DisplayMember = "Type", DisplayMember = "Type",
ValueMember = "Id", ValueMember = "Id",
@ -73,6 +71,15 @@ public partial class FormOrder : Form
}; };
dataGridViewProducts.Columns.Add(quantityColumn); dataGridViewProducts.Columns.Add(quantityColumn);
// Столбец "Тип"
var typeColumn = new DataGridViewTextBoxColumn
{
Name = "ColumnType",
ValueType = typeof(int),
Visible = false // Скрываем столбец
};
dataGridViewProducts.Columns.Add(typeColumn);
productColumn.AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill; productColumn.AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
quantityColumn.AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill; quantityColumn.AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
} }
@ -117,11 +124,19 @@ public partial class FormOrder : Form
if (row.Cells["ColumnProduct"].Value == null || row.Cells["ColumnQuantity"].Value == null) if (row.Cells["ColumnProduct"].Value == null || row.Cells["ColumnQuantity"].Value == null)
continue; continue;
list.Add(Order_Product.CreateElement(0, Convert.ToInt32(row.Cells["ColumnProduct"].Value), var productId = Convert.ToInt32(row.Cells["ColumnProduct"].Value);
Convert.ToInt32(row.Cells["ColumnQuantity"].Value))); var quantity = Convert.ToInt32(row.Cells["ColumnQuantity"].Value);
} // Какой же говнокод
return list.GroupBy(x => x.ProductId, x => x.Quantity, (id, quantity) => var typeValue = row.Cells["ColumnType"].Value?.ToString();
Order_Product.CreateElement(0, id, quantity.Sum())).ToList(); ProductTypeEnum type = ProductTypeEnum.Glasses;
list.Add(Order_Product.CreateElement(0, productId, type, quantity));
}
return list.GroupBy(
x => new { x.ProductId, x.Type }, // Группируем по ProductId и Type
x => x.Quantity,
(key, quantity) => Order_Product.CreateElement(0, key.ProductId, key.Type, quantity.Sum())
).ToList();
} }
} }

View File

@ -49,12 +49,10 @@ public partial class FormOrders : Form
// Метод для загрузки списка заказов в DataGridView // Метод для загрузки списка заказов в DataGridView
private void LoadList() private void LoadList()
{ {
dataGridViewOrders.DataSource = _orderRepository.ReadOrders();
//if (dataGridViewOrders.Columns.Contains("OrderProducts")) dataGridViewOrders.DataSource = _orderRepository.ReadOrders();
//{ dataGridViewOrders.Columns["Id"].Visible = false;
// dataGridViewOrders.Columns["OrderProducts"].Visible = false; dataGridViewOrders.Columns["DateCreated"].DefaultCellStyle.Format = "dd MMMM yyyy hh:mm";
//}
} }
// Метод для получения идентификатора заказа из выбранной строки в DataGridView // Метод для получения идентификатора заказа из выбранной строки в DataGridView

View File

@ -63,7 +63,7 @@ public partial class FormProduct : Form
// Инициализация ComboBox для магазинов // Инициализация ComboBox для магазинов
comboBoxStore.DataSource = _storeRepository.ReadStores().ToList(); comboBoxStore.DataSource = _storeRepository.ReadStores().ToList();
comboBoxStore.DisplayMember = "Address"; // Отображаем адрес магазина comboBoxStore.DisplayMember = "FullInformation"; // Отображаем полную информацию о магазине
comboBoxStore.ValueMember = "Id"; // Значение это идентификатор магазина comboBoxStore.ValueMember = "Id"; // Значение это идентификатор магазина
} }

View File

@ -1,5 +1,6 @@
using ProjectOpticsStore.Entities; using ProjectOpticsStore.Entities;
using ProjectOpticsStore.Repositories; using ProjectOpticsStore.Repositories;
using System.ComponentModel;
using Unity; using Unity;
namespace ProjectOpticsStore.Forms; namespace ProjectOpticsStore.Forms;
@ -88,10 +89,60 @@ public partial class FormProducts : Form
private void LoadList() private void LoadList()
{ {
// Загрузка списка товаров в DataGridView // Загружаем список товаров
dataGridViewProducts.DataSource = _productRepository.ReadProducts().ToList(); var products = _productRepository.ReadProducts().ToList();
// Преобразуем данные с FullInformation магазинов
var productsWithStoreInfo = products.Select(product =>
{
var store = _container.Resolve<IStoreRepository>().ReadStoreById(product.Store);
return new
{
product.Id,
product.Type,
product.Power,
product.Price,
Store = store?.FullInformation, //деваться некуда, приходится передавать FullInformation
product.Thickness,
product.Disease
};
}).ToList();
// Привязываем данные к DataGridView
dataGridViewProducts.DataSource = productsWithStoreInfo;
// Настраиваем заголовки колонок на основе DisplayName
ApplyDisplayNames();
dataGridViewProducts.Columns["Id"].Visible = false;
} }
//После обновления метода LoadList у меня все русские заголовки с DisplayName перестали работать, поэтому
//мною было принято решение о создании нового метода, который может и костыльно, но это фиксит. Главное что оно работает
private void ApplyDisplayNames()
{
foreach (var column in dataGridViewProducts.Columns.Cast<DataGridViewColumn>())
{
// Получаем свойство, соответствующее колонке, из типа Product
var property = typeof(Product).GetProperty(column.DataPropertyName);
if (property == null)
{
continue;
}
// Читаем атрибут DisplayName
var displayNameAttr = property.GetCustomAttributes(typeof(DisplayNameAttribute), false)
.FirstOrDefault() as DisplayNameAttribute;
// Если атрибут найден, задаем его значение в качестве заголовка
if (displayNameAttr != null)
{
column.HeaderText = displayNameAttr.DisplayName;
}
}
}
private bool TryGetIdentifierFromSelectedRow(out int id) private bool TryGetIdentifierFromSelectedRow(out int id)
{ {
id = 0; id = 0;

View File

@ -32,30 +32,34 @@
labelFullName = new Label(); labelFullName = new Label();
buttonSave = new Button(); buttonSave = new Button();
buttonCancel = new Button(); buttonCancel = new Button();
textBoxOrganisation = new TextBox();
labelOrganisation = new Label();
SuspendLayout(); SuspendLayout();
// //
// textBoxAddress // textBoxAddress
// //
textBoxAddress.Location = new Point(134, 69); textBoxAddress.Location = new Point(133, 52);
textBoxAddress.Margin = new Padding(3, 2, 3, 2);
textBoxAddress.Name = "textBoxAddress"; textBoxAddress.Name = "textBoxAddress";
textBoxAddress.Size = new Size(295, 27); textBoxAddress.Size = new Size(243, 23);
textBoxAddress.TabIndex = 1; textBoxAddress.TabIndex = 1;
// //
// labelFullName // labelFullName
// //
labelFullName.AutoSize = true; labelFullName.AutoSize = true;
labelFullName.Font = new Font("Segoe UI", 12F, FontStyle.Regular, GraphicsUnit.Point, 204); labelFullName.Font = new Font("Segoe UI", 12F, FontStyle.Regular, GraphicsUnit.Point, 204);
labelFullName.Location = new Point(22, 65); labelFullName.Location = new Point(19, 49);
labelFullName.Name = "labelFullName"; labelFullName.Name = "labelFullName";
labelFullName.Size = new Size(71, 28); labelFullName.Size = new Size(56, 21);
labelFullName.TabIndex = 4; labelFullName.TabIndex = 4;
labelFullName.Text = "Адрес:"; labelFullName.Text = "Адрес:";
// //
// buttonSave // buttonSave
// //
buttonSave.Location = new Point(40, 278); buttonSave.Location = new Point(35, 208);
buttonSave.Margin = new Padding(3, 2, 3, 2);
buttonSave.Name = "buttonSave"; buttonSave.Name = "buttonSave";
buttonSave.Size = new Size(124, 40); buttonSave.Size = new Size(108, 30);
buttonSave.TabIndex = 5; buttonSave.TabIndex = 5;
buttonSave.Text = "Сохранить"; buttonSave.Text = "Сохранить";
buttonSave.UseVisualStyleBackColor = true; buttonSave.UseVisualStyleBackColor = true;
@ -63,23 +67,45 @@
// //
// buttonCancel // buttonCancel
// //
buttonCancel.Location = new Point(206, 278); buttonCancel.Location = new Point(180, 208);
buttonCancel.Margin = new Padding(3, 2, 3, 2);
buttonCancel.Name = "buttonCancel"; buttonCancel.Name = "buttonCancel";
buttonCancel.Size = new Size(124, 40); buttonCancel.Size = new Size(108, 30);
buttonCancel.TabIndex = 6; buttonCancel.TabIndex = 6;
buttonCancel.Text = "Отмена"; buttonCancel.Text = "Отмена";
buttonCancel.UseVisualStyleBackColor = true; buttonCancel.UseVisualStyleBackColor = true;
buttonCancel.Click += ButtonCancel_Click; buttonCancel.Click += ButtonCancel_Click;
// //
// textBoxOrganisation
//
textBoxOrganisation.Location = new Point(133, 127);
textBoxOrganisation.Margin = new Padding(3, 2, 3, 2);
textBoxOrganisation.Name = "textBoxOrganisation";
textBoxOrganisation.Size = new Size(243, 23);
textBoxOrganisation.TabIndex = 7;
//
// labelOrganisation
//
labelOrganisation.AutoSize = true;
labelOrganisation.Font = new Font("Segoe UI", 12F, FontStyle.Regular, GraphicsUnit.Point, 204);
labelOrganisation.Location = new Point(19, 127);
labelOrganisation.Name = "labelOrganisation";
labelOrganisation.Size = new Size(108, 21);
labelOrganisation.TabIndex = 8;
labelOrganisation.Text = "Организация:";
//
// FormStore // FormStore
// //
AutoScaleDimensions = new SizeF(8F, 20F); AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font; AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(469, 341); ClientSize = new Size(410, 256);
Controls.Add(labelOrganisation);
Controls.Add(textBoxOrganisation);
Controls.Add(buttonCancel); Controls.Add(buttonCancel);
Controls.Add(buttonSave); Controls.Add(buttonSave);
Controls.Add(labelFullName); Controls.Add(labelFullName);
Controls.Add(textBoxAddress); Controls.Add(textBoxAddress);
Margin = new Padding(3, 2, 3, 2);
Name = "FormStore"; Name = "FormStore";
Text = "Магазины"; Text = "Магазины";
ResumeLayout(false); ResumeLayout(false);
@ -92,5 +118,7 @@
private Label labelFullName; private Label labelFullName;
private Button buttonSave; private Button buttonSave;
private Button buttonCancel; private Button buttonCancel;
private TextBox textBoxOrganisation;
private Label labelOrganisation;
} }
} }

View File

@ -1,4 +1,5 @@
using ProjectOpticsStore.Entities; using DocumentFormat.OpenXml.Office2010.PowerPoint;
using ProjectOpticsStore.Entities;
using ProjectOpticsStore.Repositories; using ProjectOpticsStore.Repositories;
namespace ProjectOpticsStore.Forms; namespace ProjectOpticsStore.Forms;
@ -22,6 +23,7 @@ public partial class FormStore : Form
} }
textBoxAddress.Text = store.Address; textBoxAddress.Text = store.Address;
textBoxOrganisation.Text = store.Organisation;
_storeId = value; _storeId = value;
} }
catch (Exception ex) catch (Exception ex)
@ -48,6 +50,11 @@ public partial class FormStore : Form
throw new Exception("Адрес магазина не указан."); throw new Exception("Адрес магазина не указан.");
} }
if (string.IsNullOrWhiteSpace(textBoxOrganisation.Text))
{
throw new Exception("Организация магазина не указана.");
}
// Сохранение данных // Сохранение данных
if (_storeId.HasValue) if (_storeId.HasValue)
{ {
@ -74,6 +81,6 @@ public partial class FormStore : Form
private Store CreateStore(int id) private Store CreateStore(int id)
{ {
// Создание сущности Store // Создание сущности Store
return Store.CreateEntity(id, textBoxAddress.Text); return Store.CreateEntity(id, textBoxAddress.Text, textBoxOrganisation.Text);
} }
} }

View File

@ -88,6 +88,8 @@ public partial class FormStores : Form
{ {
// Загрузка списка магазинов в DataGridView // Загрузка списка магазинов в DataGridView
dataGridViewStores.DataSource = _storeRepository.ReadStores().ToList(); dataGridViewStores.DataSource = _storeRepository.ReadStores().ToList();
dataGridViewStores.Columns["Id"].Visible = false;
dataGridViewStores.Columns["FullInformation"].Visible = false;
} }
private bool TryGetIdentifierFromSelectedRow(out int id) private bool TryGetIdentifierFromSelectedRow(out int id)

View File

@ -44,6 +44,8 @@ public partial class FormSupplies : Form
{ {
// Загрузка списка поставок в DataGridView // Загрузка списка поставок в DataGridView
dataGridViewSupplies.DataSource = _supplyRepository.ReadSupplies().ToList(); dataGridViewSupplies.DataSource = _supplyRepository.ReadSupplies().ToList();
dataGridViewSupplies.Columns["Id"].Visible = false;
dataGridViewSupplies.Columns["OperationDate"].DefaultCellStyle.Format = "dd.MM.yyyy";
} }
private void ButtonDel_Click(object sender, EventArgs e) private void ButtonDel_Click(object sender, EventArgs e)

View File

@ -18,12 +18,12 @@ public partial class FormSupply : Form
// Инициализация ComboBox для магазинов // Инициализация ComboBox для магазинов
comboBoxStore.DataSource = _storeRepository.ReadStores().ToList(); comboBoxStore.DataSource = _storeRepository.ReadStores().ToList();
comboBoxStore.DisplayMember = "Address"; comboBoxStore.DisplayMember = "FullInformation";
comboBoxStore.ValueMember = "Id"; comboBoxStore.ValueMember = "Id";
// Инициализация ComboBox для товаров // Инициализация ComboBox для товаров
comboBoxProduct.DataSource = _productRepository.ReadProducts().ToList(); comboBoxProduct.DataSource = _productRepository.ReadProducts().ToList();
comboBoxProduct.DisplayMember = "Name"; comboBoxProduct.DisplayMember = "Type";
comboBoxProduct.ValueMember = "Id"; comboBoxProduct.ValueMember = "Id";
// Устанавливаем дату как текущую и блокируем редактирование // Устанавливаем дату как текущую и блокируем редактирование

View File

@ -15,6 +15,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Dapper" Version="2.1.35" /> <PackageReference Include="Dapper" Version="2.1.35" />
<PackageReference Include="DocumentFormat.OpenXml" Version="3.2.0" /> <PackageReference Include="DocumentFormat.OpenXml" Version="3.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Http.Extensions" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="9.0.0" /> <PackageReference Include="Microsoft.Extensions.Configuration" Version="9.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="9.0.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="9.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="9.0.0" /> <PackageReference Include="Microsoft.Extensions.Logging" Version="9.0.0" />

View File

@ -1,48 +1,72 @@
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using ProjectOpticsStore.Repositories; using ProjectOpticsStore.Repositories;
using ProjectOpticsStore.Entities;
using ProjectOpticsStore.Entities.Enums;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace ProjectOpticsStore.Reports; namespace ProjectOpticsStore.Reports
public class ChartReport
{ {
private readonly ISupplyRepository _supplyRepository; // Изменение типа репозитория public class ChartReport
private readonly ILogger<ChartReport> _logger;
public ChartReport(ISupplyRepository supplyRepository, ILogger<ChartReport> logger) // Изменение параметра конструктора
{ {
_supplyRepository = supplyRepository ?? throw new ArgumentNullException(nameof(supplyRepository)); private readonly ISupplyRepository _supplyRepository; // Репозиторий для поставок
_logger = logger ?? throw new ArgumentNullException(nameof(logger)); private readonly IProductRepository _productRepository; // Репозиторий для продуктов
} private readonly ILogger<ChartReport> _logger;
public bool CreateChart(string filePath, DateTime dateTime) // Конструктор с зависимостями
{ public ChartReport(ISupplyRepository supplyRepository, IProductRepository productRepository, ILogger<ChartReport> logger)
try
{ {
new PdfBuilder(filePath) _supplyRepository = supplyRepository ?? throw new ArgumentNullException(nameof(supplyRepository));
.AddHeader("Распределение поставок по товарам") // Изменено заголовок для соответствия Supply _productRepository = productRepository ?? throw new ArgumentNullException(nameof(productRepository)); // Для получения типа продукта
.AddPieChart("Поставки", GetData(dateTime)) // Изменено название графика _logger = logger ?? throw new ArgumentNullException(nameof(logger));
.Build();
return true;
} }
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка при формировании документа");
return false;
}
}
private List<(string Caption, double Value)> GetData(DateTime dateTime) // Метод для создания графика
{ public bool CreateChart(string filePath, DateTime dateTime)
return _supplyRepository {
.ReadSupplies() // Изменено на метод, который читает поставки try
.Where(x => x.OperationDate.Date == dateTime.Date) // Используем OperationDate вместо DateCreated {
.GroupBy(x => x.ProductId, (key, group) => new { ID = key, TotalQuantity = group.Sum(y => y.Quantity) }) // Группировка по ProductId // Создание PDF с графиком
.Select(x => (x.ID.ToString(), (double)x.TotalQuantity)) // Изменено на TotalQuantity new PdfBuilder(filePath)
.ToList(); .AddHeader("Распределение поставок по товарам") // Заголовок
.AddPieChart($"Поставки на {dateTime:dd MMMM yyyy}", GetData(dateTime)) // График
.Build();
return true;
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка при формировании документа");
return false;
}
}
// Метод для получения данных для графика
private List<(string Caption, double Value)> GetData(DateTime dateTime)
{
// Получаем все поставки для заданной даты
var supplies = _supplyRepository
.ReadSupplies()
.Where(x => x.OperationDate.Date == dateTime.Date) // Фильтруем по дате
.GroupBy(x => x.ProductId) // Группируем по ProductId
.Select(g => new
{
ProductId = g.Key,
TotalQuantity = g.Sum(x => x.Quantity)
})
.ToList();
// Для каждого ProductId находим тип товара через репозиторий продуктов
return supplies
.Select(x =>
{
var product = _productRepository.ReadProductById(x.ProductId); // Получаем продукт по ProductId
var productType = product.Type.ToString(); // Получаем тип товара (ProductTypeEnum)
return (productType, (double)x.TotalQuantity); // Возвращаем тип товара и общее количество
})
.ToList();
}
} }
} }

View File

@ -29,7 +29,7 @@ public class DocReport
} }
if (includeStores) if (includeStores)
{ {
builder.AddParagraph("Магазины").AddTable([2400], GetStores()); builder.AddParagraph("Магазины").AddTable([2400, 2400], GetStores());
} }
if (includeProducts) if (includeProducts)
{ {
@ -58,10 +58,10 @@ public class DocReport
private List<string[]> GetStores() private List<string[]> GetStores()
{ {
return [ return [
["Адрес магазина"], ["Адрес магазина", "Организация"],
.. _storeRepository .. _storeRepository
.ReadStores() .ReadStores()
.Select(x => new string[] { x.Address}), .Select(x => new string[] { x.Address, x.Organisation}),
]; ];
} }

View File

@ -1,5 +1,9 @@
using Microsoft.Extensions.Logging; using DocumentFormat.OpenXml.Wordprocessing;
using Microsoft.Extensions.Logging;
using ProjectOpticsStore.Repositories; using ProjectOpticsStore.Repositories;
using System;
using System.Collections.Generic;
using System.Linq;
namespace ProjectOpticsStore.Reports; namespace ProjectOpticsStore.Reports;
@ -8,7 +12,12 @@ public class TableReport
private readonly IOrderRepository _orderRepository; private readonly IOrderRepository _orderRepository;
private readonly ISupplyRepository _supplyRepository; private readonly ISupplyRepository _supplyRepository;
private readonly ILogger<TableReport> _logger; private readonly ILogger<TableReport> _logger;
internal static readonly string[] item = ["Продукт", "Дата", "Количество пришло", "Количество ушло"];
// Заголовки таблицы
// Типо Order - заказ - количество ушло - заказчик, Поставка - количество пришло - магазин.
// Поэтому в первой строчке Заказчик/Магазин а не только Заказчик. Все согласно Ерке.
internal static readonly string[] item = { "Заказчик", "Магазин", "Дата", "Количество пришло", "Количество ушло" };
public TableReport(IOrderRepository orderRepository, ISupplyRepository supplyRepository, public TableReport(IOrderRepository orderRepository, ISupplyRepository supplyRepository,
ILogger<TableReport> logger) ILogger<TableReport> logger)
@ -17,15 +26,22 @@ public class TableReport
_supplyRepository = supplyRepository ?? throw new ArgumentNullException(nameof(supplyRepository)); _supplyRepository = supplyRepository ?? throw new ArgumentNullException(nameof(supplyRepository));
_logger = logger ?? throw new ArgumentNullException(nameof(logger)); _logger = logger ?? throw new ArgumentNullException(nameof(logger));
} }
// Метод для создания таблицы
public bool CreateTable(string filePath, int productID, DateTime startDate, DateTime endDate) public bool CreateTable(string filePath, int productID, DateTime startDate, DateTime endDate)
{ {
try try
{ {
// Получение данных
var data = GetData(productID, startDate, endDate);
// Создание Excel документа
new ExcelBuilder(filePath) new ExcelBuilder(filePath)
.AddHeader("Сводка по движению товара", 0, 4) .AddHeader("Сводка по движению товаров", 0, 4)
.AddParagraph("за период", 0) .AddParagraph($"За период c {startDate:dd.MM.yyyy} по {endDate:dd.MM.yyyy}", 0)
.AddTable([10, 10, 15, 15], GetData(productID, startDate, endDate)) .AddTable(new[] { 15, 15, 12, 15, 15 }, data) // Ширины столбцов
.Build(); .Build();
return true; return true;
} }
catch (Exception ex) catch (Exception ex)
@ -35,47 +51,49 @@ public class TableReport
} }
} }
private List<string[]> GetData(int productID, DateTime startDate, DateTime endDate) // Метод для получения данных
private List<string[]> GetData(int productId, DateTime startDate, DateTime endDate)
{ {
var data = _orderRepository // Получение данных заказов
.ReadOrders() var ordersData = _orderRepository
.Where(x => x.DateCreated >= startDate && x.DateCreated <= endDate && x.OrderProducts.Any(y => y.ProductId == productID)) .ReadOrders(dateFrom: startDate, dateTo: endDate, productId: productId)
.Select(x => new .Select(order => new
{ {
ProductID = x.OrderProducts.First(y => y.ProductId == productID).ProductId, CustomerName = order.CustomerName,
Date = x.DateCreated, StoreName = string.Empty, // Магазин не указывается для заказов
Date = order.DateCreated,
CountIn = (int?)null, CountIn = (int?)null,
CountOut = (int?)x.OrderProducts.FirstOrDefault(y => y.ProductId == productID)?.Quantity CountOut = (int?)order.OrderProducts.Sum(op => op.Quantity)
}) });
.Union(
_supplyRepository // Получение данных поставок
.ReadSupplies() var suppliesData = _supplyRepository
.Where(x => x.OperationDate >= startDate && x.OperationDate <= endDate && x.ProductId == productID) .ReadSupplies(dateFrom: startDate, dateTo: endDate, productId: productId)
.Select(x => new .Select(supply => new
{ {
ProductID = x.ProductId, CustomerName = string.Empty, // Заказчик не указывается для поставок
Date = x.OperationDate, StoreName = supply.StoreName,
CountIn = (int?)x.Quantity, Date = supply.OperationDate,
CountOut = (int?)null CountIn = (int?)supply.Quantity,
})) CountOut = (int?)null
});
// Объединение и сортировка данных
var combinedData = ordersData
.Union(suppliesData)
.OrderBy(x => x.Date); .OrderBy(x => x.Date);
return // Формирование таблицы
new List<string[]> { TableReport.item } return new List<string[]> { item } // Добавляем заголовок таблицы
.Union( .Union(
data.Select(x => new string[] combinedData.Select(entry => new string[] {entry.CustomerName ?? string.Empty, entry.StoreName ?? string.Empty, entry.Date.ToString("dd.MM.yyyy"), entry.CountIn?.ToString("N0") ?? string.Empty, entry.CountOut?.ToString("N0") ?? string.Empty
{ })
x.ProductID.ToString(), )
x.Date.ToString(), .Union(new[]
x.CountIn?.ToString() ?? string.Empty, {
x.CountOut?.ToString() ?? string.Empty // Итоговая строка
})) new string[] { "Всего", "", "", combinedData.Sum(entry => entry.CountIn ?? 0).ToString("N0"), combinedData.Sum(entry => entry.CountOut ?? 0).ToString("N0")}
.Union(new[] {
new[] { "Всего", "", data.Sum(x => x.CountIn ?? 0).ToString(), data.Sum(x => x.CountOut ?? 0).ToString() }
}) })
.ToList(); .ToList();
} }
} }

View File

@ -5,7 +5,8 @@ public interface IOrderRepository
IEnumerable<Order> ReadOrders( IEnumerable<Order> ReadOrders(
DateTime? dateFrom = null, DateTime? dateFrom = null,
DateTime? dateTo = null, DateTime? dateTo = null,
int? customerId = null int? customerId = null,
int? productId = null
); );
void CreateOrder(Order order); void CreateOrder(Order order);
} }

View File

@ -1,8 +1,11 @@
using Dapper; using Dapper;
using DocumentFormat.OpenXml.Wordprocessing;
using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Newtonsoft.Json; using Newtonsoft.Json;
using Npgsql; using Npgsql;
using ProjectOpticsStore.Entities; using ProjectOpticsStore.Entities;
using ProjectOpticsStore.Entities.Enums;
using Unity; using Unity;
namespace ProjectOpticsStore.Repositories.Implementations; namespace ProjectOpticsStore.Repositories.Implementations;
@ -51,32 +54,77 @@ internal class OrderRepository : IOrderRepository
} }
} }
public IEnumerable<Order> ReadOrders(DateTime? dateFrom = null, DateTime? dateTo = null, int? productId = null) public IEnumerable<Order> ReadOrders(DateTime? dateFrom = null, DateTime? dateTo = null, int? customerId = null, int? productId = null)
{ {
_logger.LogInformation("Получение всех объектов"); _logger.LogInformation("Получение всех объектов");
try try
{ {
var builder = new QueryBuilder();
if (dateFrom.HasValue)
{
builder.AddCondition("o.DateCreated >= @dateFrom");
}
if (dateTo.HasValue)
{
builder.AddCondition("o.DateCreated <= @dateTo");
}
if (customerId.HasValue)
{
builder.AddCondition("o.CustomerId = @customerId");
}
if (productId.HasValue)
{
builder.AddCondition("op.ProductId = @productId");
}
using var connection = new NpgsqlConnection(_connectionString.ConnectionString); using var connection = new NpgsqlConnection(_connectionString.ConnectionString);
var querySelect = @"SELECT o.*, op.OrderId, op.ProductId, op.Quantity var querySelect = $@"
FROM Orders o SELECT o.Id,
INNER JOIN Orders_Products op ON op.OrderId = o.Id"; o.DateCreated,
o.Status,
c.FullName AS CustomerName,
os.Name AS StatusName,
p.Id AS ProductId,
p.Type AS Type,
op.Quantity
FROM Orders o
LEFT JOIN Customers c ON c.Id = o.CustomerId
LEFT JOIN OrderStatus os ON os.Id = o.Status
INNER JOIN Orders_Products op ON op.OrderId = o.Id
LEFT JOIN Products p ON p.Id = op.ProductId
{builder.Build()}";
_logger.LogDebug("Выполняется SQL-запрос: {Query}", querySelect); _logger.LogDebug("Выполняется SQL-запрос: {Query}", querySelect);
var orderProducts = connection.Query<TempOrderProduct>(querySelect); var orderDict = new Dictionary<int, List<Order_Product>>();
_logger.LogDebug("Полученные объекты: {json}", JsonConvert.SerializeObject(orderProducts)); var orders = connection.Query<Order, Order_Product, Order>(querySelect,
(order, orderProduct) =>
{
if (!orderDict.TryGetValue(order.Id, out var products))
{
products = new List<Order_Product>();
orderDict.Add(order.Id, products);
}
return orderProducts products.Add(Order_Product.CreateElement(order.Id, orderProduct.ProductId, orderProduct.Type, orderProduct.Quantity));
.GroupBy( return order;
x => x.Id, },
y => y, splitOn: "ProductId",
(key, value) => Order.CreateOperation( param: new { dateFrom, dateTo, customerId, productId });
value.First(),
value.Select(z => Order_Product.CreateElement(z.OrderId, z.ProductId, z.Quantity)) _logger.LogDebug("Полученные объекты: {json}", JsonConvert.SerializeObject(orders));
)
).ToList(); return orderDict.Select(x =>
{
var order = orders.First(y => y.Id == x.Key);
order.SetOrderProducts(x.Value);
return order;
}).ToArray();
} }
catch (Exception ex) catch (Exception ex)
{ {

View File

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

View File

@ -24,8 +24,8 @@ internal class StoreRepository : IStoreRepository
{ {
using var connection = new NpgsqlConnection(_connectionString.ConnectionString); using var connection = new NpgsqlConnection(_connectionString.ConnectionString);
var queryInsert = @" var queryInsert = @"
INSERT INTO Stores (Address) INSERT INTO Stores (Address, Organisation)
VALUES (@Address)"; VALUES (@Address, @Organisation)";
connection.Execute(queryInsert, store); connection.Execute(queryInsert, store);
} }
catch (Exception ex) catch (Exception ex)
@ -44,7 +44,8 @@ internal class StoreRepository : IStoreRepository
var queryUpdate = @" var queryUpdate = @"
UPDATE Stores UPDATE Stores
SET SET
Address=@Address Address=@Address,
Organisation=@Organisation
WHERE Id=@Id"; WHERE Id=@Id";
connection.Execute(queryUpdate, store); connection.Execute(queryUpdate, store);
} }

View File

@ -1,9 +1,12 @@
using Dapper; using Dapper;
using DocumentFormat.OpenXml.Office2010.Excel; using DocumentFormat.OpenXml.Office2010.Excel;
using DocumentFormat.OpenXml.Presentation;
using DocumentFormat.OpenXml.Wordprocessing;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Newtonsoft.Json; using Newtonsoft.Json;
using Npgsql; using Npgsql;
using ProjectOpticsStore.Entities; using ProjectOpticsStore.Entities;
using System.Windows.Forms;
namespace ProjectOpticsStore.Repositories.Implementations; namespace ProjectOpticsStore.Repositories.Implementations;
@ -60,12 +63,51 @@ internal class SupplyRepository : ISupplyRepository
public IEnumerable<Supply> ReadSupplies(DateTime? dateFrom = null, DateTime? dateTo = null, int? storeId = null, int? productId = null) public IEnumerable<Supply> ReadSupplies(DateTime? dateFrom = null, DateTime? dateTo = null, int? storeId = null, int? productId = null)
{ {
_logger.LogInformation("Получение всех объектов"); _logger.LogInformation("Получение всех объектов");
try try
{ {
var builder = new QueryBuilder();
if (dateFrom.HasValue)
{
builder.AddCondition("su.OperationDate >= @dateFrom");
}
if (dateTo.HasValue)
{
builder.AddCondition("su.OperationDate <= @dateTo");
}
if (storeId.HasValue)
{
builder.AddCondition("su.StoreId = @storeId");
}
if (productId.HasValue)
{
builder.AddCondition("su.ProductId = @productId");
}
using var connection = new NpgsqlConnection(_connectionString.ConnectionString); using var connection = new NpgsqlConnection(_connectionString.ConnectionString);
var querySelect = "SELECT * FROM Supplies";
var supplies = connection.Query<Supply>(querySelect); var querySelect = $@"
SELECT
su.*,
--p.Type AS ProductName,
TRIM(
CASE WHEN p.Type & 1 <> 0 THEN 'Очки, ' ELSE '' END ||
CASE WHEN p.Type & 2 <> 0 THEN 'Контактные линзы, ' ELSE '' END ||
CASE WHEN p.Type & 4 <> 0 THEN 'Солнцезащитные очки, ' ELSE '' END ||
CASE WHEN p.Type & 8 <> 0 THEN 'Оправа, ' ELSE '' END ||
CASE WHEN p.Type & 16 <> 0 THEN 'Футляры, ' ELSE '' END
, ', ') AS ProductName,
CONCAT(s.Address, ' ', s.Organisation) AS StoreName
FROM Supplies su
LEFT JOIN Products p ON p.Id = su.ProductId
LEFT JOIN Stores s ON s.Id = su.StoreId
{builder.Build()}";
var supplies = connection.Query<Supply>(querySelect, new { dateFrom, dateTo, storeId, productId });
_logger.LogDebug("Полученные объекты: {json}", JsonConvert.SerializeObject(supplies)); _logger.LogDebug("Полученные объекты: {json}", JsonConvert.SerializeObject(supplies));
return supplies; return supplies;
} }
catch (Exception ex) catch (Exception ex)