LingAdmin/Backend/LingAdmin.API/Controllers/RequisitionsController.cs

235 lines
7.6 KiB
C#

using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using LingAdmin.API.Data;
using LingAdmin.API.Models;
using LingAdmin.API.DTOs;
using Dapr.Client;
namespace LingAdmin.API.Controllers;
[ApiController]
[Route("api/[controller]")]
public class RequisitionsController : ControllerBase
{
private readonly AppDbContext _context;
private readonly DaprClient _daprClient;
private readonly ILogger<RequisitionsController> _logger;
public RequisitionsController(AppDbContext context, DaprClient daprClient, ILogger<RequisitionsController> logger)
{
_context = context;
_daprClient = daprClient;
_logger = logger;
}
[HttpGet]
public async Task<ActionResult<ApiResponse<List<object>>>> GetRequisitions()
{
try
{
var requisitions = await _context.Requisitions
.Select(r => new
{
id = r.Id,
reqNo = r.ReqNo,
requester = r.Requester,
department = r.Department,
date = r.Date.ToString("yyyy-MM-dd"),
status = r.Status,
totalAmount = r.TotalAmount
})
.ToListAsync();
return Ok(ApiResponse<List<object>>.Success(requisitions.Cast<object>().ToList()));
}
catch (Exception ex)
{
_logger.LogError(ex, "Error retrieving requisitions");
return StatusCode(500, ApiResponse<List<object>>.Error("Internal server error", 500));
}
}
[HttpGet("{id}")]
public async Task<ActionResult<ApiResponse<object>>> GetRequisition(int id)
{
try
{
var requisition = await _context.Requisitions
.Include(r => r.Items)
.FirstOrDefaultAsync(r => r.Id == id);
if (requisition == null)
{
return NotFound(ApiResponse<object>.Error("Requisition not found", 404));
}
var result = new
{
id = requisition.Id,
reqNo = requisition.ReqNo,
requester = requisition.Requester,
department = requisition.Department,
date = requisition.Date.ToString("yyyy-MM-dd"),
status = requisition.Status,
description = requisition.Description,
items = requisition.Items.Select(i => new
{
id = i.Id,
itemName = i.ItemName,
quantity = i.Quantity,
price = i.Price
}).ToList()
};
return Ok(ApiResponse<object>.Success(result));
}
catch (Exception ex)
{
_logger.LogError(ex, "Error retrieving requisition {Id}", id);
return StatusCode(500, ApiResponse<object>.Error("Internal server error", 500));
}
}
[HttpPost]
public async Task<ActionResult<ApiResponse<object>>> CreateRequisition(CreateRequisitionDto dto)
{
try
{
// Generate next requisition number
var lastReqNo = await _context.Requisitions
.OrderByDescending(r => r.Id)
.Select(r => r.ReqNo)
.FirstOrDefaultAsync();
int nextNumber = 1;
if (!string.IsNullOrEmpty(lastReqNo))
{
var numberPart = lastReqNo.Split('-').LastOrDefault();
if (int.TryParse(numberPart, out int current))
{
nextNumber = current + 1;
}
}
var reqNo = $"PR-{DateTime.Now.Year}{nextNumber:D3}";
var requisition = new Requisition
{
ReqNo = reqNo,
Requester = dto.Requester,
Department = dto.Department,
Date = dto.Date,
Status = dto.Status,
Description = dto.Description,
TotalAmount = dto.Items.Sum(i => i.Quantity * i.Price)
};
foreach (var itemDto in dto.Items)
{
requisition.Items.Add(new RequisitionItem
{
ItemName = itemDto.ItemName,
Quantity = itemDto.Quantity,
Price = itemDto.Price
});
}
_context.Requisitions.Add(requisition);
await _context.SaveChangesAsync();
// Publish event via Dapr
try
{
await _daprClient.PublishEventAsync("pubsub", "requisition-created", new
{
id = requisition.Id,
reqNo = requisition.ReqNo,
requester = requisition.Requester,
totalAmount = requisition.TotalAmount
});
}
catch (Exception pubEx)
{
_logger.LogWarning(pubEx, "Failed to publish requisition-created event");
}
return Ok(ApiResponse<object>.Success(new { id = requisition.Id }));
}
catch (Exception ex)
{
_logger.LogError(ex, "Error creating requisition");
return StatusCode(500, ApiResponse<object>.Error("Internal server error", 500));
}
}
[HttpPut("{id}")]
public async Task<ActionResult<ApiResponse<object>>> UpdateRequisition(int id, CreateRequisitionDto dto)
{
try
{
var requisition = await _context.Requisitions
.Include(r => r.Items)
.FirstOrDefaultAsync(r => r.Id == id);
if (requisition == null)
{
return NotFound(ApiResponse<object>.Error("Requisition not found", 404));
}
requisition.Requester = dto.Requester;
requisition.Department = dto.Department;
requisition.Date = dto.Date;
requisition.Status = dto.Status;
requisition.Description = dto.Description;
// Remove old items and add new ones
_context.RequisitionItems.RemoveRange(requisition.Items);
requisition.Items.Clear();
foreach (var itemDto in dto.Items)
{
requisition.Items.Add(new RequisitionItem
{
ItemName = itemDto.ItemName,
Quantity = itemDto.Quantity,
Price = itemDto.Price
});
}
requisition.TotalAmount = dto.Items.Sum(i => i.Quantity * i.Price);
await _context.SaveChangesAsync();
return Ok(ApiResponse<object>.Success(new { id = requisition.Id }));
}
catch (Exception ex)
{
_logger.LogError(ex, "Error updating requisition {Id}", id);
return StatusCode(500, ApiResponse<object>.Error("Internal server error", 500));
}
}
[HttpDelete("{id}")]
public async Task<ActionResult<ApiResponse<object>>> DeleteRequisition(int id)
{
try
{
var requisition = await _context.Requisitions.FindAsync(id);
if (requisition == null)
{
return NotFound(ApiResponse<object>.Error("Requisition not found", 404));
}
_context.Requisitions.Remove(requisition);
await _context.SaveChangesAsync();
return Ok(ApiResponse<object>.Success(new { }));
}
catch (Exception ex)
{
_logger.LogError(ex, "Error deleting requisition {Id}", id);
return StatusCode(500, ApiResponse<object>.Error("Internal server error", 500));
}
}
}