Initial project setup with domain, UoW, and API structure
Added .gitignore, solution, and project files for .NET 10. Introduced AGENTS.md and PLAN.md for guidelines and planning. Implemented appsettings.json, launchSettings.json, and MySQL config. Created AppDBContext and all domain models with composite keys. Added IUnitOfWork and EFUnitOfWork. Structured feature folders for Region, Route, Vehicle, Store, Warehouse, and Order with DTOs, repositories, services, and controllers. Added initial EF Core migrations and sample HTTP request. Registered dependencies and enabled OpenAPI in development.
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
namespace Distribution.Features.Store;
|
||||
|
||||
public interface IStoreRepository
|
||||
{
|
||||
Task<Models.Store?> GetByIdAsync(Guid id);
|
||||
Task<List<Models.Store>> GetAllAsync();
|
||||
Task AddAsync(Models.Store entity);
|
||||
void Update(Models.Store entity);
|
||||
void Remove(Models.Store entity);
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Distribution.Features.Store;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/stores")]
|
||||
public class StoreController(StoreService service) : ControllerBase
|
||||
{
|
||||
[HttpGet]
|
||||
public async Task<IActionResult> GetAll() =>
|
||||
Ok(await service.GetAllAsync());
|
||||
|
||||
[HttpGet("{id:guid}")]
|
||||
public async Task<IActionResult> GetById(Guid id)
|
||||
{
|
||||
var result = await service.GetByIdAsync(id);
|
||||
return result is null ? NotFound() : Ok(result);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> Create(CreateStoreRequest request, CancellationToken ct)
|
||||
{
|
||||
var result = await service.CreateAsync(request, ct);
|
||||
return CreatedAtAction(nameof(GetById), new { id = result.Id }, result);
|
||||
}
|
||||
|
||||
[HttpPut("{id:guid}")]
|
||||
public async Task<IActionResult> Update(Guid id, UpdateStoreRequest request, CancellationToken ct)
|
||||
{
|
||||
var result = await service.UpdateAsync(id, request, ct);
|
||||
return result is null ? NotFound() : Ok(result);
|
||||
}
|
||||
|
||||
[HttpDelete("{id:guid}")]
|
||||
public async Task<IActionResult> Delete(Guid id, CancellationToken ct)
|
||||
{
|
||||
var deleted = await service.DeleteAsync(id, ct);
|
||||
return deleted ? NoContent() : NotFound();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
namespace Distribution.Features.Store;
|
||||
|
||||
public record CreateStoreRequest(
|
||||
string OwnerName,
|
||||
string StoreName,
|
||||
string StoreAddress,
|
||||
decimal Latitude,
|
||||
decimal Longitude,
|
||||
decimal OneTimeAmount,
|
||||
decimal CreditAmount);
|
||||
|
||||
public record UpdateStoreRequest(
|
||||
string OwnerName,
|
||||
string StoreName,
|
||||
string StoreAddress,
|
||||
decimal Latitude,
|
||||
decimal Longitude,
|
||||
decimal OneTimeAmount,
|
||||
decimal CreditAmount);
|
||||
|
||||
public record StoreResponse(
|
||||
Guid Id,
|
||||
string OwnerName,
|
||||
string StoreName,
|
||||
string StoreAddress,
|
||||
decimal Latitude,
|
||||
decimal Longitude,
|
||||
decimal OneTimeAmount,
|
||||
decimal CreditAmount,
|
||||
bool IsActive,
|
||||
DateTime CreatedAt);
|
||||
@@ -0,0 +1,25 @@
|
||||
using Distribution.Data;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Distribution.Features.Store;
|
||||
|
||||
public class StoreRepository(AppDBContext context) : IStoreRepository
|
||||
{
|
||||
public async Task<Models.Store?> GetByIdAsync(Guid id) =>
|
||||
await context.Stores.FindAsync(id);
|
||||
|
||||
public async Task<List<Models.Store>> GetAllAsync() =>
|
||||
await context.Stores.ToListAsync();
|
||||
|
||||
public async Task AddAsync(Models.Store entity) =>
|
||||
await context.Stores.AddAsync(entity);
|
||||
|
||||
public void Update(Models.Store entity) =>
|
||||
context.Stores.Update(entity);
|
||||
|
||||
public void Remove(Models.Store entity)
|
||||
{
|
||||
entity.IsActive = false;
|
||||
context.Stores.Update(entity);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
using Distribution.Infra.UoW;
|
||||
|
||||
namespace Distribution.Features.Store;
|
||||
|
||||
public class StoreService(IStoreRepository repo, IUnitOfWork uow)
|
||||
{
|
||||
private static StoreResponse ToResponse(Models.Store s) =>
|
||||
new(s.Id, s.OwnerName, s.StoreName, s.StoreAddress, s.Latitude, s.Longitude, s.OneTimeAmount, s.CreditAmount, s.IsActive, s.CreatedAt);
|
||||
|
||||
public async Task<List<StoreResponse>> GetAllAsync() =>
|
||||
(await repo.GetAllAsync())
|
||||
.Where(s => s.IsActive)
|
||||
.Select(ToResponse)
|
||||
.ToList();
|
||||
|
||||
public async Task<StoreResponse?> GetByIdAsync(Guid id)
|
||||
{
|
||||
var store = await repo.GetByIdAsync(id);
|
||||
if (store is null || !store.IsActive) return null;
|
||||
return ToResponse(store);
|
||||
}
|
||||
|
||||
public async Task<StoreResponse> CreateAsync(CreateStoreRequest request, CancellationToken ct = default)
|
||||
{
|
||||
var store = new Models.Store
|
||||
{
|
||||
OwnerName = request.OwnerName,
|
||||
StoreName = request.StoreName,
|
||||
StoreAddress = request.StoreAddress,
|
||||
Latitude = request.Latitude,
|
||||
Longitude = request.Longitude,
|
||||
OneTimeAmount = request.OneTimeAmount,
|
||||
CreditAmount = request.CreditAmount
|
||||
};
|
||||
await uow.BeginAsync(ct);
|
||||
try
|
||||
{
|
||||
await repo.AddAsync(store);
|
||||
await uow.CommitAsync(ct);
|
||||
}
|
||||
catch
|
||||
{
|
||||
await uow.RollbackAsync(ct);
|
||||
throw;
|
||||
}
|
||||
return ToResponse(store);
|
||||
}
|
||||
|
||||
public async Task<StoreResponse?> UpdateAsync(Guid id, UpdateStoreRequest request, CancellationToken ct = default)
|
||||
{
|
||||
var store = await repo.GetByIdAsync(id);
|
||||
if (store is null || !store.IsActive) return null;
|
||||
store.OwnerName = request.OwnerName;
|
||||
store.StoreName = request.StoreName;
|
||||
store.StoreAddress = request.StoreAddress;
|
||||
store.Latitude = request.Latitude;
|
||||
store.Longitude = request.Longitude;
|
||||
store.OneTimeAmount = request.OneTimeAmount;
|
||||
store.CreditAmount = request.CreditAmount;
|
||||
await uow.BeginAsync(ct);
|
||||
try
|
||||
{
|
||||
repo.Update(store);
|
||||
await uow.CommitAsync(ct);
|
||||
}
|
||||
catch
|
||||
{
|
||||
await uow.RollbackAsync(ct);
|
||||
throw;
|
||||
}
|
||||
return ToResponse(store);
|
||||
}
|
||||
|
||||
public async Task<bool> DeleteAsync(Guid id, CancellationToken ct = default)
|
||||
{
|
||||
var store = await repo.GetByIdAsync(id);
|
||||
if (store is null || !store.IsActive) return false;
|
||||
await uow.BeginAsync(ct);
|
||||
try
|
||||
{
|
||||
repo.Remove(store);
|
||||
await uow.CommitAsync(ct);
|
||||
}
|
||||
catch
|
||||
{
|
||||
await uow.RollbackAsync(ct);
|
||||
throw;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user