From f3f4c54d6a49de3a37c2239416c4338252ea06a2 Mon Sep 17 00:00:00 2001 From: Luc Saffre Date: Tue, 10 Dec 2019 22:21:24 +0200 Subject: [PATCH] http://luc.lino-framework.org/blog/2019/1210.html --- lino_xl/lib/bevat/choicelists.py | 23 +-- lino_xl/lib/bevats/choicelists.py | 18 +-- lino_xl/lib/eevat/choicelists.py | 142 ++++++++++++------- lino_xl/lib/eevat/desktop.py | 2 +- lino_xl/lib/ledger/choicelists.py | 13 +- lino_xl/lib/ledger/fixtures/demo_bookings.py | 4 +- lino_xl/lib/ledger/ui.py | 2 +- lino_xl/lib/products/fixtures/furniture.py | 18 ++- lino_xl/lib/products/models.py | 2 +- lino_xl/lib/sales/fixtures/demo_bookings.py | 5 +- lino_xl/lib/sales/mixins.py | 7 +- lino_xl/lib/vat/__init__.py | 2 +- lino_xl/lib/vat/choicelists.py | 15 +- lino_xl/lib/vat/desktop.py | 17 ++- lino_xl/lib/vat/mixins.py | 22 ++- lino_xl/lib/vat/models.py | 6 - 16 files changed, 179 insertions(+), 119 deletions(-) diff --git a/lino_xl/lib/bevat/choicelists.py b/lino_xl/lib/bevat/choicelists.py index 1c6bbbc2..ad26d2aa 100644 --- a/lino_xl/lib/bevat/choicelists.py +++ b/lino_xl/lib/bevat/choicelists.py @@ -33,18 +33,24 @@ add('71', _("Luxemburg"), 'lu') +VAT_CLASSES_AND_RATES = [("services", "0.21"), ("goods", "0.21"), ("reduced", "0.07")] VatRules.clear() add = VatRules.add_item -add('normal', '0.21', NAT, 'purchases', None, CommonAccounts.vat_deductible) -add('reduced', '0.07', NAT, 'purchases', None, CommonAccounts.vat_deductible) -add('normal', '0.21', EU, 'purchases', 'intracom', CommonAccounts.vat_deductible, CommonAccounts.vat_returnable) -add('reduced', '0.07', EU, 'purchases', 'intracom', CommonAccounts.vat_deductible, CommonAccounts.vat_returnable) +for vat_class, rate in VAT_CLASSES_AND_RATES: + add(vat_class, rate, NAT, 'purchases', None, CommonAccounts.vat_deductible) + add(vat_class, rate, EU, 'purchases', 'intracom', CommonAccounts.vat_deductible, CommonAccounts.vat_returnable) + add(vat_class, rate, None, 'sales', None, CommonAccounts.vat_due) + +# add('normal', '0.21', NAT, 'purchases', None, CommonAccounts.vat_deductible) +# add('reduced', '0.07', NAT, 'purchases', None, CommonAccounts.vat_deductible) +# add('normal', '0.21', EU, 'purchases', 'intracom', CommonAccounts.vat_deductible, CommonAccounts.vat_returnable) +# add('reduced', '0.07', EU, 'purchases', 'intracom', CommonAccounts.vat_deductible, CommonAccounts.vat_returnable) # add('normal', '0.21', EU, 'sales', 'intracom', CommonAccounts.vat_due, CommonAccounts.vat_returnable) # add('reduced', '0.07', EU, 'sales', 'intracom', CommonAccounts.vat_due, CommonAccounts.vat_returnable) -add('normal', '0.00', EU, 'sales', 'intracom') -add('reduced', '0.00', EU, 'sales', 'intracom') -add('normal', '0.21', None, 'sales', None, CommonAccounts.vat_due) -add('reduced', '0.07', None, 'sales', None, CommonAccounts.vat_due) +# add('normal', '0.00', EU, 'sales', 'intracom') +# add('reduced', '0.00', EU, 'sales', 'intracom') +# add('normal', '0.21', None, 'sales', None, CommonAccounts.vat_due) +# add('reduced', '0.07', None, 'sales', None, CommonAccounts.vat_due) add() @@ -63,7 +69,6 @@ - class DeclarationFields(DeclarationFieldsBase): pass diff --git a/lino_xl/lib/bevats/choicelists.py b/lino_xl/lib/bevats/choicelists.py index 7e6d8748..0cf8aa7d 100644 --- a/lino_xl/lib/bevats/choicelists.py +++ b/lino_xl/lib/bevats/choicelists.py @@ -29,20 +29,14 @@ add('30', _("Intracom services"), 'intracom', EU, needs_vat_id=True) add('35', _("Intracom supplies"), 'intracom_supp', EU, needs_vat_id=True) - +VAT_CLASSES_AND_RATES = [("services", "0.21"), ("goods", "0.21"), ("reduced", "0.07")] VatRules.clear() add = VatRules.add_item -add('normal', '0.21', NAT, 'purchases', 'subject', CommonAccounts.vat_deductible) -add('reduced', '0.07', NAT, 'purchases', 'subject', CommonAccounts.vat_deductible) -# add('normal', '0.21', EU, 'purchases', 'intracom', CommonAccounts.vat_deductible, CommonAccounts.vat_returnable) -# add('reduced', '0.07', EU, 'purchases', 'intracom', CommonAccounts.vat_deductible, CommonAccounts.vat_returnable) -# add('normal', '0.21', EU, 'purchases', 'intracom_supp', CommonAccounts.vat_deductible, CommonAccounts.vat_returnable) -# add('reduced', '0.07', EU, 'purchases', 'intracom_supp', CommonAccounts.vat_deductible, CommonAccounts.vat_returnable) -add('normal', '0.21', EU, 'purchases', 'intracom', CommonAccounts.vat_due, vat_returnable=True) -add('reduced', '0.07', EU, 'purchases', 'intracom', CommonAccounts.vat_due, vat_returnable=True) -add('normal', '0.21', EU, 'purchases', 'intracom_supp', CommonAccounts.vat_due, vat_returnable=True) -add('reduced', '0.07', EU, 'purchases', 'intracom_supp', CommonAccounts.vat_due, vat_returnable=True) -add() +for vat_class, rate in VAT_CLASSES_AND_RATES: + add(vat_class, rate, NAT, 'purchases', 'subject', CommonAccounts.vat_deductible) + add(vat_class, rate, EU, 'purchases', 'intracom', CommonAccounts.vat_due, vat_returnable=True) + add(vat_class, rate, EU, 'purchases', 'intracom_supp', CommonAccounts.vat_due, vat_returnable=True) +add() # allow any other combination with rate 0 # print('\n'.join(["{}:{}".format(i.vat_area, i.vat_regime) for i in VatRules.get_list_items()])) # for va in VatAreas.get_list_items(): diff --git a/lino_xl/lib/eevat/choicelists.py b/lino_xl/lib/eevat/choicelists.py index f49e55c9..b06290cd 100644 --- a/lino_xl/lib/eevat/choicelists.py +++ b/lino_xl/lib/eevat/choicelists.py @@ -13,6 +13,7 @@ from lino_xl.lib.vat.choicelists import VatRegimes, VatAreas, VatRules from lino_xl.lib.ledger.choicelists import CommonAccounts + NAT = VatAreas.national EU = VatAreas.eu INT = VatAreas.international @@ -26,41 +27,48 @@ add('30', _("Intra-community"), 'intracom', EU, needs_vat_id=True) # add('31', _("Delay in collection"), 'delayed', EU) # report de perception # add('40', _("Inside EU"), 'inside', EU) +add('40', _("Tax-free"), 'tax_free') add('50', _("Outside EU"), 'outside', INT) -add('60', _("Exempt"), 'exempt', item_vat=False) +add('60', _("Exempt"), 'exempt', item_vat=False) # army, ... if False: # tim2lino can need it add('70', _("Germany"), 'de') add('71', _("Luxemburg"), 'lu') +VAT_CLASSES_AND_RATES = [ + ("services", "0.20"), ("goods", "0.20"), + ("real_estate", "0.20"), ("vehicles", "0.20"), + ("reduced", "0.09")] VatRules.clear() add = VatRules.add_item -add('normal', '0.20', NAT, 'purchases', None, CommonAccounts.vat_deductible) -add('reduced', '0.09', NAT, 'purchases', None, CommonAccounts.vat_deductible) -add('normal', '0.20', EU, 'purchases', 'intracom', CommonAccounts.vat_deductible, CommonAccounts.vat_returnable) -add('reduced', '0.09', EU, 'purchases', 'intracom', CommonAccounts.vat_deductible, CommonAccounts.vat_returnable) -# add('normal', '0.20', EU, 'sales', 'intracom', CommonAccounts.vat_due, CommonAccounts.vat_returnable) -# add('reduced', '0.09', EU, 'sales', 'intracom', CommonAccounts.vat_due, CommonAccounts.vat_returnable) -add('normal', '0.00', EU, 'sales', 'intracom') -add('reduced', '0.00', EU, 'sales', 'intracom') -add('reduced', '0.09', None, 'sales', None, CommonAccounts.vat_due) -add('normal', '0.20', None, 'sales', None, CommonAccounts.vat_due) -add() +# vat_class rate vat_area trade_type vat_regime vat_account vat_returnable_account vat_returnable +add(None, '0', None, None, "exempt") + + +for vat_class, rate in VAT_CLASSES_AND_RATES: + for vat_regime, area in [('intracom', EU), ('cocontractor', NAT)]: + add(vat_class, rate, area, 'purchases', vat_regime, CommonAccounts.vat_deductible, CommonAccounts.vat_returnable) + add(vat_class, rate, area, 'sales', vat_regime, CommonAccounts.vat_due, CommonAccounts.vat_returnable) + +for vat_class, rate in VAT_CLASSES_AND_RATES: + add(vat_class, rate, NAT, 'purchases', None, CommonAccounts.vat_deductible) + add(vat_class, rate, None, 'sales', None, CommonAccounts.vat_due) + +add() # allow any other combination with rate 0 + VatColumns.clear() add = VatColumns.add_item -add('00', _("Sales with 20% VAT"), CommonAccounts.sales) -add('01', _("Sales with 9% VAT"), CommonAccounts.sales) -add('02', _("Sales with 0% VAT"), CommonAccounts.sales) +add('10', _("Sales turnover"), CommonAccounts.sales) +# add('01', _("Sales with 20% VAT"), CommonAccounts.sales) +# add('02', _("Sales with 9% VAT"), CommonAccounts.sales) +# add('03', _("Sales with 0% VAT"), CommonAccounts.sales) add('40', _("VAT due"), CommonAccounts.vat_due) add('41', _("VAT returnable"), CommonAccounts.vat_returnable) add('50', _("VAT deductible"), CommonAccounts.vat_deductible) -add('51', _("VAT deductible import"), CommonAccounts.vat_deductible) -add('52', _("VAT deductible real estate"), CommonAccounts.vat_deductible) -add('53', _("VAT deductible vehicles 100%"), CommonAccounts.vat_deductible) -add('54', _("VAT deductible vehicles"), CommonAccounts.vat_deductible) -add('81', _("Purchase of goods"), CommonAccounts.purchase_of_goods) -add('82', _("Purchase of services"), CommonAccounts.purchase_of_services) -add('83', _("Purchase of investments"), CommonAccounts.purchase_of_investments) +add('60', _("Purchase of goods"), CommonAccounts.purchase_of_goods) +add('61', _("Other purchases"), CommonAccounts.purchase_of_services) +# add('62', _("Purchase of services"), CommonAccounts.purchase_of_services) +# add('63', _("Purchase of investments"), CommonAccounts.purchase_of_investments) class DeclarationFields(DeclarationFieldsBase): @@ -73,48 +81,78 @@ class DeclarationFields(DeclarationFieldsBase): # https://www.riigiteataja.ee/aktilisa/1060/1201/7010/Lisa%201.pdf# -# value, dc, vat_columns, text +# value dc vat_columns text // fieldnames both_dc vat_regimes vat_classes + +mfld("1", CREDIT, '10', "20% määraga maksustatavad toimingud ja tehingud", + vat_classes="goods services", vat_regimes="!exempt !tax_free !intracom !cocontractor") +mfld("2", CREDIT, '10', "9% määraga maksustatavad toimingud ja tehingud", + vat_classes="reduced", vat_regimes="!exempt !tax_free !intracom !cocontractor") + +mfld("3", CREDIT, '10', "0% määraga maksustatavad toimingud ja tehingud, sh", + vat_regimes="exempt tax_free intracom cocontractor") -mfld("1", CREDIT, '00', "20% määraga maksustatavad toimingud ja tehingud") -mfld("2", CREDIT, '01', "9% määraga maksustatavad toimingud ja tehingud") -mfld("3", CREDIT, '02', "0% määraga maksustatavad toimingud ja tehingud, sh") -mfld("31", CREDIT, '02', +mfld("31", CREDIT, '10', "1) kauba ühendusesisene käive ja teise liikmesriigi maksukohustuslasele / " "piiratud maksukohustuslasele osutatud teenuste käive kokku, sh", + vat_regimes="intracom cocontractor") +mfld("311", CREDIT, '10', "1) kauba ühendusesisene käive", vat_regimes="intracom") -mfld("311", CREDIT, '02', "kauba ühendusesisene käive", vat_regimes="intracom") -mfld("32", CREDIT, '02', "2) kauba eksport, sh", vat_regimes="!intracom") -mfld("321", CREDIT, '02', "käibemaksutagastusega müük reisijale", vat_regimes="!intracom") -mfld("4", CREDIT, '40', "Käibemaks kokku (20% lahtrist 1 + 9% lahtrist 2)") -mfld("41", CREDIT, '41', "Impordilt tasumisele kuuluv käibemaks") -mfld("5", CREDIT, '50', "Kokku sisendkäibemaksusumma, mis on seadusega lubatud maha arvata, sh") -mfld("51", CREDIT, '51', "1) impordilt tasutud või tasumisele kuuluv käibemaks") -mfld("52", CREDIT, '52', "2) põhivara soetamiselt tasutud või tasumisele kuuluv käibemaks") -mfld("53", CREDIT, '53', + +mfld("32", CREDIT, '10', "2) kauba eksport, sh", + vat_regimes="tax_free exempt") +mfld("321", CREDIT, '10', "1) käibemaksutagastusega müük reisijale", + vat_regimes="tax_free") + +mfld("4", CREDIT, '40', + "Käibemaks kokku (20% lahtrist 1 + 9% lahtrist 2)") +mfld("41", CREDIT, '41', + "Impordilt tasumisele kuuluv käibemaks") + +mfld("5", CREDIT, '50', + "Kokku sisendkäibemaksusumma, mis on seadusega lubatud maha arvata, sh") +mfld("51", CREDIT, '50', + "1) impordilt tasutud või tasumisele kuuluv käibemaks", + vat_regimes="intracom") +mfld("52", CREDIT, '50', + "2) põhivara soetamiselt tasutud või tasumisele kuuluv käibemaks", + vat_classes="real_estate") +mfld("53", CREDIT, '50', "3) ettevõtluses (100%) kasutatava sõiduauto soetamiselt ja sellise" "sõiduauto tarbeks kaupade soetamiselt ja teenuste saamiselt" - "tasutud või tasumisele kuuluv käibemaks") -mfld("54", CREDIT, '54', + "tasutud või tasumisele kuuluv käibemaks", + vat_classes="vehicles") +mfld("54", CREDIT, '50', "4) osaliselt ettevõtluses kasutatava sõiduauto soetamiselt ja sellise" "sõiduauto tarbeks kaupade soetamiselt ja teenuste saamiselt" - "tasutud või tasumisele kuuluv käibemaks") - -mfld("6", CREDIT, '52', "Kauba ühendusesisene soetamine ja teise liikmesriigi maksukohustuslaselt saadud teenused kokku, sh") -mfld("61", CREDIT, '52', "1) kauba ühendusesisene soetamine") -mfld("7", CREDIT, '52', "Muu kauba soetamine ja teenuse saamine, mida maksustatakse käibemaksuga, sh") -mfld("71", CREDIT, '52', "1) erikorra alusel maksustatava kinnisasja, metallijäätmete, väärismetallija metalltoodete soetamine (KMS § 41¹)") - -mfld("8", CREDIT, '52', "Maksuvaba käive") -mfld("9", CREDIT, '52', + "tasutud või tasumisele kuuluv käibemaks", + vat_classes="vehicles") + +mfld("6", DEBIT, '60', + "Kauba ühendusesisene soetamine ja teise liikmesriigi " + "maksukohustuslaselt saadud teenused kokku, sh") +mfld("61", DEBIT, '60', "1) kauba ühendusesisene soetamine", + vat_regimes="intracom", vat_classes="goods") + +mfld("7", DEBIT, '60', + "Muu kauba soetamine ja teenuse saamine, mida maksustatakse käibemaksuga, sh", + vat_regimes="!intracom", vat_classes="!goods") +mfld("71", DEBIT, '60', + "1) erikorra alusel maksustatava kinnisasja, metallijäätmete, väärismetalli " + "ja metalltoodete soetamine (KMS § 41¹)", + vat_regimes="!intracom", vat_classes="!goods") # not yet handled + +mfld("8", DEBIT, '60', "Maksuvaba käive", vat_classes="exempt") +mfld("9", DEBIT, '61', "Erikorra alusel maksustatava kinnisasja, metallijäätmete, väärismetalli ja " - "metalltoodetekäive (KMS § 411) ning teises liikmesriigis paigaldatava või " + "metalltoodete käive (KMS § 411) ning teises liikmesriigis paigaldatava või " "kokkupandava kauba maksustatav väärtus") -wfld("10", CREDIT, None, "Täpsustused -", is_payable=True) -wfld("11", DEBIT, None, "Täpsustused +", is_payable=True) +wfld("10", CREDIT, None, "Täpsustused -", editable=True) +wfld("11", DEBIT, None, "Täpsustused +", editable=True) + sfld("12", DEBIT, None, "Tasumisele kuuluv käibemaks (lahter 4 + lahter 41 - lahter 5 + " - "lahter 10 - lahter 11)", is_payable=True) + "lahter 10 - lahter 11)", is_payable=True, fieldnames="4 41 5 10 11", both_dc=False) sfld("13", CREDIT, None, "Enammakstud käibemaks (lahter 4 + lahter 41 - lahter 5 + " - "lahter 10 - lahter 11)", is_payable=True) + "lahter 10 - lahter 11)", is_payable=True, fieldnames="4 41 5 10 11", both_dc=False) diff --git a/lino_xl/lib/eevat/desktop.py b/lino_xl/lib/eevat/desktop.py index dc9d629e..52108cb5 100644 --- a/lino_xl/lib/eevat/desktop.py +++ b/lino_xl/lib/eevat/desktop.py @@ -25,7 +25,7 @@ class VouchersByDeclaration(ledger.Vouchers): # required_roles = set([1]) class DeclarationDetail(dd.DetailLayout): - main = "info values" + main = "info values vat.MovementsByDeclaration" info = dd.Panel(""" start_period end_period entry_date accounting_period diff --git a/lino_xl/lib/ledger/choicelists.py b/lino_xl/lib/ledger/choicelists.py index 75e9a2b8..abf9d712 100644 --- a/lino_xl/lib/ledger/choicelists.py +++ b/lino_xl/lib/ledger/choicelists.py @@ -127,18 +127,19 @@ def clearable(cls, choice, ar): add = CommonAccounts.add_item add('1000', _("Net income (loss)"), 'net_income_loss', True) + add('4000', _("Customers"), 'customers', True) +add('4100', _("Suppliers"), 'suppliers', True) +add('4200', _("Employees"), 'employees', True) add('4300', _("Pending Payment Orders"), 'pending_po', True) -add('4400', _("Suppliers"), 'suppliers', True) -add('4500', _("Employees"), 'employees', True) -add('4550', _("Internal clearings"), 'clearings', True) -add('4600', _("Tax Offices"), 'tax_offices', True) +add('4500', _("Tax Offices"), 'tax_offices', True) add('4510', _("VAT due"), 'vat_due', False) -add('4511', _("VAT returnable"), 'vat_returnable', False) -add('4512', _("VAT deductible"), 'vat_deductible', False) +add('4520', _("VAT deductible"), 'vat_deductible', False) +add('4530', _("VAT returnable"), 'vat_returnable', False) add('4513', _("VAT declared"), 'due_taxes', False) +add('4800', _("Internal clearings"), 'clearings', True) add('4900', _("Waiting account"), 'waiting', True) add('5500', _("BestBank"), 'best_bank', False) diff --git a/lino_xl/lib/ledger/fixtures/demo_bookings.py b/lino_xl/lib/ledger/fixtures/demo_bookings.py index e2f9ce7c..e6a8d754 100644 --- a/lino_xl/lib/ledger/fixtures/demo_bookings.py +++ b/lino_xl/lib/ledger/fixtures/demo_bookings.py @@ -20,7 +20,7 @@ REQUEST = settings.SITE.login() # BaseRequest() MORE_THAN_A_MONTH = datetime.timedelta(days=40) -from lino_xl.lib.vat.choicelists import VatAreas, VatRules +from lino_xl.lib.vat.choicelists import VatAreas, VatRules, VatClasses from lino_xl.lib.ledger.choicelists import TradeTypes def objects(): @@ -89,6 +89,7 @@ def func(): # print(20151216, START_YEAR, settings.SITE.demo_date(), end_date - date) PAYMENT_TERMS = Cycler(PaymentTerm.objects.all()) + VAT_CLASSES = Cycler(VatClasses.get_list_items()) if len(PAYMENT_TERMS) == 0: raise Exception("No PAYMENT_TERMS.") @@ -120,6 +121,7 @@ def func(): (amount * INFLATION_RATE * (date.year - START_YEAR)) item = model(voucher=invoice, account=account, + vat_class=VAT_CLASSES.pop(), total_incl=myround(amount) + AMOUNT_DELTAS.pop(), **kwargs) try: diff --git a/lino_xl/lib/ledger/ui.py b/lino_xl/lib/ledger/ui.py index bb982a17..ec15e279 100644 --- a/lino_xl/lib/ledger/ui.py +++ b/lino_xl/lib/ledger/ui.py @@ -1007,7 +1007,7 @@ class MovementsByVoucher(Movements): See also :class:`lino_xl.lib.ledger.models.Movement`. """ master_key = 'voucher' - column_names = 'account project partner debit credit match_link cleared *' + column_names = 'account project partner debit credit vat_class match_link cleared *' sum_text_column = 3 # auto_fit_column_widths = True display_mode = "html" diff --git a/lino_xl/lib/products/fixtures/furniture.py b/lino_xl/lib/products/fixtures/furniture.py index 4e731e96..018e338e 100644 --- a/lino_xl/lib/products/fixtures/furniture.py +++ b/lino_xl/lib/products/fixtures/furniture.py @@ -1,13 +1,11 @@ # -*- coding: UTF-8 -*- -# Copyright 2009-2014 Rumma & Ko Ltd -# +# Copyright 2009-2019 Rumma & Ko Ltd # License: BSD (see file COPYING for details) -from __future__ import unicode_literals - from lino.utils.instantiator import Instantiator +from lino_xl.lib.products.choicelists import ProductTypes -from lino.api import dd +from lino.api import dd, _ def objects(): @@ -16,13 +14,13 @@ def objects(): product = Instantiator('products.Product', "sales_price cat").build furniture = productcat( - id=1, **dd.babel_values( + id=1, product_type=ProductTypes.default, **dd.babel_values( 'name', en="Furniture", et="Mööbel", de="Möbel", fr="Meubles")) yield furniture # print "foo", furniture.id, furniture hosting = productcat( - id=2, **dd.babel_values( + id=2, product_type=ProductTypes.default, **dd.babel_values( 'name', en="Website Hosting", et="Veebimajutus", @@ -30,6 +28,9 @@ def objects(): fr="Hébergement de sites Internet")) yield hosting + other = productcat(id=3, **dd.str2kw('name', _("Other"))) + yield other + kw = dd.babel_values('name', en="Wooden table", et=u"Laud puidust", @@ -107,3 +108,6 @@ def objects(): et="Pilditöötlus ja kodulehtede sisuhaldustööd", de="Bildbearbeitung und Unterhalt Website", fr="Traitement d'images et maintenance site existant")) + + yield product("29.90", 3, **dd.str2kw('name', _("Book"), vat_class="reduced")) + yield product("1.40", 3, **dd.str2kw('name', _("Stamp"), vat_class="exempt")) diff --git a/lino_xl/lib/products/models.py b/lino_xl/lib/products/models.py index 9dcb7e59..2ee33bee 100644 --- a/lino_xl/lib/products/models.py +++ b/lino_xl/lib/products/models.py @@ -59,7 +59,6 @@ class Meta: delivery_unit = DeliveryUnits.field(default='piece') product_type = ProductTypes.field() - vat_class = VatClasses.field(blank=True) @dd.chooser() @@ -109,6 +108,7 @@ def get_rule_fee(cls, partner, event_type): return rule.fee def full_clean(self): + # print("20191210", self.name, self.vat_class) if self.product_type is None: if self.cat_id: self.product_type = self.cat.product_type or ProductTypes.default diff --git a/lino_xl/lib/sales/fixtures/demo_bookings.py b/lino_xl/lib/sales/fixtures/demo_bookings.py index be56e24b..89f643f4 100644 --- a/lino_xl/lib/sales/fixtures/demo_bookings.py +++ b/lino_xl/lib/sales/fixtures/demo_bookings.py @@ -44,11 +44,10 @@ def get_trade_countries(tt): USERS = Cycler(settings.SITE.user_model.objects.all()) - qs = Product.objects.order_by('id') # if dd.is_installed('invoicing'): if not dd.plugins.ledger.sales_stories: return - PRODUCTS = Cycler(qs) + PRODUCTS = Cycler(Product.objects.order_by('id')) JOURNAL_S = Journal.objects.get(ref="SLS") @@ -67,7 +66,7 @@ def get_trade_countries(tt): if len(CUSTOMERS) == 0: raise Exception("20171006 no customers ({})".format( len(list(get_trade_countries(TradeTypes.sales))))) - + # CUSTOMERS = Cycler(Person.objects.filter( # gender=dd.Genders.male).order_by('id')) # assert Person.objects.count() > 0 diff --git a/lino_xl/lib/sales/mixins.py b/lino_xl/lib/sales/mixins.py index 064c7587..efa7fb9a 100644 --- a/lino_xl/lib/sales/mixins.py +++ b/lino_xl/lib/sales/mixins.py @@ -88,6 +88,11 @@ def get_base_account(self, tt): return tt.get_product_base_account(self.product) # return self.voucher.journal.chart.get_account_by_ref(ref) + def get_default_vat_class(self, tt): + if self.product and self.product.vat_class: + return self.product.vat_class + return super(ProductDocItem, self).get_default_vat_class(tt) + def discount_changed(self, ar=None): if not self.product: return @@ -103,7 +108,7 @@ def discount_changed(self, ar=None): return va = VatAreas.get_for_country() cat_rule = VatRules.get_vat_rule( - va, tt, get_default_vat_regime(), self.get_vat_class(tt), + va, tt, get_default_vat_regime(), self.vat_class, dd.today()) if cat_rule is None: return diff --git a/lino_xl/lib/vat/__init__.py b/lino_xl/lib/vat/__init__.py index 9c27a748..b609778a 100644 --- a/lino_xl/lib/vat/__init__.py +++ b/lino_xl/lib/vat/__init__.py @@ -59,7 +59,7 @@ class Plugin(ad.Plugin): """ - default_vat_class = 'normal' + default_vat_class = 'services' """The default VAT class. If this is specified as a string, Lino will resolve it at startup into an item of :class:`VatClasses `. diff --git a/lino_xl/lib/vat/choicelists.py b/lino_xl/lib/vat/choicelists.py index f51cb7fe..a418fefc 100644 --- a/lino_xl/lib/vat/choicelists.py +++ b/lino_xl/lib/vat/choicelists.py @@ -22,9 +22,13 @@ class VatClasses(dd.ChoiceList): required_roles = dd.login_required(LedgerStaff) add = VatClasses.add_item -add('0', _("Exempt from VAT"), 'exempt') # post stamps, ... -add('1', _("Reduced VAT rate"), 'reduced') # food, books,... -add('2', _("Normal VAT rate"), 'normal') # everything else +add('010', _("Goods at normal VAT rate"), 'goods') # everything else +add('020', _("Goods at reduced VAT rate"), 'reduced') # food, books,... +add('030', _("Goods exempt from VAT"), 'exempt') # post stamps, ... +add('100', _("Services"), 'services') +add('200', _("Investments"), 'investments') +add('210', _("Real estate"), 'real_estate') +add('220', _("Vehicles"), 'vehicles') @@ -119,7 +123,7 @@ def needs_vat_id(cls, regime, ar): # re-populated in bevat and bevats. # See also lino_xl.lib.vat.Plugin.default_vat_regime -# +# class DeclarationField(dd.Choice): editable = False vat_regimes = None @@ -129,7 +133,7 @@ class DeclarationField(dd.Choice): vat_columns = None exclude_vat_columns = None is_payable = False - + # value dc vat_columns text fieldnames both_dc vat_regimes vat_classes def __init__(self, value, dc, vat_columns=None, # is_base, @@ -374,7 +378,6 @@ def x(label, lst, xlst): class VatRule(dd.Choice): - start_date = None end_date= None vat_area = None diff --git a/lino_xl/lib/vat/desktop.py b/lino_xl/lib/vat/desktop.py index c57a27de..cc32447a 100644 --- a/lino_xl/lib/vat/desktop.py +++ b/lino_xl/lib/vat/desktop.py @@ -1,17 +1,13 @@ # Copyright 2012-2019 Rumma & Ko Ltd # License: BSD (see file COPYING for details) - -from __future__ import unicode_literals -from __future__ import print_function - from lino.api import dd, rt, _ # from etgen.html import E +# from django.db.models import Q -from .mixins import VatDocument, VatVoucher -from lino_xl.lib.ledger.ui import PartnerVouchers, ByJournal, PrintableByJournal +from lino_xl.lib.ledger.ui import PartnerVouchers, ByJournal, PrintableByJournal, Movements from lino_xl.lib.ledger.choicelists import TradeTypes from lino_xl.lib.ledger.choicelists import VoucherTypes from lino_xl.lib.ledger.roles import LedgerUser, LedgerStaff @@ -19,7 +15,7 @@ from lino_xl.lib.ledger.mixins import VouchersByPartnerBase from .choicelists import VatRegimes, VatAreas -from .mixins import VatDeclaration +from .mixins import VatDeclaration, VatDocument, VatVoucher # class VatRules(dd.Table): @@ -170,6 +166,13 @@ def param_defaults(self, ar, **kw): # print("20191205", kw) return kw +class MovementsByDeclaration(ByDeclaration, Movements): + label = _("Declared movements") + master = VatDeclaration + exclude = dict(vat_class="") + column_names = "value_date voucher_link description debit credit vat_class vat_regime *" + + class SalesByDeclaration(ByDeclaration, VatInvoices): _trade_type = TradeTypes.sales diff --git a/lino_xl/lib/vat/mixins.py b/lino_xl/lib/vat/mixins.py index 7eeb4c23..c60ed935 100644 --- a/lino_xl/lib/vat/mixins.py +++ b/lino_xl/lib/vat/mixins.py @@ -52,8 +52,8 @@ def get_default_vat_regime(): return dd.plugins.vat.default_vat_regime -def get_default_vat_class(): - return dd.plugins.vat.default_vat_class +# def get_default_vat_class(): +# return dd.plugins.vat.default_vat_class class VatTotal(dd.Model): @@ -325,7 +325,7 @@ class VatItemBase(VoucherItem, VatTotal): class Meta: abstract = True - vat_class = VatClasses.field(blank=True, default=get_default_vat_class) + vat_class = VatClasses.field(blank=True) # , default=get_default_vat_class) def delete(self, **kw): super(VatItemBase, self).delete(**kw) @@ -338,7 +338,7 @@ def delete(self, **kw): def get_trade_type(self): return self.voucher.get_trade_type() - def get_vat_class(self, tt): + def get_default_vat_class(self, tt): acc = self.get_base_account(tt) if acc and acc.vat_class: return acc.vat_class @@ -356,7 +356,7 @@ def get_base_account(self, tt): def get_vat_rule(self, tt): if self.vat_class is None: - self.vat_class = self.get_vat_class(tt) + self.vat_class = self.get_default_vat_class(tt) # we store it because there might come more calls, but we # don't save it because here's not the place to decide # this. @@ -406,6 +406,11 @@ def reset_totals(self, ar): self.total_incl_changed(ar) super(VatItemBase, self).reset_totals(ar) + def full_clean(self): + if self.vat_class is None: + self.vat_class = self.get_default_vat_class(self.get_trade_type()) + super(VatItemBase, self).full_clean() + def before_ui_save(self, ar): if self.total_incl is None: self.reset_totals(ar) @@ -590,3 +595,10 @@ def get_payable_sums_dict(self): # self.full_clean() # self.save() return payable_sums + + def print_declared_values(self): + # used in doctests + for fld in self.fields_list.get_list_items(): + v = getattr(self, fld.name) + if v: + print("[{}] {} : {}".format(fld.value, fld.help_text, v)) diff --git a/lino_xl/lib/vat/models.py b/lino_xl/lib/vat/models.py index 3e1cc4c9..f6b11c92 100644 --- a/lino_xl/lib/vat/models.py +++ b/lino_xl/lib/vat/models.py @@ -102,12 +102,6 @@ def partner_vat_regime_choices(cls, country): class VatColumnsChecker(Checker): # model = 'system.SiteConfig' - """ - This is an unbound data checker - (:attr:`lino.modlib.checkdata.Checker.model` is `None`), i.e. the checker - is unbound, i.e. the problem messages aren't bound to a particular - database object. - """ verbose_name = _("Check VAT columns configuration.")