171 lines
4.5 KiB
Python
Executable File
171 lines
4.5 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
import os
|
|
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",
|
|
}
|
|
|
|
WORKORDER_STATES = ["waiting", "ready", "progress", "done"]
|
|
|
|
|
|
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=20, order="id asc"):
|
|
fields = existing_fields(models, db, uid, password, model, fields)
|
|
return models.execute_kw(
|
|
db, uid, password,
|
|
model, "search_read",
|
|
[domain],
|
|
{"fields": fields, "limit": limit, "order": order},
|
|
)
|
|
|
|
|
|
def main():
|
|
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"]
|
|
|
|
print("ODOO_URL =", url)
|
|
print("ODOO_DB =", db)
|
|
print("ODOO_USER=", user)
|
|
print()
|
|
|
|
common = xmlrpc.client.ServerProxy(f"{url}/xmlrpc/2/common")
|
|
uid = common.authenticate(db, user, password, {})
|
|
if not uid:
|
|
raise SystemExit("ERROR: autenticación Odoo fallida")
|
|
|
|
print("uid =", uid)
|
|
print()
|
|
|
|
models = xmlrpc.client.ServerProxy(f"{url}/xmlrpc/2/object")
|
|
|
|
wc_fields = existing_fields(
|
|
models, db, uid, password,
|
|
"mrp.workcenter",
|
|
["id", "name", "code", "active", "display_name"],
|
|
)
|
|
|
|
wo_fields = existing_fields(
|
|
models, db, uid, password,
|
|
"mrp.workorder",
|
|
[
|
|
"id",
|
|
"name",
|
|
"state",
|
|
"workcenter_id",
|
|
"production_id",
|
|
"product_id",
|
|
"date_start",
|
|
"date_finished",
|
|
"duration_expected",
|
|
"duration",
|
|
"qty_production",
|
|
],
|
|
)
|
|
|
|
print("Campos workcenter disponibles:", wc_fields)
|
|
print("Campos workorder disponibles :", wo_fields)
|
|
print()
|
|
|
|
for machine_id, wc_name in MACHINE_MAP.items():
|
|
print("=" * 80)
|
|
print(f"{machine_id} -> {wc_name}")
|
|
|
|
workcenters = search_read(
|
|
models, db, uid, password,
|
|
"mrp.workcenter",
|
|
[("name", "=", wc_name)],
|
|
["id", "name", "code", "active", "display_name"],
|
|
limit=5,
|
|
order="id asc",
|
|
)
|
|
|
|
if not workcenters:
|
|
print("ERROR: no se encuentra centro de trabajo exacto")
|
|
continue
|
|
|
|
if len(workcenters) > 1:
|
|
print("AVISO: hay más de un centro exacto")
|
|
|
|
wc = workcenters[0]
|
|
wc_id = wc["id"]
|
|
print("Workcenter:", wc)
|
|
|
|
workorders = search_read(
|
|
models, db, uid, password,
|
|
"mrp.workorder",
|
|
[
|
|
("workcenter_id", "=", wc_id),
|
|
("state", "in", WORKORDER_STATES),
|
|
],
|
|
[
|
|
"id",
|
|
"name",
|
|
"state",
|
|
"workcenter_id",
|
|
"production_id",
|
|
"product_id",
|
|
"date_start",
|
|
"date_finished",
|
|
"duration_expected",
|
|
"duration",
|
|
"qty_production",
|
|
],
|
|
limit=20,
|
|
order="id desc",
|
|
)
|
|
|
|
if not workorders:
|
|
print("Sin workorders candidatas")
|
|
continue
|
|
|
|
print(f"Workorders candidatas: {len(workorders)}")
|
|
for wo in workorders:
|
|
print(
|
|
" -",
|
|
{
|
|
"id": wo.get("id"),
|
|
"name": wo.get("name"),
|
|
"state": wo.get("state"),
|
|
"production_id": wo.get("production_id"),
|
|
"product_id": wo.get("product_id"),
|
|
"date_start": wo.get("date_start"),
|
|
"date_finished": wo.get("date_finished"),
|
|
"qty_production": wo.get("qty_production"),
|
|
},
|
|
)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|