Skip to content

Commit

Permalink
refacto: infra: reorganize files (#34)
Browse files Browse the repository at this point in the history
* move infra code in /infra

* move application code in /src
  • Loading branch information
clarani authored Oct 27, 2023
1 parent ee15abb commit f022380
Show file tree
Hide file tree
Showing 90 changed files with 1,230 additions and 1 deletion.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
1 change: 0 additions & 1 deletion modules/api/sync/data/.gitignore

This file was deleted.

9 changes: 9 additions & 0 deletions src/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Sync

## Getting Started

```console
docker compose up -d
docker compose run --rm app pip install -r requirements.txt
docker compose run --rm app python index.py
```
22 changes: 22 additions & 0 deletions src/compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
services:
app:
image: python
working_dir: /package
volumes:
- ./package:/package
- app_vendors:/usr/local/lib/python3.11/site-packages
pg:
image: postgis/postgis
environment:
POSTGRES_PASSWORD: ecowater
POSTGRES_USER: ecowater
POSTGRES_DB: ecowater
ports:
- 5432:5432
volumes:
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
- pgdata:/var/lib/postgresql/data

volumes:
app_vendors: ~
pgdata: ~
61 changes: 61 additions & 0 deletions src/features/display_data/data_provider.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
def get_mocked_restrictions():
return [
('alerte renforcée', 'Interdiction', 'Alimentation des fontaines publiques et privées', 'Alimentation des fontaines publiques et privées d’ornement', '', ' Interdit', None, None),
('alerte renforcée', 'Interdiction', 'Alimentation des fontaines publiques et privées', 'Alimentation des fontaines publiques et privées d’ornement', '', " qui ne fonctionnent pas sur un circuit d'eau fermé", None, None),
('alerte renforcée', 'Interdiction', 'Alimentation des fontaines publiques et privées', 'Alimentation des fontaines publiques et privées d’ornement', '', "qui ne fonctionnent pas sur un circuit d'eau fermé", None, None),
('alerte renforcée', 'Interdiction', 'Arrosage', 'Arrosage des espaces verts', '', ' Interdit', None, None),
('alerte renforcée', 'Interdiction', 'Arrosage', "Arrosage des golfs(Conformément à l'accord cadre golf et environnement 2019-2024", '', ' Interdit', None, None),
('alerte renforcée', 'Interdiction', 'Arrosage', 'Arrosage des jardins potagers', '', ' Interdit', None, None),
('alerte renforcée', 'Interdiction', 'Arrosage', 'Arrosage des pelouses, massifs fleuris', '', ' hors arrosage par micro-irrigation et goutte à goutte', None, None),
('alerte renforcée', 'Interdiction', 'Arrosage', 'Arrosage des pelouses, massifs fleuris', '', ' Interdit', None, None),
('alerte renforcée', 'Interdiction sauf exception', 'Arrosage', "Arrosage des golfs(Conformément à l'accord cadre golf et environnement 2019-2024", '', "A l'exception des greens et des départs", None, None),
('alerte renforcée', 'Interdiction sauf exception', 'Arrosage', 'Arrosage des jardins potagers', '', 'les béals qui alimentent les jardins potagers sont soumis aux mêmes restrictions que les usages agricoles', None, None),
('alerte renforcée', 'Interdiction sauf exception', 'Nettoyage', 'Lavage de véhicules chez les particuliers', '', ' Sauf pour les véhicules ayant une obligation réglementaire (véhicule sanitaire ou alimentaire) ou technique (épareuse, bétonnière,...) et pour les organismes liés à la sécurité.', None, None),
('alerte renforcée', 'Interdiction sauf exception', 'Nettoyage', 'Lavage de véhicules chez les particuliers', '', 'Sauf pour les véhicules ayant une obligation réglementaire (véhicule sanitaire ou alimentaire) ou technique (épareuse, bétonnière, ...) et pour les organismes liés à la sécurité.', None, None),
('alerte renforcée', 'Interdiction sauf exception', 'Remplissage vidange', "Remplissage et vidange de piscines privées (de plus d'1 m3)", '', "A l'exception de la première mise en eau des piscines nouvellement construites. A l'exception de la mise à niveau.", None, None),
('alerte renforcée', 'Interdiction sauf exception', 'Remplissage vidange', "Remplissage et vidange de piscines privées (de plus d'1 m3)", '', 'Sauf la mise à niveau.', None, None),
('alerte renforcée', 'Interdiction sauf exception', 'Travaux en cours d’eau', 'Travaux en cours d’eau', '', "Sauf autorisation service Police de l'Eau.", None, None),
('alerte renforcée', 'Interdiction sur plage horaire', 'Arrosage', 'Arrosage des espaces verts', '', 'NULL', 8, 20),
('alerte renforcée', 'Interdiction sur plage horaire', 'Arrosage', "Arrosage des golfs(Conformément à l'accord cadre golf et environnement 2019-2024", '', 'NULL', 8, 20),
('alerte renforcée', 'Interdiction sur plage horaire', 'Arrosage', 'Arrosage des jardins potagers', '', 'NULL', 8, 10),
('alerte renforcée', 'Interdiction sur plage horaire', 'Arrosage', 'Arrosage des jardins potagers', '', 'NULL', 10, 18),
('alerte renforcée', 'Interdiction sur plage horaire', 'Arrosage', 'Arrosage des pelouses, massifs fleuris', '', 'NULL', 8, 20),
('alerte renforcée', 'Pas de restriction', 'Abreuvement', 'Abreuvement des animaux', '', 'NULL', None, None),
('alerte renforcée', 'Sensibilisation', 'Alimentation des fontaines publiques et privées', 'Alimentation des fontaines publiques et privées d’ornement', '', 'Limitation volontaire', None, None),
('alerte renforcée', 'Sensibilisation', 'Arrosage', 'Arrosage des espaces verts', '', 'Limitation volontaire ', None, None),
('alerte renforcée', 'Sensibilisation', 'Arrosage', "Arrosage des golfs(Conformément à l'accord cadre golf et environnement 2019-2024", '', ' Limitation volontaire', None, None),
('alerte renforcée', 'Sensibilisation', 'Arrosage', 'Arrosage des jardins potagers', '', ' Limitation volontaire', None, None),
('alerte renforcée', 'Sensibilisation', 'Arrosage', 'Arrosage des pelouses, massifs fleuris', '', ' Limitation volontaire', None, None),
('alerte renforcée', 'Sensibilisation', 'Nettoyage', 'Lavage de véhicules chez les particuliers', '', ' Limitation volontaire', None, None),
('alerte renforcée', 'Sensibilisation', 'Remplissage vidange', "Remplissage et vidange de piscines privées (de plus d'1 m3)", '', 'Limitation volontaire', None, None),
('alerte renforcée', 'Sensibilisation', 'Travaux en cours d’eau', 'Travaux en cours d’eau', '', "Éviter de prévoir des travaux dont les interventions nécessitent le rejet d'effluents pas ou partiellement traités dans le milieu récepteur.", None, None),
('vigilance', 'Interdiction', 'Alimentation des fontaines publiques et privées', 'Alimentation des fontaines publiques et privées d’ornement', '', ' Interdit', None, None),
('vigilance', 'Interdiction', 'Alimentation des fontaines publiques et privées', 'Alimentation des fontaines publiques et privées d’ornement', '', " qui ne fonctionnent pas sur un circuit d'eau fermé", None, None),
('vigilance', 'Interdiction', 'Alimentation des fontaines publiques et privées', 'Alimentation des fontaines publiques et privées d’ornement', '', "qui ne fonctionnent pas sur un circuit d'eau fermé", None, None),
('vigilance', 'Interdiction', 'Arrosage', 'Arrosage des espaces verts', '', ' Interdit', None, None),
('vigilance', 'Interdiction', 'Arrosage', "Arrosage des golfs(Conformément à l'accord cadre golf et environnement 2019-2024", '', ' Interdit', None, None),
('vigilance', 'Interdiction', 'Arrosage', 'Arrosage des jardins potagers', '', ' Interdit', None, None),
('vigilance', 'Interdiction', 'Arrosage', 'Arrosage des pelouses, massifs fleuris', '', ' hors arrosage par micro-irrigation et goutte à goutte', None, None),
('vigilance', 'Interdiction', 'Arrosage', 'Arrosage des pelouses, massifs fleuris', '', ' Interdit', None, None),
('vigilance', 'Interdiction sauf exception', 'Arrosage', "Arrosage des golfs(Conformément à l'accord cadre golf et environnement 2019-2024", '', "A l'exception des greens et des départs", None, None),
('vigilance', 'Interdiction sauf exception', 'Arrosage', 'Arrosage des jardins potagers', '', 'les béals qui alimentent les jardins potagers sont soumis aux mêmes restrictions que les usages agricoles', None, None),
('vigilance', 'Interdiction sauf exception', 'Nettoyage', 'Lavage de véhicules chez les particuliers', '', ' Sauf pour les véhicules ayant une obligation réglementaire (véhicule sanitaire ou alimentaire) ou technique (épareuse, bétonnière,...) et pour les organismes liés à la sécurité.', None, None),
('vigilance', 'Interdiction sauf exception', 'Nettoyage', 'Lavage de véhicules chez les particuliers', '', 'Sauf pour les véhicules ayant une obligation réglementaire (véhicule sanitaire ou alimentaire) ou technique (épareuse, bétonnière, ...) et pour les organismes liés à la sécurité.', None, None),
('vigilance', 'Interdiction sauf exception', 'Remplissage vidange', "Remplissage et vidange de piscines privées (de plus d'1 m3)", '', "A l'exception de la première mise en eau des piscines nouvellement construites. A l'exception de la mise à niveau.", None, None),
('vigilance', 'Interdiction sauf exception', 'Remplissage vidange', "Remplissage et vidange de piscines privées (de plus d'1 m3)", '', 'Sauf la mise à niveau.', None, None),
('vigilance', 'Interdiction sauf exception', 'Travaux en cours d’eau', 'Travaux en cours d’eau', '', "Sauf autorisation service Police de l'Eau.", None, None),
('vigilance', 'Interdiction sur plage horaire', 'Arrosage', 'Arrosage des espaces verts', '', 'NULL', 8, 20),
('vigilance', 'Interdiction sur plage horaire', 'Arrosage', "Arrosage des golfs(Conformément à l'accord cadre golf et environnement 2019-2024", '', 'NULL', 8, 20),
('vigilance', 'Interdiction sur plage horaire', 'Arrosage', 'Arrosage des jardins potagers', '', 'NULL', 8, 10),
('vigilance', 'Interdiction sur plage horaire', 'Arrosage', 'Arrosage des jardins potagers', '', 'NULL', 10, 18),
('vigilance', 'Interdiction sur plage horaire', 'Arrosage', 'Arrosage des pelouses, massifs fleuris', '', 'NULL', 8, 20),
('vigilance', 'Pas de restriction', 'Abreuvement', 'Abreuvement des animaux', '', 'NULL', None, None),
('vigilance', 'Sensibilisation', 'Alimentation des fontaines publiques et privées', 'Alimentation des fontaines publiques et privées d’ornement', '', 'Limitation volontaire', None, None),
('vigilance', 'Sensibilisation', 'Arrosage', 'Arrosage des espaces verts', '', 'Limitation volontaire ', None, None),
('vigilance', 'Sensibilisation', 'Arrosage', "Arrosage des golfs(Conformément à l'accord cadre golf et environnement 2019-2024", '', ' Limitation volontaire', None, None),
('vigilance', 'Sensibilisation', 'Arrosage', 'Arrosage des jardins potagers', '', ' Limitation volontaire', None, None),
('vigilance', 'Sensibilisation', 'Arrosage', 'Arrosage des pelouses, massifs fleuris', '', ' Limitation volontaire', None, None),
('vigilance', 'Sensibilisation', 'Nettoyage', 'Lavage de véhicules chez les particuliers', '', ' Limitation volontaire', None, None),
('vigilance', 'Sensibilisation', 'Remplissage vidange', "Remplissage et vidange de piscines privées (de plus d'1 m3)", '', 'Limitation volontaire', None, None),
('vigilance', 'Sensibilisation', 'Travaux en cours d’eau', 'Travaux en cours d’eau', '', "Éviter de prévoir des travaux dont les interventions nécessitent le rejet d'effluents pas ou partiellement traités dans le milieu récepteur.", None, None)
]
62 changes: 62 additions & 0 deletions src/features/display_data/getSummary.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
from data_provider import get_mocked_restrictions
import urllib.parse

PDF_URL = "https://propluvia-data.s3.gra.io.cloud.ovh.net/pdf/"

restriction_levels = {
"vigilance": 1,
"alerte": 2,
"alerte renforcée": 3,
"crise": 4,
}

PDF_URL = "https://propluvia-data.s3.gra.io.cloud.ovh.net/pdf/"

def create_summary(restrictions_data):
restrictions_dict = {
"sensibilisation": {},
"reduction-prelevement": {},
"interdiction-plage-horaire": {},
"interdiction-sauf-exception": {},
"interdiction": {},
}

for item in restrictions_data:
formatted_restriction = {
"thematique": item[2],
"libelle-personnalise": item[6],
"en-savoir-plus": item[5],
}

if item[1] == "Sensibilisation":
restrictions_dict["sensibilisation"][item[3]] = formatted_restriction

elif item[1] == "Réduction de prélèvement":
restrictions_dict["reduction-prelevement"][item[3]] = formatted_restriction

elif item[1] == "Interdiction sur plage horaire":
restrictions_dict["interdiction-plage-horaire"][item[3]] = {
"thematique": item[2],
"heure-debut": item[6],
"heure-fin": item[7],
"en-savoir-plus": item[5],
}

elif item[1] == "Interdiction sauf exception":
restrictions_dict["interdiction-sauf-exception"][item[3]] = formatted_restriction

elif item[1] == "Interdiction":
restrictions_dict["interdiction"][item[3]] = formatted_restriction

result_dict = {
"niveau-alerte": restrictions_data[0][0],
"niveau-alerte-chiffre": restriction_levels[restrictions_data[0][0]],
"document": f"{PDF_URL}{urllib.parse.quote_plus(restrictions_data[0][8])}",
"restrictions": restrictions_dict
}

return result_dict


if __name__ == '__main__':
create_summary(get_mocked_restrictions())
60 changes: 60 additions & 0 deletions src/features/display_data/index.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import os
import logging
import db_connection
from psycopg2.extensions import AsIs
from getSummary import create_summary

# Lambda environment variables
SECRET_NAME = os.environ['secret_name']
REGION_NAME = os.environ['region_name']
DB = os.environ['db']
RAW_PATH = os.environ['raw_path']
ENV = os.environ['env']

# Connect to database. Keep out of lambda_handler for performance
read_replica = True if ENV == 'prod' else False
connection = db_connection.connect_to_db(SECRET_NAME, REGION_NAME, DB, read_replica)
connection.autocommit = True
logging.debug("Connected to the database")

def lambda_handler(event, context):
RAW_PATH = os.environ['raw_path']

if event['rawPath'] == RAW_PATH:
# get the coordinates from the API query
longitude = event['queryStringParameters']['longitude']
latitude = event['queryStringParameters']['latitude']
situation = event['queryStringParameters']['situation']

query = """
SELECT DISTINCT de.alert_level, re.restriction_level, re.theme, re.label, re.description, re.specification, re.from_hour, re.to_hour, de.document
FROM geozone AS gz
INNER JOIN decree AS de ON de.geozone_id = gz.id
LEFT JOIN restriction AS re ON re.decree_id = de.id
WHERE ST_Contains(
gz.geom,
ST_SetSRID(
ST_MakePoint(%s, %s),
4326
)
)
AND de.start_date <= NOW()
AND NOW() <= de.end_date;
"""
params = (longitude, latitude)

try:
cursor = connection.cursor()
cursor.execute(query, params)
data = cursor.fetchall()
cursor.close()
connection.commit()
except Exception as e:
logging.error('Failed to fetch restrictions. User: %s, Longitude: %s, Latitude: %s, Exception: %s', situation, longitude, latitude, str(e))

# create the summary from the data
results_dict = create_summary(data) if len(data) > 0 else {}
return results_dict

else:
return {"Error" : "Wrong API path"}
96 changes: 96 additions & 0 deletions src/features/email_alerting.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import logging
from mailjet_rest import Client
import os
import psycopg2
from psycopg2.extras import DictCursor

import db_connection

import repositories


# lambda environment variables
SECRET_NAME = os.environ['secret_name']
REGION_NAME = os.environ['region_name']
DB = os.environ['db']

# def connect_to_local_db():
# connection = psycopg2.connect(database="ecowater", user="ecowater", password="ecowater", host="pg", port="5432")
# return connection

# def get_credentials():
# '''get the DB credentials from Secrets Manager'''
# return {
# 'mailjet_api_key': 'find key on aws',
# 'mailjet_api_secret': 'find key on aws',
# }

credential = db_connection.get_credentials(SECRET_NAME, REGION_NAME, DB)
# credential = get_credentials()

def create_email(email_address):
return {
'Messages': [
{
"From": {
"Email": "[email protected]",
"Name": "Alerte Sécheresse"
},
"To": [
{
"Email": email_address,
"Name": email_address
}
],
"TemplateID": 4732985,
"TemplateLanguage": True,
"Subject": "renforcée",
"Variables": {
"niveau": "maximale"
}
}
]
}


def lambda_handler(event, context):
logging.basicConfig(level = logging.DEBUG, format = '%(asctime)s - %(levelname)s - %(message)s')
logging.debug('Connected to the database')

connection = db_connection.connect_to_db(SECRET_NAME, REGION_NAME, DB)
# connection = connect_to_local_db()
connection.autocommit = True
cursor = connection.cursor(cursor_factory=DictCursor)

mailjet = Client(auth=(credential['mailjet_api_key'], credential['mailjet_api_secret']), version='v3.1')

# on récupère les events qui doivent être consommés
events = repositories.find_all_decree_events(cursor)

for event in events:
# on récupère le decree associé et sa geozone
decree_id = event[1]
decree = repositories.get_decree_by_id(cursor, decree_id)
if decree == None:
logging.error('Decree with id %s not found.', decree_id)
continue

# on récupère les utilisateurs associés à la zone
geozone_id = decree.get_geozone_id()
email_addresses = repositories.find_user_emails_by_geozone_id(cursor, geozone_id)

# on envoie les emails à chaque utilisateur
for email_address in email_addresses:
email = create_email(email_address[0])
result = mailjet.send.create(data=email)
logging.info(f"Sending email to {email_address[0]}")
if (result.status != 200):
logging.error(f"Failed to send email to {email_address[0]} (decree_id: {decree})")

# on supprime l'event
repositories.delete_event(cursor, event[0])

return

if __name__ == '__main__':
lambda_handler(None, None)
Loading

0 comments on commit f022380

Please sign in to comment.