PIbd-22. Fedorenko G.Y. Lab Work 2 HARD #11

Closed
fedorenko wants to merge 7 commits from LabWork02Hard into LabWork01Hard
18 changed files with 651 additions and 149 deletions
Showing only changes of commit 831820a677 - Show all commits

View File

@ -32,6 +32,7 @@
справочникиToolStripMenuItem = new ToolStripMenuItem();
КомпонентыToolStripMenuItem = new ToolStripMenuItem();
ИзделияToolStripMenuItem = new ToolStripMenuItem();
продажиToolStripMenuItem = new ToolStripMenuItem();
магазиныToolStripMenuItem = new ToolStripMenuItem();
поставкиToolStripMenuItem = new ToolStripMenuItem();
dataGridView = new DataGridView();
@ -56,7 +57,7 @@
//
// справочникиToolStripMenuItem
//
справочникиToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { КомпонентыToolStripMenuItem, ИзделияToolStripMenuItem, магазиныToolStripMenuItem, поставкиToolStripMenuItem });
справочникиToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { КомпонентыToolStripMenuItem, ИзделияToolStripMenuItem, магазиныToolStripMenuItem, поставкиToolStripMenuItem, продажиToolStripMenuItem });
справочникиToolStripMenuItem.Name = "справочникиToolStripMenuItem";
справочникиToolStripMenuItem.Size = new Size(94, 20);
справочникиToolStripMenuItem.Text = "Справочники";
@ -89,6 +90,12 @@
поставкиToolStripMenuItem.Text = "Поставки";
поставкиToolStripMenuItem.Click += поставкиToolStripMenuItem_Click;
//
// продажиToolStripMenuItem
//
продажиToolStripMenuItem.Name = "продажиToolStripMenuItem";
продажиToolStripMenuItem.Size = new Size(180, 22);
продажиToolStripMenuItem.Text = "Продажи";
//
// dataGridView
//
dataGridView.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
@ -193,5 +200,6 @@
private ToolStripMenuItem ИзделияToolStripMenuItem;
private ToolStripMenuItem магазиныToolStripMenuItem;
private ToolStripMenuItem поставкиToolStripMenuItem;
private ToolStripMenuItem продажиToolStripMenuItem;
}
}

View File

@ -169,5 +169,13 @@ namespace CarpentryWorkshopView
form.ShowDialog();
}
}
private void продажиToolStripMenuItem_Click(object sender, EventArgs e)
{
var service = Program.ServiceProvider?.GetService(typeof(FormSell));
if (service is FormSell form)
{
form.ShowDialog();
}
}
}
}

View File

@ -0,0 +1,117 @@
namespace CarpentryWorkshopView
{
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()
{
WoodComboBox = new ComboBox();
WoodLabel = new Label();
CountLabel = new Label();
CountTextBox = new TextBox();
SaveButton = new Button();
CancelButton = new Button();
SuspendLayout();
//
// WoodComboBox
//
WoodComboBox.FormattingEnabled = true;
WoodComboBox.Location = new Point(99, 12);
WoodComboBox.Name = "WoodComboBox";
WoodComboBox.Size = new Size(121, 23);
WoodComboBox.TabIndex = 0;
//
// WoodLabel
//
WoodLabel.AutoSize = true;
WoodLabel.Location = new Point(12, 20);
WoodLabel.Name = "WoodLabel";
WoodLabel.Size = new Size(81, 15);
WoodLabel.TabIndex = 1;
WoodLabel.Text = "Изделие";
//
// CountLabel
//
CountLabel.AutoSize = true;
CountLabel.Location = new Point(21, 49);
CountLabel.Name = "CountLabel";
CountLabel.Size = new Size(72, 15);
CountLabel.TabIndex = 2;
CountLabel.Text = "Количество";
//
// CountTextBox
//
CountTextBox.Location = new Point(99, 41);
CountTextBox.Name = "CountTextBox";
CountTextBox.Size = new Size(121, 23);
CountTextBox.TabIndex = 3;
//
// SaveButton
//
SaveButton.Location = new Point(64, 73);
SaveButton.Name = "SaveButton";
SaveButton.Size = new Size(75, 23);
SaveButton.TabIndex = 4;
SaveButton.Text = "Сохранить";
SaveButton.UseVisualStyleBackColor = true;
SaveButton.Click += SaveButton_Click;
//
// CancelButton
//
CancelButton.Location = new Point(145, 73);
CancelButton.Name = "CancelButton";
CancelButton.Size = new Size(75, 23);
CancelButton.TabIndex = 5;
CancelButton.Text = "Отмена";
CancelButton.UseVisualStyleBackColor = true;
//
// FormSell
//
AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(224, 108);
Controls.Add(CancelButton);
Controls.Add(SaveButton);
Controls.Add(CountTextBox);
Controls.Add(CountLabel);
Controls.Add(WoodLabel);
Controls.Add(WoodComboBox);
Name = "FormSell";
Text = "Форма продажи";
ResumeLayout(false);
PerformLayout();
}
#endregion
private ComboBox WoodComboBox;
private Label WoodLabel;
private Label CountLabel;
private TextBox CountTextBox;
private Button SaveButton;
private Button CancelButton;
}
}

View File

