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)
- creates allocations with all corresponding utilizations connected (all declaration.utilisations or selected ones; one allocation for each licensee)
- with no selection, it should iterate over all complete declarations with utilisations 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)`?

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

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

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_tarrif_system_version_and_tarrif_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)` `TariffSystem.calculate_invoice_amount()`

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