Example #1
0
        //---------------------------------------------------------------------------------------------
        /// <summary>
        /// private Constructor for internal use only
        /// </summary>
        private PollingService()
        {
            FDatabase = VAT100Database.Instance;

            pollingTimer = new System.Timers.Timer();
            StopPolling();
            pollingTimer.Interval = DEFAULT_POLLING_INTERVAL;

            pollingTimer.Elapsed += OnTimerElapsedEvent;

            FPendingDocument = SelectNextDocument();
            if (FPendingDocument != null)
            {
                PrepareHMRCRequest(FPendingDocument);
            }
            else
            {
                //        Log.Add("Polling Service ready, but no VAT submissions are pending");
                // Switch back to the default polling interval
                pollingTimer.Interval = DEFAULT_POLLING_INTERVAL;
            }

            // Documents could arrive at any time, so poll continuously
            StartPolling();
        }
Example #2
0
        /// <summary>
        /// Sets the correct submission URL and polling interval for the
        /// supplied submission. Once this has been called, the PollingService
        /// will wait for the specified interval, and then call the HMRC
        /// service.
        /// </summary>
        /// <param name="record"></param>
        /// <returns></returns>
        private void PrepareHMRCRequest(DocumentRecord record)
        {
            pollingTimer.Interval = record.theDocument.pollingInterval * SECONDS_TO_TIMER_INTERVAL_MULTIPLIER;

            //      Log.Add(string.Format("Preparing request for HMRC service, polling interval of {0}", pollingTimer.Interval));

            switch (record.theDocument.documentType)
            {
            case "STD":
                FPendingDocument.docClass = HMRCFilingServiceProcessor.MESSAGE_CLASS_VAT_RETURN;
                destURL = HMRCFilingServiceProcessor.HMRC_LIVE_URL;
                break;

            case "TIL":
                FPendingDocument.docClass = HMRCFilingServiceProcessor.MESSAGE_CLASS_VAT_RETURN_TIL;
                destURL = HMRCFilingServiceProcessor.HMRC_LIVE_URL;
                break;

            case "DEV":
                FPendingDocument.docClass = HMRCFilingServiceProcessor.MESSAGE_CLASS_VAT_RETURN;
                destURL = HMRCFilingServiceProcessor.HMRC_DEV_URL;
                break;
            }
            return;
        }
Example #3
0
        /// <summary>
        /// Calls the HMRC Gateway web-service to retrieve the current status of the
        /// VAT Submission supplied in the Document Record, and returns an XML string
        /// of the results.
        /// </summary>
        /// <param name="record"></param>
        /// <returns></returns>
        private string RetrieveHMRCResponse(DocumentRecord record)
        {
            VAT100_Poll pollMessage = new VAT100_Poll();

            pollMessage.Header.MessageDetails.Class         = record.docClass;
            pollMessage.Header.MessageDetails.CorrelationID = record.theDocument.correlationID;
            string pollMsg;

            // Serialize the message to a string
            XmlSerializer xmlSerializer = new XmlSerializer(pollMessage.GetType());

            //SS:04/06/2018:2018-R1:ABSEXCH-20538:VAT 100 Submissions failing due to HMRC gateway changes
            using (Utf8StringWriter textWriter = new Utf8StringWriter())
            {
                xmlSerializer.Serialize(textWriter, pollMessage);
                pollMsg = textWriter.ToString();
            }

            // Submit the resulting XML to HMRC
            // Create a request
            var request = (HttpWebRequest)WebRequest.Create(FPendingDocument.theDocument.PollingURL);
            var data    = Encoding.ASCII.GetBytes(pollMsg);

            request.Method        = "POST";
            request.ContentType   = "application/x-www-form-urlencoded";
            request.ContentLength = data.Length;

            // Write the data to the request parameters
            using (var stream = request.GetRequestStream())
            {
                stream.Write(data, 0, data.Length);
            }

            // Send the request and get the response.
            var response = (HttpWebResponse)request.GetResponse();

            // Get the response in a stream.
            var responseData = new StreamReader(response.GetResponseStream()).ReadToEnd();

            // Convert the stream to a string
            string responseXML = responseData.ToString();

            return(responseXML);
        }
Example #4
0
        /// <summary>
        /// Processes the currently selected document, if any, then selects
        /// the next document. This is the central polling routine, and is
        /// called from the timer event at regular intervals, so that all
        /// pending documents are cycled through one at a time.
        /// </summary>
        private int ProcessPendingDocument()
        {
            // Need to send a poll message to HMRC for the current pending submission
            // The message has all its fixed fields populated automatically.
            // We just have to set:
            // 1) Class
            // 2) CorrelationID

            int Result = 0;

            // Stop polling while we send a polling message so that we can't possibly re-enter (especially while debugging)
            // Poll timimg is not critical and the user won't see it happening.
            StopPolling();

            try
            {
                // Ensure that we have a document to work with
                if (FPendingDocument != null)
                {
                    // Get the response message and deal with it
                    string responseXML = RetrieveHMRCResponse(FPendingDocument);
                    Result = HandleHMRCResponse(responseXML);

                    if (Result != 0)
                    {
                        Log.Add("Error handling HMRC response : Code " + Result.ToString());
                    }
                }

                FPendingDocument = SelectNextDocument();
                if (FPendingDocument != null)
                {
                    PrepareHMRCRequest(FPendingDocument);
                }
            }
            finally
            {
                StartPolling();
            }

            return(Result);
        }
Example #5
0
        //---------------------------------------------------------------------------------------------
        /// <summary>
        /// Scans the VAT100 tables in all companies to find the next VAT
        /// submission that is waiting for a response from HMRC, and returns
        /// a DocumentRecord containing the details.
        /// </summary>
        /// <returns></returns>
        private DocumentRecord SelectNextDocument()
        {
            Enterprise04.ICompanyDetail CompanyDetail;

            DocumentRecord document = null;

            // Cycle through all the companies
            int CompanyCount = FDatabase.tToolkit.Company.cmCount;

            for (int i = 1; i <= CompanyCount; i++)
            {
                // Point the Toolkit at the company path (getPendingVAT100Entry will
                // open and close the Toolkit using this path)
                CompanyDetail = FDatabase.tToolkit.Company.get_cmCompany(i);

                // Find any pending VAT Submission for this company and add it to the list
                VAT100Record Entry = FDatabase.GetPendingVAT100Entry(CompanyDetail.coCode);
                if (Entry != null)
                {
                    document             = new DocumentRecord();
                    document.theDocument = Entry;
                    document.companyCode = CompanyDetail.coCode;
                    document.companyPath = CompanyDetail.coPath;
                    document.status      = ServiceStatus.ssPolling;
                    break;
                }
            }

            if (document == null)
            {
                // No more pending documents, so revert back to the
                // slow polling interval.
                pollingTimer.Interval = DEFAULT_POLLING_INTERVAL;
            }

            return(document);
        }
Example #6
0
        /// <summary>
        /// Adds a new VAT Return Submission to the VAT100 database table following receipt of an Acknowledgement.
        /// </summary>
        /// <param name="companyCode"></param>
        /// <param name="documentType"></param>
        /// <param name="userName"></param>
        /// <param name="request"></param>
        /// <param name="acknowledgement"></param>
        /// <returns></returns>
        public bool Add(string companyCode, string documentType, string userName, VAT100_GovTalkMessage request, VAT100_Acknowledgement acknowledgement)
        {
            // Create a Document for use by the Polling functions.
            DocumentRecord newDocument = new DocumentRecord();

            newDocument.theDocument = new VAT100Record();
            newDocument.companyCode = companyCode;
            newDocument.companyPath = FDatabase.GetCompanyPath(companyCode);

            // Fill in the details
            newDocument.theDocument.correlationID = acknowledgement.Header.MessageDetails.CorrelationID;
            newDocument.theDocument.IRMark        = request.Body.IRenvelope.IRheader.IRMark.Value;
            DateTime timeNow = DateTime.Now;

            newDocument.theDocument.dateSubmitted          = timeNow.ToString("ddMMyyyy HHmmss");
            newDocument.theDocument.documentType           = documentType;
            newDocument.theDocument.VATPeriod              = request.Body.IRenvelope.IRheader.PeriodID;
            newDocument.theDocument.username               = userName;
            newDocument.theDocument.status                 = (short)SubmissionStatus.ssSubmitted;
            newDocument.theDocument.pollingInterval        = acknowledgement.Header.MessageDetails.ResponseEndPoint.PollInterval;
            newDocument.theDocument.VATDueOnOutputs        = request.Body.IRenvelope.VATDeclarationRequest.VATDueOnOutputs;
            newDocument.theDocument.VATDueOnECAcquisitions = request.Body.IRenvelope.VATDeclarationRequest.VATDueOnECAcquisitions;
            newDocument.theDocument.VATTotal               = request.Body.IRenvelope.VATDeclarationRequest.TotalVAT;
            newDocument.theDocument.VATReclaimedOnInputs   = request.Body.IRenvelope.VATDeclarationRequest.VATReclaimedOnInputs;
            newDocument.theDocument.VATNet                 = request.Body.IRenvelope.VATDeclarationRequest.NetVAT;
            newDocument.theDocument.netSalesAndOutputs     = request.Body.IRenvelope.VATDeclarationRequest.NetSalesAndOutputs;
            newDocument.theDocument.netPurchasesAndInputs  = request.Body.IRenvelope.VATDeclarationRequest.NetPurchasesAndInputs;
            newDocument.theDocument.netECSupplies          = request.Body.IRenvelope.VATDeclarationRequest.NetECSupplies;
            newDocument.theDocument.netECAcquisitions      = request.Body.IRenvelope.VATDeclarationRequest.NetECAcquisitions;

            // PKR. 16/09/2015. ABSEXCH-16865. Add a temporary narrative so that the Submission record isn't empty.
            newDocument.theDocument.hmrcNarrative = "Acknowledgement received from HMRC.";

            newDocument.theDocument.PollingURL = acknowledgement.Header.MessageDetails.ResponseEndPoint.EndPoint;

            // Save the pending document
            int Res = 0;

            // CJS 2016-06-06 - ABSEXCH-17494 - VAT submission returning HMRC message to wrong company.
            // If we are not polling, it probably means that we are searching for or processing
            // an existing document, in which case it is not safe to use the VAT100Database singleton,
            // because it is already being used and might be open in the wrong company. Instead use
            // a new instance.
            if (!pollingTimer.Enabled)
            {
                Res = VAT100Database.GetNewInstance().AddVAT100Entry(newDocument.theDocument, companyCode);
            }
            else
            {
                Res = VAT100Database.Instance.AddVAT100Entry(newDocument.theDocument, companyCode);
            }
            if (Res != 0)
            {
                Log.Add(string.Format("Failed to save pending document for {0}. Error code : {1}", companyCode, Res));
                return(false);
            }
            else
            {
                return(true);
            }
        }