-
Notifications
You must be signed in to change notification settings - Fork 46
[WIP] Create metric and billing interface outline #173
[WIP] Create metric and billing interface outline #173
Conversation
invoice_policy = fields.Selection( | ||
selection_add=[ | ||
('threshold', 'Invoice and Enforce a Threshold'), | ||
('usage', 'Invoice Based on Usage'), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This may be removed in favor of using pre-existing delivery
policy, which represents the same thing for the most part
e88d57f
to
b0bff52
Compare
@@ -0,0 +1,5 @@ | |||
# -*- coding: utf-8 -*- | |||
# Copyright 2016 LasLabs Inc. | |||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Change all to LGPL
Great @lasley , I had a first look at it but I'll have a second one tomorrow. Thanks! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Two comment, but other than that LGTM
required=True, | ||
ondelete='restrict', | ||
) | ||
service_id = fields.Many2one( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't forget that we shall also be able to invoice a base, not only a service.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah good call, I knew it seemed like I was missing a layer of abstraction!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just so I'm clear, what metrics are going to be monitored on base? That's just going to be flat rate for the most part right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hum the main one I see we can use for billing is the number of users
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmmm but wouldn't the number of users be dictated in the Service itself? The base represents a collection of services doesn't it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nope it's the other way around.
A service is a set of containers, aka one Odoo instance.
A base represent both a database and an url. You can have several database in one service, like the Odoo SA offer.
And you want to count the number of user for each database of course.
from odoo import api, fields, models | ||
|
||
|
||
class ClouderMetricValue(models.Model): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't really understand the use of this model, because we said the value would be recovered realtime from ELK. If we need to store it here, we shall probably have a datetime field to know when the value was recovered.
That said, I understand this is a POC and it will probably change when we get close to the end.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah everything is going to be stored in ELK, but we need some way to store the aggregate billing metrics so they don't change out from under us after they have been used for billing.
Yup you're totally right about the need for datetimes indicating the aggregation interval. I added that in my RFC at https://github.com/clouder-community/clouder/issues/174
This module is likely going to be removed from this PR, it was just here so I could connect accounting to something while figuring that all out.
bca9547
to
3051df9
Compare
|
||
@api.multi | ||
def _get_quantity_usage(self, account_line, invoice): | ||
""" It provides a quantity based on unbilled and used metrics """ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @lasley,
My assumption is that we need to get a RecordSet of clouder.metric.interface
to return here, right? I'm just failing to find a good relation between the two. Perhaps it just wasn't implemented yet?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ummm no, it would be an actual numeric. All of these _get_quantity_*
methods would be used to determine the product_qty
of the invoice line item.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Take a look at _get_quantity_flat
3f9e1ff
to
41717e5
Compare
Codecov Report
@@ Coverage Diff @@
## master #173 +/- ##
==========================================
+ Coverage 31.53% 32.91% +1.37%
==========================================
Files 73 79 +6
Lines 5755 5873 +118
==========================================
+ Hits 1815 1933 +118
Misses 3940 3940
Continue to review full report at Codecov.
|
bbfdc58
to
92cafec
Compare
Hey guys, This is should be ready for review. Let me know if I missed anything. Thanks! |
92cafec
to
d57d815
Compare
clouder_metric/__manifest__.py
Outdated
@@ -0,0 +1,23 @@ | |||
# -*- coding: utf-8 -*- | |||
# Copyright 2016 LasLabs Inc. | |||
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This has to be AGPL due to contract_variable_quantity depends - assuming we're still using logic from it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Argh... This may be a problem, the metric module will probably be deployed in all infrastructures. If it becomes AGPL, we can practically assume that all Clouder will become AGPL, this is not the same case than clouder_asynchronous.
I'm afraid I have to be against such move just because we use this dependency. Either we can convince people that contract_variable_quantity is considered a component and shall be LGPL, or we'll have to do without it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That being said, I think I'll not block the PR just for that, we can find a solution later and merge it AGPL for the time being.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@YannickB - I think we'll be fine here. Reason being is that the metrics and sales modules are far from the core, nothing will need to depend on them, and there will likely not be third party proprietary changes.
Anything to do with contract is licensed AGPL, primarily due to it being ripped out from v8 - before the LGPL license switch in v9. I don't really want to rewrite the contract module at this time, but that would be the requirement to move from this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very well, I'm fine anyway we'll figure out what happen later.
This object receives all attributes from ``clouder.metric.type``. | ||
""" | ||
|
||
_name = 'clouder.metric.interface' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_description
key on all new models
class ClouderMetricType(models.Model): | ||
""" It provides context for usage metric types """ | ||
|
||
_name = 'clouder.metric.type' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_description
key on all new models
return _("# Python code. \n" | ||
"Use `value = my_value` to specify the final calculated " | ||
" metric value. This is required. \n" | ||
"Optionally use ``uom == product_uom_record`` to change the " |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/==/=
"units that the metric is being measured in. \n" | ||
"# You can use the following variables: \n" | ||
"# - self: browse_record of the current ID Category " | ||
"browse_record. \n" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Double browse_record
line being referenced. | ||
invoice (account.invoice): Invoice that is being created. | ||
Returns: | ||
(float) Quantity with no calculations performed |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
float:
line being referenced. | ||
invoice (account.invoice): Invoice that is being created. | ||
Returns: | ||
(float) Quantity to use on invoice line in the UOM defined on the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
float:
return False | ||
start = fields.Datetime.from_string(rec.date_start) | ||
end = fields.Datetime.from_string(rec.date_end) | ||
return start >= start_date and end <= inv_date |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add blank line
end = fields.Datetime.from_string(rec.date_end) | ||
return start >= start_date and end <= inv_date | ||
usage_values = vals.filtered(filter) | ||
for val in usage_values: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
usage = sum(usage_values.mapped('value'))
class ClouderContractLine(models.Model): | ||
""" It provides the link between billing and Clouder Services. """ | ||
|
||
_name = 'clouder.contract.line' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_description
* Fix docstrings * Implement unimplemented methods * Fix bugs found * Add test coverage * Add README [IMP] clouder_metric: Finish module * Fix/Add docstrings * Add test coverage * Fix logic * Add README
* Update license to AGPL * Add model `_description` * Clean up lint issues
489375c
to
8c7645c
Compare
* Update license to AGPL * Add model `_description` * Clean up lint issues * Improve usage metric aggregation logic
297f6c7
to
400f151
Compare
Thanks @lasley! I've attended to your comments in commit 8c7645c & 400f151 Again, I was unable to switch the I also boiled down some of the logic used to calculate the usage quantity in Thanks! |
Hi guys, Good job ! I'll make my review this afternoon, hope we can merge it quickly after that. Thanks again for your hard work. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, except one minor comment, I'm ok for this PR.
Note I've yet to make a functional review. I think make optimistic merge and correct functional issues through next PRs is the way to go here, so I'm ready to merge when @lasley approve.
@@ -0,0 +1,25 @@ | |||
# -*- coding: utf-8 -*- |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please make a symbolic link from openerp.py to manifest.py to ensure the module can be installed on Odoo 9 (see my last commit on master)
@@ -0,0 +1,23 @@ | |||
# -*- coding: utf-8 -*- |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please make a symbolic link from openerp.py to manifest.py to ensure the module can be installed on Odoo 9 (see my last commit on master)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not so sure about this. What about the changed namespace (from odoo
vs from openerp
)? I'm pretty sure I have also used some new API decorators that will not work on v9 (api.model_cr_context
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well at the very least the tricks worked on my dev instance, and all other modules now have the symbolic link. Anyway I'll not block the PR for this, so I'm just waiting for your approval.
LGTM thanks @tedsalmon. We'll likely need to make some changes when we actually implement with the Elastic connector, but this is a great start for a merge IMO. |
OK, LGTM for me too then. I'm merging, thanks @tedsalmon @lasley for the hard work ! |
This is a prelim outline of what I have been describing in #157. Nothing functional at the moment other than data schemas and a few theoretical methods.
There's also a shell of a metric interface definition, but that was just so I had something to connect the billing models to. I'm still coming up with a real plan there.