diff --git a/.gitignore b/.gitignore index e289cd75..16768962 100644 --- a/.gitignore +++ b/.gitignore @@ -366,4 +366,6 @@ FodyWeavers.xsd appsettings.json appsettings.*.json -!appsettings.example.json \ No newline at end of file +!appsettings.example.json +# Docker compose override +SnakeAid.dockercompose.yml diff --git a/Directory.Packages.props b/Directory.Packages.props index f3e4765f..e9a40a32 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -39,6 +39,7 @@ + @@ -50,4 +51,4 @@ - + \ No newline at end of file diff --git a/SnakeAid.Core/Domains/SnakebiteIncident.cs b/SnakeAid.Core/Domains/SnakebiteIncident.cs index fbc6f7b2..1459bddb 100644 --- a/SnakeAid.Core/Domains/SnakebiteIncident.cs +++ b/SnakeAid.Core/Domains/SnakebiteIncident.cs @@ -70,4 +70,16 @@ public enum SnakebiteIncidentStatus Disputed = 6, Completed = 7 } + + public enum SnakebiteIncidentTrigger + { + Pending = 0, + Assigned = 1, + Finished = 2, + Cancelled = 3, + NoRescuerFound = 4, + Paid = 5, + Disputed = 6, + Completed = 7 + } } \ No newline at end of file diff --git a/SnakeAid.Core/StateMachines/IncidentStateMachine.cs b/SnakeAid.Core/StateMachines/IncidentStateMachine.cs new file mode 100644 index 00000000..ee8b76dd --- /dev/null +++ b/SnakeAid.Core/StateMachines/IncidentStateMachine.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SnakeAid.Core.StateMachines +{ + public class IncidentStateMachine + { + + } +} diff --git a/SnakeAid.Service/Implements/Email/EmailTemplateService.cs b/SnakeAid.Service/Implements/Email/EmailTemplateService.cs index 5b639680..dc5c6500 100644 --- a/SnakeAid.Service/Implements/Email/EmailTemplateService.cs +++ b/SnakeAid.Service/Implements/Email/EmailTemplateService.cs @@ -32,10 +32,30 @@ public EmailTemplateService( _emailProvider = emailProvider; // Initialize RazorLight engine - // Find template root in source code location, not bin output + // Handle both local development and Docker container paths var baseDir = AppContext.BaseDirectory; - var projectRoot = Directory.GetParent(baseDir)?.Parent?.Parent?.Parent?.Parent?.FullName; - _templateRoot = Path.Combine(projectRoot!, "SnakeAid.Service", "Implements", "Email", "Templates"); + string? projectRoot = null; + + // Try to find project root by going up from bin directory (local development) + var currentDir = new DirectoryInfo(baseDir); + while (currentDir != null && projectRoot == null) + { + // Look for solution file or specific project marker + if (Directory.Exists(Path.Combine(currentDir.FullName, "SnakeAid.Service"))) + { + projectRoot = currentDir.FullName; + break; + } + currentDir = currentDir.Parent; + } + + // If not found (Docker container), use /src path + if (string.IsNullOrEmpty(projectRoot)) + { + projectRoot = "/src"; + } + + _templateRoot = Path.Combine(projectRoot, "SnakeAid.Service", "Implements", "Email", "Templates"); // Create directory if it doesn't exist if (!Directory.Exists(_templateRoot)) diff --git a/SnakeAid.Service/Implements/SnakebiteIncidentService.cs b/SnakeAid.Service/Implements/SnakebiteIncidentService.cs index 55af1b29..e513f2ad 100644 --- a/SnakeAid.Service/Implements/SnakebiteIncidentService.cs +++ b/SnakeAid.Service/Implements/SnakebiteIncidentService.cs @@ -34,6 +34,38 @@ public SnakebiteIncidentService(IUnitOfWork unitOfWork, ILogg _configuration = configuration; } + public async Task> CancelIncidentAsync(Guid incidentId) + { + try + { + return await _unitOfWork.ExecuteInTransactionAsync(async () => + { + var existingIncident = await _unitOfWork.GetRepository().FirstOrDefaultAsync( + predicate: s => s.Id == incidentId + ); + if (existingIncident == null) + { + throw new NotFoundException("Snakebite incident not found."); + } + // Validate incident status - only allow cancelling for Pending incidents + if (existingIncident.Status != SnakebiteIncidentStatus.Pending && existingIncident.Status != SnakebiteIncidentStatus.Assigned) + { + throw new BadRequestException($"Cannot cancel incident with status: {existingIncident.Status}"); + } + existingIncident.Status = SnakebiteIncidentStatus.Cancelled; + _unitOfWork.GetRepository().Update(existingIncident); + await _unitOfWork.CommitAsync(); + var responseData = existingIncident.Adapt(); + return ApiResponseBuilder.BuildSuccessResponse(responseData, "Snakebite Incident cancelled successfully!"); + }); + } + catch (Exception ex) + { + _logger.LogError(ex, "Error cancelling snakebite incident: {Message}", ex.Message); + throw; + } + } + public async Task> CreateIncidentAsync(CreateIncidentRequest request, Guid userId) { try diff --git a/SnakeAid.Service/Interfaces/ISnakebiteIncidentService.cs b/SnakeAid.Service/Interfaces/ISnakebiteIncidentService.cs index 8c4edf31..3837df8e 100644 --- a/SnakeAid.Service/Interfaces/ISnakebiteIncidentService.cs +++ b/SnakeAid.Service/Interfaces/ISnakebiteIncidentService.cs @@ -20,6 +20,6 @@ public interface ISnakebiteIncidentService Task> UpdateSymptomReportAsync(Guid incidentId, UpdateSymptomReportRequest request); - + Task> CancelIncidentAsync(Guid incidentId); } } diff --git a/SnakeAid.Service/SnakeAid.Service.csproj b/SnakeAid.Service/SnakeAid.Service.csproj index 2c9310cc..0d897940 100644 --- a/SnakeAid.Service/SnakeAid.Service.csproj +++ b/SnakeAid.Service/SnakeAid.Service.csproj @@ -18,6 +18,7 @@ +