mirror of
https://github.com/Sea-Haven-Industries/shoc-backend.git
synced 2026-09-30 07:13:12 +00:00
Add dispatch sign-offs with signature capture
- DispatchSignoff model (DispatchId, SignoffType, Name, Signature base64, SignatureMethod, SignedAt) - AddDispatchSignoff endpoint — one per type per dispatch, validates no duplicate - GetDispatchById includes signoffs in response - Migration for DispatchSignoffs table
This commit is contained in:
parent
c482fa0558
commit
81472bf729
8 changed files with 3001 additions and 0 deletions
|
|
@ -1259,6 +1259,16 @@ namespace Api.SeaHavenIndustries.Controllers
|
|||
ci.SortOrder,
|
||||
ci.WorkOrderId
|
||||
}).ToList(),
|
||||
signoffs = _db.DispatchSignoffs
|
||||
.Where(s => s.DispatchId == x.Id)
|
||||
.Select(s => new {
|
||||
s.Id,
|
||||
s.SignoffType,
|
||||
s.Name,
|
||||
s.Signature,
|
||||
s.SignatureMethod,
|
||||
s.SignedAt
|
||||
}).ToList(),
|
||||
comments = _db.Comments
|
||||
.Where(c => c.DispatchId == x.Id)
|
||||
.OrderBy(c => c.CreatedDate)
|
||||
|
|
@ -1376,6 +1386,40 @@ namespace Api.SeaHavenIndustries.Controllers
|
|||
return match.Success ? match.Groups[1].Value : null;
|
||||
}
|
||||
|
||||
[HttpPost("AddDispatchSignoff")]
|
||||
public async Task<IActionResult> AddDispatchSignoff([FromBody] DispatchSignoff_DTO model)
|
||||
{
|
||||
try
|
||||
{
|
||||
var dispatch = await _db.Dispatches.FindAsync(model.DispatchId);
|
||||
if (dispatch == null)
|
||||
return BadRequest(new Response { Status = "Error", Message = "Dispatch not found" });
|
||||
|
||||
var existing = await _db.DispatchSignoffs
|
||||
.AnyAsync(s => s.DispatchId == model.DispatchId && s.SignoffType == model.SignoffType);
|
||||
if (existing)
|
||||
return BadRequest(new Response { Status = "Error", Message = $"{model.SignoffType} sign-off already exists" });
|
||||
|
||||
var signoff = new DispatchSignoff
|
||||
{
|
||||
DispatchId = model.DispatchId,
|
||||
SignoffType = model.SignoffType,
|
||||
Name = model.Name,
|
||||
Signature = model.Signature,
|
||||
SignatureMethod = model.SignatureMethod,
|
||||
SignedAt = DateTime.UtcNow
|
||||
};
|
||||
_db.DispatchSignoffs.Add(signoff);
|
||||
await _db.SaveChangesAsync();
|
||||
|
||||
return Ok(new { signoff.Id, signoff.SignoffType, signoff.Name, signoff.SignedAt, signoff.SignatureMethod });
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return BadRequest(new Response { Status = "Error", Message = ex.Message });
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPost("UpdateChecklistItem")]
|
||||
public async Task<IActionResult> UpdateChecklistItem([FromBody] ChecklistItemUpdate_DTO model)
|
||||
{
|
||||
|
|
|
|||
11
Api.SeaHavenIndustries/DTOs/DispatchSignoff_DTO.cs
Normal file
11
Api.SeaHavenIndustries/DTOs/DispatchSignoff_DTO.cs
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
namespace Api.SeaHavenIndustries.DTOs
|
||||
{
|
||||
public class DispatchSignoff_DTO
|
||||
{
|
||||
public int DispatchId { get; set; }
|
||||
public string? SignoffType { get; set; }
|
||||
public string? Name { get; set; }
|
||||
public string? Signature { get; set; }
|
||||
public string? SignatureMethod { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -43,6 +43,7 @@ namespace Data.SeaHavenIndustries
|
|||
public DbSet<Dispatch> Dispatches { get; set; }
|
||||
public DbSet<DispatchWorkOrder> DispatchWorkOrders { get; set; }
|
||||
public DbSet<DispatchChecklistItem> DispatchChecklistItems { get; set; }
|
||||
public DbSet<DispatchSignoff> DispatchSignoffs { get; set; }
|
||||
public DbSet<TaskListTemplate> TaskListTemplates { get; set; }
|
||||
public DbSet<TaskListTemplateItem> TaskListTemplateItems { get; set; }
|
||||
|
||||
|
|
|
|||
2803
Data.SeaHavenIndustries/Migrations/20260417194438_AddDispatchSignoffs.Designer.cs
generated
Normal file
2803
Data.SeaHavenIndustries/Migrations/20260417194438_AddDispatchSignoffs.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,58 @@
|
|||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Data.SeaHavenIndustries.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddDispatchSignoffs : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "DispatchSignoffs",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("SqlServer:Identity", "1, 1"),
|
||||
DispatchId = table.Column<int>(type: "int", nullable: false),
|
||||
SignoffType = table.Column<string>(type: "nvarchar(max)", nullable: true),
|
||||
Name = table.Column<string>(type: "nvarchar(max)", nullable: true),
|
||||
Signature = table.Column<string>(type: "nvarchar(max)", nullable: true),
|
||||
SignatureMethod = table.Column<string>(type: "nvarchar(max)", nullable: true),
|
||||
SignedAt = table.Column<DateTime>(type: "datetime2", nullable: true),
|
||||
IsDeleted = table.Column<bool>(type: "bit", nullable: true),
|
||||
createdby = table.Column<string>(type: "nvarchar(max)", nullable: true),
|
||||
DeleterUserId = table.Column<string>(type: "nvarchar(max)", nullable: true),
|
||||
DeletionTime = table.Column<DateTime>(type: "datetime2", nullable: true),
|
||||
CreatedDate = table.Column<DateTime>(type: "datetime2", nullable: true),
|
||||
LastModificationTime = table.Column<DateTime>(type: "datetime2", nullable: true),
|
||||
LastModifierUserId = table.Column<int>(type: "int", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_DispatchSignoffs", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_DispatchSignoffs_Dispatches_DispatchId",
|
||||
column: x => x.DispatchId,
|
||||
principalTable: "Dispatches",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_DispatchSignoffs_DispatchId",
|
||||
table: "DispatchSignoffs",
|
||||
column: "DispatchId");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "DispatchSignoffs");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -771,6 +771,60 @@ namespace Data.SeaHavenIndustries.Migrations
|
|||
b.ToTable("DispatchChecklistItems");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Data.SeaHavenIndustries.DispatchSignoff", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<DateTime?>("CreatedDate")
|
||||
.HasColumnType("datetime2");
|
||||
|
||||
b.Property<string>("DeleterUserId")
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<DateTime?>("DeletionTime")
|
||||
.HasColumnType("datetime2");
|
||||
|
||||
b.Property<int>("DispatchId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<bool?>("IsDeleted")
|
||||
.HasColumnType("bit");
|
||||
|
||||
b.Property<DateTime?>("LastModificationTime")
|
||||
.HasColumnType("datetime2");
|
||||
|
||||
b.Property<int?>("LastModifierUserId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<string>("Signature")
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<string>("SignatureMethod")
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<DateTime?>("SignedAt")
|
||||
.HasColumnType("datetime2");
|
||||
|
||||
b.Property<string>("SignoffType")
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<string>("createdby")
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("DispatchId");
|
||||
|
||||
b.ToTable("DispatchSignoffs");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Data.SeaHavenIndustries.DispatchWorkOrder", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
|
|
@ -2294,6 +2348,17 @@ namespace Data.SeaHavenIndustries.Migrations
|
|||
b.Navigation("WorkOrder");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Data.SeaHavenIndustries.DispatchSignoff", b =>
|
||||
{
|
||||
b.HasOne("Data.SeaHavenIndustries.Dispatch", "Dispatch")
|
||||
.WithMany("Signoffs")
|
||||
.HasForeignKey("DispatchId")
|
||||
.OnDelete(DeleteBehavior.Restrict)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Dispatch");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Data.SeaHavenIndustries.DispatchWorkOrder", b =>
|
||||
{
|
||||
b.HasOne("Data.SeaHavenIndustries.Dispatch", "Dispatch")
|
||||
|
|
@ -2670,6 +2735,8 @@ namespace Data.SeaHavenIndustries.Migrations
|
|||
b.Navigation("Comments");
|
||||
|
||||
b.Navigation("DispatchWorkOrders");
|
||||
|
||||
b.Navigation("Signoffs");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Data.SeaHavenIndustries.Employee", b =>
|
||||
|
|
|
|||
|
|
@ -27,5 +27,6 @@ namespace Data.SeaHavenIndustries
|
|||
public ICollection<Comments>? Comments { get; set; }
|
||||
public ICollection<DispatchWorkOrder>? DispatchWorkOrders { get; set; }
|
||||
public ICollection<DispatchChecklistItem>? ChecklistItems { get; set; }
|
||||
public ICollection<DispatchSignoff>? Signoffs { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
16
Data.SeaHavenIndustries/Models/DispatchSignoff.cs
Normal file
16
Data.SeaHavenIndustries/Models/DispatchSignoff.cs
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace Data.SeaHavenIndustries
|
||||
{
|
||||
public class DispatchSignoff : FullAuditEntity
|
||||
{
|
||||
public int DispatchId { get; set; }
|
||||
[ForeignKey(nameof(DispatchId))]
|
||||
public virtual Dispatch? Dispatch { get; set; }
|
||||
public string? SignoffType { get; set; }
|
||||
public string? Name { get; set; }
|
||||
public string? Signature { get; set; }
|
||||
public string? SignatureMethod { get; set; }
|
||||
public DateTime? SignedAt { get; set; }
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue