Merge branch 'LabWork02_Hard' into LabWork03_Hard

This commit is contained in:
commit 12c34b4097
31 changed files with 3137 additions and 5 deletions

View File

@ -4,6 +4,7 @@ using AircraftPlantContracts.SearchModels;
using AircraftPlantContracts.StoragesContracts;
using AircraftPlantContracts.ViewModels;
using AircraftPlantDataModels.Enums;
using AircraftPlantDataModels.Models;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
@ -28,16 +29,33 @@ namespace AircraftPlantBusinessLogic.BusinessLogics
/// </summary>
private readonly IOrderStorage _orderStorage;
/// <summary>
/// Взаимодействие с хранилищем магазинов
/// </summary>
private IShopStorage _shopStorage;
/// <summary>
/// Бизнес-логика магазинов
/// </summary>
private IShopLogic _shopLogic;
/// <summary>
/// Взаимодействие с хранилищем изделий
/// </summary>
private IPlaneStorage _planeStorage;
/// <summary>
/// Конструктор
/// </summary>
/// <param name="logger"></param>
/// <param name="orderStorage"></param>
public OrderLogic(ILogger<OrderLogic> logger, IOrderStorage
orderStorage)
public OrderLogic(ILogger<OrderLogic> logger, IOrderStorage orderStorage, IShopStorage shopStorage, IShopLogic shopLogic, IPlaneStorage planeStorage)
{
_logger = logger;
_orderStorage = orderStorage;
_shopStorage = shopStorage;
_shopLogic = shopLogic;
_planeStorage = planeStorage;
}
/// <summary>
@ -168,6 +186,21 @@ orderStorage)
model.Status = newStatus;
if (newStatus == OrderStatus.Выдан)
{
var plane = _planeStorage.GetElement(new PlaneSearchModel { Id = element.PlaneId });
if (plane == null)
{
_logger.LogWarning("Status change error. Plane not found");
return false;
}
if (!CheckSupply(plane, element.Count))
{
_logger.LogWarning("Status change error. Shop is overflowed");
return false;
}
}
if (model.Status == OrderStatus.Выдан)
{
model.DateImplement = DateTime.Now;
@ -184,5 +217,79 @@ orderStorage)
}
return true;
}
/// <summary>
/// Проверка заказа
/// </summary>
/// <param name="plane"></param>
/// <param name="count"></param>
/// <returns></returns>
public bool CheckSupply(IPlaneModel model, int count)
{
if (count <= 0)
{
_logger.LogWarning("Check supply operation error. Planes count < 0");
return false;
}
int sumCapacity = _shopStorage.GetFullList().Select(x => x.MaxPlanes).Sum();
int sumCount = _shopStorage.GetFullList().Select(x => x.ShopPlanes.Select(y => y.Value.Item2).Sum()).Sum();
int free = sumCapacity - sumCount;
if (free < count)
{
_logger.LogWarning("Check supply error. No place for new planes");
return false;
}
foreach (var shop in _shopStorage.GetFullList())
{
free = shop.MaxPlanes;
foreach (var plane in shop.ShopPlanes)
{
free -= plane.Value.Item2;
}
if (free == 0)
{
continue;
}
if (free >= count)
{
if (_shopLogic.AddPlaneInShop(new()
{
Id = shop.Id
}, model, count))
{
count = 0;
}
else
{
_logger.LogWarning("Supply error");
return false;
}
}
else
{
if (_shopLogic.AddPlaneInShop(new()
{
Id = shop.Id
}, model, free))
{
count -= free;
}
else
{
_logger.LogWarning("Supply error");
return false;
}
}
if (count <= 0)
{
return true;
}
}
return false;
}
}
}

View File

