@@ -23,7 +23,10 @@ import {
2323 getVariantDetails ,
2424 getVolumeGroupDetails ,
2525} from "../services/supplier-config" ;
26- import { calculateSupplierAllocatedFactor } from "../services/supplier-quotas" ;
26+ import {
27+ calculateSupplierAllocatedFactor ,
28+ updateSupplierAllocation ,
29+ } from "../services/supplier-quotas" ;
2730import { Deps } from "../config/deps" ;
2831
2932type SupplierSpec = {
@@ -32,6 +35,12 @@ type SupplierSpec = {
3235 priority : number ;
3336 billingId : string ;
3437} ;
38+
39+ type SupplierDetails = {
40+ supplierSpec : SupplierSpec ;
41+ volumeGroupId : string ;
42+ } ;
43+
3544type PreparedEvents = LetterRequestPreparedEventV2 | LetterRequestPreparedEvent ;
3645
3746// small envelope that must exist in all inputs
@@ -71,7 +80,10 @@ function validateType(event: unknown) {
7180 }
7281}
7382
74- async function getSupplierFromConfig ( letterEvent : PreparedEvents , deps : Deps ) {
83+ async function getSupplierFromConfig (
84+ letterEvent : PreparedEvents ,
85+ deps : Deps ,
86+ ) : Promise < SupplierDetails | undefined > {
7587 try {
7688 const variantDetails : LetterVariant = await getVariantDetails (
7789 letterEvent . data . letterVariantId ,
@@ -119,7 +131,7 @@ async function getSupplierFromConfig(letterEvent: PreparedEvents, deps: Deps) {
119131
120132 let supplierAllocationsForPack : SupplierAllocation [ ] = [ ] ;
121133 let supplierFactors : { supplierId : string ; factor : number } [ ] = [ ] ;
122-
134+ let selectedSupplierId = "unknown" ; // Default to first supplier if no allocations or factors can be calculated
123135 if ( suppliersForPack && suppliersForPack . length > 0 ) {
124136 supplierAllocationsForPack = supplierAllocations . filter ( ( alloc ) =>
125137 suppliersForPack . some ( ( supplier ) => supplier . id === alloc . supplier ) ,
@@ -137,6 +149,16 @@ async function getSupplierFromConfig(letterEvent: PreparedEvents, deps: Deps) {
137149 console . log ( "Supplier factors calculated for allocation" , {
138150 supplierFactors,
139151 } ) ;
152+
153+ // Get the supplierid with the lowest factor
154+ selectedSupplierId = supplierFactors [ 0 ] . supplierId ;
155+ let lowestFactor = supplierFactors [ 0 ] . factor ;
156+ for ( const supplierFactor of supplierFactors ) {
157+ if ( supplierFactor . factor < lowestFactor ) {
158+ lowestFactor = supplierFactor . factor ;
159+ selectedSupplierId = supplierFactor . supplierId ;
160+ }
161+ }
140162 }
141163
142164 deps . logger . info ( {
@@ -152,16 +174,26 @@ async function getSupplierFromConfig(letterEvent: PreparedEvents, deps: Deps) {
152174 suppliersForPack,
153175 supplierAllocationsForPack,
154176 supplierFactors,
177+ selectedSupplierId,
155178 } ) ;
156179
157- return allocatedSuppliers ;
180+ const supplierDetails : SupplierDetails = {
181+ supplierSpec : {
182+ supplierId : selectedSupplierId ,
183+ specId : preferredPack . id ,
184+ priority : 0 ,
185+ billingId : preferredPack . billingId ,
186+ } ,
187+ volumeGroupId : volumeGroupDetails . id ,
188+ } ;
189+ return supplierDetails ;
158190 } catch ( error ) {
159191 deps . logger . error ( {
160192 description : "Error fetching supplier from config" ,
161193 err : error ,
162194 variantId : letterEvent . data . letterVariantId ,
163195 } ) ;
164- return [ ] ;
196+ return undefined ;
165197 }
166198}
167199
@@ -170,6 +202,7 @@ function getSupplier(letterEvent: PreparedEvents, deps: Deps): SupplierSpec {
170202}
171203
172204type AllocationMetrics = Map < string , Map < string , number > > ;
205+ type VolumeGroupAllocation = Map < string , Record < string , number > > ;
173206
174207function incrementMetric (
175208 map : AllocationMetrics ,
@@ -203,12 +236,40 @@ function emitMetrics(
203236 }
204237}
205238
239+ function incrementAllocation (
240+ map : VolumeGroupAllocation ,
241+ volumeGroupId : string ,
242+ supplierId : string ,
243+ allocation : number ,
244+ ) {
245+ const groupAllocations = map . get ( volumeGroupId ) ?? { } ;
246+ groupAllocations [ supplierId ] =
247+ ( groupAllocations [ supplierId ] ?? 0 ) + allocation ;
248+ map . set ( volumeGroupId , groupAllocations ) ;
249+ }
250+
251+ async function saveAllocations (
252+ deps : Deps ,
253+ volumeGroupAllocations : VolumeGroupAllocation ,
254+ ) {
255+ for ( const [ volumeGroupId , allocations ] of volumeGroupAllocations ) {
256+ for ( const [ supplierId , allocation ] of Object . entries ( allocations ) ) {
257+ await updateSupplierAllocation (
258+ volumeGroupId ,
259+ supplierId ,
260+ allocation ,
261+ deps ,
262+ ) ;
263+ }
264+ }
265+ }
266+
206267export default function createSupplierAllocatorHandler ( deps : Deps ) : SQSHandler {
207268 return async ( event : SQSEvent ) => {
208269 const batchItemFailures : SQSBatchItemFailure [ ] = [ ] ;
209270 const perAllocationSuccess : AllocationMetrics = new Map ( ) ;
210271 const perAllocationFailure : AllocationMetrics = new Map ( ) ;
211-
272+ const volumeGroupAllocations : VolumeGroupAllocation = new Map ( ) ; // Map of volume group id to supplier allocations for that group, used to track the allocations calculated in this batch for emitting metrics and updating the quotas after processing the batch
212273 // Initialise the supplier quotas.
213274
214275 const tasks = event . Records . map ( async ( record ) => {
@@ -225,7 +286,17 @@ export default function createSupplierAllocatorHandler(deps: Deps): SQSHandler {
225286 validateType ( letterEvent ) ;
226287
227288 const supplierSpec = getSupplier ( letterEvent as PreparedEvents , deps ) ;
228- await getSupplierFromConfig ( letterEvent as PreparedEvents , deps ) ;
289+ const supplierDetails = await getSupplierFromConfig (
290+ letterEvent as PreparedEvents ,
291+ deps ,
292+ ) ;
293+
294+ incrementAllocation (
295+ volumeGroupAllocations ,
296+ supplierDetails ?. volumeGroupId ?? "unknown" ,
297+ supplierSpec . supplierId ,
298+ 1 ,
299+ ) ;
229300
230301 supplier = supplierSpec . supplierId ;
231302 priority = String ( supplierSpec . priority ) ;
@@ -276,6 +347,7 @@ export default function createSupplierAllocatorHandler(deps: Deps): SQSHandler {
276347
277348 emitMetrics ( perAllocationSuccess , MetricStatus . Success , deps ) ;
278349 emitMetrics ( perAllocationFailure , MetricStatus . Failure , deps ) ;
350+ await saveAllocations ( deps , volumeGroupAllocations ) ;
279351 return { batchItemFailures } ;
280352 } ;
281353}
0 commit comments