fix
This commit is contained in:
@@ -0,0 +1,318 @@
|
||||
namespace MyOffice.Services.Account
|
||||
{
|
||||
using Core;
|
||||
using Core.Helpers;
|
||||
using Data.Models.Accounts;
|
||||
using Data.Models.Motions;
|
||||
using Data.Repositories.Account;
|
||||
using Data.Repositories.Currency;
|
||||
using Data.Repositories.Motion;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using MyOffice.Services.Account.Domain;
|
||||
|
||||
public class AccountService
|
||||
{
|
||||
private ILogger<AccountService> _logger;
|
||||
public readonly IAccountCategoryRepository _accountCategoryRepository;
|
||||
public readonly IAccountRepository _accountRepository;
|
||||
public readonly ICurrencyRepository _currencyRepository;
|
||||
public readonly IAccountAccountCategoryRepository _accountAccountCategoryRepository;
|
||||
public readonly IAccountMotionRepository _accountMotionRepository;
|
||||
public readonly IMotionRepository _motionRepository;
|
||||
public readonly IMotionGlobalRepository _motionGlobalRepository;
|
||||
|
||||
public AccountService(
|
||||
ILogger<AccountService> logger,
|
||||
IAccountCategoryRepository accountCategoryRepository,
|
||||
IAccountRepository accountRepository,
|
||||
ICurrencyRepository currencyRepository,
|
||||
IAccountAccountCategoryRepository accountAccountCategoryRepository,
|
||||
IAccountMotionRepository accountMotionRepository,
|
||||
IMotionRepository motionRepository,
|
||||
IMotionGlobalRepository motionGlobalRepository
|
||||
)
|
||||
{
|
||||
_logger = logger;
|
||||
_accountCategoryRepository = accountCategoryRepository;
|
||||
_accountRepository = accountRepository;
|
||||
_currencyRepository = currencyRepository;
|
||||
_accountAccountCategoryRepository = accountAccountCategoryRepository;
|
||||
_accountMotionRepository = accountMotionRepository;
|
||||
_motionRepository = motionRepository;
|
||||
_motionGlobalRepository = motionGlobalRepository;
|
||||
}
|
||||
|
||||
public List<AccountCategory> GetAllCategories(Guid userId)
|
||||
{
|
||||
return _accountCategoryRepository.GetAll(userId);
|
||||
}
|
||||
|
||||
public Exec<AccountCategory, GeneralExecStatus> CategoryAdd(Guid userId, AccountCategory category)
|
||||
{
|
||||
if (category == null)
|
||||
throw new ArgumentNullException(nameof(category));
|
||||
|
||||
var result = new Exec<AccountCategory, GeneralExecStatus>(GeneralExecStatus.success);
|
||||
|
||||
category.Id = Guid.NewGuid();
|
||||
category.UserId = userId;
|
||||
|
||||
if (!_accountCategoryRepository.Add(category))
|
||||
{
|
||||
return result.Set(GeneralExecStatus.failure);
|
||||
}
|
||||
|
||||
return result.Set(category);
|
||||
}
|
||||
|
||||
public Exec<AccountCategory, GeneralExecStatus> CategoryUpdate(Guid userId, Guid id, AccountCategory category)
|
||||
{
|
||||
if (category == null)
|
||||
throw new ArgumentNullException(nameof(category));
|
||||
|
||||
var result = new Exec<AccountCategory, GeneralExecStatus>(GeneralExecStatus.success);
|
||||
|
||||
var exists = _accountCategoryRepository.Get(userId, id);
|
||||
if (exists == null)
|
||||
{
|
||||
return result.Set(GeneralExecStatus.not_found);
|
||||
}
|
||||
|
||||
exists.Name = category.Name;
|
||||
|
||||
if (!_accountCategoryRepository.Update(exists))
|
||||
{
|
||||
return result.Set(GeneralExecStatus.failure);
|
||||
}
|
||||
|
||||
return result.Set(exists);
|
||||
}
|
||||
|
||||
public Exec<AccountCategory, AccountCategoryRemoveResult> CategoryRemove(Guid userId, Guid id)
|
||||
{
|
||||
var result = new Exec<AccountCategory, AccountCategoryRemoveResult>(AccountCategoryRemoveResult.success);
|
||||
|
||||
var exists = _accountCategoryRepository.Get(userId, id);
|
||||
if (exists == null)
|
||||
{
|
||||
return result.Set(AccountCategoryRemoveResult.not_found);
|
||||
}
|
||||
|
||||
if (exists.Accounts?.Any() == true)
|
||||
{
|
||||
return result.Set(AccountCategoryRemoveResult.accounts_exists);
|
||||
}
|
||||
if (!_accountCategoryRepository.Remove(exists))
|
||||
{
|
||||
return result.Set(AccountCategoryRemoveResult.failure);
|
||||
}
|
||||
|
||||
return result.Set(exists);
|
||||
}
|
||||
|
||||
public List<Account> GetAllAccounts(Guid userId)
|
||||
{
|
||||
return _accountRepository.GetAll(userId);
|
||||
}
|
||||
|
||||
public List<Account> GetByCategory(Guid userId, Guid categoryId)
|
||||
{
|
||||
return _accountRepository.GetByCategory(userId, categoryId);
|
||||
}
|
||||
|
||||
public List<AccountDetailed> GetByCategoryDetailed(Guid userId, Guid categoryId)
|
||||
{
|
||||
return _accountRepository.GetByCategoryDetailed(userId, categoryId);
|
||||
}
|
||||
|
||||
public Exec<Account, AccountAddResult> AccountAdd(Guid userId, AccountAdd input)
|
||||
{
|
||||
if (input == null)
|
||||
throw new ArgumentNullException(nameof(input));
|
||||
|
||||
var result = new Exec<Account, AccountAddResult>(AccountAddResult.success);
|
||||
|
||||
var category = _accountCategoryRepository.Get(userId, input.CategoryId);
|
||||
if (category == null)
|
||||
{
|
||||
return result.Set(AccountAddResult.category_not_found);
|
||||
}
|
||||
var currency = _currencyRepository.GetByGlobalCurrency(userId, input.CurrencyId);
|
||||
if (currency == null)
|
||||
{
|
||||
return result.Set(AccountAddResult.currency_not_found);
|
||||
}
|
||||
|
||||
var account = new Account
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
Name = input.Name,
|
||||
CurrencyGlobalId = currency.CurrencyGlobalId,
|
||||
};
|
||||
|
||||
account.Categories = new List<AccountAccountCategory>
|
||||
{
|
||||
new()
|
||||
{
|
||||
AccountId = account.Id,
|
||||
CategoryId = category.Id,
|
||||
}
|
||||
};
|
||||
account.AccessRights = new List<AccountAccess>
|
||||
{
|
||||
new()
|
||||
{
|
||||
AccountId = account.Id,
|
||||
UserId = userId,
|
||||
IsAllowManage = true,
|
||||
IsAllowRead = true,
|
||||
IsAllowWrite = true,
|
||||
}
|
||||
};
|
||||
|
||||
if (!_accountRepository.Add(account))
|
||||
{
|
||||
return result.Set(AccountAddResult.failure);
|
||||
}
|
||||
|
||||
return result.Set(account);
|
||||
}
|
||||
|
||||
public Exec<Account, AccountEditResult> AccountUpdate(Guid userId, Guid accountId, AccountEdit input)
|
||||
{
|
||||
if (input == null)
|
||||
throw new ArgumentNullException(nameof(input));
|
||||
|
||||
var result = new Exec<Account, AccountEditResult>(AccountEditResult.success);
|
||||
|
||||
AccountCategory? category = null;
|
||||
if (input.CategoryId.HasValue)
|
||||
{
|
||||
category = _accountCategoryRepository.Get(userId, input.CategoryId.Value);
|
||||
if (category == null)
|
||||
{
|
||||
return result.Set(AccountEditResult.category_not_found);
|
||||
}
|
||||
}
|
||||
|
||||
var currency = _currencyRepository.GetByGlobalCurrency(userId, input.CurrencyId);
|
||||
if (currency == null)
|
||||
{
|
||||
return result.Set(AccountEditResult.currency_not_found);
|
||||
}
|
||||
|
||||
var account = _accountRepository.Get(userId, accountId);
|
||||
if (account == null)
|
||||
{
|
||||
return result.Set(AccountEditResult.not_found);
|
||||
}
|
||||
|
||||
account.Name = input.Name;
|
||||
if (account.CurrencyGlobalId != currency.CurrencyGlobalId)
|
||||
{
|
||||
account.CurrencyGlobalId = currency.CurrencyGlobalId;
|
||||
}
|
||||
|
||||
if (category != null && account.Categories!.All(x => x.CategoryId != category.Id))
|
||||
{
|
||||
account.Categories = new List<AccountAccountCategory>
|
||||
{
|
||||
new()
|
||||
{
|
||||
AccountId = account.Id,
|
||||
CategoryId = category.Id,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
if (!_accountRepository.Update(account))
|
||||
{
|
||||
return result.Set(AccountEditResult.failure);
|
||||
}
|
||||
|
||||
return result.Set(account);
|
||||
}
|
||||
|
||||
public Exec<List<AccountAccountCategory>, GeneralExecStatus> AccountCategoryRemove(Guid userId, Guid accountId, Guid categoryId)
|
||||
{
|
||||
var result = new Exec<List<AccountAccountCategory>, GeneralExecStatus>(GeneralExecStatus.success);
|
||||
|
||||
var categories = _accountAccountCategoryRepository.Get(userId, accountId, categoryId);
|
||||
if (categories.Count == 0)
|
||||
{
|
||||
return result.Set(GeneralExecStatus.not_found);
|
||||
}
|
||||
|
||||
foreach (var category in categories)
|
||||
{
|
||||
_accountAccountCategoryRepository.Remove(category);
|
||||
}
|
||||
|
||||
return result.Set(categories);
|
||||
}
|
||||
|
||||
public Exec<AccountMotion, AccountMotionAddResult> AccountMotionAdd(
|
||||
Guid userId,
|
||||
Guid accountId,
|
||||
AccountMotionAdd accountMotion
|
||||
)
|
||||
{
|
||||
if (accountMotion == null)
|
||||
throw new ArgumentNullException(nameof(accountMotion));
|
||||
if (accountMotion.Motion == null)
|
||||
throw new ArgumentNullException(nameof(accountMotion.Motion));
|
||||
|
||||
var result = new Exec<AccountMotion, AccountMotionAddResult>(AccountMotionAddResult.success);
|
||||
|
||||
var account = _accountRepository.Get(userId, accountId);
|
||||
if (account == null)
|
||||
{
|
||||
return result.Set(AccountMotionAddResult.account_not_found);
|
||||
}
|
||||
|
||||
var motion = _motionGlobalRepository.GetByName(accountMotion.Motion);
|
||||
if (motion == null)
|
||||
{
|
||||
motion = new MotionGlobal
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
Name = accountMotion.Motion.Trim(),
|
||||
};
|
||||
if (_motionGlobalRepository.Add(motion))
|
||||
{
|
||||
return result.Set(AccountMotionAddResult.failure);
|
||||
}
|
||||
}
|
||||
|
||||
var motionAccount = _motionRepository.GetByGlobal(userId, motion.Id);
|
||||
if (motionAccount == null)
|
||||
{
|
||||
motionAccount = new MotionAccount
|
||||
{
|
||||
CategoryId = userId,
|
||||
MotionGlobalId = motion.Id,
|
||||
};
|
||||
_motionRepository.Add(motionAccount);
|
||||
}
|
||||
|
||||
var accountMotionDb = new AccountMotion
|
||||
{
|
||||
CreatedOn = DateTime.UtcNow,
|
||||
DateTime = accountMotion.Date,
|
||||
AccountId = account.Id,
|
||||
MotionId = motionAccount.Id,
|
||||
AmountPlus = accountMotion.Plus,
|
||||
AmountMinus = accountMotion.Minus,
|
||||
Description = accountMotion.Description,
|
||||
};
|
||||
|
||||
if (!_accountMotionRepository.Add(accountMotionDb))
|
||||
{
|
||||
return result.Set(GeneralExecStatus.failure);
|
||||
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace MyOffice.Services.Account.Domain
|
||||
{
|
||||
public class AccountAdd
|
||||
{
|
||||
public string Name { get; set; } = null!;
|
||||
public string CurrencyId { get; set; } = null!;
|
||||
public Guid CategoryId { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace MyOffice.Services.Account.Domain
|
||||
{
|
||||
public enum AccountAddResult
|
||||
{
|
||||
success,
|
||||
failure,
|
||||
category_not_found,
|
||||
currency_not_found,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace MyOffice.Services.Account.Domain
|
||||
{
|
||||
public enum AccountCategoryRemoveResult
|
||||
{
|
||||
success,
|
||||
failure,
|
||||
not_found,
|
||||
accounts_exists,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace MyOffice.Services.Account.Domain;
|
||||
|
||||
public class AccountEdit
|
||||
{
|
||||
public string Name { get; set; } = null!;
|
||||
public string CurrencyId { get; set; } = null!;
|
||||
public Guid? CategoryId { get; set; }
|
||||
public Guid? UserId { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace MyOffice.Services.Account.Domain;
|
||||
|
||||
public enum AccountEditResult
|
||||
{
|
||||
success,
|
||||
failure,
|
||||
not_found,
|
||||
category_not_found,
|
||||
currency_not_found,
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
namespace MyOffice.Services.Account.Domain
|
||||
{
|
||||
public class AccountMotionAdd
|
||||
{
|
||||
public DateTime Date { get; set; }
|
||||
public string Motion { get; set; } = null!;
|
||||
public string Description { get; set; } = null!;
|
||||
public decimal Plus { get; set; }
|
||||
public decimal Minus { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace MyOffice.Services.Account.Domain;
|
||||
|
||||
public enum AccountMotionAddResult
|
||||
{
|
||||
success,
|
||||
failure,
|
||||
account_not_found,
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
namespace MyOffice.Services.Currency;
|
||||
|
||||
using Core;
|
||||
using Data.Models.Currencies;
|
||||
using Data.Repositories.Currency;
|
||||
using MyOffice.Services.Currency.Domain;
|
||||
|
||||
public class CurrencyService
|
||||
{
|
||||
private readonly ICurrencyGlobalRepository _currencyGlobalRepository;
|
||||
private readonly ICurrencyRepository _currencyRepository;
|
||||
private readonly ICurrencyRateRepository _currencyRateRepository;
|
||||
|
||||
public CurrencyService(
|
||||
ICurrencyGlobalRepository currencyGlobalRepository,
|
||||
ICurrencyRepository currencyRepository,
|
||||
ICurrencyRateRepository currencyRateRepository
|
||||
)
|
||||
{
|
||||
_currencyGlobalRepository = currencyGlobalRepository;
|
||||
_currencyRepository = currencyRepository;
|
||||
_currencyRateRepository = currencyRateRepository;
|
||||
}
|
||||
|
||||
public List<CurrencyGlobal> GetGlobalAll()
|
||||
{
|
||||
return _currencyGlobalRepository.GetAll();
|
||||
}
|
||||
|
||||
public List<Currency> GetAll(Guid userId)
|
||||
{
|
||||
return _currencyRepository.GetAll(userId);
|
||||
}
|
||||
|
||||
public Dictionary<Currency, CurrencyRate?> GetAllWithRates(Guid userId)
|
||||
{
|
||||
var list = _currencyRepository.GetAll(userId);
|
||||
return list.ToDictionary(
|
||||
x => x,
|
||||
x => _currencyRateRepository.GetLastRates(x.Id, 1).FirstOrDefault()
|
||||
);
|
||||
}
|
||||
|
||||
public Exec<Currency, AddCurrencyStatus> AddCurrency(Guid userId, Currency currency)
|
||||
{
|
||||
if (currency == null)
|
||||
throw new ArgumentNullException(nameof(currency));
|
||||
|
||||
var result = new Exec<Currency, AddCurrencyStatus>(AddCurrencyStatus.success);
|
||||
|
||||
var exists = _currencyRepository.GetByGlobalCurrency(userId, currency.CurrencyGlobalId);
|
||||
if (exists != null)
|
||||
{
|
||||
return result.Set(exists, AddCurrencyStatus.exists);
|
||||
}
|
||||
|
||||
currency.Id = Guid.NewGuid();
|
||||
currency.UserId = userId;
|
||||
if (!_currencyRepository.Add(currency))
|
||||
{
|
||||
return result.Set(AddCurrencyStatus.failed);
|
||||
}
|
||||
|
||||
return result.Set(currency);
|
||||
}
|
||||
|
||||
public Exec<CurrencyRate, CurrencyAddRateStatus> AddCurrencyRate(Guid userId, Guid currencyId, CurrencyRate currencyRate)
|
||||
{
|
||||
if (currencyRate == null)
|
||||
throw new ArgumentNullException(nameof(currencyRate));
|
||||
|
||||
var result = new Exec<CurrencyRate, CurrencyAddRateStatus>(CurrencyAddRateStatus.success);
|
||||
|
||||
var exists = _currencyRepository.Get(userId, currencyId);
|
||||
if (exists == null)
|
||||
{
|
||||
return result.Set(CurrencyAddRateStatus.not_found);
|
||||
}
|
||||
|
||||
currencyRate.CurrencyId = exists.Id;
|
||||
currencyRate.DateTime = currencyRate.DateTime.Date;
|
||||
|
||||
var rate = _currencyRateRepository.GetAtDate(currencyRate.CurrencyId, currencyRate.DateTime);
|
||||
if (rate.All(x => x.Rate != currencyRate.Rate))
|
||||
{
|
||||
if (_currencyRateRepository.AddRate(currencyRate))
|
||||
{
|
||||
return result.Set(currencyRate);
|
||||
}
|
||||
}
|
||||
|
||||
return result.Set(CurrencyAddRateStatus.failed);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
namespace MyOffice.Services.Currency.Domain
|
||||
{
|
||||
public enum AddCurrencyStatus
|
||||
{
|
||||
success,
|
||||
failed,
|
||||
exists,
|
||||
}
|
||||
|
||||
public enum CurrencyAddRateStatus
|
||||
{
|
||||
not_found,
|
||||
success,
|
||||
failed,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace MyOffice.Services.Motion.Domain
|
||||
{
|
||||
public enum MotionCategoryRemoveResult
|
||||
{
|
||||
success,
|
||||
failure,
|
||||
not_found,
|
||||
accounts_exists,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
namespace MyOffice.Services.Motion
|
||||
{
|
||||
using MyOffice.Data.Repositories.Motion;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Data.Models.Motions;
|
||||
using MyOffice.Core;
|
||||
using MyOffice.Services.Motion.Domain;
|
||||
|
||||
public class MotionService
|
||||
{
|
||||
private readonly IMotionCategoryRepository _motionCategoryRepository;
|
||||
private readonly IMotionRepository _motionRepository;
|
||||
|
||||
public MotionService(
|
||||
IMotionCategoryRepository motionCategoryRepository,
|
||||
IMotionRepository motionRepository
|
||||
)
|
||||
{
|
||||
_motionCategoryRepository = motionCategoryRepository;
|
||||
_motionRepository = motionRepository;
|
||||
|
||||
}
|
||||
|
||||
public List<MotionCategory> GetAllCategories(Guid userId)
|
||||
{
|
||||
var result = _motionCategoryRepository.GetAll(userId);
|
||||
if (result.All(x => x.Id != userId))
|
||||
{
|
||||
var category = new MotionCategory
|
||||
{
|
||||
Id = userId,
|
||||
UserId = userId,
|
||||
Name = "UnCategorized",
|
||||
};
|
||||
_motionCategoryRepository.Add(category);
|
||||
|
||||
result.Add(_motionCategoryRepository.Get(userId, userId)!);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public Exec<MotionCategory, GeneralExecStatus> CategoryAdd(Guid userId, MotionCategory category)
|
||||
{
|
||||
if (category == null)
|
||||
throw new ArgumentNullException(nameof(category));
|
||||
|
||||
var result = new Exec<MotionCategory, GeneralExecStatus>(GeneralExecStatus.success);
|
||||
|
||||
category.Id = Guid.NewGuid();
|
||||
category.UserId = userId;
|
||||
|
||||
if (!_motionCategoryRepository.Add(category))
|
||||
{
|
||||
return result.Set(GeneralExecStatus.failure);
|
||||
}
|
||||
|
||||
return result.Set(category);
|
||||
}
|
||||
|
||||
public Exec<MotionCategory, GeneralExecStatus> CategoryUpdate(Guid userId, Guid id, MotionCategory category)
|
||||
{
|
||||
if (category == null)
|
||||
throw new ArgumentNullException(nameof(category));
|
||||
|
||||
var result = new Exec<MotionCategory, GeneralExecStatus>(GeneralExecStatus.success);
|
||||
|
||||
var exists = _motionCategoryRepository.Get(userId, id);
|
||||
if (exists == null)
|
||||
{
|
||||
return result.Set(GeneralExecStatus.not_found);
|
||||
}
|
||||
|
||||
exists.Name = category.Name;
|
||||
|
||||
if (!_motionCategoryRepository.Update(exists))
|
||||
{
|
||||
return result.Set(GeneralExecStatus.failure);
|
||||
}
|
||||
|
||||
return result.Set(exists);
|
||||
}
|
||||
|
||||
public Exec<MotionCategory, MotionCategoryRemoveResult> CategoryRemove(Guid userId, Guid id)
|
||||
{
|
||||
var result = new Exec<MotionCategory, MotionCategoryRemoveResult>(MotionCategoryRemoveResult.success);
|
||||
|
||||
var exists = _motionCategoryRepository.Get(userId, id);
|
||||
if (exists == null)
|
||||
{
|
||||
return result.Set(MotionCategoryRemoveResult.not_found);
|
||||
}
|
||||
|
||||
if (exists.Motions.Any())
|
||||
{
|
||||
return result.Set(MotionCategoryRemoveResult.accounts_exists);
|
||||
}
|
||||
if (!_motionCategoryRepository.Remove(exists))
|
||||
{
|
||||
return result.Set(MotionCategoryRemoveResult.failure);
|
||||
}
|
||||
|
||||
return result.Set(exists);
|
||||
}
|
||||
|
||||
public List<MotionAccount> GetAll(Guid userId)
|
||||
{
|
||||
return _motionRepository.GetAll(userId);
|
||||
}
|
||||
|
||||
public List<MotionAccount> GetByCategory(Guid userId, Guid categoryId)
|
||||
{
|
||||
return _motionRepository.GetByCategory(userId, categoryId);
|
||||
}
|
||||
|
||||
public Exec<MotionAccount, GeneralExecStatus> Update(Guid userId, Guid motionId, Guid categoryId)
|
||||
{
|
||||
var result = new Exec<MotionAccount, GeneralExecStatus>(GeneralExecStatus.success);
|
||||
|
||||
var motion = _motionRepository.GetByGlobal(userId, motionId);
|
||||
if (motion == null)
|
||||
{
|
||||
return result.Set(GeneralExecStatus.not_found);
|
||||
}
|
||||
|
||||
motion.Category.Id = categoryId;
|
||||
//motion.CategoryId = categoryId;
|
||||
_motionRepository.Update(motion);
|
||||
|
||||
return result.Set(motion);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace MyOffice.Services.Validators
|
||||
{
|
||||
public static class ContextValidator
|
||||
{
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user