示例#1
0
        public void Test_DipsStatus1Bitmasks()
        {
            //const int ExtraAuxDom = 16;
            //const int AuxDom = 32;
            //const int BsbNumber = 64;
            //const int AccountNumber = 128;
            //const int TransactionCode = 256;
            //const int Amount = 512;

            // NOTE: False == Invalid
            Assert.IsFalse(DipsStatus1Bitmask.GetAccountNumberStatusMasked(128));
            Assert.IsFalse(DipsStatus1Bitmask.GetAmountStatusMasked(512));
            Assert.IsFalse(DipsStatus1Bitmask.GetAuxDomStatusMasked(32));
            Assert.IsFalse(DipsStatus1Bitmask.GetBsbNumberStatusMasked(64));
            Assert.IsFalse(DipsStatus1Bitmask.GetExtraAuxDomStatusMasked(16));
            Assert.IsFalse(DipsStatus1Bitmask.GetTransactionCodeStatusMasked(256));

            // NOTE: True == Valid
            Assert.IsTrue(DipsStatus1Bitmask.GetAccountNumberStatusMasked(0));
            Assert.IsTrue(DipsStatus1Bitmask.GetAmountStatusMasked(0));
            Assert.IsTrue(DipsStatus1Bitmask.GetAuxDomStatusMasked(0));
            Assert.IsTrue(DipsStatus1Bitmask.GetBsbNumberStatusMasked(0));
            Assert.IsTrue(DipsStatus1Bitmask.GetExtraAuxDomStatusMasked(0));
            Assert.IsTrue(DipsStatus1Bitmask.GetTransactionCodeStatusMasked(0));

            // NOTE: Redundant tests!
            Assert.IsFalse(DipsStatus1Bitmask.GetAccountNumberStatusMasked(1 << 7));
            Assert.IsFalse(DipsStatus1Bitmask.GetAmountStatusMasked(1 << 9));
            Assert.IsFalse(DipsStatus1Bitmask.GetAuxDomStatusMasked(1 << 5));
            Assert.IsFalse(DipsStatus1Bitmask.GetBsbNumberStatusMasked(1 << 6));
            Assert.IsFalse(DipsStatus1Bitmask.GetExtraAuxDomStatusMasked(1 << 4));
            Assert.IsFalse(DipsStatus1Bitmask.GetTransactionCodeStatusMasked(1 << 8));
        }
