public void Then1(string batchNumber, Table table)
        {
            var task = ValidateCodelineBus.GetSingleResponseAsync(5);
            task.Wait();

            response = task.Result;

            Assert.IsNotNull(response, "No response received");
            Assert.IsFalse(string.IsNullOrEmpty(response.voucherBatch.scannedBatchNumber));
            Assert.AreEqual(batchNumber, response.voucherBatch.scannedBatchNumber);

            table.CompareToSet(response.voucher);
        }
        public override void ExecuteJob()
        {
            using (var dbConnection = new SqlConnection(Configuration.SqlConnectionString))
            {
                using (var dbContext = new DipsDbContext(dbConnection))
                {
                    Log.Information("Scanning database for completed codeline validation batches");
                    //Get all the potential batches that have been completed
                    var completedBatches =
                        dbContext.Queues
                            .Where(q =>
                                !q.ResponseCompleted
                                && q.S_LOCATION == DipsLocationType.CodelineValidationDone.Value
                                && q.S_LOCK.Trim() == "0")
                            .ToList();

                    Serilog.Log.Information("Found {0} completed codeline validation batches", completedBatches.Count());

                    foreach (var completedBatch in completedBatches)
                    {
                        string routingKey;
                        Serilog.Log.Debug("Creating response for batch {@batch}", completedBatch.S_BATCH);

                        //only commit the transaction if
                        // a) we were the first application to mark this batch row as ValidateCodelineCompleted (DipsQueue uses optimistic concurrency) 
                        // b) we were able to place a response message on the bus
                        using (var tx = dbContext.BeginTransaction())
                        {
                            try
                            {
                                //mark the batch as completed so it gets 'locked'
                                completedBatch.ResponseCompleted = true;
                                routingKey = completedBatch.RoutingKey;

                                dbContext.SaveChanges();

                                var batchNumber = completedBatch.S_BATCH;

                                //get the vouchers, generate and send the response
                                var vouchers = dbContext.NabChqPods
                                    .Where(v => v.S_BATCH == batchNumber)
                                    .AsEnumerable()
                                    .Select(v => new
                                    {
                                        S_STATUS1 =
                                            int.Parse(string.IsNullOrWhiteSpace(v.S_STATUS1) ? "0" : v.S_STATUS1),
                                        voucher = v
                                    }).ToList();

                                //use bitmasks to map the values from S_STATUS1 field
                                var batchResponse = new ValidateBatchCodelineResponse
                                {
                                    voucherBatch = new VoucherBatch
                                    {
                                        scannedBatchNumber = completedBatch.S_BATCH,
                                        workType =
                                            ResponseHelper.ParseWorkType(
                                                ResponseHelper.TrimString(completedBatch.S_JOB_ID)),
                                        batchAccountNumber = vouchers.First().voucher.batchAccountNumber,
                                        captureBsb = vouchers.First().voucher.captureBSB,
                                        processingState =
                                            ResponseHelper.ParseState(
                                                ResponseHelper.TrimString(vouchers.First().voucher.processing_state)),
                                        collectingBank = vouchers.First().voucher.collecting_bank,
                                        unitID = vouchers.First().voucher.unit_id,
                                        batchType = ResponseHelper.TrimString(vouchers.First().voucher.batch_type),
                                        subBatchType =
                                            ResponseHelper.TrimString(vouchers.First().voucher.sub_batch_type),
                                    },
                                    voucher = vouchers.Select(v => new ValidateCodelineResponse
                                    {
                                        extraAuxDomStatus = DipsStatus1Bitmask.GetExtraAuxDomStatusMasked(v.S_STATUS1),
                                        auxDomStatus = DipsStatus1Bitmask.GetAuxDomStatusMasked(v.S_STATUS1),
                                        accountNumberStatus =
                                            DipsStatus1Bitmask.GetAccountNumberStatusMasked(v.S_STATUS1),
                                        amountStatus = DipsStatus1Bitmask.GetAmountStatusMasked(v.S_STATUS1),
                                        bsbNumberStatus = DipsStatus1Bitmask.GetBsbNumberStatusMasked(v.S_STATUS1),
                                        transactionCodeStatus =
                                            DipsStatus1Bitmask.GetTransactionCodeStatusMasked(v.S_STATUS1),
                                        documentReferenceNumber =
                                            ResponseHelper.ResolveDocumentReferenceNumber(
                                                ResponseHelper.TrimString(v.voucher.doc_ref_num)),
                                        targetEndPoint = ResponseHelper.TrimString(v.voucher.ie_endPoint),
                                        documentType = ResponseHelper.ParseDocumentType(v.voucher.doc_type),
                                        processingDate =
                                            DateTime.ParseExact(string.Format("{0}", v.voucher.proc_date), "yyyyMMdd",
                                                CultureInfo.InvariantCulture),
                                    }).ToArray()
                                };


                                if (Configuration.DeleteDatabaseRows)
                                {
                                    ResponseHelper.CleanupBatchData(batchNumber, dbContext);
                                }

                                if (string.IsNullOrEmpty(routingKey))
                                {
                                    routingKey = string.Empty;
                                }

                                //Task.WaitAll(responseExchange.PublishAsync(batchResponse, completedBatch.CorrelationId, routingKey.Trim()));

                                tx.Commit();

                                Serilog.Log.Debug(
                                    "Codeline validation batch '{@batch}' has been completed and a response has been placed on the queue",
                                    completedBatch.S_BATCH);
                                Serilog.Log.Information("Batch '{@batch}' response sent: {@response}",
                                    completedBatch.S_BATCH, batchResponse);

                            }
                            catch (OptimisticConcurrencyException)
                            {
                                //this is to handle the race condition where more than instance of this service is running at the same time and tries to update the row.

                                //basically ignore the message by loggin a warning and roll back.
                                //if this row was not included by mistake (e.g. it should be included), it will just come in in the next batch run.
                                Serilog.Log.Warning(
                                    "Could not create a codeline validation response for batch '{@batch}' because the DIPS database row was updated by another connection",
                                    completedBatch.S_BATCH);

                                tx.Rollback();
                            }
                            catch (Exception ex)
                            {
                                Serilog.Log.Error(
                                    ex,
                                    "Could not complete and create a codeline validation response for batch '{@batch}'",
                                    completedBatch.S_BATCH);
                                tx.Rollback();
                            }
                        }
                    }
                }
            }
        }