fix store profile fields
This commit is contained in:
@@ -7,8 +7,8 @@ public interface IStoreRepository
|
|||||||
Task<Models.Store?> GetByIdAsync(Guid id);
|
Task<Models.Store?> GetByIdAsync(Guid id);
|
||||||
Task<Models.Store?> GetByIdWithRegionAsync(Guid id);
|
Task<Models.Store?> GetByIdWithRegionAsync(Guid id);
|
||||||
Task<List<Models.Store>> GetAllAsync();
|
Task<List<Models.Store>> GetAllAsync();
|
||||||
Task<List<Models.Store>> GetAllAsync(Guid? routeId, KycStatus? kycStatus, string? search, int page, int pageSize);
|
Task<List<Models.Store>> GetAllAsync(Guid? routeId, string? search, int page, int pageSize);
|
||||||
Task<int> GetCountAsync(Guid? routeId, KycStatus? kycStatus, string? search);
|
Task<int> GetCountAsync(Guid? routeId, string? search);
|
||||||
Task AddAsync(Models.Store entity);
|
Task AddAsync(Models.Store entity);
|
||||||
void Update(Models.Store entity);
|
void Update(Models.Store entity);
|
||||||
void Remove(Models.Store entity);
|
void Remove(Models.Store entity);
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
namespace Distribution.Features.Store.Kyc;
|
|
||||||
|
|
||||||
public interface IStoreKycDocumentRepository
|
|
||||||
{
|
|
||||||
Task<List<Models.StoreKycDocument>> GetByStoreIdAsync(Guid storeId);
|
|
||||||
Task AddAsync(Models.StoreKycDocument entity);
|
|
||||||
}
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
|
|
||||||
namespace Distribution.Features.Store.Kyc;
|
|
||||||
|
|
||||||
[ApiController]
|
|
||||||
[Route("api/stores/{storeId:guid}/kyc-documents")]
|
|
||||||
public class StoreKycDocumentController(StoreKycDocumentService service) : ControllerBase
|
|
||||||
{
|
|
||||||
[HttpGet]
|
|
||||||
public async Task<IActionResult> GetByStoreId(Guid storeId)
|
|
||||||
{
|
|
||||||
var result = await service.GetByStoreIdAsync(storeId);
|
|
||||||
return result is null ? NotFound() : Ok(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpPost]
|
|
||||||
public async Task<IActionResult> Upload(Guid storeId, [FromForm] UploadKycDocumentRequest request, CancellationToken ct)
|
|
||||||
{
|
|
||||||
var result = await service.UploadAsync(storeId, request, ct);
|
|
||||||
return result is null ? NotFound() : Ok(result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
namespace Distribution.Features.Store.Kyc;
|
|
||||||
|
|
||||||
public record UploadKycDocumentRequest(string DocumentType, IFormFile File);
|
|
||||||
|
|
||||||
public record StoreKycDocumentResponse(Guid Id, Guid StoreId, string DocumentType, string FileReference, DateTime UploadedAt);
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
using Distribution.Data;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
|
|
||||||
namespace Distribution.Features.Store.Kyc;
|
|
||||||
|
|
||||||
public class StoreKycDocumentRepository(AppDBContext context) : IStoreKycDocumentRepository
|
|
||||||
{
|
|
||||||
public async Task<List<Models.StoreKycDocument>> GetByStoreIdAsync(Guid storeId) =>
|
|
||||||
await context.StoreKycDocuments.Where(d => d.FK_StoreId == storeId && d.IsActive).ToListAsync();
|
|
||||||
|
|
||||||
public async Task AddAsync(Models.StoreKycDocument entity) =>
|
|
||||||
await context.StoreKycDocuments.AddAsync(entity);
|
|
||||||
}
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
using Distribution.Infra.Authorization;
|
|
||||||
using Distribution.Infra.UoW;
|
|
||||||
|
|
||||||
namespace Distribution.Features.Store.Kyc;
|
|
||||||
|
|
||||||
public class StoreKycDocumentService(
|
|
||||||
IStoreKycDocumentRepository repo,
|
|
||||||
IStoreRepository storeRepo,
|
|
||||||
IUnitOfWork uow,
|
|
||||||
ICurrentUserService currentUser,
|
|
||||||
IScopeAccessService scopeAccess,
|
|
||||||
IWebHostEnvironment env)
|
|
||||||
{
|
|
||||||
private const int GlobalScopeRoleLevel = 50;
|
|
||||||
|
|
||||||
private bool HasGlobalScope => currentUser.RoleLevel >= GlobalScopeRoleLevel;
|
|
||||||
|
|
||||||
private async Task<bool> HasStoreScopeAsync(Guid storeId)
|
|
||||||
{
|
|
||||||
if (HasGlobalScope || currentUser.UserId is null) return HasGlobalScope;
|
|
||||||
return await scopeAccess.HasStoreScopeAsync(currentUser.UserId.Value, storeId);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static StoreKycDocumentResponse ToResponse(Models.StoreKycDocument d) =>
|
|
||||||
new(d.Id, d.FK_StoreId, d.DocumentType, d.FileReference, d.UploadedAt);
|
|
||||||
|
|
||||||
public async Task<List<StoreKycDocumentResponse>?> GetByStoreIdAsync(Guid storeId)
|
|
||||||
{
|
|
||||||
if (!await HasStoreScopeAsync(storeId)) return null;
|
|
||||||
var docs = await repo.GetByStoreIdAsync(storeId);
|
|
||||||
return docs.Select(ToResponse).ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<StoreKycDocumentResponse?> UploadAsync(Guid storeId, UploadKycDocumentRequest request, CancellationToken ct = default)
|
|
||||||
{
|
|
||||||
var store = await storeRepo.GetByIdAsync(storeId);
|
|
||||||
if (store is null || !store.IsActive) return null;
|
|
||||||
if (!await HasStoreScopeAsync(storeId)) return null;
|
|
||||||
|
|
||||||
var uploadsRoot = Path.Combine(env.ContentRootPath, "wwwroot", "uploads", "kyc", storeId.ToString());
|
|
||||||
Directory.CreateDirectory(uploadsRoot);
|
|
||||||
var fileName = $"{Guid.NewGuid()}{Path.GetExtension(request.File.FileName)}";
|
|
||||||
var filePath = Path.Combine(uploadsRoot, fileName);
|
|
||||||
await using (var stream = new FileStream(filePath, FileMode.Create))
|
|
||||||
{
|
|
||||||
await request.File.CopyToAsync(stream, ct);
|
|
||||||
}
|
|
||||||
var fileReference = $"uploads/kyc/{storeId}/{fileName}";
|
|
||||||
|
|
||||||
var doc = new Models.StoreKycDocument
|
|
||||||
{
|
|
||||||
FK_StoreId = storeId,
|
|
||||||
DocumentType = request.DocumentType,
|
|
||||||
FileReference = fileReference,
|
|
||||||
UploadedAt = DateTime.Now
|
|
||||||
};
|
|
||||||
|
|
||||||
await uow.BeginAsync(ct);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await repo.AddAsync(doc);
|
|
||||||
await uow.CommitAsync(ct);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
await uow.RollbackAsync(ct);
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
return ToResponse(doc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -10,11 +10,10 @@ public class StoreController(StoreService service) : ControllerBase
|
|||||||
[HttpGet]
|
[HttpGet]
|
||||||
public async Task<IActionResult> GetAll(
|
public async Task<IActionResult> GetAll(
|
||||||
[FromQuery] Guid? routeId,
|
[FromQuery] Guid? routeId,
|
||||||
[FromQuery] KycStatus? kycStatus,
|
|
||||||
[FromQuery] string? search,
|
[FromQuery] string? search,
|
||||||
[FromQuery] int page = 1,
|
[FromQuery] int page = 1,
|
||||||
[FromQuery] int pageSize = 20) =>
|
[FromQuery] int pageSize = 20) =>
|
||||||
Ok(await service.GetAllAsync(routeId, kycStatus, search, page, pageSize));
|
Ok(await service.GetAllAsync(routeId, search, page, pageSize));
|
||||||
|
|
||||||
[HttpGet("{id:guid}")]
|
[HttpGet("{id:guid}")]
|
||||||
public async Task<IActionResult> GetById(Guid id)
|
public async Task<IActionResult> GetById(Guid id)
|
||||||
@@ -65,13 +64,6 @@ public class StoreController(StoreService service) : ControllerBase
|
|||||||
return result is null ? NotFound() : Ok(result);
|
return result is null ? NotFound() : Ok(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPut("{id:guid}/kyc/verify")]
|
|
||||||
public async Task<IActionResult> VerifyKyc(Guid id, VerifyKycRequest request, CancellationToken ct)
|
|
||||||
{
|
|
||||||
var result = await service.VerifyKycAsync(id, request, ct);
|
|
||||||
return result is null ? NotFound() : Ok(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpPut("{id:guid}/segment")]
|
[HttpPut("{id:guid}/segment")]
|
||||||
public async Task<IActionResult> ClassifySegment(Guid id, ClassifySegmentRequest request, CancellationToken ct)
|
public async Task<IActionResult> ClassifySegment(Guid id, ClassifySegmentRequest request, CancellationToken ct)
|
||||||
{
|
{
|
||||||
@@ -100,13 +92,6 @@ public class StoreController(StoreService service) : ControllerBase
|
|||||||
return result is null ? NotFound() : Ok(result);
|
return result is null ? NotFound() : Ok(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPatch("{id:guid}/kyc-status")]
|
|
||||||
public async Task<IActionResult> PatchKycStatus(Guid id, PatchKycStatusRequest request, CancellationToken ct)
|
|
||||||
{
|
|
||||||
var result = await service.VerifyKycAsync(id, new VerifyKycRequest(request.KycStatus, null), ct);
|
|
||||||
return result is null ? NotFound() : Ok(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpPatch("{id:guid}/status")]
|
[HttpPatch("{id:guid}/status")]
|
||||||
public async Task<IActionResult> PatchStatus(Guid id, PatchStoreStatusRequest request, CancellationToken ct)
|
public async Task<IActionResult> PatchStatus(Guid id, PatchStoreStatusRequest request, CancellationToken ct)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -4,29 +4,34 @@ namespace Distribution.Features.Store;
|
|||||||
|
|
||||||
public record CreateStoreRequest(
|
public record CreateStoreRequest(
|
||||||
Guid RouteId,
|
Guid RouteId,
|
||||||
string OwnerName,
|
string? OwnerName,
|
||||||
string StoreName,
|
|
||||||
string StoreAddress,
|
|
||||||
decimal Latitude,
|
|
||||||
decimal Longitude,
|
|
||||||
decimal OneTimeAmount,
|
|
||||||
decimal CreditAmount);
|
|
||||||
|
|
||||||
public record UpdateStoreRequest(
|
|
||||||
Guid RouteId,
|
|
||||||
string OwnerName,
|
|
||||||
string StoreName,
|
string StoreName,
|
||||||
string StoreAddress,
|
string StoreAddress,
|
||||||
decimal Latitude,
|
decimal Latitude,
|
||||||
decimal Longitude,
|
decimal Longitude,
|
||||||
decimal OneTimeAmount,
|
decimal OneTimeAmount,
|
||||||
decimal CreditAmount,
|
decimal CreditAmount,
|
||||||
bool IsActive = true);
|
decimal CreditLimit = 0,
|
||||||
|
string? ContactNumber = null);
|
||||||
|
|
||||||
|
public record UpdateStoreRequest(
|
||||||
|
Guid RouteId,
|
||||||
|
string? OwnerName,
|
||||||
|
string StoreName,
|
||||||
|
string StoreAddress,
|
||||||
|
decimal Latitude,
|
||||||
|
decimal Longitude,
|
||||||
|
decimal OneTimeAmount,
|
||||||
|
decimal CreditAmount,
|
||||||
|
bool IsActive = true,
|
||||||
|
decimal? CreditLimit = null,
|
||||||
|
string? ContactNumber = null);
|
||||||
|
|
||||||
public record StoreResponse(
|
public record StoreResponse(
|
||||||
Guid Id,
|
Guid Id,
|
||||||
Guid RouteId,
|
Guid RouteId,
|
||||||
string OwnerName,
|
string? OwnerName,
|
||||||
|
string? ContactNumber,
|
||||||
string StoreName,
|
string StoreName,
|
||||||
string StoreAddress,
|
string StoreAddress,
|
||||||
decimal Latitude,
|
decimal Latitude,
|
||||||
@@ -36,7 +41,6 @@ public record StoreResponse(
|
|||||||
decimal CreditLimit,
|
decimal CreditLimit,
|
||||||
decimal OutstandingBalance,
|
decimal OutstandingBalance,
|
||||||
string? Segment,
|
string? Segment,
|
||||||
KycStatus KycStatus,
|
|
||||||
bool IsActive,
|
bool IsActive,
|
||||||
DateTime CreatedAt);
|
DateTime CreatedAt);
|
||||||
|
|
||||||
@@ -44,8 +48,6 @@ public record UpdateCreditLimitRequest(decimal NewLimit, Guid ApproverId);
|
|||||||
|
|
||||||
public record UpdateOutstandingBalanceRequest(decimal NewBalance);
|
public record UpdateOutstandingBalanceRequest(decimal NewBalance);
|
||||||
|
|
||||||
public record VerifyKycRequest(KycStatus Status, string? Notes);
|
|
||||||
|
|
||||||
public record ClassifySegmentRequest(string Segment);
|
public record ClassifySegmentRequest(string Segment);
|
||||||
|
|
||||||
public record OutstandingBalanceResponse(Guid StoreId, decimal CreditLimit, decimal OutstandingBalance, decimal AvailableCredit);
|
public record OutstandingBalanceResponse(Guid StoreId, decimal CreditLimit, decimal OutstandingBalance, decimal AvailableCredit);
|
||||||
@@ -54,8 +56,6 @@ public record StoreVisitHistoryItem(Guid VisitId, DateTime VisitDate, Guid RepUs
|
|||||||
|
|
||||||
public record SchemeEligibilityResponse(bool Eligible, string? Reason);
|
public record SchemeEligibilityResponse(bool Eligible, string? Reason);
|
||||||
|
|
||||||
public record PatchKycStatusRequest(KycStatus KycStatus);
|
|
||||||
|
|
||||||
public record PatchStoreStatusRequest(bool IsActive);
|
public record PatchStoreStatusRequest(bool IsActive);
|
||||||
|
|
||||||
public record StoreDashboardResponse(Guid StoreId, string Period, int OrderCount, decimal TotalOrderValue, DateTime? LastOrderDate);
|
public record StoreDashboardResponse(Guid StoreId, string Period, int OrderCount, decimal TotalOrderValue, DateTime? LastOrderDate);
|
||||||
|
|||||||
@@ -18,23 +18,22 @@ public class StoreRepository(AppDBContext context) : IStoreRepository
|
|||||||
await context.Stores.ToListAsync();
|
await context.Stores.ToListAsync();
|
||||||
|
|
||||||
private static IQueryable<Models.Store> ApplyFilters(
|
private static IQueryable<Models.Store> ApplyFilters(
|
||||||
IQueryable<Models.Store> query, Guid? routeId, KycStatus? kycStatus, string? search) =>
|
IQueryable<Models.Store> query, Guid? routeId, string? search) =>
|
||||||
query
|
query
|
||||||
.Where(s => routeId == null || s.FK_RouteId == routeId)
|
.Where(s => routeId == null || s.FK_RouteId == routeId)
|
||||||
.Where(s => kycStatus == null || s.KycStatus == kycStatus)
|
|
||||||
.Where(s => string.IsNullOrWhiteSpace(search)
|
.Where(s => string.IsNullOrWhiteSpace(search)
|
||||||
|| s.StoreName.Contains(search)
|
|| s.StoreName.Contains(search)
|
||||||
|| s.OwnerName.Contains(search));
|
|| (s.OwnerName != null && s.OwnerName.Contains(search)));
|
||||||
|
|
||||||
public async Task<List<Models.Store>> GetAllAsync(Guid? routeId, KycStatus? kycStatus, string? search, int page, int pageSize) =>
|
public async Task<List<Models.Store>> GetAllAsync(Guid? routeId, string? search, int page, int pageSize) =>
|
||||||
await ApplyFilters(context.Stores, routeId, kycStatus, search)
|
await ApplyFilters(context.Stores, routeId, search)
|
||||||
.OrderBy(s => s.StoreName)
|
.OrderBy(s => s.StoreName)
|
||||||
.Skip((page - 1) * pageSize)
|
.Skip((page - 1) * pageSize)
|
||||||
.Take(pageSize)
|
.Take(pageSize)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
|
||||||
public async Task<int> GetCountAsync(Guid? routeId, KycStatus? kycStatus, string? search) =>
|
public async Task<int> GetCountAsync(Guid? routeId, string? search) =>
|
||||||
await ApplyFilters(context.Stores, routeId, kycStatus, search).CountAsync();
|
await ApplyFilters(context.Stores, routeId, search).CountAsync();
|
||||||
|
|
||||||
public async Task AddAsync(Models.Store entity) =>
|
public async Task AddAsync(Models.Store entity) =>
|
||||||
await context.Stores.AddAsync(entity);
|
await context.Stores.AddAsync(entity);
|
||||||
|
|||||||
@@ -21,16 +21,16 @@ public class StoreService(IStoreRepository repo, IUnitOfWork uow, ICurrentUserSe
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static StoreResponse ToResponse(Models.Store s) =>
|
private static StoreResponse ToResponse(Models.Store s) =>
|
||||||
new(s.Id, s.FK_RouteId, s.OwnerName, s.StoreName, s.StoreAddress, s.Latitude, s.Longitude, s.OneTimeAmount, s.CreditAmount,
|
new(s.Id, s.FK_RouteId, s.OwnerName, s.ContactNumber, s.StoreName, s.StoreAddress, s.Latitude, s.Longitude, s.OneTimeAmount, s.CreditAmount,
|
||||||
s.CreditLimit, s.OutstandingBalance, s.Segment, s.KycStatus, s.IsActive, s.CreatedAt);
|
s.CreditLimit, s.OutstandingBalance, s.Segment, s.IsActive, s.CreatedAt);
|
||||||
|
|
||||||
public async Task<PagedResponse<StoreResponse>> GetAllAsync(
|
public async Task<PagedResponse<StoreResponse>> GetAllAsync(
|
||||||
Guid? routeId, KycStatus? kycStatus, string? search, int page, int pageSize)
|
Guid? routeId, string? search, int page, int pageSize)
|
||||||
{
|
{
|
||||||
// Deactivated stores stay visible in the list showing Inactive — deactivate never
|
// Deactivated stores stay visible in the list showing Inactive — deactivate never
|
||||||
// removes the row, only marks it (same rule as Orders, see testbug.md #42).
|
// removes the row, only marks it (same rule as Orders, see testbug.md #42).
|
||||||
var total = await repo.GetCountAsync(routeId, kycStatus, search);
|
var total = await repo.GetCountAsync(routeId, search);
|
||||||
var stores = await repo.GetAllAsync(routeId, kycStatus, search, page, pageSize);
|
var stores = await repo.GetAllAsync(routeId, search, page, pageSize);
|
||||||
return new PagedResponse<StoreResponse>(page, pageSize, total, stores.Select(ToResponse).ToList());
|
return new PagedResponse<StoreResponse>(page, pageSize, total, stores.Select(ToResponse).ToList());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,12 +48,14 @@ public class StoreService(IStoreRepository repo, IUnitOfWork uow, ICurrentUserSe
|
|||||||
{
|
{
|
||||||
FK_RouteId = request.RouteId,
|
FK_RouteId = request.RouteId,
|
||||||
OwnerName = request.OwnerName,
|
OwnerName = request.OwnerName,
|
||||||
|
ContactNumber = request.ContactNumber,
|
||||||
StoreName = request.StoreName,
|
StoreName = request.StoreName,
|
||||||
StoreAddress = request.StoreAddress,
|
StoreAddress = request.StoreAddress,
|
||||||
Latitude = request.Latitude,
|
Latitude = request.Latitude,
|
||||||
Longitude = request.Longitude,
|
Longitude = request.Longitude,
|
||||||
OneTimeAmount = request.OneTimeAmount,
|
OneTimeAmount = request.OneTimeAmount,
|
||||||
CreditAmount = request.CreditAmount
|
CreditAmount = request.CreditAmount,
|
||||||
|
CreditLimit = request.CreditLimit
|
||||||
};
|
};
|
||||||
await uow.BeginAsync(ct);
|
await uow.BeginAsync(ct);
|
||||||
try
|
try
|
||||||
@@ -76,12 +78,14 @@ public class StoreService(IStoreRepository repo, IUnitOfWork uow, ICurrentUserSe
|
|||||||
if (!await HasStoreScopeAsync(id)) return null;
|
if (!await HasStoreScopeAsync(id)) return null;
|
||||||
store.FK_RouteId = request.RouteId;
|
store.FK_RouteId = request.RouteId;
|
||||||
store.OwnerName = request.OwnerName;
|
store.OwnerName = request.OwnerName;
|
||||||
|
store.ContactNumber = request.ContactNumber;
|
||||||
store.StoreName = request.StoreName;
|
store.StoreName = request.StoreName;
|
||||||
store.StoreAddress = request.StoreAddress;
|
store.StoreAddress = request.StoreAddress;
|
||||||
store.Latitude = request.Latitude;
|
store.Latitude = request.Latitude;
|
||||||
store.Longitude = request.Longitude;
|
store.Longitude = request.Longitude;
|
||||||
store.OneTimeAmount = request.OneTimeAmount;
|
store.OneTimeAmount = request.OneTimeAmount;
|
||||||
store.CreditAmount = request.CreditAmount;
|
store.CreditAmount = request.CreditAmount;
|
||||||
|
if (request.CreditLimit is not null) store.CreditLimit = request.CreditLimit.Value;
|
||||||
store.IsActive = request.IsActive;
|
store.IsActive = request.IsActive;
|
||||||
await uow.BeginAsync(ct);
|
await uow.BeginAsync(ct);
|
||||||
try
|
try
|
||||||
@@ -165,27 +169,6 @@ public class StoreService(IStoreRepository repo, IUnitOfWork uow, ICurrentUserSe
|
|||||||
if (!await HasStoreScopeAsync(id)) return null;
|
if (!await HasStoreScopeAsync(id)) return null;
|
||||||
return new OutstandingBalanceResponse(store.Id, store.CreditLimit, store.OutstandingBalance, store.CreditLimit - store.OutstandingBalance);
|
return new OutstandingBalanceResponse(store.Id, store.CreditLimit, store.OutstandingBalance, store.CreditLimit - store.OutstandingBalance);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<StoreResponse?> VerifyKycAsync(Guid id, VerifyKycRequest request, CancellationToken ct = default)
|
|
||||||
{
|
|
||||||
var store = await repo.GetByIdAsync(id);
|
|
||||||
if (store is null || !store.IsActive) return null;
|
|
||||||
if (!await HasStoreScopeAsync(id)) return null;
|
|
||||||
store.KycStatus = request.Status;
|
|
||||||
await uow.BeginAsync(ct);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
repo.Update(store);
|
|
||||||
await uow.CommitAsync(ct);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
await uow.RollbackAsync(ct);
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
return ToResponse(store);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<StoreResponse?> ClassifySegmentAsync(Guid id, ClassifySegmentRequest request, CancellationToken ct = default)
|
public async Task<StoreResponse?> ClassifySegmentAsync(Guid id, ClassifySegmentRequest request, CancellationToken ct = default)
|
||||||
{
|
{
|
||||||
var store = await repo.GetByIdAsync(id);
|
var store = await repo.GetByIdAsync(id);
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ namespace Distribution.Models
|
|||||||
{ Warehouse, Vehicle, External }
|
{ Warehouse, Vehicle, External }
|
||||||
|
|
||||||
|
|
||||||
public enum KycStatus { Pending, Verified, Rejected }
|
|
||||||
|
|
||||||
public enum MovementType { Sale, CustomerReturn, Transfer, Damage, Adjustment, Load, PurchaseReceipt, PurchaseReturn }
|
public enum MovementType { Sale, CustomerReturn, Transfer, Damage, Adjustment, Load, PurchaseReceipt, PurchaseReturn }
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,8 @@ namespace Distribution.Models
|
|||||||
{
|
{
|
||||||
public class Store : Template
|
public class Store : Template
|
||||||
{
|
{
|
||||||
public String OwnerName { get; set; }
|
public String? OwnerName { get; set; }
|
||||||
|
public String? ContactNumber { get; set; }
|
||||||
public String StoreName { get; set; }
|
public String StoreName { get; set; }
|
||||||
public String StoreAddress { get; set; }
|
public String StoreAddress { get; set; }
|
||||||
public decimal Latitude { get; set; } = 0;
|
public decimal Latitude { get; set; } = 0;
|
||||||
@@ -14,7 +15,6 @@ namespace Distribution.Models
|
|||||||
public decimal CreditLimit { get; set; } = 0;
|
public decimal CreditLimit { get; set; } = 0;
|
||||||
public decimal OutstandingBalance { get; set; } = 0;
|
public decimal OutstandingBalance { get; set; } = 0;
|
||||||
public String? Segment { get; set; } //Gold ,silver,key Account,high risk
|
public String? Segment { get; set; } //Gold ,silver,key Account,high risk
|
||||||
public KycStatus KycStatus { get; set; } = KycStatus.Pending;
|
|
||||||
|
|
||||||
public Guid FK_RouteId { get; set; }
|
public Guid FK_RouteId { get; set; }
|
||||||
[ForeignKey("FK_RouteId")]
|
[ForeignKey("FK_RouteId")]
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
using System.ComponentModel.DataAnnotations.Schema;
|
|
||||||
|
|
||||||
namespace Distribution.Models
|
|
||||||
{
|
|
||||||
public class StoreKycDocument : Template
|
|
||||||
{
|
|
||||||
public Guid FK_StoreId { get; set; }
|
|
||||||
[ForeignKey("FK_StoreId")]
|
|
||||||
public Store Store { get; set; }
|
|
||||||
public String DocumentType { get; set; }
|
|
||||||
public String FileReference { get; set; }
|
|
||||||
public DateTime UploadedAt { get; set; } = DateTime.Now;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -2,11 +2,9 @@ import { api } from '@/lib/api'
|
|||||||
import type {
|
import type {
|
||||||
PaginatedResponse,
|
PaginatedResponse,
|
||||||
StoreResponse,
|
StoreResponse,
|
||||||
KycDocumentResponse,
|
|
||||||
OutstandingBalanceResponse,
|
OutstandingBalanceResponse,
|
||||||
StoreDashboardResponse,
|
StoreDashboardResponse,
|
||||||
StoreVisitHistoryItem,
|
StoreVisitHistoryItem,
|
||||||
KycStatus,
|
|
||||||
} from '@/types/api'
|
} from '@/types/api'
|
||||||
|
|
||||||
import type { PageParams } from './master'
|
import type { PageParams } from './master'
|
||||||
@@ -15,7 +13,8 @@ import type { PageParams } from './master'
|
|||||||
|
|
||||||
export interface StoreBody {
|
export interface StoreBody {
|
||||||
routeId: string
|
routeId: string
|
||||||
ownerName: string
|
ownerName?: string | null
|
||||||
|
contactNumber?: string | null
|
||||||
storeName: string
|
storeName: string
|
||||||
storeAddress: string
|
storeAddress: string
|
||||||
latitude: number
|
latitude: number
|
||||||
@@ -28,7 +27,6 @@ export interface StoreBody {
|
|||||||
|
|
||||||
export interface StoreListParams extends PageParams {
|
export interface StoreListParams extends PageParams {
|
||||||
routeId?: string
|
routeId?: string
|
||||||
kycStatus?: KycStatus
|
|
||||||
search?: string
|
search?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,16 +51,6 @@ export const stores = {
|
|||||||
|
|
||||||
dashboard: (id: string, period?: string) =>
|
dashboard: (id: string, period?: string) =>
|
||||||
api.get<StoreDashboardResponse>(`/stores/${id}/dashboard`, { params: { period } }).then(r => r.data),
|
api.get<StoreDashboardResponse>(`/stores/${id}/dashboard`, { params: { period } }).then(r => r.data),
|
||||||
|
|
||||||
kycDocuments: (id: string) =>
|
|
||||||
api.get<KycDocumentResponse[]>(`/stores/${id}/kyc-documents`).then(r => r.data),
|
|
||||||
|
|
||||||
uploadKycDocument: (id: string, documentType: string, fileReference: string) =>
|
|
||||||
api.post<KycDocumentResponse>(`/stores/${id}/kyc-documents`, { documentType, fileReference }).then(r => r.data),
|
|
||||||
|
|
||||||
updateKycStatus: (id: string, kycStatus: KycStatus) =>
|
|
||||||
api.patch<StoreResponse>(`/stores/${id}/kyc-status`, { kycStatus }).then(r => r.data),
|
|
||||||
|
|
||||||
visitHistory: (id: string) =>
|
visitHistory: (id: string) =>
|
||||||
api.get<StoreVisitHistoryItem[]>(`/stores/${id}/visit-history`).then(r => r.data),
|
api.get<StoreVisitHistoryItem[]>(`/stores/${id}/visit-history`).then(r => r.data),
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user