示例#2
0
 public void Test_GetStatusMask()
 {
     Assert.AreEqual(0, DipsStatus1Bitmask.GetStatusMask(true, true, true, true, true, true));
     Assert.AreEqual(16, DipsStatus1Bitmask.GetStatusMask(false, true, true, true, true, true));                                  // bad extraauxdom
     Assert.AreEqual(32, DipsStatus1Bitmask.GetStatusMask(true, false, true, true, true, true));                                  // bad auxdom
     Assert.AreEqual(128, DipsStatus1Bitmask.GetStatusMask(true, true, false, true, true, true));                                 // bad account
     Assert.AreEqual(512, DipsStatus1Bitmask.GetStatusMask(true, true, true, false, true, true));                                 // bad amount
     Assert.AreEqual(64, DipsStatus1Bitmask.GetStatusMask(true, true, true, true, false, true));                                  // bad bsb
     Assert.AreEqual(256, DipsStatus1Bitmask.GetStatusMask(true, true, true, true, true, false));                                 // bad tc
     Assert.AreEqual(272, DipsStatus1Bitmask.GetStatusMask(false, true, true, true, true, false));                                // bad ead & tc
     Assert.AreEqual(16 + 32 + 64 + 128 + 256 + 512, DipsStatus1Bitmask.GetStatusMask(false, false, false, false, false, false)); // all bad
 }
        public DipsNabChq CreateNewDipsNabChq(
            string batchNumber,
            string documentReferenceNumber,
            DateTime processingDate,
            string extraAuxDom,
            bool extraAuxDomStatus,
            string auxDom,
            bool auxDomStatus,
            string bsbNumber,
            bool bsbNumberStatus,
            string accountNumber,
            bool accountNumberStatus,
            string transactionCode,
            bool transactionCodeStatus,
            string capturedAmount,
            string amountConfidenceLevel,
            string documentType,
            string jobId,
            int manualRepair,
            string amount,
            bool amountStatus,
            string captureBsb,
            string batchAccountNumber,
            string processingState,
            string collectingBank,
            string unitId,
            bool tpcRequired,
            string preAdjustmentAmount,
            bool adjustedFlag,
            bool thirdPartyCheckFailed,
            bool thirdPartyPoolFlag,
            bool highValueFlag,
            string voucherDelayedIndicator,
            string batchType,
            bool unprocessable,
            bool unencodedEcdReturnFlag,
            string transactionLinkNumber,
            bool thirdPartyMixedDepositReturnFlag,
            bool suspectFraud,
            bool surplusItemFlag,
            string rawMicr,
            string rawOcr,
            string presentationMode,
            bool isGeneratedVoucher,
            string dipsTraceNumber,
            string dipsSequenceNumber,
            bool adjustmentLetterRequired,
            bool postTransmissionQaAmountFlag,
            bool postTransmissionQaCodelineFlag,
            string adjustmentReasonCode,
            string adjustmentDescription,
            string subBatchType,
            string alt_acc_num,
            string alt_bsb_num,
            string alt_ead,
            string alt_ser_num,
            string alt_trancode,
            bool creditNoteFlag,
            string insertedCreditType
            )
        {
            if (string.IsNullOrEmpty(jobId))
            {
                jobId = DipsJobIdType.NabChqPod.Value;
            }

            if (WorkTypeEnum.NABCHQ_POD.ToString().Equals(jobId))
            {
                jobId = DipsJobIdType.NabChqPod.Value;
            }

            // calculate a value for the S_STATUS1 field, which represents a
            // bitmask of invalid fields in Dips
            int statusMask = DipsStatus1Bitmask.GetStatusMask(extraAuxDomStatus, auxDomStatus, accountNumberStatus,
                                                              amountStatus, bsbNumberStatus, transactionCodeStatus);

            var output = new DipsNabChq
            {
                //Dynamic DipsNabChq Values
                S_BATCH               = batchNumber.PadRight(8, '0'),
                S_TRACE               = (!string.IsNullOrEmpty(dipsTraceNumber)) ? dipsTraceNumber : documentReferenceNumber, // preserve dipsTraceNumber
                acc_num               = accountNumber,
                adjustedFlag          = RequestHelper.ConvertBoolToIntString(adjustedFlag),
                amount                = string.IsNullOrEmpty(capturedAmount) ? amount : capturedAmount,
                amountConfidenceLevel = RequestHelper.ResolveAmountConfidenceLevel(amountConfidenceLevel),
                batch = batchNumber.PadRight(8, '0'),
                batchAccountNumber = batchAccountNumber,
                batch_type         = batchType,
                bsb_num            = bsbNumber,
                captureBSB         = captureBsb,
                collecting_bank    = collectingBank,
                doc_ref_num        = documentReferenceNumber,
                doc_type           = documentType,
                ead = RequestHelper.ConvertNullValueToEmptyString(extraAuxDom),
                fxa_tpc_suspense_pool_flag = RequestHelper.ConvertBoolToIntString(thirdPartyPoolFlag),
                fxa_unencoded_ECD_return   = RequestHelper.ConvertBoolToIntString(unencodedEcdReturnFlag),
                highValueFlag           = RequestHelper.ConvertBoolToIntString(highValueFlag),
                isGeneratedVoucher      = RequestHelper.ConvertBoolToIntString(isGeneratedVoucher),
                job_id                  = jobId.PadRight(15, ' '),
                man_rep_ind             = RequestHelper.ConvertintvalueToString(manualRepair),
                micr_suspect_fraud_flag = RequestHelper.ConvertBoolToIntString(suspectFraud),
                orig_amount             = preAdjustmentAmount,
                presentationMode        = presentationMode,
                proc_date               = processingDate.ToString("yyyyMMdd"),
                processing_state        = processingState,
                raw_micr                = rawMicr,
                raw_ocr                 = rawOcr,
                ser_num                 = RequestHelper.ConvertNullValueToEmptyString(auxDom),
                surplusItemFlag         = RequestHelper.ConvertBoolToIntString(surplusItemFlag),
                tpcMixedDepRet          = RequestHelper.ConvertBoolToIntString(thirdPartyMixedDepositReturnFlag),
                tpcRequired             = RequestHelper.ConvertBoolToYNString(tpcRequired),
                trace    = (!string.IsNullOrEmpty(dipsTraceNumber)) ? dipsTraceNumber : documentReferenceNumber, // preserve dipsTraceNumber
                trancode = RequestHelper.ConvertNullValueToEmptyString(transactionCode),
                transactionLinkNumber = transactionLinkNumber,
                unit_id               = unitId,
                unproc_flag           = RequestHelper.ConvertBoolToIntString(unprocessable),
                voucherIndicatorField = voucherDelayedIndicator,

                S_SEQUENCE = (string.IsNullOrEmpty(dipsSequenceNumber)) ? "0000 " : dipsSequenceNumber,

                adjustmentLetterRequired = RequestHelper.ConvertBoolToIntString(adjustmentLetterRequired),

                fxaPtQAAmtFlag      = RequestHelper.ConvertBoolToIntString(postTransmissionQaAmountFlag),
                fxaPtQACodelineFlag = RequestHelper.ConvertBoolToIntString(postTransmissionQaCodelineFlag),
                creditNoteFlag      = RequestHelper.ConvertBoolToIntString(creditNoteFlag),
                insertedCreditType  = RequestHelper.InsertedCreditTypeToDipsConversion(insertedCreditType),

                alt_acc_num  = alt_acc_num,
                alt_bsb_num  = alt_bsb_num,
                alt_ead      = alt_ead,
                alt_ser_num  = alt_ser_num,
                alt_trancode = alt_trancode,

                adjustmentReasonCode  = adjustmentReasonCode,
                adjustmentDescription = adjustmentDescription,
                sub_batch_type        = subBatchType,

                //Default DipsNabChq Values
                //mandatory fields
                S_DEL_IND  = ZeroString(5),
                S_MODIFIED = ZeroString(5),
                S_COMPLETE = ZeroString(5),
                S_TYPE     = ZeroString(5),
                S_STATUS1  = statusMask.ToString().PadLeft(9, ' '),
                S_STATUS2  = ZeroString(9),
                S_STATUS3  = ZeroString(9),
                S_STATUS4  = ZeroString(9),
                S_IMG1_OFF = ZeroString(9),
                S_IMG1_LEN = ZeroString(9),
                S_IMG1_TYP = ZeroString(5),
                S_IMG2_OFF = ZeroString(9),
                S_IMG2_LEN = ZeroString(9),
                S_IMG2_TYP = ZeroString(5),
                S_LENGTH   = SLength,
                //S_SEQUENCE = "0000 ",
                S_BALANCE   = ZeroString(6),
                S_REPROCESS = ZeroString(5),
                S_REPORTED  = ZeroString(5),
                S_COMMITTED = ZeroString(5),
                //custom fields
                sys_date = dateTimeProvider.CurrentTimeInAustralianEasternTimeZone().ToString("yyyyMMdd"),
                //ignored fields
                pocket            = ZeroString(2),
                payee_name        = IgnoreString(240),
                manual_repair     = IgnoreString(5),
                rec_type_id       = IgnoreString(4),
                proof_seq         = IgnoreString(12),
                trans_seq         = IgnoreString(5),
                delay_ind         = IgnoreString(1),
                fv_exchange       = IgnoreString(1),
                adj_code          = IgnoreString(2),
                adj_desc          = IgnoreString(30),
                op_id             = IgnoreString(15),
                proc_time         = IgnoreString(4),
                @override         = IgnoreString(5),
                fv_ind            = IgnoreString(1),
                host_trans_no     = IgnoreString(3),
                volume            = IgnoreString(8),
                img_location      = IgnoreString(80),
                img_front         = IgnoreString(8),
                img_rear          = IgnoreString(8),
                held_ind          = IgnoreString(1),
                receiving_bank    = IgnoreString(3),
                ie_transaction_id = IgnoreString(12),
                micr_flag         = IgnoreString(1),
                micr_unproc_flag  = IgnoreString(1),
                adjustedBy        = IgnoreString(15),
                //adjustedFlag = IgnoreString(1),
                adjustmentType = IgnoreString(9)
            };

            return(output);
        }
        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();
                            }
                        }
                    }
                }
            }
        }
        public DipsNabChq CreateNewDipsNabChqForValidateTransactionRequest(
            string batchNumber,
            string traceId,
            DateTime processingDate,
            string reasonCode,
            string transactionLinkNumber,
            bool unprocessable,
            string extraAuxDom,
            bool extraAuxDomStatus,
            string auxDom,
            bool auxDomStatus,
            string bsbNumber,
            bool bsbNumberStatus,
            string accountNumber,
            bool accountNumberStatus,
            string transactionCode,
            bool transactionCodeStatus,
            string capturedAmount,
            bool amountStatus,
            string documentType,
            string jobId,
            string rawMicr,
            string rawOcr,
            string captureBsb,
            string batchAccountNumber,
            string processingState,
            string collectingBank,
            string unitId,
            string forValueIndicator,
            string dipsOverride,
            string batchType,
            bool postTransmissionQaAmountFlag,
            bool postTransmissionQaCodelineFlag,
            string subBatchType)
        {
            // calculate a value for the S_STATUS1 field, which represents a
            // bitmask of invalid fields in Dips
            int statusMask = DipsStatus1Bitmask.GetStatusMask(extraAuxDomStatus, auxDomStatus, accountNumberStatus,
                                                              amountStatus, bsbNumberStatus, transactionCodeStatus);

            if (string.IsNullOrEmpty(jobId))
            {
                jobId = DipsJobIdType.NabChqPod.Value;
            }

            if (WorkTypeEnum.NABCHQ_POD.ToString().Equals(jobId))
            {
                jobId = DipsJobIdType.NabChqPod.Value;
            }
            else if (WorkTypeEnum.NABCHQ_LBOX.ToString().Equals(jobId))
            {
                jobId = DipsJobIdType.NabChqLBox.Value;
            }

            var output = new DipsNabChq
            {
                //Dynamic DipsNabChq Values
                @override          = dipsOverride,
                S_BATCH            = batchNumber.PadRight(8, '0'),
                S_TRACE            = traceId.PadLeft(9, '0'),
                acc_num            = accountNumber,
                amount             = capturedAmount ?? string.Empty,
                balanceReason      = reasonCode,
                batch              = batchNumber.PadRight(8, '0'),
                batchAccountNumber = batchAccountNumber,
                batch_type         = batchType,
                bsb_num            = bsbNumber,
                captureBSB         = captureBsb,
                collecting_bank    = collectingBank,
                doc_type           = documentType,
                ead                   = RequestHelper.ConvertNullValueToEmptyString(extraAuxDom),
                fv_ind                = RequestHelper.ConvertNullValueToEmptyString(forValueIndicator),
                fxaPtQAAmtFlag        = RequestHelper.ConvertBoolToIntString(postTransmissionQaAmountFlag),
                fxaPtQACodelineFlag   = RequestHelper.ConvertBoolToIntString(postTransmissionQaCodelineFlag),
                job_id                = jobId.PadRight(15, ' '),
                micr_unproc_flag      = Convert.ToInt32(unprocessable).ToString(CultureInfo.InvariantCulture),
                proc_date             = processingDate.ToString("yyyyMMdd"),
                processing_state      = processingState,
                raw_micr              = rawMicr,
                raw_ocr               = rawOcr,
                ser_num               = RequestHelper.ConvertNullValueToEmptyString(auxDom),
                trace                 = traceId.PadLeft(9, '0'),
                trancode              = RequestHelper.ConvertNullValueToEmptyString(transactionCode),
                transactionLinkNumber = transactionLinkNumber,
                unit_id               = unitId,
                unproc_flag           = Convert.ToInt32(unprocessable).ToString(CultureInfo.InvariantCulture),
                sub_batch_type        = subBatchType,

                //Default DipsNabChq Values
                //mandatory fields
                S_DEL_IND   = ZeroString(5),
                S_MODIFIED  = ZeroString(5),
                S_COMPLETE  = ZeroString(5),
                S_TYPE      = ZeroString(5),
                S_STATUS1   = statusMask.ToString().PadLeft(9, ' '),
                S_STATUS2   = ZeroString(9),
                S_STATUS3   = ZeroString(9),
                S_STATUS4   = ZeroString(9),
                S_IMG1_OFF  = ZeroString(9),
                S_IMG1_LEN  = ZeroString(9),
                S_IMG1_TYP  = ZeroString(5),
                S_IMG2_OFF  = ZeroString(9),
                S_IMG2_LEN  = ZeroString(9),
                S_IMG2_TYP  = ZeroString(5),
                S_LENGTH    = SLength,
                S_SEQUENCE  = "0000 ",
                S_BALANCE   = ZeroString(6),
                S_REPROCESS = ZeroString(5),
                S_REPORTED  = ZeroString(5),
                S_COMMITTED = ZeroString(5),
                //custom fields
                sys_date = dateTimeProvider.CurrentTimeInAustralianEasternTimeZone().ToString("yyyyMMdd"),
                //ignored fields
                pocket                   = ZeroString(2),
                man_rep_ind              = "0",
                payee_name               = IgnoreString(240),
                manual_repair            = IgnoreString(5),
                rec_type_id              = IgnoreString(4),
                proof_seq                = IgnoreString(12),
                trans_seq                = IgnoreString(5),
                delay_ind                = IgnoreString(1),
                fv_exchange              = IgnoreString(1),
                adj_code                 = IgnoreString(2),
                adj_desc                 = IgnoreString(30),
                op_id                    = IgnoreString(15),
                proc_time                = IgnoreString(4),
                host_trans_no            = IgnoreString(3),
                volume                   = IgnoreString(8),
                img_location             = IgnoreString(80),
                img_front                = IgnoreString(8),
                img_rear                 = IgnoreString(8),
                held_ind                 = IgnoreString(1),
                receiving_bank           = IgnoreString(3),
                ie_transaction_id        = IgnoreString(12),
                doc_ref_num              = IgnoreString(9),
                micr_flag                = IgnoreString(1),
                micr_suspect_fraud_flag  = IgnoreString(1),
                presentationMode         = IgnoreString(1),
                adjustmentReasonCode     = IgnoreString(2),
                adjustmentDescription    = IgnoreString(60),
                adjustedBy               = IgnoreString(15),
                adjustedFlag             = IgnoreString(1),
                adjustmentLetterRequired = IgnoreString(1),
                adjustmentType           = IgnoreString(9)
            };

            return(output);
        }
        public override void ExecuteJob()
        {
            Log.Information("Scanning database for completed transaction validation batches");

            using (var dbConnection = new SqlConnection(Configuration.SqlConnectionString))
            {
                using (var dbContext = new DipsDbContext(dbConnection))
                {
                    //Get all the potential batches that have been completed
                    var completedBatches =
                        dbContext.Queues
                        .Where(q =>
                               !q.ResponseCompleted &&
                               q.S_LOCATION == DipsLocationType.TransactionValidationDone.Value &&
                               q.S_LOCK.Trim() == "0")
                        .ToList();

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

                    foreach (var completedBatch in completedBatches)
                    {
                        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 ValidateTransactionCompleted (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;
                                var 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 && v.S_DEL_IND != "  255")
                                               .ToList()
                                               .Select(v => new
                                {
                                    S_STATUS1 = int.Parse(string.IsNullOrWhiteSpace(v.S_STATUS1) ? "0" : v.S_STATUS1),
                                    voucher   = v
                                }).ToList();

                                if (vouchers.Count > 0)
                                {
                                    var firstVoucher = vouchers.First(v => v.voucher.isGeneratedVoucher != "1");

                                    //use bitmasks to map the values from S_STATUS1 field
                                    var batchResponse = new ValidateBatchTransactionResponse
                                    {
                                        voucherBatch = new VoucherBatch
                                        {
                                            scannedBatchNumber = completedBatch.S_BATCH,
                                            workType           = ResponseHelper.ParseWorkType(ResponseHelper.TrimString(completedBatch.S_JOB_ID)),
                                            batchAccountNumber = firstVoucher.voucher.batchAccountNumber,
                                            captureBsb         = firstVoucher.voucher.captureBSB,
                                            processingState    = ResponseHelper.ParseState(ResponseHelper.TrimString(firstVoucher.voucher.processing_state)),
                                            collectingBank     = firstVoucher.voucher.collecting_bank,
                                            unitID             = firstVoucher.voucher.unit_id,
                                            batchType          = ResponseHelper.TrimString(firstVoucher.voucher.batch_type),
                                            subBatchType       = ResponseHelper.TrimString(firstVoucher.voucher.sub_batch_type),
                                        },
                                        voucher = vouchers.Select(v => new ValidateTransactionResponse
                                        {
                                            documentReferenceNumber = v.voucher.S_TRACE,
                                            surplusItemFlag         = ResponseHelper.ParseStringAsBool(v.voucher.surplusItemFlag),
                                            suspectFraudFlag        = ResponseHelper.ParseStringAsBool(v.voucher.micr_suspect_fraud_flag),
                                            isGeneratedVoucher      = ResponseHelper.ParseStringAsBool(v.voucher.isGeneratedVoucher),
                                            codelineFieldsStatus    = new CodelineStatus
                                            {
                                                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),
                                            },
                                            reasonCode                       = ResponseHelper.GetExpertBalanceReason(v.voucher.balanceReason),
                                            transactionLinkNumber            = ResponseHelper.TrimString(v.voucher.transactionLinkNumber),
                                            unprocessable                    = ResponseHelper.ParseStringAsBool(v.voucher.unproc_flag),
                                            forValueIndicator                = ResponseHelper.TrimString(v.voucher.fv_ind),
                                            dips_override                    = ResponseHelper.TrimString(v.voucher.@override),
                                            thirdPartyCheckRequired          = ResponseHelper.ParseYNStringAsBool(v.voucher.tpcRequired),
                                            unencodedECDReturnFlag           = ResponseHelper.ParseStringAsBool(v.voucher.fxa_unencoded_ECD_return),
                                            thirdPartyMixedDepositReturnFlag = ResponseHelper.ParseStringAsBool(v.voucher.tpcMixedDepRet),
                                            postTransmissionQaAmountFlag     = ResponseHelper.ParseStringAsBool(v.voucher.fxaPtQAAmtFlag),
                                            postTransmissionQaCodelineFlag   = ResponseHelper.ParseStringAsBool(v.voucher.fxaPtQACodelineFlag),
                                            voucher = new Voucher
                                            {
                                                accountNumber = ResponseHelper.TrimString(v.voucher.acc_num),
                                                amount        = ResponseHelper.ParseAmountField(v.voucher.amount),
                                                auxDom        = ResponseHelper.TrimString(v.voucher.ser_num),
                                                bsbNumber     = v.voucher.bsb_num,
                                                //DIPS overwrites doc_ref_num with empty values during auto balancing ..
                                                //documentReferenceNumber = ResponseHelper.ResolveDocumentReferenceNumber(ResponseHelper.TrimString(v.voucher.doc_ref_num)),
                                                documentReferenceNumber = ResponseHelper.ResolveDocumentReferenceNumber(v.voucher.S_TRACE.Trim()),
                                                extraAuxDom             = ResponseHelper.TrimString(v.voucher.ead),
                                                transactionCode         = ResponseHelper.TrimString(v.voucher.trancode),
                                                documentType            = ResponseHelper.ParseDocumentType(v.voucher.doc_type),
                                                processingDate          = DateTime.ParseExact(string.Format("{0}{1}", completedBatch.S_SDATE, completedBatch.S_STIME), "dd/MM/yyHH:mm:ss", CultureInfo.InvariantCulture),
                                            }
                                        }).ToArray()
                                    };

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

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

                                    Exchange.SendMessage(CustomJsonSerializer.MessageToBytes(batchResponse), routingKey.Trim(), completedBatch.CorrelationId);
                                    //Task.WaitAll(responseExchange.PublishAsync(batchResponse, completedBatch.CorrelationId, routingKey.Trim()));

                                    tx.Commit();

                                    Log.Debug("Transaction validation batch '{@batch}' has been completed and a response has been placed on the queue", completedBatch.S_BATCH);
                                    Log.Information("Batch '{@batch}' response sent: {@response}", completedBatch.S_BATCH, batchResponse);
                                }
                                else
                                {
                                    Log.Error(
                                        "Could not create a transaction validation response for batch '{@batch}' because the vouchers cannot be queried",
                                        completedBatch.S_BATCH);
                                }
                            }
                            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.
                                Log.Warning(
                                    "Could not create a transaction validation response for batch '{@batch}' because the DIPS database row was updated by another connection",
                                    completedBatch.S_BATCH);

                                tx.Rollback();
                            }
                            catch (Exception ex)
                            {
                                Log.Error(
                                    ex,
                                    "Could not complete and create an transaction validation response for batch '{@batch}'",
                                    completedBatch.S_BATCH);
                                tx.Rollback();
                            }
                        }
                    }
                }
            }
            Log.Information("Finished processing completed transaction validation batches");
        }
