merchant onboarding process completed
This commit is contained in:
@ -1,6 +1,7 @@
|
|||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.EntityFrameworkCore.Design;
|
using Microsoft.EntityFrameworkCore.Design;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Singer_Hexdive.Models;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
||||||
namespace Singer_Hexdive
|
namespace Singer_Hexdive
|
||||||
@ -9,6 +10,12 @@ namespace Singer_Hexdive
|
|||||||
{
|
{
|
||||||
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options) { }
|
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options) { }
|
||||||
|
|
||||||
|
public DbSet<IdentificationType> IdentificationTypes { get; set; }
|
||||||
|
public DbSet<MerchantBankDetails> MerchantBankDetails { get; set; }
|
||||||
|
public DbSet<MerchantBusinessDetail> MerchantBusinessDetail { get; set; }
|
||||||
|
public DbSet<MerchantPersonalDetail> MerchantPersonalDetail { get; set; }
|
||||||
|
public DbSet<MerchantShareHolders> MerchantShareHolders { get; set; }
|
||||||
|
public DbSet<MerchantDirectors> MerchantDirectors { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ApplicationDbContextFactory : IDesignTimeDbContextFactory<ApplicationDbContext>
|
public class ApplicationDbContextFactory : IDesignTimeDbContextFactory<ApplicationDbContext>
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Singer_Hexdive.Models.IOs;
|
||||||
|
using Singer_Hexdive.Services.FunctionHandlers;
|
||||||
|
|
||||||
namespace Singer_Hexdive.Controllers
|
namespace Singer_Hexdive.Controllers
|
||||||
{
|
{
|
||||||
@ -7,5 +9,18 @@ namespace Singer_Hexdive.Controllers
|
|||||||
[Route("api")]
|
[Route("api")]
|
||||||
public class ApiController : ControllerBase
|
public class ApiController : ControllerBase
|
||||||
{
|
{
|
||||||
|
private readonly MerchantManager _merchantManager;
|
||||||
|
|
||||||
|
public ApiController(MerchantManager merchantManager)
|
||||||
|
{
|
||||||
|
_merchantManager = merchantManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost("merchant")]
|
||||||
|
public async Task<IActionResult> MerchantExecute([FromBody] ApiRequest request)
|
||||||
|
{
|
||||||
|
var response = await _merchantManager.Execute(request);
|
||||||
|
return StatusCode(response.StatusCode, response);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
9
Singer_Hexdive/Enums/ApprovedStatus.cs
Normal file
9
Singer_Hexdive/Enums/ApprovedStatus.cs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
namespace Singer_Hexdive.Enums
|
||||||
|
{
|
||||||
|
public enum ApprovedStatus
|
||||||
|
{
|
||||||
|
pending = 1,
|
||||||
|
approved = 2,
|
||||||
|
rejected = 3
|
||||||
|
}
|
||||||
|
}
|
8
Singer_Hexdive/Enums/BankAccountTypes.cs
Normal file
8
Singer_Hexdive/Enums/BankAccountTypes.cs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
namespace Singer_Hexdive.Enums
|
||||||
|
{
|
||||||
|
public enum BankAccountTypes
|
||||||
|
{
|
||||||
|
Saving = 1,
|
||||||
|
Current = 2,
|
||||||
|
}
|
||||||
|
}
|
7
Singer_Hexdive/Exceptions/NotfoundException.cs
Normal file
7
Singer_Hexdive/Exceptions/NotfoundException.cs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
namespace Singer_Hexdive.Exceptions
|
||||||
|
{
|
||||||
|
public class NotfoundException : Exception
|
||||||
|
{
|
||||||
|
public NotfoundException(string message) : base(message) { }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
using Singer_Hexdive.Models;
|
||||||
|
|
||||||
|
namespace Singer_Hexdive.Interfaces.RepositoryInterfaces
|
||||||
|
{
|
||||||
|
public interface IMerchantRepository
|
||||||
|
{
|
||||||
|
//-------------------------------------------Merchant_Onboarding_Start----------------------------------//
|
||||||
|
Task<object> GetM_PersonalDetailsAsync(int merchantId);
|
||||||
|
Task<object> PostM_PersonalDetailsAsync(MerchantPersonalDetail merchantPersonalDetail);
|
||||||
|
Task<object> GetM_BusinessDetailsAsync(int merchantId);
|
||||||
|
Task<object> PostM_BusinessDetailsAsync(MerchantBusinessDetail merchantBusinessDetail);
|
||||||
|
Task<object> PostM_ShareHolderDetailsAsync(MerchantShareHolders merchantShareHolders);
|
||||||
|
Task<object> PostM_DiretorDetailsAsync(MerchantDirectors merchantDirectors);
|
||||||
|
Task<object> GetM_BankDetailsAsync(int merchantId);
|
||||||
|
Task<object> PostM_BankDetailsAsync(MerchantBankDetails merchantBankDetails);
|
||||||
|
//Task<object> PostM_ReviewDetails(object payload);
|
||||||
|
//Task<object> PostM_CompleteOnboarding(object payload);
|
||||||
|
//-------------------------------------------Merchant_Onboarding_End----------------------------------//
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------Merchant_Management_Start----------------------------------//
|
||||||
|
//Task<object> GetMerchantDetails(string merchantId);
|
||||||
|
//Task<object> UpdateMerchantDetails(string merchantId, object payload);
|
||||||
|
//Task<object> DeleteMerchant(string merchantId);
|
||||||
|
//-------------------------------------------Merchant_Management_End----------------------------------//
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------Merchant_SupportFunctions_Start----------------------------//
|
||||||
|
Task<int> CheckApprovedStatus(int merchantId, string tableName);
|
||||||
|
//-------------------------------------------Merchant_SupportFunctions_End------------------------------//
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
using System.Text.Json;
|
||||||
|
|
||||||
|
namespace Singer_Hexdive.Interfaces.ServiceInterfaces
|
||||||
|
{
|
||||||
|
public abstract class BaseMerchantService
|
||||||
|
{
|
||||||
|
protected Dictionary<string, JsonElement> DeserializePayload(object payload)
|
||||||
|
{
|
||||||
|
if (payload is null)
|
||||||
|
throw new ArgumentNullException(nameof(payload));
|
||||||
|
|
||||||
|
var json = JsonSerializer.Serialize(payload);
|
||||||
|
return JsonSerializer.Deserialize<Dictionary<string, JsonElement>>(json)
|
||||||
|
?? throw new InvalidOperationException("Failed to deserialize payload.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract Task<object> GetM_PersonalDetails(object payload);
|
||||||
|
public abstract Task<object> PostM_PersonalDetails(object payload);
|
||||||
|
public abstract Task<object> GetM_BusinessDetails(object payload);
|
||||||
|
public abstract Task<object> PostM_BusinessDetails(object payload);
|
||||||
|
public abstract Task<object> GetM_BankDetails(object payload);
|
||||||
|
public abstract Task<object> PostM_BankDetails(object payload);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
14
Singer_Hexdive/Models/IOs/ApiRequest.cs
Normal file
14
Singer_Hexdive/Models/IOs/ApiRequest.cs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
|
||||||
|
namespace Singer_Hexdive.Models.IOs
|
||||||
|
{
|
||||||
|
[NotMapped]
|
||||||
|
public class ApiRequest
|
||||||
|
{
|
||||||
|
public string FunctionName { get; set; }
|
||||||
|
|
||||||
|
public object Payload { get; set; }
|
||||||
|
|
||||||
|
public string Reference { get; set; }
|
||||||
|
}
|
||||||
|
}
|
12
Singer_Hexdive/Models/IOs/ApiResponse.cs
Normal file
12
Singer_Hexdive/Models/IOs/ApiResponse.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
|
||||||
|
namespace Singer_Hexdive.Models.IOs
|
||||||
|
{
|
||||||
|
[NotMapped]
|
||||||
|
public class ApiResponse<T>
|
||||||
|
{
|
||||||
|
public int StatusCode { get; set; }
|
||||||
|
public string Message { get; set; }
|
||||||
|
public T Data { get; set; }
|
||||||
|
}
|
||||||
|
}
|
12
Singer_Hexdive/Models/IdentificationType.cs
Normal file
12
Singer_Hexdive/Models/IdentificationType.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace Singer_Hexdive.Models
|
||||||
|
{
|
||||||
|
public class IdentificationType
|
||||||
|
{
|
||||||
|
[Key]
|
||||||
|
public int Id { get; set; }
|
||||||
|
public string IdType { get; set; }
|
||||||
|
public DateTime CreateAt { get; set; }
|
||||||
|
}
|
||||||
|
}
|
25
Singer_Hexdive/Models/MerchantBankDetails.cs
Normal file
25
Singer_Hexdive/Models/MerchantBankDetails.cs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using Singer_Hexdive.Enums;
|
||||||
|
|
||||||
|
namespace Singer_Hexdive.Models
|
||||||
|
{
|
||||||
|
public class MerchantBankDetails
|
||||||
|
{
|
||||||
|
[Key]
|
||||||
|
public int Id { get; set; }
|
||||||
|
public int FK_MId { get; set; }
|
||||||
|
[ForeignKey("FK_MId")]
|
||||||
|
public MerchantPersonalDetail MerchantPersonalDetail { get; set; }
|
||||||
|
public string CurrencyCode { get; set; }
|
||||||
|
public BankAccountTypes BankAccountTypes { get; set; }
|
||||||
|
public string M_BankName { get; set; }
|
||||||
|
public string M_BankBranchName { get; set; }
|
||||||
|
public int M_BankAccNum { get; set; }
|
||||||
|
public string M_BankAccHolderName { get; set; }
|
||||||
|
public string M_BankHolderIdNum { get; set; }
|
||||||
|
public string M_PhoneNum { get; set; }
|
||||||
|
public ApprovedStatus ApprovedStatus { get; set; } = ApprovedStatus.pending;
|
||||||
|
public DateTime CreatedAt { get; set; }
|
||||||
|
}
|
||||||
|
}
|
26
Singer_Hexdive/Models/MerchantBusinessDetail.cs
Normal file
26
Singer_Hexdive/Models/MerchantBusinessDetail.cs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using Singer_Hexdive.Enums;
|
||||||
|
|
||||||
|
namespace Singer_Hexdive.Models
|
||||||
|
{
|
||||||
|
public class MerchantBusinessDetail
|
||||||
|
{
|
||||||
|
[Key]
|
||||||
|
public int Id { get; set; }
|
||||||
|
public int FK_MechantId { get; set; }
|
||||||
|
[ForeignKey("FK_MechantId")]
|
||||||
|
public MerchantPersonalDetail merchantPersonalDetail { get; set; }
|
||||||
|
public string BusinessName { get; set; }
|
||||||
|
public string BusinessDoingName { get; set; }
|
||||||
|
public string BusinessRegNum { get; set; }
|
||||||
|
public string BusinessIncomeTaxNum { get; set; }
|
||||||
|
public DateTime BusinessRegDate { get; set; }
|
||||||
|
public DateTime BusinessIncomeDate { get; set; }
|
||||||
|
public string BusinessAddress { get; set; }
|
||||||
|
public string BusinessCity { get; set; }
|
||||||
|
public int PostalCode { get; set; }
|
||||||
|
public ApprovedStatus ApprovedStatus { get; set; } = ApprovedStatus.pending;
|
||||||
|
public DateTime CreatedAt { get; set; }
|
||||||
|
}
|
||||||
|
}
|
21
Singer_Hexdive/Models/MerchantDirectors.cs
Normal file
21
Singer_Hexdive/Models/MerchantDirectors.cs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
|
||||||
|
namespace Singer_Hexdive.Models
|
||||||
|
{
|
||||||
|
public class MerchantDirectors
|
||||||
|
{
|
||||||
|
[Key]
|
||||||
|
public int DirectorId { get; set; }
|
||||||
|
public int FK_MBusinessId { get; set; }
|
||||||
|
[ForeignKey("FK_MBusinessId")]
|
||||||
|
public MerchantBusinessDetail MerchantBusinessDetail { get; set; }
|
||||||
|
public string D_FullName { get; set; }
|
||||||
|
public string D_IdNumber { get; set; }
|
||||||
|
public DateTime Birthday { get; set; }
|
||||||
|
public string D_MobileNumber { get; set; }
|
||||||
|
public string D_Address { get; set; }
|
||||||
|
public DateTime createdAt { get; set; } = DateTime.Now;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
27
Singer_Hexdive/Models/MerchantPersonalDetail.cs
Normal file
27
Singer_Hexdive/Models/MerchantPersonalDetail.cs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using Singer_Hexdive.Enums;
|
||||||
|
|
||||||
|
namespace Singer_Hexdive.Models
|
||||||
|
{
|
||||||
|
public class MerchantPersonalDetail
|
||||||
|
{
|
||||||
|
[Key]
|
||||||
|
public int MechantId { get; set; }
|
||||||
|
public string MerchantName { get; set; }
|
||||||
|
public int FK_IdType { get; set; }
|
||||||
|
[ForeignKey("FK_IdType")]
|
||||||
|
public IdentificationType IdentificationType { get; set; }
|
||||||
|
public string M_IdNumber { get; set; }
|
||||||
|
public string M_Email { get; set; }
|
||||||
|
public string M_Mobile_Primary { get; set; }
|
||||||
|
public string? M_Mobile_Secondary { get; set; }
|
||||||
|
public string M_Address { get; set; }
|
||||||
|
public string M_City { get; set; }
|
||||||
|
public int M_PostalCode { get; set; }
|
||||||
|
public DateTime OnboardDate { get; set; }
|
||||||
|
public DateTime CreatedAt { get; set; } = DateTime.Now;
|
||||||
|
public bool IsActive { get; set; } = true;
|
||||||
|
public ApprovedStatus ApprovedStatus { get; set; } = ApprovedStatus.pending;
|
||||||
|
}
|
||||||
|
}
|
21
Singer_Hexdive/Models/MerchantShareHolders.cs
Normal file
21
Singer_Hexdive/Models/MerchantShareHolders.cs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
|
||||||
|
namespace Singer_Hexdive.Models
|
||||||
|
{
|
||||||
|
public class MerchantShareHolders
|
||||||
|
{
|
||||||
|
[Key]
|
||||||
|
public int ShareHolderId { get; set; }
|
||||||
|
public int FK_MBusinessId { get; set; }
|
||||||
|
[ForeignKey("FK_MBusinessId")]
|
||||||
|
public MerchantBusinessDetail MerchantBusinessDetail { get; set; }
|
||||||
|
public string S_FullName { get; set; }
|
||||||
|
public string S_IdNumber { get; set; }
|
||||||
|
public DateTime Bithday { get; set; }
|
||||||
|
public string S_MobileNumber { get; set; }
|
||||||
|
public string S_Address { get; set; }
|
||||||
|
public decimal S_SharePercentage { get; set; }
|
||||||
|
public DateTime createdAt { get; set; } = DateTime.Now;
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,15 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Singer_Hexdive;
|
||||||
|
|
||||||
var builder = WebApplication.CreateBuilder(args);
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
|
||||||
|
builder.Services.AddDbContext<ApplicationDbContext>(option =>
|
||||||
|
option.UseMySql(
|
||||||
|
builder.Configuration.GetConnectionString("DefaultConnection"),
|
||||||
|
ServerVersion.AutoDetect(builder.Configuration.GetConnectionString("DefaultConnection"))
|
||||||
|
));
|
||||||
|
|
||||||
// Add services to the container.
|
// Add services to the container.
|
||||||
|
|
||||||
builder.Services.AddControllers();
|
builder.Services.AddControllers();
|
||||||
@ -7,6 +17,12 @@ builder.Services.AddControllers();
|
|||||||
builder.Services.AddEndpointsApiExplorer();
|
builder.Services.AddEndpointsApiExplorer();
|
||||||
builder.Services.AddSwaggerGen();
|
builder.Services.AddSwaggerGen();
|
||||||
|
|
||||||
|
builder.Services.AddControllers()
|
||||||
|
.AddJsonOptions(options =>
|
||||||
|
{
|
||||||
|
options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
|
||||||
|
});
|
||||||
|
|
||||||
var app = builder.Build();
|
var app = builder.Build();
|
||||||
|
|
||||||
// Configure the HTTP request pipeline.
|
// Configure the HTTP request pipeline.
|
||||||
|
146
Singer_Hexdive/Repositories/MerchantRepository.cs
Normal file
146
Singer_Hexdive/Repositories/MerchantRepository.cs
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Singer_Hexdive.Exceptions;
|
||||||
|
using Singer_Hexdive.Interfaces.RepositoryInterfaces;
|
||||||
|
using Singer_Hexdive.Models;
|
||||||
|
|
||||||
|
namespace Singer_Hexdive.Repositories
|
||||||
|
{
|
||||||
|
public class MerchantRepository : IMerchantRepository
|
||||||
|
{
|
||||||
|
private readonly ApplicationDbContext _context;
|
||||||
|
|
||||||
|
public MerchantRepository(ApplicationDbContext applicationDbContext)
|
||||||
|
{
|
||||||
|
_context = applicationDbContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------Merchant_Onboarding_Start----------------------------------//
|
||||||
|
public async Task<object> GetM_PersonalDetailsAsync(int merchantId)
|
||||||
|
{
|
||||||
|
var merchantPersonalDetail = await _context.MerchantPersonalDetail
|
||||||
|
.Where(m => m.MechantId == merchantId)
|
||||||
|
.FirstOrDefaultAsync();
|
||||||
|
if (merchantPersonalDetail == null)
|
||||||
|
{
|
||||||
|
throw new NotfoundException($"Merchant presonal deatils with ID {merchantId} not found.");
|
||||||
|
}
|
||||||
|
return merchantPersonalDetail;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<object> PostM_PersonalDetailsAsync(MerchantPersonalDetail merchantPersonalDetail)
|
||||||
|
{
|
||||||
|
await _context.MerchantPersonalDetail.AddAsync(merchantPersonalDetail);
|
||||||
|
await _context.SaveChangesAsync();
|
||||||
|
return merchantPersonalDetail;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<object> GetM_BusinessDetailsAsync(int merchantId)
|
||||||
|
{
|
||||||
|
var merchantBusinessDetail = await _context.MerchantBusinessDetail
|
||||||
|
.Where(m => m.FK_MechantId == merchantId)
|
||||||
|
.FirstOrDefaultAsync();
|
||||||
|
|
||||||
|
if (merchantBusinessDetail == null)
|
||||||
|
{
|
||||||
|
throw new NotfoundException($"Merchant business deatils with ID {merchantId} not found.");
|
||||||
|
}
|
||||||
|
|
||||||
|
var merchantShareHolders = await _context.MerchantShareHolders
|
||||||
|
.Where(m => m.FK_MBusinessId == merchantBusinessDetail.Id)
|
||||||
|
.ToListAsync();
|
||||||
|
var merchantDirectors = await _context.MerchantDirectors
|
||||||
|
.Where(m => m.FK_MBusinessId == merchantBusinessDetail.Id)
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
var details = new
|
||||||
|
{
|
||||||
|
BusinessDetails = merchantBusinessDetail,
|
||||||
|
ShareHolders = merchantShareHolders,
|
||||||
|
Directors = merchantDirectors
|
||||||
|
};
|
||||||
|
return details;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<object> PostM_BusinessDetailsAsync(MerchantBusinessDetail merchantBusinessDetail)
|
||||||
|
{
|
||||||
|
await _context.MerchantBusinessDetail.AddAsync(merchantBusinessDetail);
|
||||||
|
await _context.SaveChangesAsync();
|
||||||
|
return merchantBusinessDetail;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<object> PostM_ShareHolderDetailsAsync(MerchantShareHolders merchantShareHolders)
|
||||||
|
{
|
||||||
|
await _context.MerchantShareHolders.AddAsync(merchantShareHolders);
|
||||||
|
await _context.SaveChangesAsync();
|
||||||
|
return merchantShareHolders;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<object> PostM_DiretorDetailsAsync(MerchantDirectors merchantDirectors)
|
||||||
|
{
|
||||||
|
await _context.MerchantDirectors.AddAsync(merchantDirectors);
|
||||||
|
await _context.SaveChangesAsync();
|
||||||
|
return merchantDirectors;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<object> GetM_BankDetailsAsync(int merchantId)
|
||||||
|
{
|
||||||
|
var merchantBankDetail = await _context.MerchantBankDetails
|
||||||
|
.Where(m => m.FK_MId == merchantId)
|
||||||
|
.FirstOrDefaultAsync();
|
||||||
|
if (merchantBankDetail == null)
|
||||||
|
{
|
||||||
|
throw new NotfoundException($"Merchant Bank deatils with ID {merchantId} not found.");
|
||||||
|
}
|
||||||
|
return merchantBankDetail;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<object> PostM_BankDetailsAsync(MerchantBankDetails merchantBankDetails)
|
||||||
|
{
|
||||||
|
await _context.MerchantBankDetails.AddAsync(merchantBankDetails);
|
||||||
|
await _context.SaveChangesAsync();
|
||||||
|
return merchantBankDetails;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------Merchant_Onboarding_End------------------------------------//
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------Merchant_Management_Start----------------------------------//
|
||||||
|
//-------------------------------------------Merchant_Management_End------------------------------------//
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------Merchant_SupportFunctions_Start----------------------------//
|
||||||
|
public async Task<int> CheckApprovedStatus(int merchantId, string tableName)
|
||||||
|
{
|
||||||
|
object? approveSatatus = null;
|
||||||
|
|
||||||
|
switch (tableName)
|
||||||
|
{
|
||||||
|
case "MerchantPersonalDetail":
|
||||||
|
approveSatatus = await _context.MerchantPersonalDetail
|
||||||
|
.Where(m => m.MechantId == merchantId)
|
||||||
|
.Select(m => new { m.ApprovedStatus })
|
||||||
|
.FirstOrDefaultAsync();
|
||||||
|
break;
|
||||||
|
case "MerchantBusinessDetail":
|
||||||
|
approveSatatus = await _context.MerchantBusinessDetail
|
||||||
|
.Where(m => m.FK_MechantId == merchantId)
|
||||||
|
.Select(m => new { m.ApprovedStatus })
|
||||||
|
.FirstOrDefaultAsync();
|
||||||
|
break;
|
||||||
|
case "MerchantBankDetail":
|
||||||
|
approveSatatus = await _context.MerchantBankDetails
|
||||||
|
.Where(m => m.FK_MId == merchantId)
|
||||||
|
.Select(m => new { m.ApprovedStatus })
|
||||||
|
.FirstOrDefaultAsync();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new ArgumentException("Invalid table name provided.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return (int)approveSatatus;
|
||||||
|
}
|
||||||
|
//-------------------------------------------Merchant_SupportFunctions_End------------------------------//
|
||||||
|
}
|
||||||
|
}
|
71
Singer_Hexdive/Services/FunctionHandlers/MerchantManager.cs
Normal file
71
Singer_Hexdive/Services/FunctionHandlers/MerchantManager.cs
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
using Singer_Hexdive.Exceptions;
|
||||||
|
using Singer_Hexdive.Interfaces.ServiceInterfaces;
|
||||||
|
using Singer_Hexdive.Models.IOs;
|
||||||
|
|
||||||
|
namespace Singer_Hexdive.Services.FunctionHandlers
|
||||||
|
{
|
||||||
|
public class MerchantManager
|
||||||
|
{
|
||||||
|
private readonly Dictionary<string, Func<object, Task<object>>> _functionHandler;
|
||||||
|
|
||||||
|
public MerchantManager(BaseMerchantService merchantService)
|
||||||
|
{
|
||||||
|
_functionHandler = new()
|
||||||
|
{
|
||||||
|
{"PostM_PersonalDetails", merchantService.PostM_PersonalDetails }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<ApiResponse<object>> Execute(ApiRequest request)
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
if (!_functionHandler.TryGetValue(request.FunctionName, out var handler))
|
||||||
|
{
|
||||||
|
return new ApiResponse<object>
|
||||||
|
{
|
||||||
|
StatusCode = 404,
|
||||||
|
Message = $"Function '{request.FunctionName}' not found.",
|
||||||
|
Data = null
|
||||||
|
};
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var results = await handler(request.Payload);
|
||||||
|
return new ApiResponse<object>
|
||||||
|
{
|
||||||
|
StatusCode = 200,
|
||||||
|
Message = "success",
|
||||||
|
Data = results
|
||||||
|
};
|
||||||
|
}
|
||||||
|
catch (NotfoundException ex)
|
||||||
|
{
|
||||||
|
return new ApiResponse<object>
|
||||||
|
{
|
||||||
|
StatusCode = 404,
|
||||||
|
Message = ex.Message,
|
||||||
|
Data = null
|
||||||
|
};
|
||||||
|
}
|
||||||
|
catch (InvalidOperationException ex)
|
||||||
|
{
|
||||||
|
return new ApiResponse<object>
|
||||||
|
{
|
||||||
|
StatusCode = 400,
|
||||||
|
Message = ex.Message,
|
||||||
|
Data = null
|
||||||
|
};
|
||||||
|
}
|
||||||
|
catch (ArgumentException ex)
|
||||||
|
{
|
||||||
|
return new ApiResponse<object>
|
||||||
|
{
|
||||||
|
StatusCode = 500,
|
||||||
|
Message = ex.Message,
|
||||||
|
Data = null
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
165
Singer_Hexdive/Services/MerchantService.cs
Normal file
165
Singer_Hexdive/Services/MerchantService.cs
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
using System.Text.Json;
|
||||||
|
using Singer_Hexdive.Enums;
|
||||||
|
using Singer_Hexdive.Interfaces.RepositoryInterfaces;
|
||||||
|
using Singer_Hexdive.Interfaces.ServiceInterfaces;
|
||||||
|
using Singer_Hexdive.Models;
|
||||||
|
using Singer_Hexdive.Validations;
|
||||||
|
|
||||||
|
namespace Singer_Hexdive.Services
|
||||||
|
{
|
||||||
|
public class MerchantService : BaseMerchantService
|
||||||
|
{
|
||||||
|
private readonly IMerchantRepository _merchantRepository;
|
||||||
|
|
||||||
|
public MerchantService(IMerchantRepository merchantRepository)
|
||||||
|
{
|
||||||
|
_merchantRepository = merchantRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------Merchant_Onboarding_Start----------------------------------//
|
||||||
|
public override async Task<object> GetM_PersonalDetails(object payload)
|
||||||
|
{
|
||||||
|
var data = DeserializePayload(payload);
|
||||||
|
int merchantId = FieldValidators.EnsureNotLessZero(data["MerchantId"].GetInt32(), "MerchantId");
|
||||||
|
var result = await _merchantRepository.GetM_PersonalDetailsAsync(merchantId);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
public override async Task<object> PostM_PersonalDetails(object payload)
|
||||||
|
{
|
||||||
|
var data = DeserializePayload(payload);
|
||||||
|
int approveStatus = await _merchantRepository.CheckApprovedStatus(data["MechantId"].GetInt32(), "MerchantPersonalDetail");
|
||||||
|
if (approveStatus == 2)
|
||||||
|
{
|
||||||
|
var merchantPersonalDetail = new MerchantPersonalDetail
|
||||||
|
{
|
||||||
|
MerchantName = FieldValidators.EnsureNotNullOrEmpty(data["MerchantName"].GetString(), "MerchantName"),
|
||||||
|
FK_IdType = FieldValidators.EnsureNotLessZero(data["FK_IdType"].GetInt32(), "FK_IdType"),
|
||||||
|
M_IdNumber = FieldValidators.EnsureNotNullOrEmpty(data["M_IdNumber"].GetString(), "M_IdNumber"),
|
||||||
|
M_Email = FieldValidators.EnsureValidEmail(data["M_Email"].GetString(), "M_Email"),
|
||||||
|
M_Mobile_Primary = FieldValidators.IsValidPhoneNumber(data["M_Mobile_Primary"].GetString(), "M_Mobile_Primary"),
|
||||||
|
M_Mobile_Secondary = FieldValidators.IsValidPhoneNumber(data["M_Mobile_Secondary"].GetString(), "M_Mobile_Secondary"),
|
||||||
|
M_Address = FieldValidators.EnsureNotNullOrEmpty(data["M_Address"].GetString(), "M_Address"),
|
||||||
|
M_City = FieldValidators.EnsureNotNullOrEmpty(data["M_City"].GetString(), "M_City"),
|
||||||
|
M_PostalCode = FieldValidators.EnsureNotLessZero(data["M_PostalCode"].GetInt32(), "M_PostalCode"),
|
||||||
|
OnboardDate = data["OnboardDate"].GetDateTime(),
|
||||||
|
};
|
||||||
|
var result = await _merchantRepository.PostM_PersonalDetailsAsync(merchantPersonalDetail);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Merchant is not approved for onboarding.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task<object> GetM_BusinessDetails(object payload)
|
||||||
|
{
|
||||||
|
var data = DeserializePayload(payload);
|
||||||
|
int merchantId = FieldValidators.EnsureNotLessZero(data["MerchantId"].GetInt32(), "MerchantId");
|
||||||
|
var result = await _merchantRepository.GetM_PersonalDetailsAsync(merchantId);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task<object> PostM_BusinessDetails(object payload)
|
||||||
|
{
|
||||||
|
var data = DeserializePayload(payload);
|
||||||
|
int approveStatus = await _merchantRepository.CheckApprovedStatus(data["MechantId"].GetInt32(), "MerchantBusinessDetail");
|
||||||
|
if (approveStatus == 2)
|
||||||
|
{
|
||||||
|
var merchantBusinessDetail = new MerchantBusinessDetail
|
||||||
|
{
|
||||||
|
FK_MechantId = FieldValidators.EnsureNotLessZero(data["MechantId"].GetInt32(), "MechantId"),
|
||||||
|
BusinessName = FieldValidators.EnsureNotNullOrEmpty(data["BusinessName"].GetString(), "BusinessName"),
|
||||||
|
BusinessDoingName = FieldValidators.EnsureNotNullOrEmpty(data["BusinessDoingName"].GetString(), "BusinessDoingName"),
|
||||||
|
BusinessRegNum = FieldValidators.EnsureNotNullOrEmpty(data["BusinessRegNum"].GetString(), "BusinessRegNum"),
|
||||||
|
BusinessIncomeTaxNum = FieldValidators.EnsureNotNullOrEmpty(data["BusinessIncomeTaxNum"].GetString(), "BusinessIncomeTaxNum"),
|
||||||
|
BusinessRegDate = data["BusinessRegDate"].GetDateTime(),
|
||||||
|
BusinessIncomeDate = data["BusinessIncomeDate"].GetDateTime(),
|
||||||
|
BusinessAddress = FieldValidators.EnsureNotNullOrEmpty(data["BusinessAddress"].GetString(), "BusinessAddress"),
|
||||||
|
BusinessCity = FieldValidators.EnsureNotNullOrEmpty(data["BusinessCity"].GetString(), "BusinessCity"),
|
||||||
|
PostalCode = FieldValidators.EnsureNotLessZero(data["PostalCode"].GetInt32(), "PostalCode"),
|
||||||
|
};
|
||||||
|
var result = (MerchantBusinessDetail)await _merchantRepository.PostM_BusinessDetailsAsync(merchantBusinessDetail);
|
||||||
|
|
||||||
|
|
||||||
|
if (data["ShareHolders"].ValueKind == JsonValueKind.Array)
|
||||||
|
{
|
||||||
|
foreach (var shareHolder in data["ShareHolders"].EnumerateArray())
|
||||||
|
{
|
||||||
|
var shareHolderDetail = new MerchantShareHolders
|
||||||
|
{
|
||||||
|
FK_MBusinessId = result.Id,
|
||||||
|
S_FullName = FieldValidators.EnsureNotNullOrEmpty(shareHolder.GetProperty("S_FullName").GetString(), "S_FullName"),
|
||||||
|
S_IdNumber = FieldValidators.EnsureNotNullOrEmpty(shareHolder.GetProperty("S_IdNumber").GetString(), "S_IdNumber"),
|
||||||
|
S_MobileNumber = FieldValidators.IsValidPhoneNumber(shareHolder.GetProperty("S_MobileNumber").GetString(), "S_MobileNumber"),
|
||||||
|
S_Address = FieldValidators.EnsureNotNullOrEmpty(shareHolder.GetProperty("S_Address").GetString(), "S_Address"),
|
||||||
|
S_SharePercentage = shareHolder.GetProperty("S_SharePercentage").GetDecimal(),
|
||||||
|
Bithday = shareHolder.GetProperty("Bithday").GetDateTime(),
|
||||||
|
};
|
||||||
|
await _merchantRepository.PostM_ShareHolderDetailsAsync(shareHolderDetail);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data["Directors"].ValueKind == JsonValueKind.Array)
|
||||||
|
{
|
||||||
|
foreach (var directors in data["Directors"].EnumerateArray())
|
||||||
|
{
|
||||||
|
var DirectorsDetail = new MerchantDirectors
|
||||||
|
{
|
||||||
|
FK_MBusinessId = result.Id,
|
||||||
|
D_FullName = FieldValidators.EnsureNotNullOrEmpty(directors.GetProperty("D_FullName").GetString(), "D_FullName"),
|
||||||
|
D_IdNumber = FieldValidators.EnsureNotNullOrEmpty(directors.GetProperty("D_IdNumber").GetString(), "D_IdNumber"),
|
||||||
|
D_MobileNumber = FieldValidators.IsValidPhoneNumber(directors.GetProperty("D_MobileNumber").GetString(), "D_MobileNumber"),
|
||||||
|
D_Address = FieldValidators.EnsureNotNullOrEmpty(directors.GetProperty("D_Address").GetString(), "D_Address"),
|
||||||
|
Birthday = directors.GetProperty("D_Bithday").GetDateTime(),
|
||||||
|
};
|
||||||
|
await _merchantRepository.PostM_DiretorDetailsAsync(DirectorsDetail);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Merchant is not approved for onboarding.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task<object> GetM_BankDetails(object payload)
|
||||||
|
{
|
||||||
|
var data = DeserializePayload(payload);
|
||||||
|
int merchantId = FieldValidators.EnsureNotLessZero(data["MerchantId"].GetInt32(), "MerchantId");
|
||||||
|
var result = await _merchantRepository.GetM_BankDetailsAsync(merchantId);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task<object> PostM_BankDetails(object payload)
|
||||||
|
{
|
||||||
|
var data = DeserializePayload(payload);
|
||||||
|
int approveStatus = await _merchantRepository.CheckApprovedStatus(data["MechantId"].GetInt32(), "MerchantBankDetail");
|
||||||
|
if (approveStatus == 2)
|
||||||
|
{
|
||||||
|
var merchantBankDetails = new MerchantBankDetails
|
||||||
|
{
|
||||||
|
FK_MId = FieldValidators.EnsureNotLessZero(data["MechantId"].GetInt32(), "MechantId"),
|
||||||
|
CurrencyCode = FieldValidators.EnsureNotNullOrEmpty(data["CurrencyCode"].GetString(), "CurrencyCode"),
|
||||||
|
BankAccountTypes = (BankAccountTypes)FieldValidators.EnsureNotLessZero(data["BankAccountTypes"].GetInt32(), "BankAccountTypes"),
|
||||||
|
M_BankName = FieldValidators.EnsureNotNullOrEmpty(data["M_BankName"].GetString(), "M_BankName"),
|
||||||
|
M_BankBranchName = FieldValidators.EnsureNotNullOrEmpty(data["M_BankBranchName"].GetString(), "M_BankBranchName"),
|
||||||
|
M_BankAccNum = FieldValidators.EnsureNotLessZero(data["M_BankAccNum"].GetInt32(), "M_BankAccNum"),
|
||||||
|
M_BankAccHolderName = FieldValidators.EnsureNotNullOrEmpty(data["M_BankAccHolderName"].GetString(), "M_BankAccHolderName"),
|
||||||
|
M_BankHolderIdNum = FieldValidators.EnsureNotNullOrEmpty(data["M_BankHolderIdNum"].GetString(), "M_BankHolderIdNum"),
|
||||||
|
M_PhoneNum = FieldValidators.IsValidPhoneNumber(data["M_PhoneNum"].GetString(), "M_PhoneNum")
|
||||||
|
};
|
||||||
|
var result = await _merchantRepository.PostM_BankDetailsAsync(merchantBankDetails);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Merchant is not approved for onboarding.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------Merchant_Onboarding_End----------------------------------//
|
||||||
|
}
|
||||||
|
}
|
@ -7,17 +7,12 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.3">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="8.0.3" />
|
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="8.0.3" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.6.2" />
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.6.2" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Folder Include="Interfaces\ServiceInterfaces\" />
|
|
||||||
<Folder Include="Interfaces\RepositoryInterfaces\" />
|
|
||||||
<Folder Include="Models\IOs\" />
|
|
||||||
<Folder Include="Validations\" />
|
|
||||||
<Folder Include="Services\" />
|
|
||||||
<Folder Include="Repositories\" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
92
Singer_Hexdive/Validations/FieldValidators.cs
Normal file
92
Singer_Hexdive/Validations/FieldValidators.cs
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
namespace Singer_Hexdive.Validations
|
||||||
|
{
|
||||||
|
public class FieldValidators
|
||||||
|
{
|
||||||
|
public static string EnsureNotNullOrEmpty(string value, string fieldName)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(value))
|
||||||
|
throw new ArgumentException($"{fieldName} cannot be empty.", fieldName);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int EnsureNotLessZero(int value, string fieldName)
|
||||||
|
{
|
||||||
|
if (value < 0)
|
||||||
|
throw new ArgumentException($"{fieldName} cannot be less than zero.", fieldName);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static decimal EnsureIsMin(decimal value, int minValue, string fieldName)
|
||||||
|
{
|
||||||
|
if (value > minValue)
|
||||||
|
throw new ArgumentException($"{fieldName} cannot be less than {minValue}.", fieldName);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static decimal EnsureIsMax(decimal value, int maxValue, string fieldName)
|
||||||
|
{
|
||||||
|
if (value < maxValue)
|
||||||
|
throw new ArgumentException($"{fieldName} cannot be less than {maxValue}.", fieldName);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//public static bool IsValidEmail(string email, string fieldName)
|
||||||
|
//{
|
||||||
|
// if (string.IsNullOrWhiteSpace(email))
|
||||||
|
// throw new ArgumentException($"{fieldName} cannot be empty.", fieldName);
|
||||||
|
// try
|
||||||
|
// {
|
||||||
|
// var addr = new System.Net.Mail.MailAddress(email);
|
||||||
|
// return addr.Address == email;
|
||||||
|
// }
|
||||||
|
// catch
|
||||||
|
// {
|
||||||
|
// throw new ArgumentException($"{fieldName} is not a valid .", fieldName);
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
|
public static string IsValidPhoneNumber(string phoneNumber, string fieldName)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(phoneNumber))
|
||||||
|
throw new ArgumentException($"{fieldName} cannot be empty.", fieldName);
|
||||||
|
|
||||||
|
|
||||||
|
if (!phoneNumber.All(char.IsDigit) || phoneNumber.Length != 10)
|
||||||
|
throw new ArgumentException($"{fieldName} must be exactly 10 digits.", fieldName);
|
||||||
|
|
||||||
|
return phoneNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static string EnsureValidEmail(string email, string fieldName)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(email))
|
||||||
|
throw new ArgumentException($"{fieldName} cannot be empty.", fieldName);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var addr = new System.Net.Mail.MailAddress(email);
|
||||||
|
if (addr.Address != email)
|
||||||
|
throw new ArgumentException($"{fieldName} is not a valid email address.", fieldName);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
throw new ArgumentException($"{fieldName} is not a valid email address.", fieldName);
|
||||||
|
}
|
||||||
|
|
||||||
|
return email;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,9 +1,12 @@
|
|||||||
{
|
{
|
||||||
"Logging": {
|
"Logging": {
|
||||||
"LogLevel": {
|
"LogLevel": {
|
||||||
"Default": "Information",
|
"Default": "Information",
|
||||||
"Microsoft.AspNetCore": "Warning"
|
"Microsoft.AspNetCore": "Warning"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"AllowedHosts": "*"
|
"ConnectionStrings": {
|
||||||
|
"DefaultConnection": "server=localhost;port=3306;database=singer;user=root;password="
|
||||||
|
},
|
||||||
|
"AllowedHosts": "*"
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user