Skip to content
Extraits de code Groupes Projets
Valider a22ed240 rédigé par Benjamin - Le Filament's avatar Benjamin - Le Filament
Parcourir les fichiers

[REF] refactor functions to store only day flow data

parent 6567f1ec
Branches
Aucune étiquette associée trouvée
Aucune requête de fusion associée trouvée
......@@ -3,14 +3,14 @@
from dateutil.relativedelta import relativedelta
from odoo import _, api, fields, models
from odoo.exceptions import UserError
from odoo.addons.api_connector.tools.date_utils import local_to_utc
from odoo import api, fields, models
class HallFlowLog(models.Model):
_name = "hall.flow.log"
_description = "Hall Flow Logs"
_rec_name = "date_log"
_order = "date_log desc"
# ------------------------------------------------------
# Fields declaration
......@@ -39,110 +39,63 @@ class HallFlowLog(models.Model):
"""
if not hall_ids:
hall_ids = self.env["hall.hall"].search([])
log_ids = self
if not (start_date and end_date):
start_date = fields.Datetime.start_of(
fields.Datetime.now(), granularity="day"
)
end_date = fields.Datetime.end_of(fields.Datetime.now(), granularity="day")
if not hall_ids.mapped("zone_ids"):
return
for hall in hall_ids:
if hall.zone_ids:
last_import = self._get_last_import(hall)
if start_date and last_import and start_date < last_import:
raise UserError(_(
"Un import existe déjà pour cette date %s"
) % (fields.Date.to_string(start_date)))
if not start_date:
start_date = last_import + relativedelta(days=1)
if not end_date:
end_date = fields.Date.today() - relativedelta(days=1)
log_id = self.create({
log_id = self.create(
{
"date_log": fields.Datetime.now(),
"date_start": start_date,
"date_end": end_date,
"hall_id": hall.id
})
"hall_id": hall.id,
}
)
for zone in hall.zone_ids:
# Retrieve visitor datas
visit_desc = log_id.hall_id.name + " - " + zone.name + " - Visiteurs"
zone.with_delay(description=visit_desc)._wts_create_visitor(
start_date, end_date, log_id
visit_desc = "%s - %s - Visiteurs" % (
log_id.hall_id.name,
zone.name,
)
# Retrieve passer_by datas
delta_days = (end_date - start_date).days
pass_desc = log_id.hall_id.name + " - " + zone.name + " - Passants"
if delta_days > 0:
start_passerby = start_date
for day in range(0, delta_days):
zone.with_delay(description=pass_desc, max_retries=10)._wts_create_passerby(
start_passerby, end_date, log_id
zone.with_delay(description=visit_desc)._wts_create_entry(
start_date, end_date, log_id, endpoint="visitor"
)
start_passerby = start_passerby + relativedelta(days=1, hours=1)
else:
zone.with_delay(description=pass_desc, max_retries=10)._wts_create_passerby(
start_date, end_date, log_id
pass_desc = "%s - %s - Passants" % (log_id.hall_id.name, zone.name)
zone.with_delay(description=pass_desc)._wts_create_entry(
start_date, end_date, log_id, endpoint="passerby"
)
# Retrieve In/Out datas
for sensor in zone.sensor_ids.filtered(lambda s: s.sensor_type == "sensor"):
description = log_id.hall_id.name + " - " + sensor.name
sensor.with_delay(description=description, max_retries=10)._wts_create_inout(
start_date, end_date, log_id
)
log_ids += log_id
return log_ids
# ------------------------------------------------------
# CRON functions
# ------------------------------------------------------
def cron_wts(self, days=None, interval=None):
def cron_wts(self, days=1, interval=None):
"""
WTS datas retrieve CRON
:param integer days: days before today if specified
:param integer interval: number of days to retrieve
:param bool group_by_day: aggregate result number by day
"""
now = fields.Datetime.now()
day_end = float(
self.env["ir.config_parameter"].sudo().get_param("hall.day_end")
)
hour_end = int(day_end)
minute_end = int((day_end - hour_end) * 60)
day_start = float(
self.env["ir.config_parameter"].sudo().get_param("hall.day_start")
)
hour_start = int(day_start)
minute_start = int((day_start - hour_start) * 60)
timezone = self._context.get("tz") if self._context.get("tz") else "Europe/Paris"
end_date = local_to_utc(
now.replace(hour=hour_end + 1, minute=minute_end, second=0), timezone
)
if now < end_date:
end_date = end_date - relativedelta(days=1)
yesterday = fields.Datetime.now() - relativedelta(days=1)
start_date = fields.Datetime.start_of(yesterday, granularity="day")
end_date = fields.Datetime.end_of(yesterday, granularity="day")
if days:
start_date = start_date - relativedelta(days=days)
end_date = end_date - relativedelta(days=days)
start_date = (end_date - relativedelta(days=1)).replace(
hour=hour_start, minute=minute_start
)
start_date = local_to_utc(start_date, timezone)
if interval and interval > 1:
start_date = start_date - relativedelta(days=interval)
end_date = end_date - relativedelta(days=interval)
for day in range(0, interval):
self.import_wts_data(start_date=start_date, end_date=end_date)
start_date = start_date + relativedelta(days=1)
end_date = end_date + relativedelta(days=1)
else:
self.import_wts_data(start_date=start_date, end_date=end_date)
# ------------------------------------------------------
# Common functions
# ------------------------------------------------------
def _get_last_import(self, hall_id):
last_log_id = self.search(
[("hall_id", "=", hall_id.id)], order="date_end desc", limit=1
)
return last_log_id.date_end if last_log_id else False
......@@ -4,6 +4,7 @@
from datetime import datetime
from odoo import fields, models
from odoo.addons.api_connector.tools.date_utils import local_to_utc
......@@ -72,7 +73,7 @@ class HallFlowSensor(models.Model):
{
"date": local_to_utc(
datetime.strptime(date, "%Y-%m-%d %H:%M:%S"),
sensor.zone_id.timezone
sensor.zone_id.timezone,
),
"flow_type": key,
"count": data,
......
# Copyright 2023 Le Filament (https://le-filament.com)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
from datetime import datetime
from psycopg2.errors import UniqueViolation
from odoo import _, fields, models
from odoo.exceptions import UserError, ValidationError
from odoo import fields, models
from odoo.addons.api_connector.tools.date_utils import local_to_utc
from odoo.addons.queue_job.exception import FailedJobError
......@@ -46,10 +47,7 @@ class HallFlowZone(models.Model):
inverse_name="zone_id",
string="Capteurs",
)
timezone = fields.Char(
string='Timezone',
default=lambda self: self._context.get('tz')
)
timezone = fields.Char(default=lambda self: self._context.get("tz"))
# ------------------------------------------------------
# SQL Constrains
......@@ -71,97 +69,93 @@ class HallFlowZone(models.Model):
if zone_data and zone_data.get("children", False):
for child in zone_data.get("children"):
child_id = self.with_context(active_test=False).search(
[("wts_id", "=", child)])
[("wts_id", "=", child)]
)
if child_id:
child_id.parent_id = zone
# Create/update sensors
if zone_data and zone_data.get("sensors", False):
for sensor in zone_data.get("sensors"):
sensor_id = self.sensor_ids.with_context(active_test=False).search(
[("wts_id", "=", sensor)])
[("wts_id", "=", sensor)]
)
if not sensor_id:
zone.update({
"sensor_ids": [(0, 0, {
"wts_id": sensor,
"sensor_type": "sensor"
})]
})
zone.update(
{
"sensor_ids": [
(0, 0, {"wts_id": sensor, "sensor_type": "sensor"})
]
}
)
def _wts_create_visitor(
self, start_date, end_date, log_id, opening_time=True
def _wts_create_entry(
self,
start_date,
end_date,
log_id,
endpoint,
opening_time=True,
):
"""
Create visitors flows depending on zone
Create visitors flows depending on zone by hours
:param datetime start_date: Start date of period
:param datetime end_date: End date of period
:param object log_id: Related log
:param bool opening_time: Defines if opening times need to be consider or not
:param bool opening_time: Defines if opening times need to be considered or not
@return flow_ids
"""
flow_ids = self.env["hall.flow"]
backend_id = log_id.hall_id.backend_id
if endpoint not in ["visitor", "passerby"]:
raise ValidationError(_("Wrong endpoint value"))
for zone in self:
try:
visitor_datas = backend_id._get_wifi_datas(
url="/visitor/counthourdetails",
wts_datas = backend_id._get_wifi_datas(
url="/%s/countdetails" % (endpoint),
zone_ids=zone.mapped("wts_id"),
start_date=start_date,
end_date=end_date,
opening_time=opening_time,
)
if visitor_datas:
for date, data in visitor_datas.items():
if wts_datas:
datas = wts_datas.get("all")
for date, value in datas.items():
log = "Import OK: %s - %s - %s - %s\n" % (
date,
log_id.hall_id.name,
zone.name,
endpoint,
)
print(log)
flow_ids += flow_ids.sudo().create(
{
"date": local_to_utc(
datetime.strptime(date, "%Y-%m-%d %H:%M:%S"), zone.timezone
),
"flow_type": "visitor",
"count": data,
"date": fields.Date.from_string(date),
"flow_type": endpoint,
"count": value,
"log_id": log_id.id,
"hall_id": log_id.hall_id.id,
"zone_id": zone.id,
}
)
if not log_id.log:
log_id.log = log
else:
log_id.log += log
except (UniqueViolation, UserError):
log = "Already exists: %s - %s - %s - %s\n" % (
date,
log_id.hall_id.name,
zone.name,
endpoint,
)
if not log_id.log:
log_id.log = log
else:
log_id.log += log
except Exception as e:
raise FailedJobError(e.__str__())
return flow_ids
def _wts_create_passerby(
self, start_date, end_date, log_id, opening_time=True
):
"""
Create passer by flows depending on zone
:param datetime start_date: Start date of period
:param datetime end_date: End date of period
:param object log_id: Related log
:param bool opening_time: Defines if opening times need to be consider or not
"""
backend_id = log_id.hall_id.backend_id
flow_ids = self.env["hall.flow"]
for zone in self:
passerby_datas = backend_id._get_wifi_datas(
url="/passerby/counthour",
zone_ids=zone.mapped("wts_id"),
start_date=start_date,
end_date=end_date,
opening_time=opening_time,
)
if passerby_datas:
for date, data in passerby_datas.items():
date_passerby = datetime(
start_date.year, start_date.month, start_date.day, int(date), 0, 0
)
flow_ids += flow_ids.create(
{
"date": local_to_utc(date_passerby, zone.timezone),
"flow_type": "passerby",
"count": data,
"log_id": log_id.id,
"hall_id": log_id.hall_id.id,
"zone_id": zone.id,
}
)
return flow_ids
......@@ -8,7 +8,7 @@
<field name="name">hall.flow.log.tree</field>
<field name="model">hall.flow.log</field>
<field name="arch" type="xml">
<tree create="0" editable="top">
<tree create="0">
<field name="date_log" />
<field name="hall_id" />
<field name="create_uid" />
......@@ -17,6 +17,32 @@
</tree>
</field>
</record>
<!-- Form View -->
<record id="hall_flow_log_form" model="ir.ui.view">
<field name="name">hall.flow.log.form</field>
<field name="model">hall.flow.log</field>
<field name="arch" type="xml">
<form>
<sheet>
<group>
<group>
<field name="date_log" readonly="1" />
<field name="hall_id" readonly="1" />
<field name="create_uid" readonly="1" />
</group>
<group>
<field name="date_start" readonly="1" />
<field name="date_end" readonly="1" />
</group>
</group>
<separator string="Log info" />
<field name="log" readonly="1" />
</sheet>
</form>
</field>
</record>
<!-- Search View -->
<record id="hall_flow_log_search" model="ir.ui.view">
......@@ -36,6 +62,6 @@
<field name="name">Log flux</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">hall.flow.log</field>
<field name="view_mode">tree</field>
<field name="view_mode">tree,form</field>
</record>
</odoo>
# Copyright 2023 Le Filament (https://le-filament.com)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
from odoo import _, fields, models
from odoo.exceptions import UserError
from odoo import fields, models
class HallFlowImportWizard(models.TransientModel):
......@@ -12,14 +11,6 @@ class HallFlowImportWizard(models.TransientModel):
# ------------------------------------------------------
# Fields declaration
# ------------------------------------------------------
import_type = fields.Selection(
selection=[
("last_import", "Depuis le dernier import"),
("choose_date", "Choisir les dates"),
],
string="Import",
required=True,
)
hall_id = fields.Many2one(comodel_name="hall.hall", string="Site", required=True)
date_start = fields.Date("Date de début")
date_end = fields.Date("Date de fin")
......@@ -28,27 +19,13 @@ class HallFlowImportWizard(models.TransientModel):
# Action functions
# ------------------------------------------------------
def action_import_flow(self):
Log = self.env["hall.flow.log"].sudo()
# Détermination des dates de début et de fin de requête
if self.import_type == "choose_date":
start_date = fields.Datetime.start_of(
fields.Datetime.to_datetime(self.date_start), granularity="day"
)
end_date = fields.Datetime.end_of(
fields.Datetime.to_datetime(self.date_end), granularity="day"
)
else:
last_log = Log.search([], order="date_start desc", limit=1)
if last_log:
start_date = fields.Datetime.start_of(
fields.Datetime.add(last_log.end_date, days=1), granularity="day"
)
else:
raise UserError(_("Aucun import n'a été effectué"))
yesterday = fields.Datetime.subtract(fields.Datetime.now(), days=1)
end_date = fields.Datetime.end_of(yesterday, granularity="day")
log_ids = Log.import_wts_data(
self.env["hall.flow.log"].sudo().import_wts_data(
hall_ids=self.hall_id, start_date=start_date, end_date=end_date
)
......@@ -11,23 +11,14 @@
</div>
<group>
<group>
<field name="import_type" widget="radio" />
<field
name="hall_id"
options="{'no_create': True, 'no_open': True}"
/>
</group>
<group
attrs="{'invisible': [('import_type', '!=', 'choose_date')]}"
>
<field
name="date_start"
attrs="{'required': [('import_type', '=', 'choose_date')]}"
/>
<field
name="date_end"
attrs="{'required': [('import_type', '=', 'choose_date')]}"
/>
<group>
<field name="date_start" required="1" />
<field name="date_end" required="1" />
</group>
</group>
<footer>
......
0% Chargement en cours ou .
You are about to add 0 people to the discussion. Proceed with caution.
Veuillez vous inscrire ou vous pour commenter