This commit is contained in:
2023-07-23 20:27:23 +03:00
parent d0cdaa85b6
commit 96eca795ab
62 changed files with 2934 additions and 847 deletions
+6 -11
View File
@@ -1,22 +1,16 @@
namespace MyOffice.Data.Models.Accounts; namespace MyOffice.Data.Models.Accounts;
using Currencies; using Currencies;
using MyOffice.Data.Models.Users;
public enum AccountTypeEnum
{
debit,
credit,
transit,
other,
}
public class Account public class Account
{ {
public Guid Id { get; set; } public Guid Id { get; set; }
public string CurrencyGlobalId { get; set; } = null!; public string CurrencyGlobalId { get; set; } = null!;
public CurrencyGlobal? CurrencyGlobal { get; set; } public CurrencyGlobal? CurrencyGlobal { get; set; }
public Guid? OwnerId { get; set; }
public User? Owner { get; set; }
public string Name { get; set; } = null!; public string Name { get; set; } = null!;
public AccountTypeEnum Type { get; set; }
public IEnumerable<AccountAccess>? AccessRights { get; set; } public IEnumerable<AccountAccess>? AccessRights { get; set; }
public IEnumerable<Motion>? Motions { get; set; } public IEnumerable<Motion>? Motions { get; set; }
public IEnumerable<AccountAccountCategory>? Categories { get; set; } public IEnumerable<AccountAccountCategory>? Categories { get; set; }
@@ -34,8 +28,9 @@ public struct AccountSimple
{ {
public Guid Id { get; set; } public Guid Id { get; set; }
public string Name { get; set; } public string Name { get; set; }
public string? CurrencyName { get; set; } public AccountAccessTypeEnum Type { get; set; }
public string? CurrencyShortName { get; set; } public string CurrencyName { get; set; }
public string CurrencyShortName { get; set; }
public decimal? CurrencyRate { get; set; } public decimal? CurrencyRate { get; set; }
public int? CurrencyQuantity { get; set; } public int? CurrencyQuantity { get; set; }
public decimal? TotalPlus { get; set; } public decimal? TotalPlus { get; set; }
@@ -2,6 +2,14 @@
using MyOffice.Data.Models.Users; using MyOffice.Data.Models.Users;
public enum AccountAccessTypeEnum
{
balance,
credit,
external,
other,
}
public class AccountAccess public class AccountAccess
{ {
public int Id { get; set; } public int Id { get; set; }
@@ -13,4 +21,5 @@ public class AccountAccess
public bool IsAllowRead { get; set; } public bool IsAllowRead { get; set; }
public bool IsAllowWrite { get; set; } public bool IsAllowWrite { get; set; }
public bool IsAllowManage { get; set; } public bool IsAllowManage { get; set; }
public AccountAccessTypeEnum Type { get; set; }
} }
@@ -2,6 +2,19 @@
using MyOffice.Data.Models.Accounts; using MyOffice.Data.Models.Accounts;
public enum CurrencyGlobalIdEnum
{
UAH,
USD,
EUR,
GBP,
RUB,
BTC,
ETH,
TON,
OTHER,
}
public class CurrencyGlobal public class CurrencyGlobal
{ {
public string Id { get; set; } = null!; public string Id { get; set; } = null!;
+1
View File
@@ -29,4 +29,5 @@ public class User
public IEnumerable<Motion>? AccountMotions { get; set; } public IEnumerable<Motion>? AccountMotions { get; set; }
public IEnumerable<AccountCategory>? AccountCategories { get; set; } public IEnumerable<AccountCategory>? AccountCategories { get; set; }
public IEnumerable<ItemCategory>? ItemCategories { get; set; } public IEnumerable<ItemCategory>? ItemCategories { get; set; }
public IEnumerable<Account>? Accounts { get; set; }
} }
@@ -0,0 +1,13 @@
namespace MyOffice.Data.Repositories.Account;
using Models.Accounts;
using MyOffice.Data.Repositories;
public class AccountAccessRepository : AppRepository<AccountAccess>, IAccountAccessRepository
{
public bool Update(AccountAccess accountAccess)
{
return UpdateBase(accountAccess) > 0;
}
}
@@ -1,9 +1,7 @@
namespace MyOffice.Data.Repositories.Account; namespace MyOffice.Data.Repositories.Account;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using Models.Accounts; using Models.Accounts;
using MyOffice.Data.Models.Currencies;
using MyOffice.Data.Repositories; using MyOffice.Data.Repositories;
public class AccountRepository : AppRepository<Account>, IAccountRepository public class AccountRepository : AppRepository<Account>, IAccountRepository
@@ -16,6 +14,7 @@ public class AccountRepository : AppRepository<Account>, IAccountRepository
.ThenInclude(x => x.Category) .ThenInclude(x => x.Category)
.Include(x => x.AccessRights)! .Include(x => x.AccessRights)!
.ThenInclude(x => x.User) .ThenInclude(x => x.User)
.Include(x => x.Motions)!
.Where(x => x.AccessRights!.Any(a => a.UserId == userId)) .Where(x => x.AccessRights!.Any(a => a.UserId == userId))
.ToList(); .ToList();
} }
@@ -28,6 +27,7 @@ public class AccountRepository : AppRepository<Account>, IAccountRepository
.ThenInclude(x => x.Category) .ThenInclude(x => x.Category)
.Include(x => x.AccessRights)! .Include(x => x.AccessRights)!
.ThenInclude(x => x.User) .ThenInclude(x => x.User)
.Include(x => x.Motions)!
.Where(x => x.Categories!.Any(c => c.CategoryId == categoryId) && x.AccessRights!.Any(a => a.UserId == userId)) .Where(x => x.Categories!.Any(c => c.CategoryId == categoryId) && x.AccessRights!.Any(a => a.UserId == userId))
.ToList(); .ToList();
} }
@@ -73,6 +73,11 @@ public class AccountRepository : AppRepository<Account>, IAccountRepository
return AddBase(account) > 0; return AddBase(account) > 0;
} }
public bool Delete(Account account)
{
return RemoveBase(account) > 0;
}
public Account? Get(Guid userId, Guid id) public Account? Get(Guid userId, Guid id)
{ {
return _context.Accounts! return _context.Accounts!
@@ -80,6 +85,7 @@ public class AccountRepository : AppRepository<Account>, IAccountRepository
.ThenInclude(x => x.Category) .ThenInclude(x => x.Category)
.Include(x => x.AccessRights)! .Include(x => x.AccessRights)!
.ThenInclude(x => x.User) .ThenInclude(x => x.User)
.Include(x => x.Motions)!
.FirstOrDefault(x => x.Id == id && x.AccessRights!.Any(r => r.UserId == userId)); .FirstOrDefault(x => x.Id == id && x.AccessRights!.Any(r => r.UserId == userId));
} }
@@ -141,27 +147,42 @@ public class AccountRepository : AppRepository<Account>, IAccountRepository
public List<AccountSimple> GetRestAtDate(Guid userId, DateTime date) public List<AccountSimple> GetRestAtDate(Guid userId, DateTime date)
{ {
return _context.Accounts return _context.AccountAccesses!
.Include(x => x.CurrencyGlobal!) .Where(x => x.UserId == userId)
.Include(x => x.Account!)
.ThenInclude(x => x.CurrencyGlobal!)
.ThenInclude(x => x.Currencies!) .ThenInclude(x => x.Currencies!)
.ThenInclude(x => x.CurrentRate!) .ThenInclude(x => x.CurrentRate!)
.Where(x => x.AccessRights!.Any(u => u.UserId == userId)) .Include(x => x.Account)
.Select(x => new { .ThenInclude(x => x!.Motions)
Id = x.Id, .Select(x => new
Name = x.Name, {
Currency = x.CurrencyGlobal!.Currencies!.FirstOrDefault(x => x.UserId == userId), Id = x.AccountId,
Rest = x.Motions!.Sum(m => (m.AmountPlus - m.AmountMinus)) Name = x.Account!.Name,
Type = x.Type,
Currency = x.Account!.CurrencyGlobal!.Currencies!.FirstOrDefault(c => c.UserId == userId),
CurrentRate = x.Account!.CurrencyGlobal!.Currencies!.FirstOrDefault(c => c.UserId == userId)!.CurrentRate,
Plus = x.Account.Motions!
.Where(x => !x.DeletedOn.HasValue)
.Sum(m => m.AmountPlus),
Minus = x.Account.Motions!
.Where(x => !x.DeletedOn.HasValue)
.Sum(m => m.AmountMinus),
}) })
.ToList() .ToList()
.Select(x => new AccountSimple .Select(x => new AccountSimple
{ {
Id = x.Id, Id = x.Id,
Name = x.Name, Name = x.Name,
Balance = x.Rest, Type = x.Type,
CurrencyName = x.Currency?.Name, CurrencyName = x.Currency!.Name,
CurrencyShortName = x.Currency?.ShortName, CurrencyShortName = x.Currency!.ShortName,
CurrencyRate = x.Currency?.CurrentRate?.Rate, CurrencyRate = x.CurrentRate?.Rate,
CurrencyQuantity = x.Currency?.CurrentRate?.Quantity, CurrencyQuantity = x.CurrentRate?.Quantity,
}).ToList(); TotalMinus = x.Minus,
TotalPlus = x.Plus,
Balance = x.Plus - x.Minus,
})
.ToList();
} }
} }
@@ -0,0 +1,8 @@
namespace MyOffice.Data.Repositories.Account;
using Models.Accounts;
public interface IAccountAccessRepository
{
bool Update(AccountAccess accountAccess);
}
@@ -9,6 +9,7 @@ public interface IAccountRepository
List<AccountDetailed> GetByCategoryDetailed(Guid userId, Guid categoryId); List<AccountDetailed> GetByCategoryDetailed(Guid userId, Guid categoryId);
AccountDetailed? GetByIdDetailed(Guid userId, Guid id); AccountDetailed? GetByIdDetailed(Guid userId, Guid id);
bool Add(Account account); bool Add(Account account);
bool Delete(Account account);
Account? Get(Guid userId, Guid id); Account? Get(Guid userId, Guid id);
bool Update(Account account); bool Update(Account account);
bool Remove(Account account); bool Remove(Account account);
@@ -11,7 +11,7 @@ public class ItemRepository : AppRepository<Item>, IItemRepository
.Include(x => x.Motions) .Include(x => x.Motions)
.Include(x => x.Category) .Include(x => x.Category)
.Include(x => x.ItemGlobal) .Include(x => x.ItemGlobal)
.Where(x => x.Category.UserId == userId) .Where(x => x.Category!.UserId == userId)
.ToList(); .ToList();
} }
@@ -21,7 +21,7 @@ public class ItemRepository : AppRepository<Item>, IItemRepository
.Include(x => x.Motions) .Include(x => x.Motions)
.Include(x => x.Category) .Include(x => x.Category)
.Include(x => x.ItemGlobal) .Include(x => x.ItemGlobal)
.Where(x => x.Category.UserId == userId && x.CategoryId == categoryId) .Where(x => x.Category!.UserId == userId && x.CategoryId == categoryId)
.ToList(); .ToList();
} }
@@ -50,7 +50,7 @@ public class ItemRepository : AppRepository<Item>, IItemRepository
.Items .Items
.Include(x => x.ItemGlobal) .Include(x => x.ItemGlobal)
.Where(x => x.Category!.UserId == userId && x.ItemGlobal.Name.Contains(term)) .Where(x => x.Category!.UserId == userId && x.ItemGlobal.Name.Contains(term))
.OrderByDescending(x => x.Motions.Count()) .OrderByDescending(x => x!.Motions!.Count())
.Take(limit) .Take(limit)
.ToList(); .ToList();
} }
@@ -44,6 +44,11 @@ public class RepositoryBase<TEntity> where TEntity : class
return await _context.Set<TEntity>().FindAsync(id); return await _context.Set<TEntity>().FindAsync(id);
} }
protected TEntity? GetBase(Guid id)
{
return _context.Set<TEntity>().Find(id);
}
protected async Task<int> AddBaseAsync(TEntity entity) protected async Task<int> AddBaseAsync(TEntity entity)
{ {
//await _context.Set<TEntity>().AddAsync(entity); //await _context.Set<TEntity>().AddAsync(entity);
@@ -5,6 +5,7 @@ using MyOffice.Data.Models.Users;
public interface IUserRepository public interface IUserRepository
{ {
Task<User?> GetUserAsync(Guid id); Task<User?> GetUserAsync(Guid id);
User? GetUser(Guid id);
Task<User?> GetByUserUserNameAsync(string userName); Task<User?> GetByUserUserNameAsync(string userName);
User? GetByUserUserName(string userName); User? GetByUserUserName(string userName);
@@ -11,6 +11,11 @@ public class UserRepository : AppRepository<User>, IUserRepository
return await GetBaseAsync(id); return await GetBaseAsync(id);
} }
public User? GetUser(Guid id)
{
return GetBase(id);
}
public async Task<User?> GetByUserUserNameAsync(string userName) public async Task<User?> GetByUserUserNameAsync(string userName)
{ {
return await _context.Users.FirstOrDefaultAsync(x => x.UserName == userName); return await _context.Users.FirstOrDefaultAsync(x => x.UserName == userName);
+11
View File
@@ -5,6 +5,7 @@ using Data.Models.Currencies;
using Data.Models.Items; using Data.Models.Items;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Data.Models.Users; using Data.Models.Users;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
public enum AppDbContextProvidersEnum public enum AppDbContextProvidersEnum
{ {
@@ -144,6 +145,11 @@ public class AppDbContext : DbContext
.WithMany(x => x.Accounts) .WithMany(x => x.Accounts)
.HasForeignKey(x => x.CurrencyGlobalId); .HasForeignKey(x => x.CurrencyGlobalId);
modelBuilder.Entity<Account>()
.HasOne(x => x.Owner)
.WithMany(x => x.Accounts)
.HasForeignKey(x => x.OwnerId);
modelBuilder.Entity<AccountAccess>() modelBuilder.Entity<AccountAccess>()
.HasOne(x => x.Account) .HasOne(x => x.Account)
.WithMany(x => x.AccessRights) .WithMany(x => x.AccessRights)
@@ -173,6 +179,11 @@ public class AppDbContext : DbContext
.HasOne(x => x.Category) .HasOne(x => x.Category)
.WithMany(x => x.Accounts) .WithMany(x => x.Accounts)
.HasForeignKey(x => x.CategoryId); .HasForeignKey(x => x.CategoryId);
modelBuilder
.Entity<AccountAccess>()
.Property(d => d.Type)
.HasConversion(new EnumToStringConverter<AccountAccessTypeEnum>());
} }
private void MotionsCreating(ModelBuilder modelBuilder) private void MotionsCreating(ModelBuilder modelBuilder)
+9 -9
View File
@@ -32,15 +32,15 @@ public class RepositoryInitializer
// CurrencyGlobals // CurrencyGlobals
var predefinedCurrencyGlobals = new List<CurrencyGlobal>() var predefinedCurrencyGlobals = new List<CurrencyGlobal>()
{ {
new() { Id = "UAH", DefaultQuantity = 1, Symbol = "₴", Name = "Ukrainian hryvnias" }, new() { Id = CurrencyGlobalIdEnum.UAH.ToString(), DefaultQuantity = 1, Symbol = "₴", Name = "Ukrainian hryvnias" },
new() { Id = "USD", DefaultQuantity = 1, Symbol = "$", Name = "US Dollar" }, new() { Id = CurrencyGlobalIdEnum.USD.ToString(), DefaultQuantity = 1, Symbol = "$", Name = "US Dollar" },
new() { Id = "EUR", DefaultQuantity = 1, Symbol = "€", Name = "Euros" }, new() { Id = CurrencyGlobalIdEnum.EUR.ToString(), DefaultQuantity = 1, Symbol = "€", Name = "Euros" },
new() { Id = "GBP", DefaultQuantity = 1, Symbol = "£", Name = "British pounds sterling" }, new() { Id = CurrencyGlobalIdEnum.GBP.ToString(), DefaultQuantity = 1, Symbol = "£", Name = "British pounds sterling" },
new() { Id = "RUB", DefaultQuantity = 10, Symbol = "₽", Name = "Russia Ruble" }, new() { Id = CurrencyGlobalIdEnum.RUB.ToString(), DefaultQuantity = 10, Symbol = "₽", Name = "Russia Ruble" },
new() { Id = "BTC", DefaultQuantity = 10, Symbol = "btc", Name = "Bitcoin" }, new() { Id = CurrencyGlobalIdEnum.BTC.ToString(), DefaultQuantity = 10, Symbol = "btc", Name = "Bitcoin" },
new() { Id = "ETH", DefaultQuantity = 10, Symbol = "eth", Name = "Ethereum" }, new() { Id = CurrencyGlobalIdEnum.ETH.ToString(), DefaultQuantity = 10, Symbol = "eth", Name = "Ethereum" },
new() { Id = "TON", DefaultQuantity = 10, Symbol = "ton", Name = "TON" }, new() { Id = CurrencyGlobalIdEnum.TON.ToString(), DefaultQuantity = 10, Symbol = "ton", Name = "TON" },
new() { Id = "OTHER", DefaultQuantity = 1, Symbol = "", Name = "Other" }, new() { Id = CurrencyGlobalIdEnum.OTHER.ToString(), DefaultQuantity = 1, Symbol = "", Name = "Other" },
}; };
var currencyGlobals = dbContext.CurrencyGlobals.ToList(); var currencyGlobals = dbContext.CurrencyGlobals.ToList();
@@ -0,0 +1,636 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using MyOffice.DbContext;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
namespace MyOffice.Migrations.Postgres.Migrations
{
[DbContext(typeof(AppDbContext))]
[Migration("20230721200424_AccountType")]
partial class AccountType
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("Npgsql:CollationDefinition:my_ci_collation", "en-u-ks-primary,en-u-ks-primary,icu,False")
.HasAnnotation("ProductVersion", "7.0.0")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("MyOffice.Data.Models.Accounts.Account", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("CurrencyGlobalId")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.Property<int>("Type")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("CurrencyGlobalId");
b.ToTable("Accounts");
});
modelBuilder.Entity("MyOffice.Data.Models.Accounts.AccountAccess", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<Guid>("AccountId")
.HasColumnType("uuid");
b.Property<bool>("IsAllowManage")
.HasColumnType("boolean");
b.Property<bool>("IsAllowRead")
.HasColumnType("boolean");
b.Property<bool>("IsAllowWrite")
.HasColumnType("boolean");
b.Property<Guid>("UserId")
.HasColumnType("uuid");
b.HasKey("Id");
b.HasIndex("AccountId");
b.HasIndex("UserId");
b.ToTable("AccountAccesses");
});
modelBuilder.Entity("MyOffice.Data.Models.Accounts.AccountAccountCategory", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<Guid>("AccountId")
.HasColumnType("uuid");
b.Property<Guid>("CategoryId")
.HasColumnType("uuid");
b.HasKey("Id");
b.HasIndex("AccountId");
b.HasIndex("CategoryId");
b.ToTable("AccountAccountCategories");
});
modelBuilder.Entity("MyOffice.Data.Models.Accounts.AccountCategory", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.Property<Guid>("UserId")
.HasColumnType("uuid");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("AccountCategories");
});
modelBuilder.Entity("MyOffice.Data.Models.Accounts.Motion", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<Guid>("AccountId")
.HasColumnType("uuid");
b.Property<decimal>("AmountMinus")
.HasPrecision(18, 6)
.HasColumnType("numeric(18,6)");
b.Property<decimal>("AmountPlus")
.HasPrecision(18, 6)
.HasColumnType("numeric(18,6)");
b.Property<DateTime>("CreatedOn")
.HasColumnType("timestamp with time zone");
b.Property<DateTime>("DateTime")
.HasColumnType("timestamp with time zone");
b.Property<DateTime?>("DeletedOn")
.HasColumnType("timestamp with time zone");
b.Property<string>("Description")
.HasColumnType("text");
b.Property<int>("ItemId")
.HasColumnType("integer");
b.Property<Guid?>("UserId")
.HasColumnType("uuid");
b.HasKey("Id");
b.HasIndex("AccountId");
b.HasIndex("ItemId");
b.HasIndex("UserId");
b.ToTable("Motions");
});
modelBuilder.Entity("MyOffice.Data.Models.Currencies.Currency", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("CurrencyGlobalId")
.IsRequired()
.HasColumnType("text");
b.Property<int?>("CurrentRateId")
.HasColumnType("integer");
b.Property<bool>("IsPrimary")
.HasColumnType("boolean");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.Property<string>("ShortName")
.IsRequired()
.HasColumnType("text");
b.Property<Guid>("UserId")
.HasColumnType("uuid");
b.HasKey("Id");
b.HasIndex("CurrencyGlobalId");
b.HasIndex("CurrentRateId");
b.HasIndex("UserId");
b.ToTable("Currencies");
});
modelBuilder.Entity("MyOffice.Data.Models.Currencies.CurrencyGlobal", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<int>("DefaultQuantity")
.HasColumnType("integer");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Symbol")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("CurrencyGlobals");
});
modelBuilder.Entity("MyOffice.Data.Models.Currencies.CurrencyRate", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<Guid>("CurrencyId")
.HasColumnType("uuid");
b.Property<DateTime>("DateTime")
.HasColumnType("timestamp with time zone");
b.Property<int>("Quantity")
.HasColumnType("integer");
b.Property<decimal>("Rate")
.HasColumnType("numeric");
b.HasKey("Id");
b.HasIndex("CurrencyId");
b.ToTable("CurrencyRates");
});
modelBuilder.Entity("MyOffice.Data.Models.Items.Item", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<Guid>("CategoryId")
.HasColumnType("uuid");
b.Property<Guid>("ItemGlobalId")
.HasColumnType("uuid");
b.HasKey("Id");
b.HasIndex("CategoryId");
b.HasIndex("ItemGlobalId");
b.ToTable("Items");
});
modelBuilder.Entity("MyOffice.Data.Models.Items.ItemCategory", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<bool>("IsInternal")
.HasColumnType("boolean");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.Property<Guid>("UserId")
.HasColumnType("uuid");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("ItemCategories");
});
modelBuilder.Entity("MyOffice.Data.Models.Items.ItemGlobal", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("ItemGlobals");
});
modelBuilder.Entity("MyOffice.Data.Models.Users.User", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("CurrencyId")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Email")
.IsRequired()
.HasColumnType("text")
.UseCollation("my_ci_collation");
b.Property<string>("FirstName")
.HasColumnType("text");
b.Property<string>("FullName")
.HasColumnType("text");
b.Property<bool>("IsEmailConfirmed")
.HasColumnType("boolean");
b.Property<string>("LastName")
.HasColumnType("text");
b.Property<string>("PasswordHash")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Phone")
.HasColumnType("text");
b.Property<string>("UserName")
.IsRequired()
.HasColumnType("text")
.UseCollation("my_ci_collation");
b.HasKey("Id");
b.HasIndex("CurrencyId");
b.ToTable("Users");
});
modelBuilder.Entity("MyOffice.Data.Models.Users.UserExternal", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<DateTime>("CreatedOn")
.HasColumnType("timestamp with time zone");
b.Property<string>("Email")
.IsRequired()
.HasColumnType("text")
.UseCollation("my_ci_collation");
b.Property<string>("ExternalId")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Provider")
.IsRequired()
.HasColumnType("text")
.UseCollation("my_ci_collation");
b.Property<Guid>("UserId")
.HasColumnType("uuid");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("UserClaims");
});
modelBuilder.Entity("MyOffice.Data.Models.Accounts.Account", b =>
{
b.HasOne("MyOffice.Data.Models.Currencies.CurrencyGlobal", "CurrencyGlobal")
.WithMany("Accounts")
.HasForeignKey("CurrencyGlobalId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("CurrencyGlobal");
});
modelBuilder.Entity("MyOffice.Data.Models.Accounts.AccountAccess", b =>
{
b.HasOne("MyOffice.Data.Models.Accounts.Account", "Account")
.WithMany("AccessRights")
.HasForeignKey("AccountId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("MyOffice.Data.Models.Users.User", "User")
.WithMany("AccountAccess")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Account");
b.Navigation("User");
});
modelBuilder.Entity("MyOffice.Data.Models.Accounts.AccountAccountCategory", b =>
{
b.HasOne("MyOffice.Data.Models.Accounts.Account", "Account")
.WithMany("Categories")
.HasForeignKey("AccountId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("MyOffice.Data.Models.Accounts.AccountCategory", "Category")
.WithMany("Accounts")
.HasForeignKey("CategoryId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Account");
b.Navigation("Category");
});
modelBuilder.Entity("MyOffice.Data.Models.Accounts.AccountCategory", b =>
{
b.HasOne("MyOffice.Data.Models.Users.User", "User")
.WithMany("AccountCategories")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("MyOffice.Data.Models.Accounts.Motion", b =>
{
b.HasOne("MyOffice.Data.Models.Accounts.Account", "Account")
.WithMany("Motions")
.HasForeignKey("AccountId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("MyOffice.Data.Models.Items.Item", "Item")
.WithMany("Motions")
.HasForeignKey("ItemId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("MyOffice.Data.Models.Users.User", null)
.WithMany("AccountMotions")
.HasForeignKey("UserId");
b.Navigation("Account");
b.Navigation("Item");
});
modelBuilder.Entity("MyOffice.Data.Models.Currencies.Currency", b =>
{
b.HasOne("MyOffice.Data.Models.Currencies.CurrencyGlobal", "CurrencyGlobal")
.WithMany("Currencies")
.HasForeignKey("CurrencyGlobalId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("MyOffice.Data.Models.Currencies.CurrencyRate", "CurrentRate")
.WithMany("Currencies")
.HasForeignKey("CurrentRateId");
b.HasOne("MyOffice.Data.Models.Users.User", "User")
.WithMany("Currencies")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("CurrencyGlobal");
b.Navigation("CurrentRate");
b.Navigation("User");
});
modelBuilder.Entity("MyOffice.Data.Models.Currencies.CurrencyRate", b =>
{
b.HasOne("MyOffice.Data.Models.Currencies.Currency", "Currency")
.WithMany("Rates")
.HasForeignKey("CurrencyId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Currency");
});
modelBuilder.Entity("MyOffice.Data.Models.Items.Item", b =>
{
b.HasOne("MyOffice.Data.Models.Items.ItemCategory", "Category")
.WithMany("Items")
.HasForeignKey("CategoryId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("MyOffice.Data.Models.Items.ItemGlobal", "ItemGlobal")
.WithMany("Items")
.HasForeignKey("ItemGlobalId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Category");
b.Navigation("ItemGlobal");
});
modelBuilder.Entity("MyOffice.Data.Models.Items.ItemCategory", b =>
{
b.HasOne("MyOffice.Data.Models.Users.User", "User")
.WithMany("ItemCategories")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("MyOffice.Data.Models.Users.User", b =>
{
b.HasOne("MyOffice.Data.Models.Currencies.CurrencyGlobal", "Currency")
.WithMany()
.HasForeignKey("CurrencyId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Currency");
});
modelBuilder.Entity("MyOffice.Data.Models.Users.UserExternal", b =>
{
b.HasOne("MyOffice.Data.Models.Users.User", "User")
.WithMany("UserClaims")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("MyOffice.Data.Models.Accounts.Account", b =>
{
b.Navigation("AccessRights");
b.Navigation("Categories");
b.Navigation("Motions");
});
modelBuilder.Entity("MyOffice.Data.Models.Accounts.AccountCategory", b =>
{
b.Navigation("Accounts");
});
modelBuilder.Entity("MyOffice.Data.Models.Currencies.Currency", b =>
{
b.Navigation("Rates");
});
modelBuilder.Entity("MyOffice.Data.Models.Currencies.CurrencyGlobal", b =>
{
b.Navigation("Accounts");
b.Navigation("Currencies");
});
modelBuilder.Entity("MyOffice.Data.Models.Currencies.CurrencyRate", b =>
{
b.Navigation("Currencies");
});
modelBuilder.Entity("MyOffice.Data.Models.Items.Item", b =>
{
b.Navigation("Motions");
});
modelBuilder.Entity("MyOffice.Data.Models.Items.ItemCategory", b =>
{
b.Navigation("Items");
});
modelBuilder.Entity("MyOffice.Data.Models.Items.ItemGlobal", b =>
{
b.Navigation("Items");
});
modelBuilder.Entity("MyOffice.Data.Models.Users.User", b =>
{
b.Navigation("AccountAccess");
b.Navigation("AccountCategories");
b.Navigation("AccountMotions");
b.Navigation("Currencies");
b.Navigation("ItemCategories");
b.Navigation("UserClaims");
});
#pragma warning restore 612, 618
}
}
}
@@ -0,0 +1,29 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace MyOffice.Migrations.Postgres.Migrations
{
/// <inheritdoc />
public partial class AccountType : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<int>(
name: "Type",
table: "Accounts",
type: "integer",
nullable: false,
defaultValue: 0);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "Type",
table: "Accounts");
}
}
}
@@ -0,0 +1,637 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using MyOffice.DbContext;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
namespace MyOffice.Migrations.Postgres.Migrations
{
[DbContext(typeof(AppDbContext))]
[Migration("20230722051335_AccountType2")]
partial class AccountType2
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("Npgsql:CollationDefinition:my_ci_collation", "en-u-ks-primary,en-u-ks-primary,icu,False")
.HasAnnotation("ProductVersion", "7.0.0")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("MyOffice.Data.Models.Accounts.Account", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("CurrencyGlobalId")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("CurrencyGlobalId");
b.ToTable("Accounts");
});
modelBuilder.Entity("MyOffice.Data.Models.Accounts.AccountAccess", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<Guid>("AccountId")
.HasColumnType("uuid");
b.Property<bool>("IsAllowManage")
.HasColumnType("boolean");
b.Property<bool>("IsAllowRead")
.HasColumnType("boolean");
b.Property<bool>("IsAllowWrite")
.HasColumnType("boolean");
b.Property<string>("Type")
.IsRequired()
.HasColumnType("text");
b.Property<Guid>("UserId")
.HasColumnType("uuid");
b.HasKey("Id");
b.HasIndex("AccountId");
b.HasIndex("UserId");
b.ToTable("AccountAccesses");
});
modelBuilder.Entity("MyOffice.Data.Models.Accounts.AccountAccountCategory", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<Guid>("AccountId")
.HasColumnType("uuid");
b.Property<Guid>("CategoryId")
.HasColumnType("uuid");
b.HasKey("Id");
b.HasIndex("AccountId");
b.HasIndex("CategoryId");
b.ToTable("AccountAccountCategories");
});
modelBuilder.Entity("MyOffice.Data.Models.Accounts.AccountCategory", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.Property<Guid>("UserId")
.HasColumnType("uuid");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("AccountCategories");
});
modelBuilder.Entity("MyOffice.Data.Models.Accounts.Motion", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<Guid>("AccountId")
.HasColumnType("uuid");
b.Property<decimal>("AmountMinus")
.HasPrecision(18, 6)
.HasColumnType("numeric(18,6)");
b.Property<decimal>("AmountPlus")
.HasPrecision(18, 6)
.HasColumnType("numeric(18,6)");
b.Property<DateTime>("CreatedOn")
.HasColumnType("timestamp with time zone");
b.Property<DateTime>("DateTime")
.HasColumnType("timestamp with time zone");
b.Property<DateTime?>("DeletedOn")
.HasColumnType("timestamp with time zone");
b.Property<string>("Description")
.HasColumnType("text");
b.Property<int>("ItemId")
.HasColumnType("integer");
b.Property<Guid?>("UserId")
.HasColumnType("uuid");
b.HasKey("Id");
b.HasIndex("AccountId");
b.HasIndex("ItemId");
b.HasIndex("UserId");
b.ToTable("Motions");
});
modelBuilder.Entity("MyOffice.Data.Models.Currencies.Currency", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("CurrencyGlobalId")
.IsRequired()
.HasColumnType("text");
b.Property<int?>("CurrentRateId")
.HasColumnType("integer");
b.Property<bool>("IsPrimary")
.HasColumnType("boolean");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.Property<string>("ShortName")
.IsRequired()
.HasColumnType("text");
b.Property<Guid>("UserId")
.HasColumnType("uuid");
b.HasKey("Id");
b.HasIndex("CurrencyGlobalId");
b.HasIndex("CurrentRateId");
b.HasIndex("UserId");
b.ToTable("Currencies");
});
modelBuilder.Entity("MyOffice.Data.Models.Currencies.CurrencyGlobal", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<int>("DefaultQuantity")
.HasColumnType("integer");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Symbol")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("CurrencyGlobals");
});
modelBuilder.Entity("MyOffice.Data.Models.Currencies.CurrencyRate", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<Guid>("CurrencyId")
.HasColumnType("uuid");
b.Property<DateTime>("DateTime")
.HasColumnType("timestamp with time zone");
b.Property<int>("Quantity")
.HasColumnType("integer");
b.Property<decimal>("Rate")
.HasColumnType("numeric");
b.HasKey("Id");
b.HasIndex("CurrencyId");
b.ToTable("CurrencyRates");
});
modelBuilder.Entity("MyOffice.Data.Models.Items.Item", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<Guid>("CategoryId")
.HasColumnType("uuid");
b.Property<Guid>("ItemGlobalId")
.HasColumnType("uuid");
b.HasKey("Id");
b.HasIndex("CategoryId");
b.HasIndex("ItemGlobalId");
b.ToTable("Items");
});
modelBuilder.Entity("MyOffice.Data.Models.Items.ItemCategory", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<bool>("IsInternal")
.HasColumnType("boolean");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.Property<Guid>("UserId")
.HasColumnType("uuid");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("ItemCategories");
});
modelBuilder.Entity("MyOffice.Data.Models.Items.ItemGlobal", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("ItemGlobals");
});
modelBuilder.Entity("MyOffice.Data.Models.Users.User", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("CurrencyId")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Email")
.IsRequired()
.HasColumnType("text")
.UseCollation("my_ci_collation");
b.Property<string>("FirstName")
.HasColumnType("text");
b.Property<string>("FullName")
.HasColumnType("text");
b.Property<bool>("IsEmailConfirmed")
.HasColumnType("boolean");
b.Property<string>("LastName")
.HasColumnType("text");
b.Property<string>("PasswordHash")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Phone")
.HasColumnType("text");
b.Property<string>("UserName")
.IsRequired()
.HasColumnType("text")
.UseCollation("my_ci_collation");
b.HasKey("Id");
b.HasIndex("CurrencyId");
b.ToTable("Users");
});
modelBuilder.Entity("MyOffice.Data.Models.Users.UserExternal", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<DateTime>("CreatedOn")
.HasColumnType("timestamp with time zone");
b.Property<string>("Email")
.IsRequired()
.HasColumnType("text")
.UseCollation("my_ci_collation");
b.Property<string>("ExternalId")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Provider")
.IsRequired()
.HasColumnType("text")
.UseCollation("my_ci_collation");
b.Property<Guid>("UserId")
.HasColumnType("uuid");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("UserClaims");
});
modelBuilder.Entity("MyOffice.Data.Models.Accounts.Account", b =>
{
b.HasOne("MyOffice.Data.Models.Currencies.CurrencyGlobal", "CurrencyGlobal")
.WithMany("Accounts")
.HasForeignKey("CurrencyGlobalId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("CurrencyGlobal");
});
modelBuilder.Entity("MyOffice.Data.Models.Accounts.AccountAccess", b =>
{
b.HasOne("MyOffice.Data.Models.Accounts.Account", "Account")
.WithMany("AccessRights")
.HasForeignKey("AccountId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("MyOffice.Data.Models.Users.User", "User")
.WithMany("AccountAccess")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Account");
b.Navigation("User");
});
modelBuilder.Entity("MyOffice.Data.Models.Accounts.AccountAccountCategory", b =>
{
b.HasOne("MyOffice.Data.Models.Accounts.Account", "Account")
.WithMany("Categories")
.HasForeignKey("AccountId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("MyOffice.Data.Models.Accounts.AccountCategory", "Category")
.WithMany("Accounts")
.HasForeignKey("CategoryId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Account");
b.Navigation("Category");
});
modelBuilder.Entity("MyOffice.Data.Models.Accounts.AccountCategory", b =>
{
b.HasOne("MyOffice.Data.Models.Users.User", "User")
.WithMany("AccountCategories")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("MyOffice.Data.Models.Accounts.Motion", b =>
{
b.HasOne("MyOffice.Data.Models.Accounts.Account", "Account")
.WithMany("Motions")
.HasForeignKey("AccountId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("MyOffice.Data.Models.Items.Item", "Item")
.WithMany("Motions")
.HasForeignKey("ItemId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("MyOffice.Data.Models.Users.User", null)
.WithMany("AccountMotions")
.HasForeignKey("UserId");
b.Navigation("Account");
b.Navigation("Item");
});
modelBuilder.Entity("MyOffice.Data.Models.Currencies.Currency", b =>
{
b.HasOne("MyOffice.Data.Models.Currencies.CurrencyGlobal", "CurrencyGlobal")
.WithMany("Currencies")
.HasForeignKey("CurrencyGlobalId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("MyOffice.Data.Models.Currencies.CurrencyRate", "CurrentRate")
.WithMany("Currencies")
.HasForeignKey("CurrentRateId");
b.HasOne("MyOffice.Data.Models.Users.User", "User")
.WithMany("Currencies")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("CurrencyGlobal");
b.Navigation("CurrentRate");
b.Navigation("User");
});
modelBuilder.Entity("MyOffice.Data.Models.Currencies.CurrencyRate", b =>
{
b.HasOne("MyOffice.Data.Models.Currencies.Currency", "Currency")
.WithMany("Rates")
.HasForeignKey("CurrencyId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Currency");
});
modelBuilder.Entity("MyOffice.Data.Models.Items.Item", b =>
{
b.HasOne("MyOffice.Data.Models.Items.ItemCategory", "Category")
.WithMany("Items")
.HasForeignKey("CategoryId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("MyOffice.Data.Models.Items.ItemGlobal", "ItemGlobal")
.WithMany("Items")
.HasForeignKey("ItemGlobalId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Category");
b.Navigation("ItemGlobal");
});
modelBuilder.Entity("MyOffice.Data.Models.Items.ItemCategory", b =>
{
b.HasOne("MyOffice.Data.Models.Users.User", "User")
.WithMany("ItemCategories")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("MyOffice.Data.Models.Users.User", b =>
{
b.HasOne("MyOffice.Data.Models.Currencies.CurrencyGlobal", "Currency")
.WithMany()
.HasForeignKey("CurrencyId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Currency");
});
modelBuilder.Entity("MyOffice.Data.Models.Users.UserExternal", b =>
{
b.HasOne("MyOffice.Data.Models.Users.User", "User")
.WithMany("UserClaims")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("MyOffice.Data.Models.Accounts.Account", b =>
{
b.Navigation("AccessRights");
b.Navigation("Categories");
b.Navigation("Motions");
});
modelBuilder.Entity("MyOffice.Data.Models.Accounts.AccountCategory", b =>
{
b.Navigation("Accounts");
});
modelBuilder.Entity("MyOffice.Data.Models.Currencies.Currency", b =>
{
b.Navigation("Rates");
});
modelBuilder.Entity("MyOffice.Data.Models.Currencies.CurrencyGlobal", b =>
{
b.Navigation("Accounts");
b.Navigation("Currencies");
});
modelBuilder.Entity("MyOffice.Data.Models.Currencies.CurrencyRate", b =>
{
b.Navigation("Currencies");
});
modelBuilder.Entity("MyOffice.Data.Models.Items.Item", b =>
{
b.Navigation("Motions");
});
modelBuilder.Entity("MyOffice.Data.Models.Items.ItemCategory", b =>
{
b.Navigation("Items");
});
modelBuilder.Entity("MyOffice.Data.Models.Items.ItemGlobal", b =>
{
b.Navigation("Items");
});
modelBuilder.Entity("MyOffice.Data.Models.Users.User", b =>
{
b.Navigation("AccountAccess");
b.Navigation("AccountCategories");
b.Navigation("AccountMotions");
b.Navigation("Currencies");
b.Navigation("ItemCategories");
b.Navigation("UserClaims");
});
#pragma warning restore 612, 618
}
}
}
@@ -0,0 +1,29 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace MyOffice.Migrations.Postgres.Migrations
{
/// <inheritdoc />
public partial class AccountType2 : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>(
name: "Type",
table: "AccountAccesses",
type: "text",
nullable: false,
defaultValue: "");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "Type",
table: "AccountAccesses");
}
}
}
@@ -0,0 +1,650 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using MyOffice.DbContext;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
namespace MyOffice.Migrations.Postgres.Migrations
{
[DbContext(typeof(AppDbContext))]
[Migration("20230722052053_AccountOwner")]
partial class AccountOwner
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("Npgsql:CollationDefinition:my_ci_collation", "en-u-ks-primary,en-u-ks-primary,icu,False")
.HasAnnotation("ProductVersion", "7.0.0")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("MyOffice.Data.Models.Accounts.Account", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("CurrencyGlobalId")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.Property<Guid?>("OwnerId")
.HasColumnType("uuid");
b.HasKey("Id");
b.HasIndex("CurrencyGlobalId");
b.HasIndex("OwnerId");
b.ToTable("Accounts");
});
modelBuilder.Entity("MyOffice.Data.Models.Accounts.AccountAccess", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<Guid>("AccountId")
.HasColumnType("uuid");
b.Property<bool>("IsAllowManage")
.HasColumnType("boolean");
b.Property<bool>("IsAllowRead")
.HasColumnType("boolean");
b.Property<bool>("IsAllowWrite")
.HasColumnType("boolean");
b.Property<string>("Type")
.IsRequired()
.HasColumnType("text");
b.Property<Guid>("UserId")
.HasColumnType("uuid");
b.HasKey("Id");
b.HasIndex("AccountId");
b.HasIndex("UserId");
b.ToTable("AccountAccesses");
});
modelBuilder.Entity("MyOffice.Data.Models.Accounts.AccountAccountCategory", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<Guid>("AccountId")
.HasColumnType("uuid");
b.Property<Guid>("CategoryId")
.HasColumnType("uuid");
b.HasKey("Id");
b.HasIndex("AccountId");
b.HasIndex("CategoryId");
b.ToTable("AccountAccountCategories");
});
modelBuilder.Entity("MyOffice.Data.Models.Accounts.AccountCategory", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.Property<Guid>("UserId")
.HasColumnType("uuid");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("AccountCategories");
});
modelBuilder.Entity("MyOffice.Data.Models.Accounts.Motion", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<Guid>("AccountId")
.HasColumnType("uuid");
b.Property<decimal>("AmountMinus")
.HasPrecision(18, 6)
.HasColumnType("numeric(18,6)");
b.Property<decimal>("AmountPlus")
.HasPrecision(18, 6)
.HasColumnType("numeric(18,6)");
b.Property<DateTime>("CreatedOn")
.HasColumnType("timestamp with time zone");
b.Property<DateTime>("DateTime")
.HasColumnType("timestamp with time zone");
b.Property<DateTime?>("DeletedOn")
.HasColumnType("timestamp with time zone");
b.Property<string>("Description")
.HasColumnType("text");
b.Property<int>("ItemId")
.HasColumnType("integer");
b.Property<Guid?>("UserId")
.HasColumnType("uuid");
b.HasKey("Id");
b.HasIndex("AccountId");
b.HasIndex("ItemId");
b.HasIndex("UserId");
b.ToTable("Motions");
});
modelBuilder.Entity("MyOffice.Data.Models.Currencies.Currency", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("CurrencyGlobalId")
.IsRequired()
.HasColumnType("text");
b.Property<int?>("CurrentRateId")
.HasColumnType("integer");
b.Property<bool>("IsPrimary")
.HasColumnType("boolean");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.Property<string>("ShortName")
.IsRequired()
.HasColumnType("text");
b.Property<Guid>("UserId")
.HasColumnType("uuid");
b.HasKey("Id");
b.HasIndex("CurrencyGlobalId");
b.HasIndex("CurrentRateId");
b.HasIndex("UserId");
b.ToTable("Currencies");
});
modelBuilder.Entity("MyOffice.Data.Models.Currencies.CurrencyGlobal", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<int>("DefaultQuantity")
.HasColumnType("integer");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Symbol")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("CurrencyGlobals");
});
modelBuilder.Entity("MyOffice.Data.Models.Currencies.CurrencyRate", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<Guid>("CurrencyId")
.HasColumnType("uuid");
b.Property<DateTime>("DateTime")
.HasColumnType("timestamp with time zone");
b.Property<int>("Quantity")
.HasColumnType("integer");
b.Property<decimal>("Rate")
.HasColumnType("numeric");
b.HasKey("Id");
b.HasIndex("CurrencyId");
b.ToTable("CurrencyRates");
});
modelBuilder.Entity("MyOffice.Data.Models.Items.Item", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<Guid>("CategoryId")
.HasColumnType("uuid");
b.Property<Guid>("ItemGlobalId")
.HasColumnType("uuid");
b.HasKey("Id");
b.HasIndex("CategoryId");
b.HasIndex("ItemGlobalId");
b.ToTable("Items");
});
modelBuilder.Entity("MyOffice.Data.Models.Items.ItemCategory", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<bool>("IsInternal")
.HasColumnType("boolean");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.Property<Guid>("UserId")
.HasColumnType("uuid");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("ItemCategories");
});
modelBuilder.Entity("MyOffice.Data.Models.Items.ItemGlobal", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("ItemGlobals");
});
modelBuilder.Entity("MyOffice.Data.Models.Users.User", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("CurrencyId")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Email")
.IsRequired()
.HasColumnType("text")
.UseCollation("my_ci_collation");
b.Property<string>("FirstName")
.HasColumnType("text");
b.Property<string>("FullName")
.HasColumnType("text");
b.Property<bool>("IsEmailConfirmed")
.HasColumnType("boolean");
b.Property<string>("LastName")
.HasColumnType("text");
b.Property<string>("PasswordHash")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Phone")
.HasColumnType("text");
b.Property<string>("UserName")
.IsRequired()
.HasColumnType("text")
.UseCollation("my_ci_collation");
b.HasKey("Id");
b.HasIndex("CurrencyId");
b.ToTable("Users");
});
modelBuilder.Entity("MyOffice.Data.Models.Users.UserExternal", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<DateTime>("CreatedOn")
.HasColumnType("timestamp with time zone");
b.Property<string>("Email")
.IsRequired()
.HasColumnType("text")
.UseCollation("my_ci_collation");
b.Property<string>("ExternalId")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Provider")
.IsRequired()
.HasColumnType("text")
.UseCollation("my_ci_collation");
b.Property<Guid>("UserId")
.HasColumnType("uuid");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("UserClaims");
});
modelBuilder.Entity("MyOffice.Data.Models.Accounts.Account", b =>
{
b.HasOne("MyOffice.Data.Models.Currencies.CurrencyGlobal", "CurrencyGlobal")
.WithMany("Accounts")
.HasForeignKey("CurrencyGlobalId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("MyOffice.Data.Models.Users.User", "Owner")
.WithMany("Accounts")
.HasForeignKey("OwnerId");
b.Navigation("CurrencyGlobal");
b.Navigation("Owner");
});
modelBuilder.Entity("MyOffice.Data.Models.Accounts.AccountAccess", b =>
{
b.HasOne("MyOffice.Data.Models.Accounts.Account", "Account")
.WithMany("AccessRights")
.HasForeignKey("AccountId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("MyOffice.Data.Models.Users.User", "User")
.WithMany("AccountAccess")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Account");
b.Navigation("User");
});
modelBuilder.Entity("MyOffice.Data.Models.Accounts.AccountAccountCategory", b =>
{
b.HasOne("MyOffice.Data.Models.Accounts.Account", "Account")
.WithMany("Categories")
.HasForeignKey("AccountId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("MyOffice.Data.Models.Accounts.AccountCategory", "Category")
.WithMany("Accounts")
.HasForeignKey("CategoryId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Account");
b.Navigation("Category");
});
modelBuilder.Entity("MyOffice.Data.Models.Accounts.AccountCategory", b =>
{
b.HasOne("MyOffice.Data.Models.Users.User", "User")
.WithMany("AccountCategories")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("MyOffice.Data.Models.Accounts.Motion", b =>
{
b.HasOne("MyOffice.Data.Models.Accounts.Account", "Account")
.WithMany("Motions")
.HasForeignKey("AccountId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("MyOffice.Data.Models.Items.Item", "Item")
.WithMany("Motions")
.HasForeignKey("ItemId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("MyOffice.Data.Models.Users.User", null)
.WithMany("AccountMotions")
.HasForeignKey("UserId");
b.Navigation("Account");
b.Navigation("Item");
});
modelBuilder.Entity("MyOffice.Data.Models.Currencies.Currency", b =>
{
b.HasOne("MyOffice.Data.Models.Currencies.CurrencyGlobal", "CurrencyGlobal")
.WithMany("Currencies")
.HasForeignKey("CurrencyGlobalId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("MyOffice.Data.Models.Currencies.CurrencyRate", "CurrentRate")
.WithMany("Currencies")
.HasForeignKey("CurrentRateId");
b.HasOne("MyOffice.Data.Models.Users.User", "User")
.WithMany("Currencies")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("CurrencyGlobal");
b.Navigation("CurrentRate");
b.Navigation("User");
});
modelBuilder.Entity("MyOffice.Data.Models.Currencies.CurrencyRate", b =>
{
b.HasOne("MyOffice.Data.Models.Currencies.Currency", "Currency")
.WithMany("Rates")
.HasForeignKey("CurrencyId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Currency");
});
modelBuilder.Entity("MyOffice.Data.Models.Items.Item", b =>
{
b.HasOne("MyOffice.Data.Models.Items.ItemCategory", "Category")
.WithMany("Items")
.HasForeignKey("CategoryId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("MyOffice.Data.Models.Items.ItemGlobal", "ItemGlobal")
.WithMany("Items")
.HasForeignKey("ItemGlobalId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Category");
b.Navigation("ItemGlobal");
});
modelBuilder.Entity("MyOffice.Data.Models.Items.ItemCategory", b =>
{
b.HasOne("MyOffice.Data.Models.Users.User", "User")
.WithMany("ItemCategories")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("MyOffice.Data.Models.Users.User", b =>
{
b.HasOne("MyOffice.Data.Models.Currencies.CurrencyGlobal", "Currency")
.WithMany()
.HasForeignKey("CurrencyId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Currency");
});
modelBuilder.Entity("MyOffice.Data.Models.Users.UserExternal", b =>
{
b.HasOne("MyOffice.Data.Models.Users.User", "User")
.WithMany("UserClaims")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("MyOffice.Data.Models.Accounts.Account", b =>
{
b.Navigation("AccessRights");
b.Navigation("Categories");
b.Navigation("Motions");
});
modelBuilder.Entity("MyOffice.Data.Models.Accounts.AccountCategory", b =>
{
b.Navigation("Accounts");
});
modelBuilder.Entity("MyOffice.Data.Models.Currencies.Currency", b =>
{
b.Navigation("Rates");
});
modelBuilder.Entity("MyOffice.Data.Models.Currencies.CurrencyGlobal", b =>
{
b.Navigation("Accounts");
b.Navigation("Currencies");
});
modelBuilder.Entity("MyOffice.Data.Models.Currencies.CurrencyRate", b =>
{
b.Navigation("Currencies");
});
modelBuilder.Entity("MyOffice.Data.Models.Items.Item", b =>
{
b.Navigation("Motions");
});
modelBuilder.Entity("MyOffice.Data.Models.Items.ItemCategory", b =>
{
b.Navigation("Items");
});
modelBuilder.Entity("MyOffice.Data.Models.Items.ItemGlobal", b =>
{
b.Navigation("Items");
});
modelBuilder.Entity("MyOffice.Data.Models.Users.User", b =>
{
b.Navigation("AccountAccess");
b.Navigation("AccountCategories");
b.Navigation("AccountMotions");
b.Navigation("Accounts");
b.Navigation("Currencies");
b.Navigation("ItemCategories");
b.Navigation("UserClaims");
});
#pragma warning restore 612, 618
}
}
}
@@ -0,0 +1,49 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace MyOffice.Migrations.Postgres.Migrations
{
/// <inheritdoc />
public partial class AccountOwner : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<Guid>(
name: "OwnerId",
table: "Accounts",
type: "uuid",
nullable: true);
migrationBuilder.CreateIndex(
name: "IX_Accounts_OwnerId",
table: "Accounts",
column: "OwnerId");
migrationBuilder.AddForeignKey(
name: "FK_Accounts_Users_OwnerId",
table: "Accounts",
column: "OwnerId",
principalTable: "Users",
principalColumn: "Id");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_Accounts_Users_OwnerId",
table: "Accounts");
migrationBuilder.DropIndex(
name: "IX_Accounts_OwnerId",
table: "Accounts");
migrationBuilder.DropColumn(
name: "OwnerId",
table: "Accounts");
}
}
}
@@ -37,10 +37,15 @@ namespace MyOffice.Migrations.Postgres.Migrations
.IsRequired() .IsRequired()
.HasColumnType("text"); .HasColumnType("text");
b.Property<Guid?>("OwnerId")
.HasColumnType("uuid");
b.HasKey("Id"); b.HasKey("Id");
b.HasIndex("CurrencyGlobalId"); b.HasIndex("CurrencyGlobalId");
b.HasIndex("OwnerId");
b.ToTable("Accounts"); b.ToTable("Accounts");
}); });
@@ -64,6 +69,10 @@ namespace MyOffice.Migrations.Postgres.Migrations
b.Property<bool>("IsAllowWrite") b.Property<bool>("IsAllowWrite")
.HasColumnType("boolean"); .HasColumnType("boolean");
b.Property<string>("Type")
.IsRequired()
.HasColumnType("text");
b.Property<Guid>("UserId") b.Property<Guid>("UserId")
.HasColumnType("uuid"); .HasColumnType("uuid");
@@ -401,7 +410,13 @@ namespace MyOffice.Migrations.Postgres.Migrations
.OnDelete(DeleteBehavior.Cascade) .OnDelete(DeleteBehavior.Cascade)
.IsRequired(); .IsRequired();
b.HasOne("MyOffice.Data.Models.Users.User", "Owner")
.WithMany("Accounts")
.HasForeignKey("OwnerId");
b.Navigation("CurrencyGlobal"); b.Navigation("CurrencyGlobal");
b.Navigation("Owner");
}); });
modelBuilder.Entity("MyOffice.Data.Models.Accounts.AccountAccess", b => modelBuilder.Entity("MyOffice.Data.Models.Accounts.AccountAccess", b =>
@@ -618,6 +633,8 @@ namespace MyOffice.Migrations.Postgres.Migrations
b.Navigation("AccountMotions"); b.Navigation("AccountMotions");
b.Navigation("Accounts");
b.Navigation("Currencies"); b.Navigation("Currencies");
b.Navigation("ItemCategories"); b.Navigation("ItemCategories");
+2
View File
@@ -23,6 +23,7 @@ import { AuthCodeFlowConfig, AuthModuleConfig } from '../config.oidc';
import { SubjectExtensions } from './extensions/general.extensions'; import { SubjectExtensions } from './extensions/general.extensions';
import { ExternalLoginConfig } from '../config.external-login'; import { ExternalLoginConfig } from '../config.external-login';
import { AccountCategoryService } from '../services/account.category.service'; import { AccountCategoryService } from '../services/account.category.service';
import { AccountService } from '../services/account.service';
export function storageFactory(): OAuthStorage { export function storageFactory(): OAuthStorage {
return localStorage; return localStorage;
@@ -49,6 +50,7 @@ export function storageFactory(): OAuthStorage {
OidcHelperService, OidcHelperService,
SubjectExtensions, SubjectExtensions,
AccountCategoryService, AccountCategoryService,
AccountService,
], ],
schemas: [ schemas: [
CUSTOM_ELEMENTS_SCHEMA CUSTOM_ELEMENTS_SCHEMA
@@ -5,7 +5,7 @@ import { TranslateService } from '@ngx-translate/core';
providedIn: 'root', providedIn: 'root',
}) })
export class LanguageService { export class LanguageService {
languages: string[] = ['en', 'es', 'de']; languages: string[] = ['en', 'es', 'de', 'ua'];
constructor(public translate: TranslateService) { constructor(public translate: TranslateService) {
let browserLang: string; let browserLang: string;
@@ -16,7 +16,8 @@ export class LanguageService {
} else { } else {
browserLang = translate.getBrowserLang() as string; browserLang = translate.getBrowserLang() as string;
} }
translate.use(browserLang.match(/en|es|de/) ? browserLang : 'en'); console.log(browserLang.match(/en|es|de|ua/));
translate.use(browserLang.match(/en|es|de|ua/) ? browserLang : 'en');
} }
setLanguage(lang: string) { setLanguage(lang: string) {
@@ -1,9 +1,9 @@
// angular
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
import { DecimalPipe } from '@angular/common';
import { DashboardRoutingModule } from './dashboard-routing.module'; // libs
import { Dashboard1Component } from './dashboard1/dashboard1.component';
import { Dashboard2Component } from './dashboard2/dashboard2.component';
import { NgScrollbarModule } from 'ngx-scrollbar'; import { NgScrollbarModule } from 'ngx-scrollbar';
import { NgChartsModule } from 'ng2-charts'; import { NgChartsModule } from 'ng2-charts';
import { MatIconModule } from '@angular/material/icon'; import { MatIconModule } from '@angular/material/icon';
@@ -14,6 +14,12 @@ import { DragDropModule } from '@angular/cdk/drag-drop';
import { MatCheckboxModule } from '@angular/material/checkbox'; import { MatCheckboxModule } from '@angular/material/checkbox';
import { MatTooltipModule } from '@angular/material/tooltip'; import { MatTooltipModule } from '@angular/material/tooltip';
import { NgApexchartsModule } from 'ng-apexcharts'; import { NgApexchartsModule } from 'ng-apexcharts';
import { TranslateModule } from '@ngx-translate/core';
// app
import { DashboardRoutingModule } from './dashboard-routing.module';
import { Dashboard1Component } from './dashboard1/dashboard1.component';
import { Dashboard2Component } from './dashboard2/dashboard2.component';
import { ComponentsModule } from 'src/app/shared/components/components.module'; import { ComponentsModule } from 'src/app/shared/components/components.module';
import { SharedModule } from '../shared/shared.module'; import { SharedModule } from '../shared/shared.module';
@@ -34,7 +40,11 @@ import { SharedModule } from '../shared/shared.module';
MatProgressBarModule, MatProgressBarModule,
ComponentsModule, ComponentsModule,
SharedModule, SharedModule,
TranslateModule,
], ],
providers: [
DecimalPipe,
]
}) })
export class DashboardModule { export class DashboardModule {
} }
@@ -2,7 +2,7 @@
<div class="content-block"> <div class="content-block">
<div class="block-header"> <div class="block-header">
<!-- breadcrumb --> <!-- breadcrumb -->
<app-breadcrumb [title]="'Dashboad 2'" [items]="['Home']" [active_item]="'Dashboad 2'"></app-breadcrumb> <app-breadcrumb [title]="'MENUITEMS.DASHBOARD.LIST.DASHBOARD1'" [items]="['HOME']" [active_item]="'MENUITEMS.DASHBOARD.LIST.DASHBOARD1'"></app-breadcrumb>
</div> </div>
<div class="row"> <div class="row">
@@ -12,7 +12,7 @@
<div class="card-body"> <div class="card-body">
<div class="d-flex justify-content-between"> <div class="d-flex justify-content-between">
<div> <div>
<h5>Balance</h5> <h5>{{'BALANCE' | translate}}</h5>
</div> </div>
<h3 class="text-danger">{{dashboardModel?.balance | number: '0.2-2'}}</h3> <h3 class="text-danger">{{dashboardModel?.balance | number: '0.2-2'}}</h3>
</div> </div>
@@ -25,7 +25,7 @@
<div class="card-body"> <div class="card-body">
<div class="d-flex justify-content-between"> <div class="d-flex justify-content-between">
<div> <div>
<h5>Debit balance</h5> <h5>{{'DEBIT.BALANCE' | translate}}</h5>
<p class="text-muted"></p> <p class="text-muted"></p>
</div> </div>
<h3 class="text-success">{{dashboardModel?.balanceDebit | number: '0.2-2'}}</h3> <h3 class="text-success">{{dashboardModel?.balanceDebit | number: '0.2-2'}}</h3>
@@ -39,7 +39,7 @@
<div class="card-body"> <div class="card-body">
<div class="d-flex justify-content-between"> <div class="d-flex justify-content-between">
<div> <div>
<h5>Credit balance</h5> <h5>{{'CREDIT.BALANCE' | translate}}</h5>
</div> </div>
<h3 class="text-danger">{{dashboardModel?.balanceCredit | number: '0.2-2'}}</h3> <h3 class="text-danger">{{dashboardModel?.balanceCredit | number: '0.2-2'}}</h3>
</div> </div>
@@ -53,7 +53,7 @@
<div class="col-xl-12 col-lg-12 col-md-12 col-sm-12"> <div class="col-xl-12 col-lg-12 col-md-12 col-sm-12">
<div class="card"> <div class="card">
<div class="header"> <div class="header">
<h2>Current rest</h2> <h2>{{'CURRENT.BALANCE' | translate}}</h2>
<button mat-icon-button [matMenuTriggerFor]="menu" class="header-dropdown"> <button mat-icon-button [matMenuTriggerFor]="menu" class="header-dropdown">
<mat-icon>more_vert</mat-icon> <mat-icon>more_vert</mat-icon>
</button> </button>
@@ -65,491 +65,32 @@
</div> </div>
<div class="body"> <div class="body">
<div id="chart"> <div id="chart">
<apx-chart [series]="pieChartOptions.series2!" [chart]="pieChartOptions.chart!" <apx-chart #chart *ngIf="pieChartOptions" class="apex-pie-center"
[labels]="pieChartOptions.labels!" [responsive]="pieChartOptions.responsive!" [series]="pieChartOptions.series2!"
[dataLabels]="pieChartOptions.dataLabels!" [legend]="pieChartOptions.legend!" class="apex-pie-center"> [chart]="pieChartOptions.chart!"
[labels]="pieChartOptions.labels!"
[responsive]="pieChartOptions.responsive!"
[tooltip]="pieChartOptions.tooltip!"
>
</apx-chart> </apx-chart>
</div> </div>
<div class="table-responsive m-t-15"> <div class="table-responsive m-t-15">
<table class="table align-items-center"> <table class="table align-items-center">
<tbody> <tbody>
<tr> <tr *ngFor="let item of top10Balance">
<td><i class="fa fa-circle col-cyan msr-2"></i> India</td> <td><i class="fa fa-circle col-cyan msr-2"></i> {{item.name}}</td>
<td>23</td> <td class="col-green" style="text-align: right;">{{item.balance | number: '1.2'}} ({{item.currencyShortName}})</td>
<td class="col-green">+32%</td> <td class="col-green" style="text-align: right;">{{item.balanceAtRate | number: '1.2'}}</td>
</tr> </tr>
<tr> <tr>
<td><i class="fa fa-circle col-blue msr-2"></i>USA</td> <td><i class="fa fa-circle col-green msr-2"></i> {{'OTHER' | translate}}</td>
<td>32</td> <td></td>
<td class="col-green">+12%</td> <td class="col-green" style="text-align: right;">{{top10BalanceOther | number: '1.2'}}</td>
</tr> </tr>
<tr> <tr>
<td><i class="fa fa-circle col-orange msr-2"></i>Shrilanka</td> <td style="text-align: right; font-size: 16px;"><i class="fa fa-circle col-orange msr-2"></i> {{'TOTAL' | translate}}</td>
<td>12</td> <td></td>
<td class="col-orange">-12%</td> <td class="col-green" style="text-align: right; font-size: 16px;">{{top10BalanceTotal | number: '1.2'}}</td>
</tr>
<tr>
<td><i class="fa fa-circle col-green msr-2"></i>Australia</td>
<td>32</td>
<td class="col-green">+3%</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
<div class="row clearfix">
<div class="col-xs-12 col-sm-12 col-md-4 col-lg-4">
<div class="card">
<div class="header">
<h2>Notice Board</h2>
<button mat-icon-button [matMenuTriggerFor]="menu" class="header-dropdown">
<mat-icon>more_vert</mat-icon>
</button>
<mat-menu #menu="matMenu">
<button mat-menu-item>Action</button>
<button mat-menu-item>Another action</button>
<button mat-menu-item>Something else here</button>
</mat-menu>
</div>
<div class="body">
<ng-scrollbar style="height: 380px" visibility="hover">
<div class="recent-comment">
<div class="notice-board">
<div class="table-img">
<img class="notice-object" src="assets/images/user/user6.jpg" alt="...">
</div>
<div class="notice-body">
<h6 class="notice-heading col-green">Airi Satou</h6>
<p>Lorem ipsum dolor sit amet, id quo eruditi eloquentiam.</p>
<small class="text-muted">7 hours ago</small>
</div>
</div>
<div class="notice-board">
<div class="table-img">
<img class="notice-object" src="assets/images/user/user4.jpg" alt="...">
</div>
<div class="notice-body">
<h6 class="notice-heading color-primary col-indigo">Sarah Smith</h6>
<p>Lorem ipsum dolor sit amet, id quo eruditi eloquentiam.</p>
<p class="comment-date">1 hour ago</p>
</div>
</div>
<div class="notice-board">
<div class="table-img">
<img class="notice-object" src="assets/images/user/user3.jpg" alt="...">
</div>
<div class="notice-body">
<h6 class="notice-heading color-danger col-cyan">Cara Stevens</h6>
<p>Lorem ipsum dolor sit amet, id quo eruditi eloquentiam.</p>
<div class="comment-date">Yesterday</div>
</div>
</div>
<div class="notice-board no-border">
<div class="table-img">
<img class="notice-object" src="assets/images/user/user7.jpg" alt="...">
</div>
<div class="notice-body">
<h6 class="notice-heading color-info col-orange">Ashton Cox</h6>
<p>Lorem ipsum dolor sit amet, id quo eruditi eloquentiam.</p>
<div class="comment-date">Yesterday</div>
</div>
</div>
<div class="notice-board">
<div class="table-img">
<img class="notice-object" src="assets/images/user/user9.jpg" alt="...">
</div>
<div class="notice-body">
<h6 class="notice-heading color-primary col-red">Mark Hay</h6>
<p>Lorem ipsum dolor sit amet, id quo eruditi eloquentiam.</p>
<p class="comment-date">1 hour ago</p>
</div>
</div>
<div class="notice-board">
<div class="table-img">
<img class="notice-object" src="assets/images/user/user8.jpg" alt="...">
</div>
<div class="notice-body">
<h6 class="notice-heading color-primary col-green">Jay Pandya</h6>
<p>Lorem ipsum dolor sit amet, id quo eruditi eloquentiam.</p>
<p class="comment-date">3 hour ago</p>
</div>
</div>
</div>
</ng-scrollbar>
</div>
</div>
</div>
<div class="col-xl-4 col-lg-4 col-md-12 col-sm-12">
<div class="card">
<div class="header">
<h2>Project Status</h2>
<button mat-icon-button [matMenuTriggerFor]="menu" class="header-dropdown">
<mat-icon>more_vert</mat-icon>
</button>
<mat-menu #menu="matMenu">
<button mat-menu-item>Action</button>
<button mat-menu-item>Another action</button>
<button mat-menu-item>Something else here</button>
</mat-menu>
</div>
<ng-scrollbar style="height: 410px" visibility="hover">
<div class="tableBody">
<div class="table-responsive">
<table class="table table-hover">
<thead>
<tr>
<th>Project Name</th>
<th>Progress</th>
<th>Duration</th>
</tr>
</thead>
<tbody>
<tr>
<td>Project A</td>
<td>
30%
<mat-progress-bar mode="determinate" value="30" color="warn" class="progress-round">
</mat-progress-bar>
</td>
<td>2 Months</td>
</tr>
<tr>
<td>Project B</td>
<td>
55%
<mat-progress-bar mode="determinate" class="progress-round" value="55">
</mat-progress-bar>
</td>
<td>3 Months</td>
</tr>
<tr>
<td>Project C</td>
<td>
67%
<mat-progress-bar mode="determinate" class="progress-round orange-progress" value="67">
</mat-progress-bar>
</td>
<td>1 Months</td>
</tr>
<tr>
<td>Project D</td>
<td>
70%
<mat-progress-bar mode="determinate" class="progress-round green-progress" value="70">
</mat-progress-bar>
</td>
<td>2 Months</td>
</tr>
<tr>
<td>Project E</td>
<td>
24%
<mat-progress-bar mode="determinate" value="24" class="progress-round l-red-progress">
</mat-progress-bar>
</td>
<td>3 Months</td>
</tr>
<tr>
<td>Project F</td>
<td>
77%
<mat-progress-bar mode="determinate" class="progress-round l-green-progress" value="77">
</mat-progress-bar>
</td>
<td>4 Months</td>
</tr>
<tr>
<td>Project G</td>
<td>
41%
<mat-progress-bar mode="determinate" value="41" class="progress-round l-cyan-progress">
</mat-progress-bar>
</td>
<td>2 Months</td>
</tr>
<tr>
<td>Project H</td>
<td>
41%
<mat-progress-bar mode="determinate" value="41" class="progress-round l-orange-progress">
</mat-progress-bar>
</td>
<td>2 Months</td>
</tr>
</tbody>
</table>
</div>
</div>
</ng-scrollbar>
</div>
</div>
<div class="col-xs-12 col-sm-12 col-md-4 col-lg-4">
<div class="card">
<div class="header">
<h2>Earning Source</h2>
<button mat-icon-button [matMenuTriggerFor]="menu" class="header-dropdown">
<mat-icon>more_vert</mat-icon>
</button>
<mat-menu #menu="matMenu">
<button mat-menu-item>Action</button>
<button mat-menu-item>Another action</button>
<button mat-menu-item>Something else here</button>
</mat-menu>
</div>
<div class="body">
<div class="totalEarning">
<h2>$90,808</h2>
</div>
<div class="tab-pane body" id="skills">
<ul class="list-unstyled">
<li>
<div class="mb-2">
<span class="progress-label">envato.com</span>
<span class="float-end progress-percent label label-info m-b-5">17%</span>
</div>
<div class="progress skill-progress m-b-20 w-100">
<div class="progress-bar l-bg-green width-per-45" role="progressbar" aria-valuenow="45"
aria-valuemin="0" aria-valuemax="100">
</div>
</div>
</li>
<li>
<div class="mb-2">
<span class="float-start progress-label">google.com</span>
<span class="float-end progress-percent label label-danger m-b-5">27%</span>
</div>
<div class="progress skill-progress m-b-20 w-100">
<div class="progress-bar l-bg-purple width-per-27" role="progressbar" aria-valuenow="27"
aria-valuemin="0" aria-valuemax="100">
</div>
</div>
</li>
<li>
<div class="mb-2">
<span class="float-start progress-label">yahoo.com</span>
<span class="float-end progress-percent label label-primary m-b-5">25%</span>
</div>
<div class="progress skill-progress m-b-20 w-100">
<div class="progress-bar l-bg-orange width-per-25" role="progressbar" aria-valuenow="25"
aria-valuemin="0" aria-valuemax="100">
</div>
</div>
</li>
<li>
<div class="mb-2">
<span class="float-start progress-label">store</span>
<span class="float-end progress-percent label label-success m-b-5">18%</span>
</div>
<div class="progress skill-progress m-b-20 w-100">
<div class="progress-bar l-bg-cyan width-per-18" role="progressbar" aria-valuenow="18"
aria-valuemin="0" aria-valuemax="100">
</div>
</div>
</li>
<li>
<div class="mb-2">
<span class="float-start progress-label">Others</span>
<span class="float-end progress-percent label label-warning m-b-5">13%</span>
</div>
<div class="progress skill-progress m-b-20 w-100">
<div class="progress-bar l-bg-red width-per-13" role="progressbar" aria-valuenow="13"
aria-valuemin="0" aria-valuemax="100">
</div>
</div>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
<div class="row clearfix">
<div class="col-xs-12 col-sm-12 col-md-12 col-lg-12">
<div class="card">
<div class="header">
<h2>Recent Orders</h2>
<button mat-icon-button [matMenuTriggerFor]="menu" class="header-dropdown">
<mat-icon>more_vert</mat-icon>
</button>
<mat-menu #menu="matMenu">
<button mat-menu-item>Action</button>
<button mat-menu-item>Another action</button>
<button mat-menu-item>Something else here</button>
</mat-menu>
</div>
<div class="tableBody">
<div class="table-responsive">
<table class="table display product-overview mb-30" id="support_table">
<thead>
<tr>
<th>Order ID</th>
<th>Customer Name</th>
<th>Item</th>
<th>Order Date</th>
<th>Quantity</th>
<th>Payment</th>
<th>Status</th>
<th>Invoice</th>
<th>Details</th>
</tr>
</thead>
<tbody>
<tr>
<td>ID7865</td>
<td>
<img src="assets/images/user/user1.jpg" alt="" class="tbl-user-img-small">Jens
Brincker
</td>
<td>iPhone X</td>
<td>22/05/2021</td>
<td>2</td>
<td>Credit Card</td>
<td>
<div class="badge badge-solid-green">Paid</div>
</td>
<td>
<i class="far fa-file-pdf tbl-pdf"></i>
</td>
<td>
<button mat-stroked-button color="primary">Details</button>
</td>
</tr>
<tr>
<td>ID9357</td>
<td>
<img src="assets/images/user/user2.jpg" alt="" class="tbl-user-img-small">Mark Harry
</td>
<td> Pixel 2</td>
<td>12/06/2021</td>
<td>1</td>
<td>COD</td>
<td>
<div class="badge badge-solid-orange">Unpaid</div>
</td>
<td>
<i class="far fa-file-pdf tbl-pdf"></i>
</td>
<td>
<button mat-stroked-button color="primary">Details</button>
</td>
</tr>
<tr>
<td>ID3987</td>
<td>
<img src="assets/images/user/user3.jpg" alt="" class="tbl-user-img-small">Anthony
Davie
</td>
<td>OnePlus</td>
<td>02/02/2021</td>
<td>5</td>
<td>Debit Card</td>
<td>
<div class="badge badge-solid-blue">Pending</div>
</td>
<td>
<i class="far fa-file-pdf tbl-pdf"></i>
</td>
<td>
<button mat-stroked-button color="primary">Details</button>
</td>
</tr>
<tr>
<td>ID2483</td>
<td>
<img src="assets/images/user/user4.jpg" alt="" class="tbl-user-img-small">David Perry
</td>
<td>Moto Z2</td>
<td>10/01/2021</td>
<td>2</td>
<td>Credit Card</td>
<td>
<div class="badge badge-solid-green">Paid</div>
</td>
<td>
<i class="far fa-file-pdf tbl-pdf"></i>
</td>
<td>
<button mat-stroked-button color="primary">Details</button>
</td>
</tr>
<tr>
<td>ID2986</td>
<td>
<img src="assets/images/user/user5.jpg" alt="" class="tbl-user-img-small">John Doe
</td>
<td>Samsung F62</td>
<td>20/05/2021</td>
<td>3</td>
<td>Net Banking</td>
<td>
<div class="badge badge-solid-orange">Unpaid</div>
</td>
<td>
<i class="far fa-file-pdf tbl-pdf"></i>
</td>
<td>
<button mat-stroked-button color="primary">Details</button>
</td>
</tr>
<tr>
<td>ID1267</td>
<td>
<img src="assets/images/user/user6.jpg" alt="" class="tbl-user-img-small">Sarah Smith
</td>
<td>iPhone 12</td>
<td>10/07/2021</td>
<td>1</td>
<td>COD</td>
<td>
<div class="badge badge-solid-green">Paid</div>
</td>
<td>
<i class="far fa-file-pdf tbl-pdf"></i>
</td>
<td>
<button mat-stroked-button color="primary">Details</button>
</td>
</tr>
<tr>
<td>ID3398</td>
<td>
<img src="assets/images/user/user7.jpg" alt="" class="tbl-user-img-small">Cara Stevens
</td>
<td>Moto Gs5</td>
<td>11/04/2021</td>
<td>2</td>
<td>UPI Payment</td>
<td>
<div class="badge badge-solid-blue">Pending</div>
</td>
<td>
<i class="far fa-file-pdf tbl-pdf"></i>
</td>
<td>
<button mat-stroked-button color="primary">Details</button>
</td>
</tr>
<tr>
<td>ID9965</td>
<td>
<img src="assets/images/user/user8.jpg" alt="" class="tbl-user-img-small">Ashton Cox
</td>
<td>Pixel 2</td>
<td>14/05/2021</td>
<td>4</td>
<td>Credit Card</td>
<td>
<div class="badge badge-solid-green">Paid</div>
</td>
<td>
<i class="far fa-file-pdf tbl-pdf"></i>
</td>
<td>
<button mat-stroked-button color="primary">Details</button>
</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
@@ -1,6 +1,9 @@
// angular // angular
import { Component, OnInit } from '@angular/core'; import { Component } from '@angular/core';
import { OnInit } from '@angular/core';
import { ViewChild } from '@angular/core';
import { HttpClient } from '@angular/common/http'; import { HttpClient } from '@angular/common/http';
import { DecimalPipe } from '@angular/common';
// libs // libs
import { import {
@@ -19,10 +22,12 @@ import {
ApexResponsive, ApexResponsive,
ApexNonAxisChartSeries, ApexNonAxisChartSeries,
} from 'ng-apexcharts'; } from 'ng-apexcharts';
import { ChartComponent } from "ng-apexcharts";
// app // app
import { ApiRoutes } from '../../api-routes'; import { ApiRoutes } from '../../api-routes';
import { DashboardModel } from '../../model/dashboard.model'; import { DashboardModel } from '../../model/dashboard.model';
import { DashboardRestModel } from '../../model/dashboard.model';
export type ChartOptions = { export type ChartOptions = {
series: ApexAxisChartSeries; series: ApexAxisChartSeries;
@@ -49,24 +54,48 @@ export type ChartOptions = {
styleUrls: ['./dashboard2.component.scss'], styleUrls: ['./dashboard2.component.scss'],
}) })
export class Dashboard2Component implements OnInit { export class Dashboard2Component implements OnInit {
lineChartOptions!: Partial<ChartOptions>;
pieChartOptions!: Partial<ChartOptions>; @ViewChild("chart") chart!: ChartComponent;
public pieChartOptions!: Partial<ChartOptions>;
top10Balance?: DashboardRestModel[];
top10BalanceOther?: number;
top10BalanceTotal?: number;
dashboardModel?: DashboardModel; dashboardModel?: DashboardModel;
// color: ["#3FA7DC", "#F6A025", "#9BC311"], // color: ["#3FA7DC", "#F6A025", "#9BC311"],
constructor(private httpClient: HttpClient) { constructor(
private httpClient: HttpClient,
private _decimalPipe: DecimalPipe
) {
} }
ngOnInit() { ngOnInit() {
this.chart1();
this.chart2();
this.httpClient this.httpClient
.get<DashboardModel>(ApiRoutes.Dashboard) .get<DashboardModel>(ApiRoutes.Dashboard)
.subscribe(data => { .subscribe(data => {
data.incomeChange = this.calcChanges(data.incomeLast, data.incomePrevious); data.incomeChange = this.calcChanges(data.incomeLast, data.incomePrevious);
data.outcomeChange = this.calcChanges(data.outcomeLast, data.outcomePrevious); data.outcomeChange = this.calcChanges(data.outcomeLast, data.outcomePrevious);
var labels = [];
var series2: number[] = [];
for (var i = 0; i < data.balanceRests.length; i++) {
let item = data.balanceRests[i];
labels.push(item.name);
series2.push(item.balanceAtRate);
}
this.balanceChart(labels, series2);
this.top10Balance = data.balanceRests
.filter(x => x.balanceAtRate > 0)
.sort(x => x.balanceAtRate)
.slice(0, 10);
this.top10BalanceTotal = data.balanceRests.reduce((sum, current) => sum + current.balanceAtRate, 0);
this.top10BalanceOther = this.top10Balance.reduce((sum, current) => sum + current.balanceAtRate, 0);
this.top10BalanceOther = this.top10BalanceTotal - this.top10BalanceOther;
this.dashboardModel = data; this.dashboardModel = data;
}); });
} }
@@ -82,101 +111,41 @@ export class Dashboard2Component implements OnInit {
return 0; return 0;
} }
private chart1() { private balanceChart(labels: string[], series2: number[]) {
this.lineChartOptions = { var self = this;
series: [
{
name: 'Product 1',
data: [70, 200, 80, 180, 170, 105, 210],
},
{
name: 'Product 2',
data: [80, 250, 30, 120, 260, 100, 180],
},
{
name: 'Product 3',
data: [85, 130, 85, 225, 80, 190, 120],
},
],
chart: {
height: 350,
type: 'line',
foreColor: '#9aa0ac',
dropShadow: {
enabled: true,
color: '#000',
top: 18,
left: 7,
blur: 10,
opacity: 0.2,
},
toolbar: {
show: false,
},
},
colors: ['#00E396', '#775DD0', '#FEB019'],
stroke: {
curve: 'smooth',
},
grid: {
show: true,
borderColor: '#9aa0ac',
strokeDashArray: 1,
},
markers: {
size: 3,
},
xaxis: {
categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul'],
title: {
text: 'Month',
},
},
yaxis: {
// opposite: true,
title: {
text: 'Sales',
},
},
legend: {
position: 'top',
horizontalAlign: 'right',
floating: true,
offsetY: -25,
offsetX: -5,
},
tooltip: {
theme: 'dark',
marker: {
show: true,
},
x: {
show: true,
},
},
};
}
private chart2() {
this.pieChartOptions = { this.pieChartOptions = {
series2: [44, 55, 13, 43, 22], labels: labels,
series2: series2,
chart: { chart: {
type: 'donut', type: 'donut',
width: 225, width: 600,
height: 600,
}, },
legend: { legend: {
show: false, show: true,
}, },
dataLabels: { dataLabels: {
enabled: false, enabled: false,
}, },
labels: ['Science', 'Mathes', 'Economics', 'History', 'Music'], responsive: [{
responsive: [ breakpoint: 480,
{ options: {
breakpoint: 480, legend: {
options: {}, position: 'bottom'
}
}, },
], }],
tooltip: {
x: {
show: false,
},
y: {
formatter: function (value, series) {
return self._decimalPipe.transform(value, '1.2-2') || "";
}
}
}
}; };
} }
} }
@@ -67,6 +67,7 @@ export class HeaderComponent extends UnsubscribeOnDestroyAdapter implements OnIn
{ text: 'English', flag: 'assets/images/flags/us.jpg', lang: 'en' }, { text: 'English', flag: 'assets/images/flags/us.jpg', lang: 'en' },
{ text: 'Spanish', flag: 'assets/images/flags/spain.jpg', lang: 'es' }, { text: 'Spanish', flag: 'assets/images/flags/spain.jpg', lang: 'es' },
{ text: 'German', flag: 'assets/images/flags/germany.jpg', lang: 'de' }, { text: 'German', flag: 'assets/images/flags/germany.jpg', lang: 'de' },
{ text: 'Ukraine', flag: 'assets/images/flags/ukraine.png', lang: 'ua' },
]; ];
notifications: Notifications[] = [ notifications: Notifications[] = [
{ {
@@ -22,20 +22,9 @@ export const ROUTES: RouteInfo[] = [
badge: '', badge: '',
badgeClass: '', badgeClass: '',
submenu: [ submenu: [
{
path: 'dashboard/dashboard1',
title: 'MENUITEMS.DASHBOARD.LIST.DASHBOARD1',
iconType: '',
icon: '',
class: 'ml-menu',
groupTitle: false,
badge: '',
badgeClass: '',
submenu: [],
},
{ {
path: 'dashboard/dashboard2', path: 'dashboard/dashboard2',
title: 'MENUITEMS.DASHBOARD.LIST.DASHBOARD2', title: 'MENUITEMS.DASHBOARD.LIST.DASHBOARD1',
iconType: '', iconType: '',
icon: '', icon: '',
class: 'ml-menu', class: 'ml-menu',
@@ -48,66 +37,10 @@ export const ROUTES: RouteInfo[] = [
}, },
// Common Modules // Common Modules
{
path: '',
title: 'Authentication',
iconType: 'feather',
icon: 'user-check',
class: 'menu-toggle',
groupTitle: false,
badge: '',
badgeClass: '',
submenu: [
{
path: '/authentication/forgot-password',
title: 'Forgot Password',
iconType: '',
icon: '',
class: 'ml-menu',
groupTitle: false,
badge: '',
badgeClass: '',
submenu: [],
},
{
path: '/authentication/locked',
title: 'Locked',
iconType: '',
icon: '',
class: 'ml-menu',
groupTitle: false,
badge: '',
badgeClass: '',
submenu: [],
},
{
path: '/authentication/page404',
title: '404 - Not Found',
iconType: '',
icon: '',
class: 'ml-menu',
groupTitle: false,
badge: '',
badgeClass: '',
submenu: [],
},
{
path: '/authentication/page500',
title: '500 - Server Error',
iconType: '',
icon: '',
class: 'ml-menu',
groupTitle: false,
badge: '',
badgeClass: '',
submenu: [],
},
],
},
{ {
id: 'accounts', id: 'accounts',
path: '', path: '',
title: 'Accounts', title: 'MENUITEMS.ACCOUNTS.TEXT',
iconType: 'feather', iconType: 'feather',
icon: 'chevrons-down', icon: 'chevrons-down',
class: 'menu-toggle', class: 'menu-toggle',
@@ -115,79 +48,11 @@ export const ROUTES: RouteInfo[] = [
badge: '', badge: '',
badgeClass: '', badgeClass: '',
submenu: [ submenu: [
/*{
path: '/multilevel/first1',
title: 'First',
iconType: '',
icon: '',
class: 'ml-menu',
groupTitle: false,
badge: '',
badgeClass: '',
submenu: [],
},
{
path: '/',
title: 'Second',
iconType: '',
icon: '',
class: 'ml-sub-menu',
groupTitle: false,
badge: '',
badgeClass: '',
submenu: [
{
path: '/multilevel/secondlevel/second1',
title: 'Second 1',
iconType: '',
icon: '',
class: 'ml-menu2',
groupTitle: false,
badge: '',
badgeClass: '',
submenu: [],
},
{
path: '/',
title: 'Second 2',
iconType: '',
icon: '',
class: 'ml-sub-menu2',
groupTitle: false,
badge: '',
badgeClass: '',
submenu: [
{
path: '/multilevel/thirdlevel/third1',
title: 'third 1',
iconType: '',
icon: '',
class: 'ml-menu3',
groupTitle: false,
badge: '',
badgeClass: '',
submenu: [],
},
],
},
],
},
{
path: '/multilevel/first3',
title: 'Third',
iconType: '',
icon: '',
class: 'ml-menu',
groupTitle: false,
badge: '',
badgeClass: '',
submenu: [],
},*/
], ],
}, },
{ {
path: '', path: '',
title: 'Settings', title: 'MENUITEMS.SETTINGS.TEXT',
iconType: 'feather', iconType: 'feather',
icon: 'settings', icon: 'settings',
class: 'menu-toggle', class: 'menu-toggle',
@@ -197,7 +62,7 @@ export const ROUTES: RouteInfo[] = [
submenu: [ submenu: [
{ {
path: '/settings/currencies', path: '/settings/currencies',
title: 'Currencies', title: 'MENUITEMS.SETTINGS.LIST.CURRENCIES',
iconType: '', iconType: '',
icon: '', icon: '',
class: 'ml-menu', class: 'ml-menu',
@@ -208,7 +73,7 @@ export const ROUTES: RouteInfo[] = [
}, },
{ {
path: '/settings/account-categories', path: '/settings/account-categories',
title: 'Account categories', title: 'MENUITEMS.SETTINGS.LIST.ACCOUNTCATEGORIES',
iconType: '', iconType: '',
icon: '', icon: '',
class: 'ml-menu', class: 'ml-menu',
@@ -219,7 +84,7 @@ export const ROUTES: RouteInfo[] = [
}, },
{ {
path: '/settings/accounts', path: '/settings/accounts',
title: 'Accounts', title: 'MENUITEMS.SETTINGS.LIST.ACCOUNTS',
iconType: '', iconType: '',
icon: '', icon: '',
class: 'ml-menu', class: 'ml-menu',
@@ -230,7 +95,7 @@ export const ROUTES: RouteInfo[] = [
}, },
{ {
path: '/settings/item-categories', path: '/settings/item-categories',
title: 'Item categories', title: '',
iconType: '', iconType: '',
icon: '', icon: '',
class: 'ml-menu', class: 'ml-menu',
@@ -241,7 +106,7 @@ export const ROUTES: RouteInfo[] = [
}, },
{ {
path: '/settings/items', path: '/settings/items',
title: 'Items', title: 'MENUITEMS.SETTINGS.LIST.ITEMS',
iconType: '', iconType: '',
icon: '', icon: '',
class: 'ml-menu', class: 'ml-menu',
@@ -6,6 +6,8 @@ export interface AccountModel {
name?: string, name?: string,
currencyId?: string, currencyId?: string,
currencyName?: string, currencyName?: string,
type?: string,
allowDelete: boolean,
categories?: AccountCategoryModel[], categories?: AccountCategoryModel[],
accessRights?: AccountAccessRightModel[], accessRights?: AccountAccessRightModel[],
} }
@@ -5,7 +5,21 @@ export interface DashboardModel {
outcomeLast: number; outcomeLast: number;
outcomePrevious: number; outcomePrevious: number;
outcomeChange: number; outcomeChange: number;
balance: number; balance: number;
balanceDebit: number; balanceDebit: number;
balanceCredit: number; balanceCredit: number;
balanceRests: DashboardRestModel[];
}
export interface DashboardRestModel {
id: string;
name: string;
currencyName: string;
currencyShortName: string;
balance: number;
currencyRate: number;
currencyQuantity: number;
balanceAtRate: number;
} }
@@ -30,11 +30,12 @@
<tr *ngFor="let account of accountInCategory(category)"> <tr *ngFor="let account of accountInCategory(category)">
<td>{{account.name}}</td> <td>{{account.name}}</td>
<td>{{account.currencyId}}</td> <td>{{account.currencyId}}</td>
<td>{{account.type}}</td>
<td> <td>
<button class="btn-space " (click)="edit(account)" mat-raised-button color="primary"> <button class="btn-space" (click)="edit(account)" mat-raised-button color="primary">
Edit Edit
</button> </button>
<button class="btn-space " (click)="remove(account)" mat-raised-button color="primary"> <button class="btn-space" *ngIf="account.allowDelete" (click)="remove(account)" mat-raised-button color="primary">
Delete Delete
</button> </button>
</td> </td>
@@ -48,11 +49,12 @@
<tr *ngFor="let account of accountInCategory()"> <tr *ngFor="let account of accountInCategory()">
<td>{{account.name}}</td> <td>{{account.name}}</td>
<td>{{account.currencyId}}</td> <td>{{account.currencyId}}</td>
<td>{{account.type}}</td>
<td> <td>
<button class="btn-space " (click)="edit(account)" mat-raised-button color="primary"> <button class="btn-space" (click)="edit(account)" mat-raised-button color="primary">
Edit Edit
</button> </button>
<button class="btn-space " (click)="remove(account)" mat-raised-button color="primary"> <button class="btn-space" *ngIf="account.allowDelete" (click)="remove(account)" mat-raised-button color="primary">
Delete Delete
</button> </button>
</td> </td>
@@ -67,10 +69,10 @@
<td>{{account.name}}</td> <td>{{account.name}}</td>
<td>{{account.currencyId}}</td> <td>{{account.currencyId}}</td>
<td> <td>
<button class="btn-space " (click)="edit(account)" mat-raised-button color="primary"> <button class="btn-space" (click)="edit(account)" mat-raised-button color="primary">
Edit Edit
</button> </button>
<button class="btn-space " (click)="remove(account)" mat-raised-button color="primary"> <button class="btn-space" *ngIf="account.allowDelete" (click)="remove(account)" mat-raised-button color="primary">
Delete Delete
</button> </button>
</td> </td>
@@ -81,15 +81,15 @@ export class SettingsAccountComponent {
}); });
} }
public remove(category: AccountModel) { public remove(account: AccountModel) {
/*Swal.fire({ Swal.fire({
title: 'Remove account category ' + category.name, title: 'Remove account ' + account.name,
showCancelButton: true, showCancelButton: true,
confirmButtonText: 'Add', confirmButtonText: 'Delete',
showLoaderOnConfirm: true, showLoaderOnConfirm: true,
preConfirm: (name) => { preConfirm: (name) => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this.httpClient.delete(ApiRoutes.SettingsAccountCategory.replace(':id', category.id!)) this.httpClient.delete(ApiRoutes.SettingsAccount.replace(':id', account.id!))
.subscribe(data => { .subscribe(data => {
resolve(data); resolve(data);
}, error => { }, error => {
@@ -103,7 +103,7 @@ export class SettingsAccountComponent {
}, },
allowOutsideClick: () => !Swal.isLoading(), allowOutsideClick: () => !Swal.isLoading(),
}).then((result) => { }).then((result) => {
this.load(); this.loadAccounts();
});*/ });
} }
} }
@@ -4,6 +4,22 @@
</h2> </h2>
<div mat-dialog-content> <div mat-dialog-content>
<form [formGroup]="editForm!" (ngSubmit)="onSubmitClick()"> <form [formGroup]="editForm!" (ngSubmit)="onSubmitClick()">
<div class="row">
<div class="col-md-12">
<div class="text-inside">
<mat-form-field class="example-full-width">
<mat-label>Type</mat-label>
<mat-select formControlName="type">
<mat-option *ngFor="let type of types | keyvalue" [value]="type.key">
{{type.key}} ({{type.value}})
</mat-option>
</mat-select>
</mat-form-field>
</div>
</div>
</div>
<div class="row"> <div class="row">
<div class="col-md-6"> <div class="col-md-6">
<div class="text-inside"> <div class="text-inside">
@@ -19,6 +19,7 @@ import { CurrencyModel } from '../../../model/currency.model';
import { AccountCategoryService } from '../../../services/account.category.service'; import { AccountCategoryService } from '../../../services/account.category.service';
import { AccountCategoryModel } from '../../../model/account.category.model'; import { AccountCategoryModel } from '../../../model/account.category.model';
import { AuthService } from '../../../core/service/auth.service'; import { AuthService } from '../../../core/service/auth.service';
import { AccountService } from '../../../services/account.service';
@Component({ @Component({
templateUrl: './add.account.component.html', templateUrl: './add.account.component.html',
@@ -30,6 +31,7 @@ export class SettingsAccountAddComponent {
public currencies?: CurrencyModel[]; public currencies?: CurrencyModel[];
public categories?: AccountCategoryModel[]; public categories?: AccountCategoryModel[];
public username: string; public username: string;
public types = new Map<string, string>();
constructor( constructor(
private fb: UntypedFormBuilder, private fb: UntypedFormBuilder,
@@ -38,9 +40,11 @@ export class SettingsAccountAddComponent {
private currencyService: CurrencyService, private currencyService: CurrencyService,
private accountCategoryService: AccountCategoryService, private accountCategoryService: AccountCategoryService,
private authService: AuthService, private authService: AuthService,
private accountService: AccountService,
@Inject(MAT_DIALOG_DATA) public account: AccountModel @Inject(MAT_DIALOG_DATA) public account: AccountModel
) { ) {
this.username = authService.currentUserValue.userName; this.username = authService.currentUserValue.userName;
this.types = this.accountService.getTypes();
} }
ngOnInit(): void { ngOnInit(): void {
@@ -60,6 +64,9 @@ export class SettingsAccountAddComponent {
'', '',
[Validators.required], [Validators.required],
], ],
type: [
this.account.type
]
}); });
this.currencyService this.currencyService
@@ -4,6 +4,22 @@
</h2> </h2>
<div mat-dialog-content> <div mat-dialog-content>
<form [formGroup]="editForm!" (ngSubmit)="onSubmitClick()"> <form [formGroup]="editForm!" (ngSubmit)="onSubmitClick()">
<div class="row">
<div class="col-md-12">
<div class="text-inside">
<mat-form-field class="example-full-width">
<mat-label>Type</mat-label>
<mat-select formControlName="type">
<mat-option *ngFor="let type of types | keyvalue" [value]="type.key">
{{type.key}} ({{type.value}})
</mat-option>
</mat-select>
</mat-form-field>
</div>
</div>
</div>
<div class="row"> <div class="row">
<div class="col-md-6"> <div class="col-md-6">
<div class="text-inside"> <div class="text-inside">
@@ -26,7 +42,9 @@
</div> </div>
</div> </div>
</div> </div>
<div class="row"> <div class="row">
<div class="col-md-6"> <div class="col-md-6">
<label>Categories</label> <label>Categories</label>
<div class="col-md-12"> <div class="col-md-12">
@@ -42,20 +60,21 @@
</div> </div>
</div> </div>
<div class="col-md-12"> <div class="col-md-12">
<table class="table"> <table class="table" style="table-layout: fixed;">
<tbody> <tbody>
<tr *ngFor="let category of account.categories"> <tr *ngFor="let category of account.categories">
<td>{{category.name}}</td> <td style="width: 100%;">{{category.name}}</td>
<td> <td style="width: 100px;">
<button class="btn-space" (click)="removeCategory(category)" mat-raised-button color="primary"> <button class="btn-space" (click)="removeCategory(category)" mat-raised-button color="primary">
Delete Delete
</button> </button>
</td> </td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
</div> </div>
</div> </div>
<div class="col-md-6"> <div class="col-md-6">
<label>Users</label> <label>Users</label>
<div class="col-md-12"> <div class="col-md-12">
@@ -70,20 +89,24 @@
</mat-form-field> </mat-form-field>
</div> </div>
</div> </div>
<table class="table"> <div class="col-md-12">
<tbody> <table class="table" style="table-layout: fixed;">
<tbody>
<tr *ngFor="let accessRight of account.accessRights"> <tr *ngFor="let accessRight of account.accessRights">
<td>{{accessRight.user.email}}</td> <td style="width: 100%;">{{accessRight.user.email}}</td>
<td> <td style="width: 100px;">
<button class="btn-space" [disabled]="account.accessRights!.length <= 1" click="removeAccessRight(accessRight)" mat-raised-button color="primary"> <button class="btn-space" [disabled]="account.accessRights!.length <= 1" click="removeAccessRight(accessRight)" mat-raised-button color="primary">
Delete Delete
</button> </button>
</td> </td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
</div>
</div> </div>
</div> </div>
<mat-dialog-actions class="mat-dialog-actions"> <mat-dialog-actions class="mat-dialog-actions">
<div class="mat-dialog-left"> <div class="mat-dialog-left">
<div class="alert alert-danger mat-dialog-error" *ngIf="errorMessage"> <div class="alert alert-danger mat-dialog-error" *ngIf="errorMessage">
@@ -19,6 +19,7 @@ import { CurrencyModel } from '../../../model/currency.model';
import { AccountCategoryService } from '../../../services/account.category.service'; import { AccountCategoryService } from '../../../services/account.category.service';
import { AccountCategoryModel } from '../../../model/account.category.model'; import { AccountCategoryModel } from '../../../model/account.category.model';
import { AccountAccessRightModel } from '../../../model/account.accessRight.model'; import { AccountAccessRightModel } from '../../../model/account.accessRight.model';
import { AccountService } from '../../../services/account.service';
@Component({ @Component({
templateUrl: './edit.account.component.html', templateUrl: './edit.account.component.html',
@@ -29,6 +30,7 @@ export class SettingsAccountEditComponent {
public errorMessage?: string; public errorMessage?: string;
public currencies?: CurrencyModel[]; public currencies?: CurrencyModel[];
public categories?: AccountCategoryModel[]; public categories?: AccountCategoryModel[];
public types = new Map<string, string>();
constructor( constructor(
private fb: UntypedFormBuilder, private fb: UntypedFormBuilder,
@@ -36,8 +38,10 @@ export class SettingsAccountEditComponent {
private dialogRef: MatDialogRef<SettingsAccountEditComponent>, private dialogRef: MatDialogRef<SettingsAccountEditComponent>,
private currencyService: CurrencyService, private currencyService: CurrencyService,
private accountCategoryService: AccountCategoryService, private accountCategoryService: AccountCategoryService,
private accountService: AccountService,
@Inject(MAT_DIALOG_DATA) public account: AccountModel @Inject(MAT_DIALOG_DATA) public account: AccountModel
) { ) {
this.types = this.accountService.getTypes();
} }
ngOnInit(): void { ngOnInit(): void {
@@ -56,6 +60,9 @@ export class SettingsAccountEditComponent {
categoryId: [ categoryId: [
'', '',
], ],
type: [
this.account.type,
],
}); });
this.currencyService this.currencyService
@@ -0,0 +1,28 @@
// angular
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
// libs
import { Observable } from 'rxjs';
// app
import { ApiRoutes } from '../api-routes';
import { AccountCategoryModel } from '../model/account.category.model';
@Injectable()
export class AccountService {
private types = new Map<string, string>();
constructor(
private httpClient: HttpClient,
) {
this.types.set('balance', 'Account with balance');
this.types.set('credit', 'Account with loan funds');
this.types.set('external', 'External account');
this.types.set('other', 'Other account');
}
public getTypes(): Map<string, string> {
return this.types;
}
}
@@ -2,7 +2,7 @@
<div class="row"> <div class="row">
<div class="col-6"> <div class="col-6">
<div class="breadcrumb-title"> <div class="breadcrumb-title">
<h4 class="page-title">{{title}}</h4> <h4 class="page-title">{{title | translate}}</h4>
</div> </div>
</div> </div>
<div class="col-6"> <div class="col-6">
@@ -12,8 +12,8 @@
<app-feather-icons [icon]="'home'" [class]="'breadcrumb-icon'"></app-feather-icons> <app-feather-icons [icon]="'home'" [class]="'breadcrumb-icon'"></app-feather-icons>
</a> </a>
</li> </li>
<li class="breadcrumb-item" *ngFor="let item of items">{{item}}</li> <li class="breadcrumb-item" *ngFor="let item of items">{{item | translate}}</li>
<li class="breadcrumb-item active">{{active_item}}</li> <li class="breadcrumb-item active">{{active_item | translate}}</li>
</ul> </ul>
</div> </div>
</div> </div>
@@ -1,12 +1,25 @@
// angular
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
// libs
import { TranslateModule } from '@ngx-translate/core';
import { FileUploadComponent } from './file-upload/file-upload.component'; import { FileUploadComponent } from './file-upload/file-upload.component';
import { BreadcrumbComponent } from './breadcrumb/breadcrumb.component'; import { BreadcrumbComponent } from './breadcrumb/breadcrumb.component';
import { SharedModule } from '../shared.module'; import { SharedModule } from '../shared.module';
@NgModule({ @NgModule({
declarations: [FileUploadComponent, BreadcrumbComponent], declarations: [
imports: [SharedModule], FileUploadComponent,
exports: [FileUploadComponent, BreadcrumbComponent], BreadcrumbComponent
],
imports: [
SharedModule,
TranslateModule,
],
exports: [
FileUploadComponent,
BreadcrumbComponent
],
}) })
export class ComponentsModule { export class ComponentsModule {
} }
+24 -4
View File
@@ -14,11 +14,23 @@
"DASHBOARD": { "DASHBOARD": {
"TEXT": "Dashboard", "TEXT": "Dashboard",
"LIST": { "LIST": {
"DASHBOARD1": "Dashboard 1", "DASHBOARD1": "Dashboard"
"DASHBOARD2": "Dashboard 2",
"DASHBOARD3": "Dashboard 3"
} }
}, },
"ACCOUNTS": {
"TEXT": "Accounts"
},
"SETTINGS": {
"TEXT": "Settings",
"LIST": {
"CURRENCIES": "Currencies",
"ACCOUNTCATEGORIES": "Account categories",
"ACCOUNTS": "Accounts",
"ITEMCATEGORIES": "Item categories",
"ITEMS": "Items"
}
},
"ADVANCE-TABLE": { "ADVANCE-TABLE": {
"TEXT": "Advance Table" "TEXT": "Advance Table"
}, },
@@ -80,5 +92,13 @@
"NGX-DATATABLE": "NGX-Datatable" "NGX-DATATABLE": "NGX-Datatable"
} }
} }
} },
"BALANCE": "Balance",
"DEBIT.BALANCE": "Debit balance",
"CREDIT.BALANCE": "Credit balance",
"CURRENT.BALANCE": "Current balance",
"HOME": "Home",
"OTHER": "Other",
"TOTAL": "Total"
} }
+103
View File
@@ -0,0 +1,103 @@
{
"HEADER": {
"SEARCH": {
"TEXT": "Шукати.."
}
},
"MENUITEMS": {
"USER": {
"POST": "Manager"
},
"MAIN": {
"TEXT": "Головне"
},
"DASHBOARD": {
"TEXT": "Панелі",
"LIST": {
"DASHBOARD1": "Панель"
}
},
"ACCOUNTS": {
"TEXT": "Рахунки"
},
"SETTINGS": {
"TEXT": "Налаштування",
"LIST": {
"CURRENCIES": "Валюти",
"ACCOUNTCATEGORIES": "Категорії рахунків",
"ACCOUNTS": "Рахунки",
"ITEMCATEGORIES": "Категорії статей",
"ITEMS": "Статті"
}
},
"ADVANCE-TABLE": {
"TEXT": "Advance Table"
},
"APPS": {
"TEXT": "Apps"
},
"CALENDAR": {
"TEXT": "Calendar"
},
"TASK": {
"TEXT": "Task"
},
"CONTACTS": {
"TEXT": "Contacts"
},
"EMAIL": {
"TEXT": "Email",
"LIST": {
"INBOX": "Inbox",
"COMPOSE": "Compose",
"READ": "Read Email"
}
},
"MORE-APPS": {
"TEXT": "More Apps",
"LIST": {
"CHAT": "Chat",
"SUPPORT": "Support",
"DRAG-DROP": "Drag & Drop",
"CONTACT-GRID": "Contact Grid"
}
},
"COMPONENTS": {
"TEXT": "Components"
},
"WIDGETS": {
"TEXT": "Widgets",
"LIST": {
"CHART-WIDGET": "Chart-Widget",
"DATA-WIDGET": "Data-Widget"
}
},
"FORMS": {
"TEXT": "Forms",
"LIST": {
"CONTROLS": "Form Controls",
"ADVANCE": "Advance Control",
"EXAMPLE": "Form Examples",
"VALIDATION": "Form Validation",
"WIZARD": "Wizard",
"EDITORS": "Editors"
}
},
"TABLES": {
"TEXT": "Tables",
"LIST": {
"BASIC": "Basic Tables",
"MATERIAL": "Material Tables",
"NGX-DATATABLE": "NGX-Datatable"
}
}
},
"BALANCE": "Баланс",
"DEBIT.BALANCE": "Остаток",
"CREDIT.BALANCE": "Кредиты",
"CURRENT.BALANCE": "Поточний баланс",
"HOME": "Головна",
"OTHER": "Інші",
"TOTAL": "Всього"
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 324 B

+57 -9
View File
@@ -1,5 +1,6 @@
namespace MyOffice.Services.Account namespace MyOffice.Services.Account
{ {
using AutoMapper;
using Core; using Core;
using Core.Extensions; using Core.Extensions;
using Core.Helpers; using Core.Helpers;
@@ -16,7 +17,9 @@
public class AccountService public class AccountService
{ {
private ILogger<AccountService> _logger; private ILogger<AccountService> _logger;
private readonly IMapper _mapper;
private readonly IAccountCategoryRepository _accountCategoryRepository; private readonly IAccountCategoryRepository _accountCategoryRepository;
private readonly IAccountAccessRepository _accountAccessRepository;
private readonly IAccountRepository _accountRepository; private readonly IAccountRepository _accountRepository;
private readonly ICurrencyRepository _currencyRepository; private readonly ICurrencyRepository _currencyRepository;
private readonly IAccountAccountCategoryRepository _accountAccountCategoryRepository; private readonly IAccountAccountCategoryRepository _accountAccountCategoryRepository;
@@ -27,7 +30,9 @@
public AccountService( public AccountService(
ILogger<AccountService> logger, ILogger<AccountService> logger,
IMapper mapper,
IAccountCategoryRepository accountCategoryRepository, IAccountCategoryRepository accountCategoryRepository,
IAccountAccessRepository accountAccessRepository,
IAccountRepository accountRepository, IAccountRepository accountRepository,
ICurrencyRepository currencyRepository, ICurrencyRepository currencyRepository,
IAccountAccountCategoryRepository accountAccountCategoryRepository, IAccountAccountCategoryRepository accountAccountCategoryRepository,
@@ -38,7 +43,9 @@
) )
{ {
_logger = logger; _logger = logger;
_mapper = mapper;
_accountCategoryRepository = accountCategoryRepository; _accountCategoryRepository = accountCategoryRepository;
_accountAccessRepository = accountAccessRepository;
_accountRepository = accountRepository; _accountRepository = accountRepository;
_currencyRepository = currencyRepository; _currencyRepository = currencyRepository;
_accountAccountCategoryRepository = accountAccountCategoryRepository; _accountAccountCategoryRepository = accountAccountCategoryRepository;
@@ -130,24 +137,24 @@
return result.Set(exists); return result.Set(exists);
} }
public List<Account> GetAllAccounts(Guid userId) public List<AccountDto> GetAllAccounts(Guid userId)
{ {
return _accountRepository.GetAll(userId); return _mapper.Map<List<AccountDto>>(_accountRepository.GetAll(userId));
} }
public List<Account> GetByCategory(Guid userId, Guid categoryId) public List<AccountDto> GetByCategory(Guid userId, Guid categoryId)
{ {
return _accountRepository.GetByCategory(userId, categoryId); return _mapper.Map<List<AccountDto>>(_accountRepository.GetByCategory(userId, categoryId));
} }
public List<AccountDetailed> GetByCategoryDetailed(Guid userId, Guid categoryId) public List<AccountDetailedDto> GetByCategoryDetailed(Guid userId, Guid categoryId)
{ {
return _accountRepository.GetByCategoryDetailed(userId, categoryId); return _mapper.Map<List<AccountDetailedDto>>(_accountRepository.GetByCategoryDetailed(userId, categoryId));
} }
public Exec<AccountDetailed, GeneralExecStatus> GetByIdDetailed(Guid userId, Guid id) public Exec<AccountDetailedDto, GeneralExecStatus> GetByIdDetailed(Guid userId, Guid id)
{ {
var result = new Exec<AccountDetailed, GeneralExecStatus>(GeneralExecStatus.success); var result = new Exec<AccountDetailedDto, GeneralExecStatus>(GeneralExecStatus.success);
var account = _accountRepository.GetByIdDetailed(userId, id); var account = _accountRepository.GetByIdDetailed(userId, id);
if (account == null) if (account == null)
@@ -155,7 +162,7 @@
return result.Set(GeneralExecStatus.not_found); return result.Set(GeneralExecStatus.not_found);
} }
return result.Set(account); return result.Set(_mapper.Map<AccountDetailedDto>(account));
} }
public Exec<Account, AccountAddResult> AccountAdd(Guid userId, AccountAdd input) public Exec<Account, AccountAddResult> AccountAdd(Guid userId, AccountAdd input)
@@ -208,9 +215,40 @@
return result.Set(AccountAddResult.failure); return result.Set(AccountAddResult.failure);
} }
var access = account.AccessRights!.FirstOrDefault(x => x.UserId == userId);
if (access != null && access.Type.ToString() != input.Type)
{
if (Enum.TryParse<AccountAccessTypeEnum>(input.Type, out var enumType))
{
access.Type = enumType;
_accountAccessRepository.Update(access);
}
}
return result.Set(account); return result.Set(account);
} }
public Exec<Account, GeneralExecStatus> AccountDelete(Guid userId, string id)
{
var result = new Exec<Account, GeneralExecStatus>(GeneralExecStatus.success);
var account = _accountRepository.Get(userId, id.AsGuid());
if (account == null)
{
return result.Set(GeneralExecStatus.not_found);
}
if (account.Motions!.Any())
{
return result.Set(GeneralExecStatus.not_found);
}
_accountRepository.Delete(account);
result.Set(account);
return result;
}
public Exec<Account, AccountEditResult> AccountUpdate(Guid userId, Guid accountId, AccountEdit input) public Exec<Account, AccountEditResult> AccountUpdate(Guid userId, Guid accountId, AccountEdit input)
{ {
if (input == null) if (input == null)
@@ -263,6 +301,16 @@
return result.Set(AccountEditResult.failure); return result.Set(AccountEditResult.failure);
} }
var access = account.AccessRights!.FirstOrDefault(x => x.UserId == userId);
if (access != null && access.Type.ToString() != input.Type)
{
if (Enum.TryParse<AccountAccessTypeEnum>(input.Type, out var enumType))
{
access.Type = enumType;
_accountAccessRepository.Update(access);
}
}
return result.Set(account); return result.Set(account);
} }
@@ -5,5 +5,6 @@
public string Name { get; set; } = null!; public string Name { get; set; } = null!;
public string CurrencyId { get; set; } = null!; public string CurrencyId { get; set; } = null!;
public Guid CategoryId { get; set; } public Guid CategoryId { get; set; }
public string Type { get; set; } = null!;
} }
} }
@@ -0,0 +1,9 @@
namespace MyOffice.Services.Account.Domain;
public class AccountDetailedDto
{
public AccountDto Account { get; set; } = null!;
public decimal TotalPlus { get; set; }
public decimal TotalMinus { get; set; }
public decimal Rest => TotalPlus - TotalMinus;
}
@@ -0,0 +1,92 @@
using MyOffice.Data.Models.Accounts;
using MyOffice.Data.Models.Users;
using MyOffice.Services.Account.Domain;
namespace MyOffice.Services.Account.Domain
{
using AutoMapper;
using MyOffice.Data.Models.Accounts;
using MyOffice.Data.Models.Currencies;
using MyOffice.Data.Models.Users;
using System;
public class AccountDto
{
public Guid Id { get; set; }
public string CurrencyGlobalId { get; set; } = null!;
public CurrencyGlobal? CurrencyGlobal { get; set; }
public Guid CurrencyId { get; set; }
public Currency? Currency { get; set; }
public Guid UserId { get; set; }
public UserDto? User { get; set; }
public Guid OwnerId { get; set; }
public UserDto? Owner { get; set; }
public string Name { get; set; } = null!;
public bool HasMotions { get; set; }
public List<AccountAccessDto>? AccessRights { get; set; }
public List<AccountAccountCategoryDto>? Categories { get; set; }
}
public class AccountAccessDto
{
public Guid AccountId { get; set; }
public AccountDto? Account { get; set; }
public Guid UserId { get; set; }
public User? User { get; set; }
public bool IsAllowRead { get; set; }
public bool IsAllowWrite { get; set; }
public bool IsAllowManage { get; set; }
public AccountAccessTypeEnum Type { get; set; }
}
public class AccountAccountCategoryDto
{
public Guid CategoryId { get; set; }
public AccountCategoryDto? Category { get; set; } = null!;
}
public class AccountMappingProfile : Profile
{
public AccountMappingProfile()
{
CreateMap<User, UserDto>();
CreateMap<Account, AccountDto>()
.ForMember(x => x.HasMotions, o => o.MapFrom(x => x.Motions.Any()))
;
CreateMap<AccountDetailed, AccountDetailedDto>();
CreateMap<AccountAccess, AccountAccessDto>();
CreateMap<AccountAccountCategory, AccountAccountCategoryDto>();
CreateMap<AccountCategory, AccountCategoryDto>()
.ForMember(x => x.Id, o => o.MapFrom(x => x.Id))
.ForMember(x => x.Id, o => o.MapFrom(x => x.Id))
;
}
}
public class UserDto
{
public Guid Id { get; set; }
public string UserName { get; set; } = null!;
public string Email { get; set; } = null!;
public string? FirstName { get; set; }
public string? LastName { get; set; }
public string? FullName { get; set; }
public string? Phone { get; set; }
public string CurrencyId { get; set; }
public CurrencyGlobal? Currency { get; set; }
}
}
public class AccountCategoryDto
{
public Guid Id { get; set; }
public Guid UserId { get; set; }
public string Name { get; set; } = null!;
}
@@ -6,4 +6,5 @@ public class AccountEdit
public string CurrencyId { get; set; } = null!; public string CurrencyId { get; set; } = null!;
public Guid? CategoryId { get; set; } public Guid? CategoryId { get; set; }
public Guid? UserId { get; set; } public Guid? UserId { get; set; }
public string? Type { get; set; }
} }
+27 -11
View File
@@ -27,21 +27,37 @@ public class DashboardService
public DashboardData GetDashboardRestData(Guid userId) public DashboardData GetDashboardRestData(Guid userId)
{ {
/*var lastDaysStart = DateTime.UtcNow.AddMonths(-3).StartOfDay();
var lastDaysEnd = lastDaysStart.AddMonths(3).EndOfDay();
var previousDaysStart = lastDaysStart.AddMonths(-3).StartOfDay();
var previousDaysEnd = previousDaysStart.AddMonths(3).EndOfDay();*/
var rests = _accountRepository.GetRestAtDate(userId, DateTime.UtcNow); var rests = _accountRepository.GetRestAtDate(userId, DateTime.UtcNow);
var result = new DashboardData var result = new DashboardData
{ {
//IncomeLast = _accountRepository.GetPeriodIncome(userId, lastDaysStart, lastDaysEnd), Balance = rests
//IncomePrevious = _accountRepository.GetPeriodIncome(userId, previousDaysStart, previousDaysEnd), .Where(x => (x.Type == AccountAccessTypeEnum.balance || x.Type == AccountAccessTypeEnum.credit) && x.CurrencyRate.HasValue)
//OutcomeLast = _accountRepository.GetPeriodOutcome(userId, lastDaysStart, lastDaysEnd), .Sum(x => x.Balance * (x.CurrencyRate * x.CurrencyQuantity)),
//OutcomePrevious = _accountRepository.GetPeriodOutcome(userId, previousDaysStart, previousDaysEnd),
Balance = rests.Sum(x => x.Balance * (x.CurrencyRate * x.CurrencyQuantity)), BalanceDebit = rests
BalanceDebit = rests.Where(x => x.Balance > 0).Sum(x => x.Balance * (x.CurrencyRate * x.CurrencyQuantity)), .Where(x => x.Type == AccountAccessTypeEnum.balance && x.CurrencyRate.HasValue)
BalanceCredit = rests.Where(x => x.Balance < 0).Sum(x => x.Balance * (x.CurrencyRate * x.CurrencyQuantity)), .Sum(x => x.Balance * (x.CurrencyRate * x.CurrencyQuantity)),
BalanceCredit = rests
.Where(x => x.Type == AccountAccessTypeEnum.credit && x.CurrencyRate.HasValue)
.Sum(x => x.Balance * (x.CurrencyRate * x.CurrencyQuantity)),
BalanceRests = rests
.Where(x => x.Type == AccountAccessTypeEnum.balance)
.Where(x => x.CurrencyRate.HasValue && x.Balance.HasValue && x.Balance != 0)
.Select(x => new DashboardRestData
{
Id = x.Id,
Name = x.Name,
Balance = x.Balance,
CurrencyName = x.CurrencyName,
CurrencyShortName = x.CurrencyShortName,
CurrencyRate = x.CurrencyRate,
CurrencyQuantity = x.CurrencyQuantity,
})
.OrderByDescending(x => x.BalanceAtRate)
.ToList(),
}; };
return result; return result;
@@ -13,13 +13,18 @@ public class DashboardData
public decimal? Balance { get; set; } public decimal? Balance { get; set; }
public decimal? BalanceDebit { get; set; } public decimal? BalanceDebit { get; set; }
public decimal? BalanceCredit { get; set; } public decimal? BalanceCredit { get; set; }
public List<DashboardRestData> BalanceRests { get; set; }
} }
public class DashboardRestData public class DashboardRestData
{ {
public AccountSimple AccountSimple { get; set; } public Guid Id { get; set; }
public decimal? Balance => AccountSimple.Balance; public string Name { get; set; } = null!;
public string CurrencyName { get; set; } = null!;
public string CurrencyShortName { get; set; } = null!;
public decimal? Balance { get; set; }
public decimal? CurrencyRate { get; set; }
public decimal? CurrencyQuantity { get; set; }
public decimal? BalanceAtRate => public decimal? BalanceAtRate => Balance * (CurrencyRate * CurrencyQuantity);
AccountSimple.Balance * (AccountSimple.CurrencyRate * AccountSimple.CurrencyQuantity);
} }
@@ -0,0 +1,10 @@
namespace MyOffice.Services.Identity;
using Data.Models.Users;
public interface IContextProvider
{
User User { get; }
Guid UserId { get; }
}
@@ -6,6 +6,10 @@
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<PackageReference Include="AutoMapper" Version="12.0.1" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\MyOffice.Core\MyOffice.Core.csproj" /> <ProjectReference Include="..\MyOffice.Core\MyOffice.Core.csproj" />
<ProjectReference Include="..\MyOffice.Data.Repositories\MyOffice.Data.Repositories.csproj" /> <ProjectReference Include="..\MyOffice.Data.Repositories\MyOffice.Data.Repositories.csproj" />
@@ -1,5 +1,6 @@
namespace MyOffice.Web.Controllers; namespace MyOffice.Web.Controllers;
using AutoMapper;
using Core; using Core;
using Core.Extensions; using Core.Extensions;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
@@ -18,28 +19,29 @@ using Services.Item;
public class AccountController : BaseApiController public class AccountController : BaseApiController
{ {
private readonly ILogger<AccountController> _logger; private readonly ILogger<AccountController> _logger;
private readonly IMapper _mapper;
private readonly AccountService _accountService; private readonly AccountService _accountService;
private readonly ItemService _itemService; private readonly ItemService _itemService;
public AccountController( public AccountController(
ILogger<AccountController> logger, ILogger<AccountController> logger,
IMapper mapper,
AccountService accountService, AccountService accountService,
ItemService itemService ItemService itemService
) )
{ {
_logger = logger; _logger = logger;
_mapper = mapper;
_accountService = accountService; _accountService = accountService;
_itemService = itemService; _itemService = itemService;
} }
[HttpGet("~/api/accounts")] [HttpGet("~/api/accounts")]
public object AccountsGet(string category) public List<AccountDetailedViewModel> AccountsGet(string category)
{ {
var list = _accountService.GetByCategoryDetailed(UserId, category!.AsGuid()); var list = _accountService.GetByCategoryDetailed(UserId, category!.AsGuid());
return list return _mapper.Map<List<AccountDetailedViewModel>>(list.OrderBy(x => x.Account.Name).ToList());
.OrderBy(x => x.Account.Name)
.Select(x => x.ToModel());
} }
[HttpGet("~/api/accounts/{id}")] [HttpGet("~/api/accounts/{id}")]
@@ -54,7 +56,8 @@ public class AccountController : BaseApiController
return ProblemBadRequest("Account not found."); return ProblemBadRequest("Account not found.");
case GeneralExecStatus.success: case GeneralExecStatus.success:
return exec.Result!.ToModel(); return _mapper.Map<AccountDetailedViewModel>(exec.Result);
//return exec.Result!.ToModel();
default: default:
throw new NotSupportedException(exec.Status.ToString()); throw new NotSupportedException(exec.Status.ToString());
@@ -1,5 +1,6 @@
namespace MyOffice.Web.Controllers; namespace MyOffice.Web.Controllers;
using AutoMapper;
using Core; using Core;
using Core.Extensions; using Core.Extensions;
using Data.Models.Accounts; using Data.Models.Accounts;
@@ -15,14 +16,17 @@ using Services.Account.Domain;
public class SettingsAccountController : BaseApiController public class SettingsAccountController : BaseApiController
{ {
private readonly ILogger<SettingsAccountController> _logger; private readonly ILogger<SettingsAccountController> _logger;
private readonly IMapper _mapper;
private readonly AccountService _accountService; private readonly AccountService _accountService;
public SettingsAccountController( public SettingsAccountController(
ILogger<SettingsAccountController> logger, ILogger<SettingsAccountController> logger,
IMapper mapper,
AccountService accountService AccountService accountService
) )
{ {
_logger = logger; _logger = logger;
_mapper = mapper;
_accountService = accountService; _accountService = accountService;
} }
@@ -111,15 +115,13 @@ public class SettingsAccountController : BaseApiController
} }
[HttpGet("~/api/settings/accounts")] [HttpGet("~/api/settings/accounts")]
public object AccountsGet(string? category) public List<AccountViewModel> AccountsGet(string? category)
{ {
var list = category.IsPresent() var list = category.IsPresent()
? _accountService.GetByCategory(UserId, category!.AsGuid()) ? _accountService.GetByCategory(UserId, category!.AsGuid())
: _accountService.GetAllAccounts(UserId); : _accountService.GetAllAccounts(UserId);
return list return _mapper.Map<List<AccountViewModel>>(list.OrderBy(x => x.Name));
.OrderBy(x => x.Name)
.Select(x => x.ToModel());
} }
[HttpPost("~/api/settings/accounts")] [HttpPost("~/api/settings/accounts")]
@@ -130,6 +132,7 @@ public class SettingsAccountController : BaseApiController
Name = request.Name, Name = request.Name,
CurrencyId = request.CurrencyId, CurrencyId = request.CurrencyId,
CategoryId = request.CategoryId.AsGuid(), CategoryId = request.CategoryId.AsGuid(),
Type = request.Type,
}); });
switch (exec.Status) switch (exec.Status)
@@ -158,6 +161,7 @@ public class SettingsAccountController : BaseApiController
CurrencyId = request.CurrencyId, CurrencyId = request.CurrencyId,
CategoryId = request.CategoryId?.AsGuidNull(), CategoryId = request.CategoryId?.AsGuidNull(),
UserId = request.UserId?.AsGuidNull(), UserId = request.UserId?.AsGuidNull(),
Type = request.Type,
}); });
switch (exec.Status) switch (exec.Status)
@@ -178,6 +182,22 @@ public class SettingsAccountController : BaseApiController
} }
} }
[HttpDelete("~/api/settings/accounts/{id}")]
public object AccountsDelete(string id)
{
var exec = _accountService.AccountDelete(UserId, id);
switch (exec.Status)
{
case GeneralExecStatus.not_found:
return ProblemBadRequest("Account not found.");
case GeneralExecStatus.success:
return exec.Result!;
default:
throw new NotSupportedException(exec.Status.ToString());
}
}
[HttpDelete("~/api/settings/accounts/{id}/category/{categoryId}")] [HttpDelete("~/api/settings/accounts/{id}/category/{categoryId}")]
public object AccountsCategoryRemove(string id, string categoryId) public object AccountsCategoryRemove(string id, string categoryId)
{ {
+3 -1
View File
@@ -13,6 +13,7 @@ using MyOffice.Core.Identity;
using Core; using Core;
using Services.Users; using Services.Users;
using Services.Users.Domain; using Services.Users.Domain;
using MyOffice.Data.Models.Currencies;
[ApiController] [ApiController]
[Route("api/[controller]")] [Route("api/[controller]")]
@@ -40,7 +41,8 @@ public class UserController : BaseApiController
{ {
Id = Guid.NewGuid(), Id = Guid.NewGuid(),
UserName = request.UserName, UserName = request.UserName,
Email = request.UserName Email = request.UserName,
CurrencyId = CurrencyGlobalIdEnum.USD.ToString(),
}; };
var result = await _userManager.CreateAsync(user, request.Password); var result = await _userManager.CreateAsync(user, request.Password);
@@ -20,7 +20,6 @@ public class ConfigureIdentityServerOptions : IConfigureNamedOptions<IdentitySer
public void Configure(string? name, IdentityServerAuthenticationOptions options) public void Configure(string? name, IdentityServerAuthenticationOptions options)
{ {
//_logger.LogError($"Configure: {_globalSettings.Host}");
if (name == IdentityServerAuthenticationDefaults.AuthenticationScheme) if (name == IdentityServerAuthenticationDefaults.AuthenticationScheme)
{ {
options.RequireHttpsMetadata = false; options.RequireHttpsMetadata = false;
+39
View File
@@ -0,0 +1,39 @@
namespace MyOffice.Web.Identity;
using Data.Repositories.Users;
using MyOffice.Data.Models.Users;
using MyOffice.Services.Identity;
public class ContextProvider : IContextProvider
{
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly IUserRepository _userRepository;
public ContextProvider(
IHttpContextAccessor httpContextAccessor,
IUserRepository userRepository
)
{
_httpContextAccessor = httpContextAccessor;
_userRepository = userRepository;
}
private User? _user = null;
public User User
{
get
{
_user ??= _userRepository.GetUser(UserId);
return _user!;
}
}
public Guid UserId
{
get
{
return Guid.Parse(_httpContextAccessor!.HttpContext!.User!.Claims!.FirstOrDefault(x => x.Type == "sub")!.Value);
}
}
}
@@ -1,6 +1,7 @@
namespace MyOffice.Web.Models.Account namespace MyOffice.Web.Models.Account
{ {
using Data.Models.Accounts; using Data.Models.Accounts;
using Services.Account.Domain;
using User; using User;
public class AccessRightsViewModel public class AccessRightsViewModel
@@ -13,7 +14,7 @@
public static class AccessRightsViewModelExtensions public static class AccessRightsViewModelExtensions
{ {
public static AccessRightsViewModel ToModel(this AccountAccess accountAccess) public static AccessRightsViewModel ToModel(this AccountAccessDto accountAccess)
{ {
return new AccessRightsViewModel return new AccessRightsViewModel
{ {
@@ -1,6 +1,7 @@
namespace MyOffice.Web.Models.Account; namespace MyOffice.Web.Models.Account;
using Data.Models.Accounts; using Data.Models.Accounts;
using Services.Account.Domain;
public class AccountDetailedViewModel public class AccountDetailedViewModel
{ {
@@ -8,9 +9,9 @@ public class AccountDetailedViewModel
public decimal Rest { get; set; } public decimal Rest { get; set; }
} }
public static class AccountDetailedViewModelExtensions /*public static class AccountDetailedViewModelExtensions
{ {
public static AccountDetailedViewModel ToModel(this AccountDetailed input) public static AccountDetailedViewModel ToModel(this AccountDetailedDto input)
{ {
return new AccountDetailedViewModel return new AccountDetailedViewModel
{ {
@@ -18,4 +19,4 @@ public static class AccountDetailedViewModelExtensions
Rest = input.Rest, Rest = input.Rest,
}; };
} }
} }*/
@@ -8,6 +8,7 @@ public class AccountEditRequestModel
public string Name { get; set; } = null!; public string Name { get; set; } = null!;
[Required] [Required]
public string CurrencyId { get; set; } = null!; public string CurrencyId { get; set; } = null!;
public string? CategoryId { get; set; } = null!; public string? CategoryId { get; set; }
public string? UserId { get; set; } = null!; public string? UserId { get; set; }
public string? Type { get; set; }
} }
@@ -1,8 +1,12 @@
namespace MyOffice.Web.Models.Account namespace MyOffice.Web.Models.Account
{ {
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using AutoMapper;
using Core.Extensions; using Core.Extensions;
using Data.Models.Accounts; using Data.Models.Accounts;
using Services.Account.Domain;
using Services.Identity;
using User;
public class AccountViewModel public class AccountViewModel
{ {
@@ -10,10 +14,12 @@
[Required] [Required]
public string Name { get; set; } = null!; public string Name { get; set; } = null!;
public string Type { get; set; } = null!;
[Required] [Required]
public string CurrencyId { get; set; } = null!; public string CurrencyId { get; set; } = null!;
public string? CurrencyName { get; set; } public string? CurrencyName { get; set; }
public bool AllowDelete { get; set; }
public List<AccountCategoryViewModel>? Categories { get; set; } public List<AccountCategoryViewModel>? Categories { get; set; }
@@ -23,9 +29,48 @@
public List<AccessRightsViewModel>? AccessRights { get; set; } public List<AccessRightsViewModel>? AccessRights { get; set; }
} }
public static class AccountViewModelExtensions public class ViewModelProfile : Profile
{ {
public static AccountViewModel ToModel(this Account input) public ViewModelProfile()
{
CreateMap<Guid, string>().ConvertUsing(x => x.ToShort());
}
}
public class AccountViewModelProfile : Profile
{
public AccountViewModelProfile(
IContextProvider contextProvider
)
{
CreateMap<AccountDetailedDto, AccountDetailedViewModel>()
.ForMember(x => x.Account, o => o.MapFrom(x => x.Account))
;
CreateMap<UserDto, UserViewModel>();
CreateMap<MyOffice.Data.Models.Users.User, UserViewModel>();
CreateMap<AccountDto, AccountViewModel>()
.ForMember(x => x.Type, o => o.MapFrom(x => x.AccessRights!.FirstOrDefault(a => a.UserId == contextProvider.UserId)!.Type.ToString()))
.ForMember(x => x.CurrencyId, o => o.MapFrom(x => x.CurrencyGlobalId))
.ForMember(x => x.CurrencyName, o => o.MapFrom(x => x.Currency!.Name))
.ForMember(x => x.AllowDelete, o => o.MapFrom(x => !x.HasMotions))
;
CreateMap<AccountAccountCategoryDto, AccountCategoryViewModel>()
.ForMember(x => x.Id, o => o.MapFrom(x => x.CategoryId))
.ForMember(x => x.Name, o => o.MapFrom(x => x.Category!.Name))
;
CreateMap<AccountAccessDto, AccessRightsViewModel>();
}
}
/*public static class AccountViewModelExtensions
{
public static AccountViewModel ToModel(this AccountDto input)
{ {
return new AccountViewModel return new AccountViewModel
{ {
@@ -41,5 +86,5 @@
.ToList(), .ToList(),
}; };
} }
} }*/
} }
+2
View File
@@ -34,6 +34,8 @@
<PackageReference Include="Auth0.AuthenticationApi" Version="7.17.4" /> <PackageReference Include="Auth0.AuthenticationApi" Version="7.17.4" />
<PackageReference Include="Auth0.Core" Version="7.17.4" /> <PackageReference Include="Auth0.Core" Version="7.17.4" />
<PackageReference Include="Auth0.ManagementApi" Version="7.17.4" /> <PackageReference Include="Auth0.ManagementApi" Version="7.17.4" />
<PackageReference Include="AutoMapper" Version="12.0.1" />
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="12.0.1" />
<PackageReference Include="Google.Apis.Auth" Version="1.58.0-beta01" /> <PackageReference Include="Google.Apis.Auth" Version="1.58.0-beta01" />
<PackageReference Include="IdentityServer4.AccessTokenValidation" Version="3.0.1" /> <PackageReference Include="IdentityServer4.AccessTokenValidation" Version="3.0.1" />
<PackageReference Include="IdentityServer4.AspNetIdentity" Version="4.1.2" /> <PackageReference Include="IdentityServer4.AspNetIdentity" Version="4.1.2" />
+36 -2
View File
@@ -37,10 +37,14 @@ using Identity.Configure;
using Infrastructure; using Infrastructure;
using Microsoft.Extensions.Logging.Console; using Microsoft.Extensions.Logging.Console;
using IdentityServer4.Services; using IdentityServer4.Services;
using Models.Account;
using MyOffice.Services.Currency; using MyOffice.Services.Currency;
using Services.Account; using Services.Account;
using Services.Item; using Services.Item;
using MyOffice.Services.Dashboard; using MyOffice.Services.Dashboard;
using Services.Account.Domain;
using MyOffice.Services.Identity;
using AutoMapper;
public class Program public class Program
{ {
@@ -92,6 +96,10 @@ public class Program
AddIdentityServices(builder); AddIdentityServices(builder);
builder.Services.AddScoped<IContextProvider, ContextProvider>();
AddMapping(builder);
AddRepositories(builder); AddRepositories(builder);
AddBusinessServices(builder); AddBusinessServices(builder);
@@ -205,6 +213,20 @@ public class Program
} }
} }
private static void AddMapping(WebApplicationBuilder builder)
{
builder.Services.AddSingleton(provider => new MapperConfiguration(cfg =>
{
cfg.AddProfile(new AccountMappingProfile());
cfg.AddProfile(new ViewModelProfile());
cfg.AddProfile(new AccountViewModelProfile(provider.CreateScope().ServiceProvider.GetService<IContextProvider>()!));
}).CreateMapper());
//builder.Services.AddAutoMapper(typeof(AccountMappingProfile));
//builder.Services.AddAutoMapper(typeof(AccountViewModelProfile));
//builder.Services.AddAutoMapper(typeof(ViewModelProfile));
}
private static void AddRepositories(WebApplicationBuilder builder) private static void AddRepositories(WebApplicationBuilder builder)
{ {
builder.Services.AddScoped<IUserRepository, UserRepository>(); builder.Services.AddScoped<IUserRepository, UserRepository>();
@@ -216,6 +238,7 @@ public class Program
builder.Services.AddScoped<IAccountCategoryRepository, AccountCategoryRepository>(); builder.Services.AddScoped<IAccountCategoryRepository, AccountCategoryRepository>();
builder.Services.AddScoped<IAccountRepository, AccountRepository>(); builder.Services.AddScoped<IAccountRepository, AccountRepository>();
builder.Services.AddScoped<IAccountAccessRepository, AccountAccessRepository>();
builder.Services.AddScoped<IAccountAccountCategoryRepository, AccountAccountCategoryRepository>(); builder.Services.AddScoped<IAccountAccountCategoryRepository, AccountAccountCategoryRepository>();
builder.Services.AddScoped<IItemCategoryRepository, ItemCategoryRepository>(); builder.Services.AddScoped<IItemCategoryRepository, ItemCategoryRepository>();
@@ -274,9 +297,20 @@ public class Program
{ {
_firstRequest = false; _firstRequest = false;
// set real frontend host
globalSettings = ctx.RequestServices.GetRequiredService<GlobalSettings>(); globalSettings = ctx.RequestServices.GetRequiredService<GlobalSettings>();
globalSettings.Host = GetFrontendHost(ctx, logger);
var configuration = ctx.RequestServices.GetRequiredService<IConfiguration>();
var frontEndHost = configuration.GetValue<string>("FrontEnd:Host");
var isDynamicFrontEndHost = frontEndHost.IsMissing();
if (!isDynamicFrontEndHost)
{
globalSettings.Host = frontEndHost;
}
else
{
// set real frontend host
globalSettings.Host = GetFrontendHost(ctx, logger);
}
// update identity server // update identity server
var options = ctx.RequestServices.GetRequiredService<IdentityServerOptions>(); var options = ctx.RequestServices.GetRequiredService<IdentityServerOptions>();