mirror of
https://github.com/Sea-Haven-Industries/shoc-backend.git
synced 2026-09-30 07:13:12 +00:00
fix(vendor-portal): vendors revise only uplift requests they raised
A work-order request stores the requested increase, not a total. Letting the vendor revise one after changes were requested rewrote RequestedNTE as a total while it still read as a work-order request, corrupting its amount and the NTE it would be approved to. Revise now answers not-found for any request the vendor did not raise and leaves the row untouched. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
eb2b442775
commit
d33ba34db9
3 changed files with 56 additions and 1 deletions
|
|
@ -419,6 +419,44 @@ public sealed class UpliftWorkflowTests
|
||||||
context.WorkOrderAuditLogs.Should().Contain(a => a.Action == "uplift_revised");
|
context.WorkOrderAuditLogs.Should().Contain(a => a.Action == "uplift_revised");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Revise_WorkOrderRequest_IsRefusedAsNotFound_AndLeavesTheRowUnchanged()
|
||||||
|
{
|
||||||
|
using var context = NewContext();
|
||||||
|
var (vendor, workOrder, dispatch) = await SeedAsync(context, nte: 600m);
|
||||||
|
context.VendorCompletionDocuments.Add(EvidenceDocument(vendor.Id, dispatch.Id, workOrder.Id));
|
||||||
|
// Raised from the work order by an internal user and sent back for changes:
|
||||||
|
// RequestedNTE holds the 90 increase, not a total.
|
||||||
|
var workOrderRequest = new DispatchUpliftRequest
|
||||||
|
{
|
||||||
|
DispatchId = dispatch.Id,
|
||||||
|
CurrentNTE = 600m,
|
||||||
|
RequestedNTE = 90m,
|
||||||
|
Status = UpliftStatus.ChangesRequested,
|
||||||
|
RequiredTier = 1,
|
||||||
|
VendorReason = "Extra parts",
|
||||||
|
RequestedByVendorName = "Alex Dispatcher",
|
||||||
|
NotificationStatus = "Sent",
|
||||||
|
createdby = "dispatcher-1",
|
||||||
|
CreatedDate = new DateTime(2026, 3, 1),
|
||||||
|
};
|
||||||
|
context.DispatchUpliftRequests.Add(workOrderRequest);
|
||||||
|
await context.SaveChangesAsync();
|
||||||
|
var service = NewPortalService(context, new FakeEmailSender(deliver: true));
|
||||||
|
var session = await service.ResolveSessionAsync(Token, CancellationToken.None);
|
||||||
|
|
||||||
|
var act = () => service.ReviseUpliftAsync(session!, dispatch.Id, workOrderRequest.Id, 900m, "vendor total", 1, CancellationToken.None);
|
||||||
|
|
||||||
|
await act.Should().ThrowAsync<KeyNotFoundException>();
|
||||||
|
var after = context.DispatchUpliftRequests.AsNoTracking().Single(u => u.Id == workOrderRequest.Id);
|
||||||
|
after.Status.Should().Be(UpliftStatus.ChangesRequested);
|
||||||
|
after.RequestedNTE.Should().Be(90m);
|
||||||
|
after.CurrentNTE.Should().Be(600m);
|
||||||
|
after.VendorReason.Should().Be("Extra parts");
|
||||||
|
after.createdby.Should().Be("dispatcher-1");
|
||||||
|
context.WorkOrderAuditLogs.Should().NotContain(a => a.Action == "uplift_revised");
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task Withdraw_Pending_TransitionsToWithdrawn_SetsDecidedAt()
|
public async Task Withdraw_Pending_TransitionsToWithdrawn_SetsDecidedAt()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -736,7 +736,9 @@ namespace SeaHaven.Services.Implementation
|
||||||
}
|
}
|
||||||
|
|
||||||
var req = await _upliftData.GetByIdAndDispatchAsync(requestId, id, cancellationToken);
|
var req = await _upliftData.GetByIdAndDispatchAsync(requestId, id, cancellationToken);
|
||||||
if (req == null) throw new KeyNotFoundException("Uplift request not found");
|
// A vendor revises only requests it raised. Work-order requests (createdby set)
|
||||||
|
// store the increase, not a total, so a vendor revise would corrupt their amount.
|
||||||
|
if (req == null || req.createdby != null) throw new KeyNotFoundException("Uplift request not found");
|
||||||
|
|
||||||
if (UpliftStatus.ToCanonical(req.Status) != UpliftStatus.ChangesRequested)
|
if (UpliftStatus.ToCanonical(req.Status) != UpliftStatus.ChangesRequested)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -261,6 +261,21 @@ public sealed class UpliftAmountPerCreationPathTests
|
||||||
.SumAutoApprovedAmountForWorkOrderAsync(WorkOrderId, CancellationToken.None));
|
.SumAutoApprovedAmountForWorkOrderAsync(WorkOrderId, CancellationToken.None));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task WorkOrderUpliftList_ShowsEachRequestsIncrease()
|
||||||
|
{
|
||||||
|
await using var context = CreateContext();
|
||||||
|
await SeedWorkOrderAsync(context);
|
||||||
|
var workOrderRequestId = await CreatePendingWorkOrderRequestAsync(context, 90m);
|
||||||
|
var vendorRequestId = await SeedVendorRequestAsync(context, SecondDispatchId, currentNte: 600m, requestedTotal: 900m);
|
||||||
|
|
||||||
|
var uplifts = await NewWorkOrderUpliftService(context)
|
||||||
|
.ListAsync(WorkOrderId, Admin(), CancellationToken.None);
|
||||||
|
|
||||||
|
Assert.Equal(90m, Assert.Single(uplifts!, u => u.Id == workOrderRequestId).Amount);
|
||||||
|
Assert.Equal(300m, Assert.Single(uplifts!, u => u.Id == vendorRequestId).Amount);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void AmountDefinition_TranslatesToSqlServer_ForRowAndGroupedSums()
|
public void AmountDefinition_TranslatesToSqlServer_ForRowAndGroupedSums()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue