SPB Git forge

spb/resto-ka

Public

Resto·Ka — tous les restaurants du Québec, menus complets et prix réels (famille ·Ka)

52commits 1branches 0releases
11.6 MBsize
maindefault branch
19 days agolast push
Python 69.3% TypeScript 16.7% CSS 7.9% JavaScript 4.7% HTML 1.4%
5.5 KB · 120 lines python
Raw Blame History
1# ==============================================================================2# Author: Simon-Pierre Boucher <contact@spboucher.ai>3# File:   tests/test_inspections.py4# Desc:   Connecteur MAPAQ (condamnations) — import CSV HORS LIGNE, parsing5#         des dates/amendes/code postal, croisement CONSERVATEUR avec les6#         restaurants (nom+lieu, adresse+nom, jamais de fusion hasardeuse),7#         anti-doublon au ré-import, endpoint et details.mapaq.8# ==============================================================================9import json1011from restoka import inspections12from restoka.schema import Restaurant13from restoka import db as rdb141516RECORDS = [17    {   # croisement par nom exact + ville contenue dans l'adresse18        "Nom_exploitant": "9277-4876 QUEBEC INC.",19        "Raison_sociale": "RESTAURANT CHEZ MAMY",20        "Description_infraction": "LIEUX NON PROPRES.",21        "Adresse_lieu_infraction": "1999 SAINTE-FAMILLE SAGUENAY, (QC) G7X4X5",22        "Type_etablissement": "CASSE-CROUTE",23        "Date_infraction": "11/27/2025 00:00:00",24        "Date_jugement": "05/19/2026 00:00:00",25        "Date_publication": "05/22/2026 00:00:00",26        "Amende": "500 $",27        "SOC_NOM_LOI": "Loi sur les produits alimentaires",28        "SOC_NOM_ARTCL_INFRC": "INSALUBRITE",29        "SOC_DESC_REGRP_TYP_ENTT": "RESTAURATION",30    },31    {   # croisement par code postal + civique + similarité de nom32        "Nom_exploitant": "GESTION PIZZA BELLA INC.",33        "Raison_sociale": "PIZZA BELLA",34        "Description_infraction": "TEMPERATURE INADEQUATE.",35        "Adresse_lieu_infraction": "300 RUE PRINCIPALE QUEBEC, (QC) G1K 3Y2",36        "Type_etablissement": "RESTAURANT",37        "Date_infraction": "01/15/2026 00:00:00",38        "Date_jugement": "03/10/2026 00:00:00",39        "Date_publication": "03/12/2026 00:00:00",40        "Amende": "1 250 $",41        "SOC_NOM_LOI": "Loi sur les produits alimentaires",42        "SOC_NOM_ARTCL_INFRC": "TEMPERATURE",43        "SOC_DESC_REGRP_TYP_ENTT": "RESTAURATION",44    },45    {   # AUCUN croisement : même nom qu'un resto mais autre ville/CP46        "Nom_exploitant": "FERME LAITIERE X INC.",47        "Raison_sociale": "CHEZ MAMY",48        "Description_infraction": "EQUIPEMENTS NON PROPRES.",49        "Adresse_lieu_infraction": "714 RANG OUEST SAINT-JEAN-DE-DIEU, (QC) G0L3M0",50        "Type_etablissement": "FERME LAITIERE",51        "Date_infraction": "05/21/2025 00:00:00",52        "Date_jugement": "04/14/2026 00:00:00",53        "Date_publication": "04/17/2026 00:00:00",54        "Amende": "2 000 $",55        "SOC_NOM_LOI": "Loi sur les produits alimentaires",56        "SOC_NOM_ARTCL_INFRC": "INSALUBRITE",57        "SOC_DESC_REGRP_TYP_ENTT": "LAIT",58    },59]606162def _seed_restaurants(con):63    restos = [64        Restaurant(source="osm", external_id="node/1", name="Chez Mamy",65                   address="1999 Rue Sainte-Famille", city="Saguenay",66                   postal_code="G7X 4X5", lat=48.42, lng=-71.06),67        Restaurant(source="osm", external_id="node/2", name="Bella Pizza Resto",68                   address="300 Rue Principale", city="Québec",69                   postal_code="G1K 3Y2", lat=46.81, lng=-71.21),70        # piège : même nom que la condamnation #1 mais dans une AUTRE ville71        Restaurant(source="osm", external_id="node/3", name="Chez Mamy",72                   address="12 Rue Untel", city="Gatineau",73                   postal_code="J8X 1A1", lat=45.47, lng=-75.70),74    ]75    rdb.sync_source(con, "osm", [r.finalize() for r in restos])767778def test_import_croisement_et_antidoublon(con):79    _seed_restaurants(con)80    added = inspections.import_rows(con, RECORDS)81    assert added == 382    # parsing : date ISO, amende numérique, code postal extrait83    row = con.execute("SELECT * FROM inspections WHERE etablissement="84                      "'RESTAURANT CHEZ MAMY'").fetchone()85    assert row["date_jugement"] == "2026-05-19"86    assert row["montant_amende"] == 500.087    assert row["postal_code"] == "G7X4X5"8889    stats = inspections.match(con)90    assert stats["matched_total"] == 291    # #1 : nom+lieu -> le Chez Mamy de SAGUENAY, jamais celui de Gatineau92    assert con.execute("SELECT uid, matched_by FROM inspections WHERE "93                       "etablissement='RESTAURANT CHEZ MAMY'").fetchone()["uid"] \94        == "osm:node/1"95    # #2 : adresse+nom (CP + civique + token « pizza/bella » partagé)96    m2 = con.execute("SELECT uid, matched_by FROM inspections WHERE "97                     "etablissement='PIZZA BELLA'").fetchone()98    assert m2["uid"] == "osm:node/2" and m2["matched_by"] == "adresse+nom"99    # #3 : la ferme laitière homonyme ne matche RIEN (ville et CP différents)100    assert con.execute("SELECT uid FROM inspections WHERE "101                       "exploitant='FERME LAITIERE X INC.'").fetchone()["uid"] is None102103    # résumé conformité écrit dans details.mapaq du resto croisé104    details = json.loads(con.execute(105        "SELECT details FROM restaurants WHERE uid='osm:node/1'")106        .fetchone()["details"])107    assert details["mapaq"]["condamnations"] == 1108    assert details["mapaq"]["total_amendes"] == 500.0109110    # ré-import : aucun doublon111    assert inspections.import_rows(con, RECORDS) == 0112    assert con.execute("SELECT COUNT(*) c FROM inspections").fetchone()["c"] == 3113114115def test_norm_et_core_name():116    n = inspections.norm_name("RESTAURANT CHEZ MAMY INC.")117    assert n == "restaurant chez mamy"118    assert inspections.core_name(n) == "mamy"119    assert inspections.norm_name("Pâtisserie L'Éclair Ltée") == "patisserie l eclair"120