Лабораторная_2_сложн

This commit is contained in:
yuliya.mavrina@internet.ru 2024-03-30 20:02:35 +03:00
parent 02c8423739
commit 21a3fe7c63
21 changed files with 802 additions and 60 deletions

View File

@ -40,6 +40,7 @@
buttonOrderReady = new Button();
buttonIssuedOrder = new Button();
buttonRef = new Button();
SalesToolStripMenuItem = new ToolStripMenuItem();
menuStrip.SuspendLayout();
((System.ComponentModel.ISupportInitialize)dataGridView).BeginInit();
SuspendLayout();
@ -55,7 +56,7 @@
//
// refbooksToolStripMenuItem
//
refbooksToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { componentsToolStripMenuItem, JobTypeToolStripMenuItem, ShopsToolStripMenuItem, SupplyToolStripMenuItem });
refbooksToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { componentsToolStripMenuItem, JobTypeToolStripMenuItem, ShopsToolStripMenuItem, SupplyToolStripMenuItem, SalesToolStripMenuItem });
refbooksToolStripMenuItem.Name = "refbooksToolStripMenuItem";
refbooksToolStripMenuItem.Size = new Size(94, 20);
refbooksToolStripMenuItem.Text = "Справочники";
@ -148,6 +149,13 @@
buttonRef.UseVisualStyleBackColor = true;
buttonRef.Click += buttonRef_Click;
//
// SalesToolStripMenuItem
//
SalesToolStripMenuItem.Name = "SalesToolStripMenuItem";
SalesToolStripMenuItem.Size = new Size(198, 22);
SalesToolStripMenuItem.Text = "Продажи";
SalesToolStripMenuItem.Click += SalesToolStripMenuItem_Click;
//
// FormMain
//
AutoScaleDimensions = new SizeF(7F, 15F);
@ -185,5 +193,6 @@
private Button buttonRef;
private ToolStripMenuItem ShopsToolStripMenuItem;
private ToolStripMenuItem SupplyToolStripMenuItem;
private ToolStripMenuItem SalesToolStripMenuItem;
}
}

View File

@ -172,6 +172,15 @@ namespace RenovationWorkView
form.ShowDialog();
}
}
private void SalesToolStripMenuItem_Click(object sender, EventArgs e)
{
var service = Program.ServiceProvider?.GetService(typeof(FormSell));
if (service is FormSell form)
{
form.ShowDialog();
}
}
}
}

View File

@ -0,0 +1,118 @@
namespace RenovationWorkView
{
partial class FormSell
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
buttonSave = new Button();
buttonCancel = new Button();
labelRepair = new Label();
labelCount = new Label();
textBoxCount = new TextBox();
comboBoxRepair = new ComboBox();
SuspendLayout();
//
// buttonSave
//
buttonSave.Location = new Point(233, 74);
buttonSave.Name = "buttonSave";
buttonSave.Size = new Size(75, 23);
buttonSave.TabIndex = 0;
buttonSave.Text = "Сохранить";
buttonSave.UseVisualStyleBackColor = true;
buttonSave.Click += buttonSave_Click;
//
// buttonCancel
//
buttonCancel.Location = new Point(314, 74);
buttonCancel.Name = "buttonCancel";
buttonCancel.Size = new Size(75, 23);
buttonCancel.TabIndex = 1;
buttonCancel.Text = "Отмена";
buttonCancel.UseVisualStyleBackColor = true;
buttonCancel.Click += buttonCancel_Click;
//
// labelRepair
//
labelRepair.AutoSize = true;
labelRepair.Location = new Point(12, 9);
labelRepair.Name = "labelRepair";
labelRepair.Size = new Size(56, 15);
labelRepair.TabIndex = 2;
labelRepair.Text = "Изделие:";
//
// labelCount
//
labelCount.AutoSize = true;
labelCount.Location = new Point(12, 46);
labelCount.Name = "labelCount";
labelCount.Size = new Size(75, 15);
labelCount.TabIndex = 3;
labelCount.Text = "Количество:";
//
// textBoxCount
//
textBoxCount.Location = new Point(100, 38);
textBoxCount.Name = "textBoxCount";
textBoxCount.Size = new Size(107, 23);
textBoxCount.TabIndex = 4;
//
// comboBoxRepair
//
comboBoxRepair.FormattingEnabled = true;
comboBoxRepair.Location = new Point(100, 6);
comboBoxRepair.Name = "comboBoxRepair";
comboBoxRepair.Size = new Size(289, 23);
comboBoxRepair.TabIndex = 5;
//
// FormSell
//
AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(401, 109);
Controls.Add(comboBoxRepair);
Controls.Add(textBoxCount);
Controls.Add(labelCount);
Controls.Add(labelRepair);
Controls.Add(buttonCancel);
Controls.Add(buttonSave);
Name = "FormSell";
Text = "Продажи";
ResumeLayout(false);
PerformLayout();
}
#endregion
private Button buttonSave;
private Button buttonCancel;
private Label labelRepair;
private Label labelCount;
private TextBox textBoxCount;
private ComboBox comboBoxRepair;
}
}

