залил

This commit is contained in:
Marselchi 2024-06-17 21:08:40 +04:00
parent 83143fffa4
commit 415df9030b
22 changed files with 1044 additions and 346 deletions

View File

@ -12,10 +12,14 @@ namespace ShipyardBusinessLogic.BusinessLogics
{ {
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly IOrderStorage _orderStorage; private readonly IOrderStorage _orderStorage;
public OrderLogic(ILogger<OrderLogic> logger, IOrderStorage orderStorage) private readonly IShopLogic _shopLogic;
private readonly IShipStorage _shipStorage;
public OrderLogic(ILogger<OrderLogic> logger, IOrderStorage orderStorage, IShopLogic shopLogic, IShipStorage shipStorage)
{ {
_logger = logger; _logger = logger;
_orderStorage = orderStorage; _orderStorage = orderStorage;
_shopLogic = shopLogic;
_shipStorage = shipStorage;
} }
public List<OrderViewModel>? ReadList(OrderSearchModel? model) public List<OrderViewModel>? ReadList(OrderSearchModel? model)
{ {
@ -72,13 +76,29 @@ namespace ShipyardBusinessLogic.BusinessLogics
public bool StatusUpdate(OrderBindingModel model, OrderStatus newStatus) public bool StatusUpdate(OrderBindingModel model, OrderStatus newStatus)
{ {
var viewModel = _orderStorage.GetElement(new OrderSearchModel { Id = model.Id }); var viewModel = _orderStorage.GetElement(new OrderSearchModel { Id = model.Id });
if (viewModel == null)
{
throw new ArgumentNullException(nameof(model));
}
if (viewModel.Status + 1 != newStatus) if (viewModel.Status + 1 != newStatus)
{ {
_logger.LogWarning("Status update to " + newStatus.ToString() + " operation failed. Order status incorrect."); _logger.LogWarning("Status update to " + newStatus.ToString() + " operation failed. Order status incorrect.");
return false; return false;
} }
model.Status = newStatus; model.Status = newStatus;
if (model.Status == OrderStatus.Готов) model.DateImplement = DateTime.Now; if (model.Status == OrderStatus.Готов)
{
model.DateImplement = DateTime.Now;
var ship = _shipStorage.GetElement(new() { Id = viewModel.ShipId });
if (ship == null)
{
throw new ArgumentNullException(nameof(ship));
}
if (!_shopLogic.AddShips(ship, viewModel.Count))
{
throw new Exception($"AddShips operation failed");
}
}
else else
{ {
model.DateImplement = viewModel.DateImplement; model.DateImplement = viewModel.DateImplement;
@ -87,7 +107,7 @@ namespace ShipyardBusinessLogic.BusinessLogics
if (_orderStorage.Update(model) == null) if (_orderStorage.Update(model) == null)
{ {
model.Status--; model.Status--;
_logger.LogWarning("Update operation failed"); _logger.LogWarning("Change status operation failed");
return false; return false;
} }
return true; return true;

View File

@ -110,6 +110,7 @@ namespace ShipyardBusinessLogic.BusinessLogics
} }
if (count <= 0) if (count <= 0)
{ {
return false;
throw new ArgumentException("Количество кораблей должно быть больше 0", nameof(count)); throw new ArgumentException("Количество кораблей должно быть больше 0", nameof(count));
} }
_logger.LogInformation("AddShip. ShopName:{ShopName}. Id:{Id}", model.ShopName, model.Id); _logger.LogInformation("AddShip. ShopName:{ShopName}. Id:{Id}", model.ShopName, model.Id);
@ -119,7 +120,10 @@ namespace ShipyardBusinessLogic.BusinessLogics
_logger.LogWarning("AddShip element not found"); _logger.LogWarning("AddShip element not found");
return false; return false;
} }
_logger.LogInformation("AddShip find. Id:{Id}", element.Id); if (element.Capacity - element.ShopShips.Select(x => x.Value.Item2).Sum() < count)
{
throw new ArgumentNullException("В магазине не хватает места", nameof(count));
}
if (element.ShopShips.TryGetValue(ship.Id, out var pair)) if (element.ShopShips.TryGetValue(ship.Id, out var pair))
{ {
@ -139,9 +143,64 @@ namespace ShipyardBusinessLogic.BusinessLogics
Address = element.Address, Address = element.Address,
ShopName = element.ShopName, ShopName = element.ShopName,
DateOpen = element.DateOpen, DateOpen = element.DateOpen,
Capacity = element.Capacity,
ShopShips = element.ShopShips ShopShips = element.ShopShips
}); });
return true; return true;
} }
public bool AddShips(IShipModel model, int count)
{
if (model == null)
{
throw new ArgumentNullException(nameof(model));
}
if (count <= 0)
{
throw new ArgumentException("Количество кораблей должно быть больше 0", nameof(count));
}
_logger.LogInformation("AddShips. ShopName:{ShopName}. Id:{Id}", model.ShipName, model.Id);
var allFreeQuantity = _shopStorage.GetFullList().Select(x => x.Capacity - x.ShopShips.Select(x => x.Value.Item2).Sum()).Sum();
if (allFreeQuantity < count)
{
_logger.LogWarning("AddTravels operation failed.");
return false;
}
foreach (var shop in _shopStorage.GetFullList())
{
int freeQuantity = shop.Capacity - shop.ShopShips.Select(x => x.Value.Item2).Sum();
if (freeQuantity <= 0)
{
continue;
}
if (freeQuantity < count)
{
if (!AddShip(new() { Id = shop.Id }, model, freeQuantity))
{
_logger.LogWarning("AddShips operation failed.");
return false;
}
count -= freeQuantity;
}
else
{
if (!AddShip(new() { Id = shop.Id }, model, count))
{
_logger.LogWarning("AddShips operation failed.");
return false;
}
count = 0;
}
if (count == 0)
{
return true;
}
}
_logger.LogWarning("AddShips operation failed.");
return false;
}
public bool SellShips(IShipModel model, int count)
{
return _shopStorage.SellShips(model, count);
}
} }
} }

View File

@ -7,6 +7,7 @@ namespace ShipyardContracts.BindingModels
public string ShopName { get; set; } = string.Empty; public string ShopName { get; set; } = string.Empty;
public string Address { get; set; } = string.Empty; public string Address { get; set; } = string.Empty;
public DateTime DateOpen { get; set; } = DateTime.Now; public DateTime DateOpen { get; set; } = DateTime.Now;
public int Capacity { get; set; }
public Dictionary<int, (IShipModel, int)> ShopShips { get; set; } = new(); public Dictionary<int, (IShipModel, int)> ShopShips { get; set; } = new();
public int Id { get; set; } public int Id { get; set; }
} }

View File

@ -13,5 +13,7 @@ namespace ShipyardContracts.BusinessLogicsContracts
bool Update(ShopBindingModel model); bool Update(ShopBindingModel model);
bool Delete(ShopBindingModel model); bool Delete(ShopBindingModel model);
bool AddShip(ShopSearchModel model, IShipModel ship, int count); bool AddShip(ShopSearchModel model, IShipModel ship, int count);
bool AddShips(IShipModel model, int count);
bool SellShips(IShipModel model, int count);
} }
} }

View File

@ -1,6 +1,7 @@
using ShipyardContracts.BindingModels; using ShipyardContracts.BindingModels;
using ShipyardContracts.SearchModels; using ShipyardContracts.SearchModels;
using ShipyardContracts.ViewModels; using ShipyardContracts.ViewModels;
using ShipyardDataModels.Models;
namespace ShipyardContracts.StoragesContracts namespace ShipyardContracts.StoragesContracts
{ {
@ -12,5 +13,6 @@ namespace ShipyardContracts.StoragesContracts
ShopViewModel? Insert(ShopBindingModel model); ShopViewModel? Insert(ShopBindingModel model);
ShopViewModel? Update(ShopBindingModel model); ShopViewModel? Update(ShopBindingModel model);
ShopViewModel? Delete(ShopBindingModel model); ShopViewModel? Delete(ShopBindingModel model);
bool SellShips(IShipModel model, int count);
} }
} }

View File

@ -13,6 +13,8 @@ namespace ShipyardContracts.ViewModels
[DisplayName("Дата открытия")] [DisplayName("Дата открытия")]
public DateTime DateOpen { get; set; } = DateTime.Now; public DateTime DateOpen { get; set; } = DateTime.Now;
[DisplayName("Вместимость магазина")]
public int Capacity { get; set; }
public Dictionary<int, (IShipModel, int)> ShopShips { get; set; } = new(); public Dictionary<int, (IShipModel, int)> ShopShips { get; set; } = new();
public int Id { get; set; } public int Id { get; set; }
} }

View File

@ -5,6 +5,7 @@
string ShopName { get; } string ShopName { get; }
string Address { get; } string Address { get; }
DateTime DateOpen { get; } DateTime DateOpen { get; }
public int Capacity { get; }
Dictionary<int, (IShipModel, int)> ShopShips { get; } Dictionary<int, (IShipModel, int)> ShopShips { get; }
} }
} }

View File