@ -0,0 +1,115 @@
using CarpentryWorkshopContracts.BusinessLogicsContracts;
using CarpentryWorkshopContracts.ViewModels;
using CarpentryWorkshopDataModels.Models;
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;
namespace CarpentryWorkshopView
{
public partial class FormSell : Form
{
private readonly List<WoodViewModel>? _woodList;
IShopLogic _shopLogic;
IWoodLogic _woodLogic;
public FormSell(IWoodLogic woodLogic, IShopLogic shopLogic)
{
InitializeComponent();
_shopLogic = shopLogic;
_woodLogic = woodLogic;
_woodList = woodLogic.ReadList(null);
if (_woodList != null)
{
WoodComboBox.DisplayMember = "WoodName";
WoodComboBox.ValueMember = "Id";
WoodComboBox.DataSource = _woodList;
WoodComboBox.SelectedItem = null;
}
}
public int WoodId
{
get
{
return Convert.ToInt32(WoodComboBox.SelectedValue);
}
set
{
WoodComboBox.SelectedValue = value;
}
}
public IWoodModel? WoodModel
{
get
{
if (_woodList == null)
{
return null;
}
foreach (var elem in _woodList)
{
if (elem.Id == WoodId)
{
return elem;
}
}
return null;
}
}
public int Count
{
get { return Convert.ToInt32(CountTextBox.Text); }
set
{ CountTextBox.Text = value.ToString(); }
}
private void SaveButton_Click(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(CountTextBox.Text))
{
MessageBox.Show("Заполните поле Количество", "Ошибка",
MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
if (WoodComboBox.SelectedValue == null)
{
MessageBox.Show("Выберите изделие", "Ошибка",
MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
try
{
int count = Convert.ToInt32(CountTextBox.Text);
bool res = _shopLogic.MakeSell(
_woodLogic.ReadElement(new() { Id = Convert.ToInt32(WoodComboBox.SelectedValue) }),
count
);
if (!res)
{
throw new Exception("Ошибка при продаже.");
}
MessageBox.Show("Продажа прошла успешно");
DialogResult = DialogResult.OK;
Close();
}
catch (Exception err)
{
MessageBox.Show("Ошибка продажи");
return;
}
}
}
}

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 @@
Название = new DataGridViewTextBoxColumn();
Цена = new DataGridViewTextBoxColumn();
Количество = new DataGridViewTextBoxColumn();
CapacityUpDown = new NumericUpDown();
CapacityLabel = new Label();
((System.ComponentModel.ISupportInitialize)DataGridView).BeginInit();
((System.ComponentModel.ISupportInitialize)CapacityUpDown).BeginInit();
SuspendLayout();
//
// DateTimePicker
@ -94,7 +97,7 @@
//
// SaveButton
//
SaveButton.Location = new Point(247, 255);
SaveButton.Location = new Point(247, 284);
SaveButton.Name = "SaveButton";
SaveButton.Size = new Size(75, 23);
SaveButton.TabIndex = 6;
@ -104,7 +107,7 @@
//
// CancelButton
//
CancelButton.Location = new Point(328, 255);
CancelButton.Location = new Point(328, 284);
CancelButton.Name = "CancelButton";
CancelButton.Size = new Size(75, 23);
CancelButton.TabIndex = 7;
@ -116,20 +119,24 @@
//
DataGridView.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize;
DataGridView.Columns.AddRange(new DataGridViewColumn[] { Column1, Название, Цена, Количество });
DataGridView.Location = new Point(12, 99);
DataGridView.Location = new Point(12, 128);
DataGridView.Name = "DataGridView";
DataGridView.RowHeadersWidth = 51;
DataGridView.Size = new Size(391, 150);
DataGridView.TabIndex = 8;
//
// Column1
//
Column1.HeaderText = "Column1";
Column1.MinimumWidth = 6;
Column1.Name = "Column1";
Column1.Visible = false;
Column1.Width = 125;
//
// Название
//
Название.HeaderText = "Название";
Название.MinimumWidth = 6;
Название.Name = "Название";
Название.ReadOnly = true;
Название.Width = 150;
@ -137,20 +144,43 @@
// Цена
//
Цена.HeaderText = "Цена";
Цена.MinimumWidth = 6;
Цена.Name = "Цена";
Цена.ReadOnly = true;
Цена.Width = 125;
//
// Количество
//
Количество.HeaderText = "Количество";
Количество.MinimumWidth = 6;
Количество.Name = "Количество";
Количество.ReadOnly = true;
Количество.Width = 125;
//
// ShopForm
// CapacityUpDown
//
CapacityUpDown.Location = new Point(98, 99);
CapacityUpDown.Maximum = new decimal(new int[] { 10000, 0, 0, 0 });
CapacityUpDown.Name = "CapacityUpDown";
CapacityUpDown.Size = new Size(120, 23);
CapacityUpDown.TabIndex = 9;
//
// CapacityLabel
//
CapacityLabel.AutoSize = true;
CapacityLabel.Location = new Point(12, 107);
CapacityLabel.Name = "CapacityLabel";
CapacityLabel.Size = new Size(80, 15);
CapacityLabel.TabIndex = 10;
CapacityLabel.Text = "Вместимость";
//
// FormShop
//
AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(411, 285);
ClientSize = new Size(411, 315);
Controls.Add(CapacityLabel);
Controls.Add(CapacityUpDown);
Controls.Add(DataGridView);
Controls.Add(CancelButton);
Controls.Add(SaveButton);
@ -160,14 +190,16 @@
Controls.Add(AddressTextBox);
Controls.Add(NameTextBox);
Controls.Add(DateTimePicker);
Name = "ShopForm";
Text = "ShopForm";
Load += ShopForm_Load;
Name = "FormShop";
Text = "Форма магазина";
Load += FormShop_Load;
((System.ComponentModel.ISupportInitialize)DataGridView).EndInit();
((System.ComponentModel.ISupportInitialize)CapacityUpDown).EndInit();
ResumeLayout(false);
PerformLayout();
}
#endregion
private DateTimePicker DateTimePicker;
@ -183,5 +215,7 @@
private DataGridViewTextBoxColumn Название;
private DataGridViewTextBoxColumn Цена;
private DataGridViewTextBoxColumn Количество;
private NumericUpDown CapacityUpDown;
private Label CapacityLabel;
}
}

View File

@ -19,7 +19,7 @@ namespace CarpentryWorkshopView
_logic = logic;
}
private void ShopForm_Load(object sender, EventArgs e)
private void FormShop_Load(object sender, EventArgs e)
{
if (_id.HasValue)
{
@ -32,6 +32,7 @@ namespace CarpentryWorkshopView
NameTextBox.Text = shop.ShopName;
AddressTextBox.Text = shop.Address;
DateTimePicker.Text = shop.DateOpen.ToString();
CapacityUpDown.Value = shop.WoodMaxCount;
_woods = shop.ShopWoods;
}
LoadData();
@ -93,6 +94,7 @@ namespace CarpentryWorkshopView
ShopName = NameTextBox.Text,
Address = AddressTextBox.Text,
DateOpen = DateTimePicker.Value.Date,
WoodMaxCount = Convert.ToInt32(CapacityUpDown.Value),
ShopWoods = _woods
};
var operationResult = _id.HasValue ? _logic.Update(model) : _logic.Create(model);

View File

@ -25,8 +25,7 @@ namespace CarpentryWorkshopView
{
get
{
return
Convert.ToInt32(ShopComboBox.SelectedValue);
return Convert.ToInt32(ShopComboBox.SelectedValue);
}
set
{
@ -37,8 +36,7 @@ namespace CarpentryWorkshopView
{
get
{
return
Convert.ToInt32(WoodComboBox.SelectedValue);
return Convert.ToInt32(WoodComboBox.SelectedValue);
}
set
{
@ -120,12 +118,11 @@ namespace CarpentryWorkshopView
{
int count = Convert.ToInt32(CountTextBox.Text);
bool res = _shopLogic.MakeSupply(new SupplyBindingModel
{
ShopId = Convert.ToInt32(ShopComboBox.SelectedValue),
WoodId = Convert.ToInt32(WoodComboBox.SelectedValue),
Count = Convert.ToInt32(CountTextBox.Text)
});
bool res = _shopLogic.MakeSupply(
new ShopSearchModel() { Id = Convert.ToInt32(ShopComboBox.SelectedValue) },
_woodLogic.ReadElement(new() { Id = Convert.ToInt32(WoodComboBox.SelectedValue) }),
count
);
if (!res)
{

View File

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

View File

@ -4,6 +4,7 @@ using CarpentryWorkshopContracts.SearchModels;
using CarpentryWorkshopContracts.StoragesContracts;
using CarpentryWorkshopContracts.ViewModels;
using CarpentryWorkshopDataModels.Enums;
using CarpentryWorkshopDataModels.Models;
using Microsoft.Extensions.Logging;
namespace CarpentryWorkshopBusinessLogic.BusinessLogics
@ -13,12 +14,17 @@ namespace CarpentryWorkshopBusinessLogic.BusinessLogics
private readonly ILogger _logger;
private readonly IOrderStorage _orderStorage;
private readonly IShopStorage _shopStorage;
private readonly IShopLogic _shopLogic;
private readonly IWoodStorage _woodStorage;
public OrderLogic(ILogger<OrderLogic> logger, IOrderStorage orderStorage, IShopStorage shopStorage)
public OrderLogic(IOrderStorage orderStorage, IShopStorage shopStorage,
IShopLogic shopLogic, IWoodStorage woodStorage, ILogger<OrderLogic> logger)
{
_logger = logger;
_orderStorage = orderStorage;
_shopStorage = shopStorage;
_shopLogic = shopLogic;
_woodStorage = woodStorage;
}
public List<OrderViewModel>? ReadList(OrderSearchModel? model)
@ -62,6 +68,20 @@ namespace CarpentryWorkshopBusinessLogic.BusinessLogics
_logger.LogWarning("Status change operation failed");
throw new InvalidOperationException("Текущий статус заказа не может быть переведен в выбранный");
}
if (element.Status == OrderStatus.Готов)
{
var wood = _woodStorage.GetElement(new WoodSearchModel() { Id = model.WoodId });
if (wood == null)
{
_logger.LogWarning("Status update to " + status.ToString() + " operation failed. Document not found.");
return false;
}
if (CheckSupply(wood, 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);
@ -80,27 +100,69 @@ namespace CarpentryWorkshopBusinessLogic.BusinessLogics
public bool DeliveryOrder(OrderBindingModel model)
{
var order = _orderStorage.GetElement(new OrderSearchModel
{
Id = model.Id,
});
if (order == null)
{
throw new ArgumentNullException(nameof(order));
}
if (!_shopStorage.RestockingShops(new SupplyBindingModel
{
WoodId = order.WoodId,
Count = order.Count
}))
{
throw new ArgumentException("Недостаточно места");
}
return ChangeStatus(model, OrderStatus.Выдан);
}
private void CheckModel(OrderBindingModel model, bool withParams =
true)
public bool CheckSupply(IWoodModel wood, int count)
{
if (count <= 0)
{
_logger.LogWarning("Check then supply operation error. Wood count < 0.");
return false;
}
int sumCapacity = 0;
int sumCount = 0;
sumCapacity = _shopStorage.GetFullList().Select(x => x.WoodMaxCount).Sum();
sumCount = _shopStorage.GetFullList().Select(x => x.ShopWoods.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 Wood in shops.");
return false;
}
foreach (var shop in _shopStorage.GetFullList())
{
freeSpace = shop.WoodMaxCount;
foreach (var doc in shop.ShopWoods)
{
freeSpace -= doc.Value.Item2;
}
if (freeSpace == 0)
{
continue;
}
if (freeSpace - count >= 0)
{
if (_shopLogic.MakeSupply(new() { Id = shop.Id }, wood, count))
count = 0;
else
{
_logger.LogWarning("Supply error");
return false;
}
}
if (freeSpace - count < 0)
{
if (_shopLogic.MakeSupply(new() { Id = shop.Id }, wood, freeSpace))
count -= freeSpace;
else
{
_logger.LogWarning("Supply error");
return false;
}
}
if (count <= 0)
{
return true;
}
}
return false;
}
private void CheckModel(OrderBindingModel model, bool withParams = true)
{
if (model == null)
{

View File

@ -12,18 +12,16 @@ namespace CarpentryWorkshopBusinessLogic.BusinessLogics
{
private readonly ILogger _logger;
private readonly IShopStorage _shopStorage;
private readonly IWoodStorage _woodStorage;
public ShopLogic(ILogger<ShopLogic> logger, IShopStorage shopStorage, IWoodStorage woodStorage)
public ShopLogic(ILogger<ShopLogic> logger, IShopStorage shopStorage)
{
_logger = logger;
_shopStorage = shopStorage;
_woodStorage = woodStorage;
}
public List<ShopViewModel> ReadList(ShopSearchModel model)
{
_logger.LogInformation("ReadList. ShopName:{ShopName}.Id:{ Id}", model?.ShopName, model?.Id);
_logger.LogInformation("ReadList. ShopName:{Name}. Id:{ Id}", model?.ShopName, model?.Id);
var list = model == null ? _shopStorage.GetFullList() : _shopStorage.GetFilteredList(model);
if (list == null)
{
@ -32,47 +30,58 @@ namespace CarpentryWorkshopBusinessLogic.BusinessLogics
}
_logger.LogInformation("ReadList. Count:{Count}", list.Count);
return list;
}
public bool MakeSupply(SupplyBindingModel model)
public bool MakeSupply(ShopSearchModel model, IWoodModel wood, int count)
{
if (model == null)
{
throw new ArgumentNullException(nameof(model));
}
if (model.Count <= 0)
if (wood == null)
throw new ArgumentNullException(nameof(wood));
if (count <= 0)
throw new ArgumentNullException("Количество должно быть положительным числом");
ShopViewModel curModel = _shopStorage.GetElement(model);
if (curModel == null)
throw new ArgumentNullException(nameof(curModel));
var countItems = curModel.ShopWoods.Select(x => x.Value.Item2).Sum();
if (curModel.WoodMaxCount - countItems >= count)
{
throw new ArgumentException("Количество изделий должно быть больше 0");
}
var shop = _shopStorage.GetElement(new ShopSearchModel
{
Id = model.ShopId
});
if (shop == null)
{
throw new ArgumentException("Магазина не существует");
}
if (shop.ShopWoods.ContainsKey(model.WoodId))
{
var oldValue = shop.ShopWoods[model.WoodId];
oldValue.Item2 += model.Count;
shop.ShopWoods[model.WoodId] = oldValue;
if (curModel.ShopWoods.TryGetValue(wood.Id, out var sameDocument))
{
curModel.ShopWoods[wood.Id] = (wood, sameDocument.Item2 + count);
_logger.LogInformation("Same wood found by supply. Added {0} of {1} in {2} shop", count, wood.WoodName, curModel.ShopName);
}
else
{
curModel.ShopWoods[wood.Id] = (wood, count);
_logger.LogInformation("New wood added by supply. Added {0} of {1} in {2} shop", count, wood.WoodName, curModel.ShopName);
}
_shopStorage.Update(new()
{
Id = curModel.Id,
ShopName = curModel.ShopName,
Address = curModel.Address,
DateOpen = curModel.DateOpen,
ShopWoods = curModel.ShopWoods,
WoodMaxCount = curModel.WoodMaxCount
});
}
else
{
var wood = _woodStorage.GetElement(new WoodSearchModel
{
Id = model.WoodId
});
if (wood == null)
{
throw new ArgumentException($"Поставка: Товар с id:{model.WoodId} не найденн");
}
shop.ShopWoods.Add(model.WoodId, (wood, model.Count));
_logger.LogWarning("Required shop is overflowed");
return false;
}
return true;
}
public bool MakeSell(IWoodModel wood, int count)
{
return _shopStorage.SellWoods(wood, count);
}
public ShopViewModel ReadElement(ShopSearchModel model)
{
if (model == null)
@ -133,15 +142,20 @@ namespace CarpentryWorkshopBusinessLogic.BusinessLogics
{
return;
}
if (string.IsNullOrEmpty(model.Address))
{
throw new ArgumentException("Адрес магазина длжен быть заполнен", nameof(model.Address));
}
if (string.IsNullOrEmpty(model.ShopName))
{
throw new ArgumentException("Название магазина должно быть заполнено", nameof(model.ShopName));
throw new ArgumentNullException("Нет названия магазина", nameof(model.ShopName));
}
_logger.LogInformation("Shop. ShopName:{ShopName}.Adres:{Adres}.OpeningDate:{OpeningDate}.Id:{ Id}", model.ShopName, model.Address, model.DateOpen, model.Id);
if (string.IsNullOrEmpty(model.Address))
{
throw new ArgumentNullException("Нет адресса магазина", nameof(model.ShopName));
}
if (model.DateOpen == null)
{
throw new ArgumentNullException("Нет даты открытия магазина", nameof(model.ShopName));
}
_logger.LogInformation("Shop. ShopName:{ShopName}.Address:{Address}. DateOpen:{DateOpen}. Id: { Id}",
model.ShopName, model.Address, model.DateOpen, model.Id);
var element = _shopStorage.GetElement(new ShopSearchModel
{
ShopName = model.ShopName
@ -151,5 +165,6 @@ namespace CarpentryWorkshopBusinessLogic.BusinessLogics
throw new InvalidOperationException("Магазин с таким названием уже есть");
}
}
}
}

View File

@ -12,7 +12,7 @@ namespace CarpentryWorkshopContracts.BusinessLogicsContracts
bool Create(ShopBindingModel model);
bool Update(ShopBindingModel model);
bool Delete(ShopBindingModel model);
bool MakeSupply(SupplyBindingModel model);
bool Sale(SupplySearchModel model);
bool MakeSupply(ShopSearchModel model, IWoodModel wood, int count);
bool MakeSell(IWoodModel wood, int count);
}
}

View File

@ -18,7 +18,6 @@ namespace CarpentryWorkshopContracts.StoragesContracts
ShopViewModel? Insert(ShopBindingModel model);
ShopViewModel? Update(ShopBindingModel model);
ShopViewModel? Delete(ShopBindingModel model);
bool Sale(SupplySearchModel model);
bool RestockingShops(SupplyBindingModel model);
public bool SellWoods(IWoodModel model, int count);
}
}

View File

@ -78,14 +78,10 @@ namespace CarpentryWorkshopFileImplement.Implements
{
if (model == null)
return null;
foreach (var wood in source.Woods)
{
if (wood.Id == model.WoodId)
{
model.WoodName = wood.WoodName;
break;
}
}
var wood = source.Woods.FirstOrDefault(x => (x.Id == model.WoodId));
if (wood == null)
return model;
model.WoodName = wood.WoodName;
return model;
}
}

View File

@ -2,6 +2,7 @@
using CarpentryWorkshopContracts.SearchModels;
using CarpentryWorkshopContracts.StoragesContracts;
using CarpentryWorkshopContracts.ViewModels;
using CarpentryWorkshopDataModels.Models;
using CarpentryWorkshopFileImplement.Models;
namespace CarpentryWorkshopFileImplement.Implements
@ -76,73 +77,51 @@ namespace CarpentryWorkshopFileImplement.Implements
return null;
}
public bool Sale(SupplySearchModel model)
public bool CheckAvailability(int woodId, int count)
{
if (model == null || !model.WoodId.HasValue || !model.Count.HasValue)
return false;
int remainingSpace = source.Shops.Select(x => x.Woods.ContainsKey(model.WoodId.Value) ? x.Woods[model.WoodId.Value] : 0).Sum();
if (remainingSpace < model.Count)
{
return false;
}
var shops = source.Shops.Where(x => x.Woods.ContainsKey(model.WoodId.Value)).OrderByDescending(x => x.Woods[model.WoodId.Value]).ToList();
foreach (var shop in shops)
{
int residue = model.Count.Value - shop.Woods[model.WoodId.Value];
if (residue > 0)
{
shop.Woods.Remove(model.WoodId.Value);
shop.Woods.Update();
model.Count = residue;
}
else
{
if (residue == 0)
{
shop.Woods.Remove(model.WoodId.Value);
}
else
{
shop.Woods[model.WoodId.Value] = -residue;
}
shop.Woods.Update();
source.SaveShops();
return true;
}
}
source.SaveShops();
return false;
int minus = source.Shops.Select(x => x.ShopWoods.Select(y => (y.Value.Item1.Id == woodId ? y.Value.Item2 : 0)).Sum()).Sum();
count -= minus;
return count <= 0;
}
public bool RestockingShops(SupplyBindingModel model)
public bool SellWoods(IWoodModel model, int count)
{
if (model == null || source.Shops.Select(x => x.WoodMaxCount - x.ShopWoods.Select(y => y.Value.Item2).Sum()).Sum() < model.Count)
var wood = source.Woods.FirstOrDefault(x => x.Id == model.Id);
if (wood == null || !CheckAvailability(wood.Id, count))
{
return false;
}
foreach (Shop shop in source.Shops)
for (int i = 0; i < source.Shops.Count; i++)
{
int free_places = shop.WoodMaxCount - shop.ShopWoods.Select(x => x.Value.Item2).Sum();
if (free_places <= 0)
continue;
free_places = Math.Min(free_places, model.Count);
model.Count -= free_places;
if (shop.Woods.ContainsKey(model.WoodId))
var shop = source.Shops[i];
var woods = shop.ShopWoods;
foreach (var wod in woods.Where(x => x.Value.Item1.Id == wood.Id))
{
shop.Woods[model.WoodId] += free_places;
var min = Math.Min(wod.Value.Item2, count);
woods[wod.Value.Item1.Id] = (wod.Value.Item1, wod.Value.Item2 - min);
count -= min;
if (count <= 0)
{
break;
}
}
else
shop.Update(new ShopBindingModel
{
shop.Woods.Add(model.WoodId, free_places);
}
shop.Woods.Update();
if (model.Count == 0)
{
source.SaveShops();
return true;
}
Id = shop.Id,
ShopName = shop.ShopName,
Address = shop.Address,
DateOpen = shop.DateOpen,
WoodMaxCount = shop.WoodMaxCount,
ShopWoods = woods
});
}
return false;
source.SaveShops();
return true;
}
}
}

