Skip to content

Commit

Permalink
[NEW] lcc_stats_api: cherry-pick commits from jojolb PR
Browse files Browse the repository at this point in the history
Based on this PR Lokavaluto#272, I've cherry-picked all the commits concerning lcc_stats_api module and I've squashed them.
  • Loading branch information
mondot committed Feb 3, 2025
1 parent bc5ab21 commit fb7c256
Show file tree
Hide file tree
Showing 13 changed files with 325 additions and 0 deletions.
56 changes: 56 additions & 0 deletions lcc_stats_api/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
=============================
lcc_stats_api
=============================

Lokavaluto statistics module on Local Currency.
It's part of Lokavaluto Project (https://lokavaluto.fr)

Installation
============

Just install lcc_stats_api, all dependencies
will be installed by default.

Known issues / Roadmap
======================

Bug Tracker
===========

Bugs are tracked on `GitHub Issues
<https://github.com/Lokavaluto/lokavaluto-addons/issues>`_. In case of trouble, please
check there if your issue has already been reported. If you spotted it first,
help us smashing it by providing a detailed and welcomed feedback.

Credits
=======

Images
------

* Lokavaluto: `Icon <https://lokavaluto.fr/web/image/res.company/1/logo?unique=f3db262>`_.

Contributors
------------

* Johan Le Baut <https://github.com/jojolb>
* Stéphan SAINLEGER <https://github.com/stephansainleger>
* Nicolas JEUDY <https://github.com/njeudy>
* Lokavaluto Teams

Funders
-------

The development of this module has been financially supported by:

* Lokavaluto (https://lokavaluto.fr)
* Mycéliandre (https://myceliandre.fr)
* Elabore (https://elabore.coop)

Maintainer
----------

This module is maintained by LOKAVALUTO.

LOKAVALUTO, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and ecosystem for local complementary currency organizations.
5 changes: 5 additions & 0 deletions lcc_stats_api/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from . import controllers

from . import datamodel
from . import models
from . import services
21 changes: 21 additions & 0 deletions lcc_stats_api/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"name": "lcc_stats_api",
"summary": "REST Odoo Backend for getting stats about local complementary currency",
"author": "Lokavaluto",
"website": "https://lokavaluto.fr",
"category": "False",
"version": "12.0.1.0.0",
# any module necessary for this one to work correctly
"depends": [
"base",
"base_rest",
"auth_api_key",
"base_rest_datamodel",
"membership",
"lcc_lokavaluto_app_connection",
],
# always loaded
"data": [],
# only loaded in demonstration mode
"demo": [],
}
1 change: 1 addition & 0 deletions lcc_stats_api/controllers/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import rest_api
13 changes: 13 additions & 0 deletions lcc_stats_api/controllers/rest_api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from odoo.addons.base_rest.controllers import main


class LokavalutoStatsPublicApiController(main.RestController):
_root_path = "/lokavaluto_api/public/stats/"
_collection_name = "lokavaluto.public.stats.services"
_default_auth = "public"


class LokavalutoStatsPrivateApiController(main.RestController):
_root_path = "/lokavaluto_api/private/stats/"
_collection_name = "lokavaluto.private.stats.services"
_default_auth = "api_key"
1 change: 1 addition & 0 deletions lcc_stats_api/datamodel/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import stats_filter
22 changes: 22 additions & 0 deletions lcc_stats_api/datamodel/stats_filter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from marshmallow import fields

from odoo.addons.datamodel.core import Datamodel


class StatsFilter(Datamodel):
"""
Describes stats API query parameters
"""

_name = "stats.filter"

start_date = fields.Date(
required=False,
allow_none=True,
description="date included, format YYYY-MM-DD",
)
end_date = fields.Date(
required=False,
allow_none=True,
description="date included, format YYYY-MM-DD",
)
5 changes: 5 additions & 0 deletions lcc_stats_api/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Copyright 2020 Lokavaluto ()
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

# from . import account_invoice
from . import res_partner
52 changes: 52 additions & 0 deletions lcc_stats_api/models/account_invoice.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Copyright 2020 Lokavaluto ()
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
import logging

from odoo import models, api
from typing_extensions import TypedDict

from ..datamodel.stats_filter import StatsFilter

_logger = logging.getLogger(__name__)


# Generic stats about currency
class CurrencyStats(TypedDict):
eur_to_mlcc: float
mlcc_to_eur: float
mlcc_circulating: float


class AccountInvoice(models.Model):
_inherit = "account.invoice"

@api.model
def get_mlcc_stats(self, stats_filter: StatsFilter = None):
# Look for paid invoices with LCC products
domain_invoices = [
("state", "=", "paid"),
("type", "in", ["out_invoice", "in_invoice"]),
("has_numeric_lcc_products", "=", True),
]

# Filter date if specified
if stats_filter:
if stats_filter.start_date:
domain_invoices.append(("date_invoice", ">=", stats_filter.start_date))
if stats_filter.end_date:
domain_invoices.append(("date_invoice", "<=", stats_filter.end_date))

invoices = self.search(domain_invoices)
mlcc_to_eur = 0.00
eur_to_mlcc = 0.00
for invoice in invoices:
if invoice.type == "out_invoice":
eur_to_mlcc += invoice.amount_total
else:
mlcc_to_eur += invoice.amount_total

return CurrencyStats(
eur_to_mlcc=eur_to_mlcc,
mlcc_to_eur=mlcc_to_eur,
mlcc_circulating=eur_to_mlcc - mlcc_to_eur,
)
39 changes: 39 additions & 0 deletions lcc_stats_api/models/res_partner.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Copyright 2020 Lokavaluto ()
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

import logging
from odoo import models, api
from typing_extensions import TypedDict

_logger = logging.getLogger(__name__)


# Stats about partners participating to local currency
class PartnersStats(TypedDict):
nb_individuals: int
nb_companies: int


class ResPartner(models.Model):
_inherit = "res.partner"

@api.model
def get_mlcc_stats(self):
# Search active members only
# Consider invoiced partners as active members
domain_partners = [
(
"membership_state",
"in",
["invoiced", "paid", "free"],
),
("is_main_profile", "=", True),
("active", "=", True),
]

partners = self.search(domain_partners)

individuals = len([p for p in partners if not p.is_company])
companies = len(partners) - individuals

return PartnersStats(nb_individuals=individuals, nb_companies=companies)
2 changes: 2 additions & 0 deletions lcc_stats_api/services/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from . import public_stats_mlcc
from . import private_stats_partner
61 changes: 61 additions & 0 deletions lcc_stats_api/services/private_stats_partner.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import logging

from odoo.addons.base_rest import restapi
from odoo.addons.base_rest_datamodel.restapi import Datamodel
from odoo.addons.component.core import Component

from ..datamodel.stats_filter import StatsFilter
from ..models.account_invoice import CurrencyStats

_logger = logging.getLogger(__name__)


class PrivateStatsPartnerService(Component):
_inherit = "base.rest.service"
_name = "private_stats_partner.service"
_usage = "partner"
_collection = "lokavaluto.private.stats.services"
_description = """
MLCC Partner Private Stats Services
Get private statistics of a local currency partner.
"""

@restapi.method(
[(["/get", "/"], "GET")],
input_param=Datamodel("stats.filter"),
)
def get(self, stats_filter: StatsFilter) -> CurrencyStats:
"""
Get a partner MLCC stats.
"""

# Get currency stats based on partner's invoices
currency_stats: CurrencyStats = self.env["account.invoice"].get_mlcc_stats(
stats_filter
)

return currency_stats

##########################################################
# Swagger Validators
##########################################################

# We override the Swagger method that will display params for this component's routes
def _get_openapi_default_parameters(self):
# For each private route in this class, we retrieve the params specified at route level
defaults = super(
PrivateStatsPartnerService, self
)._get_openapi_default_parameters()
# We append to existing params another one related to private endpoint: API-KEY
defaults.append(
{
"name": "API-KEY",
"in": "header",
"description": "Auth API key - get a token using API /lokavaluto_api/public/auth/authenticate",
"required": True,
"schema": {"type": "string"},
"style": "simple",
}
)

return defaults
47 changes: 47 additions & 0 deletions lcc_stats_api/services/public_stats_mlcc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import logging

from odoo.addons.base_rest import restapi
from odoo.addons.base_rest_datamodel.restapi import Datamodel
from odoo.addons.component.core import Component

from ..datamodel.stats_filter import StatsFilter
from ..models.account_invoice import CurrencyStats
from ..models.res_partner import PartnersStats

_logger = logging.getLogger(__name__)


class MlccStats(CurrencyStats, PartnersStats):
pass


class PublicStatsMlccService(Component):
_inherit = "base.rest.service"
_name = "public_stats.service"
_usage = "mlcc"
_collection = "lokavaluto.public.stats.services"
_description = """
MLCC Public Stats Services
Get public statistics about a local currency
"""

# The following method are 'public' and can be called from the controller.

@restapi.method(
[(["/get", "/"], "GET")],
input_param=Datamodel("stats.filter"),
)
def get(self, stats_filter: StatsFilter) -> MlccStats:
"""
Get MLCC public stats.
"""

# Get currency stats based on all invoices
currency_stats: CurrencyStats = (
self.env["account.invoice"].sudo().get_mlcc_stats(stats_filter)
)

# Get partners stats
partner_stats: PartnersStats = self.env["res.partner"].sudo().get_mlcc_stats()

return MlccStats(**currency_stats, **partner_stats)

0 comments on commit fb7c256

Please sign in to comment.