Pibd-24 Aliulov_S.R. LabWork04 #4
@ -1,8 +1,12 @@
|
||||
namespace ProjectOpticsStore.Entities;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace ProjectOpticsStore.Entities;
|
||||
|
||||
public class Customer
|
||||
{
|
||||
public int Id { get; private set; }
|
||||
|
||||
[DisplayName("ФИО заказчика")]
|
||||
public string FullName { get; private set; } = string.Empty;
|
||||
|
||||
public static Customer CreateEntity(int id, string fullName)
|
||||
|
@ -1,15 +1,33 @@
|
||||
using Newtonsoft.Json;
|
||||
using ProjectOpticsStore.Entities;
|
||||
using ProjectOpticsStore.Entities.Enums;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
|
||||
public class Order
|
||||
{
|
||||
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;
|
||||
|
||||
[DisplayName("Дата заказа")]
|
||||
public DateTime DateCreated { get; private set; }
|
||||
|
||||
[Browsable(false)]
|
||||
// Коллекция, описывающая связь "Order_Product"
|
||||
[JsonIgnore] public IEnumerable<Order_Product> OrderProducts { get; private set; } = new List<Order_Product>();
|
||||
|
||||
@ -24,16 +42,11 @@ public class Order
|
||||
OrderProducts = orderProducts
|
||||
};
|
||||
}
|
||||
|
||||
public static Order CreateOperation(TempOrderProduct tempOrderProduct, IEnumerable<Order_Product> orderProducts)
|
||||
public void SetOrderProducts(IEnumerable<Order_Product> products)
|
||||
{
|
||||
return new Order
|
||||
if (products != null && products.Any())
|
||||
{
|
||||
Id = tempOrderProduct.Id,
|
||||
CustomerId = tempOrderProduct.CustomerId,
|
||||
DateCreated = tempOrderProduct.DateCreated,
|
||||
Status = tempOrderProduct.Status,
|
||||
OrderProducts = orderProducts
|
||||
};
|
||||
OrderProducts = products;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,18 +1,26 @@
|
||||
namespace ProjectOpticsStore.Entities;
|
||||
using ProjectOpticsStore.Entities.Enums;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace ProjectOpticsStore.Entities;
|
||||
|
||||
public class Order_Product
|
||||
{
|
||||
public int OrderId { get; private set; }
|
||||
|
||||
public int ProductId { get; private set; }
|
||||
|
||||
public ProductTypeEnum Type { 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
|
||||
{
|
||||
OrderId = orderId,
|
||||
ProductId = productId,
|
||||
Type = type,
|
||||
Quantity = quantity
|
||||
};
|
||||
}
|
||||
|
@ -1,15 +1,29 @@
|
||||
using ProjectOpticsStore.Entities.Enums;
|
||||
using System.ComponentModel;
|
||||
|
||||
public class Product
|
||||
{
|
||||
public int Id { get; private set; }
|
||||
|
||||
[DisplayName("Тип Товара")]
|
||||
public ProductTypeEnum Type { get; private set; }
|
||||
|
||||
[DisplayName("Мощность")]
|
||||
public double Power { get; private set; }
|
||||
|
||||
[DisplayName("Цена")]
|
||||
public int Price { get; private set; }
|
||||
|
||||
[DisplayName("Магазин")]
|
||||
public int Store { get; private set; }
|
||||
|
||||
[DisplayName("Толщина (чево)")]
|
||||
public float Thickness { get; private set; }
|
||||
|
||||
[DisplayName("Болезнь")]
|
||||
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)
|
||||
{
|
||||
return new Product
|
||||
|
@ -1,16 +1,26 @@
|
||||
namespace ProjectOpticsStore.Entities;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace ProjectOpticsStore.Entities;
|
||||
|
||||
public class Store
|
||||
{
|
||||
public int Id { get; private set; }
|
||||
|
||||
[DisplayName("Адрес магазина")]
|
||||
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
|
||||
{
|
||||
Id = id,
|
||||
Address = address ?? string.Empty
|
||||
Address = address ?? string.Empty,
|
||||
Organisation = organisation ?? string.Empty
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -1,13 +1,30 @@
|
||||
namespace ProjectOpticsStore.Entities;
|
||||
using ProjectOpticsStore.Entities.Enums;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace ProjectOpticsStore.Entities;
|
||||
|
||||
public class Supply
|
||||
{
|
||||
public int Id { get; private set; }
|
||||
|
||||
[Browsable(false)]
|
||||
public int StoreId { get; private set; }
|
||||
public DateTime OperationDate { get; private set; }
|
||||
|
||||
[Browsable(false)]
|
||||
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; } // Количество поставленного товара
|
||||
|
||||
[DisplayName("Дата спецоперации")]
|
||||
public DateTime OperationDate { get; private set; }
|
||||
|
||||
public static Supply CreateOperation(int id, int storeId, int productId, int quantity)
|
||||
{
|
||||
return new Supply
|
||||
|
@ -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; }
|
||||
}
|
@ -84,6 +84,7 @@ public partial class FormCustomers : Form
|
||||
private void LoadList()
|
||||
{
|
||||
dataGridViewData.DataSource = _customerRepository.ReadCustomers();
|
||||
dataGridViewData.Columns["Id"].Visible = false;
|
||||
}
|
||||
|
||||
private bool TryGetIdentifierFromSelectedRow(out int id)
|
||||
|
@ -85,7 +85,7 @@
|
||||
Controls.Add(checkBoxCustomers);
|
||||
Name = "FormDirectoryReport";
|
||||
StartPosition = FormStartPosition.CenterParent;
|
||||
Text = "FormDirectoryReport";
|
||||
Text = "Отчет по т.н. справочникам";
|
||||
ResumeLayout(false);
|
||||
PerformLayout();
|
||||
}
|
||||
|
@ -19,12 +19,10 @@ public partial class FormOrder : Form
|
||||
_customerRepository = customerRepository ?? throw new ArgumentNullException(nameof(customerRepository));
|
||||
_productRepository = productRepository ?? throw new ArgumentNullException(nameof(productRepository));
|
||||
|
||||
// Настройка ComboBox для выбора клиента
|
||||
comboBoxCustomer.DataSource = _customerRepository.ReadCustomers()
|
||||
.Select(c => new { c.Id })
|
||||
.ToList();
|
||||
comboBoxCustomer.DisplayMember = "Id";
|
||||
comboBoxCustomer.ValueMember = "Id";
|
||||
// Инициализация ComboBox для магазинов
|
||||
comboBoxCustomer.DataSource = _customerRepository.ReadCustomers().ToList();
|
||||
comboBoxCustomer.DisplayMember = "FullName"; // Отображаем фио заказчиков
|
||||
comboBoxCustomer.ValueMember = "Id"; // Значение это идентификатор заказчика
|
||||
comboBoxCustomer.DropDownStyle = ComboBoxStyle.DropDownList;
|
||||
|
||||
// Настройка ComboBox для выбора статуса заказа
|
||||
@ -54,9 +52,9 @@ public partial class FormOrder : Form
|
||||
var productColumn = new DataGridViewComboBoxColumn
|
||||
{
|
||||
Name = "ColumnProduct",
|
||||
HeaderText = "Товар",
|
||||
HeaderText = "Товары",
|
||||
DataSource = _productRepository.ReadProducts()
|
||||
.Select(p => new { p.Id, p.Type }) // Пример данных: Id и Name
|
||||
.Select(p => new { p.Id, p.Type }) // Пример данных: Id и Type
|
||||
.ToList(),
|
||||
DisplayMember = "Type",
|
||||
ValueMember = "Id",
|
||||
@ -73,6 +71,15 @@ public partial class FormOrder : Form
|
||||
};
|
||||
dataGridViewProducts.Columns.Add(quantityColumn);
|
||||
|
||||
// Столбец "Тип"
|
||||
var typeColumn = new DataGridViewTextBoxColumn
|
||||
{
|
||||
Name = "ColumnType",
|
||||
ValueType = typeof(int),
|
||||
Visible = false // Скрываем столбец
|
||||
};
|
||||
dataGridViewProducts.Columns.Add(typeColumn);
|
||||
|
||||
productColumn.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)
|
||||
continue;
|
||||
|
||||
list.Add(Order_Product.CreateElement(0, Convert.ToInt32(row.Cells["ColumnProduct"].Value),
|
||||
Convert.ToInt32(row.Cells["ColumnQuantity"].Value)));
|
||||
}
|
||||
return list.GroupBy(x => x.ProductId, x => x.Quantity, (id, quantity) =>
|
||||
Order_Product.CreateElement(0, id, quantity.Sum())).ToList();
|
||||
var productId = Convert.ToInt32(row.Cells["ColumnProduct"].Value);
|
||||
var quantity = Convert.ToInt32(row.Cells["ColumnQuantity"].Value);
|
||||
// Какой же говнокод
|
||||
var typeValue = row.Cells["ColumnType"].Value?.ToString();
|
||||
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();
|
||||
}
|
||||
}
|
@ -49,12 +49,10 @@ public partial class FormOrders : Form
|
||||
// Метод для загрузки списка заказов в DataGridView
|
||||
private void LoadList()
|
||||
{
|
||||
dataGridViewOrders.DataSource = _orderRepository.ReadOrders();
|
||||
|
||||
//if (dataGridViewOrders.Columns.Contains("OrderProducts"))
|
||||
//{
|
||||
// dataGridViewOrders.Columns["OrderProducts"].Visible = false;
|
||||
//}
|
||||
dataGridViewOrders.DataSource = _orderRepository.ReadOrders();
|
||||
dataGridViewOrders.Columns["Id"].Visible = false;
|
||||
dataGridViewOrders.Columns["DateCreated"].DefaultCellStyle.Format = "dd MMMM yyyy hh:mm";
|
||||
}
|
||||
|
||||
// Метод для получения идентификатора заказа из выбранной строки в DataGridView
|
||||
|
@ -63,7 +63,7 @@ public partial class FormProduct : Form
|
||||
|
||||
// Инициализация ComboBox для магазинов
|
||||
comboBoxStore.DataSource = _storeRepository.ReadStores().ToList();
|
||||
comboBoxStore.DisplayMember = "Address"; // Отображаем адрес магазина
|
||||
comboBoxStore.DisplayMember = "FullInformation"; // Отображаем полную информацию о магазине
|
||||
comboBoxStore.ValueMember = "Id"; // Значение это идентификатор магазина
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
using ProjectOpticsStore.Entities;
|
||||
using ProjectOpticsStore.Repositories;
|
||||
using System.ComponentModel;
|
||||
using Unity;
|
||||
|
||||
namespace ProjectOpticsStore.Forms;
|
||||
@ -88,10 +89,60 @@ public partial class FormProducts : Form
|
||||
|
||||
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)
|
||||
{
|
||||
id = 0;
|
||||
|
@ -32,30 +32,34 @@
|
||||
labelFullName = new Label();
|
||||
buttonSave = new Button();
|
||||
buttonCancel = new Button();
|
||||
textBoxOrganisation = new TextBox();
|
||||
labelOrganisation = new Label();
|
||||
SuspendLayout();
|
||||
//
|
||||
// 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.Size = new Size(295, 27);
|
||||
textBoxAddress.Size = new Size(243, 23);
|
||||
textBoxAddress.TabIndex = 1;
|
||||
//
|
||||
// labelFullName
|
||||
//
|
||||
labelFullName.AutoSize = true;
|
||||
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.Size = new Size(71, 28);
|
||||
labelFullName.Size = new Size(56, 21);
|
||||
labelFullName.TabIndex = 4;
|
||||
labelFullName.Text = "Адрес:";
|
||||
//
|
||||
// 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.Size = new Size(124, 40);
|
||||
buttonSave.Size = new Size(108, 30);
|
||||
buttonSave.TabIndex = 5;
|
||||
buttonSave.Text = "Сохранить";
|
||||
buttonSave.UseVisualStyleBackColor = true;
|
||||
@ -63,23 +67,45 @@
|
||||
//
|
||||
// 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.Size = new Size(124, 40);
|
||||
buttonCancel.Size = new Size(108, 30);
|
||||
buttonCancel.TabIndex = 6;
|
||||
buttonCancel.Text = "Отмена";
|
||||
buttonCancel.UseVisualStyleBackColor = true;
|
||||
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
|
||||
//
|
||||
AutoScaleDimensions = new SizeF(8F, 20F);
|
||||
AutoScaleDimensions = new SizeF(7F, 15F);
|
||||
AutoScaleMode = AutoScaleMode.Font;
|
||||
ClientSize = new Size(469, 341);
|
||||
ClientSize = new Size(410, 256);
|
||||
Controls.Add(labelOrganisation);
|
||||
Controls.Add(textBoxOrganisation);
|
||||
Controls.Add(buttonCancel);
|
||||
Controls.Add(buttonSave);
|
||||
Controls.Add(labelFullName);
|
||||
Controls.Add(textBoxAddress);
|
||||
Margin = new Padding(3, 2, 3, 2);
|
||||
Name = "FormStore";
|
||||
Text = "Магазины";
|
||||
ResumeLayout(false);
|
||||
@ -92,5 +118,7 @@
|
||||
private Label labelFullName;
|
||||
private Button buttonSave;
|
||||
private Button buttonCancel;
|
||||
private TextBox textBoxOrganisation;
|
||||
private Label labelOrganisation;
|
||||
}
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
using ProjectOpticsStore.Entities;
|
||||
using DocumentFormat.OpenXml.Office2010.PowerPoint;
|
||||
using ProjectOpticsStore.Entities;
|
||||
using ProjectOpticsStore.Repositories;
|
||||
|
||||
namespace ProjectOpticsStore.Forms;
|
||||
@ -22,6 +23,7 @@ public partial class FormStore : Form
|
||||
}
|
||||
|
||||
textBoxAddress.Text = store.Address;
|
||||
textBoxOrganisation.Text = store.Organisation;
|
||||
_storeId = value;
|
||||
}
|
||||
catch (Exception ex)
|
||||
@ -48,6 +50,11 @@ public partial class FormStore : Form
|
||||
throw new Exception("Адрес магазина не указан.");
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(textBoxOrganisation.Text))
|
||||
{
|
||||
throw new Exception("Организация магазина не указана.");
|
||||
}
|
||||
|
||||
// Сохранение данных
|
||||
if (_storeId.HasValue)
|
||||
{
|
||||
@ -74,6 +81,6 @@ public partial class FormStore : Form
|
||||
private Store CreateStore(int id)
|
||||
{
|
||||
// Создание сущности Store
|
||||
return Store.CreateEntity(id, textBoxAddress.Text);
|
||||
return Store.CreateEntity(id, textBoxAddress.Text, textBoxOrganisation.Text);
|
||||
}
|
||||
}
|
||||
|
@ -88,6 +88,8 @@ public partial class FormStores : Form
|
||||
{
|
||||
// Загрузка списка магазинов в DataGridView
|
||||
dataGridViewStores.DataSource = _storeRepository.ReadStores().ToList();
|
||||
dataGridViewStores.Columns["Id"].Visible = false;
|
||||
dataGridViewStores.Columns["FullInformation"].Visible = false;
|
||||
}
|
||||
|
||||
private bool TryGetIdentifierFromSelectedRow(out int id)
|
||||
|
@ -44,6 +44,8 @@ public partial class FormSupplies : Form
|
||||
{
|
||||
// Загрузка списка поставок в DataGridView
|
||||
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)
|
||||
|
@ -18,12 +18,12 @@ public partial class FormSupply : Form
|
||||
|
||||
// Инициализация ComboBox для магазинов
|
||||
comboBoxStore.DataSource = _storeRepository.ReadStores().ToList();
|
||||
comboBoxStore.DisplayMember = "Address";
|
||||
comboBoxStore.DisplayMember = "FullInformation";
|
||||
comboBoxStore.ValueMember = "Id";
|
||||
|
||||
// Инициализация ComboBox для товаров
|
||||
comboBoxProduct.DataSource = _productRepository.ReadProducts().ToList();
|
||||
comboBoxProduct.DisplayMember = "Name";
|
||||
comboBoxProduct.DisplayMember = "Type";
|
||||
comboBoxProduct.ValueMember = "Id";
|
||||
|
||||
// Устанавливаем дату как текущую и блокируем редактирование
|
||||
|
@ -15,6 +15,7 @@
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Dapper" Version="2.1.35" />
|
||||
<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.Json" Version="9.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="9.0.0" />
|
||||
|
@ -1,48 +1,72 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using ProjectOpticsStore.Repositories;
|
||||
using ProjectOpticsStore.Entities;
|
||||
using ProjectOpticsStore.Entities.Enums;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ProjectOpticsStore.Reports;
|
||||
|
||||
public class ChartReport
|
||||
namespace ProjectOpticsStore.Reports
|
||||
{
|
||||
private readonly ISupplyRepository _supplyRepository; // Изменение типа репозитория
|
||||
private readonly ILogger<ChartReport> _logger;
|
||||
|
||||
public ChartReport(ISupplyRepository supplyRepository, ILogger<ChartReport> logger) // Изменение параметра конструктора
|
||||
public class ChartReport
|
||||
{
|
||||
_supplyRepository = supplyRepository ?? throw new ArgumentNullException(nameof(supplyRepository));
|
||||
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
}
|
||||
private readonly ISupplyRepository _supplyRepository; // Репозиторий для поставок
|
||||
private readonly IProductRepository _productRepository; // Репозиторий для продуктов
|
||||
private readonly ILogger<ChartReport> _logger;
|
||||
|
||||
public bool CreateChart(string filePath, DateTime dateTime)
|
||||
{
|
||||
try
|
||||
// Конструктор с зависимостями
|
||||
public ChartReport(ISupplyRepository supplyRepository, IProductRepository productRepository, ILogger<ChartReport> logger)
|
||||
{
|
||||
new PdfBuilder(filePath)
|
||||
.AddHeader("Распределение поставок по товарам") // Изменено заголовок для соответствия Supply
|
||||
.AddPieChart("Поставки", GetData(dateTime)) // Изменено название графика
|
||||
.Build();
|
||||
return true;
|
||||
_supplyRepository = supplyRepository ?? throw new ArgumentNullException(nameof(supplyRepository));
|
||||
_productRepository = productRepository ?? throw new ArgumentNullException(nameof(productRepository)); // Для получения типа продукта
|
||||
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Ошибка при формировании документа");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private List<(string Caption, double Value)> GetData(DateTime dateTime)
|
||||
{
|
||||
return _supplyRepository
|
||||
.ReadSupplies() // Изменено на метод, который читает поставки
|
||||
.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
|
||||
.Select(x => (x.ID.ToString(), (double)x.TotalQuantity)) // Изменено на TotalQuantity
|
||||
.ToList();
|
||||
// Метод для создания графика
|
||||
public bool CreateChart(string filePath, DateTime dateTime)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Создание PDF с графиком
|
||||
new PdfBuilder(filePath)
|
||||
.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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ public class DocReport
|
||||
}
|
||||
if (includeStores)
|
||||
{
|
||||
builder.AddParagraph("Магазины").AddTable([2400], GetStores());
|
||||
builder.AddParagraph("Магазины").AddTable([2400, 2400], GetStores());
|
||||
}
|
||||
if (includeProducts)
|
||||
{
|
||||
@ -58,10 +58,10 @@ public class DocReport
|
||||
private List<string[]> GetStores()
|
||||
{
|
||||
return [
|
||||
["Адрес магазина"],
|
||||
["Адрес магазина", "Организация"],
|
||||
.. _storeRepository
|
||||
.ReadStores()
|
||||
.Select(x => new string[] { x.Address}),
|
||||
.Select(x => new string[] { x.Address, x.Organisation}),
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,9 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using DocumentFormat.OpenXml.Wordprocessing;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using ProjectOpticsStore.Repositories;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace ProjectOpticsStore.Reports;
|
||||
|
||||
@ -8,7 +12,12 @@ public class TableReport
|
||||
private readonly IOrderRepository _orderRepository;
|
||||
private readonly ISupplyRepository _supplyRepository;
|
||||
private readonly ILogger<TableReport> _logger;
|
||||
internal static readonly string[] item = ["Продукт", "Дата", "Количество пришло", "Количество ушло"];
|
||||
|
||||
// Заголовки таблицы
|
||||
// Типо Order - заказ - количество ушло - заказчик, Поставка - количество пришло - магазин.
|
||||
// Поэтому в первой строчке Заказчик/Магазин а не только Заказчик. Все согласно Ерке.
|
||||
|
||||
internal static readonly string[] item = { "Заказчик", "Магазин", "Дата", "Количество пришло", "Количество ушло" };
|
||||
|
||||
public TableReport(IOrderRepository orderRepository, ISupplyRepository supplyRepository,
|
||||
ILogger<TableReport> logger)
|
||||
@ -17,15 +26,22 @@ public class TableReport
|
||||
_supplyRepository = supplyRepository ?? throw new ArgumentNullException(nameof(supplyRepository));
|
||||
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
}
|
||||
|
||||
// Метод для создания таблицы
|
||||
public bool CreateTable(string filePath, int productID, DateTime startDate, DateTime endDate)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Получение данных
|
||||
var data = GetData(productID, startDate, endDate);
|
||||
|
||||
// Создание Excel документа
|
||||
new ExcelBuilder(filePath)
|
||||
.AddHeader("Сводка по движению товара", 0, 4)
|
||||
.AddParagraph("за период", 0)
|
||||
.AddTable([10, 10, 15, 15], GetData(productID, startDate, endDate))
|
||||
.Build();
|
||||
.AddHeader("Сводка по движению товаров", 0, 4)
|
||||
.AddParagraph($"За период c {startDate:dd.MM.yyyy} по {endDate:dd.MM.yyyy}", 0)
|
||||
.AddTable(new[] { 15, 15, 12, 15, 15 }, data) // Ширины столбцов
|
||||
.Build();
|
||||
|
||||
return true;
|
||||
}
|
||||
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()
|
||||
.Where(x => x.DateCreated >= startDate && x.DateCreated <= endDate && x.OrderProducts.Any(y => y.ProductId == productID))
|
||||
.Select(x => new
|
||||
// Получение данных заказов
|
||||
var ordersData = _orderRepository
|
||||
.ReadOrders(dateFrom: startDate, dateTo: endDate, productId: productId)
|
||||
.Select(order => new
|
||||
{
|
||||
ProductID = x.OrderProducts.First(y => y.ProductId == productID).ProductId,
|
||||
Date = x.DateCreated,
|
||||
CustomerName = order.CustomerName,
|
||||
StoreName = string.Empty, // Магазин не указывается для заказов
|
||||
Date = order.DateCreated,
|
||||
CountIn = (int?)null,
|
||||
CountOut = (int?)x.OrderProducts.FirstOrDefault(y => y.ProductId == productID)?.Quantity
|
||||
})
|
||||
.Union(
|
||||
_supplyRepository
|
||||
.ReadSupplies()
|
||||
.Where(x => x.OperationDate >= startDate && x.OperationDate <= endDate && x.ProductId == productID)
|
||||
.Select(x => new
|
||||
{
|
||||
ProductID = x.ProductId,
|
||||
Date = x.OperationDate,
|
||||
CountIn = (int?)x.Quantity,
|
||||
CountOut = (int?)null
|
||||
}))
|
||||
CountOut = (int?)order.OrderProducts.Sum(op => op.Quantity)
|
||||
});
|
||||
|
||||
// Получение данных поставок
|
||||
var suppliesData = _supplyRepository
|
||||
.ReadSupplies(dateFrom: startDate, dateTo: endDate, productId: productId)
|
||||
.Select(supply => new
|
||||
{
|
||||
CustomerName = string.Empty, // Заказчик не указывается для поставок
|
||||
StoreName = supply.StoreName,
|
||||
Date = supply.OperationDate,
|
||||
CountIn = (int?)supply.Quantity,
|
||||
CountOut = (int?)null
|
||||
});
|
||||
|
||||
// Объединение и сортировка данных
|
||||
var combinedData = ordersData
|
||||
.Union(suppliesData)
|
||||
.OrderBy(x => x.Date);
|
||||
|
||||
return
|
||||
new List<string[]> { TableReport.item }
|
||||
// Формирование таблицы
|
||||
return new List<string[]> { item } // Добавляем заголовок таблицы
|
||||
.Union(
|
||||
data.Select(x => new string[]
|
||||
{
|
||||
x.ProductID.ToString(),
|
||||
x.Date.ToString(),
|
||||
x.CountIn?.ToString() ?? string.Empty,
|
||||
x.CountOut?.ToString() ?? string.Empty
|
||||
}))
|
||||
.Union(new[] {
|
||||
new[] { "Всего", "", data.Sum(x => x.CountIn ?? 0).ToString(), data.Sum(x => x.CountOut ?? 0).ToString() }
|
||||
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
|
||||
})
|
||||
)
|
||||
.Union(new[]
|
||||
{
|
||||
// Итоговая строка
|
||||
new string[] { "Всего", "", "", combinedData.Sum(entry => entry.CountIn ?? 0).ToString("N0"), combinedData.Sum(entry => entry.CountOut ?? 0).ToString("N0")}
|
||||
})
|
||||
.ToList();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -5,7 +5,8 @@ public interface IOrderRepository
|
||||
IEnumerable<Order> ReadOrders(
|
||||
DateTime? dateFrom = null,
|
||||
DateTime? dateTo = null,
|
||||
int? customerId = null
|
||||
int? customerId = null,
|
||||
int? productId = null
|
||||
);
|
||||
void CreateOrder(Order order);
|
||||
}
|
||||
|
@ -1,8 +1,11 @@
|
||||
using Dapper;
|
||||
using DocumentFormat.OpenXml.Wordprocessing;
|
||||
using Microsoft.AspNetCore.Http.Extensions;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Newtonsoft.Json;
|
||||
using Npgsql;
|
||||
using ProjectOpticsStore.Entities;
|
||||
using ProjectOpticsStore.Entities.Enums;
|
||||
using Unity;
|
||||
|
||||
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("Получение всех объектов");
|
||||
|
||||
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);
|
||||
|
||||
var querySelect = @"SELECT o.*, op.OrderId, op.ProductId, op.Quantity
|
||||
FROM Orders o
|
||||
INNER JOIN Orders_Products op ON op.OrderId = o.Id";
|
||||
var querySelect = $@"
|
||||
SELECT 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);
|
||||
|
||||
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
|
||||
.GroupBy(
|
||||
x => x.Id,
|
||||
y => y,
|
||||
(key, value) => Order.CreateOperation(
|
||||
value.First(),
|
||||
value.Select(z => Order_Product.CreateElement(z.OrderId, z.ProductId, z.Quantity))
|
||||
)
|
||||
).ToList();
|
||||
products.Add(Order_Product.CreateElement(order.Id, orderProduct.ProductId, orderProduct.Type, orderProduct.Quantity));
|
||||
return order;
|
||||
},
|
||||
splitOn: "ProductId",
|
||||
param: new { dateFrom, dateTo, customerId, productId });
|
||||
|
||||
_logger.LogDebug("Полученные объекты: {json}", JsonConvert.SerializeObject(orders));
|
||||
|
||||
return orderDict.Select(x =>
|
||||
{
|
||||
var order = orders.First(y => y.Id == x.Key);
|
||||
order.SetOrderProducts(x.Value);
|
||||
return order;
|
||||
}).ToArray();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
@ -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}";
|
||||
}
|
||||
}
|
@ -24,8 +24,8 @@ internal class StoreRepository : IStoreRepository
|
||||
{
|
||||
using var connection = new NpgsqlConnection(_connectionString.ConnectionString);
|
||||
var queryInsert = @"
|
||||
INSERT INTO Stores (Address)
|
||||
VALUES (@Address)";
|
||||
INSERT INTO Stores (Address, Organisation)
|
||||
VALUES (@Address, @Organisation)";
|
||||
connection.Execute(queryInsert, store);
|
||||
}
|
||||
catch (Exception ex)
|
||||
@ -44,7 +44,8 @@ internal class StoreRepository : IStoreRepository
|
||||
var queryUpdate = @"
|
||||
UPDATE Stores
|
||||
SET
|
||||
Address=@Address
|
||||
Address=@Address,
|
||||
Organisation=@Organisation
|
||||
WHERE Id=@Id";
|
||||
connection.Execute(queryUpdate, store);
|
||||
}
|
||||
|
@ -1,9 +1,12 @@
|
||||
using Dapper;
|
||||
using DocumentFormat.OpenXml.Office2010.Excel;
|
||||
using DocumentFormat.OpenXml.Presentation;
|
||||
using DocumentFormat.OpenXml.Wordprocessing;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Newtonsoft.Json;
|
||||
using Npgsql;
|
||||
using ProjectOpticsStore.Entities;
|
||||
using System.Windows.Forms;
|
||||
|
||||
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)
|
||||
{
|
||||
_logger.LogInformation("Получение всех объектов");
|
||||
|
||||
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);
|
||||
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));
|
||||
|
||||
return supplies;
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
Loading…
Reference in New Issue
Block a user