From 76445ea42a959375b0e5ee2e013e25eeb2bafe92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luismi=20Cavall=C3=A9?= Date: Fri, 13 Dec 2024 12:18:31 +0000 Subject: [PATCH] Add support for other taxes to myDATA Greece --- addons/gr/mydata/extensions.go | 145 +++++++++++++++++++++++++++++- addons/gr/mydata/invoices.go | 25 +++--- addons/gr/mydata/invoices_test.go | 15 ++++ 3 files changed, 171 insertions(+), 14 deletions(-) diff --git a/addons/gr/mydata/extensions.go b/addons/gr/mydata/extensions.go index 7d4233a7..2f038f0a 100644 --- a/addons/gr/mydata/extensions.go +++ b/addons/gr/mydata/extensions.go @@ -13,8 +13,7 @@ const ( ExtKeyIncomeCat = "gr-mydata-income-cat" ExtKeyIncomeType = "gr-mydata-income-type" ExtKeyPaymentMeans = "gr-mydata-payment-means" - - InvoiceTypeRetailPrefix = "11." + ExtKeyOtherTax = "gr-mydata-other-tax" ) var extensions = []*cbc.Definition{ @@ -1024,4 +1023,146 @@ var extensions = []*cbc.Definition{ }, }, }, + { + Key: ExtKeyOtherTax, + Name: i18n.String{ + i18n.EN: "Other taxes category", + i18n.EL: "Κατηγορία Λοιπών Φόρων", + }, + Values: []*cbc.Definition{ + { + Code: "1", + Name: i18n.String{ + i18n.EN: "a1) 20% fire insurance premiums", + i18n.EL: "α1) Ασφάλιστρα κλάδου πυρός 20%", + }, + }, + { + Code: "2", + Name: i18n.String{ + i18n.EN: "a2) 20% fire insurance premiums", + i18n.EL: "α2) Ασφάλιστρα κλάδου πυρός 20%", + }, + }, + { + Code: "3", + Name: i18n.String{ + i18n.EN: "b) 4% life insurance premiums", + i18n.EL: "β) Ασφάλιστρα κλάδου ζωής 4%", + }, + }, + { + Code: "4", + Name: i18n.String{ + i18n.EN: "c) 15% other insurance premiums", + i18n.EL: "γ) Ασφάλιστρα λοιπών κλάδων 15%", + }, + }, + { + Code: "5", + Name: i18n.String{ + i18n.EN: "d) 0% tax-exempt insurance premiums", + i18n.EL: "δ) Απαλλασσόμενα φόρου ασφάλιστρα 0%", + }, + }, + { + Code: "6", + Name: i18n.String{ + i18n.EN: "Hotels 1-2 stars 0,50 €", + i18n.EL: "Ξενοδοχεία 1-2 αστέρων 0,50 €", + }, + }, + { + Code: "7", + Name: i18n.String{ + i18n.EN: "Hotels 3 stars 1,50 €", + i18n.EL: "Ξενοδοχεία 3 αστέρων 1,50 €", + }, + }, + { + Code: "8", + Name: i18n.String{ + i18n.EN: "Hotels 4 stars 3,00 €", + i18n.EL: "Ξενοδοχεία 4 αστέρων 3,00 €", + }, + }, + { + Code: "9", + Name: i18n.String{ + i18n.EN: "Hotels 5 stars 4,00 €", + i18n.EL: "Ξενοδοχεία 5 αστέρων 4,00 €", + }, + }, + { + Code: "10", + Name: i18n.String{ + i18n.EN: "Rental rooms - Furnished rooms - Apartments 0,50 €", + i18n.EL: "Ενοικιαζόμενα δωμάτια - Επιπλωμένα δωμάτια - Διαμερίσματα 0,50 €", + }, + }, + { + Code: "11", + Name: i18n.String{ + i18n.EN: "Special 5% tax on tv-broadcast commercials (EFTD)", + i18n.EL: "Ειδικός φόρος στις διαφημίσεις που προβάλλονται από την τηλεόραση (ΕΦΔΤ) 5%", + }, + }, + { + Code: "12", + Name: i18n.String{ + i18n.EN: "10% luxury tax on the taxable value of intra-community acquired goods and those imported from third countries", + i18n.EL: "Φόρος πολυτελείας 10% επί της φορολογητέας αξίας για τα ενδοκοινοτικά αποκτήματα και εισαγόμενα από τρίτες χώρες", + }, + }, + { + Code: "13", + Name: i18n.String{ + i18n.EN: "10% luxury tax on the selling price before VAT for domestically produced goods", + i18n.EL: "Φόρος πολυτελείας 10% επί της τιμής πώλησης προ Φ.Π.Α. για τα εγχωρίως παραγόμενα", + }, + }, + { + Code: "14", + Name: i18n.String{ + i18n.EN: "80% Public fees on the admission ticket price for casinos", + i18n.EL: "Δικαιώματα του Δημοσίου στα εισιτήρια των καζίνο (80% επί του εισιτηρίου)", + }, + }, + { + Code: "15", + Name: i18n.String{ + i18n.EN: "Fire industry insurance premiums 20%", + i18n.EL: "Ασφάλιστρα κλάδου πυρός 20%", + }, + }, + { + Code: "16", + Name: i18n.String{ + i18n.EN: "Customs duties- Taxes", + i18n.EL: "Λοιποί Τελωνειακοί Δασμοί-Φόροι", + }, + }, + { + Code: "17", + Name: i18n.String{ + i18n.EN: "Other Taxes", + i18n.EL: "Λοιποί Φόροι", + }, + }, + { + Code: "18", + Name: i18n.String{ + i18n.EN: "Charges of other Taxes", + i18n.EL: "Επιβαρύνσεις Λοιπών Φόρων", + }, + }, + { + Code: "19", + Name: i18n.String{ + i18n.EN: "Special consumption tax", + i18n.EL: "ΕΦΚ", + }, + }, + }, + }, } diff --git a/addons/gr/mydata/invoices.go b/addons/gr/mydata/invoices.go index e3209664..2187bd9d 100644 --- a/addons/gr/mydata/invoices.go +++ b/addons/gr/mydata/invoices.go @@ -26,7 +26,7 @@ func validateInvoice(inv *bill.Invoice) error { ), validation.Field(&inv.Customer, validation.When( - !IsRetail(inv), + requiresValidCustomer(inv), validation.Required, validation.By(validateBusinessParty), validation.By(validateBusinessCustomer), @@ -40,10 +40,6 @@ func validateInvoice(inv *bill.Invoice) error { ), validation.Skip, ), - validation.Field(&inv.Charges, - validation.Empty.Error("not supported by mydata"), - validation.Skip, - ), validation.Field(&inv.Discounts, validation.Empty.Error("not supported by mydata"), validation.Skip, @@ -182,13 +178,18 @@ func validateInvoicePreceding(value any) error { ) } -// IsRetail returns true if the invoice type corresponds to a retail invoice. -func IsRetail(inv *bill.Invoice) bool { - if inv.Tax == nil || inv.Tax.Ext == nil { - return false - } +// requiresValidCustomer returns true if the invoice type requires a customer. +func requiresValidCustomer(inv *bill.Invoice) bool { + // Invoice type categories that require a valid customer. + typeCats := []string{"1", "2", "5"} + + it := inv.Tax.Ext[ExtKeyInvoiceType].String() - it := inv.Tax.Ext[ExtKeyInvoiceType] + for _, prefix := range typeCats { + if strings.HasPrefix(it, prefix+".") { + return true + } + } - return strings.HasPrefix(string(it), InvoiceTypeRetailPrefix) + return false } diff --git a/addons/gr/mydata/invoices_test.go b/addons/gr/mydata/invoices_test.go index 9a7c2986..6ce96df5 100644 --- a/addons/gr/mydata/invoices_test.go +++ b/addons/gr/mydata/invoices_test.go @@ -102,6 +102,21 @@ func TestSimplifiedInvoiceValidation(t *testing.T) { assert.NoError(t, inv.Validate()) } +func TestOtherInvoiceTypeValidation(t *testing.T) { + inv := validInvoice() + inv.Type = bill.InvoiceTypeOther + inv.Tax = &bill.Tax{ + Ext: tax.Extensions{ + mydata.ExtKeyInvoiceType: "8.2", + }, + } + inv.Customer.TaxID = nil + inv.Customer.Addresses = nil + + require.NoError(t, inv.Calculate()) + assert.NoError(t, inv.Validate()) +} + func TestPrecedingValidation(t *testing.T) { inv := validInvoice()