crud для плана питания+привязка участников к планам питания

This commit is contained in:
AnnZhimol 2023-05-16 19:43:06 +04:00
parent 482dd619e6
commit 031c9815d7
15 changed files with 572 additions and 21 deletions

View File

@ -3,6 +3,7 @@ using HotelContracts.BusinessLogicsContracts;
using HotelContracts.SearchModels;
using HotelContracts.StoragesContracts;
using HotelContracts.ViewModels;
using HotelDataModels.Models;
using Microsoft.Extensions.Logging;
namespace HotelBusinessLogic.BusinessLogics
@ -17,9 +18,43 @@ namespace HotelBusinessLogic.BusinessLogics
_logger = logger;
_mealPlanStorage = mealPlanStorage;
}
public bool AddMemberToMealPlan(MealPlanSearchModel model, IMemberModel member)
{
if (model == null)
{
throw new ArgumentNullException(nameof(model));
}
_logger.LogInformation("AddMemberToMealPlan. MealPlanName:{MealPlanName}.Id:{ Id}", model.MealPlanName, model.Id);
var element = _mealPlanStorage.GetElement(model);
if (element == null)
{
_logger.LogWarning("AddMemberToMealPlan element not found");
return false;
}
_logger.LogInformation("AddMemberToMealPlan find. Id:{Id}", element.Id);
element.MealPlanMembers[member.Id] = member;
_mealPlanStorage.Update(new()
{
Id = element.Id,
MealPlanName = element.MealPlanName,
MealPlanPrice = element.MealPlanPrice,
OrganiserId = element.OrganiserId,
MealPlanMembers = element.MealPlanMembers
});
return true;
}
public bool Create(MealPlanBindingModel model)
{
CheckModel(model);
model.MealPlanMembers = new();
if (_mealPlanStorage.Insert(model) == null)
{

View File

@ -11,6 +11,6 @@ namespace HotelContracts.BindingModels
public int OrganiserId { get; set; }
public int Id { get; set; }
public Dictionary<int, IMemberModel> MealPlanMembers { get; set; }
public Dictionary<int, IMemberModel> MealPlanMembers { get; set; } = new();
}
}

View File

@ -1,6 +1,7 @@
using HotelContracts.BindingModels;
using HotelContracts.SearchModels;
using HotelContracts.ViewModels;
using HotelDataModels.Models;
namespace HotelContracts.BusinessLogicsContracts
{
@ -8,6 +9,7 @@ namespace HotelContracts.BusinessLogicsContracts
{
List<MealPlanViewModel>? ReadList(MealPlanSearchModel? model);
MealPlanViewModel? ReadElement(MealPlanSearchModel model);
bool AddMemberToMealPlan(MealPlanSearchModel model, IMemberModel member);
bool Create(MealPlanBindingModel model);
bool Update(MealPlanBindingModel model);
bool Delete(MealPlanBindingModel model);

View File

@ -1,5 +1,6 @@
using HotelDataModels.Models;
using System.ComponentModel;
using Newtonsoft.Json;
namespace HotelContracts.ViewModels
{
@ -15,7 +16,15 @@ namespace HotelContracts.ViewModels
public int Id { get; set; }
public Dictionary<int, IMemberModel> MealPlanMembers { get; set; }
public Dictionary<int, IMemberModel> MealPlanMembers { get; set; } = new();
public Dictionary<int, IRoomModel> MealPlanRooms { get; set; }
public MealPlanViewModel() { }
[JsonConstructor]
public MealPlanViewModel(Dictionary<int, MemberViewModel> MealPlanMembers)
{
this.MealPlanMembers = MealPlanMembers.ToDictionary(x => x.Key, x => x.Value as IMemberModel);
}
}
}

View File

@ -14,6 +14,7 @@ namespace HotelDataBaseImplement.Implemets
using var context = new HotelDataBase();
var element = context.MealPlans
.Include(x => x.Members)
.FirstOrDefault(rec => rec.Id == model.Id);
if (element != null)
@ -29,7 +30,7 @@ namespace HotelDataBaseImplement.Implemets
public MealPlanViewModel? GetElement(MealPlanSearchModel model)
{
if (!model.Id.HasValue)
if (string.IsNullOrEmpty(model.MealPlanName) && !model.Id.HasValue)
{
return null;
}
@ -43,7 +44,7 @@ namespace HotelDataBaseImplement.Implemets
.ThenInclude(x => x.Conference)
.Include(x => x.Rooms)
.Include(x => x.Organiser)
.FirstOrDefault(x => (model.Id.HasValue && x.Id == model.Id))?
.FirstOrDefault(x => (!string.IsNullOrEmpty(model.MealPlanName) && x.MealPlanName == model.MealPlanName) || (model.Id.HasValue && x.Id == model.Id))?
.GetViewModel;
}
@ -79,6 +80,7 @@ namespace HotelDataBaseImplement.Implemets
.Include(x => x.Rooms)
.Include(x => x.Organiser)
.Where(x => x.MealPlanName.Contains(model.MealPlanName))
.ToList()
.Select(x => x.GetViewModel)
.ToList();
}
@ -115,14 +117,26 @@ namespace HotelDataBaseImplement.Implemets
public MealPlanViewModel? Update(MealPlanBindingModel model)
{
using var context = new HotelDataBase();
var mealPlan = context.MealPlans.FirstOrDefault(x => x.Id == model.Id);
if (mealPlan == null)
using var transaction = context.Database.BeginTransaction();
try
{
var elem = context.MealPlans.FirstOrDefault(rec => rec.Id == model.Id);
if (elem == null)
{
return null;
}
mealPlan.Update(model);
elem.Update(model);
context.SaveChanges();
return mealPlan.GetViewModel;
if (model.MealPlanMembers != null)
elem.UpdateMembers(context, model);
transaction.Commit();
return elem.GetViewModel;
}
catch
{
transaction.Rollback();
throw;
}
}
}
}

View File

@ -3,6 +3,7 @@ using HotelContracts.ViewModels;
using HotelDataModels.Models;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Text.Json.Serialization;
namespace HotelDataBaseImplement.Models
{
@ -20,13 +21,8 @@ namespace HotelDataBaseImplement.Models
public virtual Organiser Organiser { get; set; }
[ForeignKey("MealPlanId")]
public virtual List<Room> Rooms { get; set; }
[ForeignKey("MealPlanId")]
public virtual List<MealPlanMember> Members { get; set; }
private Dictionary<int, IMemberModel> _mealPlanMembers = null;
[NotMapped]
public Dictionary<int, IMemberModel> MealPlanMembers
{
@ -34,11 +30,21 @@ namespace HotelDataBaseImplement.Models
{
if (_mealPlanMembers == null)
{
_mealPlanMembers = Members.ToDictionary(recPC => recPC.MemberId, recPC => (recPC.Member as IMemberModel));
using var context = new HotelDataBase();
_mealPlanMembers = Members
.ToDictionary(x => x.MemberId, x => (context.Members
.FirstOrDefault(y => y.Id == x.MemberId)! as IMemberModel));
}
return _mealPlanMembers;
}
}
[ForeignKey("MealPlanId")]
public virtual List<Room> Rooms { get; set; }
[ForeignKey("MealPlanId")]
public virtual List<MealPlanMember> Members { get; set; } = new();
public static MealPlan Create(HotelDataBase context, MealPlanBindingModel model)
{
return new MealPlan()
@ -74,10 +80,16 @@ namespace HotelDataBaseImplement.Models
{
var mealPlanMembers = context.MealPlanMembers.Where(rec => rec.MealPlanId == model.Id).ToList();
if (mealPlanMembers != null)
if (mealPlanMembers != null && mealPlanMembers.Count > 0)
{
context.MealPlanMembers.RemoveRange(mealPlanMembers.Where(rec => !model.MealPlanMembers.ContainsKey(rec.MemberId)));
context.SaveChanges();
foreach (var updateMember in mealPlanMembers)
{
model.MealPlanMembers.Remove(updateMember.MemberId);
}
context.SaveChanges();
}
var mealPlan = context.MealPlans.First(x => x.Id == Id);

View File

@ -12,7 +12,7 @@ namespace HotelDataBaseImplement.Models
[Required]
public int MealPlanId { get; set; }
public virtual MealPlan MealPlan { get; set; }
public virtual Member Member { get; set; }
public virtual MealPlan MealPlan { get; set; } = new();
public virtual Member Member { get; set; } = new();
}
}

View File

@ -20,7 +20,7 @@ namespace HotelDataBaseImplement.Models
public virtual Organiser Organiser { get; set; }
[ForeignKey("MemberId")]
public virtual List<MealPlanMember> MealPlanMember { get; set; }
public virtual List<MealPlanMember> MealPlanMember { get; set; } = new();
[ForeignKey("MemberId")]

View File

@ -17,6 +17,161 @@ namespace HotelOrganiserApp.Controllers
_logger = logger;
}
/*--------------------MealPlans------------------------*/
public IActionResult CreateMealPlan()
{
if (APIClient.Organiser == null)
{
return Redirect("~/Home/Enter");
}
return View();
}
[HttpPost]
public void CreateMealPlan(string mealPlanName, double mealPlanPrice)
{
if (APIClient.Organiser == null)
{
throw new Exception("Необходима авторизация");
}
if (string.IsNullOrEmpty(mealPlanName) || string.IsNullOrEmpty(mealPlanPrice.ToString()))
{
throw new Exception("Введите название");
}
if (string.IsNullOrEmpty(mealPlanPrice.ToString()))
{
throw new Exception("Введите стоимость");
}
APIClient.PostRequest("api/main/createmealplan", new MealPlanBindingModel
{
MealPlanName = mealPlanName,
MealPlanPrice = mealPlanPrice,
OrganiserId = APIClient.Organiser.Id,
});
Response.Redirect("ListMealPlans");
}
public IActionResult DeleteMealPlan()
{
if (APIClient.Organiser == null)
{
return Redirect("~/Home/Enter");
}
ViewBag.MealPlans = APIClient.GetRequest<List<MealPlanViewModel>>($"api/main/getmealplanlist?organiserId={APIClient.Organiser.Id}");
return View();
}
[HttpPost]
public void DeleteMealPlan(int mealPlan)
{
if (APIClient.Organiser == null)
{
throw new Exception("Необходима авторизация");
}
APIClient.PostRequest("api/main/deletemealplan", new MealPlanBindingModel
{
Id = mealPlan
});
Response.Redirect("ListMealPlans");
}
public IActionResult UpdateMealPlan()
{
if (APIClient.Organiser == null)
{
return Redirect("~/Home/Enter");
}
ViewBag.MealPlans = APIClient.GetRequest<List<MealPlanViewModel>>($"api/main/getmealplanlist?organiserId={APIClient.Organiser.Id}");
return View();
}
[HttpPost]
public void UpdateMealPlan(int mealPlan, string mealPlanName, double mealPlanPrice)
{
if (APIClient.Organiser == null)
{
throw new Exception("Необходима авторизация");
}
if (string.IsNullOrEmpty(mealPlanName))
{
throw new Exception("Название не может быть пустым");
}
if (string.IsNullOrEmpty(mealPlanPrice.ToString()))
{
throw new Exception("стоимсоть не может быть пустым");
}
APIClient.PostRequest("api/main/updatemealplan", new MealPlanBindingModel
{
Id = mealPlan,
MealPlanName = mealPlanName,
MealPlanPrice = mealPlanPrice,
OrganiserId = APIClient.Organiser.Id
});
Response.Redirect("ListMealPlans");
}
[HttpGet]
public Tuple<MealPlanViewModel, string>? GetMealPlan(int mealPlanId)
{
if (APIClient.Organiser == null)
{
throw new Exception("Необходима авторизация");
}
var result = APIClient.GetRequest<Tuple<MealPlanViewModel, List<Tuple<string, string>>>>($"api/main/getmealplan?mealPlanId={mealPlanId}");
if (result == null)
{
return default;
}
string table = "";
for (int i = 0; i < result.Item2.Count; i++)
{
var memberFIO = result.Item2[i].Item1;
var citizenship = result.Item2[i].Item2;
table += "<tr style=\"height: 44px\">";
table += $"<td class=\"u-border-1 u-border-grey-30 u-table-cell\">{memberFIO}</td>";
table += $"<td class=\"u-border-1 u-border-grey-30 u-table-cell\">{citizenship}</td>";
table += "</tr>";
}
return Tuple.Create(result.Item1, table);
}
public IActionResult AddMemberToMealPlan()
{
if (APIClient.Organiser == null)
{
return Redirect("~/Home/Enter");
}
ViewBag.MealPlans = APIClient.GetRequest<List<MealPlanViewModel>>($"api/main/getmealplanlist?organiserId={APIClient.Organiser.Id}");
ViewBag.Members = APIClient.GetRequest<List<MemberViewModel>>($"api/main/getmemberlist?organiserId={APIClient.Organiser.Id}");
return View();
}
[HttpPost]
public void AddMemberToMealPlan(int mealPlan, int member)
{
if (APIClient.Organiser == null)
{
throw new Exception("Необходима авторизация");
}
APIClient.PostRequest("api/main/AddMemberToMealPlan", Tuple.Create(
new MealPlanSearchModel() { Id = mealPlan },
new MemberViewModel() { Id = member }
));
Response.Redirect("ListMealPlans");
}
public IActionResult ListMealPlans()
{
if (APIClient.Organiser == null)
{
return Redirect("~/Home/Enter");
}
return View(APIClient.GetRequest<List<MealPlanViewModel>>($"api/main/getmealplanlist?organiserId={APIClient.Organiser.Id}"));
}
/*--------------------Members------------------------*/
public IActionResult CreateMember()
{
if (APIClient.Organiser == null)
@ -147,6 +302,8 @@ namespace HotelOrganiserApp.Controllers
return View(APIClient.GetRequest<List<MemberViewModel>>($"api/main/getmemberlist?organiserId={APIClient.Organiser.Id}"));
}
/*--------------------Conferences------------------------*/
public IActionResult CreateConference()
{
if (APIClient.Organiser == null)
@ -298,6 +455,8 @@ namespace HotelOrganiserApp.Controllers
return View(APIClient.GetRequest<List<ConferenceViewModel>>($"api/main/getconferencelist?organiserId={APIClient.Organiser.Id}"));
}
/*--------------------Organisers------------------------*/
[HttpGet]
public IActionResult Privacy()
{

View File

@ -0,0 +1,27 @@
@using HotelContracts.ViewModels;
@using HotelDataModels.Models;
@{
ViewData["Title"] = "AddMemberToMealPlan";
}
@model Dictionary<int, IMemberModel>
<form method="post">
<div class="u-form-group u-form-name u-label-top">
<label class="u-label u-text-custom-color-1 u-label-1">План питания: </label>
<div class="u-input u-input-rectangle">
<select id="mealPlan" name="mealPlan" class="form-control" asp-items="@(new SelectList(@ViewBag.MealPlans, "Id", "MealPlanName"))"></select>
</div>
</div>
<div class="u-form-group u-form-name u-label-top">
<label class="u-label u-text-custom-color-1 u-label-1">Участник: </label>
<div class="u-input u-input-rectangle">
<select id="member" name="member" class="form-control" asp-items="@(new SelectList(@ViewBag.Members, "Id", "MemberFIO"))"></select>
</div>
</div>
<div class="u-align-right u-form-group u-form-submit u-label-top">
<div class="col-8"></div>
<div class="col-4"><input type="submit" value="Добавить участника" class="u-active-custom-color-6 u-border-none u-btn u-btn-submit u-button-style u-custom-color-1 u-hover-custom-color-2 u-btn-1" /></div>
</div>
</form>

View File

@ -0,0 +1,31 @@
@{
ViewData["Title"] = "CreateMealPlan";
}
<head>
<link rel="stylesheet" href="~/css/createmember.css" asp-append-version="true" />
</head>
<form method="post">
<div class="u-form-group u-form-name u-label-top">
<label class="u-label u-text-custom-color-1 u-label-1">Название плана питания</label>
<input
type="text"
placeholder="Введите название плана питания"
name="mealPlanName"
class="u-input u-input-rectangle"/>
</div>
<div class="u-form-email u-form-group u-label-top">
<label class="u-label u-text-custom-color-1 u-label-2">Стоимость</label>
<input
type="number"
placeholder="Введите стоимость"
step="1"
name="mealPlanPrice"
class="u-input u-input-rectangle"/>
</div>
<div class="u-align-right u-form-group u-form-submit u-label-top">
<div class="col-8"></div>
<div class="col-4"><input type="submit" value="Сохранить" class="u-active-custom-color-6 u-border-none u-btn u-btn-submit u-button-style u-custom-color-1 u-hover-custom-color-2 u-btn-1" /></div>
</div>
</form>

View File

@ -0,0 +1,18 @@
@{
ViewData["Title"] = "DeleteMealPlan";
}
<head>
<link rel="stylesheet" href="~/css/createmember.css" asp-append-version="true" />
</head>
<form method="post">
<div class="u-form-group u-form-name u-label-top">
<label class="u-label u-text-custom-color-1 u-label-1">План питания: </label>
<div class="u-input u-input-rectangle">
<select id="mealPlan" name="mealPlan" class="form-control" asp-items="@(new SelectList(@ViewBag.MealPlans, "Id", "MealPlanName"))"></select>
</div>
</div>
<div class="u-align-right u-form-group u-form-submit u-label-top">
<div class="col-8"></div>
<div class="col-4"><input type="submit" value="Удалить" class="u-active-custom-color-6 u-border-none u-btn u-btn-submit u-button-style u-custom-color-1 u-hover-custom-color-2 u-btn-1" /></div>
</div>
</form>

View File

@ -0,0 +1,95 @@
@using HotelContracts.ViewModels
@model List<MealPlanViewModel>
@{
ViewData["Title"] = "ListMealPlans";
}
<head>
<link rel="stylesheet" href="~/css/listconferences.css" asp-append-version="true" />
</head>
<section class="u-clearfix u-section-1" id="sec-096c">
<div class="u-clearfix u-sheet u-valign-middle u-sheet-1">
<div class="u-clearfix u-layout-wrap u-layout-wrap-1">
<div class="u-layout">
<div class="u-layout-row">
<div
class="u-container-style u-layout-cell u-size-48 u-layout-cell-1"
>
<div class="u-container-layout u-container-layout-1">
<div class="u-table u-table-responsive u-table-1">
<table class="u-table-entity">
<colgroup>
<col width="9.8%" />
<col width="62.9%" />
<col width="27.3%" />
</colgroup>
<thead class="u-custom-color-1 u-table-header u-table-header-1">
<tr style="height: 31px">
<th class="u-border-1 u-border-grey-50 u-table-cell">
Номер
</th>
<th class="u-border-1 u-border-grey-50 u-table-cell">
Название плана питания
</th>
<th class="u-border-1 u-border-grey-50 u-table-cell">
Стоимость
</th>
</tr>
</thead>
<tbody class="u-table-body">
@foreach (var item in Model)
{
<tr style="height: 75px">
<td
class="u-border-1 u-border-grey-40 u-border-no-left u-border-no-right u-table-cell">
@Html.DisplayFor(modelItem => item.Id)
</td>
<td
class="u-border-1 u-border-grey-40 u-border-no-left u-border-no-right u-table-cell"
>
@Html.DisplayFor(modelItem => item.MealPlanName)
</td>
<td
class="u-border-1 u-border-grey-40 u-border-no-left u-border-no-right u-table-cell"
>
@Html.DisplayFor(modelItem => item.MealPlanPrice)
</td>
</tr>
}
</tbody>
</table>
</div>
</div>
</div>
<div
class="u-container-style u-layout-cell u-size-12 u-layout-cell-2"
>
<div class="u-container-layout u-container-layout-2">
<a
asp-area="" asp-controller="Home" asp-action="CreateMealPlan"
class="u-active-custom-color-6 u-border-none u-btn u-button-style u-custom-color-1 u-hover-custom-color-2 u-btn-1"
>Добавить</a>
<a
asp-area="" asp-controller="Home" asp-action="UpdateMealPlan"
class="u-active-custom-color-6 u-border-none u-btn u-button-style u-custom-color-1 u-hover-custom-color-2 u-btn-1"
>иЗМЕНИТЬ</a>
<a
asp-area="" asp-controller="Home" asp-action="DeleteMealPlan"
class="u-active-custom-color-6 u-border-none u-btn u-button-style u-custom-color-1 u-hover-custom-color-2 u-btn-1"
>Удалить</a>
<a
asp-area="" asp-controller="Home" asp-action="AddMemberToMealPlan"
style="padding: 10 px"
class="u-active-custom-color-6 u-border-none u-btn u-button-style u-custom-color-1 u-hover-custom-color-2 u-btn-1"
>Добавить участника</a>
</div>
</div>
</div>
</div>
</div>
</div>
</section>

View File

@ -0,0 +1,89 @@
@using HotelContracts.ViewModels;
@using HotelDataModels.Models;
@{
ViewData["Title"] = "UpdateMealPlan";
}
<head>
<link rel="stylesheet" href="~/css/createmember.css" asp-append-version="true" />
<link rel="stylesheet" href="~/css/updateconference.css" asp-append-version="true" />
</head>
<form method="post">
<div class="u-form-group u-form-name u-label-top">
<label class="u-label u-text-custom-color-1 u-label-1">План питания: </label>
<div class="u-input u-input-rectangle">
<select id="mealPlan" name="mealPlan" class="form-control" asp-items="@(new SelectList(@ViewBag.MealPlans, "Id", "MealPlanName"))"></select>
</div>
</div>
<div class="u-form-group u-form-name u-label-top">
<label class="u-label u-text-custom-color-1 u-label-1">Название плана питания</label>
<input
type="text"
id="mealPlanName"
placeholder="Введите название плана питания"
name="mealPlanName"
class="u-input u-input-rectangle"/>
</div>
<div class="u-form-email u-form-group u-label-top">
<label class="u-label u-text-custom-color-1 u-label-2">Стоимость</label>
<input
type="number"
id="mealPlanPrice"
placeholder="Введите стоимость плана питания"
name="mealPlanPrice"
class="u-input u-input-rectangle"/>
</div>
<div class="u-table u-table-responsive u-table-1">
<label class="u-label u-text-custom-color-1 u-label-1">Участники плана питания</label>
<table class="u-table-entity">
<colgroup>
<col width="63%" />
<col width="37%" />
</colgroup>
<thead class="u-custom-color-1 u-table-header u-table-header-1">
<tr style="height: 44px">
<th class="u-border-1 u-border-black u-table-cell">
Участники
</th>
<th class="u-border-1 u-border-black u-table-cell">
Гражданство
</th>
</tr>
</thead>
<tbody class="u-table-body" id="table-elements">
</tbody>
</table>
</div>
<div class="u-align-right u-form-group u-form-submit u-label-top">
<div class="col-8"></div>
<div class="col-4"><input type="submit" value="Сохранить" class="u-active-custom-color-6 u-border-none u-btn u-btn-submit u-button-style u-custom-color-1 u-hover-custom-color-2 u-btn-1" /></div>
</div>
</form>
@section Scripts
{
<script>
function check() {
var mealPlan = $('#mealPlan').val();
if (mealPlan) {
$.ajax({
method: "GET",
url: "/Home/GetMealPlan",
data: { mealPlanId: mealPlan },
success: function (result) {
$('#mealPlanName').val(result.item1.mealPlanName);
$('#mealPlanPrice').val(result.item1.mealPlanPrice);
$('#table-elements').html(result.item2);
}
});
};
}
check();
$('#mealPlan').on('change', function () {
check();
});
</script>
}

View File

@ -340,6 +340,66 @@ namespace HotelRestApi.Controllers
}
}
[HttpPost]
public void UpdateMealPlan(MealPlanBindingModel model)
{
try
{
model.MealPlanMembers = null!;
_mealPlan.Update(model);
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка обновления данных");
throw;
}
}
[HttpGet]
public Tuple<MealPlanViewModel, List<Tuple<string, string>>>? GetMealPlan(int mealPlanId)
{
try
{
var elem = _mealPlan.ReadElement(new MealPlanSearchModel { Id = mealPlanId });
if (elem == null)
return null;
return Tuple.Create(elem, elem.MealPlanMembers.Select(x => Tuple.Create(x.Value.MemberFIO, x.Value.Citizenship)).ToList());
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка получения плана питания по id={Id}", mealPlanId);
throw;
}
}
[HttpPost]
public void DeleteMealPlan(MealPlanBindingModel model)
{
try
{
_mealPlan.Delete(model);
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка удаления плана питания");
throw;
}
}
[HttpPost]
public void AddMemberToMealPlan(Tuple<MealPlanSearchModel, MemberViewModel> model)
{
try
{
_mealPlan.AddMemberToMealPlan(model.Item1, model.Item2);
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка добавления участника в план питания.");
throw;
}
}
[HttpPost]
public void CreateRoom(RoomBindingModel model)
{