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

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 int Id { get; private set; }
[DisplayName("ФИО заказчика")]
public string FullName { get; private set; } = string.Empty;
public static Customer CreateEntity(int id, string fullName)

View File

@ -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;
}
}
}

View File

@ -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
};
}

View File

@ -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

View File

@ -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
};
}
}

View File

@ -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

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()
{
dataGridViewData.DataSource = _customerRepository.ReadCustomers();
dataGridViewData.Columns["Id"].Visible = false;
}
private bool TryGetIdentifierFromSelectedRow(out int id)

View File

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

View File

@ -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();
}
}

View File

@ -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

View File

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

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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)

View File

@ -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)

View File

@ -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";
// Устанавливаем дату как текущую и блокируем редактирование

View File

@ -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" />

View File

@ -1,31 +1,38 @@
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;
namespace ProjectOpticsStore.Reports
{
public class ChartReport
{
private readonly ISupplyRepository _supplyRepository; // Изменение типа репозитория
private readonly ISupplyRepository _supplyRepository; // Репозиторий для поставок
private readonly IProductRepository _productRepository; // Репозиторий для продуктов
private readonly ILogger<ChartReport> _logger;
public ChartReport(ISupplyRepository supplyRepository, ILogger<ChartReport> logger) // Изменение параметра конструктора
// Конструктор с зависимостями
public ChartReport(ISupplyRepository supplyRepository, IProductRepository productRepository, ILogger<ChartReport> logger)
{
_supplyRepository = supplyRepository ?? throw new ArgumentNullException(nameof(supplyRepository));
_productRepository = productRepository ?? throw new ArgumentNullException(nameof(productRepository)); // Для получения типа продукта
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
// Метод для создания графика
public bool CreateChart(string filePath, DateTime dateTime)
{
try
{
// Создание PDF с графиком
new PdfBuilder(filePath)
.AddHeader("Распределение поставок по товарам") // Изменено заголовок для соответствия Supply
.AddPieChart("Поставки", GetData(dateTime)) // Изменено название графика
.AddHeader("Распределение поставок по товарам") // Заголовок
.AddPieChart($"Поставки на {dateTime:dd MMMM yyyy}", GetData(dateTime)) // График
.Build();
return true;
}
@ -36,13 +43,30 @@ public class ChartReport
}
}
// Метод для получения данных для графика
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
// Получаем все поставки для заданной даты
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)
{
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}),
];
}

View File

@ -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))
.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
CountOut = (int?)order.OrderProducts.Sum(op => op.Quantity)
});
// Получение данных поставок
var suppliesData = _supplyRepository
.ReadSupplies(dateFrom: startDate, dateTo: endDate, productId: productId)
.Select(supply => new
{
ProductID = x.ProductId,
Date = x.OperationDate,
CountIn = (int?)x.Quantity,
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[]
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[]
{
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() }
// Итоговая строка
new string[] { "Всего", "", "", combinedData.Sum(entry => entry.CountIn ?? 0).ToString("N0"), combinedData.Sum(entry => entry.CountOut ?? 0).ToString("N0")}
})
.ToList();
}
}

View File

@ -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);
}

View File

@ -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
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
INNER JOIN Orders_Products op ON op.OrderId = o.Id";
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)
{

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);
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);
}

View File

@ -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)