View File

@ -93,9 +93,10 @@ namespace CarpentryWorkshopFileImplement.Models
new XElement("ShopName", ShopName),
new XElement("Address", Address),
new XElement("DateOpen", DateOpen.ToString()),
new XElement("ShopWoods", Woods.Select(
x => new XElement("ShopWood", new XElement("Key", x.Key), new XElement("Value", x.Value))).ToArray()),
new XElement("WoodMaxCount", WoodMaxCount.ToString())
);
new XElement("WoodMaxCount", WoodMaxCount),
new XElement("ShopWoods", Woods
.Select(x => new XElement("ShopWood",
new XElement("Key", x.Key),
new XElement("Value", x.Value))).ToArray()));
}
}

View File

@ -100,5 +100,50 @@ namespace CarpentryWorkshopListImplement.Implements
}
return null;
}
public bool CheckAvailability(int woodId, int count)
{
int minus = _source.Shops.Select(x => x.ShopWoods.Select(y => (y.Value.Item1.Id == woodId ? y.Value.Item2 : 0)).Sum()).Sum();
count -= minus;
return count <= 0;
}
public bool SellWoods(IWoodModel model, int count)
{
var wood = _source.Woods.FirstOrDefault(x => x.Id == model.Id);
if (wood == null || !CheckAvailability(wood.Id, count))
{
return false;
}
for (int i = 0; i < _source.Shops.Count; i++)
{
var shop = _source.Shops[i];
var woods = shop.ShopWoods;
foreach (var wod in woods.Where(x => x.Value.Item1.Id == wood.Id))
{
var min = Math.Min(wod.Value.Item2, count);
woods[wod.Value.Item1.Id] = (wod.Value.Item1, wod.Value.Item2 - min);
count -= min;
if (count <= 0)
{
break;
}
}
shop.Update(new ShopBindingModel
{
Id = shop.Id,
ShopName = shop.ShopName,
Address = shop.Address,
DateOpen = shop.DateOpen,
WoodMaxCount = shop.WoodMaxCount,
ShopWoods = woods
});
}
return true;
}
}
}

View File

@ -15,6 +15,7 @@ namespace CarpentryWorkshopListImplement.Models
public string ShopName { get; private set; }
public string Address { get; private set; }
public DateTime DateOpen { get; private set; }
public int WoodMaxCount { get; private set; }
public Dictionary<int, (IWoodModel, int)> ShopWoods { get; private set; } = new();
public static Shop? Create(ShopBindingModel model)
@ -26,7 +27,8 @@ namespace CarpentryWorkshopListImplement.Models
Id = model.Id,
ShopName = model.ShopName,
Address = model.Address,
DateOpen = model.DateOpen
DateOpen = model.DateOpen,
ShopWoods = new()
};
}
@ -39,6 +41,7 @@ namespace CarpentryWorkshopListImplement.Models
ShopName = model.ShopName;
Address = model.Address;
DateOpen = model.DateOpen;
ShopWoods = model.ShopWoods;
}
public ShopViewModel GetViewModel => new()