From e9d4053e657ffc8de7251c7833a770817d3a0581 Mon Sep 17 00:00:00 2001 From: Alexandr Sulimov Date: Wed, 21 Jun 2023 17:56:00 +0300 Subject: [PATCH] fix --- .../Extensions/DateTimeExtensions.cs | 19 + .../Account/AccountMotionRepository.cs | 13 + .../Account/AccountRepository.cs | 20 +- .../Account/IAccountMotionRepository.cs | 1 + .../Account/IAccountyRepository.cs | 1 + .../Currency/CurrencyRepository.cs | 5 +- MyOffice.DbContext/AppDbContext.cs | 8 + MyOffice.DbContext/RepositoryInitializer.cs | 4 + ...0230617113630_MotionAccountFix.Designer.cs | 533 +++++++++++++++ .../20230617113630_MotionAccountFix.cs | 75 +++ ...230617114210_MotionAccountFix2.Designer.cs | 606 +++++++++++++++++ .../20230617114210_MotionAccountFix2.cs | 73 +++ .../20230621082718_MotionPrec.Designer.cs | 607 +++++++++++++++++ .../Migrations/20230621082718_MotionPrec.cs | 36 ++ .../20230621083359_MotionPrec2.Designer.cs | 607 +++++++++++++++++ .../Migrations/20230621083359_MotionPrec2.cs | 40 ++ .../20230621083446_MotionPrec3.Designer.cs | 608 ++++++++++++++++++ .../Migrations/20230621083446_MotionPrec3.cs | 38 ++ .../Migrations/AppDbContextModelSnapshot.cs | 12 +- MyOffice.SPA/src/app/api-routes.ts | 1 + .../app/core/interceptor/error.interceptor.ts | 8 +- .../update.date.http.interceptor .ts | 11 +- .../app/layout/sidebar/sidebar.component.ts | 1 + .../app/pages/accounts/account.component.html | 70 +- .../app/pages/accounts/account.component.ts | 116 ++-- .../accounts/account.list.component.html | 18 + .../accounts/account.list.component.scss | 0 .../pages/accounts/account.list.component.ts | 51 ++ .../app/pages/accounts/motion.component.html | 35 +- .../app/pages/accounts/motion.component.ts | 47 +- .../src/app/pages/pages-routing.module.ts | 2 +- MyOffice.SPA/src/app/pages/pages.module.ts | 2 + .../settings/currency/currency.component.html | 16 +- .../settings/currency/currency.component.ts | 6 +- .../currency/rate.currency.component.html | 18 +- .../currency/rate.currency.component.ts | 14 +- .../app/services/account.category.service.ts | 5 + MyOffice.Services/Account/AccountService.cs | 66 +- MyOffice.Services/Currency/CurrencyService.cs | 51 +- .../Currency/Domain/AddCurrencyStatus.cs | 16 - .../Currency/Domain/CurrencyAddRateStatus.cs | 8 + .../Currency/Domain/CurrencyAddStatus.cs | 9 + .../Currency/Domain/CurrencyEdit.cs | 7 + .../Currency/Domain/CurrencyEditStatus.cs | 8 + MyOffice.Web/Controllers/AccountController.cs | 48 +- .../Controllers/CurrencyController.cs | 39 +- MyOffice.Web/Controllers/MotionController.cs | 15 +- .../Controllers/SettingsAccountController.cs | 25 +- .../Controllers/WeatherForecastController.cs | 47 -- .../AccountMotion/AccountMotionViewModel.cs | 8 +- .../Models/Currency/CurrencyEditModel.cs | 10 + .../Models/Currency/CurrencyViewModel.cs | 4 + .../Models/Motion/AccountMotionViewModel.cs | 33 + .../Models/Motion/AccountMotionsGetModel.cs | 12 + .../Models/WeatherForecast/WeatherForecast.cs | 12 - 55 files changed, 3883 insertions(+), 262 deletions(-) create mode 100644 MyOffice.Core/Extensions/DateTimeExtensions.cs create mode 100644 MyOffice.Migration.Postgres/Migrations/20230617113630_MotionAccountFix.Designer.cs create mode 100644 MyOffice.Migration.Postgres/Migrations/20230617113630_MotionAccountFix.cs create mode 100644 MyOffice.Migration.Postgres/Migrations/20230617114210_MotionAccountFix2.Designer.cs create mode 100644 MyOffice.Migration.Postgres/Migrations/20230617114210_MotionAccountFix2.cs create mode 100644 MyOffice.Migration.Postgres/Migrations/20230621082718_MotionPrec.Designer.cs create mode 100644 MyOffice.Migration.Postgres/Migrations/20230621082718_MotionPrec.cs create mode 100644 MyOffice.Migration.Postgres/Migrations/20230621083359_MotionPrec2.Designer.cs create mode 100644 MyOffice.Migration.Postgres/Migrations/20230621083359_MotionPrec2.cs create mode 100644 MyOffice.Migration.Postgres/Migrations/20230621083446_MotionPrec3.Designer.cs create mode 100644 MyOffice.Migration.Postgres/Migrations/20230621083446_MotionPrec3.cs create mode 100644 MyOffice.SPA/src/app/pages/accounts/account.list.component.html create mode 100644 MyOffice.SPA/src/app/pages/accounts/account.list.component.scss create mode 100644 MyOffice.SPA/src/app/pages/accounts/account.list.component.ts delete mode 100644 MyOffice.Services/Currency/Domain/AddCurrencyStatus.cs create mode 100644 MyOffice.Services/Currency/Domain/CurrencyAddRateStatus.cs create mode 100644 MyOffice.Services/Currency/Domain/CurrencyAddStatus.cs create mode 100644 MyOffice.Services/Currency/Domain/CurrencyEdit.cs create mode 100644 MyOffice.Services/Currency/Domain/CurrencyEditStatus.cs delete mode 100644 MyOffice.Web/Controllers/WeatherForecastController.cs create mode 100644 MyOffice.Web/Models/Currency/CurrencyEditModel.cs create mode 100644 MyOffice.Web/Models/Motion/AccountMotionViewModel.cs create mode 100644 MyOffice.Web/Models/Motion/AccountMotionsGetModel.cs delete mode 100644 MyOffice.Web/Models/WeatherForecast/WeatherForecast.cs diff --git a/MyOffice.Core/Extensions/DateTimeExtensions.cs b/MyOffice.Core/Extensions/DateTimeExtensions.cs new file mode 100644 index 0000000..8b22231 --- /dev/null +++ b/MyOffice.Core/Extensions/DateTimeExtensions.cs @@ -0,0 +1,19 @@ +namespace MyOffice.Core.Extensions; + +public static class DateTimeExtensions +{ + public static DateTime StartOfDay(this DateTime dateTime) + { + return dateTime.Date; + } + + public static DateTime EndOfDay(this DateTime dateTime) + { + return dateTime.AddDays(1).AddTicks(-1); + } + + public static DateTime ToUtc(this DateTime dateTime) + { + return new DateTime(dateTime.Ticks, DateTimeKind.Utc); + } +} \ No newline at end of file diff --git a/MyOffice.Data.Repositories/Account/AccountMotionRepository.cs b/MyOffice.Data.Repositories/Account/AccountMotionRepository.cs index 542468c..041594a 100644 --- a/MyOffice.Data.Repositories/Account/AccountMotionRepository.cs +++ b/MyOffice.Data.Repositories/Account/AccountMotionRepository.cs @@ -1,5 +1,6 @@ namespace MyOffice.Data.Repositories.Account; +using Microsoft.EntityFrameworkCore; using Models.Accounts; public class AccountMotionRepository : AppRepository, IAccountMotionRepository @@ -8,4 +9,16 @@ public class AccountMotionRepository : AppRepository, IAccountMot { return AddBase(accountMotion) > 0; } + + public List GetByAccount(Guid accountId, DateTime dateFrom, DateTime dateTo) + { + return _context + .AccountMotions + .Include(x => x.Motion) + .ThenInclude(x => x.MotionGlobal) + .Where(x => x.AccountId == accountId && x.DateTime >= dateFrom && x.DateTime <= dateTo) + .OrderByDescending(x => x.DateTime) + .ThenByDescending(x => x.CreatedOn) + .ToList(); + } } \ No newline at end of file diff --git a/MyOffice.Data.Repositories/Account/AccountRepository.cs b/MyOffice.Data.Repositories/Account/AccountRepository.cs index 4d08dde..4b2f5ab 100644 --- a/MyOffice.Data.Repositories/Account/AccountRepository.cs +++ b/MyOffice.Data.Repositories/Account/AccountRepository.cs @@ -43,11 +43,29 @@ public class AccountRepository : AppRepository, IAccountRepository { Account = x, TotalPlus = x.Motions!.Sum(m => m.AmountPlus), - TotalMinus = x.Motions!.Sum(m => m.AmountPlus), + TotalMinus = x.Motions!.Sum(m => m.AmountMinus), }) .ToList(); } + public AccountDetailed? GetByIdDetailed(Guid userId, Guid id) + { + return _context.Accounts! + .Include(x => x.CurrencyGlobal) + .Include(x => x.Categories)! + .ThenInclude(x => x.Category) + .Include(x => x.AccessRights)! + .ThenInclude(x => x.User) + .Where(x => x.Id == id && x.AccessRights!.Any(a => a.UserId == userId)) + .Select(x => new AccountDetailed + { + Account = x, + TotalPlus = x.Motions!.Sum(m => m.AmountPlus), + TotalMinus = x.Motions!.Sum(m => m.AmountMinus), + }) + .FirstOrDefault(); + } + public bool Add(Account account) { return AddBase(account) > 0; diff --git a/MyOffice.Data.Repositories/Account/IAccountMotionRepository.cs b/MyOffice.Data.Repositories/Account/IAccountMotionRepository.cs index 2fc94da..8ca3325 100644 --- a/MyOffice.Data.Repositories/Account/IAccountMotionRepository.cs +++ b/MyOffice.Data.Repositories/Account/IAccountMotionRepository.cs @@ -5,4 +5,5 @@ using Models.Accounts; public interface IAccountMotionRepository { bool Add(AccountMotion accountMotion); + List GetByAccount(Guid accountId, DateTime dateFrom, DateTime dateTo); } \ No newline at end of file diff --git a/MyOffice.Data.Repositories/Account/IAccountyRepository.cs b/MyOffice.Data.Repositories/Account/IAccountyRepository.cs index a34a55a..f62ce3e 100644 --- a/MyOffice.Data.Repositories/Account/IAccountyRepository.cs +++ b/MyOffice.Data.Repositories/Account/IAccountyRepository.cs @@ -7,6 +7,7 @@ public interface IAccountRepository List GetAll(Guid userId); List GetByCategory(Guid userId, Guid categoryId); List GetByCategoryDetailed(Guid userId, Guid categoryId); + AccountDetailed? GetByIdDetailed(Guid userId, Guid id); bool Add(Account account); Account? Get(Guid userId, Guid id); bool Update(Account account); diff --git a/MyOffice.Data.Repositories/Currency/CurrencyRepository.cs b/MyOffice.Data.Repositories/Currency/CurrencyRepository.cs index 7b86e2c..3543516 100644 --- a/MyOffice.Data.Repositories/Currency/CurrencyRepository.cs +++ b/MyOffice.Data.Repositories/Currency/CurrencyRepository.cs @@ -16,7 +16,10 @@ public class CurrencyRepository : AppRepository, ICurrencyRepository public Currency? Get(Guid userId, Guid id) { - return _context.Currencies.FirstOrDefault(x => x.Id == id && x.UserId == userId); + return _context + .Currencies + .Include(x => x.CurrencyGlobal) + .FirstOrDefault(x => x.Id == id && x.UserId == userId); } public Currency? GetByGlobalCurrency(Guid userId, string globalCurrencyId) diff --git a/MyOffice.DbContext/AppDbContext.cs b/MyOffice.DbContext/AppDbContext.cs index 04c6598..96b2ed5 100644 --- a/MyOffice.DbContext/AppDbContext.cs +++ b/MyOffice.DbContext/AppDbContext.cs @@ -205,5 +205,13 @@ public class AppDbContext : DbContext .HasOne(x => x.Account) .WithMany(x => x.Motions) .HasForeignKey(x => x.AccountId); + + modelBuilder.Entity() + .Property(x => x.AmountMinus) + .HasPrecision(18, 6); + + modelBuilder.Entity() + .Property(x => x.AmountPlus) + .HasPrecision(18, 6); } } \ No newline at end of file diff --git a/MyOffice.DbContext/RepositoryInitializer.cs b/MyOffice.DbContext/RepositoryInitializer.cs index b8b1ff5..5adc450 100644 --- a/MyOffice.DbContext/RepositoryInitializer.cs +++ b/MyOffice.DbContext/RepositoryInitializer.cs @@ -35,6 +35,10 @@ public class RepositoryInitializer new() { Id = "EUR", DefaultQuantity = 1, Symbol = "€", Name = "Euros" }, new() { Id = "GBP", DefaultQuantity = 1, Symbol = "£", Name = "British pounds sterling" }, new() { Id = "RUB", DefaultQuantity = 10, Symbol = "₽", Name = "Russia Ruble" }, + new() { Id = "BTC", DefaultQuantity = 10, Symbol = "btc", Name = "Bitcoin" }, + new() { Id = "ETH", DefaultQuantity = 10, Symbol = "eth", Name = "Ethereum" }, + new() { Id = "TON", DefaultQuantity = 10, Symbol = "ton", Name = "TON" }, + new() { Id = "OTHER", DefaultQuantity = 1, Symbol = "₽", Name = "Other" }, }; var currencyGlobals = dbContext.CurrencyGlobals.ToList(); diff --git a/MyOffice.Migration.Postgres/Migrations/20230617113630_MotionAccountFix.Designer.cs b/MyOffice.Migration.Postgres/Migrations/20230617113630_MotionAccountFix.Designer.cs new file mode 100644 index 0000000..87466e7 --- /dev/null +++ b/MyOffice.Migration.Postgres/Migrations/20230617113630_MotionAccountFix.Designer.cs @@ -0,0 +1,533 @@ +// +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("20230617113630_MotionAccountFix")] + partial class MotionAccountFix + { + /// + 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("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CurrencyGlobalId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("CurrencyGlobalId"); + + b.ToTable("Accounts"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Accounts.AccountAccess", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AccountId") + .HasColumnType("uuid"); + + b.Property("IsAllowManage") + .HasColumnType("boolean"); + + b.Property("IsAllowRead") + .HasColumnType("boolean"); + + b.Property("IsAllowWrite") + .HasColumnType("boolean"); + + b.Property("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("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AccountId") + .HasColumnType("uuid"); + + b.Property("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("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AccountCategories"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Currencies.Currency", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CurrencyGlobalId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("ShortName") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("CurrencyGlobalId"); + + b.HasIndex("UserId"); + + b.ToTable("Currencies"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Currencies.CurrencyGlobal", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("DefaultQuantity") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Symbol") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("CurrencyGlobals"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Currencies.CurrencyRate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CurrencyId") + .HasColumnType("uuid"); + + b.Property("DateTime") + .HasColumnType("timestamp with time zone"); + + b.Property("Quantity") + .HasColumnType("integer"); + + b.Property("Rate") + .HasColumnType("numeric"); + + b.HasKey("Id"); + + b.HasIndex("CurrencyId"); + + b.ToTable("CurrencyRates"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Motions.MotionAccount", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CategoryId") + .HasColumnType("uuid"); + + b.Property("MotionGlobalId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("CategoryId"); + + b.HasIndex("MotionGlobalId"); + + b.ToTable("Motions"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Motions.MotionCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("MotionCategories"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Motions.MotionGlobal", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("GlobalMotions"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Users.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CurrencyId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Email") + .IsRequired() + .HasColumnType("text") + .UseCollation("my_ci_collation"); + + b.Property("FirstName") + .HasColumnType("text"); + + b.Property("FullName") + .HasColumnType("text"); + + b.Property("IsEmailConfirmed") + .HasColumnType("boolean"); + + b.Property("LastName") + .HasColumnType("text"); + + b.Property("PasswordHash") + .IsRequired() + .HasColumnType("text"); + + b.Property("Phone") + .HasColumnType("text"); + + b.Property("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("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedOn") + .HasColumnType("timestamp with time zone"); + + b.Property("Email") + .IsRequired() + .HasColumnType("text") + .UseCollation("my_ci_collation"); + + b.Property("ExternalId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Provider") + .IsRequired() + .HasColumnType("text") + .UseCollation("my_ci_collation"); + + b.Property("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.Currencies.Currency", b => + { + b.HasOne("MyOffice.Data.Models.Currencies.CurrencyGlobal", "CurrencyGlobal") + .WithMany("Currencies") + .HasForeignKey("CurrencyGlobalId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MyOffice.Data.Models.Users.User", "User") + .WithMany("Currencies") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("CurrencyGlobal"); + + 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.Motions.MotionAccount", b => + { + b.HasOne("MyOffice.Data.Models.Motions.MotionCategory", "Category") + .WithMany("Motions") + .HasForeignKey("CategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MyOffice.Data.Models.Motions.MotionGlobal", "MotionGlobal") + .WithMany("Motions") + .HasForeignKey("MotionGlobalId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Category"); + + b.Navigation("MotionGlobal"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Motions.MotionCategory", b => + { + b.HasOne("MyOffice.Data.Models.Users.User", "User") + .WithMany("MotionCategories") + .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"); + }); + + 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.Motions.MotionCategory", b => + { + b.Navigation("Motions"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Motions.MotionGlobal", b => + { + b.Navigation("Motions"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Users.User", b => + { + b.Navigation("AccountAccess"); + + b.Navigation("AccountCategories"); + + b.Navigation("Currencies"); + + b.Navigation("MotionCategories"); + + b.Navigation("UserClaims"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/MyOffice.Migration.Postgres/Migrations/20230617113630_MotionAccountFix.cs b/MyOffice.Migration.Postgres/Migrations/20230617113630_MotionAccountFix.cs new file mode 100644 index 0000000..6e1daf6 --- /dev/null +++ b/MyOffice.Migration.Postgres/Migrations/20230617113630_MotionAccountFix.cs @@ -0,0 +1,75 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace MyOffice.Migrations.Postgres.Migrations +{ + /// + public partial class MotionAccountFix : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "AccountMotions"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "AccountMotions", + columns: table => new + { + Id = table.Column(type: "bigint", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + AccountId = table.Column(type: "uuid", nullable: false), + MotionId = table.Column(type: "integer", nullable: false), + AmountMinus = table.Column(type: "numeric", nullable: false), + AmountPlus = table.Column(type: "numeric", nullable: false), + CreatedOn = table.Column(type: "timestamp with time zone", nullable: false), + DateTime = table.Column(type: "timestamp with time zone", nullable: false), + Description = table.Column(type: "text", nullable: true), + UserId = table.Column(type: "uuid", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AccountMotions", x => x.Id); + table.ForeignKey( + name: "FK_AccountMotions_Accounts_AccountId", + column: x => x.AccountId, + principalTable: "Accounts", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_AccountMotions_Motions_MotionId", + column: x => x.MotionId, + principalTable: "Motions", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_AccountMotions_Users_UserId", + column: x => x.UserId, + principalTable: "Users", + principalColumn: "Id"); + }); + + migrationBuilder.CreateIndex( + name: "IX_AccountMotions_AccountId", + table: "AccountMotions", + column: "AccountId"); + + migrationBuilder.CreateIndex( + name: "IX_AccountMotions_MotionId", + table: "AccountMotions", + column: "MotionId"); + + migrationBuilder.CreateIndex( + name: "IX_AccountMotions_UserId", + table: "AccountMotions", + column: "UserId"); + } + } +} diff --git a/MyOffice.Migration.Postgres/Migrations/20230617114210_MotionAccountFix2.Designer.cs b/MyOffice.Migration.Postgres/Migrations/20230617114210_MotionAccountFix2.Designer.cs new file mode 100644 index 0000000..a3877a3 --- /dev/null +++ b/MyOffice.Migration.Postgres/Migrations/20230617114210_MotionAccountFix2.Designer.cs @@ -0,0 +1,606 @@ +// +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("20230617114210_MotionAccountFix2")] + partial class MotionAccountFix2 + { + /// + 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("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CurrencyGlobalId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("CurrencyGlobalId"); + + b.ToTable("Accounts"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Accounts.AccountAccess", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AccountId") + .HasColumnType("uuid"); + + b.Property("IsAllowManage") + .HasColumnType("boolean"); + + b.Property("IsAllowRead") + .HasColumnType("boolean"); + + b.Property("IsAllowWrite") + .HasColumnType("boolean"); + + b.Property("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("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AccountId") + .HasColumnType("uuid"); + + b.Property("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("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AccountCategories"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Accounts.AccountMotion", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AccountId") + .HasColumnType("uuid"); + + b.Property("AmountMinus") + .HasColumnType("numeric"); + + b.Property("AmountPlus") + .HasColumnType("numeric"); + + b.Property("CreatedOn") + .HasColumnType("timestamp with time zone"); + + b.Property("DateTime") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("MotionId") + .HasColumnType("integer"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("AccountId"); + + b.HasIndex("MotionId"); + + b.HasIndex("UserId"); + + b.ToTable("AccountMotions"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Currencies.Currency", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CurrencyGlobalId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("ShortName") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("CurrencyGlobalId"); + + b.HasIndex("UserId"); + + b.ToTable("Currencies"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Currencies.CurrencyGlobal", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("DefaultQuantity") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Symbol") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("CurrencyGlobals"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Currencies.CurrencyRate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CurrencyId") + .HasColumnType("uuid"); + + b.Property("DateTime") + .HasColumnType("timestamp with time zone"); + + b.Property("Quantity") + .HasColumnType("integer"); + + b.Property("Rate") + .HasColumnType("numeric"); + + b.HasKey("Id"); + + b.HasIndex("CurrencyId"); + + b.ToTable("CurrencyRates"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Motions.MotionAccount", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CategoryId") + .HasColumnType("uuid"); + + b.Property("MotionGlobalId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("CategoryId"); + + b.HasIndex("MotionGlobalId"); + + b.ToTable("Motions"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Motions.MotionCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("MotionCategories"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Motions.MotionGlobal", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("GlobalMotions"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Users.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CurrencyId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Email") + .IsRequired() + .HasColumnType("text") + .UseCollation("my_ci_collation"); + + b.Property("FirstName") + .HasColumnType("text"); + + b.Property("FullName") + .HasColumnType("text"); + + b.Property("IsEmailConfirmed") + .HasColumnType("boolean"); + + b.Property("LastName") + .HasColumnType("text"); + + b.Property("PasswordHash") + .IsRequired() + .HasColumnType("text"); + + b.Property("Phone") + .HasColumnType("text"); + + b.Property("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("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedOn") + .HasColumnType("timestamp with time zone"); + + b.Property("Email") + .IsRequired() + .HasColumnType("text") + .UseCollation("my_ci_collation"); + + b.Property("ExternalId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Provider") + .IsRequired() + .HasColumnType("text") + .UseCollation("my_ci_collation"); + + b.Property("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.AccountMotion", b => + { + b.HasOne("MyOffice.Data.Models.Accounts.Account", "Account") + .WithMany("Motions") + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MyOffice.Data.Models.Motions.MotionAccount", "Motion") + .WithMany("Motions") + .HasForeignKey("MotionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MyOffice.Data.Models.Users.User", null) + .WithMany("AccountMotions") + .HasForeignKey("UserId"); + + b.Navigation("Account"); + + b.Navigation("Motion"); + }); + + 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.Users.User", "User") + .WithMany("Currencies") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("CurrencyGlobal"); + + 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.Motions.MotionAccount", b => + { + b.HasOne("MyOffice.Data.Models.Motions.MotionCategory", "Category") + .WithMany("Motions") + .HasForeignKey("CategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MyOffice.Data.Models.Motions.MotionGlobal", "MotionGlobal") + .WithMany("Motions") + .HasForeignKey("MotionGlobalId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Category"); + + b.Navigation("MotionGlobal"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Motions.MotionCategory", b => + { + b.HasOne("MyOffice.Data.Models.Users.User", "User") + .WithMany("MotionCategories") + .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.Motions.MotionAccount", b => + { + b.Navigation("Motions"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Motions.MotionCategory", b => + { + b.Navigation("Motions"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Motions.MotionGlobal", b => + { + b.Navigation("Motions"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Users.User", b => + { + b.Navigation("AccountAccess"); + + b.Navigation("AccountCategories"); + + b.Navigation("AccountMotions"); + + b.Navigation("Currencies"); + + b.Navigation("MotionCategories"); + + b.Navigation("UserClaims"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/MyOffice.Migration.Postgres/Migrations/20230617114210_MotionAccountFix2.cs b/MyOffice.Migration.Postgres/Migrations/20230617114210_MotionAccountFix2.cs new file mode 100644 index 0000000..c574131 --- /dev/null +++ b/MyOffice.Migration.Postgres/Migrations/20230617114210_MotionAccountFix2.cs @@ -0,0 +1,73 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace MyOffice.Migrations.Postgres.Migrations +{ + /// + public partial class MotionAccountFix2 : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "AccountMotions", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + CreatedOn = table.Column(type: "timestamp with time zone", nullable: false), + DateTime = table.Column(type: "timestamp with time zone", nullable: false), + MotionId = table.Column(type: "integer", nullable: false), + AccountId = table.Column(type: "uuid", nullable: false), + Description = table.Column(type: "text", nullable: true), + AmountPlus = table.Column(type: "numeric", nullable: false), + AmountMinus = table.Column(type: "numeric", nullable: false), + UserId = table.Column(type: "uuid", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AccountMotions", x => x.Id); + table.ForeignKey( + name: "FK_AccountMotions_Accounts_AccountId", + column: x => x.AccountId, + principalTable: "Accounts", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_AccountMotions_Motions_MotionId", + column: x => x.MotionId, + principalTable: "Motions", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_AccountMotions_Users_UserId", + column: x => x.UserId, + principalTable: "Users", + principalColumn: "Id"); + }); + + migrationBuilder.CreateIndex( + name: "IX_AccountMotions_AccountId", + table: "AccountMotions", + column: "AccountId"); + + migrationBuilder.CreateIndex( + name: "IX_AccountMotions_MotionId", + table: "AccountMotions", + column: "MotionId"); + + migrationBuilder.CreateIndex( + name: "IX_AccountMotions_UserId", + table: "AccountMotions", + column: "UserId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "AccountMotions"); + } + } +} diff --git a/MyOffice.Migration.Postgres/Migrations/20230621082718_MotionPrec.Designer.cs b/MyOffice.Migration.Postgres/Migrations/20230621082718_MotionPrec.Designer.cs new file mode 100644 index 0000000..d35741b --- /dev/null +++ b/MyOffice.Migration.Postgres/Migrations/20230621082718_MotionPrec.Designer.cs @@ -0,0 +1,607 @@ +// +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("20230621082718_MotionPrec")] + partial class MotionPrec + { + /// + 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("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CurrencyGlobalId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("CurrencyGlobalId"); + + b.ToTable("Accounts"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Accounts.AccountAccess", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AccountId") + .HasColumnType("uuid"); + + b.Property("IsAllowManage") + .HasColumnType("boolean"); + + b.Property("IsAllowRead") + .HasColumnType("boolean"); + + b.Property("IsAllowWrite") + .HasColumnType("boolean"); + + b.Property("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("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AccountId") + .HasColumnType("uuid"); + + b.Property("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("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AccountCategories"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Accounts.AccountMotion", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AccountId") + .HasColumnType("uuid"); + + b.Property("AmountMinus") + .HasPrecision(6) + .HasColumnType("numeric(6)"); + + b.Property("AmountPlus") + .HasColumnType("numeric"); + + b.Property("CreatedOn") + .HasColumnType("timestamp with time zone"); + + b.Property("DateTime") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("MotionId") + .HasColumnType("integer"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("AccountId"); + + b.HasIndex("MotionId"); + + b.HasIndex("UserId"); + + b.ToTable("AccountMotions"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Currencies.Currency", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CurrencyGlobalId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("ShortName") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("CurrencyGlobalId"); + + b.HasIndex("UserId"); + + b.ToTable("Currencies"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Currencies.CurrencyGlobal", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("DefaultQuantity") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Symbol") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("CurrencyGlobals"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Currencies.CurrencyRate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CurrencyId") + .HasColumnType("uuid"); + + b.Property("DateTime") + .HasColumnType("timestamp with time zone"); + + b.Property("Quantity") + .HasColumnType("integer"); + + b.Property("Rate") + .HasColumnType("numeric"); + + b.HasKey("Id"); + + b.HasIndex("CurrencyId"); + + b.ToTable("CurrencyRates"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Motions.MotionAccount", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CategoryId") + .HasColumnType("uuid"); + + b.Property("MotionGlobalId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("CategoryId"); + + b.HasIndex("MotionGlobalId"); + + b.ToTable("Motions"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Motions.MotionCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("MotionCategories"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Motions.MotionGlobal", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("GlobalMotions"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Users.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CurrencyId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Email") + .IsRequired() + .HasColumnType("text") + .UseCollation("my_ci_collation"); + + b.Property("FirstName") + .HasColumnType("text"); + + b.Property("FullName") + .HasColumnType("text"); + + b.Property("IsEmailConfirmed") + .HasColumnType("boolean"); + + b.Property("LastName") + .HasColumnType("text"); + + b.Property("PasswordHash") + .IsRequired() + .HasColumnType("text"); + + b.Property("Phone") + .HasColumnType("text"); + + b.Property("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("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedOn") + .HasColumnType("timestamp with time zone"); + + b.Property("Email") + .IsRequired() + .HasColumnType("text") + .UseCollation("my_ci_collation"); + + b.Property("ExternalId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Provider") + .IsRequired() + .HasColumnType("text") + .UseCollation("my_ci_collation"); + + b.Property("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.AccountMotion", b => + { + b.HasOne("MyOffice.Data.Models.Accounts.Account", "Account") + .WithMany("Motions") + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MyOffice.Data.Models.Motions.MotionAccount", "Motion") + .WithMany("Motions") + .HasForeignKey("MotionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MyOffice.Data.Models.Users.User", null) + .WithMany("AccountMotions") + .HasForeignKey("UserId"); + + b.Navigation("Account"); + + b.Navigation("Motion"); + }); + + 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.Users.User", "User") + .WithMany("Currencies") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("CurrencyGlobal"); + + 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.Motions.MotionAccount", b => + { + b.HasOne("MyOffice.Data.Models.Motions.MotionCategory", "Category") + .WithMany("Motions") + .HasForeignKey("CategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MyOffice.Data.Models.Motions.MotionGlobal", "MotionGlobal") + .WithMany("Motions") + .HasForeignKey("MotionGlobalId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Category"); + + b.Navigation("MotionGlobal"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Motions.MotionCategory", b => + { + b.HasOne("MyOffice.Data.Models.Users.User", "User") + .WithMany("MotionCategories") + .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.Motions.MotionAccount", b => + { + b.Navigation("Motions"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Motions.MotionCategory", b => + { + b.Navigation("Motions"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Motions.MotionGlobal", b => + { + b.Navigation("Motions"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Users.User", b => + { + b.Navigation("AccountAccess"); + + b.Navigation("AccountCategories"); + + b.Navigation("AccountMotions"); + + b.Navigation("Currencies"); + + b.Navigation("MotionCategories"); + + b.Navigation("UserClaims"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/MyOffice.Migration.Postgres/Migrations/20230621082718_MotionPrec.cs b/MyOffice.Migration.Postgres/Migrations/20230621082718_MotionPrec.cs new file mode 100644 index 0000000..ca11cd1 --- /dev/null +++ b/MyOffice.Migration.Postgres/Migrations/20230621082718_MotionPrec.cs @@ -0,0 +1,36 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace MyOffice.Migrations.Postgres.Migrations +{ + /// + public partial class MotionPrec : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "AmountMinus", + table: "AccountMotions", + type: "numeric(6)", + precision: 6, + nullable: false, + oldClrType: typeof(decimal), + oldType: "numeric"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "AmountMinus", + table: "AccountMotions", + type: "numeric", + nullable: false, + oldClrType: typeof(decimal), + oldType: "numeric(6)", + oldPrecision: 6); + } + } +} diff --git a/MyOffice.Migration.Postgres/Migrations/20230621083359_MotionPrec2.Designer.cs b/MyOffice.Migration.Postgres/Migrations/20230621083359_MotionPrec2.Designer.cs new file mode 100644 index 0000000..b9ac160 --- /dev/null +++ b/MyOffice.Migration.Postgres/Migrations/20230621083359_MotionPrec2.Designer.cs @@ -0,0 +1,607 @@ +// +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("20230621083359_MotionPrec2")] + partial class MotionPrec2 + { + /// + 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("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CurrencyGlobalId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("CurrencyGlobalId"); + + b.ToTable("Accounts"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Accounts.AccountAccess", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AccountId") + .HasColumnType("uuid"); + + b.Property("IsAllowManage") + .HasColumnType("boolean"); + + b.Property("IsAllowRead") + .HasColumnType("boolean"); + + b.Property("IsAllowWrite") + .HasColumnType("boolean"); + + b.Property("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("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AccountId") + .HasColumnType("uuid"); + + b.Property("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("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AccountCategories"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Accounts.AccountMotion", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AccountId") + .HasColumnType("uuid"); + + b.Property("AmountMinus") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("AmountPlus") + .HasColumnType("numeric"); + + b.Property("CreatedOn") + .HasColumnType("timestamp with time zone"); + + b.Property("DateTime") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("MotionId") + .HasColumnType("integer"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("AccountId"); + + b.HasIndex("MotionId"); + + b.HasIndex("UserId"); + + b.ToTable("AccountMotions"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Currencies.Currency", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CurrencyGlobalId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("ShortName") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("CurrencyGlobalId"); + + b.HasIndex("UserId"); + + b.ToTable("Currencies"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Currencies.CurrencyGlobal", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("DefaultQuantity") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Symbol") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("CurrencyGlobals"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Currencies.CurrencyRate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CurrencyId") + .HasColumnType("uuid"); + + b.Property("DateTime") + .HasColumnType("timestamp with time zone"); + + b.Property("Quantity") + .HasColumnType("integer"); + + b.Property("Rate") + .HasColumnType("numeric"); + + b.HasKey("Id"); + + b.HasIndex("CurrencyId"); + + b.ToTable("CurrencyRates"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Motions.MotionAccount", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CategoryId") + .HasColumnType("uuid"); + + b.Property("MotionGlobalId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("CategoryId"); + + b.HasIndex("MotionGlobalId"); + + b.ToTable("Motions"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Motions.MotionCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("MotionCategories"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Motions.MotionGlobal", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("GlobalMotions"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Users.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CurrencyId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Email") + .IsRequired() + .HasColumnType("text") + .UseCollation("my_ci_collation"); + + b.Property("FirstName") + .HasColumnType("text"); + + b.Property("FullName") + .HasColumnType("text"); + + b.Property("IsEmailConfirmed") + .HasColumnType("boolean"); + + b.Property("LastName") + .HasColumnType("text"); + + b.Property("PasswordHash") + .IsRequired() + .HasColumnType("text"); + + b.Property("Phone") + .HasColumnType("text"); + + b.Property("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("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedOn") + .HasColumnType("timestamp with time zone"); + + b.Property("Email") + .IsRequired() + .HasColumnType("text") + .UseCollation("my_ci_collation"); + + b.Property("ExternalId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Provider") + .IsRequired() + .HasColumnType("text") + .UseCollation("my_ci_collation"); + + b.Property("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.AccountMotion", b => + { + b.HasOne("MyOffice.Data.Models.Accounts.Account", "Account") + .WithMany("Motions") + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MyOffice.Data.Models.Motions.MotionAccount", "Motion") + .WithMany("Motions") + .HasForeignKey("MotionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MyOffice.Data.Models.Users.User", null) + .WithMany("AccountMotions") + .HasForeignKey("UserId"); + + b.Navigation("Account"); + + b.Navigation("Motion"); + }); + + 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.Users.User", "User") + .WithMany("Currencies") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("CurrencyGlobal"); + + 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.Motions.MotionAccount", b => + { + b.HasOne("MyOffice.Data.Models.Motions.MotionCategory", "Category") + .WithMany("Motions") + .HasForeignKey("CategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MyOffice.Data.Models.Motions.MotionGlobal", "MotionGlobal") + .WithMany("Motions") + .HasForeignKey("MotionGlobalId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Category"); + + b.Navigation("MotionGlobal"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Motions.MotionCategory", b => + { + b.HasOne("MyOffice.Data.Models.Users.User", "User") + .WithMany("MotionCategories") + .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.Motions.MotionAccount", b => + { + b.Navigation("Motions"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Motions.MotionCategory", b => + { + b.Navigation("Motions"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Motions.MotionGlobal", b => + { + b.Navigation("Motions"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Users.User", b => + { + b.Navigation("AccountAccess"); + + b.Navigation("AccountCategories"); + + b.Navigation("AccountMotions"); + + b.Navigation("Currencies"); + + b.Navigation("MotionCategories"); + + b.Navigation("UserClaims"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/MyOffice.Migration.Postgres/Migrations/20230621083359_MotionPrec2.cs b/MyOffice.Migration.Postgres/Migrations/20230621083359_MotionPrec2.cs new file mode 100644 index 0000000..a9b9541 --- /dev/null +++ b/MyOffice.Migration.Postgres/Migrations/20230621083359_MotionPrec2.cs @@ -0,0 +1,40 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace MyOffice.Migrations.Postgres.Migrations +{ + /// + public partial class MotionPrec2 : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "AmountMinus", + table: "AccountMotions", + type: "numeric(18,6)", + precision: 18, + scale: 6, + nullable: false, + oldClrType: typeof(decimal), + oldType: "numeric(6,0)", + oldPrecision: 6); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "AmountMinus", + table: "AccountMotions", + type: "numeric(6,0)", + precision: 6, + nullable: false, + oldClrType: typeof(decimal), + oldType: "numeric(18,6)", + oldPrecision: 18, + oldScale: 6); + } + } +} diff --git a/MyOffice.Migration.Postgres/Migrations/20230621083446_MotionPrec3.Designer.cs b/MyOffice.Migration.Postgres/Migrations/20230621083446_MotionPrec3.Designer.cs new file mode 100644 index 0000000..80b20ac --- /dev/null +++ b/MyOffice.Migration.Postgres/Migrations/20230621083446_MotionPrec3.Designer.cs @@ -0,0 +1,608 @@ +// +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("20230621083446_MotionPrec3")] + partial class MotionPrec3 + { + /// + 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("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CurrencyGlobalId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("CurrencyGlobalId"); + + b.ToTable("Accounts"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Accounts.AccountAccess", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AccountId") + .HasColumnType("uuid"); + + b.Property("IsAllowManage") + .HasColumnType("boolean"); + + b.Property("IsAllowRead") + .HasColumnType("boolean"); + + b.Property("IsAllowWrite") + .HasColumnType("boolean"); + + b.Property("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("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AccountId") + .HasColumnType("uuid"); + + b.Property("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("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AccountCategories"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Accounts.AccountMotion", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AccountId") + .HasColumnType("uuid"); + + b.Property("AmountMinus") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("AmountPlus") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("CreatedOn") + .HasColumnType("timestamp with time zone"); + + b.Property("DateTime") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("MotionId") + .HasColumnType("integer"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("AccountId"); + + b.HasIndex("MotionId"); + + b.HasIndex("UserId"); + + b.ToTable("AccountMotions"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Currencies.Currency", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CurrencyGlobalId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("ShortName") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("CurrencyGlobalId"); + + b.HasIndex("UserId"); + + b.ToTable("Currencies"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Currencies.CurrencyGlobal", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("DefaultQuantity") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Symbol") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("CurrencyGlobals"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Currencies.CurrencyRate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CurrencyId") + .HasColumnType("uuid"); + + b.Property("DateTime") + .HasColumnType("timestamp with time zone"); + + b.Property("Quantity") + .HasColumnType("integer"); + + b.Property("Rate") + .HasColumnType("numeric"); + + b.HasKey("Id"); + + b.HasIndex("CurrencyId"); + + b.ToTable("CurrencyRates"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Motions.MotionAccount", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CategoryId") + .HasColumnType("uuid"); + + b.Property("MotionGlobalId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("CategoryId"); + + b.HasIndex("MotionGlobalId"); + + b.ToTable("Motions"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Motions.MotionCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("MotionCategories"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Motions.MotionGlobal", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("GlobalMotions"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Users.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CurrencyId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Email") + .IsRequired() + .HasColumnType("text") + .UseCollation("my_ci_collation"); + + b.Property("FirstName") + .HasColumnType("text"); + + b.Property("FullName") + .HasColumnType("text"); + + b.Property("IsEmailConfirmed") + .HasColumnType("boolean"); + + b.Property("LastName") + .HasColumnType("text"); + + b.Property("PasswordHash") + .IsRequired() + .HasColumnType("text"); + + b.Property("Phone") + .HasColumnType("text"); + + b.Property("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("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedOn") + .HasColumnType("timestamp with time zone"); + + b.Property("Email") + .IsRequired() + .HasColumnType("text") + .UseCollation("my_ci_collation"); + + b.Property("ExternalId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Provider") + .IsRequired() + .HasColumnType("text") + .UseCollation("my_ci_collation"); + + b.Property("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.AccountMotion", b => + { + b.HasOne("MyOffice.Data.Models.Accounts.Account", "Account") + .WithMany("Motions") + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MyOffice.Data.Models.Motions.MotionAccount", "Motion") + .WithMany("Motions") + .HasForeignKey("MotionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MyOffice.Data.Models.Users.User", null) + .WithMany("AccountMotions") + .HasForeignKey("UserId"); + + b.Navigation("Account"); + + b.Navigation("Motion"); + }); + + 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.Users.User", "User") + .WithMany("Currencies") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("CurrencyGlobal"); + + 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.Motions.MotionAccount", b => + { + b.HasOne("MyOffice.Data.Models.Motions.MotionCategory", "Category") + .WithMany("Motions") + .HasForeignKey("CategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MyOffice.Data.Models.Motions.MotionGlobal", "MotionGlobal") + .WithMany("Motions") + .HasForeignKey("MotionGlobalId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Category"); + + b.Navigation("MotionGlobal"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Motions.MotionCategory", b => + { + b.HasOne("MyOffice.Data.Models.Users.User", "User") + .WithMany("MotionCategories") + .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.Motions.MotionAccount", b => + { + b.Navigation("Motions"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Motions.MotionCategory", b => + { + b.Navigation("Motions"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Motions.MotionGlobal", b => + { + b.Navigation("Motions"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Users.User", b => + { + b.Navigation("AccountAccess"); + + b.Navigation("AccountCategories"); + + b.Navigation("AccountMotions"); + + b.Navigation("Currencies"); + + b.Navigation("MotionCategories"); + + b.Navigation("UserClaims"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/MyOffice.Migration.Postgres/Migrations/20230621083446_MotionPrec3.cs b/MyOffice.Migration.Postgres/Migrations/20230621083446_MotionPrec3.cs new file mode 100644 index 0000000..46a88f2 --- /dev/null +++ b/MyOffice.Migration.Postgres/Migrations/20230621083446_MotionPrec3.cs @@ -0,0 +1,38 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace MyOffice.Migrations.Postgres.Migrations +{ + /// + public partial class MotionPrec3 : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "AmountPlus", + table: "AccountMotions", + type: "numeric(18,6)", + precision: 18, + scale: 6, + nullable: false, + oldClrType: typeof(decimal), + oldType: "numeric"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "AmountPlus", + table: "AccountMotions", + type: "numeric", + nullable: false, + oldClrType: typeof(decimal), + oldType: "numeric(18,6)", + oldPrecision: 18, + oldScale: 6); + } + } +} diff --git a/MyOffice.Migration.Postgres/Migrations/AppDbContextModelSnapshot.cs b/MyOffice.Migration.Postgres/Migrations/AppDbContextModelSnapshot.cs index bf74d8e..eb3a564 100644 --- a/MyOffice.Migration.Postgres/Migrations/AppDbContextModelSnapshot.cs +++ b/MyOffice.Migration.Postgres/Migrations/AppDbContextModelSnapshot.cs @@ -121,20 +121,20 @@ namespace MyOffice.Migrations.Postgres.Migrations modelBuilder.Entity("MyOffice.Data.Models.Accounts.AccountMotion", b => { - b.Property("Id") + b.Property("Id") .ValueGeneratedOnAdd() - .HasColumnType("bigint"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + .HasColumnType("uuid"); b.Property("AccountId") .HasColumnType("uuid"); b.Property("AmountMinus") - .HasColumnType("numeric"); + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); b.Property("AmountPlus") - .HasColumnType("numeric"); + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); b.Property("CreatedOn") .HasColumnType("timestamp with time zone"); diff --git a/MyOffice.SPA/src/app/api-routes.ts b/MyOffice.SPA/src/app/api-routes.ts index 87d7473..52774b7 100644 --- a/MyOffice.SPA/src/app/api-routes.ts +++ b/MyOffice.SPA/src/app/api-routes.ts @@ -7,6 +7,7 @@ export class ApiRoutes { static GeneralCurrencies = '/api/general/currencies'; static SettingsCurrencies = '/api/settings/currencies'; + static SettingsCurrency = '/api/settings/currencies/:id'; static SettingsCurrenciesRate = '/api/settings/currencies/:id/rate'; static SettingsAccountCategories = '/api/settings/account-categories'; diff --git a/MyOffice.SPA/src/app/core/interceptor/error.interceptor.ts b/MyOffice.SPA/src/app/core/interceptor/error.interceptor.ts index af197b7..91e172a 100644 --- a/MyOffice.SPA/src/app/core/interceptor/error.interceptor.ts +++ b/MyOffice.SPA/src/app/core/interceptor/error.interceptor.ts @@ -24,10 +24,10 @@ export class ErrorInterceptor implements HttpInterceptor { this.authenticationService.logout(); location.reload(); } - - const error = err.error.message || err.statusText; - //return throwError(error); - return throwError(err.error || err); + console.log(err); + const error = err.message || err.error.message || err.statusText; + return throwError(error); + //return throwError(err.error || err); }) ); } diff --git a/MyOffice.SPA/src/app/core/interceptor/update.date.http.interceptor .ts b/MyOffice.SPA/src/app/core/interceptor/update.date.http.interceptor .ts index 9bc5db4..a75ee92 100644 --- a/MyOffice.SPA/src/app/core/interceptor/update.date.http.interceptor .ts +++ b/MyOffice.SPA/src/app/core/interceptor/update.date.http.interceptor .ts @@ -1,3 +1,4 @@ +// angular import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; import { HttpInterceptor } from '@angular/common/http'; @@ -5,6 +6,9 @@ import { HttpRequest } from '@angular/common/http'; import { HttpHandler } from '@angular/common/http'; import { HttpEvent } from '@angular/common/http'; +// libs +import * as moment from 'moment'; + @Injectable() export class UpdateDateHttpInterceptor implements HttpInterceptor { @@ -29,12 +33,7 @@ export class UpdateDateHttpInterceptor implements HttpInterceptor { for (const key of Object.keys(body)) { const value = body[key]; if (value instanceof Date) { - body[key] = new Date(Date.UTC(value.getFullYear(), - value.getMonth(), - value.getDate(), - value.getHours(), - value.getMinutes(), - value.getSeconds())); + body[key] = moment(value).utcOffset(0, true).format(); } else if (typeof value === 'object') { this.shiftDates(value); } diff --git a/MyOffice.SPA/src/app/layout/sidebar/sidebar.component.ts b/MyOffice.SPA/src/app/layout/sidebar/sidebar.component.ts index 6b5fb1c..3098240 100644 --- a/MyOffice.SPA/src/app/layout/sidebar/sidebar.component.ts +++ b/MyOffice.SPA/src/app/layout/sidebar/sidebar.component.ts @@ -86,6 +86,7 @@ export class SidebarComponent implements OnInit, OnDestroy { .getCategories() .subscribe(categories => { var accounts = this.sidebarItems.filter(x => x.id === 'accounts'); + accounts[0].submenu = []; for (var category of categories) { accounts[0].submenu.push({ path: '/account-category/' + category.id, diff --git a/MyOffice.SPA/src/app/pages/accounts/account.component.html b/MyOffice.SPA/src/app/pages/accounts/account.component.html index 6ee5f32..eba1f9f 100644 --- a/MyOffice.SPA/src/app/pages/accounts/account.component.html +++ b/MyOffice.SPA/src/app/pages/accounts/account.component.html @@ -1,30 +1,44 @@ -
-
-
- - - -
-
-
- - - - -
{{account.account.name}}
-
- {{account.rest}} - ({{account.account.currencyId}}) -
-
-
- - - - -
-
+ + + +

{{account.account.name}}

+

+ {{account.rest | number: '1.2-6'}} + ({{account.account.currencyId}}) +

+
+
+
+
+
+ + From + + YYYY/MM/DD + + + + Please enter rate date + + +
+
+ + To + + YYYY/MM/DD + + + + Please enter rate date + +
-
-
+ +
+ + + + + diff --git a/MyOffice.SPA/src/app/pages/accounts/account.component.ts b/MyOffice.SPA/src/app/pages/accounts/account.component.ts index 0000992..15da865 100644 --- a/MyOffice.SPA/src/app/pages/accounts/account.component.ts +++ b/MyOffice.SPA/src/app/pages/accounts/account.component.ts @@ -1,91 +1,99 @@ // angular import { Component } from '@angular/core'; +import { Input } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { ActivatedRoute } from '@angular/router'; +import { UntypedFormGroup } from '@angular/forms'; +import { Validators } from '@angular/forms'; +import { UntypedFormBuilder } from '@angular/forms'; +import { Output } from '@angular/core'; +import { EventEmitter } from '@angular/core'; // libs -import Swal from 'sweetalert2'; -import { MatDialog } from '@angular/material/dialog'; +import * as moment from 'moment'; // app -import { AccountCategoryService } from '../../services/account.category.service'; import { ApiRoutes } from '../../api-routes'; -import { AccountCategoryModel } from '../../model/account.category.model'; -import { SettingsAccountAddComponent } from '../settings/account/add.account.component'; -import { SettingsAccountEditComponent } from '../settings/account/edit.account.component'; -import { AccountModel } from '../../model/account.model'; import { AccountDetailedModel } from '../../model/account.detailed.model'; import { AccountMotionModel } from '../../model/account.motion'; @Component({ templateUrl: './account.component.html', styleUrls: ['./account.component.scss'], + selector: 'account' }) export class AccountComponent { - public accounts?: AccountDetailedModel[]; public motions?: AccountMotionModel[]; public newMotion: AccountMotionModel; + public form!: UntypedFormGroup; + @Input('account') account!: AccountDetailedModel; + @Input('expanded') expanded!: boolean; + + @Output() onUpdate: EventEmitter = new EventEmitter(); constructor( + private fb: UntypedFormBuilder, private httpClient: HttpClient, - private dialogModel: MatDialog, private activatedRoute: ActivatedRoute ) { this.newMotion = { date: new Date(), + plus: 0, + minus: 0, }; } ngOnInit(): void { + this.form = this.fb.group({ + dateFrom: [ + moment(new Date).add(-7, 'days').toDate(), + [Validators.required], + ], + dateTo: [ + new Date, + [Validators.required], + ], + }); + this.loadMotions(); + } + + onSubmitClick() { + } + + handlerOnAdd(accountMotion: AccountMotionModel) { + this.loadMotions(); + this.httpClient + .get(ApiRoutes.Account.replace(':id', this.account.account!.id!)) + .subscribe(data => { + this.account = data; + }); + + /*var md = moment(accountMotion.date); + var mdf = moment(this.form.value.dateFrom); + var mdt = moment(this.form.value.dateTo); + if (md.isBetween(mdf, mdt, 'days', '[]')) { + this.motions?.push(accountMotion); + //this.motions?.sort((a, b) => (b.date!.getMilliseconds() - a.date!.getMilliseconds())); + this.motions?.sort((a, b) => { + var aa = moment(a.date).toDate(); + var bb = moment(b.date).toDate(); + + return (bb.getMilliseconds() - aa.getMilliseconds()); + }); + }*/ + } + + private loadMotions() { + var url = ApiRoutes.Motions.replace(':id', this.account.account.id!); + url += '?from=' + moment(this.form.value.dateFrom).format('yyyy-MM-DD'); + url += '&to=' + moment(this.form.value.dateTo).format('yyyy-MM-DD'); + this.activatedRoute.params.subscribe(params => { this.httpClient - .get(ApiRoutes.Accounts + "?category=" + params['id']) + .get(url) .subscribe(data => { - this.accounts = data; + this.motions = data; }); }); } - - /*private loadAccounts() { - }*/ - - /*private loadCategories() { - this.accountCategoryService - .getCategories() - .subscribe(x => { - this.accountCategories = x; - this.loadAccounts(); - }); - }*/ - - /*public accountInCategory(category?: AccountCategoryModel) { - if (this.accounts) { - return this.accounts.filter(acc => (!category && (!acc.categories || acc.categories.length === 0)) || (category && acc.categories && acc.categories.filter(cat => cat.id === category.id).length > 0)); - } - return null; - }*/ - - /*public add() { - this.dialogModel.open(SettingsAccountAddComponent, { - width: '640px', - disableClose: true, - data: this.accounts, - }).afterClosed().subscribe(x => { - if (x && x.refresh) { - this.loadAccounts(); - } - }); - }*/ - - /*public edit(account: AccountModel) { - this.dialogModel.open(SettingsAccountEditComponent, { - width: '640px', - disableClose: true, - data: account, - }).afterClosed().subscribe(x => { - if (x && x.refresh) { - this.loadAccounts(); - } - }); - }*/ } diff --git a/MyOffice.SPA/src/app/pages/accounts/account.list.component.html b/MyOffice.SPA/src/app/pages/accounts/account.list.component.html new file mode 100644 index 0000000..cf3134c --- /dev/null +++ b/MyOffice.SPA/src/app/pages/accounts/account.list.component.html @@ -0,0 +1,18 @@ +
+
+
+ + + +
+
+
+ +
+ +
+
+
+
+
+
diff --git a/MyOffice.SPA/src/app/pages/accounts/account.list.component.scss b/MyOffice.SPA/src/app/pages/accounts/account.list.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/MyOffice.SPA/src/app/pages/accounts/account.list.component.ts b/MyOffice.SPA/src/app/pages/accounts/account.list.component.ts new file mode 100644 index 0000000..eb62c71 --- /dev/null +++ b/MyOffice.SPA/src/app/pages/accounts/account.list.component.ts @@ -0,0 +1,51 @@ +// angular +import { Component } from '@angular/core'; +import { HttpClient } from '@angular/common/http'; +import { ActivatedRoute } from '@angular/router'; + +// libs +import Swal from 'sweetalert2'; +import { MatDialog } from '@angular/material/dialog'; + +// app +import { AccountCategoryService } from '../../services/account.category.service'; +import { ApiRoutes } from '../../api-routes'; +import { AccountCategoryModel } from '../../model/account.category.model'; +import { SettingsAccountAddComponent } from '../settings/account/add.account.component'; +import { SettingsAccountEditComponent } from '../settings/account/edit.account.component'; +import { AccountModel } from '../../model/account.model'; +import { AccountDetailedModel } from '../../model/account.detailed.model'; +import { AccountMotionModel } from '../../model/account.motion'; + +@Component({ + templateUrl: './account.list.component.html', + styleUrls: ['./account.list.component.scss'], +}) +export class AccountListComponent { + public accounts?: AccountDetailedModel[]; + public category = ''; + + constructor( + private httpClient: HttpClient, + private activatedRoute: ActivatedRoute, + private accountCategoryService: AccountCategoryService, + ) { + } + + ngOnInit(): void { + this.activatedRoute.params.subscribe(params => { + var categoryId = params['id']; + + this.httpClient + .get(ApiRoutes.Accounts + '?category=' + categoryId) + .subscribe(data => { + this.accounts = data; + }); + this.accountCategoryService + .getCategory(categoryId) + .subscribe(data => { + this.category = data.name!; + }); + }); + } +} diff --git a/MyOffice.SPA/src/app/pages/accounts/motion.component.html b/MyOffice.SPA/src/app/pages/accounts/motion.component.html index 8588451..402ce31 100644 --- a/MyOffice.SPA/src/app/pages/accounts/motion.component.html +++ b/MyOffice.SPA/src/app/pages/accounts/motion.component.html @@ -1,6 +1,6 @@ -
-
-
+ +
+ -
+
- + Motion + + + Please enter motion +
-
+
@@ -37,19 +41,20 @@
- +
diff --git a/MyOffice.SPA/src/app/pages/accounts/motion.component.ts b/MyOffice.SPA/src/app/pages/accounts/motion.component.ts index ce8f4b6..b479297 100644 --- a/MyOffice.SPA/src/app/pages/accounts/motion.component.ts +++ b/MyOffice.SPA/src/app/pages/accounts/motion.component.ts @@ -1,29 +1,22 @@ // angular import { Component } from '@angular/core'; import { HttpClient } from '@angular/common/http'; -import { ActivatedRoute } from '@angular/router'; -import { UntypedFormBuilder } from '@angular/forms'; +import { FormBuilder } from '@angular/forms'; +import { FormGroup } from '@angular/forms'; import { Validators } from '@angular/forms'; -import { UntypedFormGroup } from '@angular/forms'; import { Input } from '@angular/core'; import { Output } from '@angular/core'; import { EventEmitter } from '@angular/core'; +import { ViewChild } from '@angular/core'; +import { ElementRef } from '@angular/core'; // libs -import Swal from 'sweetalert2'; -import { MatDialog } from '@angular/material/dialog'; import * as moment from 'moment'; // app -import { AccountCategoryService } from '../../services/account.category.service'; import { ApiRoutes } from '../../api-routes'; -import { AccountCategoryModel } from '../../model/account.category.model'; -import { SettingsAccountAddComponent } from '../settings/account/add.account.component'; -import { SettingsAccountEditComponent } from '../settings/account/edit.account.component'; import { AccountModel } from '../../model/account.model'; -import { AccountDetailedModel } from '../../model/account.detailed.model'; import { AccountMotionModel } from '../../model/account.motion'; -import { atLeastOne } from '../../core/validators/atleastone.validator'; import { atLeastOneNumber } from '../../core/validators/atleastonenumber.validator'; @Component({ @@ -32,16 +25,19 @@ import { atLeastOneNumber } from '../../core/validators/atleastonenumber.validat styleUrls: ['./motion.component.scss'], }) export class MotionComponent { - public form!: UntypedFormGroup; + public form!: FormGroup; public errorMessage?: string; - @Input() motion!: AccountMotionModel; + @Input('motion') motion!: AccountMotionModel; + @Input('account') account!: AccountModel; + + @Output() onAdd: EventEmitter = new EventEmitter(); + + @ViewChild('motionInput') motionInput?: ElementRef; constructor( - private fb: UntypedFormBuilder, + private fb: FormBuilder, private httpClient: HttpClient, - private dialogModel: MatDialog, - private activatedRoute: ActivatedRoute ) { } @@ -67,14 +63,29 @@ export class MotionComponent { minus: [ this.motion.minus, ], - }, { validator: atLeastOneNumber(Validators.required, ['plus', 'minus']) }); + }, { + validator: atLeastOneNumber(Validators.required, ['plus', 'minus']) + }); } onSubmitClick() { + this.form.markAllAsTouched(); + if (this.form.valid) { this.httpClient - .post(ApiRoutes.SettingsCurrencies, this.form.value) + .post(ApiRoutes.Motions.replace(':id', this.account.id!), this.form.value) .subscribe(response => { + if (!this.form.value.id) { + this.onAdd?.emit(response); + this.form.patchValue({ + motion: '', + plus: 0, + minus: 0, + }); + this.form.markAsUntouched(); + + this.motionInput?.nativeElement.focus(); + } }, error => { this.errorMessage = error.detail; }); diff --git a/MyOffice.SPA/src/app/pages/pages-routing.module.ts b/MyOffice.SPA/src/app/pages/pages-routing.module.ts index f00e533..857134a 100644 --- a/MyOffice.SPA/src/app/pages/pages-routing.module.ts +++ b/MyOffice.SPA/src/app/pages/pages-routing.module.ts @@ -6,7 +6,7 @@ import { SettingsAccountCategoryComponent } from './settings/account/account.cat import { SettingsAccountComponent } from './settings/account/account.component'; import { SettingsMotionCategoryComponent } from './settings/motion/motion.category.component'; import { SettingsMotionComponent } from './settings/motion/motion.component'; -import { AccountComponent } from './accounts/account.component'; +import { AccountListComponent as AccountComponent } from './accounts/account.list.component'; const routes: Routes = [ { diff --git a/MyOffice.SPA/src/app/pages/pages.module.ts b/MyOffice.SPA/src/app/pages/pages.module.ts index 3e714e5..8e644f5 100644 --- a/MyOffice.SPA/src/app/pages/pages.module.ts +++ b/MyOffice.SPA/src/app/pages/pages.module.ts @@ -36,6 +36,7 @@ import { MotionService } from '../services/motion.service'; import { SettingsMotionCategoryComponent } from './settings/motion/motion.category.component'; import { SettingsMotionComponent } from './settings/motion/motion.component'; import { SettingsMotionEditComponent } from './settings/motion/edit.motion.component'; +import { AccountListComponent } from './accounts/account.list.component'; import { AccountComponent } from './accounts/account.component'; import { MotionComponent } from './accounts/motion.component'; @@ -56,6 +57,7 @@ import { MotionComponent } from './accounts/motion.component'; SettingsMotionComponent, SettingsMotionEditComponent, + AccountListComponent, AccountComponent, MotionComponent, ], diff --git a/MyOffice.SPA/src/app/pages/settings/currency/currency.component.html b/MyOffice.SPA/src/app/pages/settings/currency/currency.component.html index 55a8dee..45daa8a 100644 --- a/MyOffice.SPA/src/app/pages/settings/currency/currency.component.html +++ b/MyOffice.SPA/src/app/pages/settings/currency/currency.component.html @@ -16,10 +16,22 @@
+ + + + + + + + + + + + @@ -27,10 +39,10 @@ {{item.rate | number: '1.2-6'}} {{item.symbol}} - + diff --git a/MyOffice.SPA/src/app/pages/settings/currency/currency.component.ts b/MyOffice.SPA/src/app/pages/settings/currency/currency.component.ts index 4d0f034..a667d03 100644 --- a/MyOffice.SPA/src/app/pages/settings/currency/currency.component.ts +++ b/MyOffice.SPA/src/app/pages/settings/currency/currency.component.ts @@ -74,16 +74,16 @@ export class SettingsCurrencyComponent { .subscribe(data => { this.myCurrencies = data.map(myCurrency => { var globalCurrency = this.currencies?.find(x => x.id === myCurrency.code); - return ({ + return { id: myCurrency.id, code: myCurrency.code, name: myCurrency.name, quantity: myCurrency.quantity, rate: myCurrency.rate, rateDate: myCurrency.rateDate, - shortName: globalCurrency?.name, + shortName: myCurrency.shortName, symbol: globalCurrency?.symbol, - }); + }; }); }); } diff --git a/MyOffice.SPA/src/app/pages/settings/currency/rate.currency.component.html b/MyOffice.SPA/src/app/pages/settings/currency/rate.currency.component.html index 5b86540..447a364 100644 --- a/MyOffice.SPA/src/app/pages/settings/currency/rate.currency.component.html +++ b/MyOffice.SPA/src/app/pages/settings/currency/rate.currency.component.html @@ -1,9 +1,9 @@
-