View File

@ -0,0 +1,116 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using RenovationWorkContracts.ViewModels;
using RenovationWorkDataModels.Models;
using Microsoft.Extensions.Logging;
using RenovationWorkContracts.BusinessLogicsContracts;
using RenovationWorkBusinessLogic.BusinessLogics;
namespace RenovationWorkView
{
public partial class FormSell : Form
{
private readonly List<RepairViewModel>? _repairList;
IShopLogic _shopLogic;
IRepairLogic _repairLogic;
public FormSell(IRepairLogic repairLogic, IShopLogic shopLogic)
{
InitializeComponent();
_shopLogic = shopLogic;
_repairLogic = repairLogic;
_repairList = repairLogic.ReadList(null);
if (_repairList != null)
{
comboBoxRepair.DisplayMember = "RepairName";
comboBoxRepair.ValueMember = "Id";
comboBoxRepair.DataSource = _repairList;
comboBoxRepair.SelectedItem = null;
}
}
public int RepairId
{
get
{
return Convert.ToInt32(comboBoxRepair.SelectedValue);
}
set
{
comboBoxRepair.SelectedValue = value;
}
}
public IRepairModel? RepairModel
{
get
{
if (_repairList == null)
{
return null;
}
foreach (var elem in _repairList)
{
if (elem.Id == RepairId)
{
return elem;
}
}
return null;
}
}
public int Count
{
get { return Convert.ToInt32(textBoxCount.Text); }
set
{ textBoxCount.Text = value.ToString(); }
}
private void buttonSave_Click(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(textBoxCount.Text))
{
MessageBox.Show("Заполните поле Количество", "Ошибка",
MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
if (comboBoxRepair.SelectedValue == null)
{
MessageBox.Show("Выберите изделие", "Ошибка",
MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
try
{
int count = Convert.ToInt32(textBoxCount.Text);
var manufacture = _repairLogic.ReadElement(new() { Id = Convert.ToInt32(comboBoxRepair.SelectedValue) });
if (manufacture == null)
{
throw new ApplicationException("Ошибка при продаже. Ошибка получения данных об элементе.");
}
if (!_shopLogic.SellRepairs(manufacture, count))
{
throw new ApplicationException("Ошибка при продаже. Недостаточно изделий данного типа в магазинах.");
}
MessageBox.Show("Продажа прошла успешно");
DialogResult = DialogResult.OK;
Close();
}
catch (Exception)
{
MessageBox.Show("Ошибка при продаже.");
return;
}
}
private void buttonCancel_Click(object sender, EventArgs e)
{
DialogResult = DialogResult.Cancel;
Close();
}
}
}

View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -41,7 +41,10 @@
ColumnCount = new DataGridViewTextBoxColumn();
buttonSave = new Button();
buttonCancel = new Button();
labelCapancy = new Label();
CapacityUpDown = new NumericUpDown();
((System.ComponentModel.ISupportInitialize)dataGridView).BeginInit();
((System.ComponentModel.ISupportInitialize)CapacityUpDown).BeginInit();
SuspendLayout();
//
// labelName
@ -96,10 +99,10 @@
//
dataGridView.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize;
dataGridView.Columns.AddRange(new DataGridViewColumn[] { ColumnId, ColumnName, ColumnPrice, ColumnCount });
dataGridView.Location = new Point(12, 108);
dataGridView.Location = new Point(12, 126);
dataGridView.Name = "dataGridView";
dataGridView.RowTemplate.Height = 25;
dataGridView.Size = new Size(770, 250);
dataGridView.Size = new Size(770, 232);
dataGridView.TabIndex = 6;
//
// ColumnId
@ -149,11 +152,29 @@
buttonCancel.UseVisualStyleBackColor = true;
buttonCancel.Click += buttonCancel_Click;
//
// labelCapancy
//
labelCapancy.AutoSize = true;
labelCapancy.Location = new Point(12, 99);
labelCapancy.Name = "labelCapancy";
labelCapancy.Size = new Size(83, 15);
labelCapancy.TabIndex = 9;
labelCapancy.Text = "Вместимость:";
//
// CapacityUpDown
//
CapacityUpDown.Location = new Point(106, 97);
CapacityUpDown.Name = "CapacityUpDown";
CapacityUpDown.Size = new Size(229, 23);
CapacityUpDown.TabIndex = 10;
//
// FormShop
//
AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(790, 411);
Controls.Add(CapacityUpDown);
Controls.Add(labelCapancy);
Controls.Add(buttonCancel);
Controls.Add(buttonSave);
Controls.Add(dataGridView);
@ -167,6 +188,7 @@
Text = "Магазин";
Load += FormShop_Load;
((System.ComponentModel.ISupportInitialize)dataGridView).EndInit();
((System.ComponentModel.ISupportInitialize)CapacityUpDown).EndInit();
ResumeLayout(false);
PerformLayout();
}
@ -186,5 +208,7 @@
private DataGridViewTextBoxColumn ColumnCount;
private Button buttonSave;
private Button buttonCancel;
private Label labelCapancy;
private NumericUpDown CapacityUpDown;
}
}