@ -32,8 +32,7 @@ namespace AircraftPlantBusinessLogic.BusinessLogics
/// </summary>
/// <param name="logger"></param>
/// <param name="planeStorage"></param>
public PlaneLogic(ILogger<PlaneLogic> logger, IPlaneStorage
planeStorage)
public PlaneLogic(ILogger<PlaneLogic> logger, IPlaneStorage planeStorage)
{
_logger = logger;
_planeStorage = planeStorage;

View File

@ -0,0 +1,258 @@
using AircraftPlantContracts.BindingModels;
using AircraftPlantContracts.BusinessLogicsContracts;
using AircraftPlantContracts.SearchModels;
using AircraftPlantContracts.StoragesContracts;
using AircraftPlantContracts.ViewModels;
using AircraftPlantDataModels.Models;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AircraftPlantBusinessLogic.BusinessLogics
{
/// <summary>
/// Реализация интерфейса бизнес-логики для магазинов
/// </summary>
public class ShopLogic : IShopLogic
{
/// <summary>
/// Логгер
/// </summary>
private readonly ILogger _logger;
/// <summary>
/// Взаимодействие с хранилищем магазинов
/// </summary>
private readonly IShopStorage _shopStorage;
/// <summary>
/// Конструктор
/// </summary>
/// <param name="logger"></param>
/// <param name="shopStorage"></param>
public ShopLogic(ILogger<ShopLogic> logger, IShopStorage shopStorage)
{
_logger = logger;
_shopStorage = shopStorage;
}
/// <summary>
/// Получение списка
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
public List<ShopViewModel>? ReadList(ShopSearchModel? model)
{
_logger.LogInformation("ReadList. ShopName:{ShopName}.Id:{ Id}", model?.ShopName, model?.Id);
var list = model == null ? _shopStorage.GetFullList() : _shopStorage.GetFilteredList(model);
if (list == null)
{
_logger.LogWarning("ReadList return null list");
return null;
}
_logger.LogInformation("ReadList. Count:{Count}", list.Count);
return list;
}
/// <summary>
/// Получение отдельной записи
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
/// <exception cref="ArgumentNullException"></exception>
public ShopViewModel? ReadElement(ShopSearchModel model)
{
if (model == null)
{
throw new ArgumentNullException(nameof(model));
}
_logger.LogInformation("ReadElement. ShopName:{ShopName}.Id:{ Id}", model.ShopName, model.Id);
var element = _shopStorage.GetElement(model);
if (element == null)
{
_logger.LogWarning("ReadElement element not found");
return null;
}
_logger.LogInformation("ReadElement find. Id:{Id}", element.Id);
return element;
}
/// <summary>
/// Создание записи
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
public bool Create(ShopBindingModel model)
{
CheckModel(model);
if (_shopStorage.Insert(model) == null)
{
_logger.LogWarning("Insert operation failed");
return false;
}
return true;
}
/// <summary>
/// Изменение записи
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
public bool Update(ShopBindingModel model)
{
CheckModel(model);
if (_shopStorage.Update(model) == null)
{
_logger.LogWarning("Update operation failed");
return false;
}
return true;
}
/// <summary>
/// Удаление записи
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
public bool Delete(ShopBindingModel model)
{
CheckModel(model, false);
_logger.LogInformation("Delete. Id:{Id}", model.Id);
if (_shopStorage.Delete(model) == null)
{
_logger.LogWarning("Delete operation failed");
return false;
}
return true;
}
/// <summary>
/// Добавление изделия в магазин
/// </summary>
/// <param name="model"></param>
/// <param name="plane"></param>
/// <param name="count"></param>
/// <returns></returns>
/// <exception cref="ArgumentNullException"></exception>
/// <exception cref="ArgumentException"></exception>
public bool AddPlaneInShop(ShopSearchModel model, IPlaneModel plane, int count)
{
if (model == null)
{
throw new ArgumentNullException(nameof(model));
}
if (count <= 0)
{
throw new ArgumentException("Количество изделий должно быть больше 0", nameof(count));
}
_logger.LogInformation("AddPlaneInShop. ShopName:{ShopName}.Id:{ Id}", model.ShopName, model.Id);
var element = _shopStorage.GetElement(model);
if (element == null)
{
_logger.LogWarning("AddPlaneInShop element not found");
return false;
}
_logger.LogInformation("AddPlaneInShop find. Id:{Id}", element.Id);
var countPlanes = element.ShopPlanes.Select(x => x.Value.Item2).Sum();
if (element.MaxPlanes - countPlanes < count)
{
_logger.LogWarning("Shop is overflowed");
return false;
}
if (element.ShopPlanes.TryGetValue(plane.Id, out var pair))
{
element.ShopPlanes[plane.Id] = (plane, count + pair.Item2);
_logger.LogInformation("AddPlaneInShop. Added {count} {plane} to '{ShopName}' shop", count, plane.PlaneName, element.ShopName);
}
else
{
element.ShopPlanes[plane.Id] = (plane, count);
_logger.LogInformation("AddPlaneInShop. Added {count} new plane {plane} to '{ShopName}' shop", count, plane.PlaneName, element.ShopName);
}
_shopStorage.Update(new()
{
Id = element.Id,
Address = element.Address,
ShopName = element.ShopName,
DateOpening = element.DateOpening,
ShopPlanes = element.ShopPlanes,
MaxPlanes = element.MaxPlanes
});
return true;
}
/// <summary>
/// Продажа изделий
/// </summary>
/// <param name="plane"></param>
/// <param name="count"></param>
/// <returns></returns>
/// <exception cref="ArgumentNullException"></exception>
/// <exception cref="ArgumentException"></exception>
public bool SellPlanes(IPlaneModel plane, int count)
{
if (plane == null)
{
throw new ArgumentNullException(nameof(plane));
}
if (count <= 0)
{
throw new ArgumentException("Количество изделий должно быть больше 0", nameof(count));
}
if (_shopStorage.SellPlanes(plane, count))
{
_logger.LogInformation("Selling sucsess");
return true;
}
_logger.LogInformation("Selling failed");
return false;
}
/// <summary>
/// Проверка модели магазина
/// </summary>
/// <param name="model"></param>
/// <param name="withParams"></param>
/// <exception cref="ArgumentNullException"></exception>
/// <exception cref="InvalidOperationException"></exception>
private void CheckModel(ShopBindingModel model, bool withParams = true)
{
if (model == null)
{
throw new ArgumentNullException(nameof(model));
}
if (!withParams)
{
return;
}
if (string.IsNullOrEmpty(model.ShopName))
{
throw new ArgumentNullException("Нет названия магазина", nameof(model.ShopName));
}
_logger.LogInformation("Shop. ShopName:{ShopName}.Address:{ Address}. Id:{ Id}", model.ShopName, model.Address, model.Id);
var element = _shopStorage.GetElement(new ShopSearchModel
{
ShopName = model.ShopName
});
if (element != null && element.Id != model.Id && element.ShopName == model.ShopName)
{
throw new InvalidOperationException("Магазин с таким названием уже есть");
}
}
}
}

View File

@ -0,0 +1,50 @@
using AircraftPlantDataModels.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AircraftPlantContracts.BindingModels
{
/// <summary>
/// Модель для передачи данных пользователя
/// в методы для сохранения данных для магазинов
/// </summary>
public class ShopBindingModel : IShopModel
{
/// <summary>
/// Идентификатор
/// </summary>
public int Id { get; set; }
/// <summary>
/// Название магазина
/// </summary>
public string ShopName { get; set; } = string.Empty;
/// <summary>
/// Адрес магазина
/// </summary>
public string Address { get; set; } = string.Empty;
/// <summary>
/// Дата открытия магазина
/// </summary>
public DateTime DateOpening { get; set; } = DateTime.Now;
/// <summary>
/// Коллекция изделий в магазине
/// </summary>
public Dictionary<int, (IPlaneModel, int)> ShopPlanes
{
get;
set;
} = new();
/// <summary>
/// Максимальное количество изделий
/// </summary>
public int MaxPlanes { get; set; }
}
}

View File

@ -0,0 +1,70 @@
using AircraftPlantContracts.BindingModels;
using AircraftPlantContracts.SearchModels;
using AircraftPlantContracts.ViewModels;
using AircraftPlantDataModels.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AircraftPlantContracts.BusinessLogicsContracts
{
/// <summary>
/// Интерфейс для описания работы бизнес-логики для магазинов
/// </summary>
public interface IShopLogic
{
/// <summary>
/// Получение списка
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
List<ShopViewModel>? ReadList(ShopSearchModel? model);
/// <summary>
/// Получение отдельной записи
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
ShopViewModel? ReadElement(ShopSearchModel model);
/// <summary>
/// Создание записи
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
bool Create(ShopBindingModel model);
/// <summary>
/// Изменение записи
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
bool Update(ShopBindingModel model);
/// <summary>
/// Удаление записи
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
bool Delete(ShopBindingModel model);
/// <summary>
/// Добавление изделия в магазин
/// </summary>
/// <param name="model"></param>
/// <param name="plane"></param>
/// <param name="count"></param>
/// <returns></returns>
bool AddPlaneInShop(ShopSearchModel model, IPlaneModel plane, int count);
/// <summary>
/// Продажа изделий
/// </summary>
/// <param name="plane"></param>
/// <param name="count"></param>
/// <returns></returns>
bool SellPlanes(IPlaneModel plane, int count);
}
}

View File

@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AircraftPlantContracts.SearchModels
{
/// <summary>
/// Модель для передачи данных пользователя
/// в методы для поиска данных для магазинов
/// </summary>
public class ShopSearchModel
{
/// <summary>
/// Идентификатор
/// </summary>
public int? Id { get; set; }
/// <summary>
/// Название магазина
/// </summary>
public string? ShopName { get; set; }
}
}

View File

@ -0,0 +1,75 @@
using AircraftPlantContracts.BindingModels;
using AircraftPlantContracts.SearchModels;
using AircraftPlantContracts.ViewModels;
using AircraftPlantDataModels.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AircraftPlantContracts.StoragesContracts
{
/// <summary>
/// Интерфейс для описания работы с хранилищем для магазинов
/// </summary>
public interface IShopStorage
{
/// <summary>
/// Получение полного списка
/// </summary>
/// <returns></returns>
List<ShopViewModel> GetFullList();
/// <summary>
/// Получение фильтрованного списка
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
List<ShopViewModel> GetFilteredList(ShopSearchModel model);
/// <summary>
/// Получение элемента
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
ShopViewModel? GetElement(ShopSearchModel model);
/// <summary>
/// Добавление элемента
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
ShopViewModel? Insert(ShopBindingModel model);
/// <summary>
/// Редактирование элемента
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
ShopViewModel? Update(ShopBindingModel model);
/// <summary>
/// Удаление элемента
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
ShopViewModel? Delete(ShopBindingModel model);
/// <summary>
/// Продажа изделий
/// </summary>
/// <param name="model"></param>
/// <param name="count"></param>
/// <returns></returns>
bool SellPlanes(IPlaneModel model, int count);
/// <summary>
/// Проверка наличия в нужном количестве
/// </summary>
/// <param name="model"></param>
/// <param name="count"></param>
/// <returns></returns>
bool CheckCount(IPlaneModel model, int count);
}
}

View File

@ -0,0 +1,55 @@
using AircraftPlantDataModels.Models;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AircraftPlantContracts.ViewModels
{
/// <summary>
/// Модель для передачи данных пользователю
/// для отображения для магазинов
/// </summary>
public class ShopViewModel : IShopModel
{
/// <summary>
/// Идентификатор
/// </summary>
public int Id { get; set; }
/// <summary>
/// Название магазина
/// </summary>
[DisplayName("Название магазина")]
public string ShopName { get; set; } = string.Empty;
/// <summary>
/// Адрес магазина
/// </summary>
[DisplayName("Адрес магазина")]
public string Address { get; set; } = string.Empty;
/// <summary>
/// Дата открытия магазина
/// </summary>
[DisplayName("Дата открытия")]
public DateTime DateOpening { get; set; } = DateTime.Now;
/// <summary>
/// Коллекция изделий в магазине
/// </summary>
public Dictionary<int, (IPlaneModel, int)> ShopPlanes
{
get;
set;
} = new();
/// <summary>
/// Максимальное количество изделий
/// </summary>
[DisplayName("Максимальное количество изделий")]
public int MaxPlanes { get; set; }
}
}

View File

@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AircraftPlantDataModels.Models
{
/// <summary>
/// Интерфейс для модели магазина
/// </summary>
public interface IShopModel : IId
{
/// <summary>
/// Название магазина
/// </summary>
string ShopName { get; }
/// <summary>
/// Адрес магазина
/// </summary>
string Address { get; }
/// <summary>
/// Дата открытия магазина
/// </summary>
DateTime DateOpening { get; }
/// <summary>
/// Коллекция изделий в магазине
/// </summary>
Dictionary<int, (IPlaneModel, int)> ShopPlanes { get; }
/// <summary>
/// Максимальное количество изделий
/// </summary>
int MaxPlanes { get; }
}
}

View File

@ -33,6 +33,11 @@ namespace AircraftPlantFileImplement
/// </summary>
private readonly string PlaneFileName = "Plane.xml";
/// <summary>
/// Название файла для хранения информации о магазинах
/// </summary>
private readonly string ShopFileName = "Shop.xml";
/// <summary>
/// Список классов-моделей компонентов
/// </summary>
@ -48,6 +53,11 @@ namespace AircraftPlantFileImplement
/// </summary>
public List<Plane> Planes { get; set; }
/// <summary>
/// Список классов-моделей магазина
/// </summary>
public List<Shop> Shops { get; set; }
/// <summary>
/// Конструктор
/// </summary>
@ -56,6 +66,7 @@ namespace AircraftPlantFileImplement
Components = LoadData(ComponentFileName, "Component", x => Component.Create(x)!)!;
Planes = LoadData(PlaneFileName, "Plane", x => Plane.Create(x)!)!;
Orders = LoadData(OrderFileName, "Order", x => Order.Create(x)!)!;
Shops = LoadData(ShopFileName, "Shop", x => Shop.Create(x)!)!;
}
/// <summary>
@ -86,6 +97,11 @@ namespace AircraftPlantFileImplement
/// </summary>
public void SaveOrders() => SaveData(Orders, OrderFileName, "Orders", x => x.GetXElement);
/// <summary>
/// Сохранение магазинов
/// </summary>
public void SaveShops() => SaveData(Shops, ShopFileName, "Shops", x => x.GetXElement);
/// <summary>
/// Метод для загрузки данных из xml-файла
/// </summary>

