Datenbank #1140

Updated by Alexander Blum about 1 year ago

# Background

- `Invoice.amount/shared_amount` are only helper attributes for testing the invoicing, should be replaced by
`UtilisationIndicators.invoice_amount` = `UtilizationIndicators.administration_fee` + `UtilizationIndicators.distribution_amount`
- relationship see also [database diagram](https://redmine.c3s.cc/projects/collecting_society/wiki/Databasemodels#Invoicing)

# Procedure

1. Write a [wizard](https://github.com/C3S/collecting_society/blob/development/collecting_society.py#L829) to trigger the allocation process
- can be triggered by
- cron job
- manual [action](https://github.com/C3S/collecting_society/blob/development/collecting_society.xml#L800)
- in Declaration Menu (action in entry view or on [selected](https://github.com/C3S/collecting_society/blob/development/collecting_society.py#L3973) items in list view)
- in Utilization Menu (action in entry view or on [selected](https://github.com/C3S/collecting_society/blob/development/collecting_society.py#L3973) items in list view)
- confirm screen (like in [fingerprint_merge](https://github.com/C3S/collecting_society/blob/development/collecting_society.py#L4194), maybe a tree list with declarations -> utilisations
- list of definitly selected utilisations/declarations
- info on deselection of non suitable utilisations/declarations
-
creates allocations with all corresponding utilizations connected, connected (all declaration.utilisations or selected ones; one allocation for each licensee licensee)
- loops over different sets of declarations depending on where/how the action was triggered:
- declarations list
with no selection: selection, it should iterate over all suitable complete declarations with suitable utilisations (default for the cron job e.g. each day)
- declarations list with selection: all suitable declaration.utilisations for each selected suitable declaration
- declaration entry: all suitable declaration.utilisations for this declaration (if suitable)
- utilisations list with no selection: all suitable selected utilisations
- utilisations list with selection: all suitable utilisations in list
- utilisation entry: this utilisation (if suitable)
ready to allocate
- ensure, that non complete utilisation datasets for manual tests are still available
2. Write a dataset [triggering](https://github.com/C3S/collecting_society_docker/blob/development/volumes/shared/data/datasets/device_message_fingerprint_merge.py#L29) the wizard for some Declarations
3. Implement the Tariff `formula` from [database diagram](https://redmine.c3s.cc/projects/collecting_society/wiki/Databasemodels#Invoicing)
- each formula should be one **class** method, so that parametrized calling is possible: tariff system version, tariff code
4. Implement the TariffSystem `formula` from [database diagram](https://redmine.c3s.cc/projects/collecting_society/wiki/Databasemodels#Invoicing)
- each formula should be one **class** method, so that parametrized calling is possible: tariff system version
5. Implement the **instance** methods (sample = indicator set, maybe also 'all' to calculate all indicator sets; update = write or just calculate)
- `Allocation.calculate_invoice_amount(self, sample, update=False)`

invoice_amount = 0
distribution_amount = 0
administration_fee = 0
for utilisation self.utilisations:
ia, da, af = utilisation.calculate_invoice_amount(sample, update)
invoice_amount += ia
distribution_amount += da
administration_fee += af
return invoice_amount, distribution_amount, administration_fee
- `Utilisation.calculate_invoice_amount(self, sample, update=False)`

utilisation = self
invoice_amount = self.tariff.calculate_invoice_amount(utilisation, sample, update)
return invoice_amount, distribution_amount, admnistration_fee
- `Tariff.calculate_invoice_amount(self, utilisation, sample, update=False)`

utilisation_indicator = ...

tariff_system_version = self.tariff_system.version
tariff_code = self.code

indication1 = utilization.estimated_stuff
indication2 = utilization.estimated_otherstuff

formula = getattr(self, <parametrized_tariff_system_version_and_tariff_code_formula_function>)

base, relevance, adjustments = formula(indicator1, indicator2):
if update:
utilisation_indicator.save()
return (base, relevace, adjustments)

invoice_amount, distribution_amount, admnistration_fee = \
tariff_system.calculate_invoice_amount(base, relevance, adjustments)
if update:
utilisation_indicator.invoice_amount = invoice_amount
utilisation_indicator.invoice_amount.save()
return invoice_amount, distribution_amount, administration_fee
- `TariffSystem.calculate_invoice_amount(self, base, relevance, adjustments)`

version = self.version
formula = getattr(self, <parametrized_version_formula_function>)
invoice_amount = formula(base, relevance, adjustments)
distribution_amount = invoice_amount * self.administration_share
administration_fee = invoice_amount - distribution_amount
# check if results add up
return invoice_amount, distribution_amount, administration_fee

6. Implement the same for `calculate_utilisation_indicators()`, maybe reuse in `calculate_invoice_amount()`
- `Utilisation.calculate_utilisation_indicators(self, sample, update)`
- `Tariff.calculate_utilisation_indicators(self, utilisation, sample, update)`
7. Implement a wizard to recalculate invoice amounts / utilsation indicators
8. Check the wizard to write invoices ([exists](https://github.com/C3S/collecting_society/blob/development/collecting_society.py#L829) already)
9. Write datasets to trigger the invoice action for the Allocations
- ensure, that some allocations are still left to invoice for manual tests

Back