Datenbank #1140
Finish allocation processes
Status: | Neu | Start date: | 03/03/2023 | ||
---|---|---|---|---|---|
Priority: | Normal | Due date: | 03/12/2023 | ||
Assignee: | Thomas Mielke | % Done: | 10% | ||
Category: | - | Estimated time: | 80.00 h | ||
Target version: | - | Spent time: | 10.00 h |
Description
Background¶
Invoice.amount/shared_amount
are only helper attributes for testing the invoicing, should be replaced byUtilisationIndicators.invoice_amount
=UtilizationIndicators.administration_fee
+UtilizationIndicators.distribution_amount
- relationship see also database diagram
use
erpserver> db-console
for a tryton console to test the functions; maybe write a script with some objects initialized and import it there>>> Tariff = pool.get('tariff_system.tariff') >>> tariff = Tariff(1)
Procedure¶
- Write a wizard to trigger the allocation process
- can be triggered by
- cron job
- manual action
- in Declaration Menu (action in entry view or on selected items in list view)
- in Utilization Menu (action in entry view or on selected items in list view). Maybe we could skip that, but probable it's a valid usecase, like:
- if some utilization (tariff bound!) of a declaration should be payed for and some other has issues to be resolved first
- or a multi day festival event and the utilisations should be split.
- creates allocations with all corresponding utilisations connected, one allocation for each licensee
- loops over different sets of declarations depending on where/how the action was triggered (algorithm should be generic, see next point confirm screen how this is done; not sure, how to handle the same action with different selections though, all other things should be similiar to the existing example):
- declarations list with no selection: all suitable 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)
- confirm screen (like in fingerprint_merge, maybe a tree list with declarations -> utilisations)
- list of definitely selected utilisations/declarations
- info on deselection of non suitable utilisations/declarations
- can be triggered by
- Write a dataset triggering the wizard for some Declarations
- ensure, that non complete utilisation datasets for manual tests are still available
Implement the Tariff and TariffSystem
formula
s from database diagram- fomulas should have the exact same plain value parameters as stated in the tariff system (check the latest version), so that parametrized calling is possible via
formula = getattr(tariff, 'method_name')
. they should not receive some tryton object, so they can be used (and tested) standalone each formula should be one static method
TariffSystem parameters: tariff system version (dot replaced with underscore); like
@staticmethod def formula_<tariffsystemversion>(...): [...] return invoice_amount
Tariff parameters: tariff code (includes version already, dot replaced with underscore); one for each tariff; like
@staticmethod def formula_<tariffcode>(...): [...] return base, relevance, adjustments
maybe better change the tariff_system.version.code, that it is save to use as function names in general and omit the replacements here
add an instance method, to be able to easily fetch the corresponding formula from an instance
TariffSystem
def get_formula(self): return getattr(self, f"formula_{self.version.replace(',', '_')}")
Tariff
def get_formula(self): return getattr(self, f"formula_{self.code.replace(',', '_')}")
- fomulas should have the exact same plain value parameters as stated in the tariff system (check the latest version), so that parametrized calling is possible via
Implement the instance methods
- params:
- sample: indicator set
- e.g. 'estimated', 'confirmed', might depend on tariff
- maybe also 'all' to calculate all indicator sets, but then the return value has to be e.g. a dict with sample name as key and the tuple
(base, relevance, adjustments)
as value
- update: write or just calculate the results
- sample: indicator set
- maybe rename
calculate_invoice_amount
, as all values are returned, or maybe better split invoice amount calculation (only invoice_amount returned) from calculating the distribution_amount and administration_fee (but not sure if this is needed by some other process) Allocation.calculate_invoice_amount(self, sample, update=False)
invoice_amount_sum = 0 distribution_amount_sum = 0 administration_fee_sum = 0 for utilisation self.utilisations: invoice_amount, distribution_amount, administration_fee = \ utilisation.calculate_invoice_amount(sample, update) invoice_amount_sum += invoice_amount distribution_amount_sum += distribution_amount administration_fee_sum += administration_fee 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)
formula = self.get_formula() context_indicators = getattr(utilisation.context, f'{sample}_indicators') # generic way to get all and only indicators needed for all different formulas import inspect # place import on top of file formula_indicators = { field: getattr(context_indicators, field) for field in inspect.signature(formula).parameters } base, relevance, adjustments = formula(**formula_indicators): invoice_amount, distribution_amount, administration_fee = \ tariff_system.calculate_invoice_amount(base, relevance, adjustments) if update: utilisation_indicators = getattr(utilisation, f'{sample}_indicators') utilisation_indicators.base = base utilisation_indicators.relevance = relevance utilisation_indicators.adjustments = adjustments utilisation_indicators.invoice_amount = invoice_amount utilisation_indicators.distribution_amount = distribution_amount utilisation_indicators.administration_fee = administration_fee utilisation_indicators.save() return invoice_amount, distribution_amount, administration_fee
TariffSystem.calculate_invoice_amount(self, base, relevance, adjustments)
formula = self.get_formula() 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
- params:
Implement the same for
calculate_utilisation_indicators()
, maybe reuse incalculate_invoice_amount()
Utilisation.calculate_utilisation_indicators(self, sample, update)
Tariff.calculate_utilisation_indicators(self, utilisation, sample, update)
- best case: each formula o node with a custom method to use, and one method to integrate all of them (e.g. another
calculate_invoice_split()
function)
Implement a wizard to recalculate invoice amounts / utilsation indicators (prevent, if invoice is already issued)
Check the wizard to write invoices (exists already)
Write datasets to trigger the invoice action for the Allocations
- ensure, that some allocations are still left to invoice for manual tests
Associated revisions
added wizard for allocation; ref #1140
renamed wizard 'allocate' to 'collect'; ref #1140
old wizard name: Allocate/utilisation.allocate new: Collect/utilisation.allocation.collect
old ModelView name: AllocateStart/utilisation.allocate.start new: CollectStart/utilisation.allocation.collect.start
History
#1 Updated by Alexander Blum 3 months ago
- Description updated (diff)
#2 Updated by Alexander Blum 3 months ago
- Description updated (diff)
#3 Updated by Alexander Blum 3 months ago
- Description updated (diff)
#4 Updated by Alexander Blum 3 months ago
- Description updated (diff)
#5 Updated by Alexander Blum 3 months ago
- Description updated (diff)
#6 Updated by Alexander Blum 3 months ago
- Description updated (diff)
#7 Updated by Alexander Blum 3 months ago
- Description updated (diff)
#8 Updated by Alexander Blum 3 months ago
For the development of the functions, the tryton console will be your friend:
$ docker compose run --rm --service-ports erpserver bash > db-console
#9 Updated by Alexander Blum 3 months ago
- Description updated (diff)
#10 Updated by Alexander Blum 3 months ago
- Description updated (diff)
#11 Updated by Alexander Blum 3 months ago
- Description updated (diff)
#12 Updated by Alexander Blum 3 months ago
- Description updated (diff)
#13 Updated by Alexander Blum 3 months ago
- Description updated (diff)
#14 Updated by Alexander Blum 3 months ago
- Description updated (diff)
#15 Updated by Alexander Blum 3 months ago
- Description updated (diff)
#16 Updated by Alexander Blum 3 months ago
- Description updated (diff)
#17 Updated by Alexander Blum 3 months ago
- Description updated (diff)
#18 Updated by Alexander Blum 3 months ago
- Description updated (diff)
#19 Updated by Alexander Blum 3 months ago
- Description updated (diff)
#20 Updated by Alexander Blum 3 months ago
- Description updated (diff)
#21 Updated by Alexander Blum 3 months ago
- Description updated (diff)
#22 Updated by Alexander Blum 3 months ago
- Description updated (diff)
#23 Updated by Thomas Mielke 3 months ago
- Due date set to 03/12/2023
- Start date set to 03/03/2023
- Estimated time set to 80.00
#24 Updated by Thomas Mielke 3 months ago
what do you mean by "dot replaced with underscore"?
#25 Updated by Alexander Blum 3 months ago
in our demo data the tariff_system.code is e.g. "1.0". dots are not allowed in method names, so instead of "formula_1.0()" sanitize the name to "formula_1_0()". same with tariff code, which is just "self.code + self.tariff_system.code". or restrict tariff_system.code and tariff.code to contain only chars allowed in function names.
#26 Updated by Alexander Blum 3 months ago
- Description updated (diff)
#27 Updated by Alexander Blum 3 months ago
- Description updated (diff)
#28 Updated by Thomas Mielke 3 months ago
- % Done changed from 0 to 10