189 lines
4.9 KiB
Python
Executable File
189 lines
4.9 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
import os
|
|
import time
|
|
import sys
|
|
import xmlrpc.client
|
|
from pathlib import Path
|
|
from datetime import datetime
|
|
|
|
MACHINE_MAP = {
|
|
"CORT-00": "Cortadora 0",
|
|
"CORT-01": "Cortadora 01",
|
|
"CORT-02": "Cortadora 02",
|
|
}
|
|
|
|
WATCH_STATES = ["waiting", "ready", "progress"]
|
|
|
|
|
|
def read_env(path=".env"):
|
|
env = {}
|
|
p = Path(path)
|
|
for raw in p.read_text().splitlines():
|
|
line = raw.strip()
|
|
if not line or line.startswith("#") or "=" not in line:
|
|
continue
|
|
k, v = line.split("=", 1)
|
|
env[k.strip()] = v.strip().strip('"').strip("'")
|
|
return env
|
|
|
|
|
|
def existing_fields(models, db, uid, password, model, wanted):
|
|
fields = models.execute_kw(
|
|
db, uid, password,
|
|
model, "fields_get",
|
|
[],
|
|
{"attributes": ["string", "type"]},
|
|
)
|
|
return [f for f in wanted if f in fields]
|
|
|
|
|
|
def search_read(models, db, uid, password, model, domain, fields, limit=50, order="id desc"):
|
|
valid_fields = existing_fields(models, db, uid, password, model, fields)
|
|
return models.execute_kw(
|
|
db, uid, password,
|
|
model, "search_read",
|
|
[domain],
|
|
{
|
|
"fields": valid_fields,
|
|
"limit": limit,
|
|
"order": order,
|
|
},
|
|
)
|
|
|
|
|
|
def m2o_name(value):
|
|
if isinstance(value, list) and len(value) >= 2:
|
|
return value[1]
|
|
return None
|
|
|
|
|
|
def connect():
|
|
env = read_env()
|
|
|
|
url = env["ODOO_URL"].rstrip("/")
|
|
db = os.getenv("ODOO_DB_OVERRIDE") or env["ODOO_DB"]
|
|
user = env["ODOO_USER"]
|
|
password = env["ODOO_PASSWORD"]
|
|
|
|
common = xmlrpc.client.ServerProxy(f"{url}/xmlrpc/2/common")
|
|
uid = common.authenticate(db, user, password, {})
|
|
if not uid:
|
|
raise RuntimeError("Autenticación Odoo fallida")
|
|
|
|
models = xmlrpc.client.ServerProxy(f"{url}/xmlrpc/2/object")
|
|
return url, db, user, password, uid, models
|
|
|
|
|
|
def print_state(models, db, uid, password):
|
|
print()
|
|
print("=" * 100)
|
|
print(datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
|
|
print("=" * 100)
|
|
|
|
for machine_id, wc_name in MACHINE_MAP.items():
|
|
workcenters = search_read(
|
|
models, db, uid, password,
|
|
"mrp.workcenter",
|
|
[("name", "=", wc_name)],
|
|
["id", "name", "active", "display_name"],
|
|
limit=5,
|
|
order="id asc",
|
|
)
|
|
|
|
if not workcenters:
|
|
print(f"{machine_id} | {wc_name} | ERROR: no existe centro de trabajo")
|
|
continue
|
|
|
|
wc = workcenters[0]
|
|
wc_id = wc["id"]
|
|
|
|
workorders = search_read(
|
|
models, db, uid, password,
|
|
"mrp.workorder",
|
|
[
|
|
("workcenter_id", "=", wc_id),
|
|
("state", "in", WATCH_STATES),
|
|
],
|
|
[
|
|
"id",
|
|
"name",
|
|
"state",
|
|
"workcenter_id",
|
|
"production_id",
|
|
"product_id",
|
|
"date_start",
|
|
"date_finished",
|
|
"qty_production",
|
|
],
|
|
limit=100,
|
|
order="id desc",
|
|
)
|
|
|
|
by_state = {s: [] for s in WATCH_STATES}
|
|
for wo in workorders:
|
|
by_state.setdefault(wo.get("state"), []).append(wo)
|
|
|
|
progress = by_state.get("progress", [])
|
|
ready = by_state.get("ready", [])
|
|
waiting = by_state.get("waiting", [])
|
|
|
|
if len(progress) == 1:
|
|
beacon_state = "AZUL_FIJO_CANDIDATO"
|
|
elif len(progress) > 1:
|
|
beacon_state = "INCOHERENTE_MULTIPLES_PROGRESS"
|
|
else:
|
|
beacon_state = "SIN_ORDEN_CARGADA"
|
|
|
|
print(
|
|
f"{machine_id} | {wc_name} | "
|
|
f"waiting={len(waiting)} ready={len(ready)} progress={len(progress)} | "
|
|
f"{beacon_state}"
|
|
)
|
|
|
|
for wo in progress:
|
|
print(
|
|
f" ACTIVE progress: "
|
|
f"wo_id={wo.get('id')} "
|
|
f"mo={m2o_name(wo.get('production_id'))} "
|
|
f"product={m2o_name(wo.get('product_id'))} "
|
|
f"date_start={wo.get('date_start')}"
|
|
)
|
|
|
|
if not progress and ready:
|
|
first = ready[0]
|
|
print(
|
|
f" primera ready: "
|
|
f"wo_id={first.get('id')} "
|
|
f"mo={m2o_name(first.get('production_id'))} "
|
|
f"product={m2o_name(first.get('product_id'))}"
|
|
)
|
|
|
|
|
|
def main():
|
|
watch = False
|
|
interval = 2.0
|
|
|
|
if "--watch" in sys.argv:
|
|
watch = True
|
|
idx = sys.argv.index("--watch")
|
|
if len(sys.argv) > idx + 1:
|
|
interval = float(sys.argv[idx + 1])
|
|
|
|
url, db, user, password, uid, models = connect()
|
|
|
|
print(f"ODOO_URL={url}")
|
|
print(f"ODOO_DB={db}")
|
|
print(f"ODOO_USER={user}")
|
|
print(f"uid={uid}")
|
|
|
|
if watch:
|
|
while True:
|
|
print_state(models, db, uid, password)
|
|
time.sleep(interval)
|
|
else:
|
|
print_state(models, db, uid, password)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|