public static void AuthorizeCCPayment <TNode>(TNode doc, PXSelectBase <CCProcTran> ccProcTran, UpdateDocStateDelegate aDocStateUpdater)
            where TNode : class, IBqlTable, ICCPayment, new()
        {
            if (doc != null && doc.PMInstanceID != null && doc.CuryDocBal != null)
            {
                if (CCPaymentEntry.HasOpenCCTran(ccProcTran))
                {
                    throw new PXException(Messages.ERR_CCTransactionCurrentlyInProgress);
                }

                CCPaymentState paymentState = CCPaymentEntry.ResolveCCPaymentState(ccProcTran.Select());
                if ((paymentState & (CCPaymentState.Captured | CCPaymentState.PreAuthorized)) > 0)
                {
                    throw new PXException(Messages.ERR_CCPaymentAlreadyAuthorized);
                }

                ccProcTran.View.Graph.Actions.PressSave();

                TNode toProc = PXCache <TNode> .CreateCopy(doc);

                PXLongOperation.StartOperation(ccProcTran.View.Graph, delegate() {
                    try
                    {
                        CCPaymentEntry.ProcessCCTransaction(toProc, null, CCTranType.AuthorizeOnly);
                    }
                    finally
                    {
                        if (aDocStateUpdater != null)
                        {
                            aDocStateUpdater(doc, CCTranType.AuthorizeOnly);
                        }
                    }
                });
            }
        }
        public static void RecordCCPayment <TNode>(TNode doc, string aExtPCTranNbr, string aPCAuthNbr, PXSelectBase <CCProcTran> ccProcTran, CCPaymentEntry.ReleaseDelegate aReleaseDelegate, UpdateDocStateDelegate aDocStateUpdater)
            where TNode : class, IBqlTable, ICCPayment, new()
        {
            if (doc != null && doc.PMInstanceID != null && doc.CuryDocBal != null)
            {
                if (CCPaymentEntry.HasOpenCCTran(ccProcTran))
                {
                    throw new PXException(Messages.ERR_CCTransactionCurrentlyInProgress);
                }

                if (string.IsNullOrEmpty(aExtPCTranNbr))
                {
                    throw new PXException(Messages.ERR_PCTransactionNumberOfTheOriginalPaymentIsRequired);
                }


                CCPaymentState paymentState = CCPaymentEntry.ResolveCCPaymentState(ccProcTran.Select());
                if ((paymentState & (CCPaymentState.Captured)) > 0)
                {
                    throw new PXException(Messages.ERR_CCAuthorizedPaymentAlreadyCaptured);
                }


                ccProcTran.View.Graph.Actions.PressSave();
                TNode toProc = PXCache <TNode> .CreateCopy(doc);

                CCProcTran authTran  = CCPaymentEntry.findCCPreAthorizing(ccProcTran.Select());
                CCTranType operation = CCTranType.AuthorizeAndCapture;
                PXLongOperation.StartOperation(ccProcTran.View.Graph, delegate()
                {
                    try
                    {
                        CCPaymentProcessing ccProcGraph = PXGraph.CreateInstance <CCPaymentProcessing>();
                        int?tranID       = 0;
                        string extTranID = aExtPCTranNbr;
                        if (ccProcGraph.RecordCapture(doc, extTranID, aPCAuthNbr, null, ref tranID))
                        {
                        }
                    }
                    finally
                    {
                        //Update doc state in any case
                        if (aDocStateUpdater != null)
                        {
                            aDocStateUpdater(doc, operation);
                        }
                    }
                    if (aReleaseDelegate != null)
                    {
                        aReleaseDelegate(toProc);                               //On Success Only
                    }
                });
            }
        }
        public static void CaptureCCPayment <TNode>(TNode doc, PXSelectBase <CCProcTran> ccProcTran, CCPaymentEntry.ReleaseDelegate aReleaseDelegate, UpdateDocStateDelegate aDocStateUpdater)
            where TNode : class, IBqlTable, ICCPayment, new()
        {
            if (doc != null && doc.PMInstanceID != null && doc.CuryDocBal != null)
            {
                if (CCPaymentEntry.HasOpenCCTran(ccProcTran))
                {
                    throw new PXException(Messages.ERR_CCTransactionCurrentlyInProgress);
                }

                CCPaymentState paymentState = CCPaymentEntry.ResolveCCPaymentState(ccProcTran.Select());
                if ((paymentState & (CCPaymentState.Captured)) > 0)
                {
                    throw new PXException(Messages.ERR_CCAuthorizedPaymentAlreadyCaptured);
                }

                ccProcTran.View.Graph.Actions.PressSave();
                CCProcTran authTran = CCPaymentEntry.findCCPreAthorizing(ccProcTran.Select());
                TNode      toProc   = PXCache <TNode> .CreateCopy(doc);

                CCProcTran authTranCopy = null;
                if (authTran != null && !CCPaymentEntry.IsExpired(authTran))
                {
                    authTranCopy = PXCache <CCProcTran> .CreateCopy(authTran);
                }
                CCTranType operation = (authTranCopy) != null ? CCTranType.PriorAuthorizedCapture : CCTranType.AuthorizeAndCapture;
                PXLongOperation.StartOperation(ccProcTran.View.Graph, delegate()
                {
                    try
                    {
                        CCPaymentEntry.ProcessCCTransaction(toProc, authTranCopy, operation);
                    }
                    finally
                    {
                        //Update doc state in any case
                        if (aDocStateUpdater != null)
                        {
                            aDocStateUpdater(doc, operation);
                        }
                    }
                    if (aReleaseDelegate != null)
                    {
                        aReleaseDelegate(toProc);                               //On Success Only
                    }
                });
            }
        }
        public static void VoidCCPayment <TNode>(TNode doc, PXSelectBase <CCProcTran> ccProcTran, CCPaymentEntry.ReleaseDelegate aReleaseDelegate, UpdateDocStateDelegate aDocStateUpdater)
            where TNode : class, IBqlTable, ICCPayment, new()
        {
            if (doc != null && doc.PMInstanceID != null && doc.CuryDocBal != null)
            {
                if (CCPaymentEntry.HasOpenCCTran(ccProcTran))
                {
                    throw new PXException(Messages.ERR_CCTransactionCurrentlyInProgress);
                }

                CCProcTran toVoid = CCPaymentEntry.findCCLastSuccessfulTran(ccProcTran);
                if (toVoid == null)
                {
                    throw new PXException(Messages.ERR_CCNoTransactionToVoid);
                }
                else if (toVoid.TranType == CCTranTypeCode.VoidTran || toVoid.TranType == CCTranTypeCode.Credit)
                {
                    throw new PXException(Messages.ERR_CCTransactionOfThisTypeInvalidToVoid);
                }

                if (CCPaymentEntry.IsExpired(toVoid))
                {
                    throw new PXException(Messages.TransactionHasExpired);
                }

                ccProcTran.View.Graph.Actions.PressSave();
                TNode toProc = PXCache <TNode> .CreateCopy(doc);

                PXLongOperation.StartOperation(ccProcTran.View.Graph, delegate() {
                    try
                    {
                        CCPaymentEntry.ProcessCCTransaction(toProc, toVoid, CCTranType.VoidOrCredit);
                    }
                    finally
                    {
                        if (aDocStateUpdater != null)
                        {
                            aDocStateUpdater(doc, CCTranType.VoidOrCredit);
                        }
                    }
                    if (aReleaseDelegate != null)
                    {
                        aReleaseDelegate(toProc);
                    }
                });
            }
        }
        public static bool UpdateCapturedState <T>(T doc, IEnumerable <PXResult <CCProcTran> > ccProcTrans)
            where T : class, IBqlTable, ICCCapturePayment
        {
            CCProcTran     lastTran;
            CCPaymentState ccPaymentState       = CCPaymentEntry.ResolveCCPaymentState(ccProcTrans, out lastTran);
            bool           isCCVoided           = (ccPaymentState & CCPaymentState.Voided) != 0;
            bool           isCCCaptured         = (ccPaymentState & CCPaymentState.Captured) != 0;
            bool           isCCPreAuthorized    = (ccPaymentState & CCPaymentState.PreAuthorized) != 0;
            bool           isCCRefunded         = (ccPaymentState & CCPaymentState.Refunded) != 0;
            bool           isCCVoidingAttempted = (ccPaymentState & CCPaymentState.VoidFailed) != 0;
            bool           needUpdate           = false;

            if (doc.IsCCCaptured != isCCCaptured)
            {
                doc.IsCCCaptured = isCCCaptured;
                needUpdate       = true;
            }

            if (lastTran != null &&
                (lastTran.TranType == CCTranTypeCode.PriorAuthorizedCapture ||
                 lastTran.TranType == CCTranTypeCode.AuthorizeAndCapture ||
                 lastTran.TranType == CCTranTypeCode.CaptureOnly))
            {
                if (isCCCaptured)
                {
                    doc.CuryCCCapturedAmt = lastTran.Amount;
                    doc.IsCCCaptureFailed = false;
                    needUpdate            = true;
                }
                else
                {
                    doc.IsCCCaptureFailed = true;
                    needUpdate            = true;
                }
            }

            if (doc.IsCCCaptured == false && (doc.CuryCCCapturedAmt != Decimal.Zero))
            {
                doc.CuryCCCapturedAmt = Decimal.Zero;
                needUpdate            = true;
            }

            return(needUpdate);
        }
        public static void CaptureOnlyCCPayment <TNode>(TNode doc, string aAuthorizationNbr, PXSelectBase <CCProcTran> ccProcTran, CCPaymentEntry.ReleaseDelegate aReleaseDelegate, UpdateDocStateDelegate aDocStateUpdater)
            where TNode : class, IBqlTable, ICCPayment, new()
        {
            if (doc != null && doc.PMInstanceID != null && doc.CuryDocBal != null)
            {
                if (CCPaymentEntry.HasOpenCCTran(ccProcTran))
                {
                    throw new PXException(Messages.ERR_CCTransactionCurrentlyInProgress);
                }

                if (string.IsNullOrEmpty(aAuthorizationNbr))
                {
                    throw new PXException(Messages.ERR_CCExternalAuthorizationNumberIsRequiredForCaptureOnlyTrans);
                }

                ccProcTran.View.Graph.Actions.PressSave();
                TNode toProc = PXCache <TNode> .CreateCopy(doc);

                PXLongOperation.StartOperation(ccProcTran.View.Graph, delegate()
                {
                    try
                    {
                        CCProcTran refTran = new CCProcTran();
                        refTran.AuthNumber = aAuthorizationNbr;
                        CCPaymentEntry.ProcessCCTransaction(toProc, refTran, CCTranType.CaptureOnly);
                    }
                    finally
                    {
                        if (aDocStateUpdater != null)
                        {
                            aDocStateUpdater(doc, CCTranType.VoidOrCredit);
                        }
                    }
                    if (aReleaseDelegate != null)
                    {
                        aReleaseDelegate(toProc);
                    }
                });
            }
        }
        public static bool HasUnfinishedCCTrans(PXGraph aGraph, CustomerPaymentMethod aCPM)
        {
            if (aCPM.PMInstanceID < 0)
            {
                return(false);
            }

            Dictionary <string, List <PXResult <CCProcTran> > > TranDictionary = new Dictionary <string, List <PXResult <CCProcTran> > >();
            PXResultset <CCProcTran> ccTrans = PXSelect <CCProcTran, Where <CCProcTran.pMInstanceID, Equal <Required <CCProcTran.pMInstanceID> >,
                                                                            And <CCProcTran.pCTranNumber, IsNotNull> >, OrderBy <Asc <CCProcTran.pCTranNumber> > > .Select(aGraph, aCPM.PMInstanceID);

            foreach (var row in ccTrans)
            {
                CCProcTran tran = (CCProcTran)row;
                if (tran.PCTranNumber != "0")
                {
                    if (!TranDictionary.ContainsKey(tran.PCTranNumber))
                    {
                        TranDictionary[tran.PCTranNumber] = new List <PXResult <CCProcTran> >();
                    }
                    TranDictionary[tran.PCTranNumber].Add(row);
                }
            }

            bool hasUnfinishedTrans = false;

            foreach (var kvp in TranDictionary)
            {
                List <PXResult <CCProcTran> > tranList = kvp.Value;
                CCProcTran     lastTran;
                CCPaymentState ccPaymentState    = CCPaymentEntry.ResolveCCPaymentState(tranList, out lastTran);
                bool           isCCPreAuthorized = (ccPaymentState & CCPaymentState.PreAuthorized) != 0;
                if (isCCPreAuthorized && lastTran != null && (lastTran.ExpirationDate == null || lastTran.ExpirationDate > DateTime.Now))
                {
                    hasUnfinishedTrans = true;
                    break;
                }
            }
            return(hasUnfinishedTrans);
        }
        public static CCTransState UpdateCCPaymentState <T>(T doc, IEnumerable <PXResult <CCProcTran> > ccProcTrans)
            where T : class, ICCAuthorizePayment, ICCCapturePayment
        {
            CCProcTran     lastTran;
            CCPaymentState ccPaymentState       = CCPaymentEntry.ResolveCCPaymentState(ccProcTrans, out lastTran);
            bool           isCCVoided           = (ccPaymentState & CCPaymentState.Voided) != 0;
            bool           isCCCaptured         = (ccPaymentState & CCPaymentState.Captured) != 0;
            bool           isCCPreAuthorized    = (ccPaymentState & CCPaymentState.PreAuthorized) != 0;
            bool           isCCRefunded         = (ccPaymentState & CCPaymentState.Refunded) != 0;
            bool           isCCVoidingAttempted = (ccPaymentState & CCPaymentState.VoidFailed) != 0 || (ccPaymentState & CCPaymentState.RefundFailed) != 0;
            bool           needUpdate           = false;

            if (doc.IsCCAuthorized != isCCPreAuthorized || doc.IsCCCaptured != isCCCaptured)
            {
                if (!isCCVoidingAttempted)
                {
                    doc.IsCCAuthorized = isCCPreAuthorized;
                    doc.IsCCCaptured   = isCCCaptured;
                    needUpdate         = true;
                }
                else
                {
                    doc.IsCCAuthorized = false;
                    doc.IsCCCaptured   = false;
                    needUpdate         = false;
                }
            }


            if (lastTran != null && isCCPreAuthorized && lastTran.TranType == CCTranTypeCode.Authorize)
            {
                doc.CCAuthExpirationDate = lastTran.ExpirationDate;
                doc.CuryCCPreAuthAmount  = lastTran.Amount;
                needUpdate = true;
            }

            if (doc.IsCCAuthorized == false && (doc.CCAuthExpirationDate != null || doc.CuryCCPreAuthAmount > Decimal.Zero))
            {
                doc.CCAuthExpirationDate = null;
                doc.CuryCCPreAuthAmount  = Decimal.Zero;

                needUpdate = true;
            }

            if (lastTran != null &&
                (lastTran.TranType == CCTranTypeCode.PriorAuthorizedCapture ||
                 lastTran.TranType == CCTranTypeCode.AuthorizeAndCapture ||
                 lastTran.TranType == CCTranTypeCode.CaptureOnly))
            {
                if (isCCCaptured)
                {
                    doc.CuryCCCapturedAmt = lastTran.Amount;
                    doc.IsCCCaptureFailed = false;
                    needUpdate            = true;
                }
                else
                {
                    doc.IsCCCaptureFailed = true;
                    needUpdate            = true;
                }
            }

            if (doc.IsCCCaptured == false && (doc.CuryCCCapturedAmt != Decimal.Zero))
            {
                doc.CuryCCCapturedAmt = Decimal.Zero;
                needUpdate            = true;
            }

            return(new CCTransState {
                NeedUpdate = needUpdate, CCState = ccPaymentState, LastTran = lastTran
            });
        }