@@ -11,6 +11,27 @@ import (
1111// invoiceValidator adds validation checks to invoices which are relevant
1212// for the region.
1313func validateInvoice (inv * bill.Invoice ) error {
14+ if inv .Tags .HasTags (tax .TagSimplified ) {
15+ // Simplified invoices only require a supplier tax ID.
16+ return validation .ValidateStruct (inv ,
17+ validation .Field (& inv .Customer ,
18+ validation .When (
19+ inv .Customer != nil ,
20+ validation .Empty ,
21+ ),
22+ validation .Nil ,
23+ validation .Skip ,
24+ ),
25+ validation .Field (& inv .Supplier ,
26+ validation .Required ,
27+ validation .By (validateSupplier ),
28+ validation .By (validateSupplierSimplifiedInvoice ),
29+ validation .Skip ,
30+ ),
31+ )
32+ }
33+
34+ // Standard invoices require a supplier and customer.
1435 return validation .ValidateStruct (inv ,
1536 validation .Field (& inv .Supplier ,
1637 validation .Required ,
@@ -21,18 +42,19 @@ func validateInvoice(inv *bill.Invoice) error {
2142 validation .Field (& inv .Customer ,
2243 validation .Required ,
2344 validation .By (validateOrgParty ),
24- validation .By (validateCustomer ),
2545 validation .Skip ,
2646 ),
2747 )
2848}
2949
50+ // validateOrgParty holds the common checks for both the supplier and customer.
3051func validateOrgParty (value any ) error {
3152 party , ok := value .(* org.Party )
3253 if ! ok || party == nil {
3354 return nil
3455 }
3556
57+ // Name and addresses are always required.
3658 return validation .ValidateStruct (party ,
3759 validation .Field (& party .Name ,
3860 validation .Required ,
@@ -42,11 +64,31 @@ func validateOrgParty(value any) error {
4264 validation .Required ,
4365 validation .Skip ,
4466 ),
67+ validation .Field (& party .Identities ,
68+ // If the party is registered in Sweden for tax purposes,
69+ // then its identities must be one of the allowed types.
70+ validation .When (
71+ party .TaxID != nil && party .TaxID .Country == l10n .TaxCountryCode (l10n .SE ),
72+ validation .Each (
73+ validation .By (func (value any ) error {
74+ id , ok := value .(* org.Identity )
75+ if ! ok || id == nil {
76+ return nil
77+ }
78+ if ! id .Type .In (IdentityTypeOrgNr , IdentityTypePersonNr , IdentityTypeCoordinationNr ) {
79+ return validation .NewError ("type" , "must be one of: SE-ON, SE-PN, SE-CN" )
80+ }
81+ return nil
82+ }),
83+ ),
84+ ),
85+ validation .Skip ,
86+ ),
4587 )
4688}
4789
48- // validateSupplier checks the supplier's tax ID and organization number requirements.
49- // The supplier's VAT number and ID Number are always required.
90+ // validateSupplier checks the supplier's tax ID requirements.
91+ // The supplier's VAT number is always required.
5092func validateSupplier (value any ) error {
5193 party , ok := value .(* org.Party )
5294 if ! ok || party == nil {
@@ -58,7 +100,8 @@ func validateSupplier(value any) error {
58100 // and must have the correct format.
59101 validation .Field (& party .TaxID ,
60102 validation .Required ,
61- validation .By (func (value interface {}) error {
103+ tax .RequireIdentityCode ,
104+ validation .By (func (value any ) error {
62105 tID , ok := value .(* tax.Identity )
63106 if ! ok || tID == nil {
64107 return nil
@@ -67,35 +110,23 @@ func validateSupplier(value any) error {
67110 }),
68111 validation .Skip ,
69112 ),
70- validation .Field (& party .Identities ,
71- validation .Required ,
72- validation .In (
73- org .RequireIdentityType (IdentityTypeOrgNr ),
74- org .RequireIdentityType (IdentityTypePersonNr ),
75- org .RequireIdentityType (IdentityTypeCoordinationNr ),
76- ),
77- ),
78113 )
79114}
80115
81- // validateCustomer checks the customer's tax ID and organization number requirements.
82- // However, the customer may not include any identities, just a name and address.
83- func validateCustomer (value any ) error {
116+ func validateSupplierSimplifiedInvoice (value any ) error {
84117 party , ok := value .(* org.Party )
85118 if ! ok || party == nil {
86119 return nil
87120 }
88121
89122 return validation .ValidateStruct (party ,
90- validation .Field (& party .Identities ,
91- validation .When (
92- party .TaxID != nil && party .TaxID .Country == l10n .TaxCountryCode (l10n .SE ),
93- validation .In (
94- org .RequireIdentityType (IdentityTypeOrgNr ),
95- org .RequireIdentityType (IdentityTypePersonNr ),
96- org .RequireIdentityType (IdentityTypeCoordinationNr ),
97- ),
98- ),
123+ validation .Field (& party .Name ,
124+ validation .NilOrNotEmpty ,
125+ validation .Skip ,
126+ ),
127+ validation .Field (& party .Addresses ,
128+ validation .NilOrNotEmpty ,
129+ validation .Skip ,
99130 ),
100131 )
101132}
0 commit comments