This commit is contained in:
adish-rmr 2026-01-13 22:20:56 +01:00
parent e3872cac5f
commit 2b39ba6324
11 changed files with 352 additions and 3 deletions

62
docs/logiche.md Normal file
View file

@ -0,0 +1,62 @@
1)
dati lista ingrediente:
- informazioni anagrafiche
- tipo > automatica associazione a esposizione, se non c'è ritorna errore
- associazione cas-inci, identificazione AQUA
- aggiungere 5 cifre decimali nelle percentuali
- CAS multipli vanno spacchettati in mini loop
va separato input da dict ingredients
Se informazioni anagrafiche hanno senso (validatore esiste, tipo cosmetico esiste) > aggiungi a Mongo.
Viene arricchito subito con informazioni da Cosing, aggiunte chiavi:
- INCI
- Tox : {NOAEL: (val, fonte), LD50, LOAEL}
- Tox Resources
- CosIng: Restrizioni, Uso : lista, Sostanze identificate
- DAP {}
- Esposizione
- Riassunto, completo si/no
- Stato
Funzione che va a verificare se tutto queste siano complete anche solo parzialmente per ogni ingrediente, viene fatto un riassunto dei dati trovati
2)
generazione excel partendo da questo dato
Processo:
1.
- Input arriva grezzo
- va caricato su mongodb, restituisce _id
Trovo ID delle info anagrafiche:
- Cliente
- Compilatore
- Tipo
- Creo un file progetto, restituisce _id
Inserisco il record su DB
-- STATO 0 --
2.
Faccio una verifica per vedere quanti dati pronti per essere elaborati
prendo il più vecchio
L'entità ha l'ordine e il progetto, recupero i due file
1. Va a cercare su CosIng
- Match relativo INCI
- Prende Restrizioni, Uso, Sostanze identificate
4. Calcolo SED
2. Va a pescare Dati DAP
5. Calcolo DAP
3. Va a cercare Echa
- orchestrator echa
- Pulizia e ricerca dei dati essenziali (NOAEL e link)
Per ognuno orchestrator > pulizia > identifico NOAEL

BIN
main.db Normal file

Binary file not shown.

BIN
main.db.wal Normal file

Binary file not shown.

158
marimo/database_creation.py Normal file
View file

@ -0,0 +1,158 @@
import marimo
__generated_with = "0.16.5"
app = marimo.App(width="medium")
@app.cell
def _():
import marimo as mo
import duckdb
return duckdb, mo
@app.cell
def _(duckdb):
con = duckdb.connect('main.db')
return (con,)
@app.cell
def _(con, mo):
_df = mo.sql(
f"""
--CREATE SEQUENCE seq_clienti START 1;
--CREATE SEQUENCE seq_compilatori START 1;
--CREATE SEQUENCE seq_tipi_prodotti START 1;
--CREATE SEQUENCE seq_stati_ordini START 1;
--CREATE SEQUENCE seq_ordini START 1;
""",
engine=con
)
return
@app.cell
def _(con, mo):
_df = mo.sql(
f"""
CREATE OR REPLACE TABLE clienti (
nome_cliente VARCHAR UNIQUE,
id_cliente INTEGER PRIMARY KEY DEFAULT NEXTVAL('seq_clienti')
)
""",
engine=con
)
return
@app.cell
def _(con, mo):
_df = mo.sql(
f"""
CREATE OR REPLACE TABLE compilatori (
nome_compilatore VARCHAR UNIQUE,
id_compilatore INTEGER PRIMARY KEY DEFAULT NEXTVAL('seq_compilatori')
)
""",
engine=con
)
return
@app.cell
def _(con, mo):
_df = mo.sql(
f"""
CREATE OR REPLACE TABLE tipi_prodotti (
nome_tipo VARCHAR UNIQUE,
id_tipo INTEGER PRIMARY KEY DEFAULT NEXTVAL('seq_tipi_prodotti'),
luogo_applicazione VARCHAR,
espo_primaria VARCHAR,
espo_secondaria VARCHAR,
espo_nano VARCHAR,
supericie_cm2 INT,
frequenza INT,
qty_daily_stimata INT,
qty_daily_relativa INT,
ritenzione FLOAT,
espo_daily_calcolata INT,
espo_daily_relativa_calcolata INT,
peso INT,
target VARCHAR
)
""",
engine=con
)
return
@app.cell
def _(con, mo):
_df = mo.sql(
f"""
CREATE OR REPLACE TABLE stati_ordini (
id_stato INTEGER PRIMARY KEY DEFAULT NEXTVAL('seq_stati_ordini'),
nome_stato VARCHAR
)
""",
engine=con
)
return (stati_ordini,)
@app.cell
def _(con, mo):
_df = mo.sql(
f"""
CREATE OR REPLACE TABLE ordini (
id_ordine INTEGER PRIMARY KEY DEFAULT NEXTVAL('seq_ordini'),
id_cliente INTEGER,
id_compilatore INTEGER,
id_tipo_prodotto INTEGER,
uuid_ordine VARCHAR NOT NULL,
uuid_progetto VARCHAR,
data_ordine DATETIME NOT NULL,
stato_ordine INTEGER DEFAULT 0,
note VARCHAR,
FOREIGN KEY (id_cliente) REFERENCES clienti(id_cliente),
FOREIGN KEY (id_compilatore) REFERENCES compilatori(id_compilatore),
FOREIGN KEY (id_tipo_prodotto) REFERENCES tipi_prodotti(id_tipo),
FOREIGN KEY (stato_ordine) REFERENCES stati_ordini(id_stato)
)
""",
engine=con
)
return
@app.cell
def _(con, mo):
_df = mo.sql(
f"""
""",
engine=con
)
return
@app.cell
def _(con, mo, stati_ordini):
_df = mo.sql(
f"""
INSERT INTO stati_ordini (nome_stato) VALUES (
'Ordine registrato',
''
)
""",
engine=con
)
return
if __name__ == "__main__":
app.run()

View file

@ -18,7 +18,7 @@ def _():
@app.cell @app.cell
def _(): def _():
cas = '102-71-6' cas = '63148-62-9'
return (cas,) return (cas,)

32
marimo/debug_cosing.py Normal file
View file

@ -0,0 +1,32 @@
import marimo
__generated_with = "0.16.5"
app = marimo.App(width="medium")
@app.cell
def _():
import marimo as mo
return
@app.cell
def _():
from pif_compiler.services.srv_cosing import cosing_search
return (cosing_search,)
@app.cell
def _():
cas = ' 9006-65-9 '
return (cas,)
@app.cell
def _(cas, cosing_search):
cosing_search(cas, mode='cas')
return
if __name__ == "__main__":
app.run()

View file

@ -6,6 +6,7 @@ import os
from pif_compiler.functions.common_func import generate_pdf from pif_compiler.functions.common_func import generate_pdf
from pif_compiler.services.srv_pubchem import pubchem_dap from pif_compiler.services.srv_pubchem import pubchem_dap
from pif_compiler.services.srv_cir import search_ingredient
from pif_compiler.functions.common_log import get_logger from pif_compiler.functions.common_log import get_logger
logger = get_logger() logger = get_logger()
@ -203,6 +204,71 @@ async def search_pubchem(request: PubchemRequest):
) )
class CirSearchRequest(BaseModel):
text: str = Field(..., description="Text to search for in the CIR database")
class Config:
json_schema_extra = {
"example": {
"text": "olio di argan"
}
}
class CirSearchResponse(BaseModel):
success: bool
text: str
results: Optional[list] = None
count: Optional[int] = None
error: Optional[str] = None
@router.post("/common/cir-search", response_model=CirSearchResponse, tags=["Common"])
async def cir_search_endpoint(request: CirSearchRequest):
"""
Search for ingredients in the CIR (Cosmetic Ingredient Review) database.
This endpoint searches the CIR NOAEL database for ingredients matching
the provided text query.
Args:
request: CirSearchRequest containing the search text
Returns:
CirSearchResponse with the search results or error information
"""
logger.info(f"API request received for CIR search: text='{request.text}'")
try:
results = search_ingredient(request.text)
if results is None:
logger.error(f"CIR search returned None for text: {request.text}")
return CirSearchResponse(
success=False,
text=request.text,
results=None,
count=0,
error="An error occurred while searching the CIR database. Please check the logs for details."
)
logger.info(f"Successfully retrieved {len(results)} results from CIR database for text: {request.text}")
return CirSearchResponse(
success=True,
text=request.text,
results=results,
count=len(results),
error=None
)
except Exception as e:
logger.error(f"Error processing CIR search request for text '{request.text}': {str(e)}", exc_info=True)
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"Internal error while processing CIR search request: {str(e)}"
)
@router.get("/common/health", tags=["Common"]) @router.get("/common/health", tags=["Common"])
async def common_health_check(): async def common_health_check():
""" """
@ -217,6 +283,10 @@ async def common_health_check():
"api": "operational", "api": "operational",
"logging": "operational", "logging": "operational",
"utilities": "operational", "utilities": "operational",
"pubchem": "operational" "pubchem": "operational",
"cir": "operational"
} }
} }

View file

@ -1,8 +1,11 @@
from playwright.async_api import async_playwright from playwright.async_api import async_playwright
import os import os
from pymongo import MongoClient
from pif_compiler.functions.common_log import get_logger from pif_compiler.functions.common_log import get_logger
log = get_logger() log = get_logger()
async def generate_pdf(link: str, name: str): async def generate_pdf(link: str, name: str):
@ -89,4 +92,8 @@ async def generate_pdf(link: str, name: str):
except Exception as e: except Exception as e:
log.error(f"Error generating PDF for {name}: {str(e)}", exc_info=True) log.error(f"Error generating PDF for {name}: {str(e)}", exc_info=True)
return False return False

View file

@ -0,0 +1,6 @@
from pymongo import MongoClient
from pif_compiler.functions.common_log import get_logger
from pif_compiler.functions.db_utils import db_connect
log = get_logger()

View file

@ -0,0 +1,14 @@
from pif_compiler.functions.common_log import get_logger
from pif_compiler.functions.db_utils import db_connect
log = get_logger()
def search_ingredient(text):
col = db_connect(db_name="cir", collection_name="noael")
col.create_index([("ingrediente", "text")])
log.info(f"Searching for ingredient in CIR database: {text}")
risultati = col.find({ "$text": { "$search": text } })
return list(risultati)