Manage service plans and the associated Odoo product information #264
Labels
No labels
API
Billing
UI/UX
dependencies
bug
change
duplicate
enhancement
help wanted
invalid
question
wontfix
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: servala/servala-portal#264
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Stories
As a user, I want to select a plan when ordering or changing a service instance.
Implementation Notes
Context
Servala service pricing depends on compute and storage plans. The plan influences the service configuration and pricing.
Example: https://servala.com/offering/cloudscale/forgejo/#plans
We need to track these plans in the Servala portal databases, offer them to the user in the service configuration form, and configure the service instance according to the chosen plan.
Plans are specific to the service and the control plane. For this initial iteration, we assign service plans in the
ControlPlaneCRDmodel and offer the associated plans to the user. In a later iteration, we might want to offer plans also in other combinations, for example, a plan that is only available for a specific "Organization+ControlPlaneCRD" combination.Compute Plans
Storage plans
As they are currently hardcoded per control-plan, add two new field to the control-plane:
Products for Services
A product (usually a product variant) in Odoo represents a service with a specific compute plan, a control-plane and a service level (SLA). Therefore, it makes the most sense to store this correlation in the
ControlPlaneCRDmodel.In this model, we should be able to choose from the available compute plans (one or many), and for each chosen compute plan configure:
This also means a compute plane can be added multiple times, but with differing SLA and pricing.
Make the SLA a text choice field with the choices of "Best Effort" and "Guaranteed Availability".
The field "Minimum service size" will be later used to set the minimum of the field
spec.parameters.instances, because the service level "Guaranteed Availability" can set some constraints on this configuration.Service instance creation
When creating or editing a service instance, allow the user to choose a compute plan and an available SLA per the chosen compute plan. Based on this choice:
spec.parameters.sizeto the configuration in the compute plan:spec.parameters.size.memory: Memory limitsspec.parameters.size.requests.memory: RAM requestsspec.parameters.size.cpu: vCPU limitsspec.parameters.size.requests.cpu: vCPU requestsservala.com/erp_product_id_resource:$ControlPlaneCRD.compute_plan.reporting_product_idservala.com/erp_unit_id_resource:$ControlPlaneCRD.compute_plan.unit_idspec.parameters.service.serviceLevel:besteffortorguaranteedIn the frontend, show the details to the user:
Storage plans
Storage plans are hardcoded at the control plane and can't be chosen by the user at this time. Set the instance annotations from the data in the control plane configuration.
servala.com/erp_product_id_storage = $StoragePlan.reporting_product_idservala.com/erp_unit_id_storage = $StoragePlan.unit_idIn the frontend, show the plan details to the user: storage price multiplied with the configured size.
Manage service plans and the associated ERP productsto Manage service plans and the associated Odoo product informationSome questions to aid with the data modeling:
Thanks to these questions, I found a fundamental flaw in the initial description I made: plans have nothing to do with products in Odoo. The connection to the product happens in a different place, see updated description.
Also, I decided to not yet connect to Odoo to query for data; let's do that in a follow-up issue when we finish this one (to not do too much at the same time).
Let's also track this in the Servala portal database, not only in the control-plane
Yes
rixx referenced this issue2025-11-25 12:58:23 +00:00
I have left my changes between the first version of this issue and the seconf version in place in my PR, for reference to see what changed according to my understanding. I have some more questions to go along with the data model:
It's the same. In the first version I wanted to overcomplicate things and store the "real" Odoo ID, but now we're using the reporting ID which we also set on the annotations. There's no need to look up things right now in Odoo. Just use the string added to the database. Oh, I see that the Odoo IDs are added as integer, they are actually strings. I forgot to mention this. Such a string can look like this:
vshn_event_billing.uom_instance_houroropenshift-exoscale-workervcpu-standard.As it is now, per record in the
controlplanemodel. It's correct as it is right now.This should be handled by the backend. We can just switch the plan in an instance via the annotations; the Kubernetes controller responsible for that will then handle this case and send an appropriate event to Odoo. Odoo then knows what to do.
We should also add a field "unit" to the "computeplanassignment" model, to communicate to the user what the price is for. For example, a service may cost CHF 42.00 per month or CHF 0.42 per hour. Let's make this a selection field, but it doesn't warrant a relation. Maybe a hardcoded list would be enough, which we can enhance should the need arise. For now, these units should be available: "hour", "day". "month (30 days / 720 hours)", "year".
I have a couple of questions UI-wise:
If we aim to cover the change/updating of chosen plans immediately, the same questions apply for the instance update form.
We don't allow the creation of such a service instance because plans are crucial for billing. I would even go so far as to not allow the user to get to the point of being able to create an instance.
We show them, but make them read-only.