Add currency

+

Edit currency

-
+
Symbol @@ -11,7 +11,7 @@
-
+
Code @@ -19,11 +19,19 @@
-
+
Name - + + +
+
+
+
+ + Short name +
diff --git a/MyOffice.SPA/src/app/pages/settings/currency/rate.currency.component.ts b/MyOffice.SPA/src/app/pages/settings/currency/rate.currency.component.ts index 0db038d..fada566 100644 --- a/MyOffice.SPA/src/app/pages/settings/currency/rate.currency.component.ts +++ b/MyOffice.SPA/src/app/pages/settings/currency/rate.currency.component.ts @@ -45,6 +45,9 @@ export class SettingsRateCurrencyComponent { name: [ this.currency.name, ], + shortName: [ + this.currency.shortName, + ], quantity: [ this.currency.quantity || 1, [Validators.required], @@ -68,9 +71,16 @@ export class SettingsRateCurrencyComponent { if (this.addForm.valid) { this.errorMessage = undefined; this.httpClient - .post(ApiRoutes.SettingsCurrenciesRate.replace(':id', this.addForm.value.id), this.addForm.value) + .put(ApiRoutes.SettingsCurrency.replace(':id', this.addForm.value.id), this.addForm.value) .subscribe(response => { - this.dialogRef.close({ refresh: true }); + console.log(this.addForm.value); + this.httpClient + .post(ApiRoutes.SettingsCurrenciesRate.replace(':id', this.addForm.value.id), this.addForm.value) + .subscribe(response => { + this.dialogRef.close({ refresh: true }); + }, error => { + this.errorMessage = error.detail; + }); }, error => { this.errorMessage = error.detail; }); diff --git a/MyOffice.SPA/src/app/services/account.category.service.ts b/MyOffice.SPA/src/app/services/account.category.service.ts index a866c00..26a3ea7 100644 --- a/MyOffice.SPA/src/app/services/account.category.service.ts +++ b/MyOffice.SPA/src/app/services/account.category.service.ts @@ -21,4 +21,9 @@ export class AccountCategoryService { return this.httpClient .get(ApiRoutes.SettingsAccountCategories); } + + public getCategory(id: string): Observable { + return this.httpClient + .get(ApiRoutes.SettingsAccountCategory.replace(':id', id)); + } } diff --git a/MyOffice.Services/Account/AccountService.cs b/MyOffice.Services/Account/AccountService.cs index f6da905..aa55fda 100644 --- a/MyOffice.Services/Account/AccountService.cs +++ b/MyOffice.Services/Account/AccountService.cs @@ -1,6 +1,7 @@ namespace MyOffice.Services.Account { using Core; + using Core.Extensions; using Core.Helpers; using Data.Models.Accounts; using Data.Models.Motions; @@ -47,6 +48,20 @@ return _accountCategoryRepository.GetAll(userId); } + public Exec GetCategory(Guid userId, Guid id) + { + var result = new Exec(GeneralExecStatus.success); + + var category = _accountCategoryRepository.Get(userId, id); + + if (category == null) + { + return result.Set(GeneralExecStatus.not_found); + } + + return result.Set(category); + } + public Exec CategoryAdd(Guid userId, AccountCategory category) { if (category == null) @@ -125,6 +140,19 @@ return _accountRepository.GetByCategoryDetailed(userId, categoryId); } + public Exec GetByIdDetailed(Guid userId, Guid id) + { + var result = new Exec(GeneralExecStatus.success); + + var account = _accountRepository.GetByIdDetailed(userId, id); + if (account == null) + { + return result.Set(GeneralExecStatus.not_found); + } + + return result.Set(account); + } + public Exec AccountAdd(Guid userId, AccountAdd input) { if (input == null) @@ -270,33 +298,36 @@ return result.Set(AccountMotionAddResult.account_not_found); } - var motion = _motionGlobalRepository.GetByName(accountMotion.Motion); - if (motion == null) + var motionGlobal = _motionGlobalRepository.GetByName(accountMotion.Motion); + if (motionGlobal == null) { - motion = new MotionGlobal + // add global motion + motionGlobal = new MotionGlobal { Id = Guid.NewGuid(), Name = accountMotion.Motion.Trim(), }; - if (_motionGlobalRepository.Add(motion)) + if (!_motionGlobalRepository.Add(motionGlobal)) { return result.Set(AccountMotionAddResult.failure); } } - var motionAccount = _motionRepository.GetByGlobal(userId, motion.Id); + var motionAccount = _motionRepository.GetByGlobal(userId, motionGlobal.Id); if (motionAccount == null) { + // add motion account motionAccount = new MotionAccount { CategoryId = userId, - MotionGlobalId = motion.Id, + MotionGlobalId = motionGlobal.Id, }; _motionRepository.Add(motionAccount); } var accountMotionDb = new AccountMotion { + Id = Guid.NewGuid(), CreatedOn = DateTime.UtcNow, DateTime = accountMotion.Date, AccountId = account.Id, @@ -312,7 +343,28 @@ } - return result; + motionAccount.MotionGlobal = motionGlobal; + accountMotionDb.Motion = motionAccount; + + return result.Set(accountMotionDb); + } + + public Exec, GeneralExecStatus> GetAccountMotion( + Guid userId, + Guid accountId, + DateTime dateFrom, + DateTime dateTo + ) + { + var result = new Exec, GeneralExecStatus>(GeneralExecStatus.success); + + var account = _accountRepository.Get(userId, accountId); + if (account == null) + { + return result.Set(GeneralExecStatus.not_found); + } + + return result.Set(_accountMotionRepository.GetByAccount(accountId, dateFrom.ToUtc(), dateTo.ToUtc())); } } } diff --git a/MyOffice.Services/Currency/CurrencyService.cs b/MyOffice.Services/Currency/CurrencyService.cs index 9198027..78c9f4a 100644 --- a/MyOffice.Services/Currency/CurrencyService.cs +++ b/MyOffice.Services/Currency/CurrencyService.cs @@ -41,30 +41,58 @@ public class CurrencyService ); } - public Exec AddCurrency(Guid userId, Currency currency) + public Exec CurrencyAdd(Guid userId, Currency currency) { if (currency == null) throw new ArgumentNullException(nameof(currency)); - var result = new Exec(AddCurrencyStatus.success); + var result = new Exec(CurrencyAddStatus.success); var exists = _currencyRepository.GetByGlobalCurrency(userId, currency.CurrencyGlobalId); if (exists != null) { - return result.Set(exists, AddCurrencyStatus.exists); + return result.Set(exists, CurrencyAddStatus.exists); } currency.Id = Guid.NewGuid(); currency.UserId = userId; if (!_currencyRepository.Add(currency)) { - return result.Set(AddCurrencyStatus.failed); + return result.Set(CurrencyAddStatus.failed); } return result.Set(currency); } - public Exec AddCurrencyRate(Guid userId, Guid currencyId, CurrencyRate currencyRate) + public Exec CurrencyUpdate( + Guid userId, + Guid currencyId, + CurrencyEdit currency + ) + { + if (currency == null) + throw new ArgumentNullException(nameof(currency)); + + var result = new Exec(CurrencyEditStatus.success); + + var exists = _currencyRepository.Get(userId, currencyId); + if (exists == null) + { + return result.Set(CurrencyEditStatus.not_found); + } + + exists.Name = currency.Name; + exists.ShortName = currency.ShortName; + + if (!_currencyRepository.Update(exists)) + { + return result.Set(CurrencyEditStatus.failed); + } + + return result.Set(exists); + } + + public Exec CurrencyRateAdd(Guid userId, Guid currencyId, CurrencyRate currencyRate) { if (currencyRate == null) throw new ArgumentNullException(nameof(currencyRate)); @@ -80,15 +108,18 @@ public class CurrencyService currencyRate.CurrencyId = exists.Id; currencyRate.DateTime = currencyRate.DateTime.Date; - var rate = _currencyRateRepository.GetAtDate(currencyRate.CurrencyId, currencyRate.DateTime); - if (rate.All(x => x.Rate != currencyRate.Rate)) + var rates = _currencyRateRepository.GetAtDate(currencyRate.CurrencyId, currencyRate.DateTime); + var rate = rates.Find(x => x.Rate == currencyRate.Rate); + if (rate == null) { - if (_currencyRateRepository.AddRate(currencyRate)) + if (!_currencyRateRepository.AddRate(currencyRate)) { - return result.Set(currencyRate); + return result.Set(CurrencyAddRateStatus.failed); } + + rate = currencyRate; } - return result.Set(CurrencyAddRateStatus.failed); + return result.Set(rate); } } diff --git a/MyOffice.Services/Currency/Domain/AddCurrencyStatus.cs b/MyOffice.Services/Currency/Domain/AddCurrencyStatus.cs deleted file mode 100644 index 3741980..0000000 --- a/MyOffice.Services/Currency/Domain/AddCurrencyStatus.cs +++ /dev/null @@ -1,16 +0,0 @@ -namespace MyOffice.Services.Currency.Domain -{ - public enum AddCurrencyStatus - { - success, - failed, - exists, - } - - public enum CurrencyAddRateStatus - { - not_found, - success, - failed, - } -} diff --git a/MyOffice.Services/Currency/Domain/CurrencyAddRateStatus.cs b/MyOffice.Services/Currency/Domain/CurrencyAddRateStatus.cs new file mode 100644 index 0000000..088ac18 --- /dev/null +++ b/MyOffice.Services/Currency/Domain/CurrencyAddRateStatus.cs @@ -0,0 +1,8 @@ +namespace MyOffice.Services.Currency.Domain; + +public enum CurrencyAddRateStatus +{ + not_found, + success, + failed, +} \ No newline at end of file diff --git a/MyOffice.Services/Currency/Domain/CurrencyAddStatus.cs b/MyOffice.Services/Currency/Domain/CurrencyAddStatus.cs new file mode 100644 index 0000000..0c375ce --- /dev/null +++ b/MyOffice.Services/Currency/Domain/CurrencyAddStatus.cs @@ -0,0 +1,9 @@ +namespace MyOffice.Services.Currency.Domain +{ + public enum CurrencyAddStatus + { + success, + failed, + exists, + } +} diff --git a/MyOffice.Services/Currency/Domain/CurrencyEdit.cs b/MyOffice.Services/Currency/Domain/CurrencyEdit.cs new file mode 100644 index 0000000..98d589b --- /dev/null +++ b/MyOffice.Services/Currency/Domain/CurrencyEdit.cs @@ -0,0 +1,7 @@ +namespace MyOffice.Services.Currency.Domain; + +public class CurrencyEdit +{ + public string Name { get; set; } = null!; + public string ShortName { get; set; } = null!; +} \ No newline at end of file diff --git a/MyOffice.Services/Currency/Domain/CurrencyEditStatus.cs b/MyOffice.Services/Currency/Domain/CurrencyEditStatus.cs new file mode 100644 index 0000000..6ca41e4 --- /dev/null +++ b/MyOffice.Services/Currency/Domain/CurrencyEditStatus.cs @@ -0,0 +1,8 @@ +namespace MyOffice.Services.Currency.Domain; + +public enum CurrencyEditStatus +{ + success, + not_found, + failed, +} \ No newline at end of file diff --git a/MyOffice.Web/Controllers/AccountController.cs b/MyOffice.Web/Controllers/AccountController.cs index 26e50ee..9773693 100644 --- a/MyOffice.Web/Controllers/AccountController.cs +++ b/MyOffice.Web/Controllers/AccountController.cs @@ -1,9 +1,12 @@ namespace MyOffice.Web.Controllers; +using Core; using Core.Extensions; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Logging; using Models.Account; +using Models.Motion; using MyOffice.Data.Models.Accounts; using MyOffice.Web.Models.AccountMotion; using Services.Account; @@ -31,29 +34,62 @@ public class AccountController : BaseApiController { var list = _accountService.GetByCategoryDetailed(UserId, category!.AsGuid()); - return list.Select(x => x.ToModel()); + return list + .OrderBy(x => x.Account.Name) + .Select(x => x.ToModel()); + } + + [HttpGet("~/api/accounts/{id}")] + public object AccountGet(string id) + { + var exec = _accountService.GetByIdDetailed(UserId, id!.AsGuid()); + + switch (exec.Status) + { + case GeneralExecStatus.not_found: + case GeneralExecStatus.failure: + return ProblemBadRequest("Account not found."); + + case GeneralExecStatus.success: + return exec.Result!.ToModel(); + + default: + throw new NotSupportedException(exec.Status.ToString()); + } } [HttpGet("~/api/accounts/{id}/motions")] - public object AccountsMotionsGet(string category) + public object AccountMotionsGet(string id, [FromQuery] AccountMotionsGetModel request) { - var list = _accountService.GetByCategoryDetailed(UserId, category!.AsGuid()); + var exec = _accountService.GetAccountMotion(UserId, id!.AsGuid(), request.From.StartOfDay(), request.To.EndOfDay()); - return list.Select(x => x.ToModel()); + switch (exec.Status) + { + case GeneralExecStatus.not_found: + case GeneralExecStatus.failure: + return ProblemBadRequest("Account not found."); + + case GeneralExecStatus.success: + return exec.Result!.Select(x => x.ToModel()); + + default: + throw new NotSupportedException(exec.Status.ToString()); + } } [HttpPost("~/api/accounts/{id}/motions")] public object AccountsMotionsPost(string id, AccountMotionRequest accountMotion) { var exec = _accountService.AccountMotionAdd(UserId, id.AsGuid(), accountMotion.FromModel()); + switch (exec.Status) { case AccountMotionAddResult.account_not_found: - return ProblemBadRequest("Account failed."); + return ProblemBadRequest("Account not found."); case AccountMotionAddResult.failure: return ProblemBadRequest("Adding motion failed."); case AccountMotionAddResult.success: - return exec.Result!; + return exec.Result!.ToModel(); default: throw new NotSupportedException(exec.Status.ToString()); diff --git a/MyOffice.Web/Controllers/CurrencyController.cs b/MyOffice.Web/Controllers/CurrencyController.cs index c2d5439..fdc40af 100644 --- a/MyOffice.Web/Controllers/CurrencyController.cs +++ b/MyOffice.Web/Controllers/CurrencyController.cs @@ -32,13 +32,15 @@ public class CurrencyController : BaseApiController { var list = _currencyService.GetAllWithRates(UserId); - return list.Select(x => x.Key.ToModel(x.Value)); + return list + .OrderBy(x => x.Key.CurrencyGlobalId) + .Select(x => x.Key.ToModel(x.Value)); } [HttpPost("~/api/settings/currencies")] public object Post(CurrencyAddModel currency) { - var exec = _currencyService.AddCurrency(UserId, new Currency + var exec = _currencyService.CurrencyAdd(UserId, new Currency { UserId = UserId, CurrencyGlobalId = currency.Id, @@ -48,9 +50,9 @@ public class CurrencyController : BaseApiController switch (exec.Status) { - case AddCurrencyStatus.success: - case AddCurrencyStatus.exists: - _currencyService.AddCurrencyRate(UserId, exec.Result!.Id, new CurrencyRate() + case CurrencyAddStatus.success: + case CurrencyAddStatus.exists: + _currencyService.CurrencyRateAdd(UserId, exec.Result!.Id, new CurrencyRate() { CurrencyId = exec.Result!.Id, Rate = currency.Rate, @@ -59,7 +61,7 @@ public class CurrencyController : BaseApiController }); return currency; - case AddCurrencyStatus.failed: + case CurrencyAddStatus.failed: return ProblemBadRequest("Adding currency failed."); default: @@ -67,10 +69,33 @@ public class CurrencyController : BaseApiController } } + [HttpPut("~/api/settings/currencies/{id}")] + public object Put(string id, CurrencyEditModel currency) + { + var exec = _currencyService.CurrencyUpdate( + UserId, + id.AsGuid(), + new CurrencyEdit { Name = currency.Name, ShortName = currency.ShortName } + ); + + switch (exec.Status) + { + case CurrencyEditStatus.success: + return exec.Result!.ToModel(); + + case CurrencyEditStatus.not_found: + case CurrencyEditStatus.failed: + return ProblemBadRequest("Currency not found."); + + default: + throw new NotSupportedException(exec.Status.ToString()); + } + } + [HttpPost("~/api/settings/currencies/{id}/rate")] public object Post(string id, CurrencyRateModel currencyRate) { - var exec = _currencyService.AddCurrencyRate(UserId, id.AsGuid(), new CurrencyRate() + var exec = _currencyService.CurrencyRateAdd(UserId, id.AsGuid(), new CurrencyRate() { CurrencyId = id.AsGuid(), Quantity = currencyRate.Quantity, diff --git a/MyOffice.Web/Controllers/MotionController.cs b/MyOffice.Web/Controllers/MotionController.cs index 377e96f..83b28ee 100644 --- a/MyOffice.Web/Controllers/MotionController.cs +++ b/MyOffice.Web/Controllers/MotionController.cs @@ -32,7 +32,10 @@ public class SettingsMotionController : BaseApiController { var list = _motionService.GetAllCategories(UserId); - return list.Select(x => x.ToModel()).OrderByDescending(x => x.SortOrder); + return list + .Select(x => x.ToModel()) + .OrderByDescending(x => x.SortOrder) + .ThenBy(x => x.Name); } [HttpPost("~/api/settings/motion-categories")] @@ -42,7 +45,7 @@ public class SettingsMotionController : BaseApiController switch (exec.Status) { case GeneralExecStatus.success: - return exec.Result!; + return exec.Result!.ToModel(); case GeneralExecStatus.failure: case GeneralExecStatus.not_found: @@ -60,7 +63,7 @@ public class SettingsMotionController : BaseApiController switch (exec.Status) { case GeneralExecStatus.success: - return exec.Result!; + return exec.Result!.ToModel(); case GeneralExecStatus.failure: case GeneralExecStatus.not_found: @@ -97,9 +100,11 @@ public class SettingsMotionController : BaseApiController { var list = category.IsMissing() ? _motionService.GetAll(UserId) - : _motionService.GetByCategory(UserId, category.AsGuid()); + : _motionService.GetByCategory(UserId, category!.AsGuid()); - return list.Select(x => x.ToModel()); + return list + .OrderBy(x => x.MotionGlobal.Name) + .Select(x => x.ToModel()); } [HttpPut("~/api/settings/motions/{id}")] diff --git a/MyOffice.Web/Controllers/SettingsAccountController.cs b/MyOffice.Web/Controllers/SettingsAccountController.cs index a463d06..0d7a23b 100644 --- a/MyOffice.Web/Controllers/SettingsAccountController.cs +++ b/MyOffice.Web/Controllers/SettingsAccountController.cs @@ -31,7 +31,26 @@ public class SettingsAccountController : BaseApiController { var list = _accountService.GetAllCategories(UserId); - return list.Select(x => x.ToModel()); + return list.OrderBy(x => x.Name).Select(x => x.ToModel()); + } + + [HttpGet("~/api/settings/account-categories/{id}")] + public object AccountCategory(string id) + { + var exec = _accountService.GetCategory(UserId, id.AsGuid()); + + switch (exec.Status) + { + case GeneralExecStatus.not_found: + case GeneralExecStatus.failure: + return ProblemBadRequest("Account category not found."); + + case GeneralExecStatus.success: + return exec.Result!.ToModel(); + + default: + throw new NotSupportedException(exec.Status.ToString()); + } } [HttpPost("~/api/settings/account-categories")] @@ -98,7 +117,9 @@ public class SettingsAccountController : BaseApiController ? _accountService.GetByCategory(UserId, category!.AsGuid()) : _accountService.GetAllAccounts(UserId); - return list.Select(x => x.ToModel()); + return list + .OrderBy(x => x.Name) + .Select(x => x.ToModel()); } [HttpPost("~/api/settings/accounts")] diff --git a/MyOffice.Web/Controllers/WeatherForecastController.cs b/MyOffice.Web/Controllers/WeatherForecastController.cs deleted file mode 100644 index bd092cb..0000000 --- a/MyOffice.Web/Controllers/WeatherForecastController.cs +++ /dev/null @@ -1,47 +0,0 @@ -namespace MyOffice.Web.Controllers; - -using Models.WeatherForecast; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Mvc; - -[ApiController] -[Route("[controller]")] -public class WeatherForecastController : ControllerBase -{ - private static readonly string[] Summaries = new[] - { - "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" - }; - - private readonly ILogger _logger; - - public WeatherForecastController(ILogger logger) - { - _logger = logger; - } - - [HttpGet("~/api/weatherforecast")] - public IEnumerable Get() - { - return Enumerable.Range(1, 5).Select(index => new WeatherForecast - { - Date = DateTime.Now.AddDays(index), - TemperatureC = Random.Shared.Next(-20, 55), - Summary = Summaries[Random.Shared.Next(Summaries.Length)] - }) - .ToArray(); - } - - [HttpGet("~/api/weatherforecast/auth")] - [Authorize] - public IEnumerable GetAuth() - { - return Enumerable.Range(1, 5).Select(index => new WeatherForecast - { - Date = DateTime.Now.AddDays(index), - TemperatureC = Random.Shared.Next(-20, 55), - Summary = Summaries[Random.Shared.Next(Summaries.Length)] - }) - .ToArray(); - } -} \ No newline at end of file diff --git a/MyOffice.Web/Models/AccountMotion/AccountMotionViewModel.cs b/MyOffice.Web/Models/AccountMotion/AccountMotionViewModel.cs index d3eea7f..d1870b8 100644 --- a/MyOffice.Web/Models/AccountMotion/AccountMotionViewModel.cs +++ b/MyOffice.Web/Models/AccountMotion/AccountMotionViewModel.cs @@ -18,8 +18,8 @@ public class AccountMotionRequest public DateTime Date { get; set; } public string Motion { get; set; } = null!; public string? Description { get; set; } - public decimal Plus { get; set; } - public decimal Minus { get; set; } + public decimal? Plus { get; set; } + public decimal? Minus { get; set; } } public static class AccountMotionViewModelExtension @@ -34,8 +34,8 @@ public static class AccountMotionRequestExtension { Date = input.Date, Motion = input.Motion, - Minus = input.Minus, - Plus = input.Plus, + Minus = input.Minus ?? 0, + Plus = input.Plus ?? 0, Description = input.Description, }; } diff --git a/MyOffice.Web/Models/Currency/CurrencyEditModel.cs b/MyOffice.Web/Models/Currency/CurrencyEditModel.cs new file mode 100644 index 0000000..e8a5d34 --- /dev/null +++ b/MyOffice.Web/Models/Currency/CurrencyEditModel.cs @@ -0,0 +1,10 @@ +namespace MyOffice.Web.Models.Currency; + +public class CurrencyEditModel +{ + public string Name { get; set; } = null!; + public string ShortName { get; set; } = null!; + public int Quantity { get; set; } + public decimal Rate { get; set; } + public DateTime RateDate { get; set; } +} \ No newline at end of file diff --git a/MyOffice.Web/Models/Currency/CurrencyViewModel.cs b/MyOffice.Web/Models/Currency/CurrencyViewModel.cs index 4a4d1b1..2d34d58 100644 --- a/MyOffice.Web/Models/Currency/CurrencyViewModel.cs +++ b/MyOffice.Web/Models/Currency/CurrencyViewModel.cs @@ -8,7 +8,9 @@ { public string Id { get; set; } = null!; public string Code { get; set; } = null!; + public string Symbol { get; set; } = null!; public string Name { get; set; } = null!; + public string ShortName { get; set; } = null!; public decimal? Rate { get; set; } public int? Quantity { get; set; } public DateTime? RateDate { get; set; } @@ -22,7 +24,9 @@ { Id = input.Id.ToShort(), Code = input.CurrencyGlobal!.Id, + Symbol = input.CurrencyGlobal!.Symbol, Name = input.Name, + ShortName = input.ShortName, Quantity = rate?.Quantity, Rate = rate?.Rate, RateDate = rate?.DateTime, diff --git a/MyOffice.Web/Models/Motion/AccountMotionViewModel.cs b/MyOffice.Web/Models/Motion/AccountMotionViewModel.cs new file mode 100644 index 0000000..20167a6 --- /dev/null +++ b/MyOffice.Web/Models/Motion/AccountMotionViewModel.cs @@ -0,0 +1,33 @@ +namespace MyOffice.Web.Models.Motion +{ + using System.ComponentModel.DataAnnotations; + using Core.Extensions; + using Data.Models.Accounts; + using MyOffice.Data.Models.Motions; + + public class AccountMotionViewModel + { + public string Id { get; set; } = null!; + public DateTime Date { get; set; } + public string Motion { get; set; } = null!; + public string? Description { get; set; } + public decimal Plus { get; set; } + public decimal Minus { get; set; } + } + + public static class AccountMotionViewModelExtensions + { + public static AccountMotionViewModel ToModel(this AccountMotion input) + { + return new AccountMotionViewModel + { + Id = input.Id.ToShort(), + Date = input.DateTime, + Motion = input.Motion.MotionGlobal.Name, + Description = input.Description, + Plus = input.AmountPlus, + Minus = input.AmountMinus, + }; + } + } +} diff --git a/MyOffice.Web/Models/Motion/AccountMotionsGetModel.cs b/MyOffice.Web/Models/Motion/AccountMotionsGetModel.cs new file mode 100644 index 0000000..7f890ec --- /dev/null +++ b/MyOffice.Web/Models/Motion/AccountMotionsGetModel.cs @@ -0,0 +1,12 @@ +namespace MyOffice.Web.Models.Motion +{ + using System.ComponentModel.DataAnnotations; + + public class AccountMotionsGetModel + { + [Required] + public DateTime From { get; set; } + [Required] + public DateTime To { get; set; } + } +} diff --git a/MyOffice.Web/Models/WeatherForecast/WeatherForecast.cs b/MyOffice.Web/Models/WeatherForecast/WeatherForecast.cs deleted file mode 100644 index f4d8836..0000000 --- a/MyOffice.Web/Models/WeatherForecast/WeatherForecast.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace MyOffice.Web.Models.WeatherForecast; - -public class WeatherForecast -{ - public DateTime Date { get; set; } - - public int TemperatureC { get; set; } - - public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); - - public string? Summary { get; set; } -} \ No newline at end of file
CodeNameShort NameQuantityRateRate Date
{{item.code}} {{item.name}}{{item.shortName}} {{item.quantity}} {{item.rateDate | date:'yyyy-MM-dd'}}{{item.rateDate | date:'yyyy-MM-dd'}}