View File

@ -45,7 +45,8 @@ namespace RenovationWorkView
textBoxName.Text = shop.ShopName;
textBoxAddress.Text = shop.Address;
dateTimePicker.Text = shop.OpeningDate.ToString();
_repairs = shop.ShopRepairs;
_repairs = shop.ShopRepairs ?? new Dictionary<int, (IRepairModel, int)>();
CapacityUpDown.Value = shop.MaxCapacity;
}
LoadData();
}
@ -101,7 +102,7 @@ namespace RenovationWorkView
ShopName = textBoxName.Text,
Address = textBoxAddress.Text,
OpeningDate = dateTimePicker.Value.Date,
ShopRepairs = _repairs
MaxCapacity = Convert.ToInt32(CapacityUpDown.Value)
};
var operationResult = _id.HasValue ? _logic.Update(model) : _logic.Create(model);
if (!operationResult)

View File

@ -100,7 +100,7 @@ namespace RenovationWorkView
}
if (comboBoxRepair.SelectedValue == null)
{
MessageBox.Show("Выберите кузнечное изделие", "Ошибка",
MessageBox.Show("Выберите ремонтное изделие", "Ошибка",
MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}

View File

@ -52,6 +52,7 @@ namespace RenovationWorkView
services.AddTransient<FormShop>();
services.AddTransient<FormShops>();
services.AddTransient<FormSupply>();
services.AddTransient<FormSell>();
}
}
}

View File