示例#7
0
        public DipsNabChq CreateNewDipsNabChq(
            string batchNumber,
            string documentReferenceNumber,
            DateTime processingDate,
            string extraAuxDom,
            bool extraAuxDomStatus,
            string auxDom,
            bool auxDomStatus,
            string bsbNumber,
            bool bsbNumberStatus,
            string accountNumber,
            bool accountNumberStatus,
            string transactionCode,
            bool transactionCodeStatus,
            string capturedAmount,
            string amountConfidenceLevel,
            string documentType,
            string jobId,
            string manualRepair,
            string amount,
            bool amountStatus,
            string captureBsb,
            string batchAccountNumber,
            string processingState,
            string collectingBank,
            string unitId,
            string batchType,
            string repostFromDRN,
            DateTime repostFromProcessingDate,
            string batchCollectingBank,
            string subBatchType)
        {
            if (string.IsNullOrEmpty(batchNumber))
            {
                batchNumber = randomBatchNumber.ToString();
            }

            if (string.IsNullOrEmpty(jobId))
            {
                jobId = DipsJobIdType.NabChqPod.Value;
            }

            if (WorkTypeEnum.NABCHQ_POD.ToString().Equals(jobId))
            {
                jobId = DipsJobIdType.NabChqPod.Value;
            }

            string originalDocumentReferenceNumber = documentReferenceNumber.Substring(documentReferenceNumber.Length - 9);

            documentReferenceNumber = RequestHelper.ResolveDocumentReferenceNumber(documentReferenceNumber);

            // calculate a value for the S_STATUS1 field, which represents a
            // bitmask of invalid fields in Dips
            int statusMask = DipsStatus1Bitmask.GetStatusMask(extraAuxDomStatus, auxDomStatus, accountNumberStatus,
                                                              amountStatus, bsbNumberStatus, transactionCodeStatus);

            var output = new DipsNabChq
            {
                //Dynamic DipsNabChq Values
                S_BATCH = batchNumber.PadRight(8, '0'),
                S_TRACE = documentReferenceNumber.PadLeft(9, '0'),
                acc_num = accountNumber,
                amount  = string.IsNullOrEmpty(capturedAmount) ? amount : capturedAmount,
                amountConfidenceLevel = amountConfidenceLevel,
                batch = batchNumber.PadRight(8, '0'),
                batchAccountNumber = batchAccountNumber,
                batch_type         = batchType,
                bsb_num            = bsbNumber,
                captureBSB         = captureBsb,
                //collecting_bank = collectingBank,
                collecting_bank = RequestHelper.ResolveCollectingBank(collectingBank, batchCollectingBank),

                doc_ref_num      = originalDocumentReferenceNumber,
                doc_type         = documentType,
                ead              = RequestHelper.ConvertNullValueToEmptyString(extraAuxDom),
                job_id           = jobId.PadRight(15, ' '),
                man_rep_ind      = manualRepair,
                proc_date        = processingDate.ToString("yyyyMMdd"),
                processing_state = processingState,
                ser_num          = RequestHelper.ConvertNullValueToEmptyString(auxDom),
                trace            = documentReferenceNumber.PadLeft(9, '0'),
                trancode         = RequestHelper.ConvertNullValueToEmptyString(transactionCode),
                unit_id          = unitId,

                repostFromDRN            = repostFromDRN,
                repostFromProcessingDate = repostFromProcessingDate.ToString("yyyyMMdd"),
                sub_batch_type           = subBatchType,

                //Default DipsNabChq Values
                //mandatory fields
                S_DEL_IND   = ZeroString(5),
                S_MODIFIED  = ZeroString(5),
                S_COMPLETE  = ZeroString(5),
                S_TYPE      = ZeroString(5),
                S_STATUS1   = statusMask.ToString().PadLeft(9, ' '),
                S_STATUS2   = ZeroString(9),
                S_STATUS3   = ZeroString(9),
                S_STATUS4   = ZeroString(9),
                S_IMG1_OFF  = ZeroString(9),
                S_IMG1_LEN  = ZeroString(9),
                S_IMG1_TYP  = ZeroString(5),
                S_IMG2_OFF  = ZeroString(9),
                S_IMG2_LEN  = ZeroString(9),
                S_IMG2_TYP  = ZeroString(5),
                S_LENGTH    = SLength,
                S_SEQUENCE  = "0000 ",
                S_BALANCE   = ZeroString(6),
                S_REPROCESS = ZeroString(5),
                S_REPORTED  = ZeroString(5),
                S_COMMITTED = ZeroString(5),
                //custom fields
                sys_date = dateTimeProvider.CurrentTimeInAustralianEasternTimeZone().ToString("yyyyMMdd"),
                //ignored fields
                pocket                   = ZeroString(2),
                payee_name               = IgnoreString(240),
                manual_repair            = IgnoreString(5),
                rec_type_id              = IgnoreString(4),
                proof_seq                = IgnoreString(12),
                trans_seq                = IgnoreString(5),
                delay_ind                = IgnoreString(1),
                fv_exchange              = IgnoreString(1),
                adj_code                 = IgnoreString(2),
                adj_desc                 = IgnoreString(30),
                op_id                    = IgnoreString(15),
                proc_time                = IgnoreString(4),
                @override                = IgnoreString(5),
                fv_ind                   = IgnoreString(1),
                host_trans_no            = IgnoreString(3),
                volume                   = IgnoreString(8),
                img_location             = IgnoreString(80),
                img_front                = IgnoreString(8),
                img_rear                 = IgnoreString(8),
                held_ind                 = IgnoreString(1),
                receiving_bank           = IgnoreString(3),
                ie_transaction_id        = IgnoreString(12),
                raw_micr                 = IgnoreString(64),
                raw_ocr                  = IgnoreString(64),
                micr_flag                = IgnoreString(1),
                micr_unproc_flag         = IgnoreString(1),
                micr_suspect_fraud_flag  = IgnoreString(1),
                presentationMode         = IgnoreString(1),
                adjustmentReasonCode     = IgnoreString(2),
                adjustmentDescription    = IgnoreString(60),
                adjustedBy               = IgnoreString(15),
                adjustedFlag             = IgnoreString(1),
                adjustmentLetterRequired = IgnoreString(1),
                adjustmentType           = IgnoreString(9)
            };

            return(output);
        }