View File

@ -8,6 +8,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace AircraftPlantFileImplement.Implements
{

View File

@ -0,0 +1,197 @@
using AircraftPlantContracts.BindingModels;
using AircraftPlantContracts.SearchModels;
using AircraftPlantContracts.StoragesContracts;
using AircraftPlantContracts.ViewModels;
using AircraftPlantDataModels.Models;
using AircraftPlantFileImplement.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
namespace AircraftPlantFileImplement.Implements
{
/// <summary>
/// Реализация интерфейса хранилища для магазина
/// </summary>
public class ShopStorage : IShopStorage
{
/// <summary>
/// Хранилище
/// </summary>
private readonly DataFileSingleton _source;
/// <summary>
/// Конструктор
/// </summary>
public ShopStorage()
{
_source = DataFileSingleton.GetInstance();
}
/// <summary>
/// Получение полного списка
/// </summary>
/// <returns></returns>
public List<ShopViewModel> GetFullList()
{
return _source.Shops
.Select(x => x.GetViewModel)
.ToList();
}
/// <summary>
/// Получение фильтрованного списка
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
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();
}
/// <summary>
/// Получение элемента
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
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;
}
/// <summary>
/// Добавление элемента
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
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;
}
/// <summary>
/// Редактирование элемента
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
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;
}
/// <summary>
/// Удаление элемента
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
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;
}
/// <summary>
/// Продажа изделий
/// </summary>
/// <param name="model"></param>
/// <param name="count"></param>
/// <returns></returns>
public bool SellPlanes(IPlaneModel model, int count)
{
var plane = _source.Planes.FirstOrDefault(x => x.Id == model.Id);
if (plane == null || !CheckCount(model, count))
{
return false;
}
foreach (var shop in _source.Shops)
{
var planes = shop.ShopPlanes;
foreach (var elem in planes.Where(x => x.Value.Item1.Id == plane.Id))
{
var selling = Math.Min(elem.Value.Item2, count);
planes[elem.Value.Item1.Id] = (elem.Value.Item1, elem.Value.Item2 - selling);
count -= selling;
if (count <= 0)
{
break;
}
}
shop.Update(new ShopBindingModel
{
Id = model.Id,
ShopName = shop.ShopName,
Address = shop.Address,
DateOpening = shop.DateOpening,
ShopPlanes = planes,
MaxPlanes = shop.MaxPlanes
});
}
_source.SaveShops();
return true;
}
/// <summary>
/// Проверка наличия в нужном количестве
/// </summary>
/// <param name="model"></param>
/// <param name="count"></param>
/// <returns></returns>
public bool CheckCount(IPlaneModel model, int count)
{
int store = _source.Shops
.Select(x => x.ShopPlanes
.Select(y => (y.Value.Item1.Id == model.Id ? y.Value.Item2 : 0))
.Sum()).Sum();
return store >= count;
}
}
}

View File

@ -0,0 +1,158 @@
using AircraftPlantContracts.BindingModels;
using AircraftPlantContracts.ViewModels;
using AircraftPlantDataModels.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace AircraftPlantFileImplement.Models
{
/// <summary>
/// Сущность "Магазин"
/// </summary>
public class Shop : IShopModel
{
/// <summary>
/// Идентификатор
/// </summary>
public int Id { get; private set; }
/// <summary>
/// Название магазина
/// </summary>
public string ShopName { get; private set; } = string.Empty;
/// <summary>
/// Адрес магазина
/// </summary>
public string Address { get; private set; } = string.Empty;
/// <summary>
/// Дата открытия магазина
/// </summary>
public DateTime DateOpening { get; private set; }
/// <summary>
/// Коллекция изделий магазина в виде
/// «идентификатор изделия количество изделий»
/// </summary>
public Dictionary<int, int> Planes { get; private set; } = new();
/// <summary>
/// Коллекция изделий в магазине
/// </summary>
private Dictionary<int, (IPlaneModel, int)>? _shopPlanes = null;
public Dictionary<int, (IPlaneModel, int)> ShopPlanes
{
get
{
if (_shopPlanes == null)
{
var source = DataFileSingleton.GetInstance();
_shopPlanes = Planes.ToDictionary(x => x.Key, y => ((source.Planes.FirstOrDefault(z => z.Id == y.Key) as IPlaneModel)!, y.Value));
}
return _shopPlanes;
}
}
/// <summary>
/// Максимальное количество изделий
/// </summary>
public int MaxPlanes { get; private set; }
/// <summary>
/// Создание модели магазина из данных файла
/// </summary>
/// <param name="element"></param>
/// <returns></returns>
public static Shop? Create(XElement element)
{
if (element == null)
{
return null;
}
return new()
{
Id = Convert.ToInt32(element.Attribute("Id")!.Value),
ShopName = element.Element("ShopName")!.Value,
Address = element.Element("Address")!.Value,
DateOpening = Convert.ToDateTime(element.Element("DateOpening")!.Value),
Planes = element.Element("ShopPlanes")!.Elements("ShopPlanes")!
.ToDictionary(x => Convert.ToInt32(x.Element("Key")?.Value), x => Convert.ToInt32(x.Element("Value")?.Value)),
MaxPlanes = Convert.ToInt32(element.Element("MaxPlanes")!.Value)
};
}
/// <summary>
/// Создание модели магазина
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
public static Shop? Create(ShopBindingModel? model)
{
if (model == null)
{
return null;
}
return new Shop()
{
Id = model.Id,
ShopName = model.ShopName,
Address = model.Address,
DateOpening = model.DateOpening,
Planes = model.ShopPlanes.ToDictionary(x => x.Key, x => x.Value.Item2),
MaxPlanes = model.MaxPlanes
};
}
/// <summary>
/// Изменение модели магазина
/// </summary>
/// <param name="model"></param>
public void Update(ShopBindingModel? model)
{
if (model == null)
{
return;
}
ShopName = model.ShopName;
Address = model.Address;
DateOpening = model.DateOpening;
Planes = model.ShopPlanes.ToDictionary(x => x.Key, x => x.Value.Item2);
MaxPlanes = model.MaxPlanes;
_shopPlanes = null;
}
/// <summary>
/// Получение модели магазина
/// </summary>
public ShopViewModel GetViewModel => new()
{
Id = Id,
ShopName = ShopName,
Address = Address,
DateOpening = DateOpening,
ShopPlanes = ShopPlanes,
MaxPlanes = MaxPlanes
};
/// <summary>
/// Запись данных о модели магазина в файл
/// </summary>
public XElement GetXElement => new("Shop",
new XAttribute("Id", Id),
new XElement("ShopName", ShopName),
new XElement("Address", Address),
new XElement("DateOpening", DateOpening.ToString()),
new XElement("ShopPlanes", Planes.Select(x =>
new XElement("ShopPlanes",
new XElement("Key", x.Key),
new XElement("Value", x.Value))).ToArray()),
new XElement("MaxPlanes", MaxPlanes.ToString()));
}
}

View File

@ -32,6 +32,11 @@ namespace AircraftPlantListImplement
/// </summary>
public List<Plane> Planes { get; set; }
/// <summary>
/// Список классов-моделей магазинов
/// </summary>
public List<Shop> Shops { get; set; }
/// <summary>
/// Конструктор
/// </summary>
@ -40,6 +45,7 @@ namespace AircraftPlantListImplement
Components = new List<Component>();
Orders = new List<Order>();
Planes = new List<Plane>();
Shops = new List<Shop>();
}
/// <summary>

View File

@ -0,0 +1,179 @@
using AircraftPlantContracts.BindingModels;
using AircraftPlantContracts.SearchModels;
using AircraftPlantContracts.StoragesContracts;
using AircraftPlantContracts.ViewModels;
using AircraftPlantDataModels.Models;
using AircraftPlantListImplement.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AircraftPlantListImplement.Implements
{
/// <summary>
/// Реализация интерфейса хранилища для магазина
/// </summary>
public class ShopStorage : IShopStorage
{
/// <summary>
/// Хранилище
/// </summary>
private readonly DataListSingleton _source;
/// <summary>
/// Конструктор
/// </summary>
public ShopStorage()
{
_source = DataListSingleton.GetInstance();
}
/// <summary>
/// Получение полного списка
/// </summary>
/// <returns></returns>
public List<ShopViewModel> GetFullList()
{
var result = new List<ShopViewModel>();
foreach (var shop in _source.Shops)
{
result.Add(shop.GetViewModel);
}
return result;
}
/// <summary>
/// Получение фильтрованного списка
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
public List<ShopViewModel> GetFilteredList(ShopSearchModel model)
{
var result = new List<ShopViewModel>();
if (string.IsNullOrEmpty(model.ShopName))
{
return result;
}
foreach (var shop in _source.Shops)
{
if (shop.ShopName.Contains(model.ShopName))
{
result.Add(shop.GetViewModel);
}
}
return result;
}
/// <summary>
/// Получение элемента
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
public ShopViewModel? GetElement(ShopSearchModel model)
{
if (string.IsNullOrEmpty(model.ShopName) && !model.Id.HasValue)
{
return null;
}
foreach (var shop in _source.Shops)
{
if ((!string.IsNullOrEmpty(model.ShopName) && shop.ShopName == model.ShopName) || (model.Id.HasValue && shop.Id == model.Id))
{
return shop.GetViewModel;
}
}
return null;
}
/// <summary>
/// Добавление элемента
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
public ShopViewModel? Insert(ShopBindingModel model)
{
model.Id = 1;
foreach (var shop in _source.Shops)
{
if (model.Id <= shop.Id)
{
model.Id = shop.Id + 1;
}
}
var newShop = Shop.Create(model);
if (newShop == null)
{
return null;
}
_source.Shops.Add(newShop);
return newShop.GetViewModel;
}
/// <summary>
/// Редактирование элемента
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
public ShopViewModel? Update(ShopBindingModel model)
{
foreach (var shop in _source.Shops)
{
if (shop.Id == model.Id)
{
shop.Update(model);
return shop.GetViewModel;
}
}
return null;
}
/// <summary>
/// Удаление элемента
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
public ShopViewModel? Delete(ShopBindingModel model)
{
for (int i = 0; i < _source.Shops.Count; ++i)
{
if (_source.Shops[i].Id == model.Id)
{
var element = _source.Shops[i];
_source.Shops.RemoveAt(i);
return element.GetViewModel;
}
}
return null;
}
/// <summary>
/// Продажа изделий
/// </summary>
/// <param name="plane"></param>
/// <param name="count"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public bool SellPlanes(IPlaneModel model, int count)
{
throw new NotImplementedException();
}
/// <summary>
/// Проверка наличия в нужном количестве
/// </summary>
/// <param name="model"></param>
/// <param name="count"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public bool CheckCount(IPlaneModel model, int count)
{
throw new NotImplementedException();
}
}
}

View File

@ -0,0 +1,105 @@
using AircraftPlantContracts.BindingModels;
using AircraftPlantContracts.ViewModels;
using AircraftPlantDataModels.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AircraftPlantListImplement.Models
{
/// <summary>
/// Сущность "Магазин"
/// </summary>
public class Shop : IShopModel
{
/// <summary>
/// Идентификатор
/// </summary>
public int Id { get; private set; }
/// <summary>
/// Название магазина
/// </summary>
public string ShopName { get; private set; } = string.Empty;
/// <summary>
/// Адрес магазина
/// </summary>
public string Address { get; private set; } = string.Empty;
/// <summary>
/// Дата открытия магазина
/// </summary>
public DateTime DateOpening { get; private set; }
/// <summary>
/// Коллекция изделий в магазине
/// </summary>
public Dictionary<int, (IPlaneModel, int)> ShopPlanes
{
get;
private set;
} = new Dictionary<int, (IPlaneModel, int)>();
/// <summary>
/// Максимальное количество изделий
/// </summary>
public int MaxPlanes { get; private set; }
/// <summary>
/// Создание модели магазина
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
public static Shop? Create(ShopBindingModel? model)
{
if (model == null)
{
return null;
}
return new Shop()
{
Id = model.Id,
ShopName = model.ShopName,
Address = model.Address,
DateOpening = model.DateOpening,
ShopPlanes = model.ShopPlanes,
MaxPlanes = model.MaxPlanes
};
}
/// <summary>
/// Изменение модели магазина
/// </summary>
/// <param name="model"></param>
public void Update(ShopBindingModel? model)
{
if (model == null)
{
return;
}
ShopName = model.ShopName;
Address = model.Address;
DateOpening = model.DateOpening;
ShopPlanes = model.ShopPlanes;
MaxPlanes = model.MaxPlanes;
}
/// <summary>
/// Получение модели магазина
/// </summary>
public ShopViewModel GetViewModel => new()
{
Id = Id,
ShopName = ShopName,
Address = Address,
DateOpening = DateOpening,
ShopPlanes = ShopPlanes,
MaxPlanes = MaxPlanes
};
}
}

View File

@ -0,0 +1,146 @@
namespace AircraftPlantView
{
partial class FormCreateSupply
{
/// <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()
{
comboBoxShop = new ComboBox();
labelShop = new Label();
labelPlane = new Label();
comboBoxPlane = new ComboBox();
numericUpDownCount = new NumericUpDown();
labelCount = new Label();
buttonCancel = new Button();
buttonSave = new Button();
((System.ComponentModel.ISupportInitialize)numericUpDownCount).BeginInit();
SuspendLayout();
//
// comboBoxShop
//
comboBoxShop.DropDownStyle = ComboBoxStyle.DropDownList;
comboBoxShop.FormattingEnabled = true;
comboBoxShop.Location = new Point(90, 12);
comboBoxShop.Name = "comboBoxShop";
comboBoxShop.Size = new Size(282, 23);
comboBoxShop.TabIndex = 0;
//
// labelShop
//
labelShop.AutoSize = true;
labelShop.Location = new Point(12, 15);
labelShop.Name = "labelShop";
labelShop.Size = new Size(57, 15);
labelShop.TabIndex = 1;
labelShop.Text = "Магазин:";
//
// labelPlane
//
labelPlane.AutoSize = true;
labelPlane.Location = new Point(12, 44);
labelPlane.Name = "labelPlane";
labelPlane.Size = new Size(56, 15);
labelPlane.TabIndex = 2;
labelPlane.Text = "Изделие:";
//
// comboBoxPlane
//
comboBoxPlane.DropDownStyle = ComboBoxStyle.DropDownList;
comboBoxPlane.FormattingEnabled = true;
comboBoxPlane.Location = new Point(90, 41);
comboBoxPlane.Name = "comboBoxPlane";
comboBoxPlane.Size = new Size(282, 23);
comboBoxPlane.TabIndex = 3;
//
// numericUpDownCount
//
numericUpDownCount.Location = new Point(90, 70);
numericUpDownCount.Name = "numericUpDownCount";
numericUpDownCount.Size = new Size(282, 23);
numericUpDownCount.TabIndex = 4;
//
// labelCount
//
labelCount.AutoSize = true;
labelCount.Location = new Point(12, 72);
labelCount.Name = "labelCount";
labelCount.Size = new Size(75, 15);
labelCount.TabIndex = 5;
labelCount.Text = "Количество:";
//
// buttonCancel
//
buttonCancel.Location = new Point(297, 99);
buttonCancel.Name = "buttonCancel";
buttonCancel.Size = new Size(75, 23);
buttonCancel.TabIndex = 6;
buttonCancel.Text = "Отмена";
buttonCancel.UseVisualStyleBackColor = true;
buttonCancel.Click += buttonCancel_Click;
//
// buttonSave
//
buttonSave.Location = new Point(216, 99);
buttonSave.Name = "buttonSave";
buttonSave.Size = new Size(75, 23);
buttonSave.TabIndex = 7;
buttonSave.Text = "Сохранить";
buttonSave.UseVisualStyleBackColor = true;
buttonSave.Click += buttonSave_Click;
//
// FormCreateSupply
//
AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(384, 131);
Controls.Add(buttonSave);
Controls.Add(buttonCancel);
Controls.Add(labelCount);
Controls.Add(numericUpDownCount);
Controls.Add(comboBoxPlane);
Controls.Add(labelPlane);
Controls.Add(labelShop);
Controls.Add(comboBoxShop);
Name = "FormCreateSupply";
Text = "Поступление";
Load += FormCreateSupply_Load;
((System.ComponentModel.ISupportInitialize)numericUpDownCount).EndInit();
ResumeLayout(false);
PerformLayout();
}
#endregion
private ComboBox comboBoxShop;
private Label labelShop;
private Label labelPlane;
private ComboBox comboBoxPlane;
private NumericUpDown numericUpDownCount;
private Label labelCount;
private Button buttonCancel;
private Button buttonSave;
}
}

View File

@ -0,0 +1,159 @@
using AircraftPlantBusinessLogic.BusinessLogics;
using AircraftPlantContracts.BusinessLogicsContracts;
using AircraftPlantContracts.SearchModels;
using Microsoft.Extensions.Logging;
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 AircraftPlantView
{
/// <summary>
/// Форма для добавления поступления
/// </summary>
public partial class FormCreateSupply : Form
{
/// <summary>
/// Логгер
/// </summary>
private readonly ILogger _logger;
/// <summary>
/// Бизнес-логика для магазина
/// </summary>
private readonly IShopLogic _logicS;
/// <summary>
/// Бизнес-логика для изделий
/// </summary>
private readonly IPlaneLogic _logicP;
/// <summary>
/// Конструктор
/// </summary>
/// <param name="logger"></param>
/// <param name="logicS"></param>
/// <param name="logicP"></param>
public FormCreateSupply(ILogger<FormCreateSupply> logger, IShopLogic logicS, IPlaneLogic logicP)
{
InitializeComponent();
_logger = logger;
_logicS = logicS;
_logicP = logicP;
}
/// <summary>
/// Загрузка списиков магазинов и изделий
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void FormCreateSupply_Load(object sender, EventArgs e)
{
_logger.LogInformation("Загрузка магазинов");
try
{
var listShops = _logicS.ReadList(null);
if (listShops != null)
{
comboBoxShop.DisplayMember = "ShopName";
comboBoxShop.ValueMember = "Id";
comboBoxShop.DataSource = listShops;
comboBoxShop.SelectedItem = null;
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка загрузки списка магазинов");
MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
_logger.LogInformation("Загрузка изделий");
try
{
var listPlanes = _logicP.ReadList(null);
if (listPlanes != null)
{
comboBoxPlane.DisplayMember = "PlaneName";
comboBoxPlane.ValueMember = "Id";
comboBoxPlane.DataSource = listPlanes;
comboBoxPlane.SelectedItem = null;
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка загрузки списка изделий");
MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
/// <summary>
/// Кнопка "Сохранить"
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void buttonSave_Click(object sender, EventArgs e)
{
if (comboBoxShop.SelectedValue == null)
{
MessageBox.Show("Выберите магазин", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
if (comboBoxPlane.SelectedValue == null)
{
MessageBox.Show("Выберите изделие", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
_logger.LogInformation("Добавление изделия в магазин");
try
{
var plane = _logicP.ReadElement(new()
{
Id = (int)comboBoxPlane.SelectedValue
});
if (plane == null)
{
throw new Exception("Не найдено изделие. Дополнительная информация в логах.");
}
var resultOperation = _logicS.AddPlaneInShop(
new ShopSearchModel
{
Id = (int)comboBoxShop.SelectedValue
},
plane,
(int)numericUpDownCount.Value
);
if (!resultOperation)
{
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);
}
}
/// <summary>
/// Кнопка "Отмена"
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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

@ -38,6 +38,9 @@
справочникиToolStripMenuItem = new ToolStripMenuItem();
компонентыToolStripMenuItem = new ToolStripMenuItem();
изделияToolStripMenuItem = new ToolStripMenuItem();
магазиныToolStripMenuItem = new ToolStripMenuItem();
buttonAddPlaneInShop = new Button();
buttonSellPlanes = new Button();
((System.ComponentModel.ISupportInitialize)dataGridView).BeginInit();
menuStrip.SuspendLayout();
SuspendLayout();
@ -121,7 +124,7 @@
//
// справочникиToolStripMenuItem
//
справочникиToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { компонентыToolStripMenuItem, изделияToolStripMenuItem });
справочникиToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { компонентыToolStripMenuItem, изделияToolStripMenuItem, магазиныToolStripMenuItem });
справочникиToolStripMenuItem.Name = "справочникиToolStripMenuItem";
справочникиToolStripMenuItem.Size = new Size(94, 20);
справочникиToolStripMenuItem.Text = "Справочники";
@ -140,11 +143,40 @@
изделияToolStripMenuItem.Text = "Изделия";
изделияToolStripMenuItem.Click += изделияToolStripMenuItem_Click;
//
// магазиныToolStripMenuItem
//
магазиныToolStripMenuItem.Name = агазиныToolStripMenuItem";
магазиныToolStripMenuItem.Size = new Size(145, 22);
магазиныToolStripMenuItem.Text = "Магазины";
магазиныToolStripMenuItem.Click += магазиныToolStripMenuItem_Click;
//
// buttonAddPlaneInShop
//
buttonAddPlaneInShop.Location = new Point(822, 210);
buttonAddPlaneInShop.Name = "buttonAddPlaneInShop";
buttonAddPlaneInShop.Size = new Size(150, 50);
buttonAddPlaneInShop.TabIndex = 7;
buttonAddPlaneInShop.Text = "Добавить изделие\r\nв магазин";
buttonAddPlaneInShop.UseVisualStyleBackColor = true;
buttonAddPlaneInShop.Click += buttonAddPlaneInShop_Click;
//
// buttonSellPlanes
//
buttonSellPlanes.Location = new Point(822, 266);
buttonSellPlanes.Name = "buttonSellPlanes";
buttonSellPlanes.Size = new Size(150, 23);
buttonSellPlanes.TabIndex = 8;
buttonSellPlanes.Text = "Продать изделия";
buttonSellPlanes.UseVisualStyleBackColor = true;
buttonSellPlanes.Click += buttonSellPlanes_Click;
//
// FormMain
//
AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(984, 361);
Controls.Add(buttonSellPlanes);
Controls.Add(buttonAddPlaneInShop);
Controls.Add(buttonRefresh);
Controls.Add(buttonIssuedOrder);
Controls.Add(buttonOrderReady);
@ -175,5 +207,8 @@
private ToolStripMenuItem справочникиToolStripMenuItem;
private ToolStripMenuItem компонентыToolStripMenuItem;
private ToolStripMenuItem изделияToolStripMenuItem;
private ToolStripMenuItem магазиныToolStripMenuItem;
private Button buttonAddPlaneInShop;
private Button buttonSellPlanes;
}
}

View File

@ -79,6 +79,20 @@ namespace AircraftPlantView
}
}
/// <summary>
/// Показать список всех магазинов
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void магазиныToolStripMenuItem_Click(object sender, EventArgs e)
{
var service = Program.ServiceProvider?.GetService(typeof(FormShops));
if (service is FormShops form)
{
form.ShowDialog();
}
}
/// <summary>
/// Кнопка "Создать заказ"
/// </summary>
@ -179,6 +193,34 @@ namespace AircraftPlantView
}
}
/// <summary>
/// Кнопка "Добавить изделие в магазин"
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void buttonAddPlaneInShop_Click(object sender, EventArgs e)
{
var service = Program.ServiceProvider?.GetService(typeof(FormCreateSupply));
if (service is FormCreateSupply form)
{
form.ShowDialog();
}
}
/// <summary>
/// Кнопка "Продать изделия"
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void buttonSellPlanes_Click(object sender, EventArgs e)
{
var services = Program.ServiceProvider?.GetService(typeof(FormSell));
if (services is FormSell form)
{
form.ShowDialog();
}
}
/// <summary>
/// Кнопка "Обновить список"
/// </summary>

View File

@ -0,0 +1,119 @@
namespace AircraftPlantView
{
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()
{
comboBoxPlane = new ComboBox();
labelPlane = new Label();
labelCount = new Label();
buttonCancel = new Button();
buttonSave = new Button();
textBoxCount = new TextBox();
SuspendLayout();
//
// comboBoxPlane
//
comboBoxPlane.FormattingEnabled = true;
comboBoxPlane.Location = new Point(90, 12);
comboBoxPlane.Name = "comboBoxPlane";
comboBoxPlane.Size = new Size(282, 23);
comboBoxPlane.TabIndex = 0;
//
// labelPlane
//
labelPlane.AutoSize = true;
labelPlane.Location = new Point(12, 15);
labelPlane.Name = "labelPlane";
labelPlane.Size = new Size(56, 15);
labelPlane.TabIndex = 2;
labelPlane.Text = "Изделие:";
//
// labelCount
//
labelCount.AutoSize = true;
labelCount.Location = new Point(12, 43);
labelCount.Name = "labelCount";
labelCount.Size = new Size(75, 15);
labelCount.TabIndex = 3;
labelCount.Text = "Количество:";
//
// buttonCancel
//
buttonCancel.Location = new Point(297, 76);
buttonCancel.Name = "buttonCancel";
buttonCancel.Size = new Size(75, 23);
buttonCancel.TabIndex = 4;
buttonCancel.Text = "Отмена";
buttonCancel.UseVisualStyleBackColor = true;
buttonCancel.Click += buttonCancel_Click;
//
// buttonSave
//
buttonSave.Location = new Point(216, 76);
buttonSave.Name = "buttonSave";
buttonSave.Size = new Size(75, 23);
buttonSave.TabIndex = 5;
buttonSave.Text = "Сохранить";
buttonSave.UseVisualStyleBackColor = true;
buttonSave.Click += buttonSave_Click;
//
// textBoxCount
//
textBoxCount.Location = new Point(90, 41);
textBoxCount.Name = "textBoxCount";
textBoxCount.Size = new Size(282, 23);
textBoxCount.TabIndex = 6;
//
// FormSell
//
AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(384, 111);
Controls.Add(textBoxCount);
Controls.Add(buttonSave);
Controls.Add(buttonCancel);
Controls.Add(labelCount);
Controls.Add(labelPlane);
Controls.Add(comboBoxPlane);
Name = "FormSell";
Text = "Продажа";
Load += FormSell_Load;
ResumeLayout(false);
PerformLayout();
}
#endregion
private ComboBox comboBoxPlane;
private Label labelPlane;
private Label labelCount;
private Button buttonCancel;
private Button buttonSave;
private TextBox textBoxCount;
}
}

View File

@ -0,0 +1,127 @@
using AircraftPlantContracts.BindingModels;
using AircraftPlantContracts.BusinessLogicsContracts;
using Microsoft.Extensions.Logging;
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 AircraftPlantView
{
/// <summary>
/// Форма продажи изделий
/// </summary>
public partial class FormSell : Form
{
/// <summary>
/// Логгер
/// </summary>
private readonly ILogger _logger;
/// <summary>
/// Бизнес-логика для изделий
/// </summary>
private readonly IPlaneLogic _logicP;
/// <summary>
/// Бизнес-логика для магазинов
/// </summary>
private readonly IShopLogic _logicS;
/// <summary>
/// Конструктор
/// </summary>
/// <param name="logger"></param>
/// <param name="planeLogic"></param>
/// <param name="shopLogic"></param>
public FormSell(ILogger<FormSell> logger, IPlaneLogic planeLogic, IShopLogic shopLogic)
{
InitializeComponent();
_logger = logger;
_logicP = planeLogic;
_logicS = shopLogic;
}
/// <summary>
/// Загрузка списка изделий
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void FormSell_Load(object sender, EventArgs e)
{
_logger.LogInformation("Загрузка изделий для продажи");
try
{
var list = _logicP.ReadList(null);
if (list != null)
{
comboBoxPlane.DisplayMember = "PlaneName";
comboBoxPlane.ValueMember = "Id";
comboBoxPlane.DataSource = list;
comboBoxPlane.SelectedItem = null;
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка загрузки списка изделий");
MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
/// <summary>
/// Кнопка "Сохранить"
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void buttonSave_Click(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(textBoxCount.Text))
{
MessageBox.Show("Заполните поле Количество", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
if (comboBoxPlane.SelectedValue == null)
{
MessageBox.Show("Выберите изделие", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
_logger.LogInformation("Продажа изделий");
_logger.LogInformation("Создание заказа");
try
{
var operationResult = _logicS.SellPlanes(
_logicP.ReadElement(new() { Id = Convert.ToInt32(comboBoxPlane.SelectedValue) }),
Convert.ToInt32(textBoxCount.Text)
);
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);
}
}
/// <summary>
/// Кнопка "Отмена"
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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

@ -0,0 +1,212 @@
namespace AircraftPlantView
{
partial class FormShop
{
/// <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()
{
labelName = new Label();
textBoxName = new TextBox();
labelAddress = new Label();
textBoxAddress = new TextBox();
dateTimePicker = new DateTimePicker();
labelDateOpening = new Label();
dataGridView = new DataGridView();
ColumnID = new DataGridViewTextBoxColumn();
ColumnPlaneName = new DataGridViewTextBoxColumn();
ColumnCount = new DataGridViewTextBoxColumn();
buttonCancel = new Button();
buttonSave = new Button();
labelMaxPlanes = new Label();
numericUpDownMaxPlanes = new NumericUpDown();
((System.ComponentModel.ISupportInitialize)dataGridView).BeginInit();
((System.ComponentModel.ISupportInitialize)numericUpDownMaxPlanes).BeginInit();
SuspendLayout();
//
// labelName
//
labelName.AutoSize = true;
labelName.Location = new Point(12, 15);
labelName.Name = "labelName";
labelName.Size = new Size(62, 15);
labelName.TabIndex = 0;
labelName.Text = "Название:";
//
// textBoxName
//
textBoxName.Location = new Point(110, 12);
textBoxName.Name = "textBoxName";
textBoxName.Size = new Size(200, 23);
textBoxName.TabIndex = 1;
//
// labelAddress
//
labelAddress.AutoSize = true;
labelAddress.Location = new Point(12, 44);
labelAddress.Name = "labelAddress";
labelAddress.Size = new Size(43, 15);
labelAddress.TabIndex = 2;
labelAddress.Text = "Адрес:";
//
// textBoxAddress
//
textBoxAddress.Location = new Point(110, 41);
textBoxAddress.Name = "textBoxAddress";
textBoxAddress.Size = new Size(200, 23);
textBoxAddress.TabIndex = 3;
//
// dateTimePicker
//
dateTimePicker.Location = new Point(110, 70);
dateTimePicker.Name = "dateTimePicker";
dateTimePicker.Size = new Size(200, 23);
dateTimePicker.TabIndex = 4;
//
// labelDateOpening
//
labelDateOpening.AutoSize = true;
labelDateOpening.Location = new Point(12, 76);
labelDateOpening.Name = "labelDateOpening";
labelDateOpening.Size = new Size(90, 15);
labelDateOpening.TabIndex = 5;
labelDateOpening.Text = "Дата открытия:";
//
// dataGridView
//
dataGridView.AllowUserToAddRows = false;
dataGridView.AllowUserToDeleteRows = false;
dataGridView.BackgroundColor = Color.White;
dataGridView.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize;
dataGridView.Columns.AddRange(new DataGridViewColumn[] { ColumnID, ColumnPlaneName, ColumnCount });
dataGridView.GridColor = Color.White;
dataGridView.Location = new Point(12, 128);
dataGridView.MultiSelect = false;
dataGridView.Name = "dataGridView";
dataGridView.ReadOnly = true;
dataGridView.RowTemplate.Height = 25;
dataGridView.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
dataGridView.Size = new Size(560, 292);
dataGridView.TabIndex = 6;
//
// ColumnID
//
ColumnID.HeaderText = "ID";
ColumnID.Name = "ColumnID";
ColumnID.ReadOnly = true;
ColumnID.Visible = false;
//
// ColumnPlaneName
//
ColumnPlaneName.AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
ColumnPlaneName.HeaderText = "Изделие";
ColumnPlaneName.Name = "ColumnPlaneName";
ColumnPlaneName.ReadOnly = true;
//
// ColumnCount
//
ColumnCount.HeaderText = "Количнство";
ColumnCount.Name = "ColumnCount";
ColumnCount.ReadOnly = true;
//
// buttonCancel
//
buttonCancel.Location = new Point(497, 426);
buttonCancel.Name = "buttonCancel";
buttonCancel.Size = new Size(75, 23);
buttonCancel.TabIndex = 7;
buttonCancel.Text = "Отмена";
buttonCancel.UseVisualStyleBackColor = true;
buttonCancel.Click += buttonCancel_Click;
//
// buttonSave
//
buttonSave.Location = new Point(416, 426);
buttonSave.Name = "buttonSave";
buttonSave.Size = new Size(75, 23);
buttonSave.TabIndex = 8;
buttonSave.Text = "Сохранить";
buttonSave.UseVisualStyleBackColor = true;
buttonSave.Click += buttonSave_Click;
//
// labelMaxPlanes
//
labelMaxPlanes.AutoSize = true;
labelMaxPlanes.Location = new Point(12, 101);
labelMaxPlanes.Name = "labelMaxPlanes";
labelMaxPlanes.Size = new Size(83, 15);
labelMaxPlanes.TabIndex = 9;
labelMaxPlanes.Text = "Вместимость:";
//
// numericUpDownMaxPlanes
//
numericUpDownMaxPlanes.Location = new Point(110, 99);
numericUpDownMaxPlanes.Name = "numericUpDownMaxPlanes";
numericUpDownMaxPlanes.Size = new Size(200, 23);
numericUpDownMaxPlanes.TabIndex = 10;
//
// FormShop
//
AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(584, 461);
Controls.Add(numericUpDownMaxPlanes);
Controls.Add(labelMaxPlanes);
Controls.Add(buttonSave);
Controls.Add(buttonCancel);
Controls.Add(dataGridView);
Controls.Add(labelDateOpening);
Controls.Add(dateTimePicker);
Controls.Add(textBoxAddress);
Controls.Add(labelAddress);
Controls.Add(textBoxName);
Controls.Add(labelName);
Name = "FormShop";
Text = "Магазин";
Load += FormShop_Load;
((System.ComponentModel.ISupportInitialize)dataGridView).EndInit();
((System.ComponentModel.ISupportInitialize)numericUpDownMaxPlanes).EndInit();
ResumeLayout(false);
PerformLayout();
}
#endregion
private Label labelName;
private TextBox textBoxName;
private Label labelAddress;
private TextBox textBoxAddress;
private DateTimePicker dateTimePicker;
private Label labelDateOpening;
private DataGridView dataGridView;
private Button buttonCancel;
private Button buttonSave;
private DataGridViewTextBoxColumn ColumnID;
private DataGridViewTextBoxColumn ColumnPlaneName;
private DataGridViewTextBoxColumn ColumnCount;
private Label labelMaxPlanes;
private NumericUpDown numericUpDownMaxPlanes;
}
}

View File

@ -0,0 +1,173 @@
using AircraftPlantContracts.BindingModels;
using AircraftPlantContracts.BusinessLogicsContracts;
using AircraftPlantContracts.SearchModels;
using AircraftPlantDataModels.Models;
using Microsoft.Extensions.Logging;
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 AircraftPlantView
{
/// <summary>
/// Форма для магазина
/// </summary>
public partial class FormShop : Form
{
/// <summary>
/// Логгер
/// </summary>
private readonly ILogger _logger;
/// <summary>
/// Бизнес-логика для магазинов
/// </summary>
private readonly IShopLogic _logic;
/// <summary>
/// Идентификатор
/// </summary>
private int? _id;
public int Id { set { _id = value; } }
/// <summary>
/// Список изделий в магазине
/// </summary>
private Dictionary<int, (IPlaneModel, int)> _shopPlanes;
/// <summary>
/// Конструктор
/// </summary>
/// <param name="logger"></param>
/// <param name="logic"></param>
public FormShop(ILogger<FormShop> logger, IShopLogic logic)
{
InitializeComponent();
_logger = logger;
_logic = logic;
_shopPlanes = new Dictionary<int, (IPlaneModel, int)>();
}
/// <summary>
/// Загрузка списка изделий в магазине
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void FormShop_Load(object sender, EventArgs e)
{
if (_id.HasValue)
{
_logger.LogInformation("Загрузка магазина");
try
{
var view = _logic.ReadElement(new ShopSearchModel { Id = _id.Value });
if (view != null)
{
textBoxName.Text = view.ShopName;
textBoxAddress.Text = view.Address;
dateTimePicker.Text = view.DateOpening.ToString();
numericUpDownMaxPlanes.Value = view.MaxPlanes;
_shopPlanes = view.ShopPlanes ?? new Dictionary<int, (IPlaneModel, int)>();
LoadData();
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка загрузки магазина");
MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
/// <summary>
/// Кнопка "Сохранить"
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void buttonSave_Click(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(textBoxName.Text))
{
MessageBox.Show("Заполните название", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
if (string.IsNullOrEmpty(textBoxAddress.Text))
{
MessageBox.Show("Заполните адрес", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
_logger.LogInformation("Сохранение магазина");
try
{
var model = new ShopBindingModel
{
Id = _id ?? 0,
ShopName = textBoxName.Text,
Address = textBoxAddress.Text,
DateOpening = dateTimePicker.Value.Date,
ShopPlanes = _shopPlanes,
MaxPlanes = Convert.ToInt32(numericUpDownMaxPlanes.Value)
};
var operationResult = _id.HasValue ? _logic.Update(model) : _logic.Create(model);
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);
}
}
/// <summary>
/// Кнопка "Отмена"
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void buttonCancel_Click(object sender, EventArgs e)
{
DialogResult = DialogResult.Cancel;
Close();
}
/// <summary>
/// Метод загрузки изделий магазина
/// </summary>
private void LoadData()
{
_logger.LogInformation("Загрузка изделий магазина");
try
{
if (_shopPlanes != null)
{
dataGridView.Rows.Clear();
foreach (var elem in _shopPlanes)
{
dataGridView.Rows.Add(new object[]
{
elem.Key,
elem.Value.Item1.PlaneName,
elem.Value.Item2
});
}
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка загрузки изделий магазина");
MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
}

View File

@ -0,0 +1,138 @@
<?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>
<metadata name="ColumnID.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="ColumnPlaneName.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="ColumnCount.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="ColumnID.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="ColumnPlaneName.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="ColumnCount.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
</root>

View File

@ -0,0 +1,122 @@
namespace AircraftPlantView
{
partial class FormShops
{
/// <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()
{
dataGridView = new DataGridView();
buttonAdd = new Button();
buttonUpdate = new Button();
buttonDelete = new Button();
buttonRefresh = new Button();
((System.ComponentModel.ISupportInitialize)dataGridView).BeginInit();
SuspendLayout();
//
// dataGridView
//
dataGridView.AllowUserToAddRows = false;
dataGridView.AllowUserToDeleteRows = false;
dataGridView.BackgroundColor = Color.White;
dataGridView.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize;
dataGridView.Dock = DockStyle.Left;
dataGridView.GridColor = Color.White;
dataGridView.Location = new Point(0, 0);
dataGridView.MultiSelect = false;
dataGridView.Name = "dataGridView";
dataGridView.ReadOnly = true;
dataGridView.RowHeadersVisible = false;
dataGridView.RowTemplate.Height = 25;
dataGridView.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
dataGridView.Size = new Size(450, 361);
dataGridView.TabIndex = 0;
//
// buttonAdd
//
buttonAdd.Location = new Point(480, 15);
buttonAdd.Name = "buttonAdd";
buttonAdd.Size = new Size(75, 23);
buttonAdd.TabIndex = 1;
buttonAdd.Text = "Добавить";
buttonAdd.UseVisualStyleBackColor = true;
buttonAdd.Click += buttonAdd_Click;
//
// buttonUpdate
//
buttonUpdate.Location = new Point(480, 44);
buttonUpdate.Name = "buttonUpdate";
buttonUpdate.Size = new Size(75, 23);
buttonUpdate.TabIndex = 2;
buttonUpdate.Text = "Изменить";
buttonUpdate.UseVisualStyleBackColor = true;
buttonUpdate.Click += buttonUpdate_Click;
//
// buttonDelete
//
buttonDelete.Location = new Point(480, 73);
buttonDelete.Name = "buttonDelete";
buttonDelete.Size = new Size(75, 23);
buttonDelete.TabIndex = 3;
buttonDelete.Text = "Удалить";
buttonDelete.UseVisualStyleBackColor = true;
buttonDelete.Click += buttonDelete_Click;
//
// buttonRefresh
//
buttonRefresh.Location = new Point(480, 102);
buttonRefresh.Name = "buttonRefresh";
buttonRefresh.Size = new Size(75, 23);
buttonRefresh.TabIndex = 4;
buttonRefresh.Text = "Обновить";
buttonRefresh.UseVisualStyleBackColor = true;
buttonRefresh.Click += buttonRefresh_Click;
//
// FormShops
//
AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(584, 361);
Controls.Add(buttonRefresh);
Controls.Add(buttonDelete);
Controls.Add(buttonUpdate);
Controls.Add(buttonAdd);
Controls.Add(dataGridView);
Name = "FormShops";
Text = "Магазины";
Load += FormShops_Load;
((System.ComponentModel.ISupportInitialize)dataGridView).EndInit();
ResumeLayout(false);
}
#endregion
private DataGridView dataGridView;
private Button buttonAdd;
private Button buttonUpdate;
private Button buttonDelete;
private Button buttonRefresh;
}
}

View File

@ -0,0 +1,153 @@
using AircraftPlantContracts.BindingModels;
using AircraftPlantContracts.BusinessLogicsContracts;
using Microsoft.Extensions.Logging;
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 AircraftPlantView
{
/// <summary>
/// Форма для вывода всех магазинов
/// </summary>
public partial class FormShops : Form
{
/// <summary>
/// Логгер
/// </summary>
private readonly ILogger _logger;
/// <summary>
/// Бизнес-логика для магазина
/// </summary>
private readonly IShopLogic _logic;
/// <summary>
/// Конструктор
/// </summary>
public FormShops(ILogger<FormShops> logger, IShopLogic logic)
{
InitializeComponent();
_logger = logger;
_logic = logic;
}
/// <summary>
/// Загрузка списка магазинов
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void FormShops_Load(object sender, EventArgs e)
{
LoadData();
}
/// <summary>
/// Кнопка "Добавить"
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void buttonAdd_Click(object sender, EventArgs e)
{
var service = Program.ServiceProvider?.GetService(typeof(FormShop));
if (service is FormShop form)
{
if (form.ShowDialog() == DialogResult.OK)
{
LoadData();
}
}
}
/// <summary>
/// Кнопка "Изменить"
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void buttonUpdate_Click(object sender, EventArgs e)
{
if (dataGridView.SelectedRows.Count == 1)
{
var service = Program.ServiceProvider?.GetService(typeof(FormShop));
if (service is FormShop form)
{
form.Id = Convert.ToInt32(dataGridView.SelectedRows[0].Cells["Id"].Value);
if (form.ShowDialog() == DialogResult.OK)
{
LoadData();
}
}
}
}
/// <summary>
/// Кнопка "Удалить"
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void buttonDelete_Click(object sender, EventArgs e)
{
if (dataGridView.SelectedRows.Count == 1)
{
if (MessageBox.Show("Удалить запись?", "Вопрос", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
{
int id = Convert.ToInt32(dataGridView.SelectedRows[0].Cells["Id"].Value);
_logger.LogInformation("Удаление магазина");
try
{
if (!_logic.Delete(new ShopBindingModel { Id = id }))
{
throw new Exception("Ошибка при удалении. Дополнительная информация в логах.");
}
LoadData();
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка удаления магазина");
MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
}
/// <summary>
/// Кнопка "Обновить"
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void buttonRefresh_Click(object sender, EventArgs e)
{
LoadData();
}
/// <summary>
/// Метод загрузки списка магазинов
/// </summary>
private void LoadData()
{
try
{
var list = _logic.ReadList(null);
if (list != null)
{
dataGridView.DataSource = list;
dataGridView.Columns["Id"].Visible = false;
dataGridView.Columns["ShopName"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
dataGridView.Columns["ShopPlanes"].Visible = false;
}
_logger.LogInformation("Загрузка магазинов");
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка загрузки магазинов");
MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
}

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

@ -49,10 +49,12 @@ namespace AircraftPlantView
services.AddTransient<IComponentStorage, ComponentStorage>();
services.AddTransient<IOrderStorage, OrderStorage>();
services.AddTransient<IPlaneStorage, PlaneStorage>();
services.AddTransient<IShopStorage, ShopStorage>();
services.AddTransient<IComponentLogic, ComponentLogic>();
services.AddTransient<IOrderLogic, OrderLogic>();
services.AddTransient<IPlaneLogic, PlaneLogic>();
services.AddTransient<IShopLogic, ShopLogic>();
services.AddTransient<FormMain>();
services.AddTransient<FormComponent>();
@ -61,6 +63,10 @@ namespace AircraftPlantView
services.AddTransient<FormPlane>();
services.AddTransient<FormPlaneComponent>();
services.AddTransient<FormPlanes>();
services.AddTransient<FormShop>();
services.AddTransient<FormShops>();
services.AddTransient<FormCreateSupply>();
services.AddTransient<FormSell>();
}
}
}