fix
This commit is contained in:
@@ -30,8 +30,8 @@ public class AccountSimple
|
||||
public Guid Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
public AccountAccessTypeEnum Type { get; set; }
|
||||
public string CurrencyName { get; set; }
|
||||
public string CurrencyShortName { get; set; }
|
||||
public string? CurrencyName { get; set; }
|
||||
public string? CurrencyShortName { get; set; }
|
||||
public decimal? CurrencyRate { get; set; }
|
||||
public int? CurrencyQuantity { get; set; }
|
||||
public decimal? TotalPlus { get; set; }
|
||||
|
||||
@@ -204,16 +204,17 @@ public class AccountRepository : AppRepository<Account>, IAccountRepository
|
||||
.Where(x => !x.Item.Category!.IsInternal)
|
||||
.GroupBy(x => new
|
||||
{
|
||||
ItemId = x.Item.CategoryId,
|
||||
ItemName = x.Item.Category!.Name,
|
||||
Id = x.Item.CategoryId,
|
||||
Name = x.Item.Category!.Name,
|
||||
CurrencyId = x.Account.CurrencyGlobalId,
|
||||
CurrencyName = x.Account.CurrencyGlobal!.Name,
|
||||
})
|
||||
.Select(x => new MotionTotalSimple
|
||||
{
|
||||
Id = x.Key.Id,
|
||||
Name = x.Key.Name,
|
||||
CurrencyId = x.Key.CurrencyId,
|
||||
CurrencyName = x.Key.CurrencyName,
|
||||
Name = x.Key.ItemName,
|
||||
Amount = x.Sum(a => a.AmountPlus),
|
||||
}).ToList();
|
||||
}
|
||||
@@ -227,8 +228,8 @@ public class AccountRepository : AppRepository<Account>, IAccountRepository
|
||||
.Where(x => x.Item.Category!.UserId == userId)
|
||||
.GroupBy(x => new
|
||||
{
|
||||
ItemId = x.Item.ItemGlobalId,
|
||||
ItemName = x.Item.ItemGlobal!.Name,
|
||||
Id = x.Item.ItemGlobalId,
|
||||
Name = x.Item.ItemGlobal!.Name,
|
||||
CurrencyId = x.Account.CurrencyGlobalId,
|
||||
CurrencyName = x.Account.CurrencyGlobal!.Name,
|
||||
})
|
||||
@@ -236,9 +237,10 @@ public class AccountRepository : AppRepository<Account>, IAccountRepository
|
||||
{
|
||||
CurrencyId = x.Key.CurrencyId,
|
||||
CurrencyName = x.Key.CurrencyName,
|
||||
Name = x.Key.ItemName,
|
||||
Name = x.Key.Name,
|
||||
Amount = x.Sum(a => a.AmountPlus),
|
||||
}).ToList();
|
||||
})
|
||||
.ToList();
|
||||
}
|
||||
|
||||
|
||||
@@ -250,18 +252,18 @@ public class AccountRepository : AppRepository<Account>, IAccountRepository
|
||||
.Where(x => !x.Item.Category!.IsInternal)
|
||||
.GroupBy(x => new
|
||||
{
|
||||
ItemId = x.Item.CategoryId,
|
||||
ItemName = x.Item.Category!.Name,
|
||||
Id = x.Item.CategoryId,
|
||||
Name = x.Item.Category!.Name,
|
||||
CurrencyId = x.Account.CurrencyGlobalId,
|
||||
CurrencyName = x.Account.CurrencyGlobal!.Name,
|
||||
})
|
||||
.Select(x => new MotionTotalSimple
|
||||
{
|
||||
Id = x.Key.ItemId,
|
||||
Name = x.Key.ItemName,
|
||||
Id = x.Key.Id,
|
||||
Name = x.Key.Name,
|
||||
CurrencyId = x.Key.CurrencyId,
|
||||
CurrencyName = x.Key.CurrencyName,
|
||||
Amount = x.Sum(a => a.AmountPlus),
|
||||
Amount = x.Sum(a => a.AmountMinus),
|
||||
}).ToList();
|
||||
}
|
||||
|
||||
@@ -273,11 +275,20 @@ public class AccountRepository : AppRepository<Account>, IAccountRepository
|
||||
.Where(x => x.Item.CategoryId == categoryId)
|
||||
.Where(x => !x.Item.Category!.IsInternal)
|
||||
.Where(x => x.Item.Category!.UserId == userId)
|
||||
.GroupBy(x => new { Id = x.Item.ItemGlobalId, x.Item.ItemGlobal.Name })
|
||||
.GroupBy(x => new
|
||||
{
|
||||
Id = x.Item.ItemGlobalId,
|
||||
Name = x.Item.ItemGlobal!.Name,
|
||||
CurrencyId = x.Account.CurrencyGlobalId,
|
||||
CurrencyName = x.Account.CurrencyGlobal!.Name,
|
||||
})
|
||||
.Select(x => new MotionTotalSimple
|
||||
{
|
||||
CurrencyId = x.Key.CurrencyId,
|
||||
CurrencyName = x.Key.CurrencyName,
|
||||
Name = x.Key.Name,
|
||||
Amount = x.Sum(a => a.AmountMinus)
|
||||
}).ToList();
|
||||
Amount = x.Sum(a => a.AmountMinus),
|
||||
})
|
||||
.ToList();
|
||||
}
|
||||
}
|
||||
@@ -205,6 +205,9 @@ public class AppDbContext : DbContext
|
||||
.Entity<AccountAccess>()
|
||||
.Property(d => d.Type)
|
||||
.HasConversion(new EnumToStringConverter<AccountAccessTypeEnum>());
|
||||
|
||||
modelBuilder.Entity<AccountAccess>()
|
||||
.HasIndex(p => new { p.AccountId, p.UserId}).IsUnique();
|
||||
}
|
||||
|
||||
private void MotionsCreating(ModelBuilder modelBuilder)
|
||||
|
||||
+729
@@ -0,0 +1,729 @@
|
||||
// <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("20230804145453_AccountAccesUnique")]
|
||||
partial class AccountAccesUnique
|
||||
{
|
||||
/// <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>("Name")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<Guid>("OwnerId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Type")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("OwnerId");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.HasIndex("AccountId", "UserId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("AccountAccesses");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Accounts.AccountAccessInvite", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTime?>("AcceptedOn")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<Guid>("AccountId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTime>("CreatedOn")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<bool>("IsAllowWrite")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<DateTime?>("RejectedOn")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AccountId");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("AccountAccessInvites");
|
||||
});
|
||||
|
||||
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", "Owner")
|
||||
.WithMany("AccountAccessOwners")
|
||||
.HasForeignKey("OwnerId")
|
||||
.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("Owner");
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Accounts.AccountAccessInvite", b =>
|
||||
{
|
||||
b.HasOne("MyOffice.Data.Models.Accounts.Account", "Account")
|
||||
.WithMany("Invites")
|
||||
.HasForeignKey("AccountId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("MyOffice.Data.Models.Users.User", "User")
|
||||
.WithMany("AccountAccessInvites")
|
||||
.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("Invites");
|
||||
|
||||
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("AccountAccessInvites");
|
||||
|
||||
b.Navigation("AccountAccessOwners");
|
||||
|
||||
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,37 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace MyOffice.Migrations.Postgres.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AccountAccesUnique : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_AccountAccesses_AccountId",
|
||||
table: "AccountAccesses");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AccountAccesses_AccountId_UserId",
|
||||
table: "AccountAccesses",
|
||||
columns: new[] { "AccountId", "UserId" },
|
||||
unique: true);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_AccountAccesses_AccountId_UserId",
|
||||
table: "AccountAccesses");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AccountAccesses_AccountId",
|
||||
table: "AccountAccesses",
|
||||
column: "AccountId");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -84,12 +84,13 @@ namespace MyOffice.Migrations.Postgres.Migrations
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AccountId");
|
||||
|
||||
b.HasIndex("OwnerId");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.HasIndex("AccountId", "UserId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("AccountAccesses");
|
||||
});
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
</div>
|
||||
<div class="body">
|
||||
<div id="chart">
|
||||
<apx-chart #chart *ngIf="chartOptions" class="apex-pie-center"
|
||||
<apx-chart #chart *ngIf="chartOptions" class="apex-pie-center" (contextmenu)="onRightClick($event)"
|
||||
[series]="chartOptions.series!"
|
||||
[chart]="chartOptions.chart!"
|
||||
[dataLabels]="chartOptions.dataLabels!"
|
||||
|
||||
@@ -90,10 +90,22 @@ export class DashboardIncomeComponent implements OnInit {
|
||||
color: this.colors[this.colors.length - i - 1],
|
||||
});
|
||||
}
|
||||
this.setChartOptions(series, ranges);
|
||||
|
||||
if (update) {
|
||||
this.chart.updateSeries([{
|
||||
data: series
|
||||
}]);
|
||||
} else {
|
||||
this.setChartOptions(series, ranges);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
onRightClick(event?: Event) {
|
||||
event?.preventDefault();
|
||||
this.loadData(true);
|
||||
}
|
||||
|
||||
private setChartOptions(data: any[], ranges: any[]) {
|
||||
var self = this;
|
||||
|
||||
@@ -105,6 +117,12 @@ export class DashboardIncomeComponent implements OnInit {
|
||||
type: 'treemap',
|
||||
width: 600,
|
||||
height: 600,
|
||||
events: {
|
||||
click: function (event, chartContext, config) {
|
||||
var data = self.dashboardModel!.data[config.dataPointIndex];
|
||||
self.loadData(true, data.id);
|
||||
}
|
||||
}
|
||||
},
|
||||
plotOptions: {
|
||||
treemap: {
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
-->
|
||||
</div>
|
||||
<div class="body">
|
||||
<apx-chart #chart *ngIf="chartOptions" class="apex-pie-center"
|
||||
<apx-chart #chart *ngIf="chartOptions" class="apex-pie-center" (contextmenu)="onRightClick($event)"
|
||||
[series]="chartOptions.series!"
|
||||
[chart]="chartOptions.chart!"
|
||||
[dataLabels]="chartOptions.dataLabels!"
|
||||
@@ -46,12 +46,12 @@
|
||||
[title]="chartOptions.title!"
|
||||
[legend]="chartOptions.legend!">
|
||||
</apx-chart>
|
||||
<div class="table-responsive m-t-15" *ngIf="dashboardModel!.details">
|
||||
<div class="table-responsive m-t-15" *ngIf="dashboardModel">
|
||||
<table class="table align-items-center">
|
||||
<tbody>
|
||||
<tr *ngFor="let item of dashboardModel!.details!">
|
||||
<td><i class="fa fa-circle col-cyan msr-2"></i> {{item.name}}</td>
|
||||
<td [ngClass]="{ 'col-green': item.value != 0, 'col-red': item.value == 0}" style="text-align: right;">{{item.value | number: '1.2'}} ({{item.currency}})</td>
|
||||
<tr *ngFor="let item of dashboardModel!.details">
|
||||
<td><i class="fa fa-circle col-cyan msr-2"></i> {{item.currency}}</td>
|
||||
<td [ngClass]="{ 'col-green': item.value != 0, 'col-red': item.value == 0}" style="text-align: right;">{{item.value | number: '1.2'}} ({{item.valueRaw}})</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
@@ -64,6 +64,11 @@ export class DashboardOutcomeComponent implements OnInit {
|
||||
this.loadData();
|
||||
}
|
||||
|
||||
onRightClick(event?: Event) {
|
||||
event?.preventDefault();
|
||||
this.loadData(true);
|
||||
}
|
||||
|
||||
private loadData(update?: boolean, category?: string) {
|
||||
let params = new HttpParams()
|
||||
.set('from', moment(this.dateFrom).format('YYYY-MM-DD'))
|
||||
@@ -91,6 +96,7 @@ export class DashboardOutcomeComponent implements OnInit {
|
||||
color: this.colors[this.colors.length - i - 1],
|
||||
});
|
||||
}
|
||||
|
||||
if (update) {
|
||||
this.chart.updateSeries([{
|
||||
data: series
|
||||
|
||||
@@ -103,5 +103,6 @@
|
||||
"OTHER": "Інші",
|
||||
"TOTAL": "Всього",
|
||||
"INCOME": "Надходження",
|
||||
"OUTCOME": "Витрати"
|
||||
"OUTCOME": "Витрати",
|
||||
"PERIOD": "Період"
|
||||
}
|
||||
|
||||
@@ -119,19 +119,44 @@ public class DashboardService
|
||||
? _accountRepository.GetOutcomeByCategory(userId, category.Value, from.ToUtc(), to.ToUtc())
|
||||
: _accountRepository.GetOutcomeByCategories(userId, from.ToUtc(), to.ToUtc());
|
||||
|
||||
data = data
|
||||
.Where(x => x.Amount != 0)
|
||||
.ToList();
|
||||
|
||||
var currencies = data
|
||||
.Where(x => x.Amount != 0)
|
||||
.Select(x => x.CurrencyId)
|
||||
.Distinct()
|
||||
.ToList();
|
||||
|
||||
var rates = _currencyRateRepository
|
||||
.GetLastRates(userId, currencies, to.ToUtc())
|
||||
.ToDictionary(x => x.Key, x => x.Value.Rate * x.Value.Quantity);
|
||||
|
||||
return new DashboardIncomeData
|
||||
{
|
||||
Data = data.Select(x => new DashboardIncomeDataItem
|
||||
Data = data.Select(x => new
|
||||
{
|
||||
Id = x.Id.ToShort(),
|
||||
Name = x.Name,
|
||||
Value = (x.Amount * rates.FirstOrDefault(r => r.Key == x.CurrencyId).Value),
|
||||
})
|
||||
.GroupBy(x => new { x.Id, x.Name })
|
||||
.Select(x => new DashboardIncomeDataItem
|
||||
{
|
||||
Id = x.Key.Id,
|
||||
Name = x.Key.Name,
|
||||
Value = x.Sum(s => s.Value),
|
||||
})
|
||||
.ToList(),
|
||||
|
||||
Details = data.Select(x => new DashboardIncomeDataItem
|
||||
{
|
||||
Id = x.Id?.ToShort(),
|
||||
Id = x.Id.ToShort(),
|
||||
Currency = x.CurrencyId,
|
||||
Name = x.Name,
|
||||
Value = x.Amount,
|
||||
ValueRaw = x.Amount,
|
||||
Value = (x.Amount * rates.FirstOrDefault(r => r.Key == x.CurrencyId).Value),
|
||||
}).ToList()
|
||||
};
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ public class UserStore :
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public async Task<IdentityResult> CreateAsync(ApplicationUser<Guid> user, CancellationToken cancellationToken)
|
||||
public Task<IdentityResult> CreateAsync(ApplicationUser<Guid> user, CancellationToken cancellationToken)
|
||||
{
|
||||
var result = _userRepository.AddUser(new User
|
||||
{
|
||||
@@ -65,10 +65,10 @@ public class UserStore :
|
||||
IsEmailConfirmed = user.IsEmailConfirmed
|
||||
});
|
||||
|
||||
return result == 1 ? IdentityResult.Success : IdentityResult.Failed();
|
||||
return Task.FromResult(result == 1 ? IdentityResult.Success : IdentityResult.Failed());
|
||||
}
|
||||
|
||||
public async Task<IdentityResult> UpdateAsync(ApplicationUser<Guid> user, CancellationToken cancellationToken)
|
||||
public Task<IdentityResult> UpdateAsync(ApplicationUser<Guid> user, CancellationToken cancellationToken)
|
||||
{
|
||||
var userDb = new User
|
||||
{
|
||||
@@ -84,7 +84,7 @@ public class UserStore :
|
||||
};
|
||||
|
||||
var result = _userRepository.UpdateUser(userDb);
|
||||
return result == 1 ? IdentityResult.Success : IdentityResult.Failed();
|
||||
return Task.FromResult(result == 1 ? IdentityResult.Success : IdentityResult.Failed());
|
||||
}
|
||||
|
||||
public Task<IdentityResult> DeleteAsync(ApplicationUser<Guid> user, CancellationToken cancellationToken)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
public class CurrencyRateViewModel: BaseViewModel
|
||||
{
|
||||
public string Currency { get; set; }
|
||||
public string Currency { get; set; } = null!;
|
||||
public DateTime DateTime { get; set; }
|
||||
public int Quantity { get; set; }
|
||||
public decimal Rate { get; set; }
|
||||
|
||||
Reference in New Issue
Block a user