@ -3,15 +3,17 @@ using System.Xml.Linq;
namespace ShipyardFileImplement namespace ShipyardFileImplement
{ {
internal class DataFileSingleton public class DataFileSingleton
{ {
private static DataFileSingleton? instance; private static DataFileSingleton? instance;
private readonly string DetailFileName = "Detail.xml"; private readonly string DetailFileName = "Detail.xml";
private readonly string OrderFileName = "Order.xml"; private readonly string OrderFileName = "Order.xml";
private readonly string ShipFileName = "Ship.xml"; private readonly string ShipFileName = "Ship.xml";
private readonly string ShopFileName = "Shop.xml";
public List<Detail> Details { get; private set; } public List<Detail> Details { get; private set; }
public List<Order> Orders { get; private set; } public List<Order> Orders { get; private set; }
public List<Ship> Ships { get; private set; } public List<Ship> Ships { get; private set; }
public List<Shop> Shops { get; private set; }
public static DataFileSingleton GetInstance() public static DataFileSingleton GetInstance()
{ {
if (instance == null) if (instance == null)
@ -23,11 +25,13 @@ namespace ShipyardFileImplement
public void SaveDetails() => SaveData(Details, DetailFileName, "Details", x => x.GetXElement); public void SaveDetails() => SaveData(Details, DetailFileName, "Details", x => x.GetXElement);
public void SaveShips() => SaveData(Ships, ShipFileName, "Ships", x => x.GetXElement); public void SaveShips() => SaveData(Ships, ShipFileName, "Ships", x => x.GetXElement);
public void SaveOrders() => SaveData(Orders, OrderFileName, "Orders", 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() private DataFileSingleton()
{ {
Details = LoadData(DetailFileName, "Detail", x => Detail.Create(x)!)!; Details = LoadData(DetailFileName, "Detail", x => Detail.Create(x)!)!;
Ships = LoadData(ShipFileName, "Ship", x => Ship.Create(x)!)!; Ships = LoadData(ShipFileName, "Ship", x => Ship.Create(x)!)!;
Orders = LoadData(OrderFileName, "Order", x => Order.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, private static List<T>? LoadData<T>(string filename, string xmlNodeName,
Func<XElement, T> selectFunction) Func<XElement, T> selectFunction)

View File

@ -24,7 +24,9 @@ namespace ShipyardFileImplement.Implements
return new(); return new();
} }
return source.Details return source.Details
.Where(x => x.DetailName.Contains(model.DetailName)).Select(x => x.GetViewModel).ToList(); .Where(x => x.DetailName.Contains(model.DetailName))
.Select(x => x.GetViewModel)
.ToList();
} }
public DetailViewModel? GetElement(DetailSearchModel model) public DetailViewModel? GetElement(DetailSearchModel model)
{ {
@ -33,9 +35,11 @@ namespace ShipyardFileImplement.Implements
return null; return null;
} }
return source.Details return source.Details
.FirstOrDefault(x => (!string.IsNullOrEmpty(model.DetailName) .FirstOrDefault(x =>
&& x.DetailName == model.DetailName) (!string.IsNullOrEmpty(model.DetailName) && x.DetailName ==
|| (model.Id.HasValue && x.Id == model.Id))?.GetViewModel; model.DetailName) ||
(model.Id.HasValue && x.Id == model.Id))
?.GetViewModel;
} }
public DetailViewModel? Insert(DetailBindingModel model) public DetailViewModel? Insert(DetailBindingModel model)
{ {
@ -51,7 +55,8 @@ namespace ShipyardFileImplement.Implements
} }
public DetailViewModel? Update(DetailBindingModel model) public DetailViewModel? Update(DetailBindingModel model)
{ {
var component = source.Details.FirstOrDefault(x => x.Id == model.Id); var component = source.Details.FirstOrDefault(x => x.Id ==
model.Id);
if (component == null) if (component == null)
{ {
return null; return null;
@ -62,7 +67,8 @@ namespace ShipyardFileImplement.Implements
} }
public DetailViewModel? Delete(DetailBindingModel model) public DetailViewModel? Delete(DetailBindingModel model)
{ {
var element = source.Details.FirstOrDefault(x => x.Id == model.Id); var element = source.Details.FirstOrDefault(x => x.Id ==
model.Id);
if (element != null) if (element != null)
{ {
source.Details.Remove(element); source.Details.Remove(element);

View File

@ -23,7 +23,8 @@ namespace ShipyardFileImplement.Implements
{ {
return new(); return new();
} }
return source.Ships.Where(x => x.ShipName.Contains(model.ShipName)).Select(x => x.GetViewModel).ToList(); return source.Ships.Where(x =>
x.ShipName.Contains(model.ShipName)).Select(x => x.GetViewModel).ToList();
} }
public ShipViewModel? GetElement(ShipSearchModel model) public ShipViewModel? GetElement(ShipSearchModel model)
{ {

View File

@ -0,0 +1,119 @@
using ShipyardContracts.BindingModels;
using ShipyardContracts.SearchModels;
using ShipyardContracts.StoragesContracts;
using ShipyardContracts.ViewModels;
using ShipyardFileImplement.Models;
using ShipyardDataModels.Models;
namespace ShipyardFileImplement.Implements
{
public class ShopStorage : IShopStorage
{
private readonly DataFileSingleton source;
public ShopStorage()
{
source = DataFileSingleton.GetInstance();
}
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 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 List<ShopViewModel> GetFullList()
{
return source.Shops.Select(x => x.GetViewModel).ToList();
}
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 shop = source.Shops.FirstOrDefault(x => x.Id == model.Id);
if (shop == null)
{
return null;
}
shop.Update(model);
source.SaveShops();
return shop.GetViewModel;
}
public ShopViewModel? Delete(ShopBindingModel model)
{
var shop = source.Shops.FirstOrDefault(x => x.Id == model.Id);
if (shop != null)
{
source.Shops.Remove(shop);
source.SaveShops();
return shop.GetViewModel;
}
return null;
}
public bool SellShips(IShipModel model, int count)
{
int availableQuantity = source.Shops.Select(x => x.ShopShips.FirstOrDefault(y => y.Key == model.Id).Value.Item2).Sum();
if (availableQuantity < count)
{
return false;
}
var shops = source.Shops.Where(x => x.ShopShips.ContainsKey(model.Id));
foreach (var shop in shops)
{
int countInCurrentShop = shop.ShopShips[model.Id].Item2;
if (countInCurrentShop <= count)
{
shop.ShopShips[model.Id] = (shop.ShopShips[model.Id].Item1, 0);
count -= countInCurrentShop;
}
else
{
shop.ShopShips[model.Id] = (shop.ShopShips[model.Id].Item1, countInCurrentShop - count);
count = 0;
}
Update(new ShopBindingModel
{
Id = shop.Id,
ShopName = shop.ShopName,
Address = shop.Address,
DateOpen = shop.DateOpen,
ShopShips = shop.ShopShips,
Capacity = shop.Capacity
});
if (count == 0)
{
return true;
}
}
return false;
}
}
}

View File

@ -0,0 +1,103 @@
using ShipyardContracts.BindingModels;
using ShipyardContracts.ViewModels;
using ShipyardDataModels.Models;
using System.Xml.Linq;
namespace ShipyardFileImplement.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 DateOpen { get; private set; }
public int Capacity { get; private set; }
public Dictionary<int, int> ShipsCount = new();
public Dictionary<int, (IShipModel, int)>? _ships = null;
public Dictionary<int, (IShipModel, int)> ShopShips
{
get
{
if (_ships == null)
{
var source = DataFileSingleton.GetInstance();
_ships = ShipsCount.ToDictionary(
x => x.Key,
y => ((source.Ships.FirstOrDefault(z => z.Id == y.Key) as IShipModel)!,
y.Value)
);
}
return _ships;
}
}
public static Shop? Create(ShopBindingModel? model)
{
if (model == null)
{
return null;
}
return new Shop()
{
Id = model.Id,
ShopName = model.ShopName,
Address = model.Address,
DateOpen = model.DateOpen,
Capacity = model.Capacity,
ShipsCount = model.ShopShips.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,
DateOpen = Convert.ToDateTime(element.Element("DateOpening")!.Value),
Capacity = Convert.ToInt32(element.Element("Capacity")!.Value),
ShipsCount = element.Element("Ships")!.Elements("Ship")
.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;
DateOpen = model.DateOpen;
Capacity = model.Capacity;
ShipsCount = model.ShopShips.ToDictionary(x => x.Key, x => x.Value.Item2);
_ships = null;
}
public ShopViewModel GetViewModel => new()
{
Id = Id,
ShopName = ShopName,
Address = Address,
DateOpen = DateOpen,
Capacity = Capacity,
ShopShips = ShopShips
};
public XElement GetXElement => new("Shop",
new XAttribute("Id", Id),
new XElement("ShopName", ShopName),
new XElement("Address", Address),
new XElement("DateOpening", DateOpen.ToString()),
new XElement("Capacity", Capacity.ToString()),
new XElement("Ships", ShipsCount.Select(x =>
new XElement("Ship",
new XElement("Key", x.Key),
new XElement("Value", x.Value)))
.ToArray()));
}
}

View File

@ -2,6 +2,7 @@
using ShipyardContracts.SearchModels; using ShipyardContracts.SearchModels;
using ShipyardContracts.StoragesContracts; using ShipyardContracts.StoragesContracts;
using ShipyardContracts.ViewModels; using ShipyardContracts.ViewModels;
using ShipyardDataModels.Models;
using ShipyardListImplement.Models; using ShipyardListImplement.Models;
namespace ShipyardListImplement.Implements namespace ShipyardListImplement.Implements
@ -103,5 +104,10 @@ namespace ShipyardListImplement.Implements
} }
return null; return null;
} }
public bool SellShips(IShipModel model, int count)
{
throw new NotImplementedException();
}
} }
} }

View File

@ -11,6 +11,7 @@ namespace ShipyardListImplement.Models
public string Address { get; set; } = string.Empty; public string Address { get; set; } = string.Empty;
public DateTime DateOpen { get; set; } public DateTime DateOpen { get; set; }
public int Capacity { get; private set; }
public int Id { get; set; } public int Id { get; set; }
public Dictionary<int, (IShipModel, int)> ShopShips { get; private set; } = new Dictionary<int, (IShipModel, int)>(); public Dictionary<int, (IShipModel, int)> ShopShips { get; private set; } = new Dictionary<int, (IShipModel, int)>();

View File

@ -41,6 +41,7 @@
buttonIssue = new Button(); buttonIssue = new Button();
buttonRefresh = new Button(); buttonRefresh = new Button();
buttonAddShip = new Button(); buttonAddShip = new Button();
buttonSellShip = new Button();
toolStrip.SuspendLayout(); toolStrip.SuspendLayout();
((System.ComponentModel.ISupportInitialize)dataGridView).BeginInit(); ((System.ComponentModel.ISupportInitialize)dataGridView).BeginInit();
SuspendLayout(); SuspendLayout();
@ -68,21 +69,21 @@
// деталиToolStripMenuItem // деталиToolStripMenuItem
// //
деталиToolStripMenuItem.Name = еталиToolStripMenuItem"; деталиToolStripMenuItem.Name = еталиToolStripMenuItem";
деталиToolStripMenuItem.Size = new Size(163, 26); деталиToolStripMenuItem.Size = new Size(224, 26);
деталиToolStripMenuItem.Text = "Детали"; деталиToolStripMenuItem.Text = "Детали";
деталиToolStripMenuItem.Click += ДеталиToolStripMenuItem_Click; деталиToolStripMenuItem.Click += ДеталиToolStripMenuItem_Click;
// //
// кораблиToolStripMenuItem // кораблиToolStripMenuItem
// //
кораблиToolStripMenuItem.Name = ораблиToolStripMenuItem"; кораблиToolStripMenuItem.Name = ораблиToolStripMenuItem";
кораблиToolStripMenuItem.Size = new Size(163, 26); кораблиToolStripMenuItem.Size = new Size(224, 26);
кораблиToolStripMenuItem.Text = "Корабли"; кораблиToolStripMenuItem.Text = "Корабли";
кораблиToolStripMenuItem.Click += КораблиToolStripMenuItem_Click; кораблиToolStripMenuItem.Click += КораблиToolStripMenuItem_Click;
// //
// магазиныToolStripMenuItem // магазиныToolStripMenuItem
// //
магазиныToolStripMenuItem.Name = агазиныToolStripMenuItem"; магазиныToolStripMenuItem.Name = агазиныToolStripMenuItem";
магазиныToolStripMenuItem.Size = new Size(163, 26); магазиныToolStripMenuItem.Size = new Size(224, 26);
магазиныToolStripMenuItem.Text = "Магазины"; магазиныToolStripMenuItem.Text = "Магазины";
магазиныToolStripMenuItem.Click += МагазиныToolStripMenuItem_Click; магазиныToolStripMenuItem.Click += МагазиныToolStripMenuItem_Click;
// //
@ -99,7 +100,7 @@
dataGridView.RowHeadersWidth = 51; dataGridView.RowHeadersWidth = 51;
dataGridView.RowTemplate.Height = 29; dataGridView.RowTemplate.Height = 29;
dataGridView.SelectionMode = DataGridViewSelectionMode.FullRowSelect; dataGridView.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
dataGridView.Size = new Size(984, 366); dataGridView.Size = new Size(984, 417);
dataGridView.TabIndex = 1; dataGridView.TabIndex = 1;
// //
// buttonCreateOrder // buttonCreateOrder
@ -162,11 +163,22 @@
buttonAddShip.UseVisualStyleBackColor = true; buttonAddShip.UseVisualStyleBackColor = true;
buttonAddShip.Click += ButtonAddShip_Click; buttonAddShip.Click += ButtonAddShip_Click;
// //
// buttonSellShip
//
buttonSellShip.Location = new Point(1032, 396);
buttonSellShip.Name = "buttonSellShip";
buttonSellShip.Size = new Size(178, 29);
buttonSellShip.TabIndex = 8;
buttonSellShip.Text = "Продать корабль";
buttonSellShip.UseVisualStyleBackColor = true;
buttonSellShip.Click += ButtonSellShip_Click;
//
// FormMain // FormMain
// //
AutoScaleDimensions = new SizeF(8F, 20F); AutoScaleDimensions = new SizeF(8F, 20F);
AutoScaleMode = AutoScaleMode.Font; AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(1251, 391); ClientSize = new Size(1251, 446);
Controls.Add(buttonSellShip);
Controls.Add(buttonAddShip); Controls.Add(buttonAddShip);
Controls.Add(buttonRefresh); Controls.Add(buttonRefresh);
Controls.Add(buttonIssue); Controls.Add(buttonIssue);
@ -199,5 +211,6 @@
private ToolStripMenuItem кораблиToolStripMenuItem; private ToolStripMenuItem кораблиToolStripMenuItem;
private ToolStripMenuItem магазиныToolStripMenuItem; private ToolStripMenuItem магазиныToolStripMenuItem;
private Button buttonAddShip; private Button buttonAddShip;
private Button buttonSellShip;
} }
} }

View File

@ -151,6 +151,15 @@ namespace ShipyardView
LoadData(); LoadData();
} }
} }
private void ButtonSellShip_Click(object sender, EventArgs e)
{
var service = Program.ServiceProvider?.GetService(typeof(FormSellShips));
if (service is FormSellShips form)
{
form.ShowDialog();
LoadData();
}
}
private void ButtonRef_Click(object sender, EventArgs e) private void ButtonRef_Click(object sender, EventArgs e)
{ {
LoadData(); LoadData();

View File

@ -0,0 +1,120 @@
namespace ShipyardView
{
partial class FormSellShips
{
/// <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()
{
this.ButtonCancel = new System.Windows.Forms.Button();
this.comboBoxShips = new System.Windows.Forms.ComboBox();
this.numericUpDownCount = new System.Windows.Forms.NumericUpDown();
this.labelShip = new System.Windows.Forms.Label();
this.labelCount = new System.Windows.Forms.Label();
this.ButtonSave = new System.Windows.Forms.Button();
((System.ComponentModel.ISupportInitialize)(this.numericUpDownCount)).BeginInit();
this.SuspendLayout();
//
// ButtonCancel
//
this.ButtonCancel.Location = new System.Drawing.Point(266, 153);
this.ButtonCancel.Name = "ButtonCancel";
this.ButtonCancel.Size = new System.Drawing.Size(94, 29);
this.ButtonCancel.TabIndex = 1;
this.ButtonCancel.Text = "Отмена";
this.ButtonCancel.UseVisualStyleBackColor = true;
this.ButtonCancel.Click += new System.EventHandler(this.ButtonCancel_Click);
//
// comboBoxShips
//
this.comboBoxShips.FormattingEnabled = true;
this.comboBoxShips.Location = new System.Drawing.Point(144, 38);
this.comboBoxShips.Name = "comboBoxShips";
this.comboBoxShips.Size = new System.Drawing.Size(216, 28);
this.comboBoxShips.TabIndex = 2;
//
// numericUpDownCount
//
this.numericUpDownCount.Location = new System.Drawing.Point(144, 102);
this.numericUpDownCount.Name = "numericUpDownCount";
this.numericUpDownCount.Size = new System.Drawing.Size(216, 27);
this.numericUpDownCount.TabIndex = 3;
//
// labelShip
//
this.labelShip.AutoSize = true;
this.labelShip.Location = new System.Drawing.Point(34, 38);
this.labelShip.Name = "labelShip";
this.labelShip.Size = new System.Drawing.Size(69, 20);
this.labelShip.TabIndex = 4;
this.labelShip.Text = "Корабль";
//
// labelCount
//
this.labelCount.AutoSize = true;
this.labelCount.Location = new System.Drawing.Point(34, 109);
this.labelCount.Name = "labelCount";
this.labelCount.Size = new System.Drawing.Size(90, 20);
this.labelCount.TabIndex = 5;
this.labelCount.Text = "Количество";
//
// ButtonSave
//
this.ButtonSave.Location = new System.Drawing.Point(144, 153);
this.ButtonSave.Name = "ButtonSave";
this.ButtonSave.Size = new System.Drawing.Size(94, 29);
this.ButtonSave.TabIndex = 6;
this.ButtonSave.Text = "Сохранить";
this.ButtonSave.UseVisualStyleBackColor = true;
this.ButtonSave.Click += new System.EventHandler(this.ButtonSave_Click);
//
// FormSellShips
//
this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 20F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(373, 194);
this.Controls.Add(this.ButtonSave);
this.Controls.Add(this.labelCount);
this.Controls.Add(this.labelShip);
this.Controls.Add(this.numericUpDownCount);
this.Controls.Add(this.comboBoxShips);
this.Controls.Add(this.ButtonCancel);
this.Name = "FormSellShips";
this.Text = "Продажа кораблей";
((System.ComponentModel.ISupportInitialize)(this.numericUpDownCount)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private Button ButtonCancel;
private ComboBox comboBoxShips;
private NumericUpDown numericUpDownCount;
private Label labelShip;
private Label labelCount;
private Button ButtonSave;
}
}

View File

@ -0,0 +1,77 @@
using Microsoft.Extensions.Logging;
using ShipyardContracts.BusinessLogicsContracts;
using ShipyardContracts.ViewModels;
namespace ShipyardView
{
public partial class FormSellShips : Form
{
private readonly ILogger _logger;
private readonly IShopLogic _shopLogic;
private readonly IShipLogic _shipLogic;
private readonly List<ShipViewModel>? _listShip;
public FormSellShips(ILogger<FormSellShips> logger, IShopLogic shopLogic, IShipLogic shipLogic)
{
InitializeComponent();
_logger = logger;
_shopLogic = shopLogic;
_shipLogic = shipLogic;
_listShip = shipLogic.ReadList(null);
if (_listShip != null)
{
comboBoxShips.DisplayMember = "ShipName";
comboBoxShips.ValueMember = "Id";
comboBoxShips.DataSource = _listShip;
comboBoxShips.SelectedItem = null;
}
}
private void ButtonSave_Click(object sender, EventArgs e)
{
if (comboBoxShips.SelectedValue == null)
{
MessageBox.Show("Выберите корабль", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
if (string.IsNullOrEmpty(numericUpDownCount.Text))
{
MessageBox.Show("Заполните количество", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
_logger.LogInformation("Продажа поездок");
try
{
var ship = _shipLogic.ReadElement(new()
{
Id = (int)comboBoxShips.SelectedValue
});
if (ship == null)
{
throw new Exception("Корабль не найден. Дополнительная информация в логах.");
}
var operationResult = _shopLogic.SellShips(
model: ship,
count: (int)numericUpDownCount.Value
);
if (!operationResult)
{
throw new Exception("Ошибка при продаже корабля. Дополнительная информация в логах.");
}
MessageBox.Show("Сохранение прошло успешно", "Сообщение", MessageBoxButtons.OK, MessageBoxIcon.Information);
DialogResult = DialogResult.OK;
Close();
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка сохранения корабля");
MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
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

@ -35,12 +35,15 @@
textBoxAddress = new TextBox(); textBoxAddress = new TextBox();
dateTimePickerDateOpen = new DateTimePicker(); dateTimePickerDateOpen = new DateTimePicker();
dataGridView = new DataGridView(); dataGridView = new DataGridView();
ButtonSave = new Button();
ButtonCancel = new Button();
ID = new DataGridViewTextBoxColumn(); ID = new DataGridViewTextBoxColumn();
ShipName = new DataGridViewTextBoxColumn(); ShipName = new DataGridViewTextBoxColumn();
Count = new DataGridViewTextBoxColumn(); Count = new DataGridViewTextBoxColumn();
ButtonSave = new Button();
ButtonCancel = new Button();
numericUpDownCapacity = new NumericUpDown();
labelCapacity = new Label();
((System.ComponentModel.ISupportInitialize)dataGridView).BeginInit(); ((System.ComponentModel.ISupportInitialize)dataGridView).BeginInit();
((System.ComponentModel.ISupportInitialize)numericUpDownCapacity).BeginInit();
SuspendLayout(); SuspendLayout();
// //
// labelShop // labelShop
@ -88,7 +91,7 @@
// //
dateTimePickerDateOpen.Location = new Point(474, 44); dateTimePickerDateOpen.Location = new Point(474, 44);
dateTimePickerDateOpen.Name = "dateTimePickerDateOpen"; dateTimePickerDateOpen.Name = "dateTimePickerDateOpen";
dateTimePickerDateOpen.Size = new Size(250, 27); dateTimePickerDateOpen.Size = new Size(195, 27);
dateTimePickerDateOpen.TabIndex = 5; dateTimePickerDateOpen.TabIndex = 5;
// //
// dataGridView // dataGridView
@ -104,29 +107,9 @@
dataGridView.RowHeadersVisible = false; dataGridView.RowHeadersVisible = false;
dataGridView.RowHeadersWidth = 51; dataGridView.RowHeadersWidth = 51;
dataGridView.RowTemplate.Height = 29; dataGridView.RowTemplate.Height = 29;
dataGridView.Size = new Size(712, 330); dataGridView.Size = new Size(870, 370);
dataGridView.TabIndex = 6; dataGridView.TabIndex = 6;
// //
// ButtonSave
//
ButtonSave.Location = new Point(490, 413);
ButtonSave.Name = "ButtonSave";
ButtonSave.Size = new Size(111, 29);
ButtonSave.TabIndex = 7;
ButtonSave.Text = "Сохранить";
ButtonSave.UseVisualStyleBackColor = true;
ButtonSave.Click += ButtonSave_Click;
//
// ButtonCancel
//
ButtonCancel.Location = new Point(630, 413);
ButtonCancel.Name = "ButtonCancel";
ButtonCancel.Size = new Size(94, 29);
ButtonCancel.TabIndex = 8;
ButtonCancel.Text = "Отмена";
ButtonCancel.UseVisualStyleBackColor = true;
ButtonCancel.Click += ButtonCancel_Click;
//
// ID // ID
// //
ID.AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill; ID.AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
@ -149,11 +132,49 @@
Count.MinimumWidth = 6; Count.MinimumWidth = 6;
Count.Name = "Count"; Count.Name = "Count";
// //
// ButtonSave
//
ButtonSave.Location = new Point(652, 453);
ButtonSave.Name = "ButtonSave";
ButtonSave.Size = new Size(111, 29);
ButtonSave.TabIndex = 7;
ButtonSave.Text = "Сохранить";
ButtonSave.UseVisualStyleBackColor = true;
ButtonSave.Click += ButtonSave_Click;
//
// ButtonCancel
//
ButtonCancel.Location = new Point(788, 453);
ButtonCancel.Name = "ButtonCancel";
ButtonCancel.Size = new Size(94, 29);
ButtonCancel.TabIndex = 8;
ButtonCancel.Text = "Отмена";
ButtonCancel.UseVisualStyleBackColor = true;
ButtonCancel.Click += ButtonCancel_Click;
//
// numericUpDownCapacity
//
numericUpDownCapacity.Location = new Point(701, 44);
numericUpDownCapacity.Name = "numericUpDownCapacity";
numericUpDownCapacity.Size = new Size(181, 27);
numericUpDownCapacity.TabIndex = 9;
//
// labelCapacity
//
labelCapacity.AutoSize = true;
labelCapacity.Location = new Point(701, 21);
labelCapacity.Name = "labelCapacity";
labelCapacity.Size = new Size(100, 20);
labelCapacity.TabIndex = 10;
labelCapacity.Text = "Вместимость";
//
// FormShop // FormShop
// //
AutoScaleDimensions = new SizeF(8F, 20F); AutoScaleDimensions = new SizeF(8F, 20F);
AutoScaleMode = AutoScaleMode.Font; AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(740, 450); ClientSize = new Size(906, 494);
Controls.Add(labelCapacity);
Controls.Add(numericUpDownCapacity);
Controls.Add(ButtonCancel); Controls.Add(ButtonCancel);
Controls.Add(ButtonSave); Controls.Add(ButtonSave);
Controls.Add(dataGridView); Controls.Add(dataGridView);
@ -167,6 +188,7 @@
Text = "Магазин"; Text = "Магазин";
Load += FormShop_Load; Load += FormShop_Load;
((System.ComponentModel.ISupportInitialize)dataGridView).EndInit(); ((System.ComponentModel.ISupportInitialize)dataGridView).EndInit();
((System.ComponentModel.ISupportInitialize)numericUpDownCapacity).EndInit();
ResumeLayout(false); ResumeLayout(false);
PerformLayout(); PerformLayout();
} }
@ -185,5 +207,7 @@
private DataGridViewTextBoxColumn ID; private DataGridViewTextBoxColumn ID;
private DataGridViewTextBoxColumn ShipName; private DataGridViewTextBoxColumn ShipName;
private DataGridViewTextBoxColumn Count; private DataGridViewTextBoxColumn Count;
private NumericUpDown numericUpDownCapacity;
private Label labelCapacity;
} }
} }

View File

@ -37,6 +37,7 @@ namespace ShipyardView
textBoxName.Text = view.ShopName; textBoxName.Text = view.ShopName;
textBoxAddress.Text = view.Address.ToString(); textBoxAddress.Text = view.Address.ToString();
dateTimePickerDateOpen.Text = view.DateOpen.ToString(); dateTimePickerDateOpen.Text = view.DateOpen.ToString();
numericUpDownCapacity.Value = view.Capacity;
_shopShips = view.ShopShips ?? new Dictionary<int, (IShipModel, int)>(); _shopShips = view.ShopShips ?? new Dictionary<int, (IShipModel, int)>();
LoadData(); LoadData();
} }
@ -86,6 +87,11 @@ namespace ShipyardView
MessageBox.Show("Заполните дату", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error); MessageBox.Show("Заполните дату", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
return; return;
} }
if (numericUpDownCapacity.Value <= 0)
{
MessageBox.Show("Вместимость должна быть больше нуля", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
_logger.LogInformation("Сохранение магазина"); _logger.LogInformation("Сохранение магазина");
try try
{ {
@ -95,6 +101,7 @@ namespace ShipyardView
ShopName = textBoxName.Text, ShopName = textBoxName.Text,
Address = textBoxAddress.Text, Address = textBoxAddress.Text,
DateOpen = DateTime.Parse(dateTimePickerDateOpen.Text), DateOpen = DateTime.Parse(dateTimePickerDateOpen.Text),
Capacity = (int)numericUpDownCapacity.Value,
ShopShips = _shopShips ShopShips = _shopShips
}; };
var operationResult = _id.HasValue ? _logic.Update(model) : _logic.Create(model); var operationResult = _id.HasValue ? _logic.Update(model) : _logic.Create(model);

View File

@ -47,6 +47,7 @@ namespace ShipyardView
services.AddTransient<FormShop>(); services.AddTransient<FormShop>();
services.AddTransient<FormShops>(); services.AddTransient<FormShops>();
services.AddTransient<FormAddShip>(); services.AddTransient<FormAddShip>();
services.AddTransient<FormSellShips>();
} }
} }