tipstrade / TipsTrade-HMRC

A strongly type .Net client for interacting with the HMRC APIs
MIT License
0 stars 1 forks source link

Posting VAT returns #4

Closed MrSent closed 5 years ago

MrSent commented 5 years ago

When posting a VAT return, I am trying to use the GovTestScenarios to try out set responses. I've posted into the Sandbox environment successfully but I need to try and simulate certain responses to check how my application reacts. I'm reading VAT returns from several sources which are placed into a folder where they are XML files. I read each individual one and then pull the data out and submit it. The code I have is here for the submit function. When I submit it I get a message back from the exception that just says "Invalid request". I've been through your test code to see what I'm doing differently, but I can't work it out.

` private void SubmitVATReturn(Client client, string psPath, Root pxMLVatReturn) { VatReturn vatReturn = new VatReturn(); SubmitRequest submitRequest = new SubmitRequest(); SubmitResponse submitResponse = new SubmitResponse();

        vatReturn.Finalised = pxMLVatReturn.finalised;
        vatReturn.PeriodKey = pxMLVatReturn.periodKey;
        vatReturn.VatDueSales = pxMLVatReturn.vatDueSales;                                              // Box 1
        vatReturn.VatDueAcquisitions = pxMLVatReturn.vatDueAcquisitions;                                // Box 2
        vatReturn.TotalVatDue = pxMLVatReturn.vatDueSales + pxMLVatReturn.vatDueAcquisitions;           // Box 3
        vatReturn.VatReclaimedCurrPeriod = pxMLVatReturn.vatReclaimedCurrPeriod;                        // Box 4
        vatReturn.NetVatDue = vatReturn.TotalVatDue - pxMLVatReturn.vatReclaimedCurrPeriod;             // Box 5
        vatReturn.TotalValueSalesExVAT = pxMLVatReturn.totalValueSalesExVAT;                            // Box 6
        vatReturn.TotalValuePurchasesExVAT = pxMLVatReturn.totalValuePurchasesExVAT;                    // Box 7
        vatReturn.TotalValueGoodsSuppliedExVAT = pxMLVatReturn.totalValueGoodsSuppliedExVAT;            // Box 8
        vatReturn.TotalAcquisitionsExVAT = pxMLVatReturn.totalAcquisitionsExVAT;                        // Box 9

        submitRequest.Return = vatReturn;
        submitRequest.Vrn = sVRNNo;
        submitRequest.GovTestScenario = SubmitRequest.ScenarioDuplicateSubmission;

        try
        {
            submitResponse = client.Vat.SubmitReturn(submitRequest);
            ' ^^^ Exception is raised on this line
            WriteToOutputBox(JsonConvert.SerializeObject(submitResponse, Newtonsoft.Json.Formatting.Indented));

            XNode xmlVATReturnsResponse = JsonConvert.DeserializeXNode(JsonConvert.SerializeObject(submitResponse, Newtonsoft.Json.Formatting.Indented), "Root");

            WriteToOutputBox(xmlVATReturnsResponse.ToString());
            WriteVATSubmissionResponsesToFile(xmlVATReturnsResponse.ToString());
        }
        catch (Exception ex)
        {
            WriteToOutputBox($"{ex.Message}");
        }
    }

` Have I misunderstood how the GovTestScenario settings work?

tipstrade commented 5 years ago

That should be expected behaviour. Submitting the return should throw an TipsTrade.HMRC.Api.ApiException for a duplicate submission (or for any errors that occur), so you should be catching that exception type first.

The ApiException has a property call ApiError which contains the core error message as well as a list of more specific errors in the Errors property.

Although, I'm a little surprised the message would be "Invalid request". When I try submitting a return with the ScenarioDuplicateSubmission scenario, the exception message is "Business validation error"

For example, I've just run added the following asserts to one of the tests (which succeed):

var request = new SubmitRequest() {
    Return = CreateVatReturn(periodKey),
    Vrn = Users.Organisation.User.Vrn,
    GovTestScenario = SubmitRequest.ScenarioDuplicateSubmission
};

var ex = Assert.Throws<Api.ApiException>(() => client.Vat.SubmitReturn(request));
Assert.Equal("Business validation error", ex.Message);
Assert.Equal("BUSINESS_ERROR", ex.ApiError.Code);
Assert.Equal("Business validation error", ex.ApiError.Message);
Assert.Single(ex.ApiError.Errors);
Assert.Equal("DUPLICATE_SUBMISSION", ex.ApiError.Errors.First().Code);
Assert.Equal("The VAT return was already submitted for the given period.", ex.ApiError.Errors.First().Message);

So in your case you could do this:

try {
  submitResponse = client.Vat.SubmitReturn(submitRequest);

  // ...
} catch (ApiException ex) {
  var detailedMessage = string.Join("\r\n", ex.ApiError.Errors.Select(x => x.Message));
}

Could you tell me the type of Exception that is being thrown?

MrSent commented 5 years ago

I have just noticed I am not picking up the ApiException. I think I have just this second found it. The human readable error is "{amount should be a monetary value (to 2 decimal places), between 0 and 99,999,999,999.99}" so I would imagine my test data is not good. I'll have a further play about with it. In my haste I was picking up Exception ex rather than ApiException. My bad :)

MrSent commented 5 years ago

And yes you were right. Duplicate submission gives Business validation error. Changing the scenario to Invalid Vrn give invalid request.

MrSent commented 5 years ago

Yeah sorted now. Thanks again.

tipstrade commented 5 years ago

Yup, HMRC is very picky about the formatting - I had the exact same issue as I was submitting Decimal values to 4 places. Make sure you round any Decimal values to 2 places.

Now I've got a bit of time, I'll hopefully be adding some documentation to the README.