1- using System . Net . Http . Headers ;
2- using System . Text ;
3- using Newtonsoft . Json ;
1+ using Newtonsoft . Json ;
42using Polly ;
53using SecurityService . Client ;
64using SecurityService . DataTransferObjects . Responses ;
75using Shared . Results ;
86using SimpleResults ;
7+ using System ;
8+ using System . Net . Http . Headers ;
9+ using System . Text ;
910using TransactionProcessor . Client ;
1011using TransactionProcessor . DataTransferObjects ;
1112using TransactionProcessor . DataTransferObjects . Requests . Merchant ;
@@ -201,62 +202,55 @@ public async Task<Result> SendSales(DateTime dateTime,
201202 MerchantResponse merchant ,
202203 ContractResponse contract ,
203204 Int32 numberOfSales ,
205+ Int32 timeDelay ,
204206 CancellationToken cancellationToken ) {
205207 List < SaleTransactionRequest > salesToSend = new List < SaleTransactionRequest > ( ) ;
206208 Decimal depositAmount = 0 ;
207209 ( Int32 accountNumber , String accountName , Decimal balance ) billDetails = default ;
208210 ( Int32 meterNumber , String customerName , Decimal amount ) meterDetails = default ;
209211
210- foreach ( ContractProduct contractProduct in contract . Products )
211- {
212- this . WriteTrace ( $ "product [{ contractProduct . DisplayText } ]") ;
213-
214- List < ( SaleTransactionRequest request , Decimal amount ) > saleRequests = null ;
215- // Get a number of sales to be sent
216- if ( numberOfSales == 0 )
217- {
218- numberOfSales = this . r . Next ( 2 , 10 ) ;
219- }
212+ // Step 2: Decide how many total transactions to generate in this run
213+ numberOfSales = this . r . Next ( 1 , 6 ) ; // e.g. 1–5 transactions per run
214+ List < ( SaleTransactionRequest request , Decimal amount ) > saleRequests = null ;
215+ for ( int i = 0 ; i < numberOfSales ; i ++ ) {
216+ ContractProduct ? contractProduct = contract . Products [ this . r . Next ( contract . Products . Count ) ] ;
220217
221- for ( Int32 i = 1 ; i <= numberOfSales ; i ++ )
222- {
223- ProductSubType productSubType = this . GetProductSubType ( contract . OperatorName ) ;
218+ // Spread transactions randomly across 5 minutes
219+ int delayMs = this . r . Next ( 0 , timeDelay * 60 * 1000 ) ;
224220
225- if ( productSubType == ProductSubType . BillPaymentPostPay )
226- {
227- // Create a bill for this sale
228- billDetails = await this . CreateBillPaymentBill ( contract . OperatorName , contractProduct , cancellationToken ) ;
229- }
221+ await Task . Delay ( delayMs ) ;
222+ ProductSubType productSubType = this . GetProductSubType ( contract . OperatorName ) ;
230223
231- if ( productSubType == ProductSubType . BillPaymentPrePay )
232- {
233- // Create a meter
234- meterDetails = await this . CreateBillPaymentMeter ( contract . OperatorName , contractProduct , cancellationToken ) ;
235- }
224+ if ( productSubType == ProductSubType . BillPaymentPostPay ) {
225+ // Create a bill for this sale
226+ billDetails = await this . CreateBillPaymentBill ( contract . OperatorName , contractProduct , cancellationToken ) ;
227+ }
236228
237- saleRequests = productSubType switch
238- {
239- ProductSubType . MobileTopup => this . BuildMobileTopupSaleRequests ( dateTime , merchant , contract , contractProduct ) ,
240- ProductSubType . Voucher => this . BuildVoucherSaleRequests ( dateTime , merchant , contract , contractProduct ) ,
241- ProductSubType . BillPaymentPostPay => this . BuildPataPawaPostPayBillPaymentSaleRequests ( dateTime , merchant , contract , contractProduct , billDetails ) ,
242- ProductSubType . BillPaymentPrePay => this . BuildPataPawaPrePayBillPaymentSaleRequests ( dateTime , merchant , contract , contractProduct , meterDetails ) ,
243- _ => throw new Exception ( $ "Product Sub Type [{ productSubType } ] not yet supported")
244- } ;
229+ if ( productSubType == ProductSubType . BillPaymentPrePay ) {
230+ // Create a meter
231+ meterDetails = await this . CreateBillPaymentMeter ( contract . OperatorName , contractProduct , cancellationToken ) ;
232+ }
245233
246- // Add the value of the sale to the deposit amount
247- Boolean addToDeposit = i switch
248- {
249- _ when i == numberOfSales => false ,
250- _ => true
251- } ;
234+ saleRequests = productSubType switch {
235+ ProductSubType . MobileTopup => this . BuildMobileTopupSaleRequests ( dateTime , merchant , contract , contractProduct ) ,
236+ ProductSubType . Voucher => this . BuildVoucherSaleRequests ( dateTime , merchant , contract , contractProduct ) ,
237+ ProductSubType . BillPaymentPostPay => this . BuildPataPawaPostPayBillPaymentSaleRequests ( dateTime , merchant , contract , contractProduct , billDetails ) ,
238+ ProductSubType . BillPaymentPrePay => this . BuildPataPawaPrePayBillPaymentSaleRequests ( dateTime , merchant , contract , contractProduct , meterDetails ) ,
239+ _ => throw new Exception ( $ "Product Sub Type [{ productSubType } ] not yet supported")
240+ } ;
252241
253- if ( addToDeposit )
254- {
255- depositAmount += saleRequests . Sum ( sr => sr . amount ) ;
256- }
242+ // Add the value of the sale to the deposit amount
243+ Boolean addToDeposit = i switch {
244+ _ when i == numberOfSales => false ,
245+ _ => true
246+ } ;
257247
258- salesToSend . AddRange ( saleRequests . Select ( s => s . request ) ) ;
248+ if ( addToDeposit ) {
249+ depositAmount += saleRequests . Sum ( sr => sr . amount ) ;
259250 }
251+
252+ salesToSend . AddRange ( saleRequests . Select ( s => s . request ) ) ;
253+
260254 }
261255
262256 // Build up a deposit (minus the last sale amount)
@@ -274,24 +268,19 @@ public async Task<Result> SendSales(DateTime dateTime,
274268 Int32 salesSent = 0 ;
275269 IOrderedEnumerable < SaleTransactionRequest > orderedSales = salesToSend . OrderBy ( s => s . TransactionDateTime ) ;
276270 // Send the sales to the host
277- foreach ( SaleTransactionRequest sale in orderedSales )
278- {
271+ foreach ( SaleTransactionRequest sale in orderedSales ) {
279272 sale . TransactionNumber = this . GetTransactionNumber ( ) . ToString ( ) ;
280273 Result < SerialisedMessage > saleResult = await this . SendSaleTransaction ( merchant , sale , cancellationToken ) ;
281- if ( saleResult . IsSuccess )
282- {
274+ if ( saleResult . IsSuccess ) {
283275 salesSent ++ ;
284276 }
285- //var random = new Random();
286- //int delaySeconds = random.Next(5, 10); // 30–60 inclusive
287- //await Task.Delay(TimeSpan.FromSeconds(delaySeconds), cancellationToken);
288277 }
289278
290- if ( salesSent == 0 )
291- {
279+ if ( salesSent == 0 ) {
292280 // All sales failed
293281 return Result . Failure ( "All sales have failed" ) ;
294282 }
283+
295284 this . WriteTraceX ( $ "{ salesSent } sales for merchant { merchant . MerchantName } sent to host { orderedSales . Count ( ) - salesSent } sales failed to send") ;
296285 return Result . Success ( ) ;
297286 }
0 commit comments