update
This commit is contained in:
parent
e3872cac5f
commit
2b39ba6324
11 changed files with 352 additions and 3 deletions
62
docs/logiche.md
Normal file
62
docs/logiche.md
Normal 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
BIN
main.db
Normal file
Binary file not shown.
BIN
main.db.wal
Normal file
BIN
main.db.wal
Normal file
Binary file not shown.
158
marimo/database_creation.py
Normal file
158
marimo/database_creation.py
Normal 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()
|
||||||
|
|
@ -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
32
marimo/debug_cosing.py
Normal 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()
|
||||||
|
|
@ -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"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
6
src/pif_compiler/functions/orders.py
Normal file
6
src/pif_compiler/functions/orders.py
Normal 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()
|
||||||
14
src/pif_compiler/services/srv_cir.py
Normal file
14
src/pif_compiler/services/srv_cir.py
Normal 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)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Loading…
Reference in a new issue