mirror of
https://github.com/Sea-Haven-Industries/shoc-backend.git
synced 2026-10-03 13:53:30 +00:00
fix(completion-templates): let PUT clear workOrderType with an explicit null
UpdateAsync only applied WorkOrderType when it had a value, so once a template was restricted to one work order type no request could make it trade-generic again. The DTO now records whether workOrderType was present in the body: omitting it keeps the stored value, an explicit null clears it, and a concrete value sets it. The templates page echoes the stored legacy fields on PUT, so its behaviour is unchanged.
This commit is contained in:
parent
cd23ad5b68
commit
a224f883bc
3 changed files with 58 additions and 4 deletions
|
|
@ -49,15 +49,33 @@ namespace SeaHaven.Services.DTOs
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create/update body. Legacy fields are optional: on update, null leaves the
|
// Create/update body. Legacy fields are optional: on update, null leaves the
|
||||||
// stored value unchanged, as does a null Procedures list. ExtraSafetyNote is
|
// stored value unchanged, as does a null Procedures list. WorkOrderType is the
|
||||||
// always applied, so null removes the note.
|
// exception: omitting it keeps the stored value, while an explicit
|
||||||
|
// "workOrderType": null clears it so the template applies to every work order
|
||||||
|
// type of its trade. ExtraSafetyNote is always applied, so null removes the note.
|
||||||
public class CompletionDocTemplateCreateDto
|
public class CompletionDocTemplateCreateDto
|
||||||
{
|
{
|
||||||
|
private WorkOrderType? _workOrderType;
|
||||||
|
|
||||||
public string? Name { get; set; }
|
public string? Name { get; set; }
|
||||||
public string? ExtraSafetyNote { get; set; }
|
public string? ExtraSafetyNote { get; set; }
|
||||||
public List<CompletionDocTemplateProcedureInputDto>? Procedures { get; set; }
|
public List<CompletionDocTemplateProcedureInputDto>? Procedures { get; set; }
|
||||||
public string? ServiceKey { get; set; }
|
public string? ServiceKey { get; set; }
|
||||||
public WorkOrderType? WorkOrderType { get; set; }
|
|
||||||
|
public WorkOrderType? WorkOrderType
|
||||||
|
{
|
||||||
|
get => _workOrderType;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_workOrderType = value;
|
||||||
|
WorkOrderTypeSpecified = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// True when the body carried workOrderType at all, including as null.
|
||||||
|
[System.Text.Json.Serialization.JsonIgnore]
|
||||||
|
public bool WorkOrderTypeSpecified { get; private set; }
|
||||||
|
|
||||||
public string? TemplateUrl { get; set; }
|
public string? TemplateUrl { get; set; }
|
||||||
public bool? IsActive { get; set; }
|
public bool? IsActive { get; set; }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -105,7 +105,7 @@ namespace SeaHaven.Services.Implementation
|
||||||
entity.ExtraSafetyNote = input.ExtraSafetyNote;
|
entity.ExtraSafetyNote = input.ExtraSafetyNote;
|
||||||
if (input.ServiceKey != null)
|
if (input.ServiceKey != null)
|
||||||
entity.ServiceKey = input.ServiceKey;
|
entity.ServiceKey = input.ServiceKey;
|
||||||
if (request.WorkOrderType.HasValue)
|
if (request.WorkOrderTypeSpecified)
|
||||||
entity.WorkOrderType = request.WorkOrderType;
|
entity.WorkOrderType = request.WorkOrderType;
|
||||||
if (input.TemplateUrl != null)
|
if (input.TemplateUrl != null)
|
||||||
entity.TemplateUrl = input.TemplateUrl;
|
entity.TemplateUrl = input.TemplateUrl;
|
||||||
|
|
|
||||||
|
|
@ -248,6 +248,42 @@ public class CompletionDocTemplateServiceTests
|
||||||
Assert.Null(updated.CreatedByName);
|
Assert.Null(updated.CreatedByName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Bodies are bound by System.Text.Json with the web defaults, as MVC does.
|
||||||
|
private static CompletionDocTemplateCreateDto JsonBody(string json) =>
|
||||||
|
System.Text.Json.JsonSerializer.Deserialize<CompletionDocTemplateCreateDto>(
|
||||||
|
json, new System.Text.Json.JsonSerializerOptions(System.Text.Json.JsonSerializerDefaults.Web))!;
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Update_WorkOrderTypeExplicitNullClears_OmittedKeeps_ValueSets()
|
||||||
|
{
|
||||||
|
using var context = NewContext();
|
||||||
|
context.CompletionDocTemplates.Add(new CompletionDocTemplate
|
||||||
|
{
|
||||||
|
Id = 8,
|
||||||
|
Name = "HVAC PM Completion",
|
||||||
|
ServiceKey = "HVAC",
|
||||||
|
WorkOrderType = WorkOrderType.PM,
|
||||||
|
TemplateUrl = "",
|
||||||
|
IsActive = true
|
||||||
|
});
|
||||||
|
await context.SaveChangesAsync();
|
||||||
|
var service = NewService(context);
|
||||||
|
|
||||||
|
var omitted = JsonBody("""{"name":"HVAC Completion"}""");
|
||||||
|
Assert.False(omitted.WorkOrderTypeSpecified);
|
||||||
|
var kept = await service.UpdateAsync(Admin(), 8, omitted, CancellationToken.None);
|
||||||
|
Assert.Equal(WorkOrderType.PM, kept.WorkOrderType);
|
||||||
|
|
||||||
|
var cleared = await service.UpdateAsync(
|
||||||
|
Admin(), 8, JsonBody("""{"name":"HVAC Completion","workOrderType":null}"""), CancellationToken.None);
|
||||||
|
Assert.Null(cleared.WorkOrderType);
|
||||||
|
Assert.Null((await context.CompletionDocTemplates.AsNoTracking().SingleAsync(t => t.Id == 8)).WorkOrderType);
|
||||||
|
|
||||||
|
var set = await service.UpdateAsync(
|
||||||
|
Admin(), 8, JsonBody("""{"name":"HVAC Completion","workOrderType":6}"""), CancellationToken.None);
|
||||||
|
Assert.Equal(WorkOrderType.Reactive, set.WorkOrderType);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task Update_MissingOrDeletedTemplate_ThrowsNotFound()
|
public async Task Update_MissingOrDeletedTemplate_ThrowsNotFound()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue