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 @@
+