From fb2d036dcee032248da88ed82b9f4f513511d681 Mon Sep 17 00:00:00 2001 From: amiralirahimii Date: Sat, 17 Aug 2024 22:49:10 +0330 Subject: [PATCH 1/4] feat: add transaction-controller --- src/Application/Application.csproj | 4 +++ .../TransactionCsv/TransactionCsvModel.cs | 11 ++++++ .../Interfaces/ITransactionRepository.cs | 8 +++++ .../Services/ITransactionService.cs | 8 +++++ .../Interfaces/SharedService/ICsvService.cs | 6 ++++ .../SharedService/CsvReaderService.cs | 22 ++++++++++++ .../Services/TransactionService.cs | 34 ++++++++++++++++++ .../Services/TransactionRepository.cs | 20 +++++++++++ src/Web/Controllers/TransactionController.cs | 35 +++++++++++++++++++ src/Web/Program.cs | 3 ++ 10 files changed, 151 insertions(+) create mode 100644 src/Application/DTOs/TransactionCsv/TransactionCsvModel.cs create mode 100644 src/Application/Interfaces/ITransactionRepository.cs create mode 100644 src/Application/Interfaces/Services/ITransactionService.cs create mode 100644 src/Application/Interfaces/SharedService/ICsvService.cs create mode 100644 src/Application/Services/SharedService/CsvReaderService.cs create mode 100644 src/Application/Services/TransactionService.cs create mode 100644 src/Infrastructure/Services/TransactionRepository.cs create mode 100644 src/Web/Controllers/TransactionController.cs diff --git a/src/Application/Application.csproj b/src/Application/Application.csproj index 4a59d20..633569a 100644 --- a/src/Application/Application.csproj +++ b/src/Application/Application.csproj @@ -10,4 +10,8 @@ + + + + diff --git a/src/Application/DTOs/TransactionCsv/TransactionCsvModel.cs b/src/Application/DTOs/TransactionCsv/TransactionCsvModel.cs new file mode 100644 index 0000000..e1f36da --- /dev/null +++ b/src/Application/DTOs/TransactionCsv/TransactionCsvModel.cs @@ -0,0 +1,11 @@ +namespace Application.DTOs.TransactionCsv; + +public class TransactionCsvModel +{ + public int TransactionId { get; set; } + public int SourceAccount { get; set; } + public int DestinationAccount { get; set; } + public decimal Amount { get; set; } + public DateTime Date { get; set; } + public string Type { get; set; } = string.Empty; +} \ No newline at end of file diff --git a/src/Application/Interfaces/ITransactionRepository.cs b/src/Application/Interfaces/ITransactionRepository.cs new file mode 100644 index 0000000..060ce17 --- /dev/null +++ b/src/Application/Interfaces/ITransactionRepository.cs @@ -0,0 +1,8 @@ +using Domain.Entities; + +namespace Application.Interfaces; + +public interface ITransactionRepository +{ + Task CreateBulkAsync(List transactions); +} \ No newline at end of file diff --git a/src/Application/Interfaces/Services/ITransactionService.cs b/src/Application/Interfaces/Services/ITransactionService.cs new file mode 100644 index 0000000..ea94d79 --- /dev/null +++ b/src/Application/Interfaces/Services/ITransactionService.cs @@ -0,0 +1,8 @@ +using Application.DTOs; + +namespace Application.Interfaces.Services; + +public interface ITransactionService +{ + Task AddTransactionsFromCsvAsync(string filePath); +} \ No newline at end of file diff --git a/src/Application/Interfaces/SharedService/ICsvService.cs b/src/Application/Interfaces/SharedService/ICsvService.cs new file mode 100644 index 0000000..58318df --- /dev/null +++ b/src/Application/Interfaces/SharedService/ICsvService.cs @@ -0,0 +1,6 @@ +namespace Application.Interfaces.SharedService; + +public interface ICsvService +{ + +} \ No newline at end of file diff --git a/src/Application/Services/SharedService/CsvReaderService.cs b/src/Application/Services/SharedService/CsvReaderService.cs new file mode 100644 index 0000000..53d2424 --- /dev/null +++ b/src/Application/Services/SharedService/CsvReaderService.cs @@ -0,0 +1,22 @@ +using System.Globalization; +using Application.DTOs.TransactionCsv; +using CsvHelper; +using CsvHelper.Configuration; + +namespace Application.Services.SharedService; + +public static class CsvReaderService +{ + public static List ReadFromCsv(string filePath) + { + using var reader = new StreamReader(filePath); + using var csv = new CsvReader(reader, new CsvConfiguration(CultureInfo.InvariantCulture) + { + HeaderValidated = null, + MissingFieldFound = null + }); + + var records = csv.GetRecords().ToList(); + return records; + } +} \ No newline at end of file diff --git a/src/Application/Services/TransactionService.cs b/src/Application/Services/TransactionService.cs new file mode 100644 index 0000000..c221f33 --- /dev/null +++ b/src/Application/Services/TransactionService.cs @@ -0,0 +1,34 @@ +using Application.DTOs; +using Application.DTOs.TransactionCsv; +using Application.Interfaces; +using Application.Interfaces.Services; +using Application.Services.SharedService; +using Domain.Entities; + +namespace Application.Services; + +public class TransactionService : ITransactionService +{ + public readonly ITransactionRepository _transactionRepository; + + public TransactionService(ITransactionRepository transactionRepository) + { + _transactionRepository = transactionRepository; + } + + public async Task AddTransactionsFromCsvAsync(string filePath) + { + var transactionCsvModels = CsvReaderService.ReadFromCsv(filePath); + + var transactions = transactionCsvModels.Select(csvModel => new Transaction + { + SourceAccountId = csvModel.SourceAccount, + DestinationAccountId = csvModel.DestinationAccount, + Amount = csvModel.Amount, + Date = csvModel.Date, + Type = csvModel.Type + }).ToList(); + + await _transactionRepository.CreateBulkAsync(transactions); + } +} \ No newline at end of file diff --git a/src/Infrastructure/Services/TransactionRepository.cs b/src/Infrastructure/Services/TransactionRepository.cs new file mode 100644 index 0000000..e695392 --- /dev/null +++ b/src/Infrastructure/Services/TransactionRepository.cs @@ -0,0 +1,20 @@ +using Application.Interfaces; +using Domain.Entities; +using Infrastructure.Data; + +namespace Infrastructure.Services; + +public class TransactionRepository : ITransactionRepository +{ + private readonly ApplicationDbContext _dbContext; + public TransactionRepository(ApplicationDbContext dbContext) + { + _dbContext = dbContext; + } + + public async Task CreateBulkAsync(List transactions) + { + await _dbContext.Transactions.AddRangeAsync(transactions); + await _dbContext.SaveChangesAsync(); + } +} \ No newline at end of file diff --git a/src/Web/Controllers/TransactionController.cs b/src/Web/Controllers/TransactionController.cs new file mode 100644 index 0000000..b69e90b --- /dev/null +++ b/src/Web/Controllers/TransactionController.cs @@ -0,0 +1,35 @@ +using Application.Interfaces.Services; +using Infrastructure.Data; +using Microsoft.AspNetCore.Mvc; + +namespace Web.Controllers; + +[ApiController] +[Route("[controller]/[action]")] +public class TransactionController : ControllerBase +{ + public readonly ITransactionService _transactionService; + + public TransactionController(ITransactionService transactionService) + { + _transactionService = transactionService; + } + + [HttpPost] + public async Task ImportTransactions([FromForm] IFormFile file) + { + if (file.Length == 0) + return BadRequest("No file uploaded."); + + var filePath = Path.GetTempFileName(); + + await using (var stream = System.IO.File.Create(filePath)) + { + await file.CopyToAsync(stream); + } + + await _transactionService.AddTransactionsFromCsvAsync(filePath); + + return Ok("Transactions imported successfully."); + } +} \ No newline at end of file diff --git a/src/Web/Program.cs b/src/Web/Program.cs index 438c493..f730163 100644 --- a/src/Web/Program.cs +++ b/src/Web/Program.cs @@ -56,6 +56,9 @@ builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); + builder.Services.AddControllers().AddNewtonsoftJson(options => { options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore; From dec1fbf736ddeea2f63893fab6de6b7fc2ccdeaf Mon Sep 17 00:00:00 2001 From: amiralirahimii Date: Sun, 18 Aug 2024 12:24:54 +0330 Subject: [PATCH 2/4] fix: fix transaction-controller functionality --- .../TransactionCsv/TransactionCsvModel.cs | 6 +- .../SharedService/PersianDateConverter.cs | 34 ++ src/Domain/Entities/Transaction.cs | 8 +- ...17193825_Accounts-Transactions.Designer.cs | 414 ++++++++++++++++++ .../20240817193825_Accounts-Transactions.cs | 138 ++++++ .../ApplicationDbContextModelSnapshot.cs | 123 +++++- src/Web/Program.cs | 2 + 7 files changed, 713 insertions(+), 12 deletions(-) create mode 100644 src/Application/Services/SharedService/PersianDateConverter.cs create mode 100644 src/Infrastructure/Migrations/20240817193825_Accounts-Transactions.Designer.cs create mode 100644 src/Infrastructure/Migrations/20240817193825_Accounts-Transactions.cs diff --git a/src/Application/DTOs/TransactionCsv/TransactionCsvModel.cs b/src/Application/DTOs/TransactionCsv/TransactionCsvModel.cs index e1f36da..55a03f8 100644 --- a/src/Application/DTOs/TransactionCsv/TransactionCsvModel.cs +++ b/src/Application/DTOs/TransactionCsv/TransactionCsvModel.cs @@ -1,4 +1,7 @@ -namespace Application.DTOs.TransactionCsv; +using Application.Services.SharedService; +using CsvHelper.Configuration.Attributes; + +namespace Application.DTOs.TransactionCsv; public class TransactionCsvModel { @@ -6,6 +9,7 @@ public class TransactionCsvModel public int SourceAccount { get; set; } public int DestinationAccount { get; set; } public decimal Amount { get; set; } + [TypeConverter(typeof(PersianDateConverter))] public DateTime Date { get; set; } public string Type { get; set; } = string.Empty; } \ No newline at end of file diff --git a/src/Application/Services/SharedService/PersianDateConverter.cs b/src/Application/Services/SharedService/PersianDateConverter.cs new file mode 100644 index 0000000..e571925 --- /dev/null +++ b/src/Application/Services/SharedService/PersianDateConverter.cs @@ -0,0 +1,34 @@ +using System.Globalization; +using CsvHelper; +using CsvHelper.Configuration; +using CsvHelper.TypeConversion; + +namespace Application.Services.SharedService; + +public class PersianDateConverter : DateTimeConverter +{ + public override object ConvertFromString(string? text, IReaderRow row, MemberMapData memberMapData) + { + if (string.IsNullOrWhiteSpace(text)) + { + return DateTime.MinValue; + } + + try + { + var persianCalendar = new PersianCalendar(); + var parts = text.Split('/'); + + var year = int.Parse(parts[0]); + var month = int.Parse(parts[1]); + var day = int.Parse(parts[2]); + + var gregorianDate = persianCalendar.ToDateTime(year, month, day, 0, 0, 0, 0); + return DateTime.SpecifyKind(gregorianDate, DateTimeKind.Utc); + } + catch (Exception ex) + { + throw new TypeConverterException(this, memberMapData, text, row.Context, ex.Message); + } + } +} \ No newline at end of file diff --git a/src/Domain/Entities/Transaction.cs b/src/Domain/Entities/Transaction.cs index 7e91748..e3d8a21 100644 --- a/src/Domain/Entities/Transaction.cs +++ b/src/Domain/Entities/Transaction.cs @@ -1,15 +1,17 @@ using System.ComponentModel.DataAnnotations.Schema; namespace Domain.Entities; -[Table("Accounts")] +[Table("Transactions")] public class Transaction { public int TransactionId { get; set; } public int SourceAccountId { get; set; } + public Account SourceAccount { get; set; } public int DestinationAccountId { get; set; } + public Account DestinationAccount { get; set; } public decimal Amount { get; set; } public DateTime Date { get; set; } public string Type { get; set; } = String.Empty; - public Account SourceAccount { get; set; } - public Account DestinationAccount { get; set; } + + } \ No newline at end of file diff --git a/src/Infrastructure/Migrations/20240817193825_Accounts-Transactions.Designer.cs b/src/Infrastructure/Migrations/20240817193825_Accounts-Transactions.Designer.cs new file mode 100644 index 0000000..e9fb4b7 --- /dev/null +++ b/src/Infrastructure/Migrations/20240817193825_Accounts-Transactions.Designer.cs @@ -0,0 +1,414 @@ +// +using System; +using Infrastructure.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace Infrastructure.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20240817193825_Accounts-Transactions")] + partial class AccountsTransactions + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.7") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Domain.Entities.Account", b => + { + b.Property("AccountId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("AccountId")); + + b.Property("AccountType") + .IsRequired() + .HasColumnType("text"); + + b.Property("BranchAddress") + .IsRequired() + .HasColumnType("text"); + + b.Property("BranchName") + .IsRequired() + .HasColumnType("text"); + + b.Property("BranchTelephone") + .IsRequired() + .HasColumnType("text"); + + b.Property("CardId") + .HasColumnType("integer"); + + b.Property("Iban") + .IsRequired() + .HasColumnType("text"); + + b.Property("OwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("OwnerLastName") + .IsRequired() + .HasColumnType("text"); + + b.Property("OwnerName") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("AccountId"); + + b.ToTable("Accounts"); + }); + + modelBuilder.Entity("Domain.Entities.AppUser", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("AccessFailedCount") + .HasColumnType("integer"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("text"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("boolean"); + + b.Property("FirstName") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("LastName") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("LockoutEnabled") + .HasColumnType("boolean"); + + b.Property("LockoutEnd") + .HasColumnType("timestamp with time zone"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("PasswordHash") + .HasColumnType("text"); + + b.Property("PhoneNumber") + .HasColumnType("text"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("boolean"); + + b.Property("SecurityStamp") + .HasColumnType("text"); + + b.Property("TwoFactorEnabled") + .HasColumnType("boolean"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Domain.Entities.Transaction", b => + { + b.Property("TransactionId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TransactionId")); + + b.Property("Amount") + .HasColumnType("numeric"); + + b.Property("Date") + .HasColumnType("timestamp with time zone"); + + b.Property("DestinationAccountId") + .HasColumnType("integer"); + + b.Property("SourceAccountId") + .HasColumnType("integer"); + + b.Property("Type") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("TransactionId"); + + b.HasIndex("DestinationAccountId"); + + b.HasIndex("SourceAccountId"); + + b.ToTable("Transactions"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("text"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("AspNetRoles", (string)null); + + b.HasData( + new + { + Id = "0a8ca877-f408-4d10-806f-1714e41b0186", + Name = "Admin", + NormalizedName = "ADMIN" + }, + new + { + Id = "fa9ffeed-788f-40cd-a86b-3e5ad7a03e0b", + Name = "DataAdmin", + NormalizedName = "DATAADMIN" + }, + new + { + Id = "913a4192-89c6-4d8e-873c-52d9695f8d59", + Name = "DataAnalyst", + NormalizedName = "DATAANALYST" + }); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("text"); + + b.Property("ClaimValue") + .HasColumnType("text"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("text"); + + b.Property("ClaimValue") + .HasColumnType("text"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("text"); + + b.Property("ProviderKey") + .HasColumnType("text"); + + b.Property("ProviderDisplayName") + .HasColumnType("text"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("RoleId") + .HasColumnType("text"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("LoginProvider") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("Value") + .HasColumnType("text"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Domain.Entities.Transaction", b => + { + b.HasOne("Domain.Entities.Account", "DestinationAccount") + .WithMany("DestinationTransactions") + .HasForeignKey("DestinationAccountId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Domain.Entities.Account", "SourceAccount") + .WithMany("SourceTransactions") + .HasForeignKey("SourceAccountId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("DestinationAccount"); + + b.Navigation("SourceAccount"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Domain.Entities.AppUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Domain.Entities.AppUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Domain.Entities.AppUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Domain.Entities.AppUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Domain.Entities.Account", b => + { + b.Navigation("DestinationTransactions"); + + b.Navigation("SourceTransactions"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Infrastructure/Migrations/20240817193825_Accounts-Transactions.cs b/src/Infrastructure/Migrations/20240817193825_Accounts-Transactions.cs new file mode 100644 index 0000000..71753e8 --- /dev/null +++ b/src/Infrastructure/Migrations/20240817193825_Accounts-Transactions.cs @@ -0,0 +1,138 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional + +namespace Infrastructure.Migrations +{ + /// + public partial class AccountsTransactions : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DeleteData( + table: "AspNetRoles", + keyColumn: "Id", + keyValue: "15b3c37c-d76a-4b52-a53f-5ec7e65bedcc"); + + migrationBuilder.DeleteData( + table: "AspNetRoles", + keyColumn: "Id", + keyValue: "1d283a73-9ec4-4897-a709-2f21f1347cd6"); + + migrationBuilder.DeleteData( + table: "AspNetRoles", + keyColumn: "Id", + keyValue: "502db14d-ec3d-42f2-a56c-c14ad1217dda"); + + migrationBuilder.CreateTable( + name: "Accounts", + columns: table => new + { + AccountId = table.Column(type: "integer", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + CardId = table.Column(type: "integer", nullable: false), + Iban = table.Column(type: "text", nullable: false), + AccountType = table.Column(type: "text", nullable: false), + BranchTelephone = table.Column(type: "text", nullable: false), + BranchAddress = table.Column(type: "text", nullable: false), + BranchName = table.Column(type: "text", nullable: false), + OwnerName = table.Column(type: "text", nullable: false), + OwnerLastName = table.Column(type: "text", nullable: false), + OwnerId = table.Column(type: "text", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Accounts", x => x.AccountId); + }); + + migrationBuilder.CreateTable( + name: "Transactions", + columns: table => new + { + TransactionId = table.Column(type: "integer", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + SourceAccountId = table.Column(type: "integer", nullable: false), + DestinationAccountId = table.Column(type: "integer", nullable: false), + Amount = table.Column(type: "numeric", nullable: false), + Date = table.Column(type: "timestamp with time zone", nullable: false), + Type = table.Column(type: "text", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Transactions", x => x.TransactionId); + table.ForeignKey( + name: "FK_Transactions_Accounts_DestinationAccountId", + column: x => x.DestinationAccountId, + principalTable: "Accounts", + principalColumn: "AccountId", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_Transactions_Accounts_SourceAccountId", + column: x => x.SourceAccountId, + principalTable: "Accounts", + principalColumn: "AccountId", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.InsertData( + table: "AspNetRoles", + columns: new[] { "Id", "ConcurrencyStamp", "Name", "NormalizedName" }, + values: new object[,] + { + { "0a8ca877-f408-4d10-806f-1714e41b0186", null, "Admin", "ADMIN" }, + { "913a4192-89c6-4d8e-873c-52d9695f8d59", null, "DataAnalyst", "DATAANALYST" }, + { "fa9ffeed-788f-40cd-a86b-3e5ad7a03e0b", null, "DataAdmin", "DATAADMIN" } + }); + + migrationBuilder.CreateIndex( + name: "IX_Transactions_DestinationAccountId", + table: "Transactions", + column: "DestinationAccountId"); + + migrationBuilder.CreateIndex( + name: "IX_Transactions_SourceAccountId", + table: "Transactions", + column: "SourceAccountId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "Transactions"); + + migrationBuilder.DropTable( + name: "Accounts"); + + migrationBuilder.DeleteData( + table: "AspNetRoles", + keyColumn: "Id", + keyValue: "0a8ca877-f408-4d10-806f-1714e41b0186"); + + migrationBuilder.DeleteData( + table: "AspNetRoles", + keyColumn: "Id", + keyValue: "913a4192-89c6-4d8e-873c-52d9695f8d59"); + + migrationBuilder.DeleteData( + table: "AspNetRoles", + keyColumn: "Id", + keyValue: "fa9ffeed-788f-40cd-a86b-3e5ad7a03e0b"); + + migrationBuilder.InsertData( + table: "AspNetRoles", + columns: new[] { "Id", "ConcurrencyStamp", "Name", "NormalizedName" }, + values: new object[,] + { + { "15b3c37c-d76a-4b52-a53f-5ec7e65bedcc", null, "DataAnalyst", "DATAANALYST" }, + { "1d283a73-9ec4-4897-a709-2f21f1347cd6", null, "DataAdmin", "DATAADMIN" }, + { "502db14d-ec3d-42f2-a56c-c14ad1217dda", null, "Admin", "ADMIN" } + }); + } + } +} diff --git a/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs b/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs index d5c3c23..fa089cc 100644 --- a/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs @@ -22,7 +22,55 @@ protected override void BuildModel(ModelBuilder modelBuilder) NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - modelBuilder.Entity("Infrastructure.Entities.AppUser", b => + modelBuilder.Entity("Domain.Entities.Account", b => + { + b.Property("AccountId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("AccountId")); + + b.Property("AccountType") + .IsRequired() + .HasColumnType("text"); + + b.Property("BranchAddress") + .IsRequired() + .HasColumnType("text"); + + b.Property("BranchName") + .IsRequired() + .HasColumnType("text"); + + b.Property("BranchTelephone") + .IsRequired() + .HasColumnType("text"); + + b.Property("CardId") + .HasColumnType("integer"); + + b.Property("Iban") + .IsRequired() + .HasColumnType("text"); + + b.Property("OwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("OwnerLastName") + .IsRequired() + .HasColumnType("text"); + + b.Property("OwnerName") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("AccountId"); + + b.ToTable("Accounts"); + }); + + modelBuilder.Entity("Domain.Entities.AppUser", b => { b.Property("Id") .HasColumnType("text"); @@ -96,6 +144,39 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("AspNetUsers", (string)null); }); + modelBuilder.Entity("Domain.Entities.Transaction", b => + { + b.Property("TransactionId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TransactionId")); + + b.Property("Amount") + .HasColumnType("numeric"); + + b.Property("Date") + .HasColumnType("timestamp with time zone"); + + b.Property("DestinationAccountId") + .HasColumnType("integer"); + + b.Property("SourceAccountId") + .HasColumnType("integer"); + + b.Property("Type") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("TransactionId"); + + b.HasIndex("DestinationAccountId"); + + b.HasIndex("SourceAccountId"); + + b.ToTable("Transactions"); + }); + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => { b.Property("Id") @@ -124,19 +205,19 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasData( new { - Id = "502db14d-ec3d-42f2-a56c-c14ad1217dda", + Id = "0a8ca877-f408-4d10-806f-1714e41b0186", Name = "Admin", NormalizedName = "ADMIN" }, new { - Id = "1d283a73-9ec4-4897-a709-2f21f1347cd6", + Id = "fa9ffeed-788f-40cd-a86b-3e5ad7a03e0b", Name = "DataAdmin", NormalizedName = "DATAADMIN" }, new { - Id = "15b3c37c-d76a-4b52-a53f-5ec7e65bedcc", + Id = "913a4192-89c6-4d8e-873c-52d9695f8d59", Name = "DataAnalyst", NormalizedName = "DATAANALYST" }); @@ -248,6 +329,25 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("AspNetUserTokens", (string)null); }); + modelBuilder.Entity("Domain.Entities.Transaction", b => + { + b.HasOne("Domain.Entities.Account", "DestinationAccount") + .WithMany("DestinationTransactions") + .HasForeignKey("DestinationAccountId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Domain.Entities.Account", "SourceAccount") + .WithMany("SourceTransactions") + .HasForeignKey("SourceAccountId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("DestinationAccount"); + + b.Navigation("SourceAccount"); + }); + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => { b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) @@ -259,7 +359,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => { - b.HasOne("Infrastructure.Entities.AppUser", null) + b.HasOne("Domain.Entities.AppUser", null) .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) @@ -268,7 +368,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => { - b.HasOne("Infrastructure.Entities.AppUser", null) + b.HasOne("Domain.Entities.AppUser", null) .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) @@ -283,7 +383,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.HasOne("Infrastructure.Entities.AppUser", null) + b.HasOne("Domain.Entities.AppUser", null) .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) @@ -292,12 +392,19 @@ protected override void BuildModel(ModelBuilder modelBuilder) modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => { - b.HasOne("Infrastructure.Entities.AppUser", null) + b.HasOne("Domain.Entities.AppUser", null) .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); }); + + modelBuilder.Entity("Domain.Entities.Account", b => + { + b.Navigation("DestinationTransactions"); + + b.Navigation("SourceTransactions"); + }); #pragma warning restore 612, 618 } } diff --git a/src/Web/Program.cs b/src/Web/Program.cs index f730163..b1780ad 100644 --- a/src/Web/Program.cs +++ b/src/Web/Program.cs @@ -91,6 +91,8 @@ new string[]{} } }); + + }); builder.Services.AddCors(options => From 62ca18ea32e709e3821b48486d9a5a388950c269 Mon Sep 17 00:00:00 2001 From: amiralirahimii Date: Sun, 18 Aug 2024 12:51:32 +0330 Subject: [PATCH 3/4] fix: fix incosistent names of Csv models and change Ids to long --- src/Application/DTOs/TransactionCsv/TransactionCsvModel.cs | 6 +++--- src/Application/Services/TransactionService.cs | 4 ++-- src/Domain/Entities/Account.cs | 4 ++-- src/Domain/Entities/Transaction.cs | 6 +++--- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/Application/DTOs/TransactionCsv/TransactionCsvModel.cs b/src/Application/DTOs/TransactionCsv/TransactionCsvModel.cs index 55a03f8..895f937 100644 --- a/src/Application/DTOs/TransactionCsv/TransactionCsvModel.cs +++ b/src/Application/DTOs/TransactionCsv/TransactionCsvModel.cs @@ -5,9 +5,9 @@ namespace Application.DTOs.TransactionCsv; public class TransactionCsvModel { - public int TransactionId { get; set; } - public int SourceAccount { get; set; } - public int DestinationAccount { get; set; } + public long TransactionID { get; set; } + public long SourceAcount { get; set; } + public long DestiantionAccount { get; set; } public decimal Amount { get; set; } [TypeConverter(typeof(PersianDateConverter))] public DateTime Date { get; set; } diff --git a/src/Application/Services/TransactionService.cs b/src/Application/Services/TransactionService.cs index c221f33..1d4868e 100644 --- a/src/Application/Services/TransactionService.cs +++ b/src/Application/Services/TransactionService.cs @@ -22,8 +22,8 @@ public async Task AddTransactionsFromCsvAsync(string filePath) var transactions = transactionCsvModels.Select(csvModel => new Transaction { - SourceAccountId = csvModel.SourceAccount, - DestinationAccountId = csvModel.DestinationAccount, + SourceAccountId = csvModel.SourceAcount, + DestinationAccountId = csvModel.DestiantionAccount, Amount = csvModel.Amount, Date = csvModel.Date, Type = csvModel.Type diff --git a/src/Domain/Entities/Account.cs b/src/Domain/Entities/Account.cs index c16996f..40a3b89 100644 --- a/src/Domain/Entities/Account.cs +++ b/src/Domain/Entities/Account.cs @@ -4,8 +4,8 @@ namespace Domain.Entities; [Table("Accounts")] public class Account { - public int AccountId { get; set; } - public int CardId { get; set; } + public long AccountId { get; set; } + public long CardId { get; set; } public string Iban { get; set; } = String.Empty; public string AccountType { get; set; } = String.Empty; public string BranchTelephone { get; set; } = String.Empty; diff --git a/src/Domain/Entities/Transaction.cs b/src/Domain/Entities/Transaction.cs index e3d8a21..64d3929 100644 --- a/src/Domain/Entities/Transaction.cs +++ b/src/Domain/Entities/Transaction.cs @@ -4,10 +4,10 @@ namespace Domain.Entities; [Table("Transactions")] public class Transaction { - public int TransactionId { get; set; } - public int SourceAccountId { get; set; } + public long TransactionId { get; set; } + public long SourceAccountId { get; set; } public Account SourceAccount { get; set; } - public int DestinationAccountId { get; set; } + public long DestinationAccountId { get; set; } public Account DestinationAccount { get; set; } public decimal Amount { get; set; } public DateTime Date { get; set; } From 3bf78a53c41dc7c8a2fb39439129de386c77d356 Mon Sep 17 00:00:00 2001 From: amiralirahimii Date: Sun, 18 Aug 2024 12:52:09 +0330 Subject: [PATCH 4/4] fix: apply migration --- .../20240818091853_CastIdsToLong.Designer.cs | 414 ++++++++++++++++++ .../20240818091853_CastIdsToLong.cs | 159 +++++++ .../ApplicationDbContextModelSnapshot.cs | 30 +- 3 files changed, 588 insertions(+), 15 deletions(-) create mode 100644 src/Infrastructure/Migrations/20240818091853_CastIdsToLong.Designer.cs create mode 100644 src/Infrastructure/Migrations/20240818091853_CastIdsToLong.cs diff --git a/src/Infrastructure/Migrations/20240818091853_CastIdsToLong.Designer.cs b/src/Infrastructure/Migrations/20240818091853_CastIdsToLong.Designer.cs new file mode 100644 index 0000000..aad3c71 --- /dev/null +++ b/src/Infrastructure/Migrations/20240818091853_CastIdsToLong.Designer.cs @@ -0,0 +1,414 @@ +// +using System; +using Infrastructure.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace Infrastructure.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20240818091853_CastIdsToLong")] + partial class CastIdsToLong + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.7") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Domain.Entities.Account", b => + { + b.Property("AccountId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("AccountId")); + + b.Property("AccountType") + .IsRequired() + .HasColumnType("text"); + + b.Property("BranchAddress") + .IsRequired() + .HasColumnType("text"); + + b.Property("BranchName") + .IsRequired() + .HasColumnType("text"); + + b.Property("BranchTelephone") + .IsRequired() + .HasColumnType("text"); + + b.Property("CardId") + .HasColumnType("bigint"); + + b.Property("Iban") + .IsRequired() + .HasColumnType("text"); + + b.Property("OwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("OwnerLastName") + .IsRequired() + .HasColumnType("text"); + + b.Property("OwnerName") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("AccountId"); + + b.ToTable("Accounts"); + }); + + modelBuilder.Entity("Domain.Entities.AppUser", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("AccessFailedCount") + .HasColumnType("integer"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("text"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("boolean"); + + b.Property("FirstName") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("LastName") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("LockoutEnabled") + .HasColumnType("boolean"); + + b.Property("LockoutEnd") + .HasColumnType("timestamp with time zone"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("PasswordHash") + .HasColumnType("text"); + + b.Property("PhoneNumber") + .HasColumnType("text"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("boolean"); + + b.Property("SecurityStamp") + .HasColumnType("text"); + + b.Property("TwoFactorEnabled") + .HasColumnType("boolean"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("Domain.Entities.Transaction", b => + { + b.Property("TransactionId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TransactionId")); + + b.Property("Amount") + .HasColumnType("numeric"); + + b.Property("Date") + .HasColumnType("timestamp with time zone"); + + b.Property("DestinationAccountId") + .HasColumnType("bigint"); + + b.Property("SourceAccountId") + .HasColumnType("bigint"); + + b.Property("Type") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("TransactionId"); + + b.HasIndex("DestinationAccountId"); + + b.HasIndex("SourceAccountId"); + + b.ToTable("Transactions"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("text"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("AspNetRoles", (string)null); + + b.HasData( + new + { + Id = "bef465d8-3d0e-469f-8b45-5f9be9c40f66", + Name = "Admin", + NormalizedName = "ADMIN" + }, + new + { + Id = "2d28da36-33b9-4ac1-b08f-50b4dd6855d2", + Name = "DataAdmin", + NormalizedName = "DATAADMIN" + }, + new + { + Id = "021da0cb-1048-4551-9858-90c98ee66289", + Name = "DataAnalyst", + NormalizedName = "DATAANALYST" + }); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("text"); + + b.Property("ClaimValue") + .HasColumnType("text"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("text"); + + b.Property("ClaimValue") + .HasColumnType("text"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("text"); + + b.Property("ProviderKey") + .HasColumnType("text"); + + b.Property("ProviderDisplayName") + .HasColumnType("text"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("RoleId") + .HasColumnType("text"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("LoginProvider") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("Value") + .HasColumnType("text"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Domain.Entities.Transaction", b => + { + b.HasOne("Domain.Entities.Account", "DestinationAccount") + .WithMany("DestinationTransactions") + .HasForeignKey("DestinationAccountId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Domain.Entities.Account", "SourceAccount") + .WithMany("SourceTransactions") + .HasForeignKey("SourceAccountId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("DestinationAccount"); + + b.Navigation("SourceAccount"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Domain.Entities.AppUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Domain.Entities.AppUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Domain.Entities.AppUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Domain.Entities.AppUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Domain.Entities.Account", b => + { + b.Navigation("DestinationTransactions"); + + b.Navigation("SourceTransactions"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Infrastructure/Migrations/20240818091853_CastIdsToLong.cs b/src/Infrastructure/Migrations/20240818091853_CastIdsToLong.cs new file mode 100644 index 0000000..79da6aa --- /dev/null +++ b/src/Infrastructure/Migrations/20240818091853_CastIdsToLong.cs @@ -0,0 +1,159 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional + +namespace Infrastructure.Migrations +{ + /// + public partial class CastIdsToLong : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DeleteData( + table: "AspNetRoles", + keyColumn: "Id", + keyValue: "0a8ca877-f408-4d10-806f-1714e41b0186"); + + migrationBuilder.DeleteData( + table: "AspNetRoles", + keyColumn: "Id", + keyValue: "913a4192-89c6-4d8e-873c-52d9695f8d59"); + + migrationBuilder.DeleteData( + table: "AspNetRoles", + keyColumn: "Id", + keyValue: "fa9ffeed-788f-40cd-a86b-3e5ad7a03e0b"); + + migrationBuilder.AlterColumn( + name: "SourceAccountId", + table: "Transactions", + type: "bigint", + nullable: false, + oldClrType: typeof(int), + oldType: "integer"); + + migrationBuilder.AlterColumn( + name: "DestinationAccountId", + table: "Transactions", + type: "bigint", + nullable: false, + oldClrType: typeof(int), + oldType: "integer"); + + migrationBuilder.AlterColumn( + name: "TransactionId", + table: "Transactions", + type: "bigint", + nullable: false, + oldClrType: typeof(int), + oldType: "integer") + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn) + .OldAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + migrationBuilder.AlterColumn( + name: "CardId", + table: "Accounts", + type: "bigint", + nullable: false, + oldClrType: typeof(int), + oldType: "integer"); + + migrationBuilder.AlterColumn( + name: "AccountId", + table: "Accounts", + type: "bigint", + nullable: false, + oldClrType: typeof(int), + oldType: "integer") + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn) + .OldAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + migrationBuilder.InsertData( + table: "AspNetRoles", + columns: new[] { "Id", "ConcurrencyStamp", "Name", "NormalizedName" }, + values: new object[,] + { + { "021da0cb-1048-4551-9858-90c98ee66289", null, "DataAnalyst", "DATAANALYST" }, + { "2d28da36-33b9-4ac1-b08f-50b4dd6855d2", null, "DataAdmin", "DATAADMIN" }, + { "bef465d8-3d0e-469f-8b45-5f9be9c40f66", null, "Admin", "ADMIN" } + }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DeleteData( + table: "AspNetRoles", + keyColumn: "Id", + keyValue: "021da0cb-1048-4551-9858-90c98ee66289"); + + migrationBuilder.DeleteData( + table: "AspNetRoles", + keyColumn: "Id", + keyValue: "2d28da36-33b9-4ac1-b08f-50b4dd6855d2"); + + migrationBuilder.DeleteData( + table: "AspNetRoles", + keyColumn: "Id", + keyValue: "bef465d8-3d0e-469f-8b45-5f9be9c40f66"); + + migrationBuilder.AlterColumn( + name: "SourceAccountId", + table: "Transactions", + type: "integer", + nullable: false, + oldClrType: typeof(long), + oldType: "bigint"); + + migrationBuilder.AlterColumn( + name: "DestinationAccountId", + table: "Transactions", + type: "integer", + nullable: false, + oldClrType: typeof(long), + oldType: "bigint"); + + migrationBuilder.AlterColumn( + name: "TransactionId", + table: "Transactions", + type: "integer", + nullable: false, + oldClrType: typeof(long), + oldType: "bigint") + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn) + .OldAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + migrationBuilder.AlterColumn( + name: "CardId", + table: "Accounts", + type: "integer", + nullable: false, + oldClrType: typeof(long), + oldType: "bigint"); + + migrationBuilder.AlterColumn( + name: "AccountId", + table: "Accounts", + type: "integer", + nullable: false, + oldClrType: typeof(long), + oldType: "bigint") + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn) + .OldAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + migrationBuilder.InsertData( + table: "AspNetRoles", + columns: new[] { "Id", "ConcurrencyStamp", "Name", "NormalizedName" }, + values: new object[,] + { + { "0a8ca877-f408-4d10-806f-1714e41b0186", null, "Admin", "ADMIN" }, + { "913a4192-89c6-4d8e-873c-52d9695f8d59", null, "DataAnalyst", "DATAANALYST" }, + { "fa9ffeed-788f-40cd-a86b-3e5ad7a03e0b", null, "DataAdmin", "DATAADMIN" } + }); + } + } +} diff --git a/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs b/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs index fa089cc..d3c4ba7 100644 --- a/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/src/Infrastructure/Migrations/ApplicationDbContextModelSnapshot.cs @@ -24,11 +24,11 @@ protected override void BuildModel(ModelBuilder modelBuilder) modelBuilder.Entity("Domain.Entities.Account", b => { - b.Property("AccountId") + b.Property("AccountId") .ValueGeneratedOnAdd() - .HasColumnType("integer"); + .HasColumnType("bigint"); - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("AccountId")); + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("AccountId")); b.Property("AccountType") .IsRequired() @@ -46,8 +46,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) .IsRequired() .HasColumnType("text"); - b.Property("CardId") - .HasColumnType("integer"); + b.Property("CardId") + .HasColumnType("bigint"); b.Property("Iban") .IsRequired() @@ -146,11 +146,11 @@ protected override void BuildModel(ModelBuilder modelBuilder) modelBuilder.Entity("Domain.Entities.Transaction", b => { - b.Property("TransactionId") + b.Property("TransactionId") .ValueGeneratedOnAdd() - .HasColumnType("integer"); + .HasColumnType("bigint"); - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TransactionId")); + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("TransactionId")); b.Property("Amount") .HasColumnType("numeric"); @@ -158,11 +158,11 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("Date") .HasColumnType("timestamp with time zone"); - b.Property("DestinationAccountId") - .HasColumnType("integer"); + b.Property("DestinationAccountId") + .HasColumnType("bigint"); - b.Property("SourceAccountId") - .HasColumnType("integer"); + b.Property("SourceAccountId") + .HasColumnType("bigint"); b.Property("Type") .IsRequired() @@ -205,19 +205,19 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasData( new { - Id = "0a8ca877-f408-4d10-806f-1714e41b0186", + Id = "bef465d8-3d0e-469f-8b45-5f9be9c40f66", Name = "Admin", NormalizedName = "ADMIN" }, new { - Id = "fa9ffeed-788f-40cd-a86b-3e5ad7a03e0b", + Id = "2d28da36-33b9-4ac1-b08f-50b4dd6855d2", Name = "DataAdmin", NormalizedName = "DATAADMIN" }, new { - Id = "913a4192-89c6-4d8e-873c-52d9695f8d59", + Id = "021da0cb-1048-4551-9858-90c98ee66289", Name = "DataAnalyst", NormalizedName = "DATAANALYST" });