@ -9,6 +9,7 @@ using RenovationWorkContracts.SearchModels;
using RenovationWorkContracts.StoragesContracts;
using RenovationWorkContracts.ViewModels;
using RenovationWorkDataModels.Enums;
using RenovationWorkDataModels.Models;
using Microsoft.Extensions.Logging;
namespace RenovationWorkBusinessLogic.BusinessLogics
@ -17,10 +18,17 @@ namespace RenovationWorkBusinessLogic.BusinessLogics
{
private readonly ILogger _logger;
private readonly IOrderStorage _orderStorage;
public OrderLogic(ILogger<OrderLogic> logger, IOrderStorage orderStorage)
private readonly IShopLogic _shopLogic;
private readonly IRepairStorage _repairStorage;
private readonly IShopStorage _shopStorage;
public OrderLogic(ILogger<OrderLogic> logger, IOrderStorage orderStorage,
IRepairStorage repairStorage, IShopLogic shopLogic, IShopStorage shopStorage)
{
_logger = logger;
_orderStorage = orderStorage;
_repairStorage = repairStorage;
_shopLogic = shopLogic;
_shopStorage = shopStorage;
}
public bool CreateOrder(OrderBindingModel model)
{
@ -39,31 +47,38 @@ namespace RenovationWorkBusinessLogic.BusinessLogics
}
return true;
}
public bool StatusUpdate(OrderBindingModel model, OrderStatus newStatus)
private bool StatusUpdate(OrderBindingModel model, OrderStatus status)
{
var viewModel = _orderStorage.GetElement(new OrderSearchModel { Id = model.Id });
if (viewModel == null)
CheckModel(model);
var element = _orderStorage.GetElement(new OrderSearchModel { Id = model.Id });
if (element == null)
{
throw new ArgumentNullException(nameof(model));
}
if (viewModel.Status + 1 != newStatus)
{
_logger.LogWarning("Update operation failed. Order status incorrect.");
_logger.LogWarning("Read operation failed");
return false;
}
model.Status = newStatus;
if (model.Status == OrderStatus.Готов) model.DateImplement = DateTime.Now;
else
if (element.Status != status - 1)
{
model.DateImplement = viewModel.DateImplement;
_logger.LogWarning("Status change operation failed");
throw new InvalidOperationException("Текущий статус заказа не может быть переведен в выбранный");
}
CheckModel(model, false);
if (_orderStorage.Update(model) == null)
if (element.Status == OrderStatus.Готов)
{
model.Status--;
_logger.LogWarning("Update operation failed");
return false;
var manufacture = _repairStorage.GetElement(new RepairSearchModel() { Id = model.RepairId });
if (manufacture == null)
{
_logger.LogWarning("Status update to " + status.ToString() + " operation failed. Document not found.");
return false;
}
if (CheckSupply(manufacture, model.Count) == false)
{
_logger.LogWarning("Status update to " + status.ToString() + " operation failed. Shop supply error.");
return false;
}
}
model.Status = status;
if (model.Status == OrderStatus.Выдан)
model.DateImplement = DateTime.Now;
_orderStorage.Update(model);
return true;
}
public bool DeliveryOrder(OrderBindingModel model)
@ -115,5 +130,60 @@ namespace RenovationWorkBusinessLogic.BusinessLogics
}
_logger.LogInformation("Order. Count: {Count}. Sum: {Sum}. Id: {Id}", model.Count, model.Sum, model.Id);
}
private bool CheckSupply(IRepairModel repair, int count)
{
if (count <= 0)
{
_logger.LogWarning("Check then supply operation error. Repair count < 0.");
return false;
}
int sumCapacity = 0;
int sumCount = 0;
sumCapacity = _shopStorage.GetFullList().Select(x => x.MaxCapacity).Sum();
sumCount = _shopStorage.GetFullList().Select(x => x.ShopRepairs.Select(y => y.Value.Item2).Sum()).Sum();
int freeSpace = sumCapacity - sumCount;
if (freeSpace - count < 0)
{
_logger.LogWarning("Check then supply operation error. There's no place for new Repair in shops.");
return false;
}
foreach (var shop in _shopStorage.GetFullList())
{
freeSpace = shop.MaxCapacity;
foreach (var doc in shop.ShopRepairs)
{
freeSpace -= doc.Value.Item2;
}
if (freeSpace == 0)
{
continue;
}
if (freeSpace - count >= 0)
{
if (_shopLogic.ReplenishRepairs(new() { Id = shop.Id }, repair, count))
count = 0;
else
{
_logger.LogWarning("Supply error");
return false;
}
}
if (freeSpace - count < 0)
{
if (_shopLogic.ReplenishRepairs(new() { Id = shop.Id }, repair, freeSpace))
count -= freeSpace;
else
{
_logger.LogWarning("Supply error");
return false;
}
}
if (count <= 0)
{
return true;
}
}
return false;
}
}
}

View File

@ -84,44 +84,61 @@ namespace RenovationWorkBusinessLogic.BusinessLogics
}
public bool ReplenishRepairs(ShopSearchModel model, IRepairModel repair, int count)
{
_logger.LogInformation("Try to replenish repairs. ShopName:{ShopName}. Id:{Id}", model.ShopName, model.Id);
if (model == null)
throw new ArgumentNullException(nameof(model));
ShopViewModel? curModel = ReadElement(model);
if (curModel == null)
{
_logger.LogWarning("Read operation failed");
return false;
_logger.LogInformation("Try to replenish repairs. ShopName:{ShopName}. Id:{Id}", model.ShopName, model.Id);
if (model == null)
{
_logger.LogWarning("Read operation failed");
throw new ArgumentNullException(nameof(model));
}
ShopViewModel? curModel = ReadElement(model);
if (curModel == null)
{
_logger.LogWarning("Read operation failed");
throw new ArgumentNullException(nameof(curModel));
}
if (repair == null)
{
_logger.LogWarning("Read operation failed");
throw new ArgumentNullException(nameof(repair));
}
if (count <= 0)
{
_logger.LogWarning("Read operation failed");
throw new ArgumentException("Количество должно быть положительным");
}
int countItems = curModel.ShopRepairs.Select(x => x.Value.Item2).Sum();
if (curModel.MaxCapacity - countItems >= count)
{
if (curModel.ShopRepairs.TryGetValue(repair.Id, out var sameDocument))
{
curModel.ShopRepairs[repair.Id] = (repair, sameDocument.Item2 + count);
_logger.LogInformation("Same repair found by supply. Added {0} of {1} in {2} shop", count, repair.RepairName, curModel.ShopName);
}
else
{
curModel.ShopRepairs[repair.Id] = (repair, count);
_logger.LogInformation("New repair added by supply. Added {0} of {1} in {2} shop", count, repair.RepairName, curModel.ShopName);
}
_shopStorage.Update(new()
{
Id = curModel.Id,
ShopName = curModel.ShopName,
Address = curModel.Address,
OpeningDate = curModel.OpeningDate,
ShopRepairs = curModel.ShopRepairs,
MaxCapacity = curModel.MaxCapacity
});
}
else
{
_logger.LogWarning("Required shop is overflowed");
return false;
}
return true;
}
if (repair == null)
throw new ArgumentNullException(nameof(repair));
if (count <= 0)
throw new ArgumentException("Количество должно быть положительным числом");
//попытка найти информацию о товаре в магазине по его идентификатору в словаре
//найден и добавляется
if (curModel.ShopRepairs.TryGetValue(repair.Id, out var pair))
{
curModel.ShopRepairs[repair.Id] = (pair.Item1, pair.Item2 + count);
}
//не найден и добавляется
else
{
curModel.ShopRepairs.Add(repair.Id, (repair, count));
}
Update(new()
{
Id = curModel.Id,
ShopName = curModel.ShopName,
OpeningDate = curModel.OpeningDate,
Address = curModel.Address,
ShopRepairs = curModel.ShopRepairs,
});
_logger.LogInformation("Success. RepairName:{RepairName}. Id:{Id}. Replenish:{count}",
repair.RepairName, repair.Id, count);
return true;
}
private void CheckModel(ShopBindingModel model, bool withParams = true)
private void CheckModel(ShopBindingModel model, bool withParams = true)
{
if (model == null)
{
@ -150,6 +167,10 @@ namespace RenovationWorkBusinessLogic.BusinessLogics
throw new InvalidOperationException("Магазин с таким названием уже есть");
}
}
public bool SellRepairs(IRepairModel repair, int count)
{
return _shopStorage.SellRepairs(repair, count);
}
}
}

View File

@ -13,6 +13,7 @@ namespace RenovationWorkContracts.BindingModels
public string ShopName { get; set; } = string.Empty;
public string Address { get; set; } = string.Empty;
public DateTime OpeningDate { get; set; }
public int MaxCapacity { get; set; }
public Dictionary<int, (IRepairModel, int)> ShopRepairs { get; set; } = new();
}
}

View File

@ -18,5 +18,6 @@ namespace RenovationWorkContracts.BusinessLogicsContracts
bool Update(ShopBindingModel model);
bool Delete(ShopBindingModel model);
bool ReplenishRepairs(ShopSearchModel shop, IRepairModel repair, int count);
bool SellRepairs(IRepairModel repair, int count);
}
}

View File

@ -6,6 +6,7 @@ using System.Threading.Tasks;
using RenovationWorkContracts.BindingModels;
using RenovationWorkContracts.SearchModels;
using RenovationWorkContracts.ViewModels;
using RenovationWorkDataModels.Models;
namespace RenovationWorkContracts.StoragesContracts
{
@ -17,5 +18,6 @@ namespace RenovationWorkContracts.StoragesContracts
ShopViewModel? Insert(ShopBindingModel model);
ShopViewModel? Update(ShopBindingModel model);
ShopViewModel? Delete(ShopBindingModel model);
public bool SellRepairs(IRepairModel model, int count);
}
}

View File

@ -17,6 +17,8 @@ namespace RenovationWorkContracts.ViewModels
public string Address { get; set; } = string.Empty;
[DisplayName("Дата открытия")]
public DateTime OpeningDate { get; set; }
[DisplayName("Вместимость")]
public int MaxCapacity { get; set; }
public Dictionary<int, (IRepairModel, int)> ShopRepairs { get; set; } = new();
}
}

View File

@ -11,6 +11,7 @@ namespace RenovationWorkDataModels.Models
string ShopName { get; }
string Address { get; }
DateTime OpeningDate { get; }
int MaxCapacity { get; }
Dictionary<int, (IRepairModel, int)> ShopRepairs { get; }
}
}

View File

@ -15,6 +15,8 @@ namespace RenovationWorkFileImplement
private readonly string ComponentFileName = "Component.xml";
private readonly string OrderFileName = "Order.xml";
private readonly string RepairFileName = "Repair.xml";
private readonly string ShopFileName = "Shops.xml";
public List<Shop> Shops { get; private set; }
public List<Component> Components { get; private set; }
public List<Order> Orders { get; private set; }
public List<Repair> Repairs { get; private set; }
@ -27,10 +29,10 @@ namespace RenovationWorkFileImplement
}
return instance;
}
public void SaveComponents() => SaveData(Components, ComponentFileName, "Components", x => x.GetXElement);
public void SaveRepairs() => SaveData(Repairs, RepairFileName, "Repairs", x => x.GetXElement);
public void SaveOrders() => SaveData(Orders, OrderFileName, "Orders", x => x.GetXElement);
public void SaveShops() => SaveData(Shops, ShopFileName,"Shops", x => x.GetXElement);
private DataFileSingleton()
{
Components = LoadData(ComponentFileName, "Component", x =>
@ -39,6 +41,8 @@ namespace RenovationWorkFileImplement
Repair.Create(x)!)!;
Orders = LoadData(OrderFileName, "Order", x =>
Order.Create(x)!)!;
Shops = LoadData(ShopFileName, "Shop", x =>
Shop.Create(x)!)!;
}
private static List<T>? LoadData<T>(string filename, string xmlNodeName, Func<XElement, T> selectFunction)
{

View File

@ -0,0 +1,129 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using RenovationWorkFileImplement;
using RenovationWorkContracts.BindingModels;
using RenovationWorkContracts.SearchModels;
using RenovationWorkContracts.StoragesContracts;
using RenovationWorkContracts.ViewModels;
using RenovationWorkDataModels.Models;
using RenovationWorkFileImplement.Models;
namespace RenovationWorkFileImplement.Implements
{
public class ShopStorage : IShopStorage
{
private readonly DataFileSingleton _source;
public ShopStorage()
{
_source = DataFileSingleton.GetInstance();
}
public List<ShopViewModel> GetFullList()
{
return _source.Shops
.Select(x => x.GetViewModel)
.ToList();
}
public List<ShopViewModel> GetFilteredList(ShopSearchModel
model)
{
if (string.IsNullOrEmpty(model.ShopName))
{
return new();
}
return _source.Shops
.Where(x => x.ShopName.Contains(model.ShopName))
.Select(x => x.GetViewModel)
.ToList(); ;
}
public ShopViewModel? GetElement(ShopSearchModel model)
{
if (string.IsNullOrEmpty(model.ShopName) && !model.Id.HasValue)
{
return null;
}
return _source.Shops
.FirstOrDefault(x => (!string.IsNullOrEmpty(model.ShopName) && x.ShopName ==
model.ShopName) || (model.Id.HasValue && x.Id == model.Id))?.GetViewModel;
}
public ShopViewModel? Insert(ShopBindingModel model)
{
model.Id = _source.Shops.Count > 0 ? _source.Shops.Max(x =>
x.Id) + 1 : 1;
var newShop = Shop.Create(model);
if (newShop == null)
{
return null;
}
_source.Shops.Add(newShop);
_source.SaveShops();
return newShop.GetViewModel;
}
public ShopViewModel? Update(ShopBindingModel model)
{
var component = _source.Shops.FirstOrDefault(x => x.Id ==
model.Id);
if (component == null)
{
return null;
}
component.Update(model);
_source.SaveShops();
return component.GetViewModel;
}
public ShopViewModel? Delete(ShopBindingModel model)
{
var element = _source.Shops.FirstOrDefault(x => x.Id ==
model.Id);
if (element != null)
{
_source.Shops.Remove(element);
_source.SaveShops();
return element.GetViewModel;
}
return null;
}
private bool CheckSell(int RepairId, int count)
{
count -= _source.Shops.Select(x => x.ShopRepairs.Select(y =>
(y.Value.Item1.Id == RepairId ? y.Value.Item2 : 0)).Sum()).Sum();
return count <= 0;
}
public bool SellRepairs(IRepairModel model, int count)
{
var neededRepair = _source.Repairs.FirstOrDefault(x => x.Id == model.Id);
if (neededRepair == null || !CheckSell(neededRepair.Id, count))
{
return false;
}
for (int i = 0; i < _source.Shops.Count; i++)
{
var shop = _source.Shops[i];
var assortment = shop.ShopRepairs;
foreach (var repair in assortment.Where(x => x.Value.Item1.Id == neededRepair.Id))
{
var min = Math.Min(repair.Value.Item2, count);
assortment[repair.Value.Item1.Id] = (repair.Value.Item1, repair.Value.Item2 - min);
count -= min;
if (count <= 0)
{
break;
}
}
shop.Update(new ShopBindingModel
{
Id = shop.Id,
ShopName = shop.ShopName,
Address = shop.Address,
OpeningDate = shop.OpeningDate,
MaxCapacity = shop.MaxCapacity,
ShopRepairs = assortment
});
}
_source.SaveShops();
return true;
}
}
}

View File

@ -0,0 +1,107 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using RenovationWorkFileImplement;
using RenovationWorkContracts.BindingModels;
using RenovationWorkContracts.ViewModels;
using RenovationWorkDataModels.Models;
using System.Xml.Linq;
namespace RenovationWorkFileImplement.Models
{
public class Shop : IShopModel
{
public int Id { get; private set; }
public string ShopName { get; private set; } = string.Empty;
public string Address { get; private set; } = string.Empty;
public DateTime OpeningDate { get; private set; }
public int MaxCapacity { get; private set; }
public Dictionary<int, int> Repairs { get; private set; } = new();
private Dictionary<int, (IRepairModel, int)>? _shopRepairs = null;
public Dictionary<int, (IRepairModel, int)> ShopRepairs
{
get
{
if (_shopRepairs == null)
{
var source = DataFileSingleton.GetInstance();
_shopRepairs = Repairs.ToDictionary(x => x.Key, y =>
((source.Repairs.FirstOrDefault(z => z.Id == y.Key) as IRepairModel)!,
y.Value));
}
return _shopRepairs;
}
}
public static Shop? Create(ShopBindingModel model)
{
if (model == null)
return null;
return new Shop()
{
Id = model.Id,
ShopName = model.ShopName,
Address = model.Address,
OpeningDate = model.OpeningDate,
MaxCapacity = model.MaxCapacity,
Repairs = model.ShopRepairs.ToDictionary(x => x.Key, x => x.Value.Item2)
};
}
public static Shop? Create(XElement element)
{
if (element == null)
{
return null;
}
return new Shop()
{
Id = Convert.ToInt32(element.Attribute("Id")!.Value),
ShopName = element.Element("ShopName")!.Value,
Address = element.Element("Address")!.Value,
MaxCapacity = Convert.ToInt32(element.Element("MaxCapacity")!.Value),
OpeningDate = Convert.ToDateTime(element.Element("DateOpen")!.Value),
Repairs = element.Element("ShopRepairs")!.Elements("ShopRepair")
.ToDictionary(x =>
Convert.ToInt32(x.Element("Key")?.Value), x =>
Convert.ToInt32(x.Element("Value")?.Value))
};
}
public void Update(ShopBindingModel model)
{
if (model == null)
{
return;
}
ShopName = model.ShopName;
Address = model.Address;
OpeningDate = model.OpeningDate;
MaxCapacity = model.MaxCapacity;
if (model.ShopRepairs.Count > 0)
{
Repairs = model.ShopRepairs.ToDictionary(x => x.Key, x => x.Value.Item2);
_shopRepairs = null;
}
}
public ShopViewModel GetViewModel => new()
{
Id = Id,
ShopName = ShopName,
Address = Address,
OpeningDate = OpeningDate,
MaxCapacity = MaxCapacity,
ShopRepairs = ShopRepairs
};
public XElement GetXElement => new("Shop",
new XAttribute("Id", Id),
new XElement("ShopName", ShopName),
new XElement("Address", Address),
new XElement("DateOpen", OpeningDate),
new XElement("MaxCapacity", MaxCapacity),
new XElement("ShopRepairs", Repairs
.Select(x => new XElement("ShopRepair",
new XElement("Key", x.Key),
new XElement("Value", x.Value))
).ToArray()));
}
}

View File

@ -7,6 +7,7 @@ using RenovationWorkContracts.BindingModels;
using RenovationWorkContracts.SearchModels;
using RenovationWorkContracts.StoragesContracts;
using RenovationWorkContracts.ViewModels;
using RenovationWorkDataModels.Models;
using RenovationWorkListImplement.Models;
namespace RenovationWorkListImplement.Implements
@ -103,5 +104,9 @@ namespace RenovationWorkListImplement.Implements
}
return null;
}
public bool SellRepairs(IRepairModel model, int count)
{
throw new NotImplementedException();
}
}
}

View File

@ -50,5 +50,6 @@ namespace RenovationWorkListImplement.Models
OpeningDate = OpeningDate,
ShopRepairs = ShopRepairs
};
public int MaxCapacity => throw new NotImplementedException();
}
}