mirror of
https://github.com/Sea-Haven-Industries/shoc-backend.git
synced 2026-09-30 06:03:12 +00:00
Adds GET /api/notifications, a per-user read model derived from live work-order state: Unassigned (grouped, High), No Vendor and Aveta Missing (per work order, Medium) and Vendor Conflict, account-scoped from claims and ordered by section severity with a fixed reason tie-break.
34 lines
1.6 KiB
C#
34 lines
1.6 KiB
C#
using SeaHaven.DataServices.Models;
|
|
|
|
namespace SeaHaven.Services.Helpers
|
|
{
|
|
public static class VendorConflictPairs
|
|
{
|
|
// Group by vendor so cross-vendor intervals are never compared, then sweep the
|
|
// start-sorted windows within a vendor. Every overlapping pair is still emitted;
|
|
// output is O(n log n + p) where p is the number of emitted pairs, so the worst
|
|
// case stays quadratic only when a single vendor has many mutually-overlapping
|
|
// windows, which is inherent to enumerating all such pairs.
|
|
public static IEnumerable<(ScheduledDispatchReadModel Left, ScheduledDispatchReadModel Right)> Build(
|
|
IReadOnlyList<ScheduledDispatchReadModel> dispatches)
|
|
{
|
|
foreach (var group in dispatches.GroupBy(dispatch => dispatch.VendorId))
|
|
{
|
|
var sorted = group.OrderBy(dispatch => dispatch.Start).ToList();
|
|
for (var leftIndex = 0; leftIndex < sorted.Count; leftIndex++)
|
|
{
|
|
var left = sorted[leftIndex];
|
|
for (var rightIndex = leftIndex + 1; rightIndex < sorted.Count; rightIndex++)
|
|
{
|
|
var right = sorted[rightIndex];
|
|
// Sorted by start: once a window starts at or after left's end, none that follow can overlap it.
|
|
if (right.Start >= left.End)
|
|
break;
|
|
if (left.WorkOrderId != right.WorkOrderId)
|
|
yield return (left, right);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|