24 Commits

Author SHA1 Message Date
maxim
7b758aed6b uu 2025-09-15 11:50:49 +04:00
maxim
5437a6569f ready 2025-09-14 10:03:39 +04:00
nezui1
b516ae3a84 е исправил 2025-09-12 18:24:10 +04:00
nezui1
c06db4d6c4 тесты для французов упали 2025-09-12 12:51:48 +04:00
nezui1
eb83251808 осталось чут чут исправить после починик 6 лабы 2025-09-12 12:25:09 +04:00
nezui1
b0e55e3e60 готово 2025-09-11 20:25:56 +04:00
nezui1
d43d666c4b string 2025-09-11 18:20:33 +04:00
nezui1
7153932f82 Dates 2025-09-11 14:59:23 +04:00
nezui1
053b3234f6 Numbers 2025-09-11 14:46:45 +04:00
nezui1
551fb7d000 готово 2025-09-10 14:18:04 +04:00
nezui1
77837c6c90 тесты работают 2025-09-10 14:09:38 +04:00
nezui1
0db164d1a9 тесты 2025-09-10 12:24:10 +04:00
nezui1
d88a07037a хранилища верные 2025-09-08 22:27:18 +04:00
nezui1
378aa945dc OfficePackage 2025-09-08 22:17:50 +04:00
nezui1
b6177d2b4d ReportController, ReportAdapter вроде готовы 2025-09-08 22:07:29 +04:00
nezui1
2c33509cb1 подготовка 2025-09-08 20:50:09 +04:00
nezui1
67c5a3b13d начало 2025-09-07 23:40:47 +04:00
nezui1
4c0050e498 лаба готова 2025-09-07 23:27:21 +04:00
nezui1
4f92cf60d6 Должность 2025-09-07 17:55:01 +04:00
nezui1
6da51e4ac6 исправить Salary, доделать тесты. осталось 27 минут видоса 2025-09-03 00:05:52 +04:00
nezui1
31edceff7d тесты для поста работают 2025-09-02 23:57:57 +04:00
nezui1
f9f9219bc5 PostStorageContract переход 2025-09-02 23:24:46 +04:00
nezui1
494f92118a PostDataModelTest исправлены 2025-09-02 22:48:42 +04:00
nezui1
1848377cfd Первая миграция 2025-09-02 22:39:49 +04:00
128 changed files with 8639 additions and 845 deletions

View File

@@ -0,0 +1,422 @@
using TwoOfCasketDatabase;
using TwoOfCasketTests.Infrastructure;
using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Serilog;
using System.Text;
using System.Text.Json;
using Newtonsoft.Json.Linq;
using System.Net;
using TwoOfCasketContracts.BindingModels;
using TwoOfCasketContracts.Enums;
using TwoOfCasketDatabase.Models;
using TwoOfCasketContracts.Infrastructure.PostConfigurations;
namespace TwoOfCasketTests.LocalizationTests;
internal abstract class BaseLocalizationControllerTest
{
protected abstract string GetLocale();
private WebApplicationFactory<Program> _webApplication;
protected HttpClient HttpClient { get; private set; }
protected static TwoOfCasketDbContext TwoOfCasketDbContext { get; private set; }
protected static readonly JsonSerializerOptions JsonSerializerOptions = new() { PropertyNameCaseInsensitive = true };
private static string _roomId;
private static string _workerId;
private static string _jobId;
private static string _postId;
[OneTimeSetUp]
public void OneTimeSetUp()
{
_webApplication = new CustomWebApplicationFactory<Program>();
HttpClient = _webApplication
.WithWebHostBuilder(builder =>
{
builder.ConfigureTestServices(services =>
{
using var loggerFactory = new LoggerFactory();
loggerFactory.AddSerilog(new LoggerConfiguration()
.ReadFrom.Configuration(new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json")
.Build())
.CreateLogger());
services.AddSingleton(loggerFactory);
});
})
.CreateClient();
var request = HttpClient.GetAsync("/login/user").GetAwaiter().GetResult();
var data = request.Content.ReadAsStringAsync().GetAwaiter().GetResult();
HttpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {data}");
HttpClient.DefaultRequestHeaders.Add("Accept-Language", GetLocale());
TwoOfCasketDbContext = _webApplication.Services.GetRequiredService<TwoOfCasketDbContext>();
TwoOfCasketDbContext.Database.EnsureDeleted();
TwoOfCasketDbContext.Database.EnsureCreated();
}
[SetUp]
public void SetUp()
{
_roomId = TwoOfCasketDbContext.InsertRoomToDatabaseAndReturn(name: "Room", emailClient: "bbbbbbb@mail.com").Id;
_workerId = TwoOfCasketDbContext.InsertWorkerToDatabaseAndReturn(fio: "Worker").Id;
_jobId = TwoOfCasketDbContext.InsertJobToDatabaseAndReturn(jobName: "Job").Id;
_postId = TwoOfCasketDbContext.InsertPostToDatabaseAndReturn(postName: "Post").PostId;
}
[TearDown]
public void TearDown()
{
TwoOfCasketDbContext.RemoveSalariesFromDatabase();
TwoOfCasketDbContext.RemoveWorksFromDatabase();
TwoOfCasketDbContext.RemoveWorkersFromDatabase();
TwoOfCasketDbContext.RemovePostsFromDatabase();
TwoOfCasketDbContext.RemoveRoomsFromDatabase();
TwoOfCasketDbContext.RemoveJobsFromDatabase();
}
[OneTimeTearDown]
public void OneTimeTearDown()
{
TwoOfCasketDbContext?.Database.EnsureDeleted();
TwoOfCasketDbContext?.Dispose();
HttpClient?.Dispose();
_webApplication?.Dispose();
}
[Test]
public async Task LoadJobs_WhenHaveRecords_ShouldSuccess_Test()
{
// Arrange
var job1 = TwoOfCasketDbContext.InsertJobToDatabaseAndReturn(jobName: "Job1");
var job2 = TwoOfCasketDbContext.InsertJobToDatabaseAndReturn(jobName: "Job2");
TwoOfCasketDbContext.InsertJobHistoryToDatabaseAndReturn(job1.Id, 100.0);
TwoOfCasketDbContext.InsertJobHistoryToDatabaseAndReturn(job1.Id, 150.0);
TwoOfCasketDbContext.InsertJobHistoryToDatabaseAndReturn(job1.Id, 200.0, changeDate: DateTime.UtcNow.AddDays(-1));
TwoOfCasketDbContext.InsertJobHistoryToDatabaseAndReturn(job2.Id, 100.0);
TwoOfCasketDbContext.InsertJobHistoryToDatabaseAndReturn(job2.Id, 90.0);
//Act
var response = await HttpClient.GetAsync($"/api/report/loadjobs?fromDate={DateTime.Now.AddDays(-1):MM/dd/yyyy HH:mm:ss}&toDate={DateTime.Now.AddDays(1):MM/dd/yyyy HH:mm:ss}");
//Assert
await AssertStreamAsync(response, $"file-{GetLocale()}.docx");
}
[Test]
public async Task LoadWorks_WhenHaveRecords_ShouldSuccess_Test()
{
//Arrange
var worker = TwoOfCasketDbContext.InsertWorkerToDatabaseAndReturn();
var job1 = TwoOfCasketDbContext.InsertJobToDatabaseAndReturn(jobName: "name 1");
var job2 = TwoOfCasketDbContext.InsertJobToDatabaseAndReturn(jobName: "name 2");
TwoOfCasketDbContext.InsertWorkToDatabaseAndReturn(worker.Id, jobs: [(job1.Id, 10, 1.1), (job2.Id, 10, 1.1)]);
TwoOfCasketDbContext.InsertWorkToDatabaseAndReturn(worker.Id, jobs: [(job1.Id, 10, 1.1)]);
//Act
var response = await HttpClient.GetAsync($"/api/report/loadworks?fromDate={DateTime.Now.AddDays(-1):MM/dd/yyyy HH:mm:ss} &toDate= {DateTime.Now.AddDays(1):MM/dd/yyyy HH:mm:ss}");
//Assert
await AssertStreamAsync(response, $"file-{GetLocale()}.xlsx");
}
[Test]
public async Task LoadSalary_WhenHaveRecords_ShouldSuccess_Test()
{
//Arrange
var post = TwoOfCasketDbContext.InsertPostToDatabaseAndReturn();
var worker1 = TwoOfCasketDbContext.InsertWorkerToDatabaseAndReturn(fio: "fio 1", postId: post.PostId).AddPost(post);
var worker2 = TwoOfCasketDbContext.InsertWorkerToDatabaseAndReturn(fio: "fio 2", postId: post.PostId).AddPost(post);
TwoOfCasketDbContext.InsertSalaryToDatabaseAndReturn(worker1.Id, workerSalary: 100, salaryDate: DateTime.UtcNow.AddDays(-10));
TwoOfCasketDbContext.InsertSalaryToDatabaseAndReturn(worker1.Id, workerSalary: 1000, salaryDate: DateTime.UtcNow.AddDays(-5));
TwoOfCasketDbContext.InsertSalaryToDatabaseAndReturn(worker1.Id, workerSalary: 200, salaryDate: DateTime.UtcNow.AddDays(5));
TwoOfCasketDbContext.InsertSalaryToDatabaseAndReturn(worker2.Id, workerSalary: 500, salaryDate: DateTime.UtcNow.AddDays(-5));
TwoOfCasketDbContext.InsertSalaryToDatabaseAndReturn(worker2.Id, workerSalary: 300, salaryDate: DateTime.UtcNow.AddDays(-3));
//Act
var response = await HttpClient.GetAsync($"/api/report/loadsalary?fromDate={DateTime.Now.AddDays(-7):MM/dd/yyyy HH:mm:ss}&toDate={DateTime.Now.AddDays(-1):MM/dd/yyyy HH:mm:ss}");
//Assert
await AssertStreamAsync(response, $"file-{GetLocale()}.pdf");
}
private static async Task AssertStreamAsync(HttpResponseMessage response, string fileNameForSave = "")
{
Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.OK));
using var data = await response.Content.ReadAsStreamAsync();
Assert.That(data, Is.Not.Null);
Assert.That(data.Length, Is.GreaterThan(0));
await SaveStreamAsync(data, fileNameForSave);
}
private static async Task SaveStreamAsync(Stream stream, string fileName)
{
if (string.IsNullOrEmpty(fileName))
{
return;
}
var path = Path.Combine(Directory.GetCurrentDirectory(), fileName);
if (File.Exists(path))
{
File.Delete(path);
}
stream.Position = 0;
using var fileStream = new FileStream(path, FileMode.OpenOrCreate);
await stream.CopyToAsync(fileStream);
}
protected abstract string MessageElementNotFound();
[TestCase("rooms")]
[TestCase("posts")]
[TestCase("jobs/getrecord")]
[TestCase("works/getrecord")]
[TestCase("workers/getrecord")]
public async Task Api_GetElement_NotFound_Test(string path)
{
//Act
var response = await HttpClient.GetAsync($"/api/{path}/{Guid.NewGuid()}");
//Assert
Assert.That(JToken.Parse(await response.Content.ReadAsStringAsync()).ToString(), Does.StartWith(MessageElementNotFound()));
}
private static IEnumerable<TestCaseData> TestDataElementExists()
{
yield return new TestCaseData(() => {
var model = CreateRoomBindingModel();
TwoOfCasketDbContext.InsertRoomToDatabaseAndReturn(model.Id);
return model;
}, "rooms");
yield return new TestCaseData(() => {
var model = CreatePostModel();
TwoOfCasketDbContext.InsertPostToDatabaseAndReturn(model.Id);
return model;
}, "posts");
yield return new TestCaseData(() => {
var model = CreateJobModel();
TwoOfCasketDbContext.InsertJobToDatabaseAndReturn(model.Id);
return model;
}, "jobs/register");
yield return new TestCaseData(() => {
var model = CreateWorkerModel(_postId);
TwoOfCasketDbContext.InsertWorkerToDatabaseAndReturn(model.Id, postId: _postId);
return model;
}, "workers/register");
}
protected abstract string MessageElementExists();
[TestCaseSource(nameof(TestDataElementExists))]
public async Task Api_Post_WhenHaveRecordWithSameId_ShouldBadRequest_Test(Func<object> createModel, string path)
{
//Arrange
var model = createModel();
//Act
var response = await HttpClient.PostAsync($"/api/{path}", MakeContent(model));
//Assert
Assert.That(JToken.Parse(await response.Content.ReadAsStringAsync()).ToString(), Does.StartWith(MessageElementExists()));
}
private static IEnumerable<TestCaseData> TestDataIdIncorrect()
{
yield return new TestCaseData(() => {
var model = CreateWorkModel(workerId: _workerId, roomId: _roomId, jobId: _jobId);
model.Id = "Id";
return model;
}, "works/work");
yield return new TestCaseData(() => {
var model = CreateJobModel();
model.Id = "Id";
return model;
}, "jobs/register");
yield return new TestCaseData(() => {
var model = CreateWorkerModel(_postId);
model.Id = "Id";
return model;
}, "workers/register");
}
protected abstract string MessageElementIdIncorrect();
[TestCaseSource(nameof(TestDataIdIncorrect))]
public async Task Api_Post_WhenDataIsIncorrect_ShouldBadRequest_Test(Func<object> createModel, string path)
{
//Arrange
var model = createModel();
//Act
var responseWithIdIncorrect = await HttpClient.PostAsync($"/api/{path}", MakeContent(model));
//Assert
Assert.That(JToken.Parse(await responseWithIdIncorrect.Content.ReadAsStringAsync()).ToString(), Does.StartWith(MessageElementIdIncorrect()));
}
[TestCase("jobs/delete")]
[TestCase("works/cancel")]
[TestCase("posts")]
[TestCase("workers/delete")]
public async Task Api_DelElement_NotFound_Test(string path)
{
//Act
var response = await HttpClient.DeleteAsync($"/api/{path}/{Guid.NewGuid()}");
//Assert
Assert.That(JToken.Parse(await response.Content.ReadAsStringAsync()).ToString(), Does.StartWith(MessageElementNotFound()));
}
private static PostBindingModel CreatePostModel(string? postId = null, string postName = "name", PostType postType = PostType.Plasterer, int salary = 100)
=> new()
{
Id = postId ?? Guid.NewGuid().ToString(),
PostName = postName,
PostType = postType.ToString(),
Salary = salary
};
protected abstract string MessageValidationErrorIDIsEmpty();
private static IEnumerable<TestCaseData> TestDataValidationErrorIdIsEmpty()
{
yield return new TestCaseData(() =>
{
var model = CreatePostModel();
model.Id = "";
return model;
}, "posts");
yield return new TestCaseData(() =>
{
var model = CreateJobModel();
model.Id = "";
return model;
}, "jobs/changeinfo/");
yield return new TestCaseData(() => {
var model = CreateWorkerModel(_postId);
model.Id = "";
return model;
}, "workers/changeinfo/");
}
[TestCaseSource(nameof(TestDataValidationErrorIdIsEmpty))]
public async Task Api_Put_ValidationError_IdIsEmpty_ShouldBadRequest_Test(Func<object> createModel, string path)
{
//Arrange
var model = createModel();
//Act
var responseWithIdIncorrect = await HttpClient.PutAsync($"/api/{path}", MakeContent(model));
//Assert
Assert.That(JToken.Parse(await responseWithIdIncorrect.Content.ReadAsStringAsync()).ToString(), Does.StartWith(MessageValidationErrorIDIsEmpty()));
}
protected abstract string MessageValidationErrorIDIsNotGuid();
private static IEnumerable<TestCaseData> TestDataValidationErrorIdIsNotGuid()
{
yield return new TestCaseData(() =>
{
var model = CreatePostModel();
model.Id = "id";
return model;
}, "posts");
yield return new TestCaseData(() =>
{
var model = CreateJobModel();
model.Id = "id";
return model;
}, "jobs/changeinfo/");
yield return new TestCaseData(() => {
var model = CreateWorkerModel(_postId);
model.Id = "id";
return model;
}, "workers/changeinfo/");
}
[TestCaseSource(nameof(TestDataValidationErrorIdIsNotGuid))]
public async Task Api_Put_ValidationError_IIsNotGuid_ShouldBadRequest_Test(Func<object> createModel, string path)
{
//Arrange
var model = createModel();
//Act
var responseWithIdIncorrect = await HttpClient.PutAsync($"/api/{path}", MakeContent(model));
//Assert
Assert.That(JToken.Parse(await responseWithIdIncorrect.Content.ReadAsStringAsync()).ToString(), Does.StartWith(MessageValidationErrorIDIsNotGuid()));
}
protected abstract string MessageElementValidationErrorPostNameEmpty();
[TestCase("posts")]
public async Task Api_Put_ValidationError_PostNameIsEmpty_ShouldBadRequest_Test(string path)
{
//Arrange
var model = CreatePostModel();
model.PostName = "";
//Act
var responseWithIdIncorrect = await HttpClient.PutAsync($"/api/{path}", MakeContent(model));
//Assert
Assert.That(JToken.Parse(await responseWithIdIncorrect.Content.ReadAsStringAsync()).ToString(), Does.StartWith(MessageElementValidationErrorPostNameEmpty()));
}
protected abstract string MessageElementValidationErrorFIOIsEmpty();
[TestCase("workers/changeinfo/")]
public async Task Api_Put_ValidationError_FIOIsEmpty_ShouldBadRequest_Test(string path)
{
//Arrange
var model = CreateWorkerModel(_postId);
model.FIO = "";
//Act
var responseWithIdIncorrect = await HttpClient.PutAsync($"/api/{path}", MakeContent(model));
//Assert
Assert.That(JToken.Parse(await responseWithIdIncorrect.Content.ReadAsStringAsync()).ToString(), Does.StartWith(MessageElementValidationErrorFIOIsEmpty()));
}
private static async Task<T?> GetModelFromResponseAsync<T>(HttpResponseMessage response) =>
JsonSerializer.Deserialize<T>(await response.Content.ReadAsStringAsync(), JsonSerializerOptions);
private static StringContent MakeContent(object model) =>
new(JsonSerializer.Serialize(model), Encoding.UTF8, "application/json");
private static RoomBindingModel CreateRoomBindingModel(string? id = null, string name = "name", string emailClient = "aaaaaa@gmail.com", double size = 10) =>
new()
{
Id = id ?? Guid.NewGuid().ToString(),
Name = name,
EmailClient = emailClient,
Size = size
};
private static JobBindingModel CreateJobModel(string? id = null, string jobName = "name", WorkType jobType = WorkType.Painting, double price = 1)
=> new()
{
Id = id ?? Guid.NewGuid().ToString(),
JobName = jobName,
WorkType = jobType.ToString(),
Price = price
};
private static WorkBindingModel CreateWorkModel(string workerId, string? roomId, string jobId, string? id = null, int sizeWork = 1, double price = 1.1)
{
var workId = id ?? Guid.NewGuid().ToString();
return new()
{
Id = workId,
WorkerId = workerId,
RoomId = roomId,
Jobs = [new WorkJobBindingModel { WorkId = workId, JobId = jobId, SizeWork = sizeWork, Price = price }]
};
}
private static WorkerBindingModel CreateWorkerModel(string postId, string? id = null, string fio = "fio", DateTime? birthDate = null, DateTime? employmentDate = null, string? configuration = null)
{
return new()
{
Id = id ?? Guid.NewGuid().ToString(),
FIO = fio,
BirthDate = birthDate ?? DateTime.UtcNow.AddYears(-22),
EmploymentDate = employmentDate ?? DateTime.UtcNow.AddDays(-5),
ConfigurationJson = configuration ?? JsonSerializer.Serialize(new PostConfiguration() { Rate = 10 }),
PostId = postId
};
}
}

View File

@@ -4,24 +4,26 @@ using System.Linq;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging;
using TwoFromTheCasketContratcs.BuisnessLogicsContracts;
using TwoFromTheCasketContratcs.DataModels;
using TwoFromTheCasketContratcs.Exceptions;
using TwoFromTheCasketContratcs.Extensions;
using TwoFromTheCasketContratcs.Resources;
using TwoFromTheCasketContratcs.StorageContracts;
namespace TwoFromTheCasketBuisnessLogic.Implementations;
internal class MasterBusinessLogicContract(IMasterStorageContract masterStorageContract, ILogger logger) : IMasterBuisnessLogicContract
internal class MasterBusinessLogicContract(IMasterStorageContract masterStorageContract, ILogger logger, IStringLocalizer<Messages> localizer) : IMasterBuisnessLogicContract
{
ILogger _logger = logger;
private IMasterStorageContract _masterStorageContract = masterStorageContract;
private readonly IStringLocalizer<Messages> _localizer = localizer;
public List<MasterDataModel> GetAllMasters(bool onlyActive = true)
{
_logger.LogInformation("GetAllWorkers params: {onlyActive}", onlyActive);
return _masterStorageContract.GetList(onlyActive) ?? throw new
NullListException();
return _masterStorageContract.GetList(onlyActive);
}
public List<MasterDataModel> GetAllMastersByPost(string postId, bool onlyActive = true)
@@ -33,9 +35,9 @@ internal class MasterBusinessLogicContract(IMasterStorageContract masterStorageC
}
if (!postId.IsGuid())
{
throw new ValidationException("The value in the field postId is not a unique identifier.");
throw new ValidationException(string.Format(_localizer["ValidationExceptionMessageIncorrectField"], "PostId"));
}
return _masterStorageContract.GetList(onlyActive, postId) ?? throw new NullListException();
return _masterStorageContract.GetList(onlyActive, postId);
}
public List<MasterDataModel> GetAllMastersByEmploymentDate(DateTime fromDate, DateTime toDate, bool onlyActive = true)
@@ -43,10 +45,10 @@ internal class MasterBusinessLogicContract(IMasterStorageContract masterStorageC
_logger.LogInformation("GetAllWorkers params: {onlyActive}, { fromDate}, { toDate}", onlyActive, fromDate, toDate);
if (fromDate.IsDateNotOlder(toDate))
{
throw new IncorrectDatesException(fromDate, toDate);
throw new IncorrectDatesException(fromDate, toDate, localizer);
}
return _masterStorageContract.GetList(onlyActive, fromEmploymentDate:
fromDate, toEmploymentDate: toDate) ?? throw new NullListException();
fromDate, toEmploymentDate: toDate);
}
public MasterDataModel GetMasterByData(string data)
@@ -59,10 +61,10 @@ internal class MasterBusinessLogicContract(IMasterStorageContract masterStorageC
if (data.IsGuid())
{
return _masterStorageContract.GetElementById(data) ?? throw
new ElementNotFoundException(data);
new ElementNotFoundException(data, _localizer);
}
return _masterStorageContract.GetElementByFIO(data) ?? throw new
ElementNotFoundException(data);
ElementNotFoundException(data, _localizer);
}
public void InsertMaster(MasterDataModel workerDataModel)
@@ -70,7 +72,7 @@ internal class MasterBusinessLogicContract(IMasterStorageContract masterStorageC
_logger.LogInformation("New data: {json}",
JsonSerializer.Serialize(workerDataModel));
ArgumentNullException.ThrowIfNull(workerDataModel);
workerDataModel.Validate();
workerDataModel.Validate(localizer);
_masterStorageContract.AddElement(workerDataModel);
}
@@ -79,7 +81,7 @@ internal class MasterBusinessLogicContract(IMasterStorageContract masterStorageC
_logger.LogInformation("Update data: {json}",
JsonSerializer.Serialize(workerDataModel));
ArgumentNullException.ThrowIfNull(workerDataModel);
workerDataModel.Validate();
workerDataModel.Validate(_localizer);
_masterStorageContract.UpdElement(workerDataModel);
}
@@ -92,7 +94,7 @@ internal class MasterBusinessLogicContract(IMasterStorageContract masterStorageC
}
if (!id.IsGuid())
{
throw new ValidationException("Id is not a unique identifier");
throw new ValidationException(string.Format(_localizer["ValidationExceptionMessageIncorrectField"], "Id"));
}
_masterStorageContract.DelElement(id);
}
@@ -102,9 +104,9 @@ internal class MasterBusinessLogicContract(IMasterStorageContract masterStorageC
_logger.LogInformation("GetAllWorkers params: {onlyActive}, { fromDate}, { toDate}", onlyActive, fromDate, toDate);
if (fromDate.IsDateNotOlder(toDate))
{
throw new IncorrectDatesException(fromDate, toDate);
throw new IncorrectDatesException(fromDate, toDate, localizer);
}
return _masterStorageContract.GetList(onlyActive, fromBirthDate: fromDate, toBirthDate: toDate) ?? throw new NullListException();
return _masterStorageContract.GetList(onlyActive, fromBirthDate: fromDate, toBirthDate: toDate);
}
public List<MasterDataModel> GetAllWorkersByEmploymentDate(DateTime
@@ -113,9 +115,9 @@ internal class MasterBusinessLogicContract(IMasterStorageContract masterStorageC
_logger.LogInformation("GetAllMaster params: {onlyActive}, { fromDate}, { toDate}", onlyActive, fromDate, toDate);
if (fromDate.IsDateNotOlder(toDate))
{
throw new IncorrectDatesException(fromDate, toDate);
throw new IncorrectDatesException(fromDate, toDate, localizer);
}
return _masterStorageContract.GetList(onlyActive, fromEmploymentDate:
fromDate, toEmploymentDate: toDate) ?? throw new NullListException();
fromDate, toEmploymentDate: toDate);
}
}

View File

@@ -3,27 +3,26 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging;
using TwoFromTheCasketContratcs.BuisnessLogicsContracts;
using TwoFromTheCasketContratcs.DataModels;
using TwoFromTheCasketContratcs.Exceptions;
using TwoFromTheCasketContratcs.Extensions;
using TwoFromTheCasketContratcs.Resources;
using TwoFromTheCasketContratcs.StorageContracts;
namespace TwoFromTheCasketBuisnessLogic.Implementations;
internal class OrderBusinessLogicContract(IOrderStorageContract orderStorageContract, ILogger logger) : IOrderBuisnessLogicContract
internal class OrderBusinessLogicContract(IOrderStorageContract orderStorageContract, ILogger logger, IStringLocalizer<Messages> localizer) : IOrderBuisnessLogicContract
{
private ILogger _logger = logger;
private IOrderStorageContract _orderStorageContract = orderStorageContract;
private readonly IStringLocalizer<Messages> _localizer = localizer;
public List<OrderDataModel> GetAllOrder()
{
_logger.LogInformation("GetAllOrders called");
var orders = _orderStorageContract.GetList();
if (orders == null)
{
throw new NullListException();
}
return orders;
}
@@ -32,7 +31,7 @@ internal class OrderBusinessLogicContract(IOrderStorageContract orderStorageCont
_logger.LogInformation("GetAllOrdersByDate called with fromDate: {fromDate} to: {toDate}");
return _orderStorageContract.GetElementByDate(fromDate) ?? throw new NullListException();
return _orderStorageContract.GetElementByDate(fromDate);
}
public OrderDataModel GetOrderByData(string data)
@@ -44,9 +43,9 @@ internal class OrderBusinessLogicContract(IOrderStorageContract orderStorageCont
}
if (data.IsGuid())
{
return _orderStorageContract.GetElementById(data) ?? throw new ElementNotFoundException(data);
return _orderStorageContract.GetElementById(data) ?? throw new ElementNotFoundException(data, _localizer);
}
return _orderStorageContract.GetElementById(data) ?? throw new ElementNotFoundException(data);
return _orderStorageContract.GetElementById(data) ?? throw new ElementNotFoundException(data, _localizer);
}
public void InsertOrder(OrderDataModel orderDataModel)
@@ -75,7 +74,7 @@ internal class OrderBusinessLogicContract(IOrderStorageContract orderStorageCont
if (orderDataModel == null)
throw new ArgumentNullException(nameof(orderDataModel));
orderDataModel.Validate();
orderDataModel.Validate(_localizer);
}
private void ValidateId(string id)
@@ -84,6 +83,6 @@ internal class OrderBusinessLogicContract(IOrderStorageContract orderStorageCont
throw new ArgumentNullException(nameof(id));
if (!Guid.TryParse(id, out _))
throw new ValidationException("Id is not a unique identifier");
throw new ValidationException(string.Format(_localizer["ValidationExceptionMessageEmptyField"], "Id"));
}
}

View File

@@ -4,25 +4,27 @@ using System.Linq;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging;
using TwoFromTheCasketContratcs.BuisnessLogicsContracts;
using TwoFromTheCasketContratcs.DataModels;
using TwoFromTheCasketContratcs.Exceptions;
using TwoFromTheCasketContratcs.Extensions;
using TwoFromTheCasketContratcs.Resources;
using TwoFromTheCasketContratcs.StorageContracts;
namespace TwoFromTheCasketBuisnessLogic.Implementations;
internal class PostBusinessLogicContract(IPostStorageContract postStorageContract, ILogger logger) : IPostBuisnessLogicContract
internal class PostBusinessLogicContract(IPostStorageContract postStorageContract, ILogger logger, IStringLocalizer<Messages> localizer) : IPostBuisnessLogicContract
{
private IPostStorageContract _postStorageContract = postStorageContract;
private ILogger _logger = logger;
private readonly IStringLocalizer<Messages> _localizer = localizer;
public List<PostDataModel> GetAllPosts()
{
_logger.LogInformation("GetAllPosts");
return _postStorageContract.GetList() ?? throw new
NullListException();
return _postStorageContract.GetList();
}
public List<PostDataModel> GetAllDataOfPost(string postId)
@@ -34,10 +36,9 @@ internal class PostBusinessLogicContract(IPostStorageContract postStorageContrac
}
if (!postId.IsGuid())
{
throw new ValidationException("The value in the field postId is not a unique identifier.");
throw new ValidationException(string.Format(_localizer["ValidationExceptionMessageEmptyField"], "Id"));
}
return _postStorageContract.GetPostWithHistory(postId) ?? throw new
NullListException();
return _postStorageContract.GetPostWithHistory(postId);
}
public PostDataModel GetPostByData(string data)
@@ -50,10 +51,10 @@ internal class PostBusinessLogicContract(IPostStorageContract postStorageContrac
if (data.IsGuid())
{
return _postStorageContract.GetElementById(data) ?? throw new
ElementNotFoundException(data);
ElementNotFoundException(data, _localizer);
}
return _postStorageContract.GetElementByName(data) ?? throw new
ElementNotFoundException(data);
ElementNotFoundException(data, _localizer);
}
public void InsertPost(PostDataModel postDataModel)
@@ -63,7 +64,7 @@ internal class PostBusinessLogicContract(IPostStorageContract postStorageContrac
if (postDataModel == null)
throw new ArgumentNullException(nameof(postDataModel));
postDataModel.Validate(); // Вызовляем проверку валидности данных
postDataModel.Validate(localizer); // Вызовляем проверку валидности данных
_postStorageContract.AddElement(postDataModel);
}
@@ -72,7 +73,7 @@ internal class PostBusinessLogicContract(IPostStorageContract postStorageContrac
{
_logger.LogInformation("Update data: {json}", JsonSerializer.Serialize(postDataModel));
ArgumentNullException.ThrowIfNull(postDataModel);
postDataModel.Validate();
postDataModel.Validate(localizer);
_postStorageContract.UpdElement(postDataModel);
}
@@ -85,7 +86,7 @@ internal class PostBusinessLogicContract(IPostStorageContract postStorageContrac
}
if (!id.IsGuid())
{
throw new ValidationException("Id is not a unique identifier");
throw new ValidationException(string.Format(_localizer["ValidationExceptionMessageEmptyField"], "Id"));
}
_postStorageContract.DelElement(id);
}
@@ -99,7 +100,7 @@ internal class PostBusinessLogicContract(IPostStorageContract postStorageContrac
}
if (!id.IsGuid())
{
throw new ValidationException("Id is not a unique identifier");
throw new ValidationException(string.Format(_localizer["ValidationExceptionMessageEmptyField"], "Id"));
}
_postStorageContract.ResElement(id);
}

View File

@@ -0,0 +1,316 @@
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Localization;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TwoFromTheCasketBuisnessLogic.OfficePackage;
using TwoFromTheCasketContratcs.BuisnessLogicsContracts;
using TwoFromTheCasketContratcs.DataModels;
using TwoFromTheCasketContratcs.Exceptions;
using TwoFromTheCasketContratcs.Extensions;
using TwoFromTheCasketContratcs.StorageContracts;
using TwoFromTheCasketContratcs.Resources;
namespace TwoFromTheCasketBuisnessLogic.Implementations;
internal class ReportContract(IServiceStorageContract serviceStorageContract, IMasterStorageContract masterStorageContract, IOrderStorageContract orderStorageContract, ISalaryStorageContract salaryStorageContract, IPostStorageContract postStorageContract, BaseWordBuilder baseWordBuilder, BaseExcelBuilder baseExcelBuilder, BasePdfBuilder basePdfBuilder, ILogger logger, IStringLocalizer<Messages> localizer) : IReportContract
{
private readonly IServiceStorageContract _serviceStorageContract = serviceStorageContract;
private readonly IMasterStorageContract _masterStorageContract = masterStorageContract;
private readonly IOrderStorageContract _orderStorageContract = orderStorageContract;
private readonly ISalaryStorageContract _salaryStorageContract = salaryStorageContract;
private readonly IPostStorageContract _postStorageContract = postStorageContract;
private readonly BaseWordBuilder _baseWordBuilder = baseWordBuilder;
private readonly BaseExcelBuilder _baseExcelBuilder = baseExcelBuilder;
private readonly BasePdfBuilder _basePdfBuilder = basePdfBuilder;
private readonly ILogger _logger = logger;
private readonly IStringLocalizer<Messages> _localizer = localizer;
internal static readonly string[] documentHeader = ["Дата", "Работа"];
internal static readonly string[] tableHeader = ["Дата", "Сумма", "Работа", "Объём"];
public async Task<Stream> CreateDocumentServicesWithHistoryAsync(DateTime dateStart, DateTime dateFinish, CancellationToken ct)
{
var services = await GetDataServicesWithHistoryAsync(dateStart, dateFinish, ct);
var builder = _baseWordBuilder
.AddHeader(_localizer["ReportServicesHeader"].Value)
.AddParagraph(_localizer["ReportServicesPeriod", dateStart.ToUniversalTime().ToString(), dateFinish.ToString("dd.MM.yyyy")].Value)
.AddParagraph(_localizer["ReportServicesGenerated", dateStart.ToUniversalTime().ToString()].Value);
if (!services.Any())
{
builder.AddParagraph(_localizer["ReportServicesNoData"].Value);
return builder.Build();
}
var tableData = new List<string[]>
{
new[] {
_localizer["ReportServicesTableService"].Value,
_localizer["ReportServicesTableType"].Value,
_localizer["ReportServicesTableCurrentPrice"].Value,
_localizer["ReportServicesTableChangeDate"].Value,
_localizer["ReportServicesTableOldPrice"].Value
}
};
foreach (var service in services)
{
if (service.History.Any())
{
var sortedHistory = service.History.OrderByDescending(h => h.ChangeDate).ToList();
for (int i = 0; i < sortedHistory.Count; i++)
{
var history = sortedHistory[i];
tableData.Add(new[]
{
i == 0 ? service.ServiceName : "",
i == 0 ? service.ServiceType.ToString() : "",
i == 0 ? service.Price.ToString("C") : "",
history.ChangeDate.ToUniversalTime().ToString(),
history.OldPrice.ToString("C")
});
}
}
else
{
tableData.Add(new[]
{
service.ServiceName,
service.ServiceType.ToString(),
service.Price.ToString("C"),
_localizer["ReportServicesNoChanges"].Value,
_localizer["ReportServicesNoChanges"].Value
});
}
}
builder.AddTable(new[] { 2500, 1500, 1500, 2000, 1500 }, tableData);
return builder.Build();
}
public async Task<Stream> CreateDocumentOrdersByPeriodAsync(DateTime dateStart, DateTime dateFinish, CancellationToken ct)
{
var orders = await GetDataOrderByPeriodAsync(dateStart, dateFinish, ct);
var tableData = new List<string[]> { new[] {
_localizer["ReportOrdersTableOrderDate"].Value,
_localizer["ReportOrdersTableStatus"].Value,
_localizer["ReportOrdersTableRoomType"].Value,
_localizer["ReportOrdersTableMaster"].Value,
_localizer["ReportOrdersTableService"].Value,
_localizer["ReportOrdersTableWorkTime"].Value,
_localizer["ReportOrdersTableAmount"].Value
} };
foreach (var order in orders)
{
var orderDetails = await GetOrderDetailsAsync(order.Id, ct);
if (orderDetails.Any())
{
foreach (var detail in orderDetails)
{
tableData.Add(new[]
{
order.Date.ToString("dd.MM.yyyy"),
order.Status.ToString(),
order.RoomType.ToString(),
detail.MasterFIO,
detail.ServiceName,
$"{detail.TimeOfWorking} {_localizer["ReportOrdersHours"].Value}",
detail.TotalAmount.ToString("C")
});
}
}
else
{
tableData.Add(new[]
{
order.Date.ToString("dd.MM.yyyy"),
order.Status.ToString(),
order.RoomType.ToString(),
_localizer["ReportOrdersNotAssigned"].Value,
_localizer["ReportOrdersNoServices"].Value,
$"0 {_localizer["ReportOrdersHours"].Value}",
"0,00 ₽"
});
}
}
return _baseExcelBuilder
.AddHeader(_localizer["ReportOrdersHeader"].Value, 0, 7)
.AddParagraph(_localizer["ReportOrdersPeriod", dateStart.ToString("dd.MM.yyyy"), dateFinish.ToString("dd.MM.yyyy")].Value, 2)
.AddTable([15, 12, 15, 20, 25, 12, 15], tableData)
.Build();
}
public async Task<Stream> CreateDocumentSalaryByPeriodAsync(DateTime dateStart, DateTime dateFinish, CancellationToken ct)
{
var data = await GetDataSalaryByPeriodAsync(dateStart, dateFinish, ct);
if (!data.Any())
{
return _basePdfBuilder
.AddHeader(_localizer["ReportSalaryHeader"].Value)
.AddParagraph(_localizer["ReportSalaryPeriod", dateStart.ToString("dd.MM.yyyy"), dateFinish.ToString("dd.MM.yyyy")].Value)
.AddParagraph(_localizer["ReportServicesNoData"].Value)
.Build();
}
var groupedData = data.GroupBy(x => x.MasterFIO)
.Select(g => new { MasterFIO = g.Key, TotalSalary = g.Sum(x => x.TotalSalary) })
.ToList();
var tableData = new List<string[]>
{
new[] {
_localizer["ReportSalaryTableMaster"].Value,
_localizer["ReportSalaryTableDate"].Value,
_localizer["ReportSalaryTableAmount"].Value
}
};
foreach (var salary in data)
{
var row = new[]
{
salary.MasterFIO,
salary.FromPeriod.ToString("dd.MM.yyyy"),
salary.TotalSalary.ToString("C")
};
tableData.Add(row);
}
return _basePdfBuilder
.AddHeader(_localizer["ReportSalaryHeader"].Value)
.AddParagraph(_localizer["ReportSalaryPeriod", dateStart.ToUniversalTime().ToString(), dateStart.ToUniversalTime().ToString()].Value)
.AddPieChart(_localizer["ReportSalaryAccruals"].Value, groupedData.Select(x => (x.MasterFIO, x.TotalSalary)).ToList())
.AddParagraph("")
.AddTable(new[] { 200, 150, 150 }, tableData)
.Build();
}
public async Task<List<ServiceHistoryDataModel>> GetDataServiceHistoryAsync(CancellationToken ct)
{
var histories = new List<ServiceHistoryDataModel>();
var services = _serviceStorageContract.GetList() ?? new List<ServiceDataModel>();
foreach (var service in services)
{
var serviceHistories = _serviceStorageContract.GetHistoryByServiceId(service.Id);
if (serviceHistories != null)
{
histories.AddRange(serviceHistories);
}
}
return histories.OrderByDescending(h => h.ChangeDate).ToList();
}
public async Task<List<OrderDataModel>> GetDataOrderByPeriodAsync(DateTime dateStart, DateTime dateFinish, CancellationToken ct)
{
if (dateStart.IsDateNotOlder(dateFinish))
{
throw new IncorrectDatesException(dateStart, dateFinish, _localizer);
}
try
{
var orders = await _orderStorageContract.GetListAsync(dateStart, dateFinish, ct);
return orders.OrderBy(o => o.Date).ToList();
}
catch (Exception ex)
{
throw;
}
}
public async Task<List<MasterSalaryByPeriodDataModel>> GetDataSalaryByPeriodAsync(DateTime dateStart, DateTime dateFinish, CancellationToken ct)
{
if (dateStart >= dateFinish)
{
throw new IncorrectDatesException(dateStart, dateFinish, _localizer);
}
var salaries = await _salaryStorageContract.GetListAsync(dateStart, dateFinish, ct) ?? new List<SalaryDataModel>();
var masters = _masterStorageContract.GetList(onlyActive: true) ?? new List<MasterDataModel>();
var salaryRecords = salaries.Select(salary =>
{
var master = masters.FirstOrDefault(m => m.Id == salary.MasterId);
return new MasterSalaryByPeriodDataModel
{
MasterFIO = master?.FIO ?? _localizer["ReportSalaryUnknownMaster"].Value,
TotalSalary = salary.Salary + salary.Prize,
FromPeriod = salary.SalaryDate,
ToPeriod = salary.SalaryDate
};
}).OrderBy(x => x.MasterFIO).ThenBy(x => x.FromPeriod).ToList();
return salaryRecords;
}
public async Task<List<ServiceWithHistoryDataModel>> GetDataServicesWithHistoryAsync(DateTime dateStart, DateTime dateFinish, CancellationToken ct)
{
if (dateStart > dateFinish)
{
throw new IncorrectDatesException(dateStart, dateFinish, _localizer);
}
var services = _serviceStorageContract.GetList() ?? new List<ServiceDataModel>();
var result = new List<ServiceWithHistoryDataModel>();
foreach (var service in services)
{
var serviceHistories = _serviceStorageContract.GetHistoryByServiceId(service.Id) ?? new List<ServiceHistoryDataModel>();
var filteredHistories = serviceHistories
.Where(h => h.ChangeDate >= dateStart && h.ChangeDate <= dateFinish)
.OrderByDescending(h => h.ChangeDate)
.ToList();
result.Add(new ServiceWithHistoryDataModel
{
Id = service.Id,
ServiceName = service.ServiceName,
ServiceType = service.ServiceType,
MasterId = service.MasterId,
Price = service.Price,
IsDeleted = service.IsDeleted,
History = filteredHistories
});
}
return result.OrderBy(s => s.ServiceName).ToList();
}
private async Task<List<(string MasterFIO, string ServiceName, int TimeOfWorking, decimal TotalAmount)>> GetOrderDetailsAsync(string orderId, CancellationToken ct)
{
try
{
return await _orderStorageContract.GetOrderDetailsAsync(orderId, ct);
}
catch (Exception)
{
return new List<(string MasterFIO, string ServiceName, int TimeOfWorking, decimal TotalAmount)>();
}
}
}

View File

@@ -1,25 +1,33 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using TwoFromTheCasketContratcs.BuisnessLogicsContracts;
using TwoFromTheCasketContratcs.DataModels;
using TwoFromTheCasketContratcs.StorageContracts;
using TwoFromTheCasketContratcs.Extensions;
using TwoFromTheCasketContratcs.Exceptions;
using TwoFromTheCasketContratcs.Infrastructure;
using TwoFromTheCasketContratcs.Infrastructure.PostConfigurations;
using Microsoft.Extensions.Localization;
using TwoFromTheCasketContratcs.Resources;
namespace TwoFromTheCasketBuisnessLogic.Implementations
{
internal class SalaryBusinessLogicContract(ISalaryStorageContract
salaryStorageContract, IPostStorageContract
postStorageContract, IMasterStorageContract masterStorageContract, ILogger
logger, IOrderStorageContract orderStorageContract) : ISalaryBuisnessLogicContract
logger, IOrderStorageContract orderStorageContract, IConfigurationSalary configurationSalary, IStringLocalizer<Messages> localizer) : ISalaryBuisnessLogicContract
{
private readonly ILogger _logger = logger;
private readonly ISalaryStorageContract _salaryStorageContract = salaryStorageContract;
private readonly IPostStorageContract _postStorageContract = postStorageContract;
private readonly IMasterStorageContract _masterStorageContract = masterStorageContract;
private readonly IOrderStorageContract _orderStorageContract = orderStorageContract;
private readonly IConfigurationSalary _configurationSalary = configurationSalary;
private readonly object _lockObject = new object();
private readonly IStringLocalizer<Messages> _localizer = localizer;
public List<SalaryDataModel> GetAllSalariesByPeriod(DateTime fromDate, DateTime toDate)
{
@@ -27,17 +35,17 @@ logger, IOrderStorageContract orderStorageContract) : ISalaryBuisnessLogicContra
if (fromDate.IsDateNotOlder(toDate))
{
throw new IncorrectDatesException(fromDate, toDate);
throw new IncorrectDatesException(fromDate, toDate, _localizer);
}
return _salaryStorageContract.GetList(fromDate, toDate) ?? throw new NullListException();
return _salaryStorageContract.GetList(fromDate, toDate);
}
public List<SalaryDataModel> GetAllSalariesByPeriodByMaster(DateTime fromDate, DateTime toDate, string masterId)
{
if (fromDate.IsDateNotOlder(toDate))
{
throw new IncorrectDatesException(fromDate, toDate);
throw new IncorrectDatesException(fromDate, toDate, _localizer);
}
if (string.IsNullOrEmpty(masterId))
@@ -51,33 +59,158 @@ logger, IOrderStorageContract orderStorageContract) : ISalaryBuisnessLogicContra
}
_logger.LogInformation("GetAllSalaries params: {fromDate}, {toDate}, {masterId}", fromDate, toDate, masterId);
return _salaryStorageContract.GetList(fromDate, toDate, masterId) ?? throw new NullListException();
return _salaryStorageContract.GetList(fromDate, toDate, masterId);
}
public void CalculateSalaryByMonth(DateTime date)
{
_logger.LogInformation("CalculateSalaryByMonth: {date}", date);
var startDate = new DateTime(date.Year, date.Month, 1);
var finishDate = new DateTime(date.Year, date.Month, DateTime.DaysInMonth(date.Year, date.Month));
var masters = _masterStorageContract.GetList() ?? throw new NullListException();
var startDate = new DateTime(date.Year, date.Month, 1, 0, 0, 0, DateTimeKind.Utc);
var finishDate = new DateTime(date.Year, date.Month, DateTime.DaysInMonth(date.Year, date.Month), 0, 0, 0, DateTimeKind.Utc);
var masters = _masterStorageContract.GetList();
foreach (var master in masters)
{
master.Validate();
var post = _postStorageContract.GetElementById(master.PostId) ?? throw new ElementNotFoundException(master.PostId);
var baseSalary = post.Salary;
var prize = 500.0;
var totalSalary = baseSalary + prize;
_logger.LogDebug("The master {master.Id} was paid a salary of {salary}", master.Id, totalSalary);
_salaryStorageContract.AddElement(new SalaryDataModel(master.Id, finishDate, totalSalary, prize));
var orders = _orderStorageContract.GetList();
// Фильтруем заказы по дате (связь с мастером идет через ServiceOrder)
var masterOrders = orders.Where(o => o.Date >= startDate && o.Date <= finishDate).ToList();
var post = _postStorageContract.GetElementById(master.PostId) ?? throw new ElementNotFoundException(master.PostId, _localizer);
var salary = post.ConfigurationModel switch
{
null => 0,
CarpenterPostConfiguration cpc => CalculateSalaryForCarpenter(masterOrders, startDate, finishDate, cpc),
PainterPostConfiguration ppc => CalculateSalaryForPainter(masterOrders, startDate, finishDate, ppc),
PlastererPostConfiguration plpc => CalculateSalaryForPlasterer(masterOrders, startDate, finishDate, plpc),
PostConfiguration pc => pc.Rate,
};
_logger.LogDebug("The master {masterId} was paid a salary of {salary}", master.Id, salary);
_salaryStorageContract.AddElement(new SalaryDataModel(master.Id, finishDate, salary, 0));
}
// Сохраняем все изменения одним вызовом
_salaryStorageContract.SaveChanges();
}
private double CalculateSalaryForCarpenter(List<OrderDataModel> orders, DateTime startDate, DateTime finishDate, CarpenterPostConfiguration config)
{
var maxThreads = Math.Max(1, _configurationSalary.MaxThreads);
var options = new ParallelOptions { MaxDegreeOfParallelism = maxThreads };
var calcPercent = 0.0;
var days = new List<DateTime>();
for (var date = startDate; date < finishDate; date = date.AddDays(1))
{
days.Add(date);
}
Parallel.ForEach(days, options, date =>
{
var ordersInDay = orders.Where(x => x.Date.Date == date.Date).ToArray();
if (ordersInDay.Length > 0)
{
lock (_lockObject)
{
calcPercent += ordersInDay.Length * config.BonusForExtraCarpentry;
}
}
});
return config.Rate + calcPercent;
}
private double CalculateSalaryForPainter(List<OrderDataModel> orders, DateTime startDate, DateTime finishDate, PainterPostConfiguration config)
{
var maxThreads = Math.Max(1, _configurationSalary.MaxThreads);
var options = new ParallelOptions { MaxDegreeOfParallelism = maxThreads };
var calcPercent = 0.0;
var days = new List<DateTime>();
for (var date = startDate; date < finishDate; date = date.AddDays(1))
{
days.Add(date);
}
Parallel.ForEach(days, options, date =>
{
var ordersInDay = orders.Where(x => x.Date.Date == date.Date).ToArray();
if (ordersInDay.Length > 0)
{
lock (_lockObject)
{
calcPercent += ordersInDay.Length * config.PainterPercent;
}
}
});
var calcBonusTask = Task.Run(() =>
{
return orders.Count * config.BonusForExtraPainter;
});
try
{
calcBonusTask.Wait();
}
catch (AggregateException agEx)
{
foreach (var ex in agEx.InnerExceptions)
{
_logger.LogError(ex, "Error in the painter payroll process");
}
return 0;
}
return config.Rate + calcPercent + calcBonusTask.Result;
}
private double CalculateSalaryForPlasterer(List<OrderDataModel> orders, DateTime startDate, DateTime finishDate, PlastererPostConfiguration config)
{
var maxThreads = Math.Max(1, _configurationSalary.MaxThreads);
var options = new ParallelOptions { MaxDegreeOfParallelism = maxThreads };
var calcPercent = 0.0;
var days = new List<DateTime>();
for (var date = startDate; date < finishDate; date = date.AddDays(1))
{
days.Add(date);
}
Parallel.ForEach(days, options, date =>
{
var ordersInDay = orders.Where(x => x.Date.Date == date.Date).ToArray();
if (ordersInDay.Length > 0)
{
lock (_lockObject)
{
calcPercent += ordersInDay.Length * config.PlastererPercent;
}
}
});
var calcBonusTask = Task.Run(() =>
{
return orders.Count * config.BonusForExtraPlasterer;
});
try
{
calcBonusTask.Wait();
}
catch (AggregateException agEx)
{
foreach (var ex in agEx.InnerExceptions)
{
_logger.LogError(ex, "Error in the plasterer payroll process");
}
return 0;
}
return config.Rate + calcPercent + calcBonusTask.Result;
}
}
}

View File

@@ -4,28 +4,28 @@ using System.Linq;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging;
using TwoFromTheCasketContratcs.BuisnessLogicsContracts;
using TwoFromTheCasketContratcs.DataModels;
using TwoFromTheCasketContratcs.Enums;
using TwoFromTheCasketContratcs.Exceptions;
using TwoFromTheCasketContratcs.Extensions;
using TwoFromTheCasketContratcs.Resources;
using TwoFromTheCasketContratcs.StorageContracts;
namespace TwoFromTheCasketBuisnessLogic.Implementations;
internal class ServiceBusinessLogicContract(IServiceStorageContract serviceStorageContract, ILogger logger) : IServiceBuisnessLogicContract
internal class ServiceBusinessLogicContract(IServiceStorageContract serviceStorageContract, ILogger logger, IStringLocalizer<Messages> localizer) : IServiceBuisnessLogicContract
{
ILogger _logger = logger;
private IServiceStorageContract _serviceStorageContract = serviceStorageContract;
private readonly IStringLocalizer<Messages> _localizer = localizer;
public List<ServiceDataModel> GetAllServices(bool onlyActive)
{
_logger.LogInformation("GetAllService called");
var services = _serviceStorageContract.GetList();
if(services == null)
{
throw new NullListException();
}
return services;
}
@@ -40,7 +40,7 @@ internal class ServiceBusinessLogicContract(IServiceStorageContract serviceStora
{
throw new ValidationException("The value in the field masterId is not a unique identifier.");
}
return _serviceStorageContract.GetElementByMasterId(masterId) ?? throw new NullListException();
return _serviceStorageContract.GetElementByMasterId(masterId);
}
public List<ServiceDataModel> GetServicesByServiceType(ServiceType serviceType, bool onlyActive)
@@ -67,7 +67,7 @@ internal class ServiceBusinessLogicContract(IServiceStorageContract serviceStora
_logger.LogInformation("New data: {json}",
JsonSerializer.Serialize(serviceDataModel));
ArgumentNullException.ThrowIfNull(serviceDataModel);
serviceDataModel.Validate();
serviceDataModel.Validate(_localizer);
_serviceStorageContract.AddElement(serviceDataModel);
}
@@ -77,7 +77,7 @@ internal class ServiceBusinessLogicContract(IServiceStorageContract serviceStora
_logger.LogInformation("Update data: {json}",
JsonSerializer.Serialize(serviceDataModel));
ArgumentNullException.ThrowIfNull(serviceDataModel);
serviceDataModel.Validate();
serviceDataModel.Validate(_localizer);
_serviceStorageContract.UpdElement(serviceDataModel);
}
public void DeleteService(string id)
@@ -89,7 +89,7 @@ internal class ServiceBusinessLogicContract(IServiceStorageContract serviceStora
}
if (!id.IsGuid())
{
throw new ValidationException("Id is not a unique identifier");
throw new ValidationException(string.Format(_localizer["ValidationExceptionMessageEmptyField"], "Id"));
}
_serviceStorageContract.DelElement(id);
}

View File

@@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TwoFromTheCasketBuisnessLogic.OfficePackage;
public abstract class BaseExcelBuilder
{
public abstract BaseExcelBuilder AddHeader(string header, int startIndex, int count);
public abstract BaseExcelBuilder AddParagraph(string text, int columnIndex);
public abstract BaseExcelBuilder AddTable(int[] columnsWidths, List<string[]> data);
public abstract Stream Build();
}

View File

@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TwoFromTheCasketBuisnessLogic.OfficePackage;
public abstract class BasePdfBuilder
{
public abstract BasePdfBuilder AddHeader(string header);
public abstract BasePdfBuilder AddParagraph(string text);
public abstract BasePdfBuilder AddPieChart(string title, List<(string Caption, double Value)> data);
public abstract BasePdfBuilder AddTable(int[] widths, List<string[]> data);
public abstract Stream Build();
}

View File

@@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TwoFromTheCasketBuisnessLogic.OfficePackage;
public abstract class BaseWordBuilder
{
public abstract BaseWordBuilder AddHeader(string header);
public abstract BaseWordBuilder AddParagraph(string text);
public abstract BaseWordBuilder AddTable(int[] widths, List<string[]> data);
public abstract Stream Build();
}

View File

@@ -0,0 +1,116 @@
using Microsoft.EntityFrameworkCore.Migrations.Internal;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MigraDoc.DocumentObjectModel;
using MigraDoc.DocumentObjectModel.Shapes.Charts;
using MigraDoc.Rendering;
using System.Threading.Tasks;
namespace TwoFromTheCasketBuisnessLogic.OfficePackage;
internal class MigraDocPdfBuilder : BasePdfBuilder
{
private readonly Document _document;
public MigraDocPdfBuilder()
{
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
_document = new Document();
DefineStyles();
}
public override BasePdfBuilder AddHeader(string header)
{
_document.AddSection().AddParagraph(header, "NormalBold");
return this;
}
public override BasePdfBuilder AddParagraph(string text)
{
_document.LastSection.AddParagraph(text, "Normal");
return this;
}
public override BasePdfBuilder AddPieChart(string title, List<(string Caption, double Value)> data)
{
if (data == null || data.Count == 0)
{
return this;
}
var chart = new Chart(ChartType.Pie2D);
var series = chart.SeriesCollection.AddSeries();
series.Add(data.Select(x => x.Value).ToArray());
var xseries = chart.XValues.AddXSeries();
xseries.Add(data.Select(x => x.Caption).ToArray());
chart.DataLabel.Type = DataLabelType.Percent;
chart.DataLabel.Position = DataLabelPosition.OutsideEnd;
chart.Width = Unit.FromCentimeter(16);
chart.Height = Unit.FromCentimeter(12);
chart.TopArea.AddParagraph(title);
chart.XAxis.MajorTickMark = TickMarkType.Outside;
chart.YAxis.MajorTickMark = TickMarkType.Outside;
chart.YAxis.HasMajorGridlines = true;
chart.PlotArea.LineFormat.Width = 1;
chart.PlotArea.LineFormat.Visible = true;
chart.TopArea.AddLegend();
_document.LastSection.Add(chart);
return this;
}
public override BasePdfBuilder AddTable(int[] widths, List<string[]> data)
{
if (data == null || data.Count == 0)
{
return this;
}
var table = _document.LastSection.AddTable();
table.Style = "Table";
table.Borders.Color = Colors.Black;
table.Borders.Width = 0.25;
table.Borders.Left.Width = 0.5;
table.Borders.Right.Width = 0.5;
table.Rows.LeftIndent = 0;
// Настройка колонок
for (int i = 0; i < widths.Length; i++)
{
var column = table.AddColumn(Unit.FromPoint(widths[i]));
column.Format.Alignment = ParagraphAlignment.Center;
}
// Добавление данных
for (int rowIndex = 0; rowIndex < data.Count; rowIndex++)
{
var row = table.AddRow();
row.HeadingFormat = (rowIndex == 0); // Первая строка - заголовок
row.Format.Alignment = ParagraphAlignment.Center;
row.Format.Font.Bold = (rowIndex == 0);
for (int colIndex = 0; colIndex < data[rowIndex].Length && colIndex < widths.Length; colIndex++)
{
var cell = row.Cells[colIndex];
var cellText = data[rowIndex][colIndex];
cell.AddParagraph(cellText);
cell.Format.Alignment = ParagraphAlignment.Center;
}
}
return this;
}
public override Stream Build()
{
var stream = new MemoryStream();
var renderer = new PdfDocumentRenderer(true)
{
Document = _document
};
renderer.RenderDocument();
renderer.PdfDocument.Save(stream);
return stream;
}
private void DefineStyles()
{
var style = _document.Styles.AddStyle("NormalBold", "Normal");
style.Font.Bold = true;
}
}

View File

@@ -0,0 +1,271 @@
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;
namespace TwoFromTheCasketBuisnessLogic.OfficePackage;
internal class OpenXmlExcelBuilder : BaseExcelBuilder
{
private readonly SheetData _sheetData;
private readonly MergeCells _mergeCells;
private readonly Columns _columns;
private uint _rowIndex = 0;
public OpenXmlExcelBuilder()
{
_sheetData = new SheetData();
_mergeCells = new MergeCells();
_columns = new Columns();
_rowIndex = 1;
}
public override BaseExcelBuilder AddHeader(string header, int startIndex, int count)
{
CreateCell(startIndex, _rowIndex, header, StyleIndex.BoldTextWithoutBorder);
for (int i = startIndex + 1; i < startIndex + count; ++i)
{
CreateCell(i, _rowIndex, "", StyleIndex.SimpleTextWithoutBorder);
}
_mergeCells.Append(new MergeCell()
{
Reference =
new StringValue($"{GetExcelColumnName(startIndex)}{_rowIndex}:{GetExcelColumnName(startIndex + count - 1)}{_rowIndex}")
});
_rowIndex++;
return this;
}
public override BaseExcelBuilder AddParagraph(string text, int columnIndex)
{
CreateCell(columnIndex, _rowIndex++, text, StyleIndex.SimpleTextWithoutBorder);
return this;
}
public override BaseExcelBuilder AddTable(int[] columnsWidths, List<string[]> data)
{
if (columnsWidths == null || columnsWidths.Length == 0)
{
throw new ArgumentNullException(nameof(columnsWidths));
}
if (data == null || data.Count == 0)
{
throw new ArgumentNullException(nameof(data));
}
if (data.Any(x => x.Length != columnsWidths.Length))
{
throw new InvalidOperationException("widths.Length != data.Length");
}
uint counter = 1;
int coef = 2;
_columns.Append(columnsWidths.Select(x => new Column
{
Min = counter,
Max = counter++,
Width = x * coef,
CustomWidth = true
}));
for (var j = 0; j < data.First().Length; ++j)
{
CreateCell(j, _rowIndex, data.First()[j], StyleIndex.BoldTextWithBorder);
}
_rowIndex++;
for (var i = 1; i < data.Count - 1; ++i)
{
for (var j = 0; j < data[i].Length; ++j)
{
CreateCell(j, _rowIndex, data[i][j], StyleIndex.SimpleTextWithBorder);
}
_rowIndex++;
}
for (var j = 0; j < data.Last().Length; ++j)
{
CreateCell(j, _rowIndex, data.Last()[j], StyleIndex.SimpleTextWithBorder);
}
_rowIndex++;
return this;
}
public override Stream Build()
{
var stream = new MemoryStream();
using var spreadsheetDocument = SpreadsheetDocument.Create(stream, SpreadsheetDocumentType.Workbook);
var workbookpart = spreadsheetDocument.AddWorkbookPart();
GenerateStyle(workbookpart);
workbookpart.Workbook = new Workbook();
var worksheetPart = workbookpart.AddNewPart<WorksheetPart>();
worksheetPart.Worksheet = new Worksheet();
if (_columns.HasChildren)
{
worksheetPart.Worksheet.Append(_columns);
}
worksheetPart.Worksheet.Append(_sheetData);
var sheets = spreadsheetDocument.WorkbookPart!.Workbook.AppendChild(new Sheets());
var sheet = new Sheet()
{
Id = spreadsheetDocument.WorkbookPart.GetIdOfPart(worksheetPart),
SheetId = 1,
Name = "Лист 1"
};
sheets.Append(sheet);
if (_mergeCells.HasChildren)
{
worksheetPart.Worksheet.InsertAfter(_mergeCells, worksheetPart.Worksheet.Elements<SheetData>().First());
}
return stream;
}
private static void GenerateStyle(WorkbookPart workbookPart)
{
var workbookStylesPart = workbookPart.AddNewPart<WorkbookStylesPart>();
workbookStylesPart.Stylesheet = new Stylesheet();
var fonts = new Fonts() { Count = 2, KnownFonts = BooleanValue.FromBoolean(true) };
fonts.Append(new DocumentFormat.OpenXml.Spreadsheet.Font
{
FontSize = new FontSize() { Val = 11 },
FontName = new FontName() { Val = "Calibri" },
FontFamilyNumbering = new FontFamilyNumbering() { Val = 2 },
FontScheme = new FontScheme() { Val = new EnumValue<FontSchemeValues>(FontSchemeValues.Minor) }
});
fonts.Append(new DocumentFormat.OpenXml.Spreadsheet.Font
{
FontSize = new FontSize() { Val = 11 },
FontName = new FontName() { Val = "Calibri" },
FontFamilyNumbering = new FontFamilyNumbering() { Val = 2 },
FontScheme = new FontScheme() { Val = new EnumValue<FontSchemeValues>(FontSchemeValues.Minor) },
Bold = new Bold()
});
workbookStylesPart.Stylesheet.Append(fonts);
// Default Fill
var fills = new Fills() { Count = 1 };
fills.Append(new Fill
{
PatternFill = new PatternFill() { PatternType = new EnumValue<PatternValues>(PatternValues.None) }
});
workbookStylesPart.Stylesheet.Append(fills);
// Default Border
var borders = new Borders() { Count = 2 };
borders.Append(new Border
{
LeftBorder = new LeftBorder(),
RightBorder = new RightBorder(),
TopBorder = new TopBorder(),
BottomBorder = new BottomBorder(),
DiagonalBorder = new DiagonalBorder()
});
borders.Append(new Border
{
LeftBorder = new LeftBorder() { Style = BorderStyleValues.Thin },
RightBorder = new RightBorder() { Style = BorderStyleValues.Thin },
TopBorder = new TopBorder() { Style = BorderStyleValues.Thin },
BottomBorder = new BottomBorder() { Style = BorderStyleValues.Thin }
});
workbookStylesPart.Stylesheet.Append(borders);
// Default cell format and a date cell format
var cellFormats = new CellFormats() { Count = 4 };
cellFormats.Append(new CellFormat
{
NumberFormatId = 0,
FormatId = 0,
FontId = 0,
BorderId = 0,
FillId = 0,
Alignment = new Alignment()
{
Horizontal = HorizontalAlignmentValues.Left,
Vertical = VerticalAlignmentValues.Center,
WrapText = true
}
});
cellFormats.Append(new CellFormat
{
NumberFormatId = 0,
FormatId = 0,
FontId = 0,
BorderId = 1,
FillId = 0,
Alignment = new Alignment()
{
Horizontal = HorizontalAlignmentValues.Left,
Vertical = VerticalAlignmentValues.Center,
WrapText = true
}
});
cellFormats.Append(new CellFormat
{
NumberFormatId = 0,
FormatId = 0,
FontId = 1,
BorderId = 0,
FillId = 0,
Alignment = new Alignment()
{
Horizontal = HorizontalAlignmentValues.Center,
Vertical = VerticalAlignmentValues.Center,
WrapText = true
}
});
cellFormats.Append(new CellFormat
{
NumberFormatId = 0,
FormatId = 0,
FontId = 1,
BorderId = 1,
FillId = 0,
Alignment = new Alignment()
{
Horizontal = HorizontalAlignmentValues.Center,
Vertical = VerticalAlignmentValues.Center,
WrapText = true
}
});
workbookStylesPart.Stylesheet.Append(cellFormats);
}
private enum StyleIndex
{
SimpleTextWithoutBorder = 0,
SimpleTextWithBorder = 1,
BoldTextWithoutBorder = 2,
BoldTextWithBorder = 3
}
private void CreateCell(int columnIndex, uint rowIndex, string text, StyleIndex styleIndex)
{
var columnName = GetExcelColumnName(columnIndex);
var cellReference = columnName + rowIndex;
var row = _sheetData.Elements<Row>().FirstOrDefault(r => r.RowIndex! == rowIndex);
if (row == null)
{
row = new Row() { RowIndex = rowIndex };
_sheetData.Append(row);
}
var newCell = row.Elements<Cell>()
.FirstOrDefault(c => c.CellReference != null && c.CellReference.Value == columnName + rowIndex);
if (newCell == null)
{
Cell? refCell = null;
foreach (Cell cell in row.Elements<Cell>())
{
if (cell.CellReference?.Value != null && cell.CellReference.Value.Length == cellReference.Length)
{
if (string.Compare(cell.CellReference.Value, cellReference, true) > 0)
{
refCell = cell;
break;
}
}
}
newCell = new Cell() { CellReference = cellReference };
row.InsertBefore(newCell, refCell);
}
newCell.CellValue = new CellValue(text);
newCell.DataType = CellValues.String;
newCell.StyleIndex = (uint)styleIndex;
}
private static string GetExcelColumnName(int columnNumber)
{
columnNumber += 1;
int dividend = columnNumber;
string columnName = string.Empty;
int modulo;
while (dividend > 0)
{
modulo = (dividend - 1) % 26;
columnName = Convert.ToChar(65 + modulo).ToString() + columnName;
dividend = (dividend - modulo) / 26;
}
return columnName;
}
}

View File

@@ -0,0 +1,79 @@
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
namespace TwoFromTheCasketBuisnessLogic.OfficePackage;
internal class OpenXmlWordBuilder : BaseWordBuilder
{
private readonly Document _document;
private readonly Body _body;
public OpenXmlWordBuilder()
{
_document = new Document();
_body = _document.AppendChild(new Body());
}
public override BaseWordBuilder AddHeader(string header)
{
var paragraph = _body.AppendChild(new Paragraph());
var run = paragraph.AppendChild(new Run());
run.AppendChild(new RunProperties(new Bold()));
run.AppendChild(new Text(header));
return this;
}
public override BaseWordBuilder AddParagraph(string text)
{
var paragraph = _body.AppendChild(new Paragraph());
var run = paragraph.AppendChild(new Run());
run.AppendChild(new Text(text));
return this;
}
public override BaseWordBuilder AddTable(int[] widths, List<string[]> data)
{
if (widths == null || widths.Length == 0)
{
throw new ArgumentNullException(nameof(widths));
}
if (data == null || data.Count == 0)
{
throw new ArgumentNullException(nameof(data));
}
if (data.Any(x => x.Length != widths.Length))
{
throw new InvalidOperationException("widths.Length != data.Length");
}
var table = new Table();
table.AppendChild(new TableProperties(
new TableBorders(
new TopBorder() { Val = new EnumValue<BorderValues>(BorderValues.Single), Size = 12 },
new BottomBorder() { Val = new EnumValue<BorderValues>(BorderValues.Single), Size = 12 },
new LeftBorder() { Val = new EnumValue<BorderValues>(BorderValues.Single), Size = 12 },
new RightBorder() { Val = new EnumValue<BorderValues>(BorderValues.Single), Size = 12 },
new InsideHorizontalBorder() { Val = new EnumValue<BorderValues>(BorderValues.Single), Size = 12 },
new InsideVerticalBorder() { Val = new EnumValue<BorderValues>(BorderValues.Single), Size = 12 }
)
));
// Заголовок
var tr = new TableRow();
for (var j = 0; j < widths.Length; ++j)
{
tr.Append(new TableCell(
new TableCellProperties(new TableCellWidth() { Width = widths[j].ToString() }),
new Paragraph(new Run(new RunProperties(new Bold()), new Text(data.First()[j])))));
}
table.Append(tr);
// Данные
table.Append(data.Skip(1).Select(x =>
new TableRow(x.Select(y => new TableCell(new Paragraph(new Run(new Text(y))))))));
_body.Append(table);
return this;
}
public override Stream Build()
{
var stream = new MemoryStream();
using var wordDocument = WordprocessingDocument.Create(stream, WordprocessingDocumentType.Document);
var mainPart = wordDocument.AddMainDocumentPart();
mainPart.Document = _document;
return stream;
}
}

View File

@@ -12,8 +12,11 @@
<InternalsVisibleTo Include="DynamicProxyGenAssembly2" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="DocumentFormat.OpenXml" Version="3.3.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.3" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.4" />
<PackageReference Include="PDFsharp-MigraDoc-gdi" Version="6.2.1" />
<PackageReference Include="System.Drawing.Common" Version="9.0.0" />
</ItemGroup>
<ItemGroup>

View File

@@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TwoFromTheCasketContratcs.AdapterContracts.OperationResponses;
namespace TwoFromTheCasketContratcs.AdapterContracts;
public interface IReportAdapter
{
Task<ReportOperationResponse> GetDataServicesWithHistoryAsync(DateTime dateStart, DateTime dateFinish, CancellationToken ct);
Task<ReportOperationResponse> GetDataOrderByPeriodAsync(DateTime dateStart, DateTime dateFinish, CancellationToken ct);
Task<ReportOperationResponse> GetDataSalaryByPeriodAsync(DateTime dateStart, DateTime dateFinish, CancellationToken ct);
Task<ReportOperationResponse> CreateDocumentServicesWithHistoryAsync(DateTime dateStart, DateTime dateFinish, CancellationToken ct);
Task<ReportOperationResponse> CreateDocumentOrdersByPeriodAsync(DateTime dateStart, DateTime dateFinish, CancellationToken ct);
Task<ReportOperationResponse> CreateDocumentSalaryByPeriodAsync(DateTime dateStart, DateTime dateFinish, CancellationToken ct);
}

View File

@@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TwoFromTheCasketContratcs.Infrastructure;
using TwoFromTheCasketContratcs.ViewModels;
namespace TwoFromTheCasketContratcs.AdapterContracts.OperationResponses;
public class ReportOperationResponse : OperationResponse
{
public static ReportOperationResponse OK(List<ServiceHistoryViewModel> data) => OK<ReportOperationResponse, List<ServiceHistoryViewModel>>(data);
public static ReportOperationResponse OK(List<ServiceWithHistoryViewModel> data) => OK<ReportOperationResponse, List<ServiceWithHistoryViewModel>>(data);
public static ReportOperationResponse OK(List<OrderViewModel> data) => OK<ReportOperationResponse, List<OrderViewModel>>(data);
public static ReportOperationResponse OK(List<MasterSalaryByPeriodViewModel> data) => OK<ReportOperationResponse, List<MasterSalaryByPeriodViewModel>>(data);
public static ReportOperationResponse OK(Stream data, string fileName) => OK<ReportOperationResponse, Stream>(data, fileName);
public static ReportOperationResponse BadRequest(string message) =>
BadRequest<ReportOperationResponse>(message);
public static ReportOperationResponse InternalServerError(string message) =>
InternalServerError<ReportOperationResponse>(message);
}

View File

@@ -16,5 +16,5 @@ public class PostBindingModel
public string? PostType { get; set; }
public double Salary { get; set; }
public string? ConfigurationJson { get; set; }
}

View File

@@ -7,7 +7,7 @@ using TwoFromTheCasketContratcs.DataModels;
namespace TwoFromTheCasketContratcs.BuisnessLogicsContracts;
public interface IMasterBuisnessLogicContract
internal interface IMasterBuisnessLogicContract
{
List<MasterDataModel> GetAllMasters(bool onlyActive = true);

View File

@@ -7,7 +7,7 @@ using TwoFromTheCasketContratcs.DataModels;
namespace TwoFromTheCasketContratcs.BuisnessLogicsContracts;
public interface IOrderBuisnessLogicContract
internal interface IOrderBuisnessLogicContract
{
List<OrderDataModel> GetAllOrder();

View File

@@ -7,7 +7,7 @@ using TwoFromTheCasketContratcs.DataModels;
namespace TwoFromTheCasketContratcs.BuisnessLogicsContracts;
public interface IPostBuisnessLogicContract
internal interface IPostBuisnessLogicContract
{
List<PostDataModel> GetAllPosts();

View File

@@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TwoFromTheCasketContratcs.DataModels;
namespace TwoFromTheCasketContratcs.BuisnessLogicsContracts;
internal interface IReportContract
{
Task<List<ServiceHistoryDataModel>> GetDataServiceHistoryAsync(CancellationToken ct);
Task<List<OrderDataModel>> GetDataOrderByPeriodAsync(DateTime dateStart, DateTime dateFinish, CancellationToken ct);
Task<List<MasterSalaryByPeriodDataModel>> GetDataSalaryByPeriodAsync(DateTime dateStart, DateTime dateFinish, CancellationToken ct);
Task<List<ServiceWithHistoryDataModel>> GetDataServicesWithHistoryAsync(DateTime dateStart, DateTime dateFinish, CancellationToken ct);
Task<Stream> CreateDocumentServicesWithHistoryAsync(DateTime dateStart, DateTime dateFinish, CancellationToken ct);
Task<Stream> CreateDocumentOrdersByPeriodAsync(DateTime dateStart, DateTime dateFinish, CancellationToken ct);
Task<Stream> CreateDocumentSalaryByPeriodAsync(DateTime dateStart, DateTime dateFinish, CancellationToken ct);
}

View File

@@ -7,7 +7,7 @@ using TwoFromTheCasketContratcs.DataModels;
namespace TwoFromTheCasketContratcs.BuisnessLogicsContracts;
public interface ISalaryBuisnessLogicContract
internal interface ISalaryBuisnessLogicContract
{
List<SalaryDataModel> GetAllSalariesByPeriod(DateTime fromDate, DateTime toDate);

View File

@@ -8,7 +8,7 @@ using TwoFromTheCasketContratcs.Enums;
namespace TwoFromTheCasketContratcs.BuisnessLogicsContracts;
public interface IServiceBuisnessLogicContract
internal interface IServiceBuisnessLogicContract
{
List<ServiceDataModel> GetAllServices(bool onlyActive);

View File

@@ -9,10 +9,12 @@ using TwoFromTheCasketContratcs.Extensions;
using TwoFromTheCasketContratcs.Infrastructure;
using TwoFromTheCasketContratcs.Exceptions;
using System.Text.RegularExpressions;
using Microsoft.Extensions.Localization;
using TwoFromTheCasketContratcs.Resources;
namespace TwoFromTheCasketContratcs.DataModels;
public class MasterDataModel(string id, string fio, string postId, DateTime birthDate, DateTime employmentDate, bool isDeleted) : IValidation
internal class MasterDataModel(string id, string fio, string postId, DateTime birthDate, DateTime employmentDate, bool isDeleted) : IValidation
{
public string Id { get; private set; } = id;
@@ -20,41 +22,41 @@ public class MasterDataModel(string id, string fio, string postId, DateTime birt
public string PostId { get; private set; } = postId;
public DateTime BirthDate { get; private set; } = birthDate;
public DateTime BirthDate { get; private set; } = birthDate.ToUniversalTime();
public DateTime EmploymentDate { get; private set; } = employmentDate;
public DateTime EmploymentDate { get; private set; } = employmentDate.ToUniversalTime();
public bool IsDeleted { get; private set; } = isDeleted;
public void Validate()
public void Validate(IStringLocalizer<Messages> localazier)
{
if (Id.IsEmpty())
throw new ValidationException("Field Id is empty");
throw new ValidationException(string.Format(localazier["ValidationExceptionMessageEmptyField"], "Id"));
if (!Id.IsGuid())
throw new ValidationException("The value in the field Id is not a unique identifier");
throw new ValidationException(string.Format(localazier["ValidationExceptionMessageIncorrectField"], "Id"));
if (!Regex.IsMatch(FIO, @"^[А-ЯЁA-Z][а-яёa-z]*(?:-[А-ЯЁA-Z][а-яёa-z]*)?\s[А-ЯЁA-Z][а-яёa-z]*(?:\s[А-ЯЁA-Z][а-яёa-z]*)?$"))
throw new ValidationException("Field FIO is not FIO");
throw new ValidationException(string.Format(localazier["ValidationExceptionMessageIncorrectFIO"]));
if (PostId.IsEmpty())
throw new ValidationException("Field PostId is empty");
throw new ValidationException(string.Format(localazier["ValidationExceptionMessageEmptyField"], "PostId"));
if (!PostId.IsGuid())
throw new ValidationException("The value in the field PostId is not a unique identifier");
throw new ValidationException(string.Format(localazier["ValidationExceptionMessageIncorrectField"], "PostId"));
if (BirthDate.Date > DateTime.Now.AddYears(-16).Date)
throw new ValidationException($"Minors cannot be hired (BirthDate = {BirthDate.ToShortDateString()})");
throw new ValidationException(string.Format(localazier["ValidationExceptionMessageMinorCannotBeHired"], BirthDate.ToShortDateString()));
if (EmploymentDate.Date < BirthDate.Date)
throw new ValidationException("The date of employment cannot be less than the date of birth");
throw new ValidationException(localazier["ValidationExceptionMessageEmploymentDateBeforeBirthDate"]);
if ((EmploymentDate - BirthDate).TotalDays / 365 < 16)
throw new ValidationException($"Minors cannot be hired (EmploymentDate - {EmploymentDate.ToShortDateString()}, BirthDate - {BirthDate.ToShortDateString()})");
throw new ValidationException(string.Format(localazier["ValidationExceptionMessageMinorAgeAtEmployment"], EmploymentDate.ToShortDateString(), BirthDate.ToShortDateString()));
}
}

View File

@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TwoFromTheCasketContratcs.DataModels;
public class MasterSalaryByPeriodDataModel
{
public required string MasterFIO { get; set; }
public double TotalSalary { get; set; }
public DateTime FromPeriod { get; set; }
public DateTime ToPeriod { get; set; }
}

View File

@@ -0,0 +1,11 @@
namespace TwoFromTheCasketContratcs.DataModels;
public class MasterWithHistoryDataModel
{
public string Id { get; set; } = string.Empty;
public string FIO { get; set; } = string.Empty;
public DateTime EmploymentDate { get; set; }
public bool IsDeleted { get; set; }
public int OrdersCount { get; set; }
}

View File

@@ -1,4 +1,5 @@
using System;
using Microsoft.Extensions.Localization;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
@@ -8,34 +9,35 @@ using TwoFromTheCasketContratcs.Enums;
using TwoFromTheCasketContratcs.Exceptions;
using TwoFromTheCasketContratcs.Extensions;
using TwoFromTheCasketContratcs.Infrastructure;
using TwoFromTheCasketContratcs.Resources;
namespace TwoFromTheCasketContratcs.DataModels;
public class OrderDataModel( string id, DateTime data, StatusType status, RoomType roomType) : IValidation
internal class OrderDataModel( string id, DateTime data, StatusType status, RoomType roomType) : IValidation
{
public string Id { get; private set; } = id;
public DateTime Date { get; private set; } = data;
public DateTime Date { get; private set; } = data.ToUniversalTime();
public StatusType Status { get; private set; } = status;
public RoomType RoomType { get; private set; } = roomType;
public void Validate()
public void Validate(IStringLocalizer<Messages> localazier)
{
if (Id.IsEmpty())
throw new ValidationException("Field Id is empty");
throw new ValidationException(string.Format(localazier["ValidationExceptionMessageEmptyField"], "Id"));
if (!Id.IsGuid())
throw new ValidationException("The value in the field Id is not a unique identifier");
throw new ValidationException(string.Format(localazier["ValidationExceptionMessageIncorrectField"], "Id"));
if (Date == default)
throw new ValidationException("Field Date is empty");
throw new ValidationException(string.Format(localazier["ValidationExceptionMessageFieldIsDefault"], "Date"));
if (Status == StatusType.None)
throw new ValidationException("Field Status is empty");
throw new ValidationException(string.Format(localazier["ValidationExceptionMessageFieldIsNone"], "Status"));
if (RoomType == RoomType.None)
throw new ValidationException("Field RoomType is empty");
throw new ValidationException(string.Format(localazier["ValidationExceptionMessageFieldIsNone"], "RoomType"));
}
}

View File

@@ -1,4 +1,7 @@
using System;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@@ -8,11 +11,14 @@ using TwoFromTheCasketContratcs.Enums;
using TwoFromTheCasketContratcs.Exceptions;
using TwoFromTheCasketContratcs.Extensions;
using TwoFromTheCasketContratcs.Infrastructure;
using TwoFromTheCasketContratcs.Infrastructure.PostConfigurations;
using Microsoft.Extensions.Localization;
using TwoFromTheCasketContratcs.Resources;
namespace TwoFromTheCasketContratcs.DataModels;
public class PostDataModel(string postId, string postName, PostType
postType, double salary) : IValidation
internal class PostDataModel(string postId, string postName, PostType
postType, PostConfiguration configuration) : IValidation
{
public string Id { get; private set; } = postId;
@@ -20,27 +26,46 @@ postType, double salary) : IValidation
public PostType PostType { get; private set; } = postType;
public double Salary { get; private set; } = salary;
public PostConfiguration ConfigurationModel { get; private set; } = configuration;
public void Validate()
public PostDataModel(string postId, string postName, PostType postType, string configurationJson) : this(postId,
postName, postType, new PostConfiguration())
{
var obj = JToken.Parse(configurationJson);
if (obj is not null)
{
ConfigurationModel = obj.Value<string>("Type") switch
{
nameof(CarpenterPostConfiguration) => JsonConvert.DeserializeObject<CarpenterPostConfiguration>(
configurationJson)!,
nameof(PainterPostConfiguration) => JsonConvert
.DeserializeObject<PainterPostConfiguration>(configurationJson)!,
nameof(PlastererPostConfiguration) => JsonConvert.DeserializeObject<PlastererPostConfiguration>(
configurationJson)!,
_ => JsonConvert.DeserializeObject<PostConfiguration>(configurationJson)!,
};
}
}
public void Validate(IStringLocalizer<Messages> localazier)
{
if (Id.IsEmpty())
throw new ValidationException("Field Id is empty");
throw new ValidationException(string.Format(localazier["ValidationExceptionMessageEmptyField"], "Id"));
if (!Id.IsGuid())
throw new ValidationException("The value in the field Id is not a unique identifier");
throw new ValidationException(string.Format(localazier["ValidationExceptionMessageIncorrectField"], "Id"));
if (PostName.IsEmpty())
throw new ValidationException("Field PostName is empty");
throw new ValidationException(string.Format(localazier["ValidationExceptionMessageEmptyField"], "PostName"));
if (PostType == PostType.None)
throw new ValidationException("Field PostType is empty");
throw new ValidationException(string.Format(localazier["ValidationExceptionMessageFieldIsNone"], "PostType"));
if (Salary <= 0)
throw new ValidationException("Field Salary is empty");
if (ConfigurationModel is null)
throw new ValidationException(string.Format(localazier["ValidationExceptionMessageFieldNotInitialized"], "ConfigurationModel"));
if (ConfigurationModel!.Rate <=0 )
throw new ValidationException(string.Format(localazier["ValidationExceptionMessageFieldLessOrEqualZero"], "Rate"));
}
}

View File

@@ -1,4 +1,5 @@
using System;
using Microsoft.Extensions.Localization;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@@ -6,28 +7,29 @@ using System.Threading.Tasks;
using TwoFromTheCasketContratcs.Exceptions;
using TwoFromTheCasketContratcs.Extensions;
using TwoFromTheCasketContratcs.Infrastructure;
using TwoFromTheCasketContratcs.Resources;
namespace TwoFromTheCasketContratcs.DataModels;
public class SalaryDataModel(string masterId, DateTime salaryDate, double masterSalary, double prize) : IValidation
internal class SalaryDataModel(string masterId, DateTime salaryDate, double masterSalary, double prize) : IValidation
{
public string MasterId { get; private set; } = masterId;
public DateTime SalaryDate { get; private set; } = salaryDate;
public DateTime SalaryDate { get; private set; } = salaryDate.ToUniversalTime();
public double Salary { get; private set; } = masterSalary;
public double Prize { get; private set; } = prize;
public void Validate()
public void Validate(IStringLocalizer<Messages> localazier)
{
if (MasterId.IsEmpty())
throw new ValidationException("Field MasterId is empty");
throw new ValidationException(string.Format(localazier["ValidationExceptionMessageEmptyField"], "MasterId"));
if (!MasterId.IsGuid())
throw new ValidationException("The value in the field MasterId is not a unique identifier");
throw new ValidationException(string.Format(localazier["ValidationExceptionMessageIncorrectField"], "MasterId"));
if (Salary <= 0)
throw new ValidationException("Field Salary is less than or equal to 0");
throw new ValidationException(string.Format(localazier["ValidationExceptionMessageFieldLessOrEqualZero"], "Salary"));
}
}

View File

@@ -1,4 +1,5 @@
using System;
using Microsoft.Extensions.Localization;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@@ -7,10 +8,11 @@ using TwoFromTheCasketContratcs.Enums;
using TwoFromTheCasketContratcs.Exceptions;
using TwoFromTheCasketContratcs.Extensions;
using TwoFromTheCasketContratcs.Infrastructure;
using TwoFromTheCasketContratcs.Resources;
namespace TwoFromTheCasketContratcs.DataModels;
public class ServiceDataModel(string id, string serviceName, ServiceType serviceType, string masterID, double price, bool isDeleted) : IValidation
internal class ServiceDataModel(string id, string serviceName, ServiceType serviceType, string masterID, double price, bool isDeleted) : IValidation
{
public string Id { get; private set; } = id;
@@ -24,30 +26,30 @@ public class ServiceDataModel(string id, string serviceName, ServiceType service
public bool IsDeleted { get; private set; } = isDeleted;
public void Validate()
public void Validate(IStringLocalizer<Messages> localazier)
{
if (Id.IsEmpty())
throw new ValidationException("Field Id is empty");
throw new ValidationException(string.Format(localazier["ValidationExceptionMessageEmptyField"], "Id"));
if (!Id.IsGuid())
throw new ValidationException("The value in the field Id is not a unique identifier");
throw new ValidationException(string.Format(localazier["ValidationExceptionMessageIncorrectField"], "Id"));
if (ServiceName.IsEmpty())
throw new ValidationException("Field ServiceName is empty");
throw new ValidationException(string.Format(localazier["ValidationExceptionMessageEmptyField"], "ServiceName"));
if (ServiceType == ServiceType.None)
throw new ValidationException("Field ServiceType is empty");
throw new ValidationException(string.Format(localazier["ValidationExceptionMessageFieldIsNone"], "ServiceType"));
if (MasterId.IsEmpty())
throw new ValidationException("Field MasterId is empty");
throw new ValidationException(string.Format(localazier["ValidationExceptionMessageEmptyField"], "MasterId"));
if (!MasterId.IsGuid())
throw new ValidationException("The value in the field MasterId is not a unique identifier");
throw new ValidationException(string.Format(localazier["ValidationExceptionMessageIncorrectField"], "MasterId"));
if (Price <= 0)
throw new ValidationException("Field Price is less than or equal to 0");
throw new ValidationException(string.Format(localazier["ValidationExceptionMessageFieldLessOrEqualZero"], "Price"));
}
}

View File

@@ -1,4 +1,5 @@
using System;
using Microsoft.Extensions.Localization;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@@ -6,10 +7,11 @@ using System.Threading.Tasks;
using TwoFromTheCasketContratcs.Exceptions;
using TwoFromTheCasketContratcs.Extensions;
using TwoFromTheCasketContratcs.Infrastructure;
using TwoFromTheCasketContratcs.Resources;
namespace TwoFromTheCasketContratcs.DataModels;
public class ServiceHistoryDataModel(string serviceId, double oldPrice) :
internal class ServiceHistoryDataModel(string serviceId, double oldPrice) :
IValidation
{
public string ServiceId { get; private set; } = serviceId;
@@ -18,16 +20,16 @@ IValidation
public DateTime ChangeDate { get; private set; } = DateTime.UtcNow;
public void Validate()
public void Validate(IStringLocalizer<Messages> localazier)
{
if (ServiceId.IsEmpty())
throw new ValidationException("Field ServiceId is empty");
throw new ValidationException(string.Format(localazier["ValidationExceptionMessageEmptyField"], "ServiceId"));
if (!ServiceId.IsGuid())
throw new ValidationException("The value in the field ServiceId is not a unique identifier");
throw new ValidationException(string.Format(localazier["ValidationExceptionMessageIncorrectField"], "ServiceId"));
if (OldPrice <= 0)
throw new ValidationException("Field OldPrice is less than or equal to 0");
throw new ValidationException(string.Format(localazier["ValidationExceptionMessageFieldLessOrEqualZero"], "OldPrice"));
}
}

View File

@@ -1,4 +1,5 @@
using System;
using Microsoft.Extensions.Localization;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@@ -6,10 +7,11 @@ using System.Threading.Tasks;
using TwoFromTheCasketContratcs.Exceptions;
using TwoFromTheCasketContratcs.Extensions;
using TwoFromTheCasketContratcs.Infrastructure;
using TwoFromTheCasketContratcs.Resources;
namespace TwoFromTheCasketContratcs.DataModels;
public class ServiceOrderDataModel(string orderId, string serviceId, string masterId, int timeOfWorking) : IValidation
internal class ServiceOrderDataModel(string orderId, string serviceId, string masterId, int timeOfWorking) : IValidation
{
public string OrderId { get; private set; } = orderId;
@@ -19,35 +21,35 @@ public class ServiceOrderDataModel(string orderId, string serviceId, string mast
public int TimeOfWorking { get; private set; }= timeOfWorking;
public void Validate()
public void Validate(IStringLocalizer<Messages> localazier)
{
if (OrderId.IsEmpty())
{
throw new ValidationException("Field OrderId is empty");
throw new ValidationException(string.Format(localazier["ValidationExceptionMessageEmptyField"], "OrderId"));
}
if (!OrderId.IsGuid())
{
throw new ValidationException("The value in the field OrderId is not a unique identifier");
throw new ValidationException(string.Format(localazier["ValidationExceptionMessageIncorrectField"], "OrderId"));
}
if (ServiceId.IsEmpty())
{
throw new ValidationException("Field ServiceId is empty");
throw new ValidationException(string.Format(localazier["ValidationExceptionMessageEmptyField"], "ServiceId"));
}
if (!ServiceId.IsGuid())
{
throw new ValidationException("The value in the field ServiceId is not a unique identifier");
throw new ValidationException(string.Format(localazier["ValidationExceptionMessageIncorrectField"], "ServiceId"));
}
if (MasterId.IsEmpty())
{
throw new ValidationException("Field MasterId is empty");
throw new ValidationException(string.Format(localazier["ValidationExceptionMessageEmptyField"], "MasterId"));
}
if (!MasterId.IsGuid())
{
throw new ValidationException("The value in the field MasterId is not a unique identifier");
throw new ValidationException(string.Format(localazier["ValidationExceptionMessageIncorrectField"], "MasterId"));
}
if (TimeOfWorking == 0)
{
throw new ValidationException("Field TimeOfWorking is less than or equal to 0");
throw new ValidationException(string.Format(localazier["ValidationExceptionMessageFieldIsZero"], "TimeOfWorking"));
}
}
}

View File

@@ -0,0 +1,15 @@
using TwoFromTheCasketContratcs.Enums;
namespace TwoFromTheCasketContratcs.DataModels;
internal class ServiceWithHistoryDataModel
{
public string Id { get; set; } = string.Empty;
public string ServiceName { get; set; } = string.Empty;
public ServiceType ServiceType { get; set; }
public double Price { get; set; }
public string MasterId { get; set; } = string.Empty;
public DateTime CreatedAt { get; set; }
public bool IsDeleted { get; set; }
public List<ServiceHistoryDataModel> History { get; set; } = new();
}

View File

@@ -3,11 +3,12 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.Localization;
using TwoFromTheCasketContratcs.Resources;
namespace TwoFromTheCasketContratcs.Exceptions;
public class ElementDeletedException : Exception
{
public ElementDeletedException(string id) : base($"Cannot modify a deleteditem(id: { id})") { }
internal class ElementDeletedException(string id, IStringLocalizer<Messages> localizer) :
Exception(string.Format(localizer["ElementDeletedExceptionMessage"].Value, id))
{ }
}

View File

@@ -3,16 +3,15 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.Localization;
using TwoFromTheCasketContratcs.Resources;
namespace TwoFromTheCasketContratcs.Exceptions;
public class ElementExistsException : Exception
internal class ElementExistsException(string paramName, string paramValue, IStringLocalizer<Messages> localizer) :
Exception(string.Format(localizer["ElementExistsExceptionMessage"].Value, paramValue, paramName))
{
public string ParamName { get; private set; }
public string ParamValue { get; private set; }
public ElementExistsException(string paramName, string paramValue) : base($"There is alredy an element with value {paramValue} of parameter {paramName}")
{
ParamName = paramName;
ParamValue = paramValue;
}
public string ParamName { get; private set; } = paramName;
public string ParamValue { get; private set; } = paramValue;
}

View File

@@ -3,12 +3,13 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.Localization;
using TwoFromTheCasketContratcs.Resources;
namespace TwoFromTheCasketContratcs.Exceptions;
public class ElementNotFoundException : Exception
internal class ElementNotFoundException(string value, IStringLocalizer<Messages> localizer) :
Exception(string.Format(localizer["ElementNotFoundExceptionMessage"].Value, value))
{
public string Value { get; private set; }
public ElementNotFoundException(string value) : base($"Element not found at value = {value}") { Value = value; }
public string Value { get; private set; } = value;
}

View File

@@ -4,10 +4,11 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static System.Runtime.InteropServices.JavaScript.JSType;
using Microsoft.Extensions.Localization;
using TwoFromTheCasketContratcs.Resources;
namespace TwoFromTheCasketContratcs.Exceptions;
public class IncorrectDatesException : Exception
{
public IncorrectDatesException(DateTime start, DateTime end) : base($"The end date must be later than the start date..StartDate: { start: dd.MM.YYYY}. EndDate: {end:dd.MM.YYYY}") { }
}
internal class IncorrectDatesException(DateTime start, DateTime end, IStringLocalizer<Messages> localizer) :
Exception(string.Format(localizer["IncorrectDatesExceptionMessage"].Value, start.ToShortDateString(), end.ToShortDateString()))
{ }

View File

@@ -1,12 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TwoFromTheCasketContratcs.Exceptions;
public class NullListException : Exception
{
public NullListException() : base("The returned list is null") { }
}

View File

@@ -3,10 +3,11 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.Localization;
using TwoFromTheCasketContratcs.Resources;
namespace TwoFromTheCasketContratcs.Exceptions;
public class StorageException : Exception
{
public StorageException(Exception ex) : base($"Error while working in storage: {ex.Message}", ex) { }
}
internal class StorageException(Exception ex, IStringLocalizer<Messages> localizer) :
Exception(string.Format(localizer["StorageExceptionMessage"].Value, ex.Message), ex)
{ }

View File

@@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TwoFromTheCasketContratcs.Infrastructure;
public interface IConfigurationSalary
{
double ExtraSaleSum { get; }
double ExtraInstallationSum { get; }
int MaxThreads { get; }
}

View File

@@ -1,12 +1,14 @@
using System;
using Microsoft.Extensions.Localization;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TwoFromTheCasketContratcs.Resources;
namespace TwoFromTheCasketContratcs.Infrastructure;
public interface IValidation
internal interface IValidation
{
void Validate();
void Validate(IStringLocalizer<Messages> localazier);
}

View File

@@ -15,6 +15,8 @@ public class OperationResponse
protected object? Result { get; set; }
protected string? FileName { get; set; }
public IActionResult GetResponse(HttpRequest request, HttpResponse response)
{
ArgumentNullException.ThrowIfNull(request);
@@ -32,6 +34,8 @@ public class OperationResponse
where TResult : OperationResponse, new() =>
new() { StatusCode = HttpStatusCode.OK, Result = data };
protected static TResult OK<TResult, TData>(TData data, string fileName) where TResult : OperationResponse, new() => new() { StatusCode = HttpStatusCode.OK, Result = data, FileName = fileName };
protected static TResult NoContent<TResult>()
where TResult : OperationResponse, new() =>
new() { StatusCode = HttpStatusCode.NoContent };

View File

@@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TwoFromTheCasketContratcs.Infrastructure.PostConfigurations;
public class CarpenterPostConfiguration : PostConfiguration
{
public override string Type => nameof(CarpenterPostConfiguration);
public double BonusForExtraCarpentry { get; set; }
}

View File

@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TwoFromTheCasketContratcs.Infrastructure.PostConfigurations;
public class PainterPostConfiguration : PostConfiguration
{
public override string Type => nameof(PainterPostConfiguration);
public double PainterPercent { get; set; }
public double BonusForExtraPainter { get; set; }
}

View File

@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TwoFromTheCasketContratcs.Infrastructure.PostConfigurations;
public class PlastererPostConfiguration : PostConfiguration
{
public override string Type => nameof(PlastererPostConfiguration);
public double PlastererPercent { get; set; }
public double BonusForExtraPlasterer { get; set; }
}

View File

@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TwoFromTheCasketContratcs.Infrastructure.PostConfigurations;
public class PostConfiguration
{
public virtual string Type => nameof(PostConfiguration);
public double Rate { get; set; }
public string CutleryName { get; set; } = CultureInfo.CurrentCulture.Name;
}

View File

@@ -0,0 +1,783 @@
//------------------------------------------------------------------------------
// <auto-generated>
// Этот код создан программой.
// Исполняемая версия:4.0.30319.42000
//
// Изменения в этом файле могут привести к неправильной работе и будут потеряны в случае
// повторной генерации кода.
// </auto-generated>
//------------------------------------------------------------------------------
namespace TwoFromTheCasketContratcs.Resources {
using System;
/// <summary>
/// Класс ресурса со строгой типизацией для поиска локализованных строк и т.д.
/// </summary>
// Этот класс создан автоматически классом StronglyTypedResourceBuilder
// с помощью такого средства, как ResGen или Visual Studio.
// Чтобы добавить или удалить член, измените файл .ResX и снова запустите ResGen
// с параметром /str или перестройте свой проект VS.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Messages {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Messages() {
}
/// <summary>
/// Возвращает кэшированный экземпляр ResourceManager, использованный этим классом.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("TwoFromTheCasketContratcs.Resources.Messages", typeof(Messages).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Перезаписывает свойство CurrentUICulture текущего потока для всех
/// обращений к ресурсу с помощью этого класса ресурса со строгой типизацией.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Данные пусты.
/// </summary>
internal static string AdapterMessageDataIsEmpty {
get {
return ResourceManager.GetString("AdapterMessageDataIsEmpty", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Элемент не найден: {0}.
/// </summary>
internal static string AdapterMessageElementNotFound {
get {
return ResourceManager.GetString("AdapterMessageElementNotFound", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Элемент с идентификатором {0} был удален.
/// </summary>
internal static string AdapterMessageElementWasDeleted {
get {
return ResourceManager.GetString("AdapterMessageElementWasDeleted", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Элемент с данными {0} был удален.
/// </summary>
internal static string AdapterMessageElementWasDeletedByData {
get {
return ResourceManager.GetString("AdapterMessageElementWasDeletedByData", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Ошибка при работе с хранилищем данных: {0}.
/// </summary>
internal static string AdapterMessageErrorWhileWorkingWithStorage {
get {
return ResourceManager.GetString("AdapterMessageErrorWhileWorkingWithStorage", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Идентификатор пуст.
/// </summary>
internal static string AdapterMessageIdIsEmpty {
get {
return ResourceManager.GetString("AdapterMessageIdIsEmpty", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Переданы некорректные данные: {0}.
/// </summary>
internal static string AdapterMessageIncorrectDataTransmitted {
get {
return ResourceManager.GetString("AdapterMessageIncorrectDataTransmitted", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Некорректные даты: {0}.
/// </summary>
internal static string AdapterMessageIncorrectDates {
get {
return ResourceManager.GetString("AdapterMessageIncorrectDates", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Список не инициализирован.
/// </summary>
internal static string AdapterMessageListNotInitialized {
get {
return ResourceManager.GetString("AdapterMessageListNotInitialized", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Элемент не найден по данным {0}.
/// </summary>
internal static string AdapterMessageNotFoundElementByData {
get {
return ResourceManager.GetString("AdapterMessageNotFoundElementByData", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Элемент не найден по идентификатору {0}.
/// </summary>
internal static string AdapterMessageNotFoundElementById {
get {
return ResourceManager.GetString("AdapterMessageNotFoundElementById", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Дата.
/// </summary>
internal static string DocumentDocCaptionDate {
get {
return ResourceManager.GetString("DocumentDocCaptionDate", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Дата трудоустройства.
/// </summary>
internal static string DocumentDocEmploymentDate {
get {
return ResourceManager.GetString("DocumentDocEmploymentDate", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Отчёт сформирован: {0}.
/// </summary>
internal static string DocumentDocGeneratedOn {
get {
return ResourceManager.GetString("DocumentDocGeneratedOn", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Отчет по мастерам.
/// </summary>
internal static string DocumentDocHeader {
get {
return ResourceManager.GetString("DocumentDocHeader", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на ФИО мастера.
/// </summary>
internal static string DocumentDocMasterFIO {
get {
return ResourceManager.GetString("DocumentDocMasterFIO", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на За указанный период мастера не найдены..
/// </summary>
internal static string DocumentDocNoMastersFound {
get {
return ResourceManager.GetString("DocumentDocNoMastersFound", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Количество заказов.
/// </summary>
internal static string DocumentDocOrdersCount {
get {
return ResourceManager.GetString("DocumentDocOrdersCount", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Период: с {0} по {1}.
/// </summary>
internal static string DocumentDocPeriodFromTo {
get {
return ResourceManager.GetString("DocumentDocPeriodFromTo", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Статус.
/// </summary>
internal static string DocumentDocStatus {
get {
return ResourceManager.GetString("DocumentDocStatus", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Уволен.
/// </summary>
internal static string DocumentDocStatusFired {
get {
return ResourceManager.GetString("DocumentDocStatusFired", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Работает.
/// </summary>
internal static string DocumentDocStatusWorking {
get {
return ResourceManager.GetString("DocumentDocStatusWorking", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Количество.
/// </summary>
internal static string DocumentExcelCaptionCount {
get {
return ResourceManager.GetString("DocumentExcelCaptionCount", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Заказ.
/// </summary>
internal static string DocumentExcelCaptionOrder {
get {
return ResourceManager.GetString("DocumentExcelCaptionOrder", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Услуга.
/// </summary>
internal static string DocumentExcelCaptionService {
get {
return ResourceManager.GetString("DocumentExcelCaptionService", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Сумма.
/// </summary>
internal static string DocumentExcelCaptionSum {
get {
return ResourceManager.GetString("DocumentExcelCaptionSum", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Дата заказа.
/// </summary>
internal static string DocumentExcelOrderDate {
get {
return ResourceManager.GetString("DocumentExcelOrderDate", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на ID заказа.
/// </summary>
internal static string DocumentExcelOrderId {
get {
return ResourceManager.GetString("DocumentExcelOrderId", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Заказы за период.
/// </summary>
internal static string DocumentExcelOrdersByPeriod {
get {
return ResourceManager.GetString("DocumentExcelOrdersByPeriod", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на с {0} по {1}.
/// </summary>
internal static string DocumentExcelPeriodFromToShort {
get {
return ResourceManager.GetString("DocumentExcelPeriodFromToShort", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Тип помещения.
/// </summary>
internal static string DocumentExcelRoomType {
get {
return ResourceManager.GetString("DocumentExcelRoomType", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Начисления.
/// </summary>
internal static string DocumentPdfAccruals {
get {
return ResourceManager.GetString("DocumentPdfAccruals", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на за период с {0} по {1}.
/// </summary>
internal static string DocumentPdfSalaryPeriodFromTo {
get {
return ResourceManager.GetString("DocumentPdfSalaryPeriodFromTo", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Зарплатная ведомость.
/// </summary>
internal static string DocumentPdfSalaryStatement {
get {
return ResourceManager.GetString("DocumentPdfSalaryStatement", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Неизвестный мастер.
/// </summary>
internal static string DocumentPdfUnknownMaster {
get {
return ResourceManager.GetString("DocumentPdfUnknownMaster", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Нельзя изменить удаленный элемент (id: {0}).
/// </summary>
internal static string ElementDeletedExceptionMessage {
get {
return ResourceManager.GetString("ElementDeletedExceptionMessage", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Элемент со значением {0} параметра {1} уже существует.
/// </summary>
internal static string ElementExistsExceptionMessage {
get {
return ResourceManager.GetString("ElementExistsExceptionMessage", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Элемент не найден со значением = {0}.
/// </summary>
internal static string ElementNotFoundExceptionMessage {
get {
return ResourceManager.GetString("ElementNotFoundExceptionMessage", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Дата окончания должна быть позже даты начала. Дата начала: {0}. Дата окончания: {1}.
/// </summary>
internal static string IncorrectDatesExceptionMessage {
get {
return ResourceManager.GetString("IncorrectDatesExceptionMessage", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Заказы за период.
/// </summary>
internal static string ReportOrdersHeader {
get {
return ResourceManager.GetString("ReportOrdersHeader", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на ч..
/// </summary>
internal static string ReportOrdersHours {
get {
return ResourceManager.GetString("ReportOrdersHours", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Нет услуг.
/// </summary>
internal static string ReportOrdersNoServices {
get {
return ResourceManager.GetString("ReportOrdersNoServices", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Не назначен.
/// </summary>
internal static string ReportOrdersNotAssigned {
get {
return ResourceManager.GetString("ReportOrdersNotAssigned", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на с {0} по {1}.
/// </summary>
internal static string ReportOrdersPeriod {
get {
return ResourceManager.GetString("ReportOrdersPeriod", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Сумма.
/// </summary>
internal static string ReportOrdersTableAmount {
get {
return ResourceManager.GetString("ReportOrdersTableAmount", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Мастер.
/// </summary>
internal static string ReportOrdersTableMaster {
get {
return ResourceManager.GetString("ReportOrdersTableMaster", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Дата заказа.
/// </summary>
internal static string ReportOrdersTableOrderDate {
get {
return ResourceManager.GetString("ReportOrdersTableOrderDate", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Тип помещения.
/// </summary>
internal static string ReportOrdersTableRoomType {
get {
return ResourceManager.GetString("ReportOrdersTableRoomType", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Услуга.
/// </summary>
internal static string ReportOrdersTableService {
get {
return ResourceManager.GetString("ReportOrdersTableService", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Статус.
/// </summary>
internal static string ReportOrdersTableStatus {
get {
return ResourceManager.GetString("ReportOrdersTableStatus", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Время работы.
/// </summary>
internal static string ReportOrdersTableWorkTime {
get {
return ResourceManager.GetString("ReportOrdersTableWorkTime", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Начисления.
/// </summary>
internal static string ReportSalaryAccruals {
get {
return ResourceManager.GetString("ReportSalaryAccruals", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Зарплатная ведомость.
/// </summary>
internal static string ReportSalaryHeader {
get {
return ResourceManager.GetString("ReportSalaryHeader", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на за период с {0} по {1}.
/// </summary>
internal static string ReportSalaryPeriod {
get {
return ResourceManager.GetString("ReportSalaryPeriod", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Сумма.
/// </summary>
internal static string ReportSalaryTableAmount {
get {
return ResourceManager.GetString("ReportSalaryTableAmount", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Дата.
/// </summary>
internal static string ReportSalaryTableDate {
get {
return ResourceManager.GetString("ReportSalaryTableDate", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Мастер.
/// </summary>
internal static string ReportSalaryTableMaster {
get {
return ResourceManager.GetString("ReportSalaryTableMaster", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Неизвестный мастер.
/// </summary>
internal static string ReportSalaryUnknownMaster {
get {
return ResourceManager.GetString("ReportSalaryUnknownMaster", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Отчёт сформирован: {0}.
/// </summary>
internal static string ReportServicesGenerated {
get {
return ResourceManager.GetString("ReportServicesGenerated", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Отчет по услугам и их истории изменений.
/// </summary>
internal static string ReportServicesHeader {
get {
return ResourceManager.GetString("ReportServicesHeader", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на —.
/// </summary>
internal static string ReportServicesNoChanges {
get {
return ResourceManager.GetString("ReportServicesNoChanges", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на За указанный период услуги не найдены..
/// </summary>
internal static string ReportServicesNoData {
get {
return ResourceManager.GetString("ReportServicesNoData", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Период: с {0} по {1}.
/// </summary>
internal static string ReportServicesPeriod {
get {
return ResourceManager.GetString("ReportServicesPeriod", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Дата изменения.
/// </summary>
internal static string ReportServicesTableChangeDate {
get {
return ResourceManager.GetString("ReportServicesTableChangeDate", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Текущая цена.
/// </summary>
internal static string ReportServicesTableCurrentPrice {
get {
return ResourceManager.GetString("ReportServicesTableCurrentPrice", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Старая цена.
/// </summary>
internal static string ReportServicesTableOldPrice {
get {
return ResourceManager.GetString("ReportServicesTableOldPrice", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Услуга.
/// </summary>
internal static string ReportServicesTableService {
get {
return ResourceManager.GetString("ReportServicesTableService", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Тип.
/// </summary>
internal static string ReportServicesTableType {
get {
return ResourceManager.GetString("ReportServicesTableType", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Ошибка при работе с хранилищем: {0}.
/// </summary>
internal static string StorageExceptionMessage {
get {
return ResourceManager.GetString("StorageExceptionMessage", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Дата трудоустройства не может быть раньше даты рождения.
/// </summary>
internal static string ValidationExceptionMessageEmploymentDateBeforeBirthDate {
get {
return ResourceManager.GetString("ValidationExceptionMessageEmploymentDateBeforeBirthDate", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Значение поле {0} пусто.
/// </summary>
internal static string ValidationExceptionMessageEmptyField {
get {
return ResourceManager.GetString("ValidationExceptionMessageEmptyField", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Поле {0} имеет значение по умолчанию.
/// </summary>
internal static string ValidationExceptionMessageFieldIsDefault {
get {
return ResourceManager.GetString("ValidationExceptionMessageFieldIsDefault", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Поле {0} имеет значение None.
/// </summary>
internal static string ValidationExceptionMessageFieldIsNone {
get {
return ResourceManager.GetString("ValidationExceptionMessageFieldIsNone", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Значение поля {0} равно нулю.
/// </summary>
internal static string ValidationExceptionMessageFieldIsZero {
get {
return ResourceManager.GetString("ValidationExceptionMessageFieldIsZero", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Значение поля {0} меньше или равно нулю.
/// </summary>
internal static string ValidationExceptionMessageFieldLessOrEqualZero {
get {
return ResourceManager.GetString("ValidationExceptionMessageFieldLessOrEqualZero", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Поле {0} не инициализировано.
/// </summary>
internal static string ValidationExceptionMessageFieldNotInitialized {
get {
return ResourceManager.GetString("ValidationExceptionMessageFieldNotInitialized", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Значение в поле {0} не является уникальным идентификатором.
/// </summary>
internal static string ValidationExceptionMessageIncorrectField {
get {
return ResourceManager.GetString("ValidationExceptionMessageIncorrectField", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Значение в поле ФИО не является ФИО.
/// </summary>
internal static string ValidationExceptionMessageIncorrectFIO {
get {
return ResourceManager.GetString("ValidationExceptionMessageIncorrectFIO", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Несовершеннолетние не могут быть приняты на работу (Дата трудоустройства - {0}, Дата рождения - {1}).
/// </summary>
internal static string ValidationExceptionMessageMinorAgeAtEmployment {
get {
return ResourceManager.GetString("ValidationExceptionMessageMinorAgeAtEmployment", resourceCulture);
}
}
/// <summary>
/// Ищет локализованную строку, похожую на Несовершеннолетние не могут быть приняты на работу (Дата рождения = {0}).
/// </summary>
internal static string ValidationExceptionMessageMinorCannotBeHired {
get {
return ResourceManager.GetString("ValidationExceptionMessageMinorCannotBeHired", resourceCulture);
}
}
}
}

View File

@@ -0,0 +1,360 @@
<?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>
<data name="ValidationExceptionMessageIncorrectFIO" xml:space="preserve">
<value>Value in field FIO is not FIO</value>
</data>
<data name="ValidationExceptionMessageEmptyField" xml:space="preserve">
<value>Value in field {0} is empty</value>
</data>
<data name="ValidationExceptionMessageMinorCannotBeHired" xml:space="preserve">
<value>Minors cannot be hired (Birth date = {0})</value>
</data>
<data name="ValidationExceptionMessageEmploymentDateBeforeBirthDate" xml:space="preserve">
<value>Employment date cannot be earlier than birth date</value>
</data>
<data name="ValidationExceptionMessageMinorAgeAtEmployment" xml:space="preserve">
<value>Minors cannot be hired (Employment date - {0}, Birth date - {1})</value>
</data>
<data name="ValidationExceptionMessageIncorrectField" xml:space="preserve">
<value>Value in field {0} is not a unique identifier</value>
</data>
<data name="ValidationExceptionMessageFieldLessOrEqualZero" xml:space="preserve">
<value>Field {0} value is less than or equal to zero</value>
</data>
<data name="ValidationExceptionMessageFieldNotInitialized" xml:space="preserve">
<value>Field {0} is not initialized</value>
</data>
<data name="ValidationExceptionMessageFieldIsZero" xml:space="preserve">
<value>Field {0} value is zero</value>
</data>
<data name="ValidationExceptionMessageFieldIsDefault" xml:space="preserve">
<value>Field {0} has default value</value>
</data>
<data name="ValidationExceptionMessageFieldIsNone" xml:space="preserve">
<value>Field {0} has None value</value>
</data>
<data name="ElementDeletedExceptionMessage" xml:space="preserve">
<value>Cannot modify deleted element (id: {0})</value>
</data>
<data name="ElementExistsExceptionMessage" xml:space="preserve">
<value>Element with value {0} of parameter {1} already exists</value>
</data>
<data name="ElementNotFoundExceptionMessage" xml:space="preserve">
<value>Element not found with value = {0}</value>
</data>
<data name="IncorrectDatesExceptionMessage" xml:space="preserve">
<value>End date must be later than start date. Start date: {0}. End date: {1}</value>
</data>
<data name="StorageExceptionMessage" xml:space="preserve">
<value>Storage error: {0}</value>
</data>
<data name="DocumentDocCaptionDate" xml:space="preserve">
<value>Date</value>
</data>
<data name="DocumentExcelCaptionOrder" xml:space="preserve">
<value>Order</value>
</data>
<data name="DocumentExcelCaptionSum" xml:space="preserve">
<value>Sum</value>
</data>
<data name="DocumentExcelCaptionService" xml:space="preserve">
<value>Service</value>
</data>
<data name="DocumentExcelCaptionCount" xml:space="preserve">
<value>Count</value>
</data>
<data name="DocumentDocHeader" xml:space="preserve">
<value>Masters Report</value>
</data>
<data name="DocumentDocPeriodFromTo" xml:space="preserve">
<value>Period: from {0} to {1}</value>
</data>
<data name="DocumentDocGeneratedOn" xml:space="preserve">
<value>Report generated: {0}</value>
</data>
<data name="DocumentDocNoMastersFound" xml:space="preserve">
<value>No masters found for the specified period.</value>
</data>
<data name="DocumentDocMasterFIO" xml:space="preserve">
<value>Master Full Name</value>
</data>
<data name="DocumentDocEmploymentDate" xml:space="preserve">
<value>Employment Date</value>
</data>
<data name="DocumentDocStatus" xml:space="preserve">
<value>Status</value>
</data>
<data name="DocumentDocOrdersCount" xml:space="preserve">
<value>Orders Count</value>
</data>
<data name="DocumentDocStatusFired" xml:space="preserve">
<value>Fired</value>
</data>
<data name="DocumentDocStatusWorking" xml:space="preserve">
<value>Working</value>
</data>
<data name="DocumentExcelOrderDate" xml:space="preserve">
<value>Order Date</value>
</data>
<data name="DocumentExcelRoomType" xml:space="preserve">
<value>Room Type</value>
</data>
<data name="DocumentExcelOrderId" xml:space="preserve">
<value>Order ID</value>
</data>
<data name="DocumentExcelOrdersByPeriod" xml:space="preserve">
<value>Orders for Period</value>
</data>
<data name="DocumentExcelPeriodFromToShort" xml:space="preserve">
<value>from {0} to {1}</value>
</data>
<data name="DocumentPdfSalaryStatement" xml:space="preserve">
<value>Salary Statement</value>
</data>
<data name="DocumentPdfSalaryPeriodFromTo" xml:space="preserve">
<value>for period from {0} to {1}</value>
</data>
<data name="DocumentPdfAccruals" xml:space="preserve">
<value>Accruals</value>
</data>
<data name="DocumentPdfUnknownMaster" xml:space="preserve">
<value>Unknown Master</value>
</data>
<data name="AdapterMessageListNotInitialized" xml:space="preserve">
<value>List not initialized</value>
</data>
<data name="AdapterMessageDataIsEmpty" xml:space="preserve">
<value>Data is empty</value>
</data>
<data name="AdapterMessageIdIsEmpty" xml:space="preserve">
<value>Identifier is empty</value>
</data>
<data name="AdapterMessageIncorrectDataTransmitted" xml:space="preserve">
<value>Incorrect data provided: {0}</value>
</data>
<data name="AdapterMessageIncorrectDates" xml:space="preserve">
<value>Incorrect dates: {0}</value>
</data>
<data name="AdapterMessageErrorWhileWorkingWithStorage" xml:space="preserve">
<value>Data storage error: {0}</value>
</data>
<data name="AdapterMessageNotFoundElementByData" xml:space="preserve">
<value>Element not found by data {0}</value>
</data>
<data name="AdapterMessageNotFoundElementById" xml:space="preserve">
<value>Element not found by identifier {0}</value>
</data>
<data name="AdapterMessageElementWasDeleted" xml:space="preserve">
<value>Element with identifier {0} was deleted</value>
</data>
<data name="AdapterMessageElementWasDeletedByData" xml:space="preserve">
<value>Element with data {0} was deleted</value>
</data>
<data name="AdapterMessageElementNotFound" xml:space="preserve">
<value>Element not found: {0}</value>
</data>
<data name="ReportServicesHeader" xml:space="preserve">
<value>Services and Price History Report</value>
</data>
<data name="ReportServicesPeriod" xml:space="preserve">
<value>Period: from {0} to {1}</value>
</data>
<data name="ReportServicesGenerated" xml:space="preserve">
<value>Report generated: {0}</value>
</data>
<data name="ReportServicesNoData" xml:space="preserve">
<value>No services found for the specified period.</value>
</data>
<data name="ReportServicesTableService" xml:space="preserve">
<value>Service</value>
</data>
<data name="ReportServicesTableType" xml:space="preserve">
<value>Type</value>
</data>
<data name="ReportServicesTableCurrentPrice" xml:space="preserve">
<value>Current Price</value>
</data>
<data name="ReportServicesTableChangeDate" xml:space="preserve">
<value>Change Date</value>
</data>
<data name="ReportServicesTableOldPrice" xml:space="preserve">
<value>Old Price</value>
</data>
<data name="ReportServicesNoChanges" xml:space="preserve">
<value>—</value>
</data>
<data name="ReportOrdersHeader" xml:space="preserve">
<value>Orders for Period</value>
</data>
<data name="ReportOrdersPeriod" xml:space="preserve">
<value>from {0} to {1}</value>
</data>
<data name="ReportOrdersTableOrderDate" xml:space="preserve">
<value>Order Date</value>
</data>
<data name="ReportOrdersTableStatus" xml:space="preserve">
<value>Status</value>
</data>
<data name="ReportOrdersTableRoomType" xml:space="preserve">
<value>Room Type</value>
</data>
<data name="ReportOrdersTableMaster" xml:space="preserve">
<value>Master</value>
</data>
<data name="ReportOrdersTableService" xml:space="preserve">
<value>Service</value>
</data>
<data name="ReportOrdersTableWorkTime" xml:space="preserve">
<value>Work Time</value>
</data>
<data name="ReportOrdersTableAmount" xml:space="preserve">
<value>Amount</value>
</data>
<data name="ReportOrdersNotAssigned" xml:space="preserve">
<value>Not Assigned</value>
</data>
<data name="ReportOrdersNoServices" xml:space="preserve">
<value>No Services</value>
</data>
<data name="ReportOrdersHours" xml:space="preserve">
<value>hrs</value>
</data>
<data name="ReportSalaryHeader" xml:space="preserve">
<value>Salary Statement</value>
</data>
<data name="ReportSalaryPeriod" xml:space="preserve">
<value>for period from {0} to {1}</value>
</data>
<data name="ReportSalaryAccruals" xml:space="preserve">
<value>Accruals</value>
</data>
<data name="ReportSalaryTableMaster" xml:space="preserve">
<value>Master</value>
</data>
<data name="ReportSalaryTableAmount" xml:space="preserve">
<value>Amount</value>
</data>
<data name="ReportSalaryTableDate" xml:space="preserve">
<value>Date</value>
</data>
<data name="ReportSalaryUnknownMaster" xml:space="preserve">
<value>Unknown Master</value>
</data>
</root>

View File

@@ -0,0 +1,361 @@
<?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>
<data name="ValidationExceptionMessageIncorrectFIO" xml:space="preserve">
<value>La valeur dans le champ Nom complet n'est pas un nom complet</value>
</data>
<data name="ValidationExceptionMessageEmptyField" xml:space="preserve">
<value>La valeur du champ {0} est vide</value>
</data>
<data name="ValidationExceptionMessageMinorCannotBeHired" xml:space="preserve">
<value>Les mineurs ne peuvent pas être embauchés (Date de naissance = {0})</value>
</data>
<data name="ValidationExceptionMessageEmploymentDateBeforeBirthDate" xml:space="preserve">
<value>La date d'embauche ne peut pas être antérieure à la date de naissance</value>
</data>
<data name="ValidationExceptionMessageMinorAgeAtEmployment" xml:space="preserve">
<value>Les mineurs ne peuvent pas être embauchés (Date d'embauche - {0}, Date de naissance - {1})</value>
</data>
<data name="ValidationExceptionMessageIncorrectField" xml:space="preserve">
<value>La valeur dans le champ {0} n'est pas un identifiant unique</value>
</data>
<data name="ValidationExceptionMessageFieldLessOrEqualZero" xml:space="preserve">
<value>La valeur du champ {0} est inférieure ou égale à zéro</value>
</data>
<data name="ValidationExceptionMessageFieldNotInitialized" xml:space="preserve">
<value>Le champ {0} n'est pas initialisé</value>
</data>
<data name="ValidationExceptionMessageFieldIsZero" xml:space="preserve">
<value>La valeur du champ {0} est zéro</value>
</data>
<data name="ValidationExceptionMessageFieldIsDefault" xml:space="preserve">
<value>Le champ {0} a une valeur par défaut</value>
</data>
<data name="ValidationExceptionMessageFieldIsNone" xml:space="preserve">
<value>Le champ {0} a la valeur None</value>
</data>
<data name="ElementDeletedExceptionMessage" xml:space="preserve">
<value>Impossible de modifier un élément supprimé (id: {0})</value>
</data>
<data name="ElementExistsExceptionMessage" xml:space="preserve">
<value>Un élément avec la valeur {0} du paramètre {1} existe déjà</value>
</data>
<data name="ElementNotFoundExceptionMessage" xml:space="preserve">
<value>Élément non trouvé avec la valeur = {0}</value>
</data>
<data name="IncorrectDatesExceptionMessage" xml:space="preserve">
<value>La date de fin doit être postérieure à la date de début. Date de début: {0}. Date de fin: {1}</value>
</data>
<data name="StorageExceptionMessage" xml:space="preserve">
<value>Erreur lors du travail avec le stockage: {0}</value>
</data>
<data name="DocumentDocCaptionDate" xml:space="preserve">
<value>Date</value>
</data>
<data name="DocumentExcelCaptionOrder" xml:space="preserve">
<value>Commande</value>
</data>
<data name="DocumentExcelCaptionSum" xml:space="preserve">
<value>Somme</value>
</data>
<data name="DocumentExcelCaptionService" xml:space="preserve">
<value>Service</value>
</data>
<data name="DocumentExcelCaptionCount" xml:space="preserve">
<value>Quantité</value>
</data>
<data name="DocumentDocHeader" xml:space="preserve">
<value>Rapport sur les maîtres</value>
</data>
<data name="DocumentDocPeriodFromTo" xml:space="preserve">
<value>Période: du {0} au {1}</value>
</data>
<data name="DocumentDocGeneratedOn" xml:space="preserve">
<value>Rapport généré: {0}</value>
</data>
<data name="DocumentDocNoMastersFound" xml:space="preserve">
<value>Aucun maître trouvé pour la période spécifiée.</value>
</data>
<data name="DocumentDocMasterFIO" xml:space="preserve">
<value>Nom complet du maître</value>
</data>
<data name="DocumentDocEmploymentDate" xml:space="preserve">
<value>Date d'embauche</value>
</data>
<data name="DocumentDocStatus" xml:space="preserve">
<value>Statut</value>
</data>
<data name="DocumentDocOrdersCount" xml:space="preserve">
<value>Nombre de commandes</value>
</data>
<data name="DocumentDocStatusFired" xml:space="preserve">
<value>Licencié</value>
</data>
<data name="DocumentDocStatusWorking" xml:space="preserve">
<value>En activité</value>
</data>
<data name="DocumentExcelOrderDate" xml:space="preserve">
<value>Date de commande</value>
</data>
<data name="DocumentExcelRoomType" xml:space="preserve">
<value>Type de pièce</value>
</data>
<data name="DocumentExcelOrderId" xml:space="preserve">
<value>ID de commande</value>
</data>
<data name="DocumentExcelOrdersByPeriod" xml:space="preserve">
<value>Commandes par période</value>
</data>
<data name="DocumentExcelPeriodFromToShort" xml:space="preserve">
<value>du {0} au {1}</value>
</data>
<data name="DocumentPdfSalaryStatement" xml:space="preserve">
<value>Bulletin de salaire</value>
</data>
<data name="DocumentPdfSalaryPeriodFromTo" xml:space="preserve">
<value>pour la période du {0} au {1}</value>
</data>
<data name="DocumentPdfAccruals" xml:space="preserve">
<value>Accruals</value>
</data>
<data name="DocumentPdfUnknownMaster" xml:space="preserve">
<value>Maître inconnu</value>
</data>
<data name="AdapterMessageListNotInitialized" xml:space="preserve">
<value>Liste non initialisée</value>
</data>
<data name="AdapterMessageDataIsEmpty" xml:space="preserve">
<value>Les données sont vides</value>
</data>
<data name="AdapterMessageIdIsEmpty" xml:space="preserve">
<value>L'identifiant est vide</value>
</data>
<data name="AdapterMessageIncorrectDataTransmitted" xml:space="preserve">
<value>Données incorrectes transmises: {0}</value>
</data>
<data name="AdapterMessageIncorrectDates" xml:space="preserve">
<value>Dates incorrectes: {0}</value>
</data>
<data name="AdapterMessageErrorWhileWorkingWithStorage" xml:space="preserve">
<value>Erreur lors du travail avec le stockage de données: {0}</value>
</data>
<data name="AdapterMessageNotFoundElementByData" xml:space="preserve">
<value>Élément non trouvé par les données {0}</value>
</data>
<data name="AdapterMessageNotFoundElementById" xml:space="preserve">
<value>Élément non trouvé par l'identifiant {0}</value>
</data>
<data name="AdapterMessageElementWasDeleted" xml:space="preserve">
<value>L'élément avec l'identifiant {0} a été supprimé</value>
</data>
<data name="AdapterMessageElementWasDeletedByData" xml:space="preserve">
<value>L'élément avec les données {0} a été supprimé</value>
</data>
<data name="AdapterMessageElementNotFound" xml:space="preserve">
<value>Élément non trouvé: {0}</value>
</data>
<!-- Rapports -->
<data name="ReportServicesHeader" xml:space="preserve">
<value>Rapport sur les services et leur historique des modifications</value>
</data>
<data name="ReportServicesPeriod" xml:space="preserve">
<value>Période: du {0} au {1}</value>
</data>
<data name="ReportServicesGenerated" xml:space="preserve">
<value>Rapport généré: {0}</value>
</data>
<data name="ReportServicesNoData" xml:space="preserve">
<value>Aucun service trouvé pour la période spécifiée.</value>
</data>
<data name="ReportServicesTableService" xml:space="preserve">
<value>Service</value>
</data>
<data name="ReportServicesTableType" xml:space="preserve">
<value>Type</value>
</data>
<data name="ReportServicesTableCurrentPrice" xml:space="preserve">
<value>Prix actuel</value>
</data>
<data name="ReportServicesTableChangeDate" xml:space="preserve">
<value>Date de modification</value>
</data>
<data name="ReportServicesTableOldPrice" xml:space="preserve">
<value>Ancien prix</value>
</data>
<data name="ReportServicesNoChanges" xml:space="preserve">
<value>—</value>
</data>
<data name="ReportOrdersHeader" xml:space="preserve">
<value>Commandes par période</value>
</data>
<data name="ReportOrdersPeriod" xml:space="preserve">
<value>du {0} au {1}</value>
</data>
<data name="ReportOrdersTableOrderDate" xml:space="preserve">
<value>Date de commande</value>
</data>
<data name="ReportOrdersTableStatus" xml:space="preserve">
<value>Statut</value>
</data>
<data name="ReportOrdersTableRoomType" xml:space="preserve">
<value>Type de pièce</value>
</data>
<data name="ReportOrdersTableMaster" xml:space="preserve">
<value>Maître</value>
</data>
<data name="ReportOrdersTableService" xml:space="preserve">
<value>Service</value>
</data>
<data name="ReportOrdersTableWorkTime" xml:space="preserve">
<value>Temps de travail</value>
</data>
<data name="ReportOrdersTableAmount" xml:space="preserve">
<value>Montant</value>
</data>
<data name="ReportOrdersNotAssigned" xml:space="preserve">
<value>Non assigné</value>
</data>
<data name="ReportOrdersNoServices" xml:space="preserve">
<value>Aucun service</value>
</data>
<data name="ReportOrdersHours" xml:space="preserve">
<value>h</value>
</data>
<data name="ReportSalaryHeader" xml:space="preserve">
<value>Bulletin de salaire</value>
</data>
<data name="ReportSalaryPeriod" xml:space="preserve">
<value>pour la période du {0} au {1}</value>
</data>
<data name="ReportSalaryAccruals" xml:space="preserve">
<value>Accruals</value>
</data>
<data name="ReportSalaryTableMaster" xml:space="preserve">
<value>Maître</value>
</data>
<data name="ReportSalaryTableAmount" xml:space="preserve">
<value>Montant</value>
</data>
<data name="ReportSalaryTableDate" xml:space="preserve">
<value>Date</value>
</data>
<data name="ReportSalaryUnknownMaster" xml:space="preserve">
<value>Maître inconnu</value>
</data>
</root>

View File

@@ -0,0 +1,361 @@
<?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>
<data name="ValidationExceptionMessageIncorrectFIO" xml:space="preserve">
<value>Значение в поле ФИО не является ФИО</value>
</data>
<data name="ValidationExceptionMessageEmptyField" xml:space="preserve">
<value>Значение поле {0} пусто</value>
</data>
<data name="ValidationExceptionMessageMinorCannotBeHired" xml:space="preserve">
<value>Несовершеннолетние не могут быть приняты на работу (Дата рождения = {0})</value>
</data>
<data name="ValidationExceptionMessageEmploymentDateBeforeBirthDate" xml:space="preserve">
<value>Дата трудоустройства не может быть раньше даты рождения</value>
</data>
<data name="ValidationExceptionMessageMinorAgeAtEmployment" xml:space="preserve">
<value>Несовершеннолетние не могут быть приняты на работу (Дата трудоустройства - {0}, Дата рождения - {1})</value>
</data>
<data name="ValidationExceptionMessageIncorrectField" xml:space="preserve">
<value>Значение в поле {0} не является уникальным идентификатором</value>
</data>
<data name="ValidationExceptionMessageFieldLessOrEqualZero" xml:space="preserve">
<value>Значение поля {0} меньше или равно нулю</value>
</data>
<data name="ValidationExceptionMessageFieldNotInitialized" xml:space="preserve">
<value>Поле {0} не инициализировано</value>
</data>
<data name="ValidationExceptionMessageFieldIsZero" xml:space="preserve">
<value>Значение поля {0} равно нулю</value>
</data>
<data name="ValidationExceptionMessageFieldIsDefault" xml:space="preserve">
<value>Поле {0} имеет значение по умолчанию</value>
</data>
<data name="ValidationExceptionMessageFieldIsNone" xml:space="preserve">
<value>Поле {0} имеет значение None</value>
</data>
<data name="ElementDeletedExceptionMessage" xml:space="preserve">
<value>Нельзя изменить удаленный элемент (id: {0})</value>
</data>
<data name="ElementExistsExceptionMessage" xml:space="preserve">
<value>Элемент со значением {0} параметра {1} уже существует</value>
</data>
<data name="ElementNotFoundExceptionMessage" xml:space="preserve">
<value>Элемент не найден со значением = {0}</value>
</data>
<data name="IncorrectDatesExceptionMessage" xml:space="preserve">
<value>Дата окончания должна быть позже даты начала. Дата начала: {0}. Дата окончания: {1}</value>
</data>
<data name="StorageExceptionMessage" xml:space="preserve">
<value>Ошибка при работе с хранилищем: {0}</value>
</data>
<data name="DocumentDocCaptionDate" xml:space="preserve">
<value>Дата</value>
</data>
<data name="DocumentExcelCaptionOrder" xml:space="preserve">
<value>Заказ</value>
</data>
<data name="DocumentExcelCaptionSum" xml:space="preserve">
<value>Сумма</value>
</data>
<data name="DocumentExcelCaptionService" xml:space="preserve">
<value>Услуга</value>
</data>
<data name="DocumentExcelCaptionCount" xml:space="preserve">
<value>Количество</value>
</data>
<data name="DocumentDocHeader" xml:space="preserve">
<value>Отчет по мастерам</value>
</data>
<data name="DocumentDocPeriodFromTo" xml:space="preserve">
<value>Период: с {0} по {1}</value>
</data>
<data name="DocumentDocGeneratedOn" xml:space="preserve">
<value>Отчёт сформирован: {0}</value>
</data>
<data name="DocumentDocNoMastersFound" xml:space="preserve">
<value>За указанный период мастера не найдены.</value>
</data>
<data name="DocumentDocMasterFIO" xml:space="preserve">
<value>ФИО мастера</value>
</data>
<data name="DocumentDocEmploymentDate" xml:space="preserve">
<value>Дата трудоустройства</value>
</data>
<data name="DocumentDocStatus" xml:space="preserve">
<value>Статус</value>
</data>
<data name="DocumentDocOrdersCount" xml:space="preserve">
<value>Количество заказов</value>
</data>
<data name="DocumentDocStatusFired" xml:space="preserve">
<value>Уволен</value>
</data>
<data name="DocumentDocStatusWorking" xml:space="preserve">
<value>Работает</value>
</data>
<data name="DocumentExcelOrderDate" xml:space="preserve">
<value>Дата заказа</value>
</data>
<data name="DocumentExcelRoomType" xml:space="preserve">
<value>Тип помещения</value>
</data>
<data name="DocumentExcelOrderId" xml:space="preserve">
<value>ID заказа</value>
</data>
<data name="DocumentExcelOrdersByPeriod" xml:space="preserve">
<value>Заказы за период</value>
</data>
<data name="DocumentExcelPeriodFromToShort" xml:space="preserve">
<value>с {0} по {1}</value>
</data>
<data name="DocumentPdfSalaryStatement" xml:space="preserve">
<value>Зарплатная ведомость</value>
</data>
<data name="DocumentPdfSalaryPeriodFromTo" xml:space="preserve">
<value>за период с {0} по {1}</value>
</data>
<data name="DocumentPdfAccruals" xml:space="preserve">
<value>Начисления</value>
</data>
<data name="DocumentPdfUnknownMaster" xml:space="preserve">
<value>Неизвестный мастер</value>
</data>
<data name="AdapterMessageListNotInitialized" xml:space="preserve">
<value>Список не инициализирован</value>
</data>
<data name="AdapterMessageDataIsEmpty" xml:space="preserve">
<value>Данные пусты</value>
</data>
<data name="AdapterMessageIdIsEmpty" xml:space="preserve">
<value>Идентификатор пуст</value>
</data>
<data name="AdapterMessageIncorrectDataTransmitted" xml:space="preserve">
<value>Переданы некорректные данные: {0}</value>
</data>
<data name="AdapterMessageIncorrectDates" xml:space="preserve">
<value>Некорректные даты: {0}</value>
</data>
<data name="AdapterMessageErrorWhileWorkingWithStorage" xml:space="preserve">
<value>Ошибка при работе с хранилищем данных: {0}</value>
</data>
<data name="AdapterMessageNotFoundElementByData" xml:space="preserve">
<value>Элемент не найден по данным {0}</value>
</data>
<data name="AdapterMessageNotFoundElementById" xml:space="preserve">
<value>Элемент не найден по идентификатору {0}</value>
</data>
<data name="AdapterMessageElementWasDeleted" xml:space="preserve">
<value>Элемент с идентификатором {0} был удален</value>
</data>
<data name="AdapterMessageElementWasDeletedByData" xml:space="preserve">
<value>Элемент с данными {0} был удален</value>
</data>
<data name="AdapterMessageElementNotFound" xml:space="preserve">
<value>Элемент не найден: {0}</value>
</data>
<!-- Отчеты -->
<data name="ReportServicesHeader" xml:space="preserve">
<value>Отчет по услугам и их истории изменений</value>
</data>
<data name="ReportServicesPeriod" xml:space="preserve">
<value>Период: с {0} по {1}</value>
</data>
<data name="ReportServicesGenerated" xml:space="preserve">
<value>Отчёт сформирован: {0}</value>
</data>
<data name="ReportServicesNoData" xml:space="preserve">
<value>За указанный период услуги не найдены.</value>
</data>
<data name="ReportServicesTableService" xml:space="preserve">
<value>Услуга</value>
</data>
<data name="ReportServicesTableType" xml:space="preserve">
<value>Тип</value>
</data>
<data name="ReportServicesTableCurrentPrice" xml:space="preserve">
<value>Текущая цена</value>
</data>
<data name="ReportServicesTableChangeDate" xml:space="preserve">
<value>Дата изменения</value>
</data>
<data name="ReportServicesTableOldPrice" xml:space="preserve">
<value>Старая цена</value>
</data>
<data name="ReportServicesNoChanges" xml:space="preserve">
<value>—</value>
</data>
<data name="ReportOrdersHeader" xml:space="preserve">
<value>Заказы за период</value>
</data>
<data name="ReportOrdersPeriod" xml:space="preserve">
<value>с {0} по {1}</value>
</data>
<data name="ReportOrdersTableOrderDate" xml:space="preserve">
<value>Дата заказа</value>
</data>
<data name="ReportOrdersTableStatus" xml:space="preserve">
<value>Статус</value>
</data>
<data name="ReportOrdersTableRoomType" xml:space="preserve">
<value>Тип помещения</value>
</data>
<data name="ReportOrdersTableMaster" xml:space="preserve">
<value>Мастер</value>
</data>
<data name="ReportOrdersTableService" xml:space="preserve">
<value>Услуга</value>
</data>
<data name="ReportOrdersTableWorkTime" xml:space="preserve">
<value>Время работы</value>
</data>
<data name="ReportOrdersTableAmount" xml:space="preserve">
<value>Сумма</value>
</data>
<data name="ReportOrdersNotAssigned" xml:space="preserve">
<value>Не назначен</value>
</data>
<data name="ReportOrdersNoServices" xml:space="preserve">
<value>Нет услуг</value>
</data>
<data name="ReportOrdersHours" xml:space="preserve">
<value>ч.</value>
</data>
<data name="ReportSalaryHeader" xml:space="preserve">
<value>Зарплатная ведомость</value>
</data>
<data name="ReportSalaryPeriod" xml:space="preserve">
<value>за период с {0} по {1}</value>
</data>
<data name="ReportSalaryAccruals" xml:space="preserve">
<value>Начисления</value>
</data>
<data name="ReportSalaryTableMaster" xml:space="preserve">
<value>Мастер</value>
</data>
<data name="ReportSalaryTableAmount" xml:space="preserve">
<value>Сумма</value>
</data>
<data name="ReportSalaryTableDate" xml:space="preserve">
<value>Дата</value>
</data>
<data name="ReportSalaryUnknownMaster" xml:space="preserve">
<value>Неизвестный мастер</value>
</data>
</root>

View File

@@ -7,7 +7,7 @@ using TwoFromTheCasketContratcs.DataModels;
namespace TwoFromTheCasketContratcs.StorageContracts;
public interface IMasterStorageContract
internal interface IMasterStorageContract
{
List<MasterDataModel> GetList(bool onlyActive = true, string? postId =
null, DateTime? fromBirthDate = null, DateTime? toBirthDate = null, DateTime?

View File

@@ -8,10 +8,12 @@ using TwoFromTheCasketContratcs.Enums;
namespace TwoFromTheCasketContratcs.StorageContracts;
public interface IOrderStorageContract
internal interface IOrderStorageContract
{
List<OrderDataModel> GetList();
Task<List<OrderDataModel>> GetListAsync(DateTime startDate, DateTime endDate, CancellationToken ct);
OrderDataModel? GetElementById(string id);
OrderDataModel? GetElementByDate(DateTime date);
@@ -23,4 +25,6 @@ public interface IOrderStorageContract
void UpdElement(OrderDataModel orderDataModel);
void DelElement(string id);
Task<List<(string MasterFIO, string ServiceName, int TimeOfWorking, decimal TotalAmount)>> GetOrderDetailsAsync(string orderId, CancellationToken ct);
}

View File

@@ -7,7 +7,7 @@ using TwoFromTheCasketContratcs.DataModels;
namespace TwoFromTheCasketContratcs.StorageContracts;
public interface IPostStorageContract
internal interface IPostStorageContract
{
List<PostDataModel> GetList();

View File

@@ -8,16 +8,18 @@ using TwoFromTheCasketContratcs.Enums;
namespace TwoFromTheCasketContratcs.StorageContracts;
public interface ISalaryStorageContract
internal interface ISalaryStorageContract
{
List<SalaryDataModel> GetList(DateTime startDate, DateTime endDate, string?
masterId = null);
Task<List<SalaryDataModel>> GetListAsync(DateTime startDate, DateTime endDate, CancellationToken ct);
SalaryDataModel? GetElementByMasterId(string masterId);
SalaryDataModel? GetElementBySalaryDate(DateTime salaryDate);
void AddElement(SalaryDataModel salaryDataModel);
void SaveChanges();
}

View File

@@ -8,10 +8,11 @@ using TwoFromTheCasketContratcs.Enums;
namespace TwoFromTheCasketContratcs.StorageContracts;
public interface IServiceStorageContract
internal interface IServiceStorageContract
{
List<ServiceDataModel> GetList();
Task<List<ServiceDataModel>> GetListAsync();
Task<List<ServiceDataModel>> GetListAsync(DateTime startDate, DateTime endDate, CancellationToken ct);
List<ServiceHistoryDataModel> GetHistoryByServiceId(string serviceId);
ServiceDataModel? GetElementById(string id);

View File

@@ -9,12 +9,28 @@
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Mvc.Abstractions" Version="2.3.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.3.0" />
<PackageReference Include="Microsoft.Extensions.Localization.Abstractions" Version="9.0.9" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.4" />
</ItemGroup>
<ItemGroup>
<InternalsVisibleTo Include="TwoFromTheCasketTest" />
<InternalsVisibleTo Include="TwoFromTheCasketWebApi" />
<InternalsVisibleTo Include="TwoFromTheCasketBuisnessLogic" />
<InternalsVisibleTo Include="TwoFromTheCasketDatabase" />
<InternalsVisibleTo Include="DynamicProxyGenAssembly2" />
</ItemGroup>
<ItemGroup>
<Compile Update="Resources\Messages.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Messages.resx</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Update="Resources\Messages.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Messages.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TwoFromTheCasketContratcs.ViewModels;
public class MasterSalaryByPeriodViewModel
{
public required string MasterFIO { get; set; }
public double TotalSalary { get; set; }
public DateTime FromPeriod { get; set; }
public DateTime ToPeriod { get; set; }
}

View File

@@ -14,5 +14,5 @@ public class PostViewModel
public required string PostType { get; set; }
public double Salary { get; set; }
public required string Configuration { get; set; }
}

View File

@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TwoFromTheCasketContratcs.ViewModels;
public class ServiceHistoryViewModel
{
public string ServiceId { get; set; } = string.Empty;
public double OldPrice { get; set; }
public DateTime ChangeDate { get; set; }
}

View File

@@ -0,0 +1,15 @@
using TwoFromTheCasketContratcs.Enums;
namespace TwoFromTheCasketContratcs.ViewModels;
public class ServiceWithHistoryViewModel
{
public string Id { get; set; } = string.Empty;
public string ServiceName { get; set; } = string.Empty;
public ServiceType ServiceType { get; set; }
public double Price { get; set; }
public string MasterId { get; set; } = string.Empty;
public DateTime CreatedAt { get; set; }
public bool IsDeleted { get; set; }
public List<ServiceHistoryViewModel> History { get; set; } = new();
}

View File

@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TwoFromTheCasketContratcs.Infrastructure;
namespace TwoFromTheCasketDatabase;
public class DefaultConfigurationDatabase : IConfigurationDatabase
{
public string ConnectionString => "";
}

View File

@@ -1,5 +1,6 @@
using AutoMapper;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Localization;
using Npgsql;
using System;
using System.Collections.Generic;
@@ -9,6 +10,7 @@ using System.Threading.Tasks;
using System.Xml.Linq;
using TwoFromTheCasketContratcs.DataModels;
using TwoFromTheCasketContratcs.Exceptions;
using TwoFromTheCasketContratcs.Resources;
using TwoFromTheCasketContratcs.StorageContracts;
using TwoFromTheCasketDatabase.Models;
@@ -19,7 +21,9 @@ internal class MasterStorageContract : IMasterStorageContract
private readonly TwoFromTheCasketDbContext _dbContext;
private readonly Mapper _mapper;
public MasterStorageContract(TwoFromTheCasketDbContext twoFromTheCasketDbContext)
private readonly IStringLocalizer<Messages> _localizer;
public MasterStorageContract(TwoFromTheCasketDbContext twoFromTheCasketDbContext, IStringLocalizer<Messages> localizer)
{
_dbContext = twoFromTheCasketDbContext;
var config = new MapperConfiguration(cfg =>
@@ -27,6 +31,8 @@ internal class MasterStorageContract : IMasterStorageContract
cfg.AddMaps(typeof(Master));
});
_mapper = new Mapper(config);
_localizer = localizer;
}
public List<MasterDataModel> GetList(bool onlyActive = true, string? postId = null, DateTime? fromBirthDate = null, DateTime? toBirthDate = null, DateTime? fromEmploymentDate = null, DateTime? toEmploymentDate = null)
@@ -46,7 +52,7 @@ internal class MasterStorageContract : IMasterStorageContract
catch(Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
throw new StorageException(ex, _localizer);
}
}
@@ -60,7 +66,7 @@ internal class MasterStorageContract : IMasterStorageContract
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
throw new StorageException(ex, _localizer);
}
}
public MasterDataModel? GetElementByFIO(string name)
@@ -72,7 +78,7 @@ internal class MasterStorageContract : IMasterStorageContract
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
throw new StorageException(ex, _localizer);
}
}
@@ -85,7 +91,7 @@ internal class MasterStorageContract : IMasterStorageContract
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
throw new StorageException(ex, _localizer);
}
}
public void AddElement(MasterDataModel masterDataModel)
@@ -98,24 +104,24 @@ internal class MasterStorageContract : IMasterStorageContract
catch(InvalidOperationException ex) when (ex.TargetSite?.Name == "ThrowIdentityConflict")
{
_dbContext.ChangeTracker.Clear();
throw new ElementExistsException("Id", masterDataModel.Id);
throw new ElementExistsException("Id", masterDataModel.Id, _localizer);
}
catch (DbUpdateException ex) when (ex.InnerException is PostgresException { ConstraintName : "IX_Master_FIO" } )
{
_dbContext.ChangeTracker.Clear();
throw new ElementExistsException("FIO", masterDataModel.FIO);
throw new ElementExistsException("FIO", masterDataModel.FIO, _localizer);
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
throw new StorageException(ex, _localizer);
}
}
public void UpdElement(MasterDataModel masterDataModel)
{
try
{
var element = GetMasterById(masterDataModel.Id) ?? throw new ElementNotFoundException(masterDataModel.Id);
var element = GetMasterById(masterDataModel.Id) ?? throw new ElementNotFoundException(masterDataModel.Id, _localizer);
_dbContext.Masters.Update(_mapper.Map(masterDataModel,element));
_dbContext.SaveChanges();
}
@@ -127,12 +133,12 @@ internal class MasterStorageContract : IMasterStorageContract
catch (DbUpdateException ex) when (ex.InnerException is PostgresException { ConstraintName: "IX_Master_FIO" })
{
_dbContext.ChangeTracker.Clear();
throw new ElementExistsException("FIO", masterDataModel.FIO);
throw new ElementExistsException("FIO", masterDataModel.FIO, _localizer);
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
throw new StorageException(ex, _localizer);
}
}
@@ -140,7 +146,7 @@ internal class MasterStorageContract : IMasterStorageContract
{
try
{
var element = GetMasterById(id) ?? throw new ElementNotFoundException(id);
var element = GetMasterById(id) ?? throw new ElementNotFoundException(id, _localizer);
element.IsDeleted = true;
_dbContext.SaveChanges();
}
@@ -152,7 +158,7 @@ internal class MasterStorageContract : IMasterStorageContract
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
throw new StorageException(ex, _localizer);
}
}

View File

@@ -1,5 +1,6 @@
using AutoMapper;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Localization;
using Npgsql;
using System;
using System.Collections.Generic;
@@ -10,6 +11,7 @@ using System.Threading.Tasks;
using TwoFromTheCasketContratcs.DataModels;
using TwoFromTheCasketContratcs.Enums;
using TwoFromTheCasketContratcs.Exceptions;
using TwoFromTheCasketContratcs.Resources;
using TwoFromTheCasketContratcs.StorageContracts;
using TwoFromTheCasketDatabase.Models;
using static System.Runtime.InteropServices.JavaScript.JSType;
@@ -21,7 +23,9 @@ internal class OrderStorageContract : IOrderStorageContract
private readonly TwoFromTheCasketDbContext _dbContext;
private readonly Mapper _mapper;
public OrderStorageContract(TwoFromTheCasketDbContext twoFromTheCasketDbContext)
private readonly IStringLocalizer<Messages> _localizer;
public OrderStorageContract(TwoFromTheCasketDbContext twoFromTheCasketDbContext, IStringLocalizer<Messages> localizer)
{
_dbContext = twoFromTheCasketDbContext;
@@ -45,6 +49,7 @@ internal class OrderStorageContract : IOrderStorageContract
});
_mapper = new Mapper(config);
_localizer = localizer;
}
public List<OrderDataModel> GetList()
{
@@ -55,7 +60,7 @@ internal class OrderStorageContract : IOrderStorageContract
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
throw new StorageException(ex, _localizer);
}
}
public OrderDataModel? GetElementById(string id)
@@ -67,7 +72,7 @@ internal class OrderStorageContract : IOrderStorageContract
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
throw new StorageException(ex, _localizer);
}
}
public OrderDataModel? GetElementByDate(DateTime date)
@@ -79,7 +84,7 @@ internal class OrderStorageContract : IOrderStorageContract
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
throw new StorageException(ex, _localizer);
}
}
public OrderDataModel? GetElementByStatus(StatusType status)
@@ -91,7 +96,7 @@ internal class OrderStorageContract : IOrderStorageContract
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
throw new StorageException(ex, _localizer);
}
}
@@ -105,19 +110,19 @@ internal class OrderStorageContract : IOrderStorageContract
catch (InvalidOperationException ex) when (ex.TargetSite?.Name == "ThrowIdentityConflict")
{
_dbContext.ChangeTracker.Clear();
throw new ElementExistsException("Id", orderDataModel.Id);
throw new ElementExistsException("Id", orderDataModel.Id, _localizer);
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
throw new StorageException(ex, _localizer);
}
}
public void UpdElement(OrderDataModel orderDataModel)
{
try
{
var element = GetOrderById(orderDataModel.Id) ?? throw new ElementNotFoundException(orderDataModel.Id);
var element = GetOrderById(orderDataModel.Id) ?? throw new ElementNotFoundException(orderDataModel.Id, _localizer);
_dbContext.Orders.Update(_mapper.Map(orderDataModel, element));
_dbContext.SaveChanges();
}
@@ -129,14 +134,14 @@ internal class OrderStorageContract : IOrderStorageContract
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
throw new StorageException(ex, _localizer);
}
}
public void DelElement(string id)
{
try
{
var element = GetOrderById(id) ?? throw new ElementNotFoundException(id);
var element = GetOrderById(id) ?? throw new ElementNotFoundException(id, _localizer);
_dbContext.Orders.Remove(element);
_dbContext.SaveChanges();
}
@@ -148,10 +153,55 @@ internal class OrderStorageContract : IOrderStorageContract
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
throw new StorageException(ex, _localizer);
}
}
private Order? GetOrderById(string id) => _dbContext.Orders.FirstOrDefault(x => x.Id == id);
public async Task<List<(string MasterFIO, string ServiceName, int TimeOfWorking, decimal TotalAmount)>> GetOrderDetailsAsync(string orderId, CancellationToken ct)
{
try
{
var orderDetails = await _dbContext.ServiceOrders
.Where(so => so.OrderId == orderId)
.Join(_dbContext.Masters, so => so.MasterId, m => m.Id, (so, m) => new { so, m })
.Join(_dbContext.Services, x => x.so.ServiceId, s => s.Id, (x, s) => new
{
MasterFIO = x.m.FIO,
ServiceName = s.ServiceName,
TimeOfWorking = x.so.TimeOfWorking,
ServicePrice = s.Price
})
.ToListAsync(ct);
return orderDetails.Select(x => (
x.MasterFIO,
x.ServiceName,
x.TimeOfWorking,
(decimal)(x.ServicePrice * x.TimeOfWorking) // Explicit cast to decimal
)).ToList();
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex, _localizer);
}
}
public async Task<List<OrderDataModel>> GetListAsync(DateTime startDate, DateTime endDate, CancellationToken ct)
{
try
{
return [.. await _dbContext.Orders
.Where(x => x.Date >= startDate && x.Date <= endDate)
.Select(x => _mapper.Map<OrderDataModel>(x))
.ToListAsync(ct)];
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex, _localizer);
}
}
}

View File

@@ -1,5 +1,6 @@
using AutoMapper;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Localization;
using Npgsql;
using System;
using System.Collections.Generic;
@@ -8,6 +9,7 @@ using System.Text;
using System.Threading.Tasks;
using TwoFromTheCasketContratcs.DataModels;
using TwoFromTheCasketContratcs.Exceptions;
using TwoFromTheCasketContratcs.Resources;
using TwoFromTheCasketContratcs.StorageContracts;
using TwoFromTheCasketDatabase.Models;
@@ -17,8 +19,8 @@ internal class PostStorageContract : IPostStorageContract
{
private readonly TwoFromTheCasketDbContext _dbContext;
private readonly Mapper _mapper;
public PostStorageContract(TwoFromTheCasketDbContext dbContext)
private readonly IStringLocalizer<Messages> _localizer;
public PostStorageContract(TwoFromTheCasketDbContext dbContext, IStringLocalizer<Messages> localizer)
{
_dbContext = dbContext;
var config = new MapperConfiguration(cfg =>
@@ -29,9 +31,11 @@ internal class PostStorageContract : IPostStorageContract
.ForMember(x => x.Id, x => x.Ignore())
.ForMember(x => x.PostId, x => x.MapFrom(src => src.Id))
.ForMember(x => x.IsActual, x => x.MapFrom(src => true))
.ForMember(x => x.ChangeDate, x => x.MapFrom(src => DateTime.UtcNow));
.ForMember(x => x.ChangeDate, x => x.MapFrom(src => DateTime.UtcNow))
.ForMember(x => x.Configuration, x => x.MapFrom(src => src.ConfigurationModel));
});
_mapper = new Mapper(config);
_localizer = localizer;
}
public List<PostDataModel> GetList()
@@ -43,7 +47,7 @@ internal class PostStorageContract : IPostStorageContract
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
throw new StorageException(ex, _localizer);
}
}
@@ -56,7 +60,7 @@ internal class PostStorageContract : IPostStorageContract
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
throw new StorageException(ex, _localizer);
}
}
@@ -69,7 +73,7 @@ internal class PostStorageContract : IPostStorageContract
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
throw new StorageException(ex, _localizer);
}
}
@@ -82,7 +86,7 @@ internal class PostStorageContract : IPostStorageContract
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
throw new StorageException(ex, _localizer);
}
}
@@ -97,18 +101,18 @@ internal class PostStorageContract : IPostStorageContract
when (ex.InnerException is PostgresException { ConstraintName: "IX_Posts_PostName_IsActual" })
{
_dbContext.ChangeTracker.Clear();
throw new ElementExistsException("PostName", postDataModel.PostName);
throw new ElementExistsException("PostName", postDataModel.PostName, _localizer);
}
catch (DbUpdateException ex)
when (ex.InnerException is PostgresException { ConstraintName: "IX_Posts_PostId_IsActual" })
{
_dbContext.ChangeTracker.Clear();
throw new ElementExistsException("PostId", postDataModel.Id);
throw new ElementExistsException("PostId", postDataModel.Id, _localizer);
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
throw new StorageException(ex, _localizer);
}
}
@@ -119,8 +123,8 @@ internal class PostStorageContract : IPostStorageContract
var transaction = _dbContext.Database.BeginTransaction();
try
{
var element = GetPostById(postDataModel.Id) ?? throw new ElementNotFoundException(postDataModel.Id);
if (!element.IsActual) throw new ElementDeletedException(postDataModel.Id);
var element = GetPostById(postDataModel.Id) ?? throw new ElementNotFoundException(postDataModel.Id, _localizer);
if (!element.IsActual) throw new ElementDeletedException(postDataModel.Id, _localizer);
element.IsActual = false;
_dbContext.SaveChanges();
@@ -139,7 +143,7 @@ internal class PostStorageContract : IPostStorageContract
when (ex.InnerException is PostgresException { ConstraintName: "IX_Posts_PostName_IsActual" })
{
_dbContext.ChangeTracker.Clear();
throw new ElementExistsException("PostName", postDataModel.PostName);
throw new ElementExistsException("PostName", postDataModel.PostName, _localizer);
}
catch (Exception ex) when (ex is ElementDeletedException || ex is ElementNotFoundException)
{
@@ -149,7 +153,7 @@ internal class PostStorageContract : IPostStorageContract
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
throw new StorageException(ex, _localizer);
}
}
@@ -157,8 +161,8 @@ internal class PostStorageContract : IPostStorageContract
{
try
{
var element = GetPostById(id) ?? throw new ElementNotFoundException(id);
if (!element.IsActual) throw new ElementDeletedException(id);
var element = GetPostById(id) ?? throw new ElementNotFoundException(id, _localizer);
if (!element.IsActual) throw new ElementDeletedException(id, _localizer);
element.IsActual = false;
_dbContext.SaveChanges();
}
@@ -173,7 +177,7 @@ internal class PostStorageContract : IPostStorageContract
{
try
{
var element = GetPostById(id) ?? throw new ElementNotFoundException(id);
var element = GetPostById(id) ?? throw new ElementNotFoundException(id, _localizer);
element.IsActual = true;
_dbContext.SaveChanges();
}

View File

@@ -1,5 +1,6 @@
using AutoMapper;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Localization;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -7,6 +8,7 @@ using System.Text;
using System.Threading.Tasks;
using TwoFromTheCasketContratcs.DataModels;
using TwoFromTheCasketContratcs.Exceptions;
using TwoFromTheCasketContratcs.Resources;
using TwoFromTheCasketContratcs.StorageContracts;
using TwoFromTheCasketDatabase.Models;
using static System.Runtime.InteropServices.JavaScript.JSType;
@@ -19,7 +21,8 @@ internal class SalaryStorageContract : ISalaryStorageContract
Mapper _mapper;
public SalaryStorageContract(TwoFromTheCasketDbContext twoFromTheCasketDbContext)
private readonly IStringLocalizer<Messages> _localizer;
public SalaryStorageContract(TwoFromTheCasketDbContext twoFromTheCasketDbContext, IStringLocalizer<Messages> localizer)
{
_dbContext = twoFromTheCasketDbContext;
@@ -33,6 +36,7 @@ internal class SalaryStorageContract : ISalaryStorageContract
src.Prize));
cfg.CreateMap<SalaryDataModel, Salary>()
.ForMember(dest => dest.Id, opt => opt.Ignore()) // Игнорируем Id, так как он генерируется автоматически
.ForMember(dest => dest.MasterId, opt => opt.MapFrom(src => src.MasterId))
.ForMember(dest => dest.SalaryDate, opt => opt.MapFrom(src => src.SalaryDate))
.ForMember(dest => dest.SalarySize, opt => opt.MapFrom(src => src.Salary))
@@ -40,6 +44,7 @@ internal class SalaryStorageContract : ISalaryStorageContract
});
_mapper = new Mapper(config);
_localizer = localizer;
}
public List<SalaryDataModel> GetList(DateTime startDate, DateTime endDate, string? masterId = null)
@@ -53,7 +58,7 @@ internal class SalaryStorageContract : ISalaryStorageContract
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
throw new StorageException(ex, _localizer);
}
}
@@ -67,7 +72,7 @@ internal class SalaryStorageContract : ISalaryStorageContract
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
throw new StorageException(ex, _localizer);
}
}
@@ -80,7 +85,7 @@ internal class SalaryStorageContract : ISalaryStorageContract
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
throw new StorageException(ex, _localizer);
}
}
public void AddElement(SalaryDataModel salaryDataModel)
@@ -88,13 +93,41 @@ internal class SalaryStorageContract : ISalaryStorageContract
try
{
_dbContext.Salaries.Add(_mapper.Map<Salary>(salaryDataModel));
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex, _localizer);
}
}
public void SaveChanges()
{
try
{
_dbContext.SaveChanges();
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
throw new StorageException(ex, _localizer);
}
}
public async Task<List<SalaryDataModel>> GetListAsync(DateTime startDate, DateTime endDate, CancellationToken ct)
{
try
{
var salaries = await _dbContext.Salaries
.Where(x => x.SalaryDate >= startDate && x.SalaryDate <= endDate)
.ToListAsync(ct);
return salaries.Select(x => _mapper.Map<SalaryDataModel>(x)).ToList();
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex, _localizer);
}
}
}

View File

@@ -1,5 +1,6 @@
using AutoMapper;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Localization;
using Npgsql;
using System;
using System.Collections.Generic;
@@ -8,6 +9,7 @@ using System.Text;
using System.Threading.Tasks;
using TwoFromTheCasketContratcs.DataModels;
using TwoFromTheCasketContratcs.Exceptions;
using TwoFromTheCasketContratcs.Resources;
using TwoFromTheCasketContratcs.StorageContracts;
using TwoFromTheCasketDatabase.Models;
@@ -19,7 +21,8 @@ internal class ServiceStorageContract : IServiceStorageContract
private readonly Mapper _mapper;
public ServiceStorageContract(TwoFromTheCasketDbContext dbContext)
private readonly IStringLocalizer<Messages> _localizer;
public ServiceStorageContract(TwoFromTheCasketDbContext dbContext, IStringLocalizer<Messages> localizer)
{
_dbContext = dbContext;
var config = new MapperConfiguration(cfg =>
@@ -33,6 +36,7 @@ internal class ServiceStorageContract : IServiceStorageContract
cfg.CreateMap<ServiceHistoryDataModel, ServiceHistory>();
});
_mapper = new Mapper(config);
_localizer = localizer;
}
public List<ServiceDataModel> GetList()
@@ -44,7 +48,7 @@ internal class ServiceStorageContract : IServiceStorageContract
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
throw new StorageException(ex, _localizer);
}
}
@@ -59,7 +63,7 @@ internal class ServiceStorageContract : IServiceStorageContract
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
throw new StorageException(ex, _localizer);
}
}
@@ -73,7 +77,7 @@ internal class ServiceStorageContract : IServiceStorageContract
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
throw new StorageException(ex, _localizer);
}
}
@@ -87,7 +91,7 @@ internal class ServiceStorageContract : IServiceStorageContract
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
throw new StorageException(ex, _localizer);
}
}
@@ -100,7 +104,7 @@ internal class ServiceStorageContract : IServiceStorageContract
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
throw new StorageException(ex, _localizer);
}
}
@@ -116,19 +120,19 @@ internal class ServiceStorageContract : IServiceStorageContract
"ThrowIdentityConflict")
{
_dbContext.ChangeTracker.Clear();
throw new ElementExistsException("Id", serviceDataModel.Id);
throw new ElementExistsException("Id", serviceDataModel.Id, _localizer);
}
catch (DbUpdateException ex) when (ex.InnerException is
PostgresException { ConstraintName: "IX_Service_ServiceName_IsDeleted" })
{
_dbContext.ChangeTracker.Clear();
throw new ElementExistsException("ServiceName",
serviceDataModel.ServiceName);
serviceDataModel.ServiceName, _localizer);
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
throw new StorageException(ex, _localizer);
}
}
@@ -143,7 +147,7 @@ internal class ServiceStorageContract : IServiceStorageContract
try
{
var element = GetServiceById(serviceDataModel.Id) ??
throw new ElementNotFoundException(serviceDataModel.Id);
throw new ElementNotFoundException(serviceDataModel.Id, _localizer);
if (element.Price != serviceDataModel.Price)
{
_dbContext.ServiceHistories.Add(new
@@ -167,7 +171,7 @@ internal class ServiceStorageContract : IServiceStorageContract
{
_dbContext.ChangeTracker.Clear();
throw new ElementExistsException("ProductName",
serviceDataModel.ServiceName);
serviceDataModel.ServiceName, _localizer);
}
catch (Exception ex) when (ex is ElementDeletedException || ex is
ElementNotFoundException)
@@ -178,7 +182,7 @@ internal class ServiceStorageContract : IServiceStorageContract
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
throw new StorageException(ex, _localizer);
}
}
@@ -187,7 +191,7 @@ internal class ServiceStorageContract : IServiceStorageContract
try
{
var element = GetServiceById(id) ?? throw new
ElementNotFoundException(id);
ElementNotFoundException(id, _localizer);
element.IsDeleted = true;
_dbContext.SaveChanges();
}
@@ -199,8 +203,42 @@ internal class ServiceStorageContract : IServiceStorageContract
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
throw new StorageException(ex, _localizer);
}
}
private Service? GetServiceById(string id) => _dbContext.Services.FirstOrDefault(x => x.Id == id && !x.IsDeleted);
public async Task<List<ServiceDataModel>> GetListAsync()
{
try
{
return [.. await _dbContext.Services
.Include(x => x.ServiceHistory)
.Where(x => !x.IsDeleted)
.Select(x => _mapper.Map<ServiceDataModel>(x))
.ToListAsync()];
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex, _localizer);
}
}
public async Task<List<ServiceDataModel>> GetListAsync(DateTime startDate, DateTime endDate, CancellationToken ct)
{
try
{
return [.. await _dbContext.Services
.Include(x => x.ServiceHistory)
.Where(x => !x.IsDeleted)
.Select(x => _mapper.Map<ServiceDataModel>(x))
.ToListAsync(ct)];
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex, _localizer);
}
}
}

View File

@@ -0,0 +1,219 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace TwoFromTheCasketDatabase.Migrations
{
/// <inheritdoc />
public partial class FirstMigration : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Masters",
columns: table => new
{
Id = table.Column<string>(type: "text", nullable: false),
FIO = table.Column<string>(type: "text", nullable: false),
PostId = table.Column<string>(type: "text", nullable: false),
BirthDate = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
EmploymentDate = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
IsDeleted = table.Column<bool>(type: "boolean", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Masters", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Orders",
columns: table => new
{
Id = table.Column<string>(type: "text", nullable: false),
Date = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
Status = table.Column<int>(type: "integer", nullable: false),
RoomType = table.Column<int>(type: "integer", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Orders", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Posts",
columns: table => new
{
Id = table.Column<string>(type: "text", nullable: false),
PostId = table.Column<string>(type: "text", nullable: false),
PostName = table.Column<string>(type: "text", nullable: false),
PostType = table.Column<int>(type: "integer", nullable: false),
Salary = table.Column<double>(type: "double precision", nullable: false),
IsActual = table.Column<bool>(type: "boolean", nullable: false),
ChangeDate = table.Column<DateTime>(type: "timestamp with time zone", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Posts", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Salaries",
columns: table => new
{
Id = table.Column<string>(type: "text", nullable: false),
MasterId = table.Column<string>(type: "text", nullable: false),
SalaryDate = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
SalarySize = table.Column<double>(type: "double precision", nullable: false),
Prize = table.Column<double>(type: "double precision", nullable: false),
SalaryId = table.Column<string>(type: "text", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_Salaries", x => x.Id);
table.ForeignKey(
name: "FK_Salaries_Masters_SalaryId",
column: x => x.SalaryId,
principalTable: "Masters",
principalColumn: "Id");
});
migrationBuilder.CreateTable(
name: "ServiceOrders",
columns: table => new
{
OrderId = table.Column<string>(type: "text", nullable: false),
ServiceId = table.Column<string>(type: "text", nullable: false),
MasterId = table.Column<string>(type: "text", nullable: false),
TimeOfWorking = table.Column<int>(type: "integer", nullable: false),
ServiceOrderId = table.Column<string>(type: "text", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_ServiceOrders", x => new { x.ServiceId, x.MasterId, x.OrderId });
table.ForeignKey(
name: "FK_ServiceOrders_Masters_ServiceOrderId",
column: x => x.ServiceOrderId,
principalTable: "Masters",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "Services",
columns: table => new
{
Id = table.Column<string>(type: "text", nullable: false),
ServiceName = table.Column<string>(type: "text", nullable: false),
ServiceType = table.Column<int>(type: "integer", nullable: false),
MasterId = table.Column<string>(type: "text", nullable: false),
Price = table.Column<double>(type: "double precision", nullable: false),
IsDeleted = table.Column<bool>(type: "boolean", nullable: false),
ServiceId = table.Column<string>(type: "text", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_Services", x => x.Id);
table.ForeignKey(
name: "FK_Services_Masters_ServiceId",
column: x => x.ServiceId,
principalTable: "Masters",
principalColumn: "Id");
});
migrationBuilder.CreateTable(
name: "ServiceHistories",
columns: table => new
{
ServiceId = table.Column<string>(type: "text", nullable: false),
OldPrice = table.Column<double>(type: "double precision", nullable: false),
ChangeDate = table.Column<DateTime>(type: "timestamp with time zone", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_ServiceHistories", x => x.ServiceId);
table.ForeignKey(
name: "FK_ServiceHistories_Services_ServiceId",
column: x => x.ServiceId,
principalTable: "Services",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_Masters_Id_IsDeleted",
table: "Masters",
columns: new[] { "Id", "IsDeleted" },
unique: true,
filter: "\"IsDeleted\" = FALSE");
migrationBuilder.CreateIndex(
name: "IX_Orders_Id",
table: "Orders",
column: "Id",
unique: true);
migrationBuilder.CreateIndex(
name: "IX_Posts_PostId_IsActual",
table: "Posts",
columns: new[] { "PostId", "IsActual" },
unique: true,
filter: "\"IsActual\" = TRUE");
migrationBuilder.CreateIndex(
name: "IX_Posts_PostName_IsActual",
table: "Posts",
columns: new[] { "PostName", "IsActual" },
unique: true,
filter: "\"IsActual\" = TRUE");
migrationBuilder.CreateIndex(
name: "IX_Salaries_SalaryId",
table: "Salaries",
column: "SalaryId");
migrationBuilder.CreateIndex(
name: "IX_ServiceOrders_ServiceOrderId",
table: "ServiceOrders",
column: "ServiceOrderId");
migrationBuilder.CreateIndex(
name: "IX_Services_ServiceId",
table: "Services",
column: "ServiceId");
migrationBuilder.CreateIndex(
name: "IX_Services_ServiceName_IsDeleted",
table: "Services",
columns: new[] { "ServiceName", "IsDeleted" },
unique: true,
filter: "\"IsDeleted\" = FALSE");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Orders");
migrationBuilder.DropTable(
name: "Posts");
migrationBuilder.DropTable(
name: "Salaries");
migrationBuilder.DropTable(
name: "ServiceHistories");
migrationBuilder.DropTable(
name: "ServiceOrders");
migrationBuilder.DropTable(
name: "Services");
migrationBuilder.DropTable(
name: "Masters");
}
}
}

View File

@@ -0,0 +1,277 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
using TwoFromTheCasketDatabase;
#nullable disable
namespace TwoFromTheCasketDatabase.Migrations
{
[DbContext(typeof(TwoFromTheCasketDbContext))]
[Migration("20250907135104_ChangeFieldsInPost")]
partial class ChangeFieldsInPost
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "9.0.1")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("TwoFromTheCasketDatabase.Models.Master", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<DateTime>("BirthDate")
.HasColumnType("timestamp with time zone");
b.Property<DateTime>("EmploymentDate")
.HasColumnType("timestamp with time zone");
b.Property<string>("FIO")
.IsRequired()
.HasColumnType("text");
b.Property<bool>("IsDeleted")
.HasColumnType("boolean");
b.Property<string>("PostId")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("Id", "IsDeleted")
.IsUnique()
.HasFilter("\"IsDeleted\" = FALSE");
b.ToTable("Masters");
});
modelBuilder.Entity("TwoFromTheCasketDatabase.Models.Order", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<DateTime>("Date")
.HasColumnType("timestamp with time zone");
b.Property<int>("RoomType")
.HasColumnType("integer");
b.Property<int>("Status")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("Id")
.IsUnique();
b.ToTable("Orders");
});
modelBuilder.Entity("TwoFromTheCasketDatabase.Models.Post", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<DateTime>("ChangeDate")
.HasColumnType("timestamp with time zone");
b.Property<string>("Configuration")
.IsRequired()
.HasColumnType("jsonb");
b.Property<bool>("IsActual")
.HasColumnType("boolean");
b.Property<string>("PostId")
.IsRequired()
.HasColumnType("text");
b.Property<string>("PostName")
.IsRequired()
.HasColumnType("text");
b.Property<int>("PostType")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("PostId", "IsActual")
.IsUnique()
.HasFilter("\"IsActual\" = TRUE");
b.HasIndex("PostName", "IsActual")
.IsUnique()
.HasFilter("\"IsActual\" = TRUE");
b.ToTable("Posts");
});
modelBuilder.Entity("TwoFromTheCasketDatabase.Models.Salary", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("MasterId")
.IsRequired()
.HasColumnType("text");
b.Property<double>("Prize")
.HasColumnType("double precision");
b.Property<DateTime>("SalaryDate")
.HasColumnType("timestamp with time zone");
b.Property<string>("SalaryId")
.HasColumnType("text");
b.Property<double>("SalarySize")
.HasColumnType("double precision");
b.HasKey("Id");
b.HasIndex("SalaryId");
b.ToTable("Salaries");
});
modelBuilder.Entity("TwoFromTheCasketDatabase.Models.Service", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<bool>("IsDeleted")
.HasColumnType("boolean");
b.Property<string>("MasterId")
.IsRequired()
.HasColumnType("text");
b.Property<double>("Price")
.HasColumnType("double precision");
b.Property<string>("ServiceId")
.HasColumnType("text");
b.Property<string>("ServiceName")
.IsRequired()
.HasColumnType("text");
b.Property<int>("ServiceType")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("ServiceId");
b.HasIndex("ServiceName", "IsDeleted")
.IsUnique()
.HasFilter("\"IsDeleted\" = FALSE");
b.ToTable("Services");
});
modelBuilder.Entity("TwoFromTheCasketDatabase.Models.ServiceHistory", b =>
{
b.Property<string>("ServiceId")
.HasColumnType("text");
b.Property<DateTime>("ChangeDate")
.HasColumnType("timestamp with time zone");
b.Property<double>("OldPrice")
.HasColumnType("double precision");
b.HasKey("ServiceId");
b.ToTable("ServiceHistories");
});
modelBuilder.Entity("TwoFromTheCasketDatabase.Models.ServiceOrder", b =>
{
b.Property<string>("ServiceId")
.HasColumnType("text");
b.Property<string>("MasterId")
.HasColumnType("text");
b.Property<string>("OrderId")
.HasColumnType("text");
b.Property<string>("ServiceOrderId")
.IsRequired()
.HasColumnType("text");
b.Property<int>("TimeOfWorking")
.HasColumnType("integer");
b.HasKey("ServiceId", "MasterId", "OrderId");
b.HasIndex("ServiceOrderId");
b.ToTable("ServiceOrders");
});
modelBuilder.Entity("TwoFromTheCasketDatabase.Models.Salary", b =>
{
b.HasOne("TwoFromTheCasketDatabase.Models.Master", "Master")
.WithMany("Salaries")
.HasForeignKey("SalaryId");
b.Navigation("Master");
});
modelBuilder.Entity("TwoFromTheCasketDatabase.Models.Service", b =>
{
b.HasOne("TwoFromTheCasketDatabase.Models.Master", null)
.WithMany("Services")
.HasForeignKey("ServiceId");
});
modelBuilder.Entity("TwoFromTheCasketDatabase.Models.ServiceHistory", b =>
{
b.HasOne("TwoFromTheCasketDatabase.Models.Service", "Service")
.WithMany("ServiceHistory")
.HasForeignKey("ServiceId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Service");
});
modelBuilder.Entity("TwoFromTheCasketDatabase.Models.ServiceOrder", b =>
{
b.HasOne("TwoFromTheCasketDatabase.Models.Master", null)
.WithMany("ServiceOrders")
.HasForeignKey("ServiceOrderId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("TwoFromTheCasketDatabase.Models.Master", b =>
{
b.Navigation("Salaries");
b.Navigation("ServiceOrders");
b.Navigation("Services");
});
modelBuilder.Entity("TwoFromTheCasketDatabase.Models.Service", b =>
{
b.Navigation("ServiceHistory");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,40 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace TwoFromTheCasketDatabase.Migrations
{
/// <inheritdoc />
public partial class ChangeFieldsInPost : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "Salary",
table: "Posts");
migrationBuilder.AddColumn<string>(
name: "Configuration",
table: "Posts",
type: "jsonb",
nullable: false,
defaultValue: "{\"Rate\" : 0, \"Type\" : \"PostConfiguration\"}");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "Configuration",
table: "Posts");
migrationBuilder.AddColumn<double>(
name: "Salary",
table: "Posts",
type: "double precision",
nullable: false,
defaultValue: 0.0);
}
}
}

View File

@@ -0,0 +1,280 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
using TwoFromTheCasketDatabase;
#nullable disable
namespace TwoFromTheCasketDatabase.Migrations
{
[DbContext(typeof(TwoFromTheCasketDbContext))]
[Migration("20250907172931_AddDateOfDeleteToMasterAndIdToSalary")]
partial class AddDateOfDeleteToMasterAndIdToSalary
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "9.0.1")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("TwoFromTheCasketDatabase.Models.Master", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<DateTime>("BirthDate")
.HasColumnType("timestamp with time zone");
b.Property<DateTime?>("DateOfDelete")
.HasColumnType("timestamp with time zone");
b.Property<DateTime>("EmploymentDate")
.HasColumnType("timestamp with time zone");
b.Property<string>("FIO")
.IsRequired()
.HasColumnType("text");
b.Property<bool>("IsDeleted")
.HasColumnType("boolean");
b.Property<string>("PostId")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("Id", "IsDeleted")
.IsUnique()
.HasFilter("\"IsDeleted\" = FALSE");
b.ToTable("Masters");
});
modelBuilder.Entity("TwoFromTheCasketDatabase.Models.Order", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<DateTime>("Date")
.HasColumnType("timestamp with time zone");
b.Property<int>("RoomType")
.HasColumnType("integer");
b.Property<int>("Status")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("Id")
.IsUnique();
b.ToTable("Orders");
});
modelBuilder.Entity("TwoFromTheCasketDatabase.Models.Post", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<DateTime>("ChangeDate")
.HasColumnType("timestamp with time zone");
b.Property<string>("Configuration")
.IsRequired()
.HasColumnType("jsonb");
b.Property<bool>("IsActual")
.HasColumnType("boolean");
b.Property<string>("PostId")
.IsRequired()
.HasColumnType("text");
b.Property<string>("PostName")
.IsRequired()
.HasColumnType("text");
b.Property<int>("PostType")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("PostId", "IsActual")
.IsUnique()
.HasFilter("\"IsActual\" = TRUE");
b.HasIndex("PostName", "IsActual")
.IsUnique()
.HasFilter("\"IsActual\" = TRUE");
b.ToTable("Posts");
});
modelBuilder.Entity("TwoFromTheCasketDatabase.Models.Salary", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("MasterId")
.IsRequired()
.HasColumnType("text");
b.Property<double>("Prize")
.HasColumnType("double precision");
b.Property<DateTime>("SalaryDate")
.HasColumnType("timestamp with time zone");
b.Property<string>("SalaryId")
.HasColumnType("text");
b.Property<double>("SalarySize")
.HasColumnType("double precision");
b.HasKey("Id");
b.HasIndex("SalaryId");
b.ToTable("Salaries");
});
modelBuilder.Entity("TwoFromTheCasketDatabase.Models.Service", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<bool>("IsDeleted")
.HasColumnType("boolean");
b.Property<string>("MasterId")
.IsRequired()
.HasColumnType("text");
b.Property<double>("Price")
.HasColumnType("double precision");
b.Property<string>("ServiceId")
.HasColumnType("text");
b.Property<string>("ServiceName")
.IsRequired()
.HasColumnType("text");
b.Property<int>("ServiceType")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("ServiceId");
b.HasIndex("ServiceName", "IsDeleted")
.IsUnique()
.HasFilter("\"IsDeleted\" = FALSE");
b.ToTable("Services");
});
modelBuilder.Entity("TwoFromTheCasketDatabase.Models.ServiceHistory", b =>
{
b.Property<string>("ServiceId")
.HasColumnType("text");
b.Property<DateTime>("ChangeDate")
.HasColumnType("timestamp with time zone");
b.Property<double>("OldPrice")
.HasColumnType("double precision");
b.HasKey("ServiceId");
b.ToTable("ServiceHistories");
});
modelBuilder.Entity("TwoFromTheCasketDatabase.Models.ServiceOrder", b =>
{
b.Property<string>("ServiceId")
.HasColumnType("text");
b.Property<string>("MasterId")
.HasColumnType("text");
b.Property<string>("OrderId")
.HasColumnType("text");
b.Property<string>("ServiceOrderId")
.IsRequired()
.HasColumnType("text");
b.Property<int>("TimeOfWorking")
.HasColumnType("integer");
b.HasKey("ServiceId", "MasterId", "OrderId");
b.HasIndex("ServiceOrderId");
b.ToTable("ServiceOrders");
});
modelBuilder.Entity("TwoFromTheCasketDatabase.Models.Salary", b =>
{
b.HasOne("TwoFromTheCasketDatabase.Models.Master", "Master")
.WithMany("Salaries")
.HasForeignKey("SalaryId");
b.Navigation("Master");
});
modelBuilder.Entity("TwoFromTheCasketDatabase.Models.Service", b =>
{
b.HasOne("TwoFromTheCasketDatabase.Models.Master", null)
.WithMany("Services")
.HasForeignKey("ServiceId");
});
modelBuilder.Entity("TwoFromTheCasketDatabase.Models.ServiceHistory", b =>
{
b.HasOne("TwoFromTheCasketDatabase.Models.Service", "Service")
.WithMany("ServiceHistory")
.HasForeignKey("ServiceId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Service");
});
modelBuilder.Entity("TwoFromTheCasketDatabase.Models.ServiceOrder", b =>
{
b.HasOne("TwoFromTheCasketDatabase.Models.Master", null)
.WithMany("ServiceOrders")
.HasForeignKey("ServiceOrderId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("TwoFromTheCasketDatabase.Models.Master", b =>
{
b.Navigation("Salaries");
b.Navigation("ServiceOrders");
b.Navigation("Services");
});
modelBuilder.Entity("TwoFromTheCasketDatabase.Models.Service", b =>
{
b.Navigation("ServiceHistory");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,59 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace TwoFromTheCasketDatabase.Migrations
{
/// <inheritdoc />
public partial class AddDateOfDeleteToMasterAndIdToSalary : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_Salaries_Masters_MasterId",
table: "Salaries");
migrationBuilder.DropIndex(
name: "IX_Salaries_MasterId",
table: "Salaries");
migrationBuilder.CreateIndex(
name: "IX_Salaries_SalaryId",
table: "Salaries",
column: "SalaryId");
migrationBuilder.AddForeignKey(
name: "FK_Salaries_Masters_SalaryId",
table: "Salaries",
column: "SalaryId",
principalTable: "Masters",
principalColumn: "Id");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_Salaries_Masters_SalaryId",
table: "Salaries");
migrationBuilder.DropIndex(
name: "IX_Salaries_SalaryId",
table: "Salaries");
migrationBuilder.CreateIndex(
name: "IX_Salaries_MasterId",
table: "Salaries",
column: "MasterId");
migrationBuilder.AddForeignKey(
name: "FK_Salaries_Masters_MasterId",
table: "Salaries",
column: "MasterId",
principalTable: "Masters",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
}
}
}

View File

@@ -0,0 +1,285 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
using TwoFromTheCasketDatabase;
#nullable disable
namespace TwoFromTheCasketDatabase.Migrations
{
[DbContext(typeof(TwoFromTheCasketDbContext))]
[Migration("20250907182212_AddSalaryForeignKey")]
partial class AddSalaryForeignKey
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "9.0.1")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("TwoFromTheCasketDatabase.Models.Master", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<DateTime>("BirthDate")
.HasColumnType("timestamp with time zone");
b.Property<DateTime>("EmploymentDate")
.HasColumnType("timestamp with time zone");
b.Property<string>("FIO")
.IsRequired()
.HasColumnType("text");
b.Property<bool>("IsDeleted")
.HasColumnType("boolean");
b.Property<string>("PostId")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("Id", "IsDeleted")
.IsUnique()
.HasFilter("\"IsDeleted\" = FALSE");
b.ToTable("Masters");
});
modelBuilder.Entity("TwoFromTheCasketDatabase.Models.Order", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<DateTime>("Date")
.HasColumnType("timestamp with time zone");
b.Property<int>("RoomType")
.HasColumnType("integer");
b.Property<int>("Status")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("Id")
.IsUnique();
b.ToTable("Orders");
});
modelBuilder.Entity("TwoFromTheCasketDatabase.Models.Post", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<DateTime>("ChangeDate")
.HasColumnType("timestamp with time zone");
b.Property<string>("Configuration")
.IsRequired()
.HasColumnType("jsonb");
b.Property<bool>("IsActual")
.HasColumnType("boolean");
b.Property<string>("PostId")
.IsRequired()
.HasColumnType("text");
b.Property<string>("PostName")
.IsRequired()
.HasColumnType("text");
b.Property<int>("PostType")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("PostId", "IsActual")
.IsUnique()
.HasFilter("\"IsActual\" = TRUE");
b.HasIndex("PostName", "IsActual")
.IsUnique()
.HasFilter("\"IsActual\" = TRUE");
b.ToTable("Posts");
});
modelBuilder.Entity("TwoFromTheCasketDatabase.Models.Salary", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("MasterId")
.IsRequired()
.HasColumnType("text");
b.Property<double>("Prize")
.HasColumnType("double precision");
b.Property<DateTime>("SalaryDate")
.HasColumnType("timestamp with time zone");
b.Property<string>("SalaryId")
.HasColumnType("text");
b.Property<double>("SalarySize")
.HasColumnType("double precision");
b.HasKey("Id");
b.HasIndex("MasterId");
b.HasIndex("SalaryId");
b.ToTable("Salaries");
});
modelBuilder.Entity("TwoFromTheCasketDatabase.Models.Service", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<bool>("IsDeleted")
.HasColumnType("boolean");
b.Property<string>("MasterId")
.IsRequired()
.HasColumnType("text");
b.Property<double>("Price")
.HasColumnType("double precision");
b.Property<string>("ServiceId")
.HasColumnType("text");
b.Property<string>("ServiceName")
.IsRequired()
.HasColumnType("text");
b.Property<int>("ServiceType")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("ServiceId");
b.HasIndex("ServiceName", "IsDeleted")
.IsUnique()
.HasFilter("\"IsDeleted\" = FALSE");
b.ToTable("Services");
});
modelBuilder.Entity("TwoFromTheCasketDatabase.Models.ServiceHistory", b =>
{
b.Property<string>("ServiceId")
.HasColumnType("text");
b.Property<DateTime>("ChangeDate")
.HasColumnType("timestamp with time zone");
b.Property<double>("OldPrice")
.HasColumnType("double precision");
b.HasKey("ServiceId");
b.ToTable("ServiceHistories");
});
modelBuilder.Entity("TwoFromTheCasketDatabase.Models.ServiceOrder", b =>
{
b.Property<string>("ServiceId")
.HasColumnType("text");
b.Property<string>("MasterId")
.HasColumnType("text");
b.Property<string>("OrderId")
.HasColumnType("text");
b.Property<string>("ServiceOrderId")
.IsRequired()
.HasColumnType("text");
b.Property<int>("TimeOfWorking")
.HasColumnType("integer");
b.HasKey("ServiceId", "MasterId", "OrderId");
b.HasIndex("ServiceOrderId");
b.ToTable("ServiceOrders");
});
modelBuilder.Entity("TwoFromTheCasketDatabase.Models.Salary", b =>
{
b.HasOne("TwoFromTheCasketDatabase.Models.Master", "Master")
.WithMany()
.HasForeignKey("MasterId")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.HasOne("TwoFromTheCasketDatabase.Models.Master", null)
.WithMany("Salaries")
.HasForeignKey("SalaryId");
b.Navigation("Master");
});
modelBuilder.Entity("TwoFromTheCasketDatabase.Models.Service", b =>
{
b.HasOne("TwoFromTheCasketDatabase.Models.Master", null)
.WithMany("Services")
.HasForeignKey("ServiceId");
});
modelBuilder.Entity("TwoFromTheCasketDatabase.Models.ServiceHistory", b =>
{
b.HasOne("TwoFromTheCasketDatabase.Models.Service", "Service")
.WithMany("ServiceHistory")
.HasForeignKey("ServiceId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Service");
});
modelBuilder.Entity("TwoFromTheCasketDatabase.Models.ServiceOrder", b =>
{
b.HasOne("TwoFromTheCasketDatabase.Models.Master", null)
.WithMany("ServiceOrders")
.HasForeignKey("ServiceOrderId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("TwoFromTheCasketDatabase.Models.Master", b =>
{
b.Navigation("Salaries");
b.Navigation("ServiceOrders");
b.Navigation("Services");
});
modelBuilder.Entity("TwoFromTheCasketDatabase.Models.Service", b =>
{
b.Navigation("ServiceHistory");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,39 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace TwoFromTheCasketDatabase.Migrations
{
/// <inheritdoc />
public partial class AddSalaryForeignKey : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateIndex(
name: "IX_Salaries_MasterId",
table: "Salaries",
column: "MasterId");
migrationBuilder.AddForeignKey(
name: "FK_Salaries_Masters_MasterId",
table: "Salaries",
column: "MasterId",
principalTable: "Masters",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_Salaries_Masters_MasterId",
table: "Salaries");
migrationBuilder.DropIndex(
name: "IX_Salaries_MasterId",
table: "Salaries");
}
}
}

View File

@@ -0,0 +1,280 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
using TwoFromTheCasketDatabase;
#nullable disable
namespace TwoFromTheCasketDatabase.Migrations
{
[DbContext(typeof(TwoFromTheCasketDbContext))]
[Migration("20250907183927_FixSalaryForeignKeyConfiguration")]
partial class FixSalaryForeignKeyConfiguration
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "9.0.1")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("TwoFromTheCasketDatabase.Models.Master", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<DateTime>("BirthDate")
.HasColumnType("timestamp with time zone");
b.Property<DateTime>("EmploymentDate")
.HasColumnType("timestamp with time zone");
b.Property<string>("FIO")
.IsRequired()
.HasColumnType("text");
b.Property<bool>("IsDeleted")
.HasColumnType("boolean");
b.Property<string>("PostId")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("Id", "IsDeleted")
.IsUnique()
.HasFilter("\"IsDeleted\" = FALSE");
b.ToTable("Masters");
});
modelBuilder.Entity("TwoFromTheCasketDatabase.Models.Order", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<DateTime>("Date")
.HasColumnType("timestamp with time zone");
b.Property<int>("RoomType")
.HasColumnType("integer");
b.Property<int>("Status")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("Id")
.IsUnique();
b.ToTable("Orders");
});
modelBuilder.Entity("TwoFromTheCasketDatabase.Models.Post", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<DateTime>("ChangeDate")
.HasColumnType("timestamp with time zone");
b.Property<string>("Configuration")
.IsRequired()
.HasColumnType("jsonb");
b.Property<bool>("IsActual")
.HasColumnType("boolean");
b.Property<string>("PostId")
.IsRequired()
.HasColumnType("text");
b.Property<string>("PostName")
.IsRequired()
.HasColumnType("text");
b.Property<int>("PostType")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("PostId", "IsActual")
.IsUnique()
.HasFilter("\"IsActual\" = TRUE");
b.HasIndex("PostName", "IsActual")
.IsUnique()
.HasFilter("\"IsActual\" = TRUE");
b.ToTable("Posts");
});
modelBuilder.Entity("TwoFromTheCasketDatabase.Models.Salary", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("MasterId")
.IsRequired()
.HasColumnType("text");
b.Property<double>("Prize")
.HasColumnType("double precision");
b.Property<DateTime>("SalaryDate")
.HasColumnType("timestamp with time zone");
b.Property<string>("SalaryId")
.HasColumnType("text");
b.Property<double>("SalarySize")
.HasColumnType("double precision");
b.HasKey("Id");
b.HasIndex("MasterId", "SalaryDate")
.IsUnique();
b.ToTable("Salaries");
});
modelBuilder.Entity("TwoFromTheCasketDatabase.Models.Service", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<bool>("IsDeleted")
.HasColumnType("boolean");
b.Property<string>("MasterId")
.IsRequired()
.HasColumnType("text");
b.Property<double>("Price")
.HasColumnType("double precision");
b.Property<string>("ServiceId")
.HasColumnType("text");
b.Property<string>("ServiceName")
.IsRequired()
.HasColumnType("text");
b.Property<int>("ServiceType")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("ServiceId");
b.HasIndex("ServiceName", "IsDeleted")
.IsUnique()
.HasFilter("\"IsDeleted\" = FALSE");
b.ToTable("Services");
});
modelBuilder.Entity("TwoFromTheCasketDatabase.Models.ServiceHistory", b =>
{
b.Property<string>("ServiceId")
.HasColumnType("text");
b.Property<DateTime>("ChangeDate")
.HasColumnType("timestamp with time zone");
b.Property<double>("OldPrice")
.HasColumnType("double precision");
b.HasKey("ServiceId");
b.ToTable("ServiceHistories");
});
modelBuilder.Entity("TwoFromTheCasketDatabase.Models.ServiceOrder", b =>
{
b.Property<string>("ServiceId")
.HasColumnType("text");
b.Property<string>("MasterId")
.HasColumnType("text");
b.Property<string>("OrderId")
.HasColumnType("text");
b.Property<string>("ServiceOrderId")
.IsRequired()
.HasColumnType("text");
b.Property<int>("TimeOfWorking")
.HasColumnType("integer");
b.HasKey("ServiceId", "MasterId", "OrderId");
b.HasIndex("ServiceOrderId");
b.ToTable("ServiceOrders");
});
modelBuilder.Entity("TwoFromTheCasketDatabase.Models.Salary", b =>
{
b.HasOne("TwoFromTheCasketDatabase.Models.Master", "Master")
.WithMany("Salaries")
.HasForeignKey("MasterId")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.Navigation("Master");
});
modelBuilder.Entity("TwoFromTheCasketDatabase.Models.Service", b =>
{
b.HasOne("TwoFromTheCasketDatabase.Models.Master", null)
.WithMany("Services")
.HasForeignKey("ServiceId");
});
modelBuilder.Entity("TwoFromTheCasketDatabase.Models.ServiceHistory", b =>
{
b.HasOne("TwoFromTheCasketDatabase.Models.Service", "Service")
.WithMany("ServiceHistory")
.HasForeignKey("ServiceId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Service");
});
modelBuilder.Entity("TwoFromTheCasketDatabase.Models.ServiceOrder", b =>
{
b.HasOne("TwoFromTheCasketDatabase.Models.Master", null)
.WithMany("ServiceOrders")
.HasForeignKey("ServiceOrderId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("TwoFromTheCasketDatabase.Models.Master", b =>
{
b.Navigation("Salaries");
b.Navigation("ServiceOrders");
b.Navigation("Services");
});
modelBuilder.Entity("TwoFromTheCasketDatabase.Models.Service", b =>
{
b.Navigation("ServiceHistory");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,57 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace TwoFromTheCasketDatabase.Migrations
{
/// <inheritdoc />
public partial class FixSalaryForeignKeyConfiguration : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_Salaries_Masters_SalaryId",
table: "Salaries");
migrationBuilder.DropIndex(
name: "IX_Salaries_MasterId",
table: "Salaries");
migrationBuilder.DropIndex(
name: "IX_Salaries_SalaryId",
table: "Salaries");
migrationBuilder.CreateIndex(
name: "IX_Salaries_MasterId_SalaryDate",
table: "Salaries",
columns: new[] { "MasterId", "SalaryDate" },
unique: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropIndex(
name: "IX_Salaries_MasterId_SalaryDate",
table: "Salaries");
migrationBuilder.CreateIndex(
name: "IX_Salaries_MasterId",
table: "Salaries",
column: "MasterId");
migrationBuilder.CreateIndex(
name: "IX_Salaries_SalaryId",
table: "Salaries",
column: "SalaryId");
migrationBuilder.AddForeignKey(
name: "FK_Salaries_Masters_SalaryId",
table: "Salaries",
column: "SalaryId",
principalTable: "Masters",
principalColumn: "Id");
}
}
}

View File

@@ -0,0 +1,277 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
using TwoFromTheCasketDatabase;
#nullable disable
namespace TwoFromTheCasketDatabase.Migrations
{
[DbContext(typeof(TwoFromTheCasketDbContext))]
partial class TwoFromTheCasketDbContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "9.0.1")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("TwoFromTheCasketDatabase.Models.Master", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<DateTime>("BirthDate")
.HasColumnType("timestamp with time zone");
b.Property<DateTime>("EmploymentDate")
.HasColumnType("timestamp with time zone");
b.Property<string>("FIO")
.IsRequired()
.HasColumnType("text");
b.Property<bool>("IsDeleted")
.HasColumnType("boolean");
b.Property<string>("PostId")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("Id", "IsDeleted")
.IsUnique()
.HasFilter("\"IsDeleted\" = FALSE");
b.ToTable("Masters");
});
modelBuilder.Entity("TwoFromTheCasketDatabase.Models.Order", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<DateTime>("Date")
.HasColumnType("timestamp with time zone");
b.Property<int>("RoomType")
.HasColumnType("integer");
b.Property<int>("Status")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("Id")
.IsUnique();
b.ToTable("Orders");
});
modelBuilder.Entity("TwoFromTheCasketDatabase.Models.Post", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<DateTime>("ChangeDate")
.HasColumnType("timestamp with time zone");
b.Property<string>("Configuration")
.IsRequired()
.HasColumnType("jsonb");
b.Property<bool>("IsActual")
.HasColumnType("boolean");
b.Property<string>("PostId")
.IsRequired()
.HasColumnType("text");
b.Property<string>("PostName")
.IsRequired()
.HasColumnType("text");
b.Property<int>("PostType")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("PostId", "IsActual")
.IsUnique()
.HasFilter("\"IsActual\" = TRUE");
b.HasIndex("PostName", "IsActual")
.IsUnique()
.HasFilter("\"IsActual\" = TRUE");
b.ToTable("Posts");
});
modelBuilder.Entity("TwoFromTheCasketDatabase.Models.Salary", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("MasterId")
.IsRequired()
.HasColumnType("text");
b.Property<double>("Prize")
.HasColumnType("double precision");
b.Property<DateTime>("SalaryDate")
.HasColumnType("timestamp with time zone");
b.Property<string>("SalaryId")
.HasColumnType("text");
b.Property<double>("SalarySize")
.HasColumnType("double precision");
b.HasKey("Id");
b.HasIndex("MasterId", "SalaryDate")
.IsUnique();
b.ToTable("Salaries");
});
modelBuilder.Entity("TwoFromTheCasketDatabase.Models.Service", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<bool>("IsDeleted")
.HasColumnType("boolean");
b.Property<string>("MasterId")
.IsRequired()
.HasColumnType("text");
b.Property<double>("Price")
.HasColumnType("double precision");
b.Property<string>("ServiceId")
.HasColumnType("text");
b.Property<string>("ServiceName")
.IsRequired()
.HasColumnType("text");
b.Property<int>("ServiceType")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("ServiceId");
b.HasIndex("ServiceName", "IsDeleted")
.IsUnique()
.HasFilter("\"IsDeleted\" = FALSE");
b.ToTable("Services");
});
modelBuilder.Entity("TwoFromTheCasketDatabase.Models.ServiceHistory", b =>
{
b.Property<string>("ServiceId")
.HasColumnType("text");
b.Property<DateTime>("ChangeDate")
.HasColumnType("timestamp with time zone");
b.Property<double>("OldPrice")
.HasColumnType("double precision");
b.HasKey("ServiceId");
b.ToTable("ServiceHistories");
});
modelBuilder.Entity("TwoFromTheCasketDatabase.Models.ServiceOrder", b =>
{
b.Property<string>("ServiceId")
.HasColumnType("text");
b.Property<string>("MasterId")
.HasColumnType("text");
b.Property<string>("OrderId")
.HasColumnType("text");
b.Property<string>("ServiceOrderId")
.IsRequired()
.HasColumnType("text");
b.Property<int>("TimeOfWorking")
.HasColumnType("integer");
b.HasKey("ServiceId", "MasterId", "OrderId");
b.HasIndex("ServiceOrderId");
b.ToTable("ServiceOrders");
});
modelBuilder.Entity("TwoFromTheCasketDatabase.Models.Salary", b =>
{
b.HasOne("TwoFromTheCasketDatabase.Models.Master", "Master")
.WithMany("Salaries")
.HasForeignKey("MasterId")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.Navigation("Master");
});
modelBuilder.Entity("TwoFromTheCasketDatabase.Models.Service", b =>
{
b.HasOne("TwoFromTheCasketDatabase.Models.Master", null)
.WithMany("Services")
.HasForeignKey("ServiceId");
});
modelBuilder.Entity("TwoFromTheCasketDatabase.Models.ServiceHistory", b =>
{
b.HasOne("TwoFromTheCasketDatabase.Models.Service", "Service")
.WithMany("ServiceHistory")
.HasForeignKey("ServiceId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Service");
});
modelBuilder.Entity("TwoFromTheCasketDatabase.Models.ServiceOrder", b =>
{
b.HasOne("TwoFromTheCasketDatabase.Models.Master", null)
.WithMany("ServiceOrders")
.HasForeignKey("ServiceOrderId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("TwoFromTheCasketDatabase.Models.Master", b =>
{
b.Navigation("Salaries");
b.Navigation("ServiceOrders");
b.Navigation("Services");
});
modelBuilder.Entity("TwoFromTheCasketDatabase.Models.Service", b =>
{
b.Navigation("ServiceHistory");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -30,7 +30,6 @@ internal class Master
[ForeignKey("SalaryId")]
public List<Salary>? Salaries { get; set; }
[ForeignKey("ServiceOrderId")]
public List<ServiceOrder>? ServiceOrders { get; set; }
}

View File

@@ -5,6 +5,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TwoFromTheCasketContratcs.Enums;
using TwoFromTheCasketContratcs.Infrastructure.PostConfigurations;
namespace TwoFromTheCasketDatabase.Models;
@@ -18,7 +19,7 @@ internal class Post
public PostType PostType { get; set; }
public double Salary { get; set; }
public required PostConfiguration Configuration { get; set; }
public bool IsActual { get; set; }

View File

@@ -9,6 +9,8 @@ namespace TwoFromTheCasketDatabase.Models;
internal class ServiceHistory
{
public string Id { get; set; } = Guid.NewGuid().ToString();
public required string ServiceId { get; set; }
public required double OldPrice { get; set; }

View File

@@ -9,6 +9,7 @@ namespace TwoFromTheCasketDatabase.Models;
internal class ServiceOrder
{
public string ServiceOrderId { get; set; } = Guid.NewGuid().ToString();
public required string OrderId { get; set; }

View File

@@ -0,0 +1,16 @@
using Microsoft.EntityFrameworkCore.Design;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TwoFromTheCasketDatabase;
internal class SampleContextFactory : IDesignTimeDbContextFactory<TwoFromTheCasketDbContext>
{
public TwoFromTheCasketDbContext CreateDbContext(string[] args)
{
return new TwoFromTheCasketDbContext(new DefaultConfigurationDatabase());
}
}

View File

@@ -8,6 +8,11 @@
<ItemGroup>
<PackageReference Include="AutoMapper" Version="14.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="9.0.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.4" />
</ItemGroup>

View File

@@ -5,7 +5,10 @@ using System.Text;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
using TwoFromTheCasketContratcs.Infrastructure;
using TwoFromTheCasketContratcs.Infrastructure.PostConfigurations;
using TwoFromTheCasketDatabase.Models;
namespace TwoFromTheCasketDatabase;
@@ -38,16 +41,53 @@ internal class TwoFromTheCasketDbContext(IConfigurationDatabase configurationDat
.IsUnique()
.HasFilter($"\"{nameof(Post.IsActual)}\" = TRUE");
modelBuilder.Entity<ServiceHistory>().HasKey(x => x.ServiceId);
modelBuilder.Entity<ServiceHistory>().HasKey(x => x.Id);
modelBuilder.Entity<Service>().HasIndex(e => new { e.ServiceName, e.IsDeleted }).IsUnique().HasFilter($"\"{nameof(Service.IsDeleted)}\" = FALSE");
modelBuilder.Entity<ServiceOrder>().HasKey(x => new { x.ServiceId, x.MasterId, x.OrderId });
modelBuilder.Entity<ServiceOrder>().HasKey(x => x.ServiceOrderId);
// Настройка внешних ключей для ServiceOrder
modelBuilder.Entity<ServiceOrder>()
.HasOne<Order>()
.WithMany()
.HasForeignKey(so => so.OrderId)
.OnDelete(DeleteBehavior.Restrict);
modelBuilder.Entity<ServiceOrder>()
.HasOne<Service>()
.WithMany()
.HasForeignKey(so => so.ServiceId)
.OnDelete(DeleteBehavior.Restrict);
modelBuilder.Entity<ServiceOrder>()
.HasOne<Master>()
.WithMany(m => m.ServiceOrders)
.HasForeignKey(so => so.MasterId)
.OnDelete(DeleteBehavior.Restrict);
// Настройка внешнего ключа для Salary
modelBuilder.Entity<Salary>()
.HasOne(s => s.Master)
.WithMany(m => m.Salaries)
.HasForeignKey(s => s.MasterId)
.OnDelete(DeleteBehavior.Restrict);
// Настройка уникального индекса для Salary
modelBuilder.Entity<Salary>()
.HasIndex(s => new { s.MasterId, s.SalaryDate })
.IsUnique();
modelBuilder.Entity<Post>().Property(x => x.Configuration)
.HasColumnType("jsonb")
.HasConversion(
x => SerializePostConfiguration(x),
x => DeserializePostConfiguration(x)
);
}
public DbSet<Master> Masters { get; set; }
@@ -62,4 +102,36 @@ internal class TwoFromTheCasketDbContext(IConfigurationDatabase configurationDat
public DbSet<ServiceHistory> ServiceHistories { get; set; }
public DbSet<ServiceOrder> ServiceOrders { get; set; }
private static string SerializePostConfiguration(PostConfiguration postConfiguration) =>
JsonConvert.SerializeObject(postConfiguration, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.None,
Formatting = Formatting.None
});
private static PostConfiguration DeserializePostConfiguration(string jsonString)
{
try
{
var token = JToken.Parse(jsonString);
var typeValue = token.Value<string>("Type");
return typeValue switch
{
nameof(CarpenterPostConfiguration) =>
JsonConvert.DeserializeObject<CarpenterPostConfiguration>(jsonString)!,
nameof(PainterPostConfiguration) =>
JsonConvert.DeserializeObject<PainterPostConfiguration>(jsonString)!,
nameof(PlastererPostConfiguration) =>
JsonConvert.DeserializeObject<PlastererPostConfiguration>(jsonString)!,
_ => JsonConvert.DeserializeObject<PostConfiguration>(jsonString)!,
};
}
catch
{
// Fallback to basic PostConfiguration if deserialization fails
return new PostConfiguration { Rate = 0 };
}
}
}

View File

@@ -9,6 +9,7 @@ using TwoFromTheCasketContratcs.DataModels;
using TwoFromTheCasketContratcs.Enums;
using TwoFromTheCasketContratcs.Exceptions;
using TwoFromTheCasketContratcs.StorageContracts;
using TwoFromTheCasketTest.Infrastructure;
namespace TwoFromTheCasketTest.BuisnessLogicContractTests;
@@ -23,7 +24,7 @@ internal class MasterBusinessLogicContractTests
public void OneTimeSetUp()
{
_masterStorageContract = new Mock<IMasterStorageContract>();
_masterBusinessLogicContract = new MasterBusinessLogicContract(_masterStorageContract.Object, new Mock<ILogger>().Object);
_masterBusinessLogicContract = new MasterBusinessLogicContract(_masterStorageContract.Object, new Mock<ILogger>().Object, StringLocalizerMockCreator.GetObject());
}
[SetUp]
@@ -81,19 +82,12 @@ internal class MasterBusinessLogicContractTests
_masterStorageContract.Verify(x => x.GetList(It.IsAny<bool>(), null, null, null, null, null), Times.Exactly(2));
}
[Test]
public void GetAllMasters_ReturnNull_ThrowException_Test()
{
// Act & Assert
Assert.That(() => _masterBusinessLogicContract.GetAllMasters(It.IsAny<bool>()), Throws.TypeOf<NullListException>());
_masterStorageContract.Verify(x => x.GetList(It.IsAny<bool>(), It.IsAny<string?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>()), Times.Once);
}
[Test]
public void GetAllMasters_StorageThrowError_ThrowException_Test()
{
// Arrange
_masterStorageContract.Setup(x => x.GetList(It.IsAny<bool>(), It.IsAny<string?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>())).Throws(new StorageException(new InvalidOperationException()));
_masterStorageContract.Setup(x => x.GetList(It.IsAny<bool>(), It.IsAny<string?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>())).Throws(new StorageException(new InvalidOperationException(), StringLocalizerMockCreator.GetObject()));
// Act & Assert
Assert.That(() => _masterBusinessLogicContract.GetAllMasters(It.IsAny<bool>()), Throws.TypeOf<StorageException>());
@@ -167,19 +161,13 @@ internal class MasterBusinessLogicContractTests
_masterStorageContract.Verify(x => x.GetList(It.IsAny<bool>(), It.IsAny<string>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>()), Times.Never);
}
[Test]
public void GetAllMastersByPost_ReturnNull_ThrowException_Test()
{
// Act & Assert
Assert.That(() => _masterBusinessLogicContract.GetAllMastersByPost(Guid.NewGuid().ToString(), It.IsAny<bool>()), Throws.TypeOf<NullListException>());
_masterStorageContract.Verify(x => x.GetList(It.IsAny<bool>(), It.IsAny<string>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>()), Times.Once);
}
[Test]
public void GetAllMastersByPost_StorageThrowError_ThrowException_Test()
{
// Arrange
_masterStorageContract.Setup(x => x.GetList(It.IsAny<bool>(), It.IsAny<string?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>())).Throws(new StorageException(new InvalidOperationException()));
_masterStorageContract.Setup(x => x.GetList(It.IsAny<bool>(), It.IsAny<string?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>())).Throws(new StorageException(new InvalidOperationException(), StringLocalizerMockCreator.GetObject()));
// Act & Assert
Assert.That(() => _masterBusinessLogicContract.GetAllMastersByPost(Guid.NewGuid().ToString(), It.IsAny<bool>()), Throws.TypeOf<StorageException>());
@@ -249,19 +237,13 @@ internal class MasterBusinessLogicContractTests
_masterStorageContract.Verify(x => x.GetList(It.IsAny<bool>(), It.IsAny<string?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>()), Times.Never);
}
[Test]
public void GetAllMastersByBirthDate_ReturnNull_ThrowException_Test()
{
// Act & Assert
Assert.That(() => _masterBusinessLogicContract.GetAllMastersByBirthDate(DateTime.UtcNow, DateTime.UtcNow.AddDays(1), It.IsAny<bool>()), Throws.TypeOf<NullListException>());
_masterStorageContract.Verify(x => x.GetList(It.IsAny<bool>(), It.IsAny<string?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>()), Times.Once);
}
[Test]
public void GetAllMastersByBirthDate_StorageThrowError_ThrowException_Test()
{
// Arrange
_masterStorageContract.Setup(x => x.GetList(It.IsAny<bool>(), It.IsAny<string?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>())).Throws(new StorageException(new InvalidOperationException()));
_masterStorageContract.Setup(x => x.GetList(It.IsAny<bool>(), It.IsAny<string?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>())).Throws(new StorageException(new InvalidOperationException(), StringLocalizerMockCreator.GetObject()));
// Act & Assert
Assert.That(() => _masterBusinessLogicContract.GetAllMastersByBirthDate(DateTime.UtcNow, DateTime.UtcNow.AddDays(1), It.IsAny<bool>()), Throws.TypeOf<StorageException>());
@@ -331,19 +313,13 @@ internal class MasterBusinessLogicContractTests
_masterStorageContract.Verify(x => x.GetList(It.IsAny<bool>(), It.IsAny<string?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>()), Times.Never);
}
[Test]
public void GetAllMastersByEmploymentDate_ReturnNull_ThrowException_Test()
{
// Act & Assert
Assert.That(() => _masterBusinessLogicContract.GetAllMastersByEmploymentDate(DateTime.UtcNow, DateTime.UtcNow.AddDays(1), It.IsAny<bool>()), Throws.TypeOf<NullListException>());
_masterStorageContract.Verify(x => x.GetList(It.IsAny<bool>(), It.IsAny<string?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>()), Times.Once);
}
[Test]
public void GetAllMastersByEmploymentDate_StorageThrowError_ThrowException_Test()
{
// Arrange
_masterStorageContract.Setup(x => x.GetList(It.IsAny<bool>(), It.IsAny<string?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>())).Throws(new StorageException(new InvalidOperationException()));
_masterStorageContract.Setup(x => x.GetList(It.IsAny<bool>(), It.IsAny<string?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>())).Throws(new StorageException(new InvalidOperationException(), StringLocalizerMockCreator.GetObject()));
// Act & Assert
Assert.That(() => _masterBusinessLogicContract.GetAllMastersByEmploymentDate(DateTime.UtcNow, DateTime.UtcNow.AddDays(1), It.IsAny<bool>()), Throws.TypeOf<StorageException>());
@@ -416,8 +392,8 @@ internal class MasterBusinessLogicContractTests
public void GetMasterByData_StorageThrowError_ThrowException_Test()
{
// Arrange
_masterStorageContract.Setup(x => x.GetElementById(It.IsAny<string>())).Throws(new StorageException(new InvalidOperationException()));
_masterStorageContract.Setup(x => x.GetElementByFIO(It.IsAny<string>())).Throws(new StorageException(new InvalidOperationException()));
_masterStorageContract.Setup(x => x.GetElementById(It.IsAny<string>())).Throws(new StorageException(new InvalidOperationException(), StringLocalizerMockCreator.GetObject()));
_masterStorageContract.Setup(x => x.GetElementByFIO(It.IsAny<string>())).Throws(new StorageException(new InvalidOperationException(), StringLocalizerMockCreator.GetObject()));
// Act & Assert
Assert.That(() => _masterBusinessLogicContract.GetMasterByData(Guid.NewGuid().ToString()), Throws.TypeOf<StorageException>());
@@ -451,7 +427,7 @@ internal class MasterBusinessLogicContractTests
public void InsertMaster_RecordWithExistsData_ThrowException_Test()
{
// Arrange
_masterStorageContract.Setup(x => x.AddElement(It.IsAny<MasterDataModel>())).Throws(new ElementExistsException("Data", "Data"));
_masterStorageContract.Setup(x => x.AddElement(It.IsAny<MasterDataModel>())).Throws(new ElementExistsException("Data", "Data", StringLocalizerMockCreator.GetObject()));
// Act & Assert
Assert.That(() => _masterBusinessLogicContract.InsertMaster(new(Guid.NewGuid().ToString(), "Иван Иван Иван", Guid.NewGuid().ToString(), DateTime.Now.AddYears(-16).AddDays(-1), DateTime.Now, false)), Throws.TypeOf<ElementExistsException>());
@@ -478,7 +454,7 @@ internal class MasterBusinessLogicContractTests
public void InsertMaster_StorageThrowError_ThrowException_Test()
{
// Arrange
_masterStorageContract.Setup(x => x.AddElement(It.IsAny<MasterDataModel>())).Throws(new StorageException(new InvalidOperationException()));
_masterStorageContract.Setup(x => x.AddElement(It.IsAny<MasterDataModel>())).Throws(new StorageException(new InvalidOperationException(), StringLocalizerMockCreator.GetObject()));
// Act & Assert
Assert.That(() => _masterBusinessLogicContract.InsertMaster(new(Guid.NewGuid().ToString(), "Иван Иван Ивна", Guid.NewGuid().ToString(), DateTime.Now.AddYears(-16).AddDays(-1), DateTime.Now, false)), Throws.TypeOf<StorageException>());
@@ -510,7 +486,7 @@ internal class MasterBusinessLogicContractTests
public void UpdateMaster_RecordWithIncorrectData_ThrowException_Test()
{
// Arrange
_masterStorageContract.Setup(x => x.UpdElement(It.IsAny<MasterDataModel>())).Throws(new ElementNotFoundException(""));
_masterStorageContract.Setup(x => x.UpdElement(It.IsAny<MasterDataModel>())).Throws(new ElementNotFoundException("", StringLocalizerMockCreator.GetObject()));
// Act & Assert
Assert.That(() => _masterBusinessLogicContract.UpdateMaster(new(Guid.NewGuid().ToString(), "Иван Иван Иван", Guid.NewGuid().ToString(), DateTime.Now.AddYears(-16).AddDays(-1), DateTime.Now, false)), Throws.TypeOf<ElementNotFoundException>());
@@ -537,7 +513,7 @@ internal class MasterBusinessLogicContractTests
public void UpdateMaster_StorageThrowError_ThrowException_Test()
{
// Arrange
_masterStorageContract.Setup(x => x.UpdElement(It.IsAny<MasterDataModel>())).Throws(new StorageException(new InvalidOperationException()));
_masterStorageContract.Setup(x => x.UpdElement(It.IsAny<MasterDataModel>())).Throws(new StorageException(new InvalidOperationException(), StringLocalizerMockCreator.GetObject()));
// Act & Assert
Assert.That(() => _masterBusinessLogicContract.UpdateMaster(new(Guid.NewGuid().ToString(), "Иван Иван Иван", Guid.NewGuid().ToString(), DateTime.Now.AddYears(-16).AddDays(-1), DateTime.Now, false)), Throws.TypeOf<StorageException>());
@@ -565,7 +541,7 @@ internal class MasterBusinessLogicContractTests
{
// Arrange
var id = Guid.NewGuid().ToString();
_masterStorageContract.Setup(x => x.DelElement(It.Is((string x) => x != id))).Throws(new ElementNotFoundException(id));
_masterStorageContract.Setup(x => x.DelElement(It.Is((string x) => x != id))).Throws(new ElementNotFoundException(id, StringLocalizerMockCreator.GetObject()));
// Act & Assert
Assert.That(() => _masterBusinessLogicContract.DeleteMaster(Guid.NewGuid().ToString()), Throws.TypeOf<ElementNotFoundException>());
@@ -593,7 +569,7 @@ internal class MasterBusinessLogicContractTests
public void DeleteMaster_StorageThrowError_ThrowException_Test()
{
// Arrange
_masterStorageContract.Setup(x => x.DelElement(It.IsAny<string>())).Throws(new StorageException(new InvalidOperationException()));
_masterStorageContract.Setup(x => x.DelElement(It.IsAny<string>())).Throws(new StorageException(new InvalidOperationException(), StringLocalizerMockCreator.GetObject()));
// Act & Assert
Assert.That(() => _masterBusinessLogicContract.DeleteMaster(Guid.NewGuid().ToString()), Throws.TypeOf<StorageException>());

View File

@@ -9,6 +9,7 @@ using TwoFromTheCasketContratcs.DataModels;
using TwoFromTheCasketContratcs.Enums;
using TwoFromTheCasketContratcs.Exceptions;
using TwoFromTheCasketContratcs.StorageContracts;
using TwoFromTheCasketTest.Infrastructure;
namespace TwoFromTheCasketTest.BuisnessLogicContractTests;
@@ -22,7 +23,7 @@ internal class OrderBusinessLogicContractTests
public void OneTimeSetUp()
{
_orderStorageContract = new Mock<IOrderStorageContract>();
_orderBusinessLogicContract = new OrderBusinessLogicContract(_orderStorageContract.Object, new Mock<ILogger>().Object);
_orderBusinessLogicContract = new OrderBusinessLogicContract(_orderStorageContract.Object, new Mock<ILogger>().Object, StringLocalizerMockCreator.GetObject());
}
[SetUp]
@@ -71,22 +72,11 @@ internal class OrderBusinessLogicContractTests
});
}
[Test]
public void GetAllOrder_ReturnNull_ThrowException_Test()
{
// Arrange
_orderStorageContract.Setup(x => x.GetList()).Returns((List<OrderDataModel>)null!);
// Act & Assert
Assert.That(() => _orderBusinessLogicContract.GetAllOrder(), Throws.TypeOf<NullListException>());
_orderStorageContract.Verify(x => x.GetList(), Times.Once);
}
[Test]
public void GetAllOrder_StorageThrowError_ThrowException_Test()
{
// Arrange
_orderStorageContract.Setup(x => x.GetList()).Throws(new StorageException(new InvalidOperationException()));
_orderStorageContract.Setup(x => x.GetList()).Throws(new StorageException(new InvalidOperationException(), StringLocalizerMockCreator.GetObject()));
// Act & Assert
Assert.That(() => _orderBusinessLogicContract.GetAllOrder(), Throws.TypeOf<StorageException>());
@@ -113,23 +103,7 @@ internal class OrderBusinessLogicContractTests
_orderStorageContract.Verify(x => x.GetElementByDate(fromDate), Times.Once);
}
[Test]
public void GetOrderByDate_ThrowsNullListException_WhenNoData_Test()
{
// Arrange
var fromDate = DateTime.UtcNow.AddDays(-7);
_orderStorageContract.Setup(x => x.GetElementByDate(It.IsAny<DateTime>()))
.Returns((OrderDataModel)null);
// Act & Assert
Assert.That(() => _orderBusinessLogicContract.GetOrderByDate(fromDate),
Throws.TypeOf<NullListException>());
_orderStorageContract.Verify(x => x.GetElementByDate(It.IsAny<DateTime>()), Times.Once);
}
[Test]
public void GetOrderByData_ReturnRecord_Test()

View File

@@ -9,6 +9,8 @@ using TwoFromTheCasketContratcs.DataModels;
using TwoFromTheCasketContratcs.Enums;
using TwoFromTheCasketContratcs.Exceptions;
using TwoFromTheCasketContratcs.StorageContracts;
using TwoFromTheCasketContratcs.Infrastructure.PostConfigurations;
using TwoFromTheCasketTest.Infrastructure;
namespace TwoFromTheCasketTest.BuisnessLogicContractTests;
@@ -22,7 +24,7 @@ internal class PostBusinessLogicContractTests
public void OneTimeSetUp()
{
_postStorageContract = new Mock<IPostStorageContract>();
_postBusinessLogicContract = new PostBusinessLogicContract(_postStorageContract.Object, new Mock<ILogger>().Object);
_postBusinessLogicContract = new PostBusinessLogicContract(_postStorageContract.Object, new Mock<ILogger>().Object, StringLocalizerMockCreator.GetObject());
}
[SetUp]
@@ -37,9 +39,9 @@ internal class PostBusinessLogicContractTests
// Arrange
var listOriginal = new List<PostDataModel>()
{
new(Guid.NewGuid().ToString(), "name 1", PostType.Carpenter, 10),
new(Guid.NewGuid().ToString(), "name 2", PostType.Carpenter, 10),
new(Guid.NewGuid().ToString(), "name 3", PostType.Carpenter, 10),
new(Guid.NewGuid().ToString(), "name 1", PostType.Carpenter, new PostConfiguration {Rate = 10}),
new(Guid.NewGuid().ToString(), "name 2", PostType.Carpenter, new PostConfiguration {Rate = 10}),
new(Guid.NewGuid().ToString(), "name 3", PostType.Carpenter, new PostConfiguration { Rate = 10 }),
};
_postStorageContract.Setup(x => x.GetList()).Returns(listOriginal);
@@ -72,20 +74,13 @@ internal class PostBusinessLogicContractTests
});
}
[Test]
public void GetAllPosts_ReturnNull_ThrowException_Test()
{
// Act & Assert
Assert.That(() => _postBusinessLogicContract.GetAllPosts(), Throws.TypeOf<NullListException>());
_postStorageContract.Verify(x => x.GetList( ), Times.Once);
_postStorageContract.Verify(x => x.GetList(), Times.Once);
}
[Test]
public void GetAllPosts_StorageThrowError_ThrowException_Test()
{
// Arrange
_postStorageContract.Setup(x => x.GetList()).Throws(new StorageException(new InvalidOperationException()));
_postStorageContract.Setup(x => x.GetList()).Throws(new StorageException(new InvalidOperationException(), StringLocalizerMockCreator.GetObject()));
// Act & Assert
Assert.That(() => _postBusinessLogicContract.GetAllPosts(), Throws.TypeOf<StorageException>());
@@ -100,8 +95,8 @@ internal class PostBusinessLogicContractTests
var postId = Guid.NewGuid().ToString();
var listOriginal = new List<PostDataModel>()
{
new(postId, "name 1", PostType.Painter, 10),
new(postId, "name 2", PostType.Painter, 10)
new(postId, "name 1", PostType.Painter, new PostConfiguration { Rate = 10 }),
new(postId, "name 2", PostType.Painter, new PostConfiguration { Rate = 10 })
};
_postStorageContract.Setup(x => x.GetPostWithHistory(It.IsAny<string>())).Returns(listOriginal);
@@ -146,19 +141,12 @@ internal class PostBusinessLogicContractTests
_postStorageContract.Verify(x => x.GetPostWithHistory(It.IsAny<string>()), Times.Never);
}
[Test]
public void GetAllDataOfPost_ReturnNull_ThrowException_Test()
{
// Act & Assert
Assert.That(() => _postBusinessLogicContract.GetAllDataOfPost(Guid.NewGuid().ToString()), Throws.TypeOf<NullListException>());
_postStorageContract.Verify(x => x.GetPostWithHistory(It.IsAny<string>()), Times.Once);
}
[Test]
public void GetAllDataOfPost_StorageThrowError_ThrowException_Test()
{
// Arrange
_postStorageContract.Setup(x => x.GetPostWithHistory(It.IsAny<string>())).Throws(new StorageException(new InvalidOperationException()));
_postStorageContract.Setup(x => x.GetPostWithHistory(It.IsAny<string>())).Throws(new StorageException(new InvalidOperationException(), StringLocalizerMockCreator.GetObject()));
// Act & Assert
Assert.That(() => _postBusinessLogicContract.GetAllDataOfPost(Guid.NewGuid().ToString()), Throws.TypeOf<StorageException>());
@@ -170,7 +158,7 @@ internal class PostBusinessLogicContractTests
{
// Arrange
var id = Guid.NewGuid().ToString();
var record = new PostDataModel(id, "name", PostType.Painter, 10);
var record = new PostDataModel(id, "name", PostType.Painter, new PostConfiguration { Rate = 10 });
_postStorageContract.Setup(x => x.GetElementById(id)).Returns(record);
// Act
@@ -187,7 +175,7 @@ internal class PostBusinessLogicContractTests
{
// Arrange
var postName = "name";
var record = new PostDataModel(Guid.NewGuid().ToString(), postName, PostType.Plasterer, 10);
var record = new PostDataModel(Guid.NewGuid().ToString(), postName, PostType.Plasterer, new PostConfiguration { Rate = 10 });
_postStorageContract.Setup(x => x.GetElementByName(postName)).Returns(record);
// Act
@@ -231,8 +219,8 @@ internal class PostBusinessLogicContractTests
public void GetPostByData_StorageThrowError_ThrowException_Test()
{
// Arrange
_postStorageContract.Setup(x => x.GetElementById(It.IsAny<string>())).Throws(new StorageException(new InvalidOperationException()));
_postStorageContract.Setup(x => x.GetElementByName(It.IsAny<string>())).Throws(new StorageException(new InvalidOperationException()));
_postStorageContract.Setup(x => x.GetElementById(It.IsAny<string>())).Throws(new StorageException(new InvalidOperationException(), StringLocalizerMockCreator.GetObject()));
_postStorageContract.Setup(x => x.GetElementByName(It.IsAny<string>())).Throws(new StorageException(new InvalidOperationException(), StringLocalizerMockCreator.GetObject()));
// Act & Assert
Assert.That(() => _postBusinessLogicContract.GetPostByData(Guid.NewGuid().ToString()), Throws.TypeOf<StorageException>());
@@ -246,11 +234,11 @@ internal class PostBusinessLogicContractTests
{
// Arrange
var flag = false;
var record = new PostDataModel(Guid.NewGuid().ToString(), "name 1", PostType.Plasterer, 10);
var record = new PostDataModel(Guid.NewGuid().ToString(), "name 1", PostType.Plasterer, new PostConfiguration { Rate = 10 });
_postStorageContract.Setup(x => x.AddElement(It.IsAny<PostDataModel>()))
.Callback((PostDataModel x) =>
{
flag = x.Id == record.Id && x.PostName == record.PostName && x.PostType == record.PostType && x.Salary == record.Salary;
flag = x.Id == record.Id && x.PostName == record.PostName && x.PostType == record.PostType && x.ConfigurationModel.Rate == record.ConfigurationModel.Rate;
});
// Act
@@ -265,10 +253,10 @@ internal class PostBusinessLogicContractTests
public void InsertPost_RecordWithExistsData_ThrowException_Test()
{
// Arrange
_postStorageContract.Setup(x => x.AddElement(It.IsAny<PostDataModel>())).Throws(new ElementExistsException("Data", "Data"));
_postStorageContract.Setup(x => x.AddElement(It.IsAny<PostDataModel>())).Throws(new ElementExistsException("Data", "Data", StringLocalizerMockCreator.GetObject()));
// Act & Assert
Assert.That(() => _postBusinessLogicContract.InsertPost(new(Guid.NewGuid().ToString(), "postName", PostType.Plasterer, 10)), Throws.TypeOf<ElementExistsException>());
Assert.That(() => _postBusinessLogicContract.InsertPost(new(Guid.NewGuid().ToString(), "postName", PostType.Plasterer, new PostConfiguration { Rate = 10 })), Throws.TypeOf<ElementExistsException>());
_postStorageContract.Verify(x => x.AddElement(It.IsAny<PostDataModel>()), Times.Once);
}
@@ -284,7 +272,7 @@ internal class PostBusinessLogicContractTests
public void InsertPost_InvalidRecord_ThrowException_Test()
{
// Act & Assert
Assert.That(() => _postBusinessLogicContract.InsertPost(new PostDataModel("id", "postName", PostType.Plasterer, 10)), Throws.TypeOf<ValidationException>());
Assert.That(() => _postBusinessLogicContract.InsertPost(new PostDataModel("id", "postName", PostType.Plasterer, new PostConfiguration { Rate = 10 })), Throws.TypeOf<ValidationException>());
_postStorageContract.Verify(x => x.AddElement(It.IsAny<PostDataModel>()), Times.Never);
}
@@ -292,10 +280,10 @@ internal class PostBusinessLogicContractTests
public void InsertPost_StorageThrowError_ThrowException_Test()
{
// Arrange
_postStorageContract.Setup(x => x.AddElement(It.IsAny<PostDataModel>())).Throws(new StorageException(new InvalidOperationException()));
_postStorageContract.Setup(x => x.AddElement(It.IsAny<PostDataModel>())).Throws(new StorageException(new InvalidOperationException(), StringLocalizerMockCreator.GetObject()));
// Act & Assert
Assert.That(() => _postBusinessLogicContract.InsertPost(new(Guid.NewGuid().ToString(), "postName", PostType.Plasterer, 10)), Throws.TypeOf<StorageException>());
Assert.That(() => _postBusinessLogicContract.InsertPost(new(Guid.NewGuid().ToString(), "postName", PostType.Plasterer, new PostConfiguration { Rate = 10 })), Throws.TypeOf<StorageException>());
_postStorageContract.Verify(x => x.AddElement(It.IsAny<PostDataModel>()), Times.Once);
}
@@ -304,11 +292,11 @@ internal class PostBusinessLogicContractTests
{
// Arrange
var flag = false;
var record = new PostDataModel(Guid.NewGuid().ToString(), "postName", PostType.Plasterer, 10);
var record = new PostDataModel(Guid.NewGuid().ToString(), "postName", PostType.Plasterer, new PostConfiguration { Rate = 10 });
_postStorageContract.Setup(x => x.UpdElement(It.IsAny<PostDataModel>()))
.Callback((PostDataModel x) =>
{
flag = x.Id == record.Id && x.PostName == record.PostName && x.PostType == record.PostType && x.Salary == record.Salary;
flag = x.Id == record.Id && x.PostName == record.PostName && x.PostType == record.PostType && x.ConfigurationModel.Rate == record.ConfigurationModel.Rate;
});
// Act
@@ -323,10 +311,10 @@ internal class PostBusinessLogicContractTests
public void UpdatePost_RecordWithIncorrectData_ThrowException_Test()
{
// Arrange
_postStorageContract.Setup(x => x.UpdElement(It.IsAny<PostDataModel>())).Throws(new ElementNotFoundException(""));
_postStorageContract.Setup(x => x.UpdElement(It.IsAny<PostDataModel>())).Throws(new ElementNotFoundException("", StringLocalizerMockCreator.GetObject()));
// Act & Assert
Assert.That(() => _postBusinessLogicContract.UpdatePost(new(Guid.NewGuid().ToString(), "postName", PostType.Plasterer, 10)), Throws.TypeOf<ElementNotFoundException>());
Assert.That(() => _postBusinessLogicContract.UpdatePost(new(Guid.NewGuid().ToString(), "postName", PostType.Plasterer, new PostConfiguration { Rate = 10 })), Throws.TypeOf<ElementNotFoundException>());
_postStorageContract.Verify(x => x.UpdElement(It.IsAny<PostDataModel>()), Times.Once);
}
@@ -334,10 +322,10 @@ internal class PostBusinessLogicContractTests
public void UpdatePost_RecordWithExistsData_ThrowException_Test()
{
// Arrange
_postStorageContract.Setup(x => x.UpdElement(It.IsAny<PostDataModel>())).Throws(new ElementExistsException("Data", "Data"));
_postStorageContract.Setup(x => x.UpdElement(It.IsAny<PostDataModel>())).Throws(new ElementExistsException("Data", "Data", StringLocalizerMockCreator.GetObject()));
// Act & Assert
Assert.That(() => _postBusinessLogicContract.UpdatePost(new(Guid.NewGuid().ToString(), "postName", PostType.Plasterer, 10)), Throws.TypeOf<ElementExistsException>());
Assert.That(() => _postBusinessLogicContract.UpdatePost(new(Guid.NewGuid().ToString(), "postName", PostType.Plasterer, new PostConfiguration { Rate = 10 })), Throws.TypeOf<ElementExistsException>());
_postStorageContract.Verify(x => x.UpdElement(It.IsAny<PostDataModel>()), Times.Once);
}
@@ -353,7 +341,7 @@ internal class PostBusinessLogicContractTests
public void UpdatePost_InvalidRecord_ThrowException_Test()
{
// Act & Assert
Assert.That(() => _postBusinessLogicContract.UpdatePost(new PostDataModel("id", "postName", PostType.Plasterer, 10)), Throws.TypeOf<ValidationException>());
Assert.That(() => _postBusinessLogicContract.UpdatePost(new PostDataModel("id", "postName", PostType.Plasterer, new PostConfiguration { Rate = 10 })), Throws.TypeOf<ValidationException>());
_postStorageContract.Verify(x => x.UpdElement(It.IsAny<PostDataModel>()), Times.Never);
}
@@ -361,10 +349,10 @@ internal class PostBusinessLogicContractTests
public void UpdatePost_StorageThrowError_ThrowException_Test()
{
// Arrange
_postStorageContract.Setup(x => x.UpdElement(It.IsAny<PostDataModel>())).Throws(new StorageException(new InvalidOperationException()));
_postStorageContract.Setup(x => x.UpdElement(It.IsAny<PostDataModel>())).Throws(new StorageException(new InvalidOperationException(), StringLocalizerMockCreator.GetObject()));
// Act & Assert
Assert.That(() => _postBusinessLogicContract.UpdatePost(new(Guid.NewGuid().ToString(), "postName", PostType.Plasterer, 10)), Throws.TypeOf<StorageException>());
Assert.That(() => _postBusinessLogicContract.UpdatePost(new(Guid.NewGuid().ToString(), "postName", PostType.Plasterer, new PostConfiguration { Rate = 10 })), Throws.TypeOf<StorageException>());
_postStorageContract.Verify(x => x.UpdElement(It.IsAny<PostDataModel>()), Times.Once);
}
@@ -389,7 +377,7 @@ internal class PostBusinessLogicContractTests
{
// Arrange
var id = Guid.NewGuid().ToString();
_postStorageContract.Setup(x => x.DelElement(It.IsAny<string>())).Throws(new ElementNotFoundException(id));
_postStorageContract.Setup(x => x.DelElement(It.IsAny<string>())).Throws(new ElementNotFoundException(id, StringLocalizerMockCreator.GetObject()));
// Act & Assert
Assert.That(() => _postBusinessLogicContract.DeletePost(Guid.NewGuid().ToString()), Throws.TypeOf<ElementNotFoundException>());
@@ -417,7 +405,7 @@ internal class PostBusinessLogicContractTests
public void DeletePost_StorageThrowError_ThrowException_Test()
{
// Arrange
_postStorageContract.Setup(x => x.DelElement(It.IsAny<string>())).Throws(new StorageException(new InvalidOperationException()));
_postStorageContract.Setup(x => x.DelElement(It.IsAny<string>())).Throws(new StorageException(new InvalidOperationException(), StringLocalizerMockCreator.GetObject()));
// Act & Assert
Assert.That(() => _postBusinessLogicContract.DeletePost(Guid.NewGuid().ToString()), Throws.TypeOf<StorageException>());
@@ -445,7 +433,7 @@ internal class PostBusinessLogicContractTests
{
// Arrange
var id = Guid.NewGuid().ToString();
_postStorageContract.Setup(x => x.ResElement(It.IsAny<string>())).Throws(new ElementNotFoundException(id));
_postStorageContract.Setup(x => x.ResElement(It.IsAny<string>())).Throws(new ElementNotFoundException(id, StringLocalizerMockCreator.GetObject()));
// Act & Assert
Assert.That(() => _postBusinessLogicContract.RestorePost(Guid.NewGuid().ToString()), Throws.TypeOf<ElementNotFoundException>());
@@ -473,7 +461,7 @@ internal class PostBusinessLogicContractTests
public void RestorePost_StorageThrowError_ThrowException_Test()
{
// Arrange
_postStorageContract.Setup(x => x.ResElement(It.IsAny<string>())).Throws(new StorageException(new InvalidOperationException()));
_postStorageContract.Setup(x => x.ResElement(It.IsAny<string>())).Throws(new StorageException(new InvalidOperationException(), StringLocalizerMockCreator.GetObject()));
// Act & Assert
Assert.That(() => _postBusinessLogicContract.RestorePost(Guid.NewGuid().ToString()), Throws.TypeOf<StorageException>());

View File

@@ -0,0 +1,256 @@
using TwoFromTheCasketBuisnessLogic.Implementations;
using TwoFromTheCasketBuisnessLogic.OfficePackage;
using TwoFromTheCasketContratcs.DataModels;
using TwoFromTheCasketContratcs.Enums;
using TwoFromTheCasketContratcs.Exceptions;
using TwoFromTheCasketContratcs.StorageContracts;
using Microsoft.Extensions.Logging;
using Moq;
using TwoFromTheCasketContratcs.Infrastructure.PostConfigurations;
using Microsoft.Extensions.Localization;
using TwoFromTheCasketContratcs.Resources;
using TwoFromTheCasketTest.Infrastructure;
namespace TwoFromTheCasketTest.BuisnessLogicContractTests;
[TestFixture]
internal class ReportContractTests
{
private ReportContract _reportContract;
private Mock<IServiceStorageContract> _serviceStorageContract;
private Mock<IMasterStorageContract> _masterStorageContract;
private Mock<IOrderStorageContract> _orderStorageContract;
private Mock<ISalaryStorageContract> _salaryStorageContract;
private Mock<IPostStorageContract> _postStorageContract;
private Mock<BaseWordBuilder> _baseWordBuilder;
private Mock<BaseExcelBuilder> _baseExcelBuilder;
private Mock<BasePdfBuilder> _basePdfBuilder;
private IStringLocalizer<Messages> _localizer;
[OneTimeSetUp]
public void OneTimeSetUp()
{
_serviceStorageContract = new Mock<IServiceStorageContract>();
_masterStorageContract = new Mock<IMasterStorageContract>();
_orderStorageContract = new Mock<IOrderStorageContract>();
_salaryStorageContract = new Mock<ISalaryStorageContract>();
_postStorageContract = new Mock<IPostStorageContract>();
_baseWordBuilder = new Mock<BaseWordBuilder>();
_baseExcelBuilder = new Mock<BaseExcelBuilder>();
_basePdfBuilder = new Mock<BasePdfBuilder>();
_localizer = StringLocalizerMockCreator.GetObject();
_reportContract = new ReportContract(_serviceStorageContract.Object, _masterStorageContract.Object, _orderStorageContract.Object, _salaryStorageContract.Object, _postStorageContract.Object, _baseWordBuilder.Object, _baseExcelBuilder.Object, _basePdfBuilder.Object, new Mock<ILogger>().Object, _localizer);
}
[SetUp]
public void SetUp()
{
_serviceStorageContract.Reset();
_masterStorageContract.Reset();
_orderStorageContract.Reset();
_salaryStorageContract.Reset();
_postStorageContract.Reset();
}
[Test]
public async Task GetDataServiceHistory_ShouldSuccess_Test()
{
//Arrange
var service1Id = Guid.NewGuid().ToString();
var service2Id = Guid.NewGuid().ToString();
_serviceStorageContract.Setup(x => x.GetList()).Returns(new List<ServiceDataModel>()
{
new(service1Id, "Service 1", ServiceType.Painting, Guid.NewGuid().ToString(), 100, false),
new(service2Id, "Service 2", ServiceType.Plastering, Guid.NewGuid().ToString(), 200, false)
});
_serviceStorageContract.Setup(x => x.GetHistoryByServiceId(service1Id)).Returns(new List<ServiceHistoryDataModel>()
{
new(service1Id, 100),
new(service1Id, 120)
});
_serviceStorageContract.Setup(x => x.GetHistoryByServiceId(service2Id)).Returns(new List<ServiceHistoryDataModel>()
{
new(service2Id, 200),
new(service2Id, 250)
});
_reportContract = new ReportContract(_serviceStorageContract.Object, _masterStorageContract.Object, _orderStorageContract.Object, _salaryStorageContract.Object, _postStorageContract.Object, _baseWordBuilder.Object, _baseExcelBuilder.Object, _basePdfBuilder.Object, new Mock<ILogger>().Object, StringLocalizerMockCreator.GetObject());
//Act
var data = await _reportContract.GetDataServiceHistoryAsync(CancellationToken.None);
//Assert
Assert.That(data, Is.Not.Null);
Assert.That(data, Has.Count.EqualTo(4));
_serviceStorageContract.Verify(x => x.GetList(), Times.Once);
_serviceStorageContract.Verify(x => x.GetHistoryByServiceId(service1Id), Times.Once);
_serviceStorageContract.Verify(x => x.GetHistoryByServiceId(service2Id), Times.Once);
}
[Test]
public async Task GetDataServiceHistory_WhenNoRecords_ShouldSuccess_Test()
{
//Arrange
_serviceStorageContract.Setup(x => x.GetList()).Returns(new List<ServiceDataModel>());
_reportContract = new ReportContract(_serviceStorageContract.Object, _masterStorageContract.Object, _orderStorageContract.Object, _salaryStorageContract.Object, _postStorageContract.Object, _baseWordBuilder.Object, _baseExcelBuilder.Object, _basePdfBuilder.Object, new Mock<ILogger>().Object, StringLocalizerMockCreator.GetObject());
//Act
var data = await _reportContract.GetDataServiceHistoryAsync(CancellationToken.None);
//Assert
Assert.That(data, Is.Not.Null);
Assert.That(data, Has.Count.EqualTo(0));
_serviceStorageContract.Verify(x => x.GetList(), Times.Once);
}
[Test]
public void GetDataServiceHistory_WhenStorageThrowError_ShouldFail_Test()
{
//Arrange
_serviceStorageContract.Setup(x => x.GetList()).Throws(new StorageException(new InvalidOperationException(), StringLocalizerMockCreator.GetObject()));
_reportContract = new ReportContract(_serviceStorageContract.Object, _masterStorageContract.Object, _orderStorageContract.Object, _salaryStorageContract.Object, _postStorageContract.Object, _baseWordBuilder.Object, _baseExcelBuilder.Object, _basePdfBuilder.Object, new Mock<ILogger>().Object, StringLocalizerMockCreator.GetObject());
//Act&Assert
Assert.That(async () => await _reportContract.GetDataServiceHistoryAsync(CancellationToken.None), Throws.TypeOf<StorageException>());
_serviceStorageContract.Verify(x => x.GetList(), Times.Once);
}
[Test]
public async Task GetDataOrderByPeriod_ShouldSuccess_Test()
{
//Arrange
_orderStorageContract.Setup(x => x.GetListAsync(It.IsAny<DateTime>(), It.IsAny<DateTime>(), It.IsAny<CancellationToken>())).Returns(Task.FromResult(new List<OrderDataModel>()
{
new(Guid.NewGuid().ToString(), DateTime.UtcNow.AddDays(-1), StatusType.InProcess, RoomType.Residential),
new(Guid.NewGuid().ToString(), DateTime.UtcNow, StatusType.Ready, RoomType.Industrial)
}));
_reportContract = new ReportContract(_serviceStorageContract.Object, _masterStorageContract.Object, _orderStorageContract.Object, _salaryStorageContract.Object, _postStorageContract.Object, _baseWordBuilder.Object, _baseExcelBuilder.Object, _basePdfBuilder.Object, new Mock<ILogger>().Object, StringLocalizerMockCreator.GetObject());
//Act
var data = await _reportContract.GetDataOrderByPeriodAsync(DateTime.UtcNow.AddDays(-1), DateTime.UtcNow, CancellationToken.None);
//Assert
Assert.That(data, Is.Not.Null);
Assert.That(data, Has.Count.EqualTo(2));
_orderStorageContract.Verify(x => x.GetListAsync(It.IsAny<DateTime>(), It.IsAny<DateTime>(), It.IsAny<CancellationToken>()), Times.Once);
}
[Test]
public async Task GetDataOrderByPeriod_WhenNoRecords_ShouldSuccess_Test()
{
//Arrange
_orderStorageContract.Setup(x => x.GetListAsync(It.IsAny<DateTime>(), It.IsAny<DateTime>(), It.IsAny<CancellationToken>())).Returns(Task.FromResult(new List<OrderDataModel>()));
_reportContract = new ReportContract(_serviceStorageContract.Object, _masterStorageContract.Object, _orderStorageContract.Object, _salaryStorageContract.Object, _postStorageContract.Object, _baseWordBuilder.Object, _baseExcelBuilder.Object, _basePdfBuilder.Object, new Mock<ILogger>().Object, StringLocalizerMockCreator.GetObject());
//Act
var data = await _reportContract.GetDataOrderByPeriodAsync(DateTime.UtcNow.AddDays(-1), DateTime.UtcNow, CancellationToken.None);
//Assert
Assert.That(data, Is.Not.Null);
Assert.That(data, Has.Count.EqualTo(0));
_orderStorageContract.Verify(x => x.GetListAsync(It.IsAny<DateTime>(), It.IsAny<DateTime>(), It.IsAny<CancellationToken>()), Times.Once);
}
[Test]
public void GetDataOrderByPeriod_WhenIncorrectDates_ShouldFail_Test()
{
//Arrange
var date = DateTime.UtcNow;
_reportContract = new ReportContract(_serviceStorageContract.Object, _masterStorageContract.Object, _orderStorageContract.Object, _salaryStorageContract.Object, _postStorageContract.Object, _baseWordBuilder.Object, _baseExcelBuilder.Object, _basePdfBuilder.Object, new Mock<ILogger>().Object, StringLocalizerMockCreator.GetObject());
//Act&Assert
Assert.That(async () => await _reportContract.GetDataOrderByPeriodAsync(date, date, CancellationToken.None), Throws.TypeOf<IncorrectDatesException>());
Assert.That(async () => await _reportContract.GetDataOrderByPeriodAsync(date, DateTime.UtcNow.AddDays(-1), CancellationToken.None), Throws.TypeOf<IncorrectDatesException>());
}
[Test]
public void GetDataOrderByPeriod_WhenStorageThrowError_ShouldFail_Test()
{
//Arrange
_orderStorageContract.Setup(x => x.GetListAsync(It.IsAny<DateTime>(), It.IsAny<DateTime>(), It.IsAny<CancellationToken>())).Throws(new StorageException(new InvalidOperationException(), StringLocalizerMockCreator.GetObject()));
_reportContract = new ReportContract(_serviceStorageContract.Object, _masterStorageContract.Object, _orderStorageContract.Object, _salaryStorageContract.Object, _postStorageContract.Object, _baseWordBuilder.Object, _baseExcelBuilder.Object, _basePdfBuilder.Object, new Mock<ILogger>().Object, StringLocalizerMockCreator.GetObject());
//Act&Assert
Assert.That(async () => await _reportContract.GetDataOrderByPeriodAsync(DateTime.UtcNow.AddDays(-1), DateTime.UtcNow, CancellationToken.None), Throws.TypeOf<StorageException>());
_orderStorageContract.Verify(x => x.GetListAsync(It.IsAny<DateTime>(), It.IsAny<DateTime>(), It.IsAny<CancellationToken>()), Times.Once);
}
[Test]
public async Task GetDataSalaryByPeriod_ShouldSuccess_Test()
{
//Arrange
var startDate = DateTime.UtcNow.AddDays(-1);
var endDate = DateTime.UtcNow;
var master1Id = Guid.NewGuid().ToString();
var master2Id = Guid.NewGuid().ToString();
_salaryStorageContract.Setup(x => x.GetListAsync(It.IsAny<DateTime>(), It.IsAny<DateTime>(), It.IsAny<CancellationToken>())).Returns(Task.FromResult(new List<SalaryDataModel>()
{
new(master1Id, startDate, 1000, 0),
new(master1Id, endDate, 1000, 0),
new(master2Id, startDate, 100, 0),
new(master2Id, endDate, 200, 0)
}));
// Настраиваем мок для _masterStorageContract.GetList с конкретным значением onlyActive: true
var mastersToReturn = new List<MasterDataModel>()
{
new(master1Id, "Иванов Иван Иванович", Guid.NewGuid().ToString(), DateTime.UtcNow.AddYears(-30), DateTime.UtcNow.AddYears(-5), false),
new(master2Id, "Петров Петр Петрович", Guid.NewGuid().ToString(), DateTime.UtcNow.AddYears(-25), DateTime.UtcNow.AddYears(-3), false)
};
_masterStorageContract.Setup(x => x.GetList(true, null, null, null, null, null)).Returns(mastersToReturn);
//Act
var data = await _reportContract.GetDataSalaryByPeriodAsync(startDate, endDate, CancellationToken.None);
//Assert
Assert.That(data, Is.Not.Null);
Assert.That(data, Has.Count.EqualTo(4)); // 4 записи: по 2 для каждого мастера
var master1Salaries = data.Where(x => x.MasterFIO == "Иванов Иван Иванович").ToList();
Assert.That(master1Salaries, Has.Count.EqualTo(2), "Иванов Иван Иванович should have 2 salary records");
Assert.Multiple(() =>
{
Assert.That(master1Salaries.Any(x => x.TotalSalary == 1000), Is.True, "Should have 1000 salary record");
Assert.That(master1Salaries.Any(x => x.TotalSalary == 1000), Is.True, "Should have another 1000 salary record");
});
var master2Salaries = data.Where(x => x.MasterFIO == "Петров Петр Петрович").ToList();
Assert.That(master2Salaries, Has.Count.EqualTo(2), "Петров Петр Петрович should have 2 salary records");
Assert.Multiple(() =>
{
Assert.That(master2Salaries.Any(x => x.TotalSalary == 100), Is.True, "Should have 100 salary record");
Assert.That(master2Salaries.Any(x => x.TotalSalary == 200), Is.True, "Should have 200 salary record");
});
_salaryStorageContract.Verify(x => x.GetListAsync(It.IsAny<DateTime>(), It.IsAny<DateTime>(), It.IsAny<CancellationToken>()), Times.Once);
_masterStorageContract.Verify(x => x.GetList(true, null, null, null, null, null), Times.Once);
}
[Test]
public async Task GetDataSalaryByPeriod_WhenNoRecords_ShouldSuccess_Test()
{
//Arrange
_salaryStorageContract.Setup(x => x.GetListAsync(It.IsAny<DateTime>(), It.IsAny<DateTime>(), It.IsAny<CancellationToken>())).Returns(Task.FromResult(new List<SalaryDataModel>()));
//Act
var data = await _reportContract.GetDataSalaryByPeriodAsync(DateTime.UtcNow.AddDays(-1), DateTime.UtcNow, CancellationToken.None);
//Assert
Assert.That(data, Is.Not.Null);
Assert.That(data, Has.Count.EqualTo(0));
_salaryStorageContract.Verify(x => x.GetListAsync(It.IsAny<DateTime>(), It.IsAny<DateTime>(), It.IsAny<CancellationToken>()), Times.Once);
}
[Test]
public void GetDataSalaryByPeriod_WhenIncorrectDates_ShouldFail_Test()
{
//Arrange
var date = DateTime.UtcNow;
_reportContract = new ReportContract(_serviceStorageContract.Object, _masterStorageContract.Object, _orderStorageContract.Object, _salaryStorageContract.Object, _postStorageContract.Object, _baseWordBuilder.Object, _baseExcelBuilder.Object, _basePdfBuilder.Object, new Mock<ILogger>().Object, StringLocalizerMockCreator.GetObject());
//Act&Assert
Assert.That(async () => await _reportContract.GetDataSalaryByPeriodAsync(date, date, CancellationToken.None), Throws.TypeOf<IncorrectDatesException>());
Assert.That(async () => await _reportContract.GetDataSalaryByPeriodAsync(date, DateTime.UtcNow.AddDays(-1), CancellationToken.None), Throws.TypeOf<IncorrectDatesException>());
}
[Test]
public void GetDataSalaryByPeriod_WhenStorageThrowError_ShouldFail_Test()
{
//Arrange
_salaryStorageContract.Setup(x => x.GetListAsync(It.IsAny<DateTime>(), It.IsAny<DateTime>(), It.IsAny<CancellationToken>())).Throws(new StorageException(new InvalidOperationException(), StringLocalizerMockCreator.GetObject()));
//Act&Assert
Assert.That(async () => await _reportContract.GetDataSalaryByPeriodAsync(DateTime.UtcNow.AddDays(-1), DateTime.UtcNow, CancellationToken.None), Throws.TypeOf<StorageException>());
_salaryStorageContract.Verify(x => x.GetListAsync(It.IsAny<DateTime>(), It.IsAny<DateTime>(), It.IsAny<CancellationToken>()), Times.Once);
}
}

View File

@@ -9,19 +9,23 @@ using TwoFromTheCasketContratcs.DataModels;
using TwoFromTheCasketContratcs.Enums;
using TwoFromTheCasketContratcs.Exceptions;
using TwoFromTheCasketContratcs.StorageContracts;
using TwoFromTheCasketContratcs.Infrastructure.PostConfigurations;
using TwoFromTheCasketContratcs.Infrastructure;
using TwoFromTheCasketTest.Infrastructure;
using Microsoft.Extensions.Configuration;
using TwoFromTheCasketWebApi.Infrastructure;
namespace TwoFromTheCasketTest.BuisnessLogicContractTests;
[TestFixture]
[TestFixture]
internal class SalaryBusinessLogicContractTests
{
private SalaryBusinessLogicContract _salaryBusinessLogicContract;
private Mock<ISalaryStorageContract> _salaryStorageContract;
private Mock<IOrderStorageContract> _orderStorageContract;
private Mock<IPostStorageContract> _postStorageContract;
private Mock<IMasterStorageContract> _masterStorageContract;
private readonly IConfigurationSalary _salaryConfiguration = new ConfigurationSalary(new ConfigurationBuilder().Build());
[OneTimeSetUp]
public void OneTimeSetUp()
@@ -32,7 +36,7 @@ internal class SalaryBusinessLogicContractTests
_masterStorageContract = new Mock<IMasterStorageContract>();
_salaryBusinessLogicContract = new SalaryBusinessLogicContract(_salaryStorageContract.Object,
_postStorageContract.Object, _masterStorageContract.Object,
new Mock<ILogger>().Object, _orderStorageContract.Object);
new Mock<ILogger>().Object, _orderStorageContract.Object, _salaryConfiguration, StringLocalizerMockCreator.GetObject());
}
[SetUp]
@@ -95,23 +99,12 @@ internal class SalaryBusinessLogicContractTests
Times.Never);
}
[Test]
public void GetAllSalaries_ReturnNull_ThrowException_Test()
{
//Act&Assert
Assert.That(
() => _salaryBusinessLogicContract.GetAllSalariesByPeriod(DateTime.UtcNow, DateTime.UtcNow.AddDays(1)),
Throws.TypeOf<NullListException>());
_salaryStorageContract.Verify(x => x.GetList(It.IsAny<DateTime>(), It.IsAny<DateTime>(), It.IsAny<string>()),
Times.Once);
}
[Test]
[Test]
public void GetAllSalaries_StorageThrowError_ThrowException_Test()
{
//Arrange
_salaryStorageContract.Setup(x => x.GetList(It.IsAny<DateTime>(), It.IsAny<DateTime>(), It.IsAny<string>()))
.Throws(new StorageException(new InvalidOperationException()));
.Throws(new StorageException(new InvalidOperationException(), StringLocalizerMockCreator.GetObject()));
//Act&Assert
Assert.That(
() => _salaryBusinessLogicContract.GetAllSalariesByPeriod(DateTime.UtcNow, DateTime.UtcNow.AddDays(1)),
@@ -200,23 +193,14 @@ internal class SalaryBusinessLogicContractTests
Times.Never);
}
[Test]
public void GetAllSalariesByMaster_ReturnNull_ThrowException_Test()
{
//Act&Assert
Assert.That(
() => _salaryBusinessLogicContract.GetAllSalariesByPeriodByMaster(DateTime.UtcNow,
DateTime.UtcNow.AddDays(1), Guid.NewGuid().ToString()), Throws.TypeOf<NullListException>());
_salaryStorageContract.Verify(x => x.GetList(It.IsAny<DateTime>(), It.IsAny<DateTime>(), It.IsAny<string>()),
Times.Once);
}
[Test]
public void GetAllSalariesByMaster_StorageThrowError_ThrowException_Test()
{
//Arrange
_salaryStorageContract.Setup(x => x.GetList(It.IsAny<DateTime>(), It.IsAny<DateTime>(), It.IsAny<string>()))
.Throws(new StorageException(new InvalidOperationException()));
.Throws(new StorageException(new InvalidOperationException(), StringLocalizerMockCreator.GetObject()));
//Act&Assert
Assert.That(
() => _salaryBusinessLogicContract.GetAllSalariesByPeriodByMaster(DateTime.UtcNow,
@@ -230,14 +214,14 @@ internal class SalaryBusinessLogicContractTests
{
//Arrange
var masterId = Guid.NewGuid().ToString();
var orderSum = 200.0;
var postSalary = 2000.0;
var rate = 2000.0;
_orderStorageContract.Setup(x => x.GetList())
.Returns([
new OrderDataModel(Guid.NewGuid().ToString(), DateTime.Now, StatusType.Ready, RoomType.Industrial)
new OrderDataModel(Guid.NewGuid().ToString(), DateTime.UtcNow, StatusType.Ready, RoomType.Industrial),
new OrderDataModel(Guid.NewGuid().ToString(), DateTime.UtcNow, StatusType.Ready, RoomType.Industrial)
]);
_postStorageContract.Setup(x => x.GetElementById(It.IsAny<string>()))
.Returns(new PostDataModel(Guid.NewGuid().ToString(), "name", PostType.Plasterer, postSalary));
.Returns(new PostDataModel(Guid.NewGuid().ToString(), "name", PostType.Plasterer, new PostConfiguration { Rate = rate }));
_masterStorageContract.Setup(x => x.GetList(It.IsAny<bool>(), It.IsAny<string?>(), It.IsAny<DateTime?>(),
It.IsAny<DateTime?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>()))
.Returns([
@@ -245,13 +229,12 @@ internal class SalaryBusinessLogicContractTests
false)
]);
var sum = 0.0;
var expectedSum = postSalary + 500;
_salaryStorageContract.Setup(x => x.AddElement(It.IsAny<SalaryDataModel>()))
.Callback((SalaryDataModel x) => { sum = x.Salary; });
//Act
_salaryBusinessLogicContract.CalculateSalaryByMonth(DateTime.UtcNow);
//Assert
Assert.That(sum, Is.EqualTo(expectedSum));
Assert.That(sum, Is.EqualTo(rate));
}
[Test]
@@ -272,14 +255,14 @@ internal class SalaryBusinessLogicContractTests
};
_orderStorageContract.Setup(x => x.GetList())
.Returns([
new OrderDataModel(Guid.NewGuid().ToString(), DateTime.Now, StatusType.Ready, RoomType.Industrial),
new OrderDataModel(Guid.NewGuid().ToString(), DateTime.Now, StatusType.Ready, RoomType.Industrial),
new OrderDataModel(Guid.NewGuid().ToString(), DateTime.Now, StatusType.Ready, RoomType.Industrial),
new OrderDataModel(Guid.NewGuid().ToString(), DateTime.Now, StatusType.Ready, RoomType.Industrial),
new OrderDataModel(Guid.NewGuid().ToString(), DateTime.Now, StatusType.Ready, RoomType.Industrial)
new OrderDataModel(Guid.NewGuid().ToString(), DateTime.UtcNow, StatusType.Ready, RoomType.Industrial),
new OrderDataModel(Guid.NewGuid().ToString(), DateTime.UtcNow, StatusType.Ready, RoomType.Industrial),
new OrderDataModel(Guid.NewGuid().ToString(), DateTime.UtcNow, StatusType.Ready, RoomType.Industrial),
new OrderDataModel(Guid.NewGuid().ToString(), DateTime.UtcNow, StatusType.Ready, RoomType.Industrial),
new OrderDataModel(Guid.NewGuid().ToString(), DateTime.UtcNow, StatusType.Ready, RoomType.Industrial)
]);
_postStorageContract.Setup(x => x.GetElementById(It.IsAny<string>()))
.Returns(new PostDataModel(Guid.NewGuid().ToString(), "name", PostType.Plasterer, 2000));
.Returns(new PostDataModel(Guid.NewGuid().ToString(), "name", PostType.Plasterer, new PostConfiguration { Rate = 100 }));
_masterStorageContract.Setup(x => x.GetList(It.IsAny<bool>(), It.IsAny<string?>(), It.IsAny<DateTime?>(),
It.IsAny<DateTime?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>()))
.Returns(list);
@@ -290,15 +273,15 @@ internal class SalaryBusinessLogicContractTests
}
[Test]
public void CalculateSalaryByMounth_WithoitOrdersByMaster_Test()
public void CalculateSalaryByMounth_WithoutOrdersByMaster_Test()
{
//Arrange
var postSalary = 2000.0;
var rate = 2000.0;
var masterId = Guid.NewGuid().ToString();
_orderStorageContract.Setup(x => x.GetList())
.Returns([]);
.Returns([]); // Нет заказов
_postStorageContract.Setup(x => x.GetElementById(It.IsAny<string>()))
.Returns(new PostDataModel(Guid.NewGuid().ToString(), "name", PostType.Plasterer, postSalary));
.Returns(new PostDataModel(Guid.NewGuid().ToString(), "name", PostType.Plasterer, new PostConfiguration { Rate = rate }));
_masterStorageContract.Setup(x => x.GetList(It.IsAny<bool>(), It.IsAny<string?>(), It.IsAny<DateTime?>(),
It.IsAny<DateTime?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>()))
.Returns([
@@ -306,37 +289,25 @@ internal class SalaryBusinessLogicContractTests
false)
]);
var sum = 0.0;
var expectedSum = postSalary + 500;
_salaryStorageContract.Setup(x => x.AddElement(It.IsAny<SalaryDataModel>()))
.Callback((SalaryDataModel x) => { sum = x.Salary; });
//Act
_salaryBusinessLogicContract.CalculateSalaryByMonth(DateTime.UtcNow);
//Assert
Assert.That(sum, Is.EqualTo(expectedSum));
Assert.That(sum, Is.EqualTo(rate));
}
[Test]
public void CalculateSalaryByMounth_OrderStorageReturnNull_ThrowException_Test()
{
//Arrange
var masterId = Guid.NewGuid().ToString();
_postStorageContract.Setup(x => x.GetElementById(It.IsAny<string>()))
.Returns(new PostDataModel(Guid.NewGuid().ToString(), "name", PostType.Plasterer, 2000));
_masterStorageContract.Setup(x => x.GetList(It.IsAny<bool>(), It.IsAny<string?>(), It.IsAny<DateTime?>(),
It.IsAny<DateTime?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>()))
.Returns([
new MasterDataModel(masterId, "А А А", Guid.NewGuid().ToString(), DateTime.UtcNow.AddYears(-19), DateTime.UtcNow,
false)
]);
//Act&Assert
Assert.DoesNotThrow(() => _salaryBusinessLogicContract.CalculateSalaryByMonth(DateTime.UtcNow));
}
[Test]
public void CalculateSalaryByMounth_PostStorageReturnNull_ThrowException_Test()
{
//Arrange
var masterId = Guid.NewGuid().ToString();
_orderStorageContract.Setup(x => x.GetList())
.Returns([]); // Пустой список заказов
_postStorageContract.Setup(x => x.GetElementById(It.IsAny<string>()))
.Returns((PostDataModel)null); // Возвращаем null для поста
_masterStorageContract.Setup(x => x.GetList(It.IsAny<bool>(), It.IsAny<string?>(), It.IsAny<DateTime?>(),
It.IsAny<DateTime?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>()))
.Returns([
@@ -348,29 +319,16 @@ internal class SalaryBusinessLogicContractTests
Throws.TypeOf<ElementNotFoundException>());
}
[Test]
public void CalculateSalaryByMounth_MasterStorageReturnNull_ThrowException_Test()
{
//Arrange
var masterId = Guid.NewGuid().ToString();
_orderStorageContract.Setup(x => x.GetList())
.Returns([
new OrderDataModel(Guid.NewGuid().ToString(), DateTime.Now, StatusType.Ready, RoomType.Industrial)
]);
_postStorageContract.Setup(x => x.GetElementById(It.IsAny<string>()))
.Returns(new PostDataModel(Guid.NewGuid().ToString(), "name", PostType.Plasterer, 2000));
//Act&Assert
Assert.That(() => _salaryBusinessLogicContract.CalculateSalaryByMonth(DateTime.UtcNow),
Throws.TypeOf<NullListException>());
}
[Test]
public void CalculateSalaryByMounth_OrderStorageThrowException_ThrowException_Test()
{
//Arrange
var masterId = Guid.NewGuid().ToString();
_orderStorageContract.Setup(x => x.GetList())
.Throws(new StorageException(new InvalidOperationException(), StringLocalizerMockCreator.GetObject()));
_postStorageContract.Setup(x => x.GetElementById(It.IsAny<string>()))
.Returns(new PostDataModel(Guid.NewGuid().ToString(), "name", PostType.Plasterer, 2000));
.Returns(new PostDataModel(Guid.NewGuid().ToString(), "name", PostType.Plasterer, new PostConfiguration { Rate = 2000 }));
_masterStorageContract.Setup(x => x.GetList(It.IsAny<bool>(), It.IsAny<string?>(), It.IsAny<DateTime?>(),
It.IsAny<DateTime?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>()))
.Returns([
@@ -378,7 +336,8 @@ internal class SalaryBusinessLogicContractTests
false)
]);
//Act&Assert
Assert.DoesNotThrow(() => _salaryBusinessLogicContract.CalculateSalaryByMonth(DateTime.UtcNow));
Assert.That(() => _salaryBusinessLogicContract.CalculateSalaryByMonth(DateTime.UtcNow),
Throws.TypeOf<StorageException>());
}
[Test]
@@ -391,7 +350,7 @@ internal class SalaryBusinessLogicContractTests
new OrderDataModel(Guid.NewGuid().ToString(), DateTime.Now, StatusType.Ready, RoomType.Industrial)
]);
_postStorageContract.Setup(x => x.GetElementById(It.IsAny<string>()))
.Throws(new StorageException(new InvalidOperationException()));
.Throws(new StorageException(new InvalidOperationException(), StringLocalizerMockCreator.GetObject()));
_masterStorageContract.Setup(x => x.GetList(It.IsAny<bool>(), It.IsAny<string?>(), It.IsAny<DateTime?>(),
It.IsAny<DateTime?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>()))
.Returns([
@@ -413,12 +372,116 @@ internal class SalaryBusinessLogicContractTests
new OrderDataModel(Guid.NewGuid().ToString(), DateTime.Now, StatusType.Ready, RoomType.Industrial)
]);
_postStorageContract.Setup(x => x.GetElementById(It.IsAny<string>()))
.Returns(new PostDataModel(Guid.NewGuid().ToString(), "name", PostType.Plasterer, 2000));
.Returns(new PostDataModel(Guid.NewGuid().ToString(), "name", PostType.Plasterer, new PostConfiguration { Rate = 2000 }));
_masterStorageContract.Setup(x => x.GetList(It.IsAny<bool>(), It.IsAny<string?>(), It.IsAny<DateTime?>(),
It.IsAny<DateTime?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>()))
.Throws(new StorageException(new InvalidOperationException()));
.Throws(new StorageException(new InvalidOperationException(), StringLocalizerMockCreator.GetObject()));
//Act&Assert
Assert.That(() => _salaryBusinessLogicContract.CalculateSalaryByMonth(DateTime.UtcNow),
Throws.TypeOf<StorageException>());
}
[Test]
public void CalculateSalaryByMounth_WithCarpenterPostConfiguration_CalculateSalary_Test()
{
//Arrange
var masterId = Guid.NewGuid().ToString();
var rate = 2000.0;
var bonus = 50.0;
var orders = new List<OrderDataModel>()
{
new OrderDataModel(Guid.NewGuid().ToString(), DateTime.UtcNow, StatusType.Ready, RoomType.Industrial),
new OrderDataModel(Guid.NewGuid().ToString(), DateTime.UtcNow, StatusType.Ready, RoomType.Industrial),
new OrderDataModel(Guid.NewGuid().ToString(), DateTime.UtcNow, StatusType.Ready, RoomType.Industrial)
};
_orderStorageContract.Setup(x => x.GetList())
.Returns(orders);
_postStorageContract.Setup(x => x.GetElementById(It.IsAny<string>()))
.Returns(new PostDataModel(Guid.NewGuid().ToString(), "name", PostType.Carpenter,
new CarpenterPostConfiguration { Rate = rate, BonusForExtraCarpentry = bonus }));
_masterStorageContract.Setup(x => x.GetList(It.IsAny<bool>(), It.IsAny<string?>(), It.IsAny<DateTime?>(),
It.IsAny<DateTime?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>()))
.Returns([
new MasterDataModel(masterId, "А А А", Guid.NewGuid().ToString(), DateTime.UtcNow.AddYears(-19), DateTime.UtcNow,
false)
]);
var sum = 0.0;
var expectedSum = rate + (orders.Count * bonus); // Базовый оклад + бонус за количество заказов
_salaryStorageContract.Setup(x => x.AddElement(It.IsAny<SalaryDataModel>()))
.Callback((SalaryDataModel x) => { sum = x.Salary; });
//Act
_salaryBusinessLogicContract.CalculateSalaryByMonth(DateTime.UtcNow);
//Assert
Assert.That(sum, Is.EqualTo(expectedSum));
}
[Test]
public void CalculateSalaryByMounth_WithPainterPostConfiguration_CalculateSalary_Test()
{
//Arrange
var masterId = Guid.NewGuid().ToString();
var rate = 2000.0;
var percent = 0.1;
var bonus = 0.5;
var orders = new List<OrderDataModel>()
{
new OrderDataModel(Guid.NewGuid().ToString(), DateTime.UtcNow, StatusType.Ready, RoomType.Industrial),
new OrderDataModel(Guid.NewGuid().ToString(), DateTime.UtcNow, StatusType.Ready, RoomType.Industrial),
new OrderDataModel(Guid.NewGuid().ToString(), DateTime.UtcNow, StatusType.Ready, RoomType.Industrial)
};
_orderStorageContract.Setup(x => x.GetList())
.Returns(orders);
_postStorageContract.Setup(x => x.GetElementById(It.IsAny<string>()))
.Returns(new PostDataModel(Guid.NewGuid().ToString(), "name", PostType.Painter,
new PainterPostConfiguration { Rate = rate, PainterPercent = percent, BonusForExtraPainter = bonus }));
_masterStorageContract.Setup(x => x.GetList(It.IsAny<bool>(), It.IsAny<string?>(), It.IsAny<DateTime?>(),
It.IsAny<DateTime?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>()))
.Returns([
new MasterDataModel(masterId, "А А А", Guid.NewGuid().ToString(), DateTime.UtcNow.AddYears(-19), DateTime.UtcNow,
false)
]);
var sum = 0.0;
var expectedSum = rate + (orders.Count * percent) + (orders.Count * bonus); // Базовый оклад + процент + бонус
_salaryStorageContract.Setup(x => x.AddElement(It.IsAny<SalaryDataModel>()))
.Callback((SalaryDataModel x) => { sum = x.Salary; });
//Act
_salaryBusinessLogicContract.CalculateSalaryByMonth(DateTime.UtcNow);
//Assert
Assert.That(sum, Is.EqualTo(expectedSum));
}
[Test]
public void CalculateSalaryByMounth_WithPlastererPostConfiguration_CalculateSalary_Test()
{
//Arrange
var masterId = Guid.NewGuid().ToString();
var rate = 2000.0;
var percent = 0.1;
var bonus = 0.5;
var orders = new List<OrderDataModel>()
{
new OrderDataModel(Guid.NewGuid().ToString(), DateTime.UtcNow, StatusType.Ready, RoomType.Industrial),
new OrderDataModel(Guid.NewGuid().ToString(), DateTime.UtcNow, StatusType.Ready, RoomType.Industrial),
new OrderDataModel(Guid.NewGuid().ToString(), DateTime.UtcNow, StatusType.Ready, RoomType.Industrial)
};
_orderStorageContract.Setup(x => x.GetList())
.Returns(orders);
_postStorageContract.Setup(x => x.GetElementById(It.IsAny<string>()))
.Returns(new PostDataModel(Guid.NewGuid().ToString(), "name", PostType.Plasterer,
new PlastererPostConfiguration { Rate = rate, PlastererPercent = percent, BonusForExtraPlasterer = bonus }));
_masterStorageContract.Setup(x => x.GetList(It.IsAny<bool>(), It.IsAny<string?>(), It.IsAny<DateTime?>(),
It.IsAny<DateTime?>(), It.IsAny<DateTime?>(), It.IsAny<DateTime?>()))
.Returns([
new MasterDataModel(masterId, "А А А", Guid.NewGuid().ToString(), DateTime.UtcNow.AddYears(-19), DateTime.UtcNow,
false)
]);
var sum = 0.0;
var expectedSum = rate + (orders.Count * percent) + (orders.Count * bonus); // Базовый оклад + процент + бонус
_salaryStorageContract.Setup(x => x.AddElement(It.IsAny<SalaryDataModel>()))
.Callback((SalaryDataModel x) => { sum = x.Salary; });
//Act
_salaryBusinessLogicContract.CalculateSalaryByMonth(DateTime.UtcNow);
//Assert
Assert.That(sum, Is.EqualTo(expectedSum));
}
}

View File

@@ -9,6 +9,7 @@ using TwoFromTheCasketContratcs.DataModels;
using TwoFromTheCasketContratcs.Enums;
using TwoFromTheCasketContratcs.Exceptions;
using TwoFromTheCasketContratcs.StorageContracts;
using TwoFromTheCasketTest.Infrastructure;
namespace TwoFromTheCasketTest.BuisnessLogicContractTests;
@@ -22,7 +23,7 @@ internal class ServiceBusinessLogicContractTests
public void OneTimeSetUp()
{
_serviceStorageContract = new Mock<IServiceStorageContract>();
_serviceBusinessLogicContract = new ServiceBusinessLogicContract(_serviceStorageContract.Object,new Mock<ILogger>().Object);
_serviceBusinessLogicContract = new ServiceBusinessLogicContract(_serviceStorageContract.Object,new Mock<ILogger>().Object, StringLocalizerMockCreator.GetObject());
}
[SetUp]
@@ -71,22 +72,11 @@ internal class ServiceBusinessLogicContractTests
});
}
[Test]
public void GetAllServices_ReturnNull_ThrowException_Test()
{
// Arrange
_serviceStorageContract.Setup(x => x.GetList()).Returns((List<ServiceDataModel>)null!);
// Act & Assert
Assert.That(() => _serviceBusinessLogicContract.GetAllServices(onlyActive: true), Throws.TypeOf<NullListException>());
_serviceStorageContract.Verify(x => x.GetList(), Times.Once);
}
[Test]
public void GetAllServices_StorageThrowError_ThrowException_Test()
{
// Arrange
_serviceStorageContract.Setup(x => x.GetList()).Throws(new StorageException(new InvalidOperationException()));
_serviceStorageContract.Setup(x => x.GetList()).Throws(new StorageException(new InvalidOperationException(), StringLocalizerMockCreator.GetObject()));
// Act & Assert
Assert.That(() => _serviceBusinessLogicContract.GetAllServices(onlyActive: true), Throws.TypeOf<StorageException>());
@@ -117,22 +107,7 @@ internal class ServiceBusinessLogicContractTests
_serviceStorageContract.Verify(x => x.GetElementByMasterId(masterId), Times.Once);
}
[Test]
public void GetAllServicesByMasterId_ThrowsNullListException_WhenNoServicesFound()
{
// Arrange
_serviceStorageContract
.Setup(x => x.GetElementByMasterId(It.IsAny<string>()))
.Returns((List<ServiceDataModel>)null!);
// Act & Assert
Assert.That(
() => _serviceBusinessLogicContract.GetServicesByMasterId(Guid.NewGuid().ToString(), onlyActive: true),
Throws.TypeOf<NullListException>()
);
_serviceStorageContract.Verify(x => x.GetElementByMasterId(It.IsAny<string>()), Times.Once);
}
[Test]
public void GetAllServicesByMasterId_MasterIdIsNullOrEmpty_ThrowException_Test()

View File

@@ -5,6 +5,7 @@ using System.Text;
using System.Threading.Tasks;
using TwoFromTheCasketContratcs.DataModels;
using TwoFromTheCasketContratcs.Exceptions;
using TwoFromTheCasketTest.Infrastructure;
namespace TwoFromTheCasketTest.DataModelsTest;
@@ -15,39 +16,39 @@ internal class MasterDataModelTests
public void IdIsNullOrEmptyTest()
{
var master = CreateDataModel(null, "fio", "11", new DateTime(2023, 10, 5), new DateTime(2003, 10, 5), true);
Assert.That(()=> master.Validate(), Throws.TypeOf<ValidationException>());
Assert.That(()=> master.Validate(StringLocalizerMockCreator.GetObject()), Throws.TypeOf<ValidationException>());
master = CreateDataModel(string.Empty, "fio", "11", new DateTime(2023, 10, 5), new DateTime(2003, 10, 5), true);
Assert.That(() => master.Validate(), Throws.TypeOf<ValidationException>());
Assert.That(() => master.Validate(StringLocalizerMockCreator.GetObject()), Throws.TypeOf<ValidationException>());
}
[Test]
public void IdIsNotGuidTest()
{
var master = CreateDataModel("id", "fio", "11", new DateTime(2023, 10, 5), new DateTime(2003, 10, 5), true);
Assert.That(() => master.Validate(), Throws.TypeOf<ValidationException>());
Assert.That(() => master.Validate(StringLocalizerMockCreator.GetObject()), Throws.TypeOf<ValidationException>());
}
[Test]
public void FIOIsNotFio()
{
var master = CreateDataModel(Guid.NewGuid().ToString(),"1231" , "11", new DateTime(2023, 10, 5), new DateTime(2003, 10, 5), true);
Assert.That(() => master.Validate(), Throws.TypeOf<ValidationException>());
Assert.That(() => master.Validate(StringLocalizerMockCreator.GetObject()), Throws.TypeOf<ValidationException>());
}
[Test]
public void PostIdIsNullOrEmptyTest()
{
var master = CreateDataModel("11", "fio", null, new DateTime(2023, 10, 5), new DateTime(2003, 10, 5), true);
Assert.That(() => master.Validate(), Throws.TypeOf<ValidationException>());
Assert.That(() => master.Validate(StringLocalizerMockCreator.GetObject()), Throws.TypeOf<ValidationException>());
master = CreateDataModel("11", "fio", string.Empty, new DateTime(2023, 10, 5), new DateTime(2003, 10, 5), true);
Assert.That(() => master.Validate(), Throws.TypeOf<ValidationException>());
Assert.That(() => master.Validate(StringLocalizerMockCreator.GetObject()), Throws.TypeOf<ValidationException>());
}
[Test]
public void PostIdIsNotGuidTest()
{
var master = CreateDataModel("11", "fio", "id", new DateTime(2023, 10, 5), new DateTime(2003, 10, 5), true);
Assert.That(() => master.Validate(), Throws.TypeOf<ValidationException>());
Assert.That(() => master.Validate(StringLocalizerMockCreator.GetObject()), Throws.TypeOf<ValidationException>());
}
[Test]
@@ -56,7 +57,7 @@ internal class MasterDataModelTests
var master = CreateDataModel(Guid.NewGuid().ToString(), "fio",
Guid.NewGuid().ToString(), DateTime.Now.AddYears(-16).AddDays(1), DateTime.Now,
false);
Assert.That(() => master.Validate(),
Assert.That(() => master.Validate(StringLocalizerMockCreator.GetObject()),
Throws.TypeOf<ValidationException>());
}
@@ -65,11 +66,11 @@ internal class MasterDataModelTests
{
var master = CreateDataModel(Guid.NewGuid().ToString(), "fio",
Guid.NewGuid().ToString(), DateTime.Now.AddYears(-15), DateTime.Now.Date, false);
Assert.That(() => master.Validate(),
Assert.That(() => master.Validate(StringLocalizerMockCreator.GetObject()),
Throws.TypeOf<ValidationException>());
master = CreateDataModel(Guid.NewGuid().ToString(), "fio",
Guid.NewGuid().ToString(), DateTime.Now.AddYears(-20), DateTime.Now.AddYears(-21), false);
Assert.That(() => master.Validate(),
Assert.That(() => master.Validate(StringLocalizerMockCreator.GetObject()),
Throws.TypeOf<ValidationException>());
}
[Test]
@@ -84,15 +85,15 @@ internal class MasterDataModelTests
var master = CreateDataModel(id, fio, postId, birthDate, employmentDate, isDeleted);
Assert.That(() => master.Validate(), Throws.Nothing);
Assert.That(() => master.Validate(StringLocalizerMockCreator.GetObject()), Throws.Nothing);
Assert.Multiple(() =>
{
Assert.That(master.Id, Is.EqualTo(id));
Assert.That(master.FIO, Is.EqualTo(fio));
Assert.That(master.PostId, Is.EqualTo(postId));
Assert.That(master.BirthDate, Is.EqualTo(birthDate));
Assert.That(master.EmploymentDate, Is.EqualTo(employmentDate));
Assert.That(master.BirthDate, Is.EqualTo(birthDate.ToUniversalTime()));
Assert.That(master.EmploymentDate, Is.EqualTo(employmentDate.ToUniversalTime()));
Assert.That(master.IsDeleted, Is.EqualTo(isDeleted));
});
}

View File

@@ -6,6 +6,7 @@ using System.Threading.Tasks;
using TwoFromTheCasketContratcs.DataModels;
using TwoFromTheCasketContratcs.Enums;
using TwoFromTheCasketContratcs.Exceptions;
using TwoFromTheCasketTest.Infrastructure;
namespace TwoFromTheCasketTest.DataModelsTest;
@@ -16,35 +17,35 @@ public class OrderDataModelTests
public void IdIsNullOrEmptyTest()
{
var order = CreateDataModel(string.Empty, DateTime.Now, StatusType.Ready, RoomType.Social);
Assert.That(() => order.Validate(), Throws.TypeOf<ValidationException>());
Assert.That(() => order.Validate(StringLocalizerMockCreator.GetObject()), Throws.TypeOf<ValidationException>());
}
[Test]
public void IdIsNotGuidTest()
{
var order = CreateDataModel("id", DateTime.Now, StatusType.Ready, RoomType.Social);
Assert.That(() => order.Validate(), Throws.TypeOf<ValidationException>());
Assert.That(() => order.Validate(StringLocalizerMockCreator.GetObject()), Throws.TypeOf<ValidationException>());
}
[Test]
public void DateIsEmptyTest()
{
var order = CreateDataModel(Guid.NewGuid().ToString(), default, StatusType.Ready, RoomType.Social);
Assert.That(() => order.Validate(), Throws.TypeOf<ValidationException>());
Assert.That(() => order.Validate(StringLocalizerMockCreator.GetObject()), Throws.TypeOf<ValidationException>());
}
[Test]
public void StatusIsNoneTest()
{
var order = CreateDataModel(Guid.NewGuid().ToString(), DateTime.Now, StatusType.None, RoomType.Social);
Assert.That(() => order.Validate(), Throws.TypeOf<ValidationException>());
Assert.That(() => order.Validate(StringLocalizerMockCreator.GetObject()), Throws.TypeOf<ValidationException>());
}
[Test]
public void RoomTypeIsNoneTest()
{
var order = CreateDataModel(Guid.NewGuid().ToString(), DateTime.Now, StatusType.Ready, RoomType.None);
Assert.That(() => order.Validate(), Throws.TypeOf<ValidationException>());
Assert.That(() => order.Validate(StringLocalizerMockCreator.GetObject()), Throws.TypeOf<ValidationException>());
}
[Test]
@@ -57,12 +58,12 @@ public class OrderDataModelTests
var order = CreateDataModel(id, date, status, roomType);
Assert.That(() => order.Validate(), Throws.Nothing);
Assert.That(() => order.Validate(StringLocalizerMockCreator.GetObject()), Throws.Nothing);
Assert.Multiple(() =>
{
Assert.That(order.Id, Is.EqualTo(id));
Assert.That(order.Date, Is.EqualTo(date));
Assert.That(order.Date, Is.EqualTo(date.ToUniversalTime()));
Assert.That(order.Status, Is.EqualTo(status));
Assert.That(order.RoomType, Is.EqualTo(roomType));
});

View File

@@ -6,6 +6,8 @@ using System.Threading.Tasks;
using TwoFromTheCasketContratcs.DataModels;
using TwoFromTheCasketContratcs.Enums;
using TwoFromTheCasketContratcs.Exceptions;
using TwoFromTheCasketContratcs.Infrastructure.PostConfigurations;
using TwoFromTheCasketTest.Infrastructure;
namespace TwoFromTheCasketTest.DataModelsTest;
@@ -15,15 +17,15 @@ public class PostDataModelTests
[Test]
public void IdIsNullOrEmptyTest()
{
var post = CreateDataModel(string.Empty, "Manager", PostType.Plasterer, 50000, true, default);
Assert.That(() => post.Validate(), Throws.TypeOf<ValidationException>());
var post = CreateDataModel(string.Empty, "Manager", PostType.Plasterer, new PostConfiguration { Rate = 50000 });
Assert.That(() => post.Validate(StringLocalizerMockCreator.GetObject()), Throws.TypeOf<ValidationException>());
}
[Test]
public void IdIsNotGuidTest()
{
var post = CreateDataModel("invalid-guid", "Manager", PostType.Plasterer, 50000, true, default);
Assert.That(() => post.Validate(), Throws.TypeOf<ValidationException>());
var post = CreateDataModel("invalid-guid", "Manager", PostType.Plasterer, new PostConfiguration { Rate = 50000 });
Assert.That(() => post.Validate(StringLocalizerMockCreator.GetObject()), Throws.TypeOf<ValidationException>());
}
@@ -31,25 +33,25 @@ public class PostDataModelTests
[Test]
public void PostNameIsNullOrEmptyTest()
{
var post = CreateDataModel(Guid.NewGuid().ToString(), string.Empty, PostType.Plasterer, 50000, true, default);
Assert.That(() => post.Validate(), Throws.TypeOf<ValidationException>());
var post = CreateDataModel(Guid.NewGuid().ToString(), string.Empty, PostType.Plasterer, new PostConfiguration { Rate = 50000 });
Assert.That(() => post.Validate(StringLocalizerMockCreator.GetObject()), Throws.TypeOf<ValidationException>());
}
[Test]
public void PostTypeIsNoneTest()
{
var post = CreateDataModel(Guid.NewGuid().ToString(), "Manager", PostType.None, 50000, true, default);
Assert.That(() => post.Validate(), Throws.TypeOf<ValidationException>());
var post = CreateDataModel(Guid.NewGuid().ToString(), "Manager", PostType.None, new PostConfiguration { Rate = 50000 });
Assert.That(() => post.Validate(StringLocalizerMockCreator.GetObject()), Throws.TypeOf<ValidationException>());
}
[Test]
public void SalaryIsLessOrEqualToZeroTest()
{
var post = CreateDataModel(Guid.NewGuid().ToString(), "Manager", PostType.Plasterer, 0, true, default);
Assert.That(() => post.Validate(), Throws.TypeOf<ValidationException>());
var post = CreateDataModel(Guid.NewGuid().ToString(), "Manager", PostType.Plasterer, new PostConfiguration { Rate = 0 });
Assert.That(() => post.Validate(StringLocalizerMockCreator.GetObject()), Throws.TypeOf<ValidationException>());
post = CreateDataModel(Guid.NewGuid().ToString(), "Manager", PostType.Plasterer, -1000, true, default);
Assert.That(() => post.Validate(), Throws.TypeOf<ValidationException>());
post = CreateDataModel(Guid.NewGuid().ToString(), "Manager", PostType.Plasterer, new PostConfiguration { Rate = -50000 });
Assert.That(() => post.Validate(StringLocalizerMockCreator.GetObject()), Throws.TypeOf<ValidationException>());
}
[Test]
@@ -58,26 +60,27 @@ public class PostDataModelTests
var id = Guid.NewGuid().ToString();
var postName = "Manager";
var postType = PostType.Plasterer;
var salary = 50000.0;
var configuration = new PostConfiguration { Rate = 50000 };
var isActual = true;
var changeDate = DateTime.Now;
var post = CreateDataModel(id, postName, postType, salary, true, default);
var post = CreateDataModel(id, postName, postType, configuration);
Assert.That(() => post.Validate(), Throws.Nothing);
Assert.That(() => post.Validate(StringLocalizerMockCreator.GetObject()), Throws.Nothing);
Assert.Multiple(() =>
{
Assert.That(post.Id, Is.EqualTo(id));
Assert.That(post.PostName, Is.EqualTo(postName));
Assert.That(post.PostType, Is.EqualTo(postType));
Assert.That(post.Salary, Is.EqualTo(salary));
Assert.That(post.ConfigurationModel, Is.EqualTo(configuration));
Assert.That(post.ConfigurationModel.CutleryName, Is.Not.Empty);
});
}
private static PostDataModel CreateDataModel(string id, string postName, PostType postType, double salary, bool isActual, DateTime changeDate)
private static PostDataModel CreateDataModel(string id, string postName, PostType postType, PostConfiguration configuration)
{
return new PostDataModel(id, postName, postType, salary);
return new PostDataModel(id, postName, postType, configuration);
}
}

View File

@@ -5,6 +5,7 @@ using System.Text;
using System.Threading.Tasks;
using TwoFromTheCasketContratcs.DataModels;
using TwoFromTheCasketContratcs.Exceptions;
using TwoFromTheCasketTest.Infrastructure;
namespace TwoFromTheCasketTest.DataModelsTest;
@@ -15,24 +16,24 @@ public class SalaryDataModelTests
public void MasterIdIsNullOrEmptyTest()
{
var salary = CreateDataModel(string.Empty, DateTime.Now, 50000, 1000);
Assert.That(() => salary.Validate(), Throws.TypeOf<ValidationException>());
Assert.That(() => salary.Validate(StringLocalizerMockCreator.GetObject()), Throws.TypeOf<ValidationException>());
}
[Test]
public void MasterIdIsNotGuidTest()
{
var salary = CreateDataModel("invalid-guid", DateTime.Now, 50000, 1000);
Assert.That(() => salary.Validate(), Throws.TypeOf<ValidationException>());
Assert.That(() => salary.Validate(StringLocalizerMockCreator.GetObject()), Throws.TypeOf<ValidationException>());
}
[Test]
public void SalaryIsLessOrEqualToZeroTest()
{
var salary = CreateDataModel(Guid.NewGuid().ToString(), DateTime.Now, 0, 1000);
Assert.That(() => salary.Validate(), Throws.TypeOf<ValidationException>());
Assert.That(() => salary.Validate(StringLocalizerMockCreator.GetObject()), Throws.TypeOf<ValidationException>());
salary = CreateDataModel(Guid.NewGuid().ToString(), DateTime.Now, -1000, 1000);
Assert.That(() => salary.Validate(), Throws.TypeOf<ValidationException>());
Assert.That(() => salary.Validate(StringLocalizerMockCreator.GetObject()), Throws.TypeOf<ValidationException>());
}
[Test]
@@ -45,12 +46,12 @@ public class SalaryDataModelTests
var salary = CreateDataModel(masterId, salaryDate, masterSalary, prize);
Assert.That(() => salary.Validate(), Throws.Nothing);
Assert.That(() => salary.Validate(StringLocalizerMockCreator.GetObject()), Throws.Nothing);
Assert.Multiple(() =>
{
Assert.That(salary.MasterId, Is.EqualTo(masterId));
Assert.That(salary.SalaryDate, Is.EqualTo(salaryDate));
Assert.That(salary.SalaryDate, Is.EqualTo(salaryDate.ToUniversalTime()));
Assert.That(salary.Salary, Is.EqualTo(masterSalary));
Assert.That(salary.Prize, Is.EqualTo(prize));
});

View File

@@ -6,6 +6,7 @@ using System.Threading.Tasks;
using TwoFromTheCasketContratcs.DataModels;
using TwoFromTheCasketContratcs.Enums;
using TwoFromTheCasketContratcs.Exceptions;
using TwoFromTheCasketTest.Infrastructure;
namespace TwoFromTheCasketTest.DataModelsTest;
@@ -16,52 +17,52 @@ public class ServiceDataModelTests
public void IdIsNullOrEmptyTest()
{
var service = CreateDataModel(string.Empty, "bb", ServiceType.Plastering, Guid.NewGuid().ToString(), 100.0, false);
Assert.That(() => service.Validate(), Throws.TypeOf<ValidationException>());
Assert.That(() => service.Validate(StringLocalizerMockCreator.GetObject()), Throws.TypeOf<ValidationException>());
}
[Test]
public void IdIsNotGuidTest()
{
var service = CreateDataModel("invalid-guid", "bb", ServiceType.Plastering, Guid.NewGuid().ToString(), 100.0, false);
Assert.That(() => service.Validate(), Throws.TypeOf<ValidationException>());
Assert.That(() => service.Validate(StringLocalizerMockCreator.GetObject()), Throws.TypeOf<ValidationException>());
}
[Test]
public void ServiceNameIsNullOrEmptyTest()
{
var service = CreateDataModel(Guid.NewGuid().ToString(), string.Empty, ServiceType.Plastering, Guid.NewGuid().ToString(), 100.0, false);
Assert.That(() => service.Validate(), Throws.TypeOf<ValidationException>());
Assert.That(() => service.Validate(StringLocalizerMockCreator.GetObject()), Throws.TypeOf<ValidationException>());
}
[Test]
public void ServiceTypeIsNoneTest()
{
var service = CreateDataModel(Guid.NewGuid().ToString(), "bb", ServiceType.None, Guid.NewGuid().ToString(), 100.0, false);
Assert.That(() => service.Validate(), Throws.TypeOf<ValidationException>());
Assert.That(() => service.Validate(StringLocalizerMockCreator.GetObject()), Throws.TypeOf<ValidationException>());
}
[Test]
public void MasterIdIsNullOrEmptyTest()
{
var service = CreateDataModel(Guid.NewGuid().ToString(), "bb", ServiceType.Plastering, string.Empty, 100.0, false);
Assert.That(() => service.Validate(), Throws.TypeOf<ValidationException>());
Assert.That(() => service.Validate(StringLocalizerMockCreator.GetObject()), Throws.TypeOf<ValidationException>());
}
[Test]
public void MasterIdIsNotGuidTest()
{
var service = CreateDataModel(Guid.NewGuid().ToString(), "bb", ServiceType.Plastering, "invalid-guid", 100.0, false);
Assert.That(() => service.Validate(), Throws.TypeOf<ValidationException>());
Assert.That(() => service.Validate(StringLocalizerMockCreator.GetObject()), Throws.TypeOf<ValidationException>());
}
[Test]
public void PriceIsLessOrEqualToZeroTest()
{
var service = CreateDataModel(Guid.NewGuid().ToString(), "Haircut", ServiceType.Plastering, Guid.NewGuid().ToString(), 0, false);
Assert.That(() => service.Validate(), Throws.TypeOf<ValidationException>());
Assert.That(() => service.Validate(StringLocalizerMockCreator.GetObject()), Throws.TypeOf<ValidationException>());
service = CreateDataModel(Guid.NewGuid().ToString(), "Haircut", ServiceType.Plastering, Guid.NewGuid().ToString(), -50.0, false);
Assert.That(() => service.Validate(), Throws.TypeOf<ValidationException>());
Assert.That(() => service.Validate(StringLocalizerMockCreator.GetObject()), Throws.TypeOf<ValidationException>());
}
[Test]
@@ -76,7 +77,7 @@ public class ServiceDataModelTests
var service = CreateDataModel(id, serviceName, serviceType, masterId, price, isDeleted);
Assert.That(() => service.Validate(), Throws.Nothing);
Assert.That(() => service.Validate(StringLocalizerMockCreator.GetObject()), Throws.Nothing);
Assert.Multiple(() =>
{

View File

@@ -5,6 +5,7 @@ using System.Text;
using System.Threading.Tasks;
using TwoFromTheCasketContratcs.DataModels;
using TwoFromTheCasketContratcs.Exceptions;
using TwoFromTheCasketTest.Infrastructure;
namespace TwoFromTheCasketTest.DataModelsTest;
@@ -15,24 +16,24 @@ public class ServiceHistoryDataModelTests
public void ServiceIdIsNullOrEmptyTest()
{
var serviceHistory = CreateDataModel(string.Empty, 100.0);
Assert.That(() => serviceHistory.Validate(), Throws.TypeOf<ValidationException>());
Assert.That(() => serviceHistory.Validate(StringLocalizerMockCreator.GetObject()), Throws.TypeOf<ValidationException>());
}
[Test]
public void ServiceIdIsNotGuidTest()
{
var serviceHistory = CreateDataModel("invalid-guid", 100.0);
Assert.That(() => serviceHistory.Validate(), Throws.TypeOf<ValidationException>());
Assert.That(() => serviceHistory.Validate(StringLocalizerMockCreator.GetObject()), Throws.TypeOf<ValidationException>());
}
[Test]
public void OldPriceIsLessOrEqualToZeroTest()
{
var serviceHistory = CreateDataModel(Guid.NewGuid().ToString(), 0);
Assert.That(() => serviceHistory.Validate(), Throws.TypeOf<ValidationException>());
Assert.That(() => serviceHistory.Validate(StringLocalizerMockCreator.GetObject()), Throws.TypeOf<ValidationException>());
serviceHistory = CreateDataModel(Guid.NewGuid().ToString(), -50.0);
Assert.That(() => serviceHistory.Validate(), Throws.TypeOf<ValidationException>());
Assert.That(() => serviceHistory.Validate(StringLocalizerMockCreator.GetObject()), Throws.TypeOf<ValidationException>());
}
[Test]
@@ -43,7 +44,7 @@ public class ServiceHistoryDataModelTests
var serviceHistory = CreateDataModel(serviceId, oldPrice);
Assert.That(() => serviceHistory.Validate(), Throws.Nothing);
Assert.That(() => serviceHistory.Validate(StringLocalizerMockCreator.GetObject()), Throws.Nothing);
Assert.Multiple(() =>
{

View File

@@ -5,6 +5,7 @@ using System.Text;
using System.Threading.Tasks;
using TwoFromTheCasketContratcs.DataModels;
using TwoFromTheCasketContratcs.Exceptions;
using TwoFromTheCasketTest.Infrastructure;
namespace TwoFromTheCasketTest.DataModelsTest;
@@ -15,49 +16,49 @@ public class ServiceOrderDataModelTests
public void OrderIdIsNullOrEmptyTest()
{
var serviceOrder = CreateDataModel(string.Empty, Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), 60);
Assert.That(() => serviceOrder.Validate(), Throws.TypeOf<ValidationException>());
Assert.That(() => serviceOrder.Validate(StringLocalizerMockCreator.GetObject()), Throws.TypeOf<ValidationException>());
}
[Test]
public void OrderIdIsNotGuidTest()
{
var serviceOrder = CreateDataModel("invalid-guid", Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), 60);
Assert.That(() => serviceOrder.Validate(), Throws.TypeOf<ValidationException>());
Assert.That(() => serviceOrder.Validate(StringLocalizerMockCreator.GetObject()), Throws.TypeOf<ValidationException>());
}
[Test]
public void ServiceIdIsNullOrEmptyTest()
{
var serviceOrder = CreateDataModel(Guid.NewGuid().ToString(), string.Empty, Guid.NewGuid().ToString(), 60);
Assert.That(() => serviceOrder.Validate(), Throws.TypeOf<ValidationException>());
Assert.That(() => serviceOrder.Validate(StringLocalizerMockCreator.GetObject()), Throws.TypeOf<ValidationException>());
}
[Test]
public void ServiceIdIsNotGuidTest()
{
var serviceOrder = CreateDataModel(Guid.NewGuid().ToString(), "invalid-guid", Guid.NewGuid().ToString(), 60);
Assert.That(() => serviceOrder.Validate(), Throws.TypeOf<ValidationException>());
Assert.That(() => serviceOrder.Validate(StringLocalizerMockCreator.GetObject()), Throws.TypeOf<ValidationException>());
}
[Test]
public void MasterIdIsNullOrEmptyTest()
{
var serviceOrder = CreateDataModel(Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), string.Empty, 60);
Assert.That(() => serviceOrder.Validate(), Throws.TypeOf<ValidationException>());
Assert.That(() => serviceOrder.Validate(StringLocalizerMockCreator.GetObject()), Throws.TypeOf<ValidationException>());
}
[Test]
public void MasterIdIsNotGuidTest()
{
var serviceOrder = CreateDataModel(Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), "invalid-guid", 60);
Assert.That(() => serviceOrder.Validate(), Throws.TypeOf<ValidationException>());
Assert.That(() => serviceOrder.Validate(StringLocalizerMockCreator.GetObject()), Throws.TypeOf<ValidationException>());
}
[Test]
public void TimeOfWorkingIsZeroTest()
{
var serviceOrder = CreateDataModel(Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), 0);
Assert.That(() => serviceOrder.Validate(), Throws.TypeOf<ValidationException>());
Assert.That(() => serviceOrder.Validate(StringLocalizerMockCreator.GetObject()), Throws.TypeOf<ValidationException>());
}
[Test]
@@ -70,7 +71,7 @@ public class ServiceOrderDataModelTests
var serviceOrder = CreateDataModel(orderId, serviceId, masterId, timeOfWorking);
Assert.That(() => serviceOrder.Validate(), Throws.Nothing);
Assert.That(() => serviceOrder.Validate(StringLocalizerMockCreator.GetObject()), Throws.Nothing);
Assert.Multiple(() =>
{

View File

@@ -1,14 +1,18 @@
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TwoFromTheCasketContratcs.Infrastructure;
using TwoFromTheCasketContratcs.Resources;
using TwoFromTheCasketTest.Infrastructure;
using Microsoft.AspNetCore.Localization;
namespace TwoFromTheCasketTest.Infrastructure;
@@ -24,6 +28,7 @@ internal class CustomWebApplicationFactory<TProgram> : WebApplicationFactory<TPr
if (databaseConfig is not null)
services.Remove(databaseConfig);
var loggerFactory = services.SingleOrDefault(x => x.ServiceType == typeof(LoggerFactory));
if (loggerFactory is not null)
services.Remove(loggerFactory);

View File

@@ -0,0 +1,25 @@
using Microsoft.Extensions.Localization;
using Moq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TwoFromTheCasketContratcs.Resources;
namespace TwoFromTheCasketTest.Infrastructure;
internal static class StringLocalizerMockCreator
{
private static Mock<IStringLocalizer<Messages>>? _mockObject = null;
public static IStringLocalizer<Messages> GetObject()
{
if (_mockObject is null)
{
_mockObject = new Mock<IStringLocalizer<Messages>>();
_mockObject.Setup(_ => _[It.IsAny<string>()]).Returns(new LocalizedString("name", "value"));
}
return _mockObject!.Object;
}
}

View File

@@ -1,5 +1,6 @@
using Microsoft.EntityFrameworkCore;
using TwoFromTheCasketContratcs.Enums;
using TwoFromTheCasketContratcs.Infrastructure.PostConfigurations;
using TwoFromTheCasketDatabase;
using TwoFromTheCasketDatabase.Models;
@@ -19,6 +20,8 @@ internal static class TwoFromTheCasketDbContextExtensions
dbContext.ExecuteSqlRaw("TRUNCATE \"Salaries\" CASCADE;");
public static void RemoveServicesFromDatabase(this TwoFromTheCasketDbContext dbContext) =>
dbContext.ExecuteSqlRaw("TRUNCATE \"Services\" CASCADE;");
public static void RemoveServiceHistoriesFromDatabase(this TwoFromTheCasketDbContext dbContext) =>
dbContext.ExecuteSqlRaw("TRUNCATE \"ServiceHistories\" CASCADE;");
public static Master InsertMasterToDatabaseAndReturn(this TwoFromTheCasketDbContext dbContext, string? id = null, string fio = "test", string? postId = null, DateTime? birthDate = null, DateTime?
employmentDate = null, bool isDeleted = false)
{
@@ -28,9 +31,8 @@ employmentDate = null, bool isDeleted = false)
FIO = fio,
PostId = postId ??
Guid.NewGuid().ToString(),
BirthDate = birthDate ?? DateTime.UtcNow.AddYears(-
20),
EmploymentDate = employmentDate ?? DateTime.UtcNow,
BirthDate = DateTime.SpecifyKind(birthDate ?? DateTime.UtcNow.AddYears(-20), DateTimeKind.Utc),
EmploymentDate = DateTime.SpecifyKind(employmentDate ?? DateTime.UtcNow, DateTimeKind.Utc),
IsDeleted = isDeleted
};
dbContext.Masters.Add(master);
@@ -42,7 +44,7 @@ employmentDate = null, bool isDeleted = false)
var order = new Order()
{
Id = id ?? Guid.NewGuid().ToString(),
Date = date ?? DateTime.UtcNow,
Date = DateTime.SpecifyKind(date ?? DateTime.UtcNow, DateTimeKind.Utc),
Status = status ?? StatusType.NotStarted,
RoomType = roomType ?? RoomType.Residential
};
@@ -51,7 +53,7 @@ employmentDate = null, bool isDeleted = false)
return order;
}
public static Post InsertPostToDatabaseAndReturn(this TwoFromTheCasketDbContext dbContext, string? id = null, string? postName = null,
PostType postType = PostType.Plasterer, double salary = 10, bool isActual = true, DateTime? changeDate = null)
PostType postType = PostType.Plasterer, PostConfiguration? configuration = null, bool isActual = true, DateTime? changeDate = null)
{
var post = new Post()
{
@@ -59,7 +61,7 @@ employmentDate = null, bool isDeleted = false)
PostId = id ?? Guid.NewGuid().ToString(),
PostName = postName ?? Guid.NewGuid().ToString(),
PostType = postType,
Salary = salary,
Configuration = configuration ?? new PostConfiguration() { Rate = 100 },
IsActual = isActual,
ChangeDate = changeDate ?? DateTime.UtcNow
};
@@ -67,11 +69,32 @@ employmentDate = null, bool isDeleted = false)
dbContext.SaveChanges();
return post;
}
//private Post InsertPostToDatabaseAndReturn(string id, string postName = "test",
// PostType postType = PostType.None, PostConfiguration? configuration = null, bool isActual = true, DateTime? changeDate = null)
//{
// var post = new Post()
// {
// Id = Guid.NewGuid().ToString(),
// PostId = id ?? Guid.NewGuid().ToString(),
// PostName = postName,
// PostType = postType,
// Configuration = configuration ?? new PostConfiguration() { Rate = 100 },
// IsActual = isActual,
// ChangeDate = changeDate ?? DateTime.UtcNow
// };
// TwoFromTheCasketDbContext.Posts.Add(post);
// TwoFromTheCasketDbContext.SaveChanges();
// return post;
//}
public static Salary InsertSalaryToDatabaseAndReturn(this TwoFromTheCasketDbContext dbContext, string masterId, double salarySize = 1,
DateTime? salaryDate = null)
{
var salary = new Salary()
{ MasterId = masterId, SalarySize = salarySize, SalaryDate = salaryDate ?? DateTime.UtcNow };
{
MasterId = masterId,
SalarySize = salarySize,
SalaryDate = DateTime.SpecifyKind(salaryDate ?? DateTime.UtcNow, DateTimeKind.Utc)
};
dbContext.Salaries.Add(salary);
dbContext.SaveChanges();
return salary;
@@ -93,4 +116,37 @@ employmentDate = null, bool isDeleted = false)
}
public static Salary[] GetSalariesFromDatabaseByEmployeeId(this TwoFromTheCasketDbContext dbContext, string id) =>
[.. dbContext.Salaries.Where(x => x.MasterId == id)];
public static Post? GetPostFromDatabaseByPostId(this TwoFromTheCasketDbContext dbContext, string id) =>
dbContext.Posts.FirstOrDefault(x => x.PostId == id && x.IsActual);
public static ServiceHistory InsertServiceHistoryToDatabaseAndReturn(this TwoFromTheCasketDbContext dbContext, string serviceId, double oldPrice = 100.0)
{
var serviceHistory = new ServiceHistory()
{
ServiceId = serviceId,
OldPrice = oldPrice,
ChangeDate = DateTime.SpecifyKind(DateTime.UtcNow, DateTimeKind.Utc)
};
dbContext.ServiceHistories.Add(serviceHistory);
dbContext.SaveChanges();
return serviceHistory;
}
public static ServiceOrder InsertServiceOrderToDatabaseAndReturn(this TwoFromTheCasketDbContext dbContext, string orderId, string serviceId, string masterId, int timeOfWorking = 1)
{
var serviceOrder = new ServiceOrder()
{
OrderId = orderId,
ServiceId = serviceId,
MasterId = masterId,
TimeOfWorking = timeOfWorking
};
dbContext.ServiceOrders.Add(serviceOrder);
dbContext.SaveChanges();
return serviceOrder;
}
public static void RemoveServiceOrdersFromDatabase(this TwoFromTheCasketDbContext dbContext) =>
dbContext.ExecuteSqlRaw("TRUNCATE \"ServiceOrders\" CASCADE;");
}

View File

@@ -0,0 +1,552 @@
using TwoFromTheCasketDatabase;
using TwoFromTheCasketTest.Infrastructure;
using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Serilog;
using System.Text;
using System.Text.Json;
using Newtonsoft.Json.Linq;
using System.Net;
using TwoFromTheCasketContratcs.BindingModels;
using TwoFromTheCasketContratcs.Enums;
using TwoFromTheCasketDatabase.Models;
using TwoFromTheCasketContratcs.Infrastructure.PostConfigurations;
namespace TwoFromTheCasketTest.LocalizationTests;
internal abstract class BaseLocalizationControllerTest
{
protected abstract string GetLocale();
private WebApplicationFactory<Program> _webApplication;
protected HttpClient HttpClient { get; private set; }
protected static TwoFromTheCasketDbContext? TwoFromTheCasketDbContext { get; private set; }
protected static readonly JsonSerializerOptions JsonSerializerOptions = new() { PropertyNameCaseInsensitive = true };
private static string _masterId = string.Empty;
private static string _postId = string.Empty;
private static string _serviceId = string.Empty;
private static string _orderId = string.Empty;
[OneTimeSetUp]
public void OneTimeSetUp()
{
_webApplication = new CustomWebApplicationFactory<Program>();
HttpClient = _webApplication
.WithWebHostBuilder(builder =>
{
builder.ConfigureTestServices(services =>
{
using var loggerFactory = new LoggerFactory();
loggerFactory.AddSerilog(new LoggerConfiguration()
.ReadFrom.Configuration(new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json")
.Build())
.CreateLogger());
services.AddSingleton(loggerFactory);
});
})
.CreateClient();
var request = HttpClient.GetAsync("/login/user").GetAwaiter().GetResult();
var data = request.Content.ReadAsStringAsync().GetAwaiter().GetResult();
HttpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {data}");
HttpClient.DefaultRequestHeaders.Add("Accept-Language", GetLocale());
TwoFromTheCasketDbContext = _webApplication.Services.GetRequiredService<TwoFromTheCasketDbContext>();
TwoFromTheCasketDbContext.Database.EnsureDeleted();
TwoFromTheCasketDbContext.Database.EnsureCreated();
}
[SetUp]
public void SetUp()
{
_postId = TwoFromTheCasketDbContext!.Posts.Add(new Post
{
Id = Guid.NewGuid().ToString(),
PostId = Guid.NewGuid().ToString(),
PostName = $"Test Post {Guid.NewGuid()}",
PostType = PostType.Plasterer,
Configuration = new PostConfiguration { Rate = 1000 },
IsActual = true,
ChangeDate = DateTime.UtcNow
}).Entity.PostId;
TwoFromTheCasketDbContext.SaveChanges();
_masterId = TwoFromTheCasketDbContext.Masters.Add(new Master
{
Id = Guid.NewGuid().ToString(),
FIO = "Иван Иванов Иванович",
PostId = _postId,
BirthDate = DateTime.UtcNow.AddYears(-25),
EmploymentDate = DateTime.UtcNow.AddDays(-30),
IsDeleted = false
}).Entity.Id;
TwoFromTheCasketDbContext.SaveChanges();
_serviceId = TwoFromTheCasketDbContext.Services.Add(new Service
{
Id = Guid.NewGuid().ToString(),
ServiceName = $"Test Service {Guid.NewGuid()}",
ServiceType = ServiceType.Plastering,
MasterId = _masterId,
Price = 100,
IsDeleted = false
}).Entity.Id;
TwoFromTheCasketDbContext.SaveChanges();
_orderId = TwoFromTheCasketDbContext.Orders.Add(new Order
{
Id = Guid.NewGuid().ToString(),
Date = DateTime.UtcNow,
Status = StatusType.InProcess,
RoomType = RoomType.Industrial
}).Entity.Id;
TwoFromTheCasketDbContext.SaveChanges();
TwoFromTheCasketDbContext.ServiceOrders.Add(new ServiceOrder
{
OrderId = _orderId,
ServiceId = _serviceId,
MasterId = _masterId,
TimeOfWorking = 2
});
TwoFromTheCasketDbContext.SaveChanges();
}
[TearDown]
public void TearDown()
{
TwoFromTheCasketDbContext!.ServiceOrders.RemoveRange(TwoFromTheCasketDbContext.ServiceOrders);
TwoFromTheCasketDbContext.Salaries.RemoveRange(TwoFromTheCasketDbContext.Salaries);
TwoFromTheCasketDbContext.Orders.RemoveRange(TwoFromTheCasketDbContext.Orders);
TwoFromTheCasketDbContext.Masters.RemoveRange(TwoFromTheCasketDbContext.Masters);
TwoFromTheCasketDbContext.Posts.RemoveRange(TwoFromTheCasketDbContext.Posts);
TwoFromTheCasketDbContext.Services.RemoveRange(TwoFromTheCasketDbContext.Services);
TwoFromTheCasketDbContext.SaveChanges();
}
[OneTimeTearDown]
public void OneTimeTearDown()
{
TwoFromTheCasketDbContext?.Database.EnsureDeleted();
TwoFromTheCasketDbContext?.Dispose();
HttpClient?.Dispose();
_webApplication?.Dispose();
}
[Test]
public async Task LoadSalary_WhenHaveRecords_ShouldSuccess_Test()
{
TwoFromTheCasketDbContext!.Salaries.Add(new Salary
{
MasterId = _masterId,
SalaryDate = DateTime.UtcNow.AddDays(-10),
SalarySize = 1000,
Prize = 0
});
TwoFromTheCasketDbContext.Salaries.Add(new Salary
{
MasterId = _masterId,
SalaryDate = DateTime.UtcNow.AddDays(-5),
SalarySize = 1500,
Prize = 200
});
TwoFromTheCasketDbContext.SaveChanges();
var response = await HttpClient.GetAsync($"/api/report/loadsalary?fromDate={DateTime.Now.AddDays(-15):MM/dd/yyyy HH:mm:ss}&toDate={DateTime.Now.AddDays(1):MM/dd/yyyy HH:mm:ss}");
await AssertStreamAsync(response, $"salary-report-{GetLocale()}.pdf");
}
[Test]
public async Task LoadOrders_WhenHaveRecords_ShouldSuccess_Test()
{
// Arrange
// Act
var response = await HttpClient.GetAsync($"/api/report/loadorders?fromDate={DateTime.Now.AddDays(-10):MM/dd/yyyy HH:mm:ss}&toDate={DateTime.Now.AddDays(1):MM/dd/yyyy HH:mm:ss}");
// Assert
await AssertStreamAsync(response, $"orders-report-{GetLocale()}.xlsx");
}
private static async Task AssertStreamAsync(HttpResponseMessage response, string fileNameForSave = "")
{
Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.OK));
using var data = await response.Content.ReadAsStreamAsync();
Assert.That(data, Is.Not.Null);
Assert.That(data.Length, Is.GreaterThan(0));
await SaveStreamAsync(data, fileNameForSave);
}
private static async Task SaveStreamAsync(Stream stream, string fileName)
{
if (string.IsNullOrEmpty(fileName))
{
return;
}
var path = Path.Combine(Directory.GetCurrentDirectory(), fileName);
if (File.Exists(path))
{
File.Delete(path);
}
stream.Position = 0;
using var fileStream = new FileStream(path, FileMode.OpenOrCreate);
await stream.CopyToAsync(fileStream);
}
protected abstract string MessageElementNotFound();
[TestCase("masters")]
[TestCase("posts")]
[TestCase("services")]
[TestCase("orders")]
public async Task Api_GetElement_NotFound_Test(string path)
{
// Act
var response = await HttpClient.GetAsync($"/api/{path}/{Guid.NewGuid()}");
// Assert
var content = await response.Content.ReadAsStringAsync();
if (!string.IsNullOrEmpty(content))
{
Assert.That(JToken.Parse(content).ToString(), Does.StartWith(MessageElementNotFound()));
}
else
{
Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.NotFound));
}
}
private static IEnumerable<TestCaseData> TestDataElementExists()
{
yield return new TestCaseData(() => {
var model = CreateMasterBindingModel();
TwoFromTheCasketDbContext!.Masters.Add(new Master
{
Id = model.Id,
FIO = model.FIO,
PostId = model.PostId,
BirthDate = model.BirthDate ?? DateTime.UtcNow.AddYears(-25),
EmploymentDate = model.EmploymentDate ?? DateTime.UtcNow.AddDays(-30),
IsDeleted = false
});
TwoFromTheCasketDbContext.SaveChanges();
return model;
}, "masters");
yield return new TestCaseData(() => {
var model = CreatePostBindingModel();
TwoFromTheCasketDbContext!.Posts.Add(new Post
{
Id = Guid.NewGuid().ToString(),
PostId = model.Id,
PostName = model.PostName,
PostType = Enum.Parse<PostType>(model.PostType ?? "Plasterer"),
Configuration = JsonSerializer.Deserialize<PostConfiguration>(model.ConfigurationJson ?? "{}") ?? new PostConfiguration { Rate = 1000 },
IsActual = true,
ChangeDate = DateTime.UtcNow
});
TwoFromTheCasketDbContext.SaveChanges();
return model;
}, "posts");
yield return new TestCaseData(() => {
var model = CreateServiceBindingModel();
TwoFromTheCasketDbContext!.Services.Add(new Service
{
Id = model.Id,
ServiceName = model.ServiceName,
ServiceType = model.ServiceType,
MasterId = _masterId,
Price = model.Price,
IsDeleted = false
});
TwoFromTheCasketDbContext.SaveChanges();
return model;
}, "services");
}
protected abstract string MessageElementExists();
[TestCaseSource(nameof(TestDataElementExists))]
public async Task Api_Post_WhenHaveRecordWithSameId_ShouldBadRequest_Test(Func<object> createModel, string path)
{
// Arrange
var model = createModel();
// Act
var response = await HttpClient.PostAsync($"/api/{path}", MakeContent(model));
// Assert
var content = await response.Content.ReadAsStringAsync();
if (!string.IsNullOrEmpty(content))
{
Assert.That(JToken.Parse(content).ToString(), Does.StartWith(MessageElementExists()));
}
else
{
Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.BadRequest).Or.EqualTo(HttpStatusCode.NotFound));
}
}
private static IEnumerable<TestCaseData> TestDataIdIncorrect()
{
yield return new TestCaseData(() => {
var model = CreateMasterBindingModel();
model.Id = "Id";
return model;
}, "masters");
yield return new TestCaseData(() => {
var model = CreatePostBindingModel();
model.Id = "Id";
return model;
}, "posts");
yield return new TestCaseData(() => {
var model = CreateServiceBindingModel();
model.Id = "Id";
return model;
}, "services");
}
protected abstract string MessageElementIdIncorrect();
[TestCaseSource(nameof(TestDataIdIncorrect))]
public async Task Api_Post_WhenDataIsIncorrect_ShouldBadRequest_Test(Func<object> createModel, string path)
{
// Arrange
var model = createModel();
// Act
var responseWithIdIncorrect = await HttpClient.PostAsync($"/api/{path}", MakeContent(model));
// Assert
var content = await responseWithIdIncorrect.Content.ReadAsStringAsync();
if (!string.IsNullOrEmpty(content))
{
Assert.That(JToken.Parse(content).ToString(), Does.StartWith(MessageElementIdIncorrect()));
}
else
{
Assert.That(responseWithIdIncorrect.StatusCode, Is.EqualTo(HttpStatusCode.BadRequest).Or.EqualTo(HttpStatusCode.NotFound));
}
}
[TestCase("masters")]
[TestCase("posts")]
[TestCase("services")]
[TestCase("orders")]
public async Task Api_DelElement_NotFound_Test(string path)
{
// Act
var response = await HttpClient.DeleteAsync($"/api/{path}/{Guid.NewGuid()}");
// Assert
var content = await response.Content.ReadAsStringAsync();
if (!string.IsNullOrEmpty(content))
{
Assert.That(JToken.Parse(content).ToString(), Does.StartWith(MessageElementNotFound()));
}
else
{
Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.NotFound));
}
}
private static MasterBindingModel CreateMasterBindingModel(string? id = null, string fio = "Test Master", string? postId = null, DateTime? birthDate = null, DateTime? employmentDate = null)
=> new()
{
Id = id ?? Guid.NewGuid().ToString(),
FIO = fio,
PostId = postId ?? Guid.NewGuid().ToString(),
BirthDate = birthDate ?? DateTime.UtcNow.AddYears(-25),
EmploymentDate = employmentDate ?? DateTime.UtcNow.AddDays(-30)
};
private static PostBindingModel CreatePostBindingModel(string? id = null, string postName = "Test Post", PostType postType = PostType.Plasterer, string? configurationJson = null)
=> new()
{
Id = id ?? Guid.NewGuid().ToString(),
PostName = postName,
PostType = postType.ToString(),
ConfigurationJson = configurationJson ?? JsonSerializer.Serialize(new PostConfiguration { Rate = 1000 })
};
private static ServiceBindingModel CreateServiceBindingModel(string? id = null, string serviceName = "Test Service", ServiceType serviceType = ServiceType.Plastering, double price = 100)
=> new()
{
Id = id ?? Guid.NewGuid().ToString(),
ServiceName = serviceName,
ServiceType = serviceType,
Price = price
};
private static OrderBindingModel CreateOrderBindingModel(string? id = null, DateTime? date = null, StatusType status = StatusType.InProcess, RoomType roomType = RoomType.Industrial)
=> new()
{
Id = id ?? Guid.NewGuid().ToString(),
Date = date ?? DateTime.UtcNow,
Status = status,
RoomType = roomType
};
protected abstract string MessageValidationErrorIDIsEmpty();
private static IEnumerable<TestCaseData> TestDataValidationErrorIdIsEmpty()
{
yield return new TestCaseData(() =>
{
var model = CreateMasterBindingModel();
model.Id = "";
return model;
}, "masters");
yield return new TestCaseData(() =>
{
var model = CreatePostBindingModel();
model.Id = "";
return model;
}, "posts");
yield return new TestCaseData(() =>
{
var model = CreateServiceBindingModel();
model.Id = "";
return model;
}, "services");
}
[TestCaseSource(nameof(TestDataValidationErrorIdIsEmpty))]
public async Task Api_Put_ValidationError_IdIsEmpty_ShouldBadRequest_Test(Func<object> createModel, string path)
{
// Arrange
var model = createModel();
// Act
var responseWithIdIncorrect = await HttpClient.PutAsync($"/api/{path}", MakeContent(model));
// Assert
var content = await responseWithIdIncorrect.Content.ReadAsStringAsync();
if (!string.IsNullOrEmpty(content))
{
Assert.That(JToken.Parse(content).ToString(), Does.StartWith(MessageValidationErrorIDIsEmpty()));
}
else
{
Assert.That(responseWithIdIncorrect.StatusCode, Is.EqualTo(HttpStatusCode.BadRequest).Or.EqualTo(HttpStatusCode.NotFound));
}
}
protected abstract string MessageValidationErrorIDIsNotGuid();
private static IEnumerable<TestCaseData> TestDataValidationErrorIdIsNotGuid()
{
yield return new TestCaseData(() =>
{
var model = CreateMasterBindingModel();
model.Id = "id";
return model;
}, "masters");
yield return new TestCaseData(() =>
{
var model = CreatePostBindingModel();
model.Id = "id";
return model;
}, "posts");
yield return new TestCaseData(() =>
{
var model = CreateServiceBindingModel();
model.Id = "id";
return model;
}, "services");
}
[TestCaseSource(nameof(TestDataValidationErrorIdIsNotGuid))]
public async Task Api_Put_ValidationError_IdIsNotGuid_ShouldBadRequest_Test(Func<object> createModel, string path)
{
// Arrange
var model = createModel();
// Act
var responseWithIdIncorrect = await HttpClient.PutAsync($"/api/{path}", MakeContent(model));
// Assert
var content = await responseWithIdIncorrect.Content.ReadAsStringAsync();
if (!string.IsNullOrEmpty(content))
{
Assert.That(JToken.Parse(content).ToString(), Does.StartWith(MessageValidationErrorIDIsNotGuid()));
}
else
{
Assert.That(responseWithIdIncorrect.StatusCode, Is.EqualTo(HttpStatusCode.BadRequest).Or.EqualTo(HttpStatusCode.NotFound));
}
}
protected abstract string MessageElementValidationErrorPostNameEmpty();
[TestCase("posts")]
public async Task Api_Put_ValidationError_PostNameIsEmpty_ShouldBadRequest_Test(string path)
{
// Arrange
var model = CreatePostBindingModel();
model.PostName = "";
// Act
var responseWithIdIncorrect = await HttpClient.PutAsync($"/api/{path}", MakeContent(model));
// Assert
var content = await responseWithIdIncorrect.Content.ReadAsStringAsync();
if (!string.IsNullOrEmpty(content))
{
Assert.That(JToken.Parse(content).ToString(), Does.StartWith(MessageElementValidationErrorPostNameEmpty()));
}
else
{
Assert.That(responseWithIdIncorrect.StatusCode, Is.EqualTo(HttpStatusCode.BadRequest).Or.EqualTo(HttpStatusCode.NotFound));
}
}
protected abstract string MessageElementValidationErrorFIOIsEmpty();
[TestCase("masters")]
public async Task Api_Put_ValidationError_FIOIsEmpty_ShouldBadRequest_Test(string path)
{
// Arrange
var model = CreateMasterBindingModel();
model.FIO = "";
// Act
var responseWithIdIncorrect = await HttpClient.PutAsync($"/api/{path}", MakeContent(model));
// Assert
var content = await responseWithIdIncorrect.Content.ReadAsStringAsync();
if (!string.IsNullOrEmpty(content))
{
Assert.That(JToken.Parse(content).ToString(), Does.StartWith(MessageElementValidationErrorFIOIsEmpty()));
}
else
{
Assert.That(responseWithIdIncorrect.StatusCode, Is.EqualTo(HttpStatusCode.BadRequest).Or.EqualTo(HttpStatusCode.NotFound));
}
}
protected abstract string MessageElementValidationErrorServiceNameEmpty();
[TestCase("services")]
public async Task Api_Put_ValidationError_ServiceNameIsEmpty_ShouldBadRequest_Test(string path)
{
// Arrange
var model = CreateServiceBindingModel();
model.ServiceName = "";
// Act
var responseWithIdIncorrect = await HttpClient.PutAsync($"/api/{path}", MakeContent(model));
// Assert
var content = await responseWithIdIncorrect.Content.ReadAsStringAsync();
if (!string.IsNullOrEmpty(content))
{
Assert.That(JToken.Parse(content).ToString(), Does.StartWith(MessageElementValidationErrorServiceNameEmpty()));
}
else
{
Assert.That(responseWithIdIncorrect.StatusCode, Is.EqualTo(HttpStatusCode.BadRequest).Or.EqualTo(HttpStatusCode.NotFound));
}
}
private static async Task<T?> GetModelFromResponseAsync<T>(HttpResponseMessage response) =>
JsonSerializer.Deserialize<T>(await response.Content.ReadAsStringAsync(), JsonSerializerOptions);
private static StringContent MakeContent(object model) =>
new(JsonSerializer.Serialize(model), Encoding.UTF8, "application/json");
}

Some files were not shown because too many files have changed in this diff Show More