I'm starting to feel a little bit of deadline pressure.
I need to get my accounts submitted by the end of September, and it's now the middle of July. If that doesn't sound like deadline pressure to you, then you're not me 🙂
The sample XML I have been working from up until now has been called no-attach.xml because it doesn't have any attachments. The accounts are an attachment, so we need to look at another example that has that. If it seems to you that I've suddenly changed my focus from CT600 to attachments, it's because my focus at the moment is on getting something complete that HMRC will accept; I can then come back and make something that reflects my accounts and does the appropriate CT600 computations; while that will require more configuration and coding, I'm confident that I can do that, and I don't think that's very interesting. On the other hand, I suspect that there is significant risk in trying to attach something to the return.
I have checked the HMRC sample with accounts attachments in as ixbrl-accounts.xml. This is basically what it has that the other one doesn't:
<ThisPeriodAccounts>yes</ThisPeriodAccounts>...
<AttachedFiles>
<XBRLsubmission>
<Accounts>
<Instance>
<InlineXBRLDocument>
<!-- Place your iXBRL accounts here -->
</InlineXBRLDocument>
</Instance>
</Accounts>
</XBRLsubmission>
</AttachedFiles>
CT600_SAMPLE_ATTACHMENTS:accounts/ct600/ixbrl-accounts.xml
This is less enlightening than I had hoped. An example of the ixbrl would be nice.iXBRL
I struggled to find examples out there of iXBRL accounts. There is an organisation that plugs iXBRL, and it has some resources, such as the specification but the only useful example I could find was a sample in PDF on the Companies House website. I would have preferred an XHTML example, but I have extracted the text from the PDF and checked it in as ixbrl-sample.xml (we will use this in a bit as our first cut at a document to include) and we can have a look at it.This is an outline:
<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ix="http://www.xbrl.org/2008/inlineXBRL"
xmlns:link="http://www.xbrl.org/2003/linkbase"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xbrldi="http://xbrl.org/2006/xbrldi"
xmlns:iso4217="http://www.xbrl.org/2003/iso4217"
xmlns:uk-gaap-pt="http://www.xbrl.org/uk/gaap/core/2009-09-01"
xmlns:uk-gaap-cd-bus="http://www.xbrl.org/uk/cd/business/2009-09-01"
xmlns:uk-gaap-rp-dir="http://www.xbrl.org/uk/reports/direp/2009-09-01"
xmlns:ixt="http://www.xbrl.org/2008/inlineXBRL/transformation"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.w3.org/1999/xhtml http://www.xbrl.org/2008/inlineXBRL/xhtml-inlinexbrl-1_0.xsd">
<head>
<meta name="generator" content="Companies House WebFiling - AA02 Form"/>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<style type="text/css">
...
</style>
<title>Dormant Company Accounts - CH Sample Company Ltd</title>
</head>
<body>
<div class="hidden">
<ix:header>
<ix:hidden>
...
</ix:hidden>
<ix:references>
<link:schemaRef xlink:type="simple" xlink:href="http://www.xbrl.org/uk/uk-gaap-main-2009-09-01.xsd"/>
</ix:references>
<ix:resources>
...
</ix:resources>
</ix:header>
</div>
<div class="titlepage accountspage pagebreak title">
<p>Registered Number 12345678</p>
<p>CH Sample Company Ltd</p>
<p>Dormant Accounts</p>
<p>31 December 2011</p>
<p class="dottedLine"/>
</div>
<div class="accountspage">
<div class="accountsheader">
<h2 class="print">CH Sample Company Ltd<span class="right">Registered Number 12345678</span></h2>
<p class="print spacer"/>
</div>
<div id="balancesheet">
...
</div>
<div id="statements">
...
</div>
<div id="approval">
...
</div>
</div>
</body>
</html>
CT600_SAMPLE_ATTACHMENTS:accounts/ct600/ixbrl-sample.xml
It starts off reasonably enough. XHTML docs are supposed to have a DOCTYPE, but I will accept they chose not to do that because it is for inline use. Note all the schema definitions. I wonder if I have those schemas in my technical packs somewhere or if I can download them somewhere. We will need schemas for anything that we want to run through the validator.To comply with the "inline xbrl" rules, the document must be fully self-contained. Since it isn't allowed to have Javascript anyway, linking in script files is not an issue. On the other hand, all the CSS needs to be included as an inline style. For us, I think it will make sense to copy those in from files provided to us in the configuration when we're ready to do that.
I don't know about you, but this ix:header block seems weird to me. I was expecting everything to be nested inside the visible elements. Why are there things that are sent electronically but would not be in the paper copy? Especially when you are already embedded in an envelope that handles all the authentication?
I was very close to the end of the specification before I realized that there is something weird going on here. Weird, but probably very sensible when you understand it.
I am going to suggest that ixbrl is akin to literate programming, and the ixbrl content we submit is the woven version of the program. There is a process by which the "original code" - in this case, a straightforward xbrl XML document, can be extracted. This needs more things than the paper copy in order to comply with a schema or something, and it needs those things in a particular order. Thus the ixbrl needs to contain instructions on how to do that; we will presumably come back to that when we are generating our accounts. Whatever this process is, it is internal to the HMRC, so I'm not sure whether we can duplicate it, or whether we will just have to deal with any errors when we submit our ixbrl attachments.
In addition to submitting accounts, there is also the requirement (or opportunity?) to submit "tax computations" as an ixbrl. If you thought there weren't many examples of ixbrl accounts out there, you'll be even more disappointed by the tax computations.
All I could find was a picture in a slide deck and an example from a tax preparer.
Fortunately, I also have my previous years' accounts which I believe are in ixbrl, so hopefully that will help. I also found this guide which has quite a lot of useful information in it.
If we can generate the ixbrl for the tax computations, it's at least clear what to do with it in the submitted XML:
<ThisPeriodComputations>yes</ThisPeriodComputations>...
<AttachedFiles>
<XBRLsubmission>
<Computation>
<Instance>
<InlineXBRLDocument>
<!-- Place your iXBRL comps here -->
</InlineXBRLDocument>
</Instance>
</Computation>
</XBRLsubmission>
</AttachedFiles>
CT600_SAMPLE_ATTACHMENTS:accounts/ct600/ixbrl-computations.xml
Submitting what We Have
I am now thoroughly bored of reading what I can find and the fruitless searching for other things. So I want to return to writing code.At the moment, we just have the "no accounts" message hacked in during accounts:
func accounts() any {
return ElementWithNesting("Accounts", ElementWithText("NoAccountsReason", "Not within charge to CT"))
}
func computations() any {
return ElementWithNesting("Computations", ElementWithText("NoComputationsReason", "Not within charge to CT"))
}
CT600_SAMPLE_ATTACHMENTS:accounts/internal/ct600/govtalk/irenvelope.go
We need to change this to support variable content. Starting at the top, we can add new customization to the IREnvelope (this is still hardcoded, but it drives the rest of the layers):func Submit(conf *config.Config) error {
utr := conf.Utr
if utr == "" {
utr = conf.Business.TaxNum
}
ctr := &govtalk.IRenvelope{Business: conf.Business, ReturnType: "new",
Sender: "Company", // the type of business we are, I believe. The schema limits it to a handful of options
UTR: utr,
PeriodStart: "2021-04-01", PeriodEnd: "2022-03-31",
Turnover: 100000.0, TradingProfits: 0, LossesBroughtForward: 0, TradingNetProfits: 0,
CorporationTax: 0,
AccountsIXBRL: "ct600/ixbrl-sample.xml",
NoComputationsReason: "Not within charge to CT",
}
submitOptions := &govtalk.EnvelopeOptions{Qualifier: "request", Function: "submit", IncludeSender: true, IncludeKeys: true, IncludeBody: true, IRenvelope: ctr}
CT600_IXBRL_ACCOUNTS:accounts/internal/ct600/submission/submit.go
This is then analyzed in the IREnvelope AsXML method:type IRenvelope struct {
Business config.Business
UTR string
ReturnType string
PeriodStart string
PeriodEnd string
Sender string
Turnover float64
TradingProfits float64
LossesBroughtForward float64
TradingNetProfits float64
CorporationTax float64
NoAccountsReason string
AccountsIXBRL string
NoComputationsReason string
ComputationsIXBRL string
}
func (ire *IRenvelope) AsXML() any {
if ire.NoAccountsReason == "" && ire.AccountsIXBRL == "" {
log.Fatalf("Must give accounts or a reason not to")
}
if ire.NoAccountsReason != "" && ire.AccountsIXBRL != "" {
log.Fatalf("Must EITHER give accounts OR a reason not to")
}
if ire.NoComputationsReason == "" && ire.ComputationsIXBRL == "" {
log.Fatalf("Must give computations or a reason not to")
}
if ire.NoComputationsReason != "" && ire.ComputationsIXBRL != "" {
log.Fatalf("Must EITHER give computations OR a reason not to")
}
CT600_IXBRL_ACCOUNTS:accounts/internal/ct600/govtalk/irenvelope.go
And used to build the summary, and then the attachments are added to the end of the overall return:summary := ElementWithNesting("ReturnInfoSummary", ire.accounts(), ire.computations())
turnover := ElementWithNesting("Turnover", ElementWithText("Total", fmt.Sprintf("%.2f", ire.Turnover)))
calc := ElementWithNesting("CompanyTaxCalculation", ire.taxCalc())
too := ElementWithNesting("CalculationOfTaxOutstandingOrOverpaid", ire.cotoo())
decl := ElementWithNesting("Declaration", decl())
attachments := ire.figureAttachments()
var attach any
if attachments != nil {
attach = ElementWithNesting("AttachedFiles", ElementWithNesting("XBRLsubmission", attachments))
}
ctr := MakeCompanyTaxReturn(ire.ReturnType, ci, summary, turnover, calc, too, decl, attach)
return MakeIRenvelopeMessage(irh, ctr)
}
CT600_IXBRL_ACCOUNTS:accounts/internal/ct600/govtalk/irenvelope.go
The excuses are now conditional:func (ire *IRenvelope) accounts() any {
if ire.NoAccountsReason != "" {
return ElementWithNesting("Accounts", ElementWithText("NoAccountsReason", ire.NoAccountsReason))
} else {
return ElementWithNesting("Accounts", ElementWithText("ThisPeriodAccounts", "yes"))
}
}
func (ire *IRenvelope) computations() any {
if ire.NoComputationsReason != "" {
return ElementWithNesting("Computations", ElementWithText("NoComputationsReason", ire.NoComputationsReason))
} else {
return ElementWithNesting("Computations", ElementWithText("ThisPeriodComputations", "yes"))
}
}
CT600_IXBRL_ACCOUNTS:accounts/internal/ct600/govtalk/irenvelope.go
And code appears at the end to generate XML elements for the attached accounts and computations:func (ire *IRenvelope) figureAttachments() []any {
ret := []any{}
if ire.AccountsIXBRL != "" {
acxml := ElementWithNesting("Accounts", ElementWithNesting("Instance", ContentFromFile("InlineXBRLDocument", ire.AccountsIXBRL)))
ret = append(ret, acxml)
}
return ret
}
CT600_IXBRL_ACCOUNTS:accounts/internal/ct600/govtalk/irenvelope.go
We need some more tricks from Go's book of tricks for manipulating XML to get this to work by just including a file from the disk (which is probably only temporary as we expect to generate this later, but we will probably end up inlining CSS):type ContentElement struct {
XMLName xml.Name
Content []byte `xml:",innerxml"`
}
CT600_IXBRL_ACCOUNTS:accounts/internal/ct600/govtalk/xml.go
The innerxml here says that this is a "string" which contains formatted XML, so don't reformat it.func ContentFromFile(tag, filename string) *ContentElement {
fp, err := os.Open(filename)
if err != nil {
log.Fatalf("Could not read %s: %v", filename, err)
}
defer fp.Close()
bs, err := io.ReadAll(fp)
if err != nil {
log.Fatalf("Could not read %s: %v", filename, err)
}
return &ContentElement{XMLName: xml.Name{Local: tag}, Content: bs}
}
CT600_IXBRL_ACCOUNTS:accounts/internal/ct600/govtalk/xml.go
And we can create one of these by reading a file and not doing sensible error handling because I can't be bothered right now (it may appear at some point).We can now run through that submission and get to this point when we check the response:
2 error(s) reported:OK, given that it does appear to validate on my end (before we submit it), we have to figure that the problem here is that the inline document itself fails schema validation. It would be nice if it gave a crisper error. It would be nice if there were more throughly worked examples. Within the realm of reality though, it would be nice if I had more schema definitions to check it against. I can at least go and look for those.
Code Raised By Location Type Message
3001 Department business The submission of this document has failed due to departmental specific business logic in the Body tag.
4999 ChRIS /hd:GovTalkMessage[1]/hd:Body[1]/ct:IRenvelope[1]/ct:CompanyTaxReturn[1]/ct:AttachedFiles[1]/ct:XBRLsubmission[1]/ct:Accounts[1]/ct:Instance[1]/ct:InlineXBRLDocument[1] schema Internal schema validation error
No comments:
Post a Comment