472 lines
25 KiB
PHP
472 lines
25 KiB
PHP
<?php
|
|
/**
|
|
* /api/em/ router — EM endpoints (GODMODE 17avr)
|
|
* Handles: agents-registry, vsm, bpmn-routines, dmaic, kpi/live, poc/start, tenant/bootstrap, plans
|
|
*/
|
|
header("Content-Type: application/json; charset=utf-8");
|
|
header("Access-Control-Allow-Origin: *");
|
|
|
|
$DB_HOST = "127.0.0.1";
|
|
$DB_PORT = 5432;
|
|
$DB_NAME = "adx_system";
|
|
$DB_USER = "admin";
|
|
$DB_PASS = "admin123";
|
|
|
|
try {
|
|
$pdo = new PDO("pgsql:host=$DB_HOST;port=$DB_PORT;dbname=$DB_NAME", $DB_USER, $DB_PASS, [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
|
|
} catch (Exception $e) {
|
|
// Fallback to local if S95 unreachable
|
|
try {
|
|
$pdo = new PDO("pgsql:host=127.0.0.1;port=5432;dbname=adx_system", $DB_USER, $DB_PASS, [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
|
|
} catch (Exception $e2) {
|
|
http_response_code(500);
|
|
echo json_encode(["error" => "db-unreachable"]);
|
|
exit;
|
|
}
|
|
}
|
|
|
|
$uri = parse_url($_SERVER["REQUEST_URI"] ?? "", PHP_URL_PATH);
|
|
$path = preg_replace("#^/api/em/?#", "", $uri);
|
|
$parts = explode("/", trim($path, "/"));
|
|
$endpoint = $parts[0] ?? "";
|
|
|
|
function audit($pdo, $action, $target = null, $payload = []) {
|
|
$tenant = $_GET["tenant"] ?? $_POST["tenant"] ?? "weval";
|
|
try {
|
|
$stmt = $pdo->prepare("INSERT INTO weval.audit_log (tenant_id, actor, action, target, payload, ip) VALUES (?,?,?,?,?,?)");
|
|
$stmt->execute([$tenant, "em-api", $action, $target, json_encode($payload), $_SERVER["REMOTE_ADDR"] ?? ""]);
|
|
} catch (Exception $e) {}
|
|
}
|
|
|
|
switch ($endpoint) {
|
|
|
|
case "agents-registry":
|
|
$tenant = $_GET["tenant"] ?? "weval";
|
|
$dept = $_GET["dept"] ?? null;
|
|
$sql = "SELECT id,name,dept,tier,layer_soa,skills,routines,status,source FROM weval.agent_registry WHERE tenant_id=?";
|
|
$params = [$tenant];
|
|
if ($dept) { $sql .= " AND dept=?"; $params[] = $dept; }
|
|
$sql .= " ORDER BY tier, name";
|
|
$stmt = $pdo->prepare($sql);
|
|
$stmt->execute($params);
|
|
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
foreach ($rows as &$r) {
|
|
$r["skills"] = json_decode($r["skills"], true);
|
|
$r["routines"] = json_decode($r["routines"], true);
|
|
}
|
|
echo json_encode(["tenant" => $tenant, "count" => count($rows), "agents" => $rows]);
|
|
break;
|
|
|
|
case "vsm":
|
|
$tenant = $_GET["tenant"] ?? "weval";
|
|
if (!empty($parts[1])) {
|
|
$stmt = $pdo->prepare("SELECT * FROM weval.vsm_dept WHERE tenant_id=? AND dept_code=?");
|
|
$stmt->execute([$tenant, $parts[1]]);
|
|
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
|
if (!$row) { http_response_code(404); echo json_encode(["error"=>"not-found"]); break; }
|
|
$row["kpis"] = json_decode($row["kpis"], true);
|
|
$row["agents"] = json_decode($row["agents"], true);
|
|
echo json_encode($row);
|
|
} else {
|
|
$stmt = $pdo->prepare("SELECT dept_code, dept_name, icon, supplier, input, process, output, customer, kpis, agents FROM weval.vsm_dept WHERE tenant_id=? ORDER BY id");
|
|
$stmt->execute([$tenant]);
|
|
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
foreach ($rows as &$r) {
|
|
$r["kpis"] = json_decode($r["kpis"], true);
|
|
$r["agents"] = json_decode($r["agents"], true);
|
|
}
|
|
echo json_encode(["tenant"=>$tenant, "count"=>count($rows), "depts"=>$rows]);
|
|
}
|
|
break;
|
|
|
|
case "bpmn-routines":
|
|
$tenant = $_GET["tenant"] ?? "weval";
|
|
$stmt = $pdo->prepare("SELECT id, name, dept, steps, sla_hours, status, mapped_intents FROM weval.bpmn_routines WHERE tenant_id=? ORDER BY id");
|
|
$stmt->execute([$tenant]);
|
|
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
foreach ($rows as &$r) {
|
|
$r["steps"] = json_decode($r["steps"], true);
|
|
$r["mapped_intents"] = json_decode($r["mapped_intents"], true);
|
|
}
|
|
echo json_encode(["tenant"=>$tenant, "count"=>count($rows), "routines"=>$rows]);
|
|
break;
|
|
|
|
case "dmaic":
|
|
$tenant = $parts[1] ?? $_GET["tenant"] ?? "weval";
|
|
$vs = $parts[2] ?? $_GET["vs"] ?? null;
|
|
if ($vs) {
|
|
$stmt = $pdo->prepare("SELECT * FROM weval.dmaic_cycles WHERE tenant_id=? AND vs_id=?");
|
|
$stmt->execute([$tenant, $vs]);
|
|
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
|
echo json_encode($row ?: ["error"=>"not-found"]);
|
|
} else {
|
|
$stmt = $pdo->prepare("SELECT id, vs_id, name, phase, progress, updated_at FROM weval.dmaic_cycles WHERE tenant_id=? ORDER BY id");
|
|
$stmt->execute([$tenant]);
|
|
echo json_encode(["tenant"=>$tenant, "cycles"=>$stmt->fetchAll(PDO::FETCH_ASSOC)]);
|
|
}
|
|
break;
|
|
|
|
case "kpi":
|
|
if (($parts[1] ?? "") === "live") {
|
|
$tenant = $_GET["tenant"] ?? "weval";
|
|
$dept = $_GET["dept"] ?? null;
|
|
$sql = "SELECT DISTINCT ON (dept, kpi_name) dept, kpi_name, value, unit, ts, source FROM weval.kpi_timeseries WHERE tenant_id=?";
|
|
$params = [$tenant];
|
|
if ($dept) { $sql .= " AND dept=?"; $params[] = $dept; }
|
|
$sql .= " ORDER BY dept, kpi_name, ts DESC";
|
|
$stmt = $pdo->prepare($sql);
|
|
$stmt->execute($params);
|
|
echo json_encode(["tenant"=>$tenant, "kpis"=>$stmt->fetchAll(PDO::FETCH_ASSOC)]);
|
|
} else {
|
|
http_response_code(404);
|
|
echo json_encode(["error"=>"unknown-kpi-endpoint"]);
|
|
}
|
|
break;
|
|
|
|
case "poc":
|
|
if (($parts[1] ?? "") === "start") {
|
|
$raw = json_decode(file_get_contents("php://input"), true) ?? $_POST;
|
|
$tenant_id = "poc_" . substr(md5(($raw["name"] ?? "demo") . time()), 0, 8);
|
|
$name = $raw["name"] ?? "POC Demo";
|
|
$email = $raw["email"] ?? "demo@example.com";
|
|
$dept = $raw["dept"] ?? "commerce";
|
|
|
|
try {
|
|
$pdo->prepare("INSERT INTO weval.tenants (tenant_id, name, plan_code, phase, contact_email) VALUES (?,?,?,?,?)")->execute([$tenant_id, $name, "poc", "poc", $email]);
|
|
// Clone the selected dept VSM
|
|
$pdo->prepare("INSERT INTO weval.vsm_dept (tenant_id, dept_code, dept_name, icon, supplier, input, process, output, customer, kpis, agents) SELECT ?, dept_code, dept_name, icon, supplier, input, process, output, customer, kpis, agents FROM weval.vsm_dept WHERE tenant_id='weval' AND dept_code=?")->execute([$tenant_id, $dept]);
|
|
// Create DMAIC cycle
|
|
$pdo->prepare("INSERT INTO weval.dmaic_cycles (tenant_id, vs_id, name, phase) VALUES (?, ?, ?, 'define')")->execute([$tenant_id, $dept . "-poc", "POC $name - $dept VSM"]);
|
|
audit($pdo, "poc_start", $tenant_id, ["email"=>$email, "dept"=>$dept]);
|
|
echo json_encode(["ok"=>true, "tenant_id"=>$tenant_id, "plan"=>"poc", "dept"=>$dept, "brain_center_url"=>"/brain-center-tenant.html?t=$tenant_id", "dmaic_url"=>"/dmaic-workbench.html?t=$tenant_id&vs=$dept-poc", "next_steps"=>["Interview DG","Scan process $dept","DMAIC Define","Baseline KPIs","Rapport"]]);
|
|
} catch (Exception $e) {
|
|
http_response_code(500);
|
|
echo json_encode(["error"=>$e->getMessage()]);
|
|
}
|
|
} else {
|
|
echo json_encode(["endpoints"=>["/api/em/poc/start"]]);
|
|
}
|
|
break;
|
|
|
|
case "plans":
|
|
$stmt = $pdo->query("SELECT plan_code, plan_name, tier, setup_fee, monthly_fee, currency, vs_count, max_users, features FROM weval.em_plans WHERE active=true ORDER BY setup_fee");
|
|
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
foreach ($rows as &$r) $r["features"] = json_decode($r["features"], true);
|
|
echo json_encode(["plans"=>$rows]);
|
|
break;
|
|
|
|
case "tenant":
|
|
if (($parts[1] ?? "") === "bootstrap") {
|
|
$raw = json_decode(file_get_contents("php://input"), true) ?? $_POST;
|
|
$tenant_id = $raw["tenant_id"] ?? "demo_" . time();
|
|
$plan = $raw["plan"] ?? "mvp";
|
|
$name = $raw["name"] ?? "Demo Tenant";
|
|
$email = $raw["email"] ?? "demo@example.com";
|
|
|
|
try {
|
|
$pdo->prepare("INSERT INTO weval.tenants (tenant_id, name, plan_code, phase, contact_email) VALUES (?,?,?,?,?) ON CONFLICT (tenant_id) DO UPDATE SET plan_code=EXCLUDED.plan_code, phase=EXCLUDED.phase")->execute([$tenant_id, $name, $plan, $plan, $email]);
|
|
// Clone all VSM depts for MVP/Enterprise
|
|
if (in_array($plan, ["mvp","enterprise"])) {
|
|
$n = $plan === "enterprise" ? 15 : 5;
|
|
$pdo->prepare("INSERT INTO weval.vsm_dept (tenant_id, dept_code, dept_name, icon, supplier, input, process, output, customer, kpis, agents) SELECT ?, dept_code, dept_name, icon, supplier, input, process, output, customer, kpis, agents FROM weval.vsm_dept WHERE tenant_id='weval' LIMIT ? ON CONFLICT DO NOTHING")->execute([$tenant_id, $n]);
|
|
}
|
|
audit($pdo, "tenant_bootstrap", $tenant_id, ["plan"=>$plan]);
|
|
echo json_encode(["ok"=>true, "tenant_id"=>$tenant_id, "plan"=>$plan, "brain_center_url"=>"/brain-center-tenant.html?t=$tenant_id"]);
|
|
} catch (Exception $e) { http_response_code(500); echo json_encode(["error"=>$e->getMessage()]); }
|
|
} else {
|
|
$stmt = $pdo->query("SELECT tenant_id, name, plan_code, phase, status FROM weval.tenants ORDER BY created_at DESC LIMIT 50");
|
|
echo json_encode(["tenants"=>$stmt->fetchAll(PDO::FETCH_ASSOC)]);
|
|
}
|
|
break;
|
|
|
|
case "audit":
|
|
$tenant = $_GET["tenant"] ?? "weval";
|
|
$limit = min(intval($_GET["limit"] ?? 50), 500);
|
|
$stmt = $pdo->prepare("SELECT actor, action, target, ts FROM weval.audit_log WHERE tenant_id=? ORDER BY ts DESC LIMIT ?");
|
|
$stmt->execute([$tenant, $limit]);
|
|
echo json_encode(["tenant"=>$tenant, "events"=>$stmt->fetchAll(PDO::FETCH_ASSOC)]);
|
|
break;
|
|
|
|
case "erp-connectors":
|
|
$stmt = $pdo->query("SELECT code, name, vendor, protocols, modules, auth_type, status, config_schema FROM weval.erp_connectors WHERE status='available' ORDER BY vendor, name");
|
|
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
foreach ($rows as &$r) {
|
|
$r["protocols"] = json_decode($r["protocols"], true);
|
|
$r["modules"] = json_decode($r["modules"], true);
|
|
$r["config_schema"] = json_decode($r["config_schema"], true);
|
|
}
|
|
echo json_encode(["count" => count($rows), "connectors" => $rows]);
|
|
break;
|
|
|
|
case "ai-providers":
|
|
$stmt = $pdo->query("SELECT code, name, vendor, models, capabilities, endpoint, auth_type, status FROM weval.ai_providers WHERE status='available' ORDER BY vendor, name");
|
|
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
foreach ($rows as &$r) {
|
|
$r["models"] = json_decode($r["models"], true);
|
|
$r["capabilities"] = json_decode($r["capabilities"], true);
|
|
}
|
|
echo json_encode(["count" => count($rows), "providers" => $rows]);
|
|
break;
|
|
|
|
case "industry-templates":
|
|
$sector = $_GET["sector"] ?? null;
|
|
$sql = "SELECT code, name, sector, vsm_depts, kpis, routines, compliance, description FROM weval.industry_templates";
|
|
$params = [];
|
|
if ($sector) { $sql .= " WHERE sector=?"; $params[] = $sector; }
|
|
$sql .= " ORDER BY name";
|
|
$stmt = $pdo->prepare($sql);
|
|
$stmt->execute($params);
|
|
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
foreach ($rows as &$r) {
|
|
$r["vsm_depts"] = json_decode($r["vsm_depts"], true);
|
|
$r["kpis"] = json_decode($r["kpis"], true);
|
|
$r["routines"] = json_decode($r["routines"], true);
|
|
$r["compliance"] = json_decode($r["compliance"], true);
|
|
}
|
|
echo json_encode(["count" => count($rows), "templates" => $rows]);
|
|
break;
|
|
|
|
case "tenant-integrations":
|
|
$tenant = $_GET["tenant"] ?? "weval";
|
|
if (!empty($parts[1]) && $parts[1] === "connect" && $_SERVER["REQUEST_METHOD"] === "POST") {
|
|
$raw = json_decode(file_get_contents("php://input"), true) ?? $_POST;
|
|
$type = $raw["type"] ?? "";
|
|
$code = $raw["code"] ?? "";
|
|
$config = $raw["config"] ?? [];
|
|
$tenant_id = $raw["tenant_id"] ?? $tenant;
|
|
if (!in_array($type, ["erp","ai","industry"])) { http_response_code(400); echo json_encode(["error"=>"invalid-type"]); break; }
|
|
try {
|
|
$pdo->prepare("INSERT INTO weval.tenant_integrations (tenant_id, integration_type, integration_code, config, status) VALUES (?,?,?,?,'active') ON CONFLICT (tenant_id, integration_type, integration_code) DO UPDATE SET config=EXCLUDED.config, status='active'")
|
|
->execute([$tenant_id, $type, $code, json_encode($config)]);
|
|
audit($pdo, "integration_connect", "$tenant_id:$type:$code", ["masked"=>count($config)." keys"]);
|
|
// If industry → apply template (clone VSM depts from template)
|
|
if ($type === "industry") {
|
|
$ts = $pdo->prepare("SELECT vsm_depts FROM weval.industry_templates WHERE code=?");
|
|
$ts->execute([$code]);
|
|
$tpl = $ts->fetch(PDO::FETCH_ASSOC);
|
|
if ($tpl) {
|
|
$depts = json_decode($tpl["vsm_depts"], true) ?? [];
|
|
foreach ($depts as $d) {
|
|
$pdo->prepare("INSERT INTO weval.vsm_dept (tenant_id, dept_code, dept_name, icon, supplier, input, process, output, customer, kpis, agents) SELECT ?, dept_code, dept_name, icon, supplier, input, process, output, customer, kpis, agents FROM weval.vsm_dept WHERE tenant_id='weval' AND dept_code=? ON CONFLICT DO NOTHING")->execute([$tenant_id, $d]);
|
|
}
|
|
}
|
|
}
|
|
echo json_encode(["ok"=>true,"tenant_id"=>$tenant_id,"type"=>$type,"code"=>$code]);
|
|
} catch (Exception $e) { http_response_code(500); echo json_encode(["error"=>$e->getMessage()]); }
|
|
} else {
|
|
$stmt = $pdo->prepare("SELECT ti.tenant_id, ti.integration_type, ti.integration_code, ti.status, ti.created_at FROM weval.tenant_integrations ti WHERE ti.tenant_id=? ORDER BY created_at DESC");
|
|
$stmt->execute([$tenant]);
|
|
echo json_encode(["tenant"=>$tenant, "integrations"=>$stmt->fetchAll(PDO::FETCH_ASSOC)]);
|
|
}
|
|
break;
|
|
|
|
case "scalability":
|
|
// Return overall scalability matrix
|
|
$erp = $pdo->query("SELECT COUNT(*) FROM weval.erp_connectors")->fetchColumn();
|
|
$ai = $pdo->query("SELECT COUNT(*) FROM weval.ai_providers")->fetchColumn();
|
|
$ind = $pdo->query("SELECT COUNT(*) FROM weval.industry_templates")->fetchColumn();
|
|
$ti = $pdo->query("SELECT COUNT(*) FROM weval.tenant_integrations")->fetchColumn();
|
|
echo json_encode([
|
|
"erp_connectors_available" => intval($erp),
|
|
"ai_providers_available" => intval($ai),
|
|
"industry_templates_available" => intval($ind),
|
|
"tenant_integrations_active" => intval($ti),
|
|
"matrix" => ["ERP" => $erp, "AI" => $ai, "Industries" => $ind, "Total_combinations" => $erp * $ai * $ind]
|
|
]);
|
|
break;
|
|
|
|
|
|
case "muda":
|
|
$tenant = $_GET["tenant"] ?? "weval";
|
|
$type = $_GET["type"] ?? null;
|
|
$sql = "SELECT id, vs_id, muda_type, description, severity, impact_hours, impact_euro, status, detected_by, created_at FROM weval.muda_entries WHERE tenant_id=?";
|
|
$params = [$tenant];
|
|
if ($type) { $sql .= " AND muda_type=?"; $params[] = $type; }
|
|
$sql .= " ORDER BY severity DESC, created_at DESC";
|
|
$stmt = $pdo->prepare($sql); $stmt->execute($params);
|
|
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
$total_hours = 0; $total_euro = 0;
|
|
foreach ($rows as $r) { $total_hours += floatval($r["impact_hours"]); $total_euro += floatval($r["impact_euro"]); }
|
|
echo json_encode(["tenant"=>$tenant,"count"=>count($rows),"total_impact_hours"=>$total_hours,"total_impact_euro"=>$total_euro,"entries"=>$rows]);
|
|
break;
|
|
|
|
case "poka-yoke":
|
|
$tenant = $_GET["tenant"] ?? "weval";
|
|
$stmt = $pdo->prepare("SELECT id, process, failure_mode, device_type, mechanism, validation, status, efficiency_pct FROM weval.poka_yoke WHERE tenant_id=? ORDER BY efficiency_pct DESC");
|
|
$stmt->execute([$tenant]);
|
|
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
$avg_eff = count($rows) ? array_sum(array_column($rows, "efficiency_pct")) / count($rows) : 0;
|
|
echo json_encode(["tenant"=>$tenant,"count"=>count($rows),"avg_efficiency_pct"=>round($avg_eff,1),"devices"=>$rows]);
|
|
break;
|
|
|
|
case "kaizen":
|
|
$tenant = $_GET["tenant"] ?? "weval";
|
|
$stmt = $pdo->prepare("SELECT id, title, dept, problem, baseline, target, actual, savings_hours, savings_euro, team, duration_days, status FROM weval.kaizen_events WHERE tenant_id=? ORDER BY created_at DESC");
|
|
$stmt->execute([$tenant]);
|
|
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
foreach ($rows as &$r) {
|
|
$r["baseline"] = json_decode($r["baseline"], true);
|
|
$r["target"] = json_decode($r["target"], true);
|
|
$r["actual"] = json_decode($r["actual"], true);
|
|
}
|
|
$total_savings_euro = array_sum(array_column($rows, "savings_euro"));
|
|
echo json_encode(["tenant"=>$tenant,"count"=>count($rows),"total_savings_euro"=>$total_savings_euro,"events"=>$rows]);
|
|
break;
|
|
|
|
case "gemba":
|
|
$tenant = $_GET["tenant"] ?? "weval";
|
|
$stmt = $pdo->prepare("SELECT id, location, walker, observations, actions, muda_spotted, walk_duration_min, created_at FROM weval.gemba_walks WHERE tenant_id=? ORDER BY created_at DESC");
|
|
$stmt->execute([$tenant]);
|
|
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
foreach ($rows as &$r) {
|
|
$r["observations"] = json_decode($r["observations"], true);
|
|
$r["actions"] = json_decode($r["actions"], true);
|
|
}
|
|
echo json_encode(["tenant"=>$tenant,"count"=>count($rows),"walks"=>$rows]);
|
|
break;
|
|
|
|
case "pdca":
|
|
$tenant = $_GET["tenant"] ?? "weval";
|
|
$stmt = $pdo->prepare("SELECT id, title, phase, kpi_name, baseline, target, actual, created_at FROM weval.pdca_cycles WHERE tenant_id=? ORDER BY created_at DESC");
|
|
$stmt->execute([$tenant]);
|
|
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
echo json_encode(["tenant"=>$tenant,"count"=>count($rows),"cycles"=>$rows]);
|
|
break;
|
|
|
|
case "andon":
|
|
$tenant = $_GET["tenant"] ?? "weval";
|
|
$status = $_GET["status"] ?? null;
|
|
$sql = "SELECT id, station, severity, message, status, triggered_by, resolved_by, resolution_time_min, created_at, resolved_at FROM weval.andon_alerts WHERE tenant_id=?";
|
|
$params = [$tenant];
|
|
if ($status) { $sql .= " AND status=?"; $params[] = $status; }
|
|
$sql .= " ORDER BY created_at DESC LIMIT 100";
|
|
$stmt = $pdo->prepare($sql); $stmt->execute($params);
|
|
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
$open = count(array_filter($rows, fn($r)=>$r["status"]==="open"));
|
|
echo json_encode(["tenant"=>$tenant,"count"=>count($rows),"open"=>$open,"alerts"=>$rows]);
|
|
break;
|
|
|
|
case "five-s":
|
|
$tenant = $_GET["tenant"] ?? "weval";
|
|
$stmt = $pdo->prepare("SELECT id, area, seiri, seiton, seiso, seiketsu, shitsuke, total_score, auditor, notes, created_at FROM weval.five_s_audits WHERE tenant_id=? ORDER BY created_at DESC");
|
|
$stmt->execute([$tenant]);
|
|
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
$avg = count($rows) ? array_sum(array_column($rows, "total_score")) / count($rows) : 0;
|
|
echo json_encode(["tenant"=>$tenant,"count"=>count($rows),"avg_score"=>round($avg,1),"max_score"=>25,"audits"=>$rows]);
|
|
break;
|
|
|
|
case "a3":
|
|
$tenant = $_GET["tenant"] ?? "weval";
|
|
$stmt = $pdo->prepare("SELECT id, title, background, current_state, target_state, gap_analysis, root_causes, countermeasures, owner, status, created_at FROM weval.a3_reports WHERE tenant_id=? ORDER BY created_at DESC");
|
|
$stmt->execute([$tenant]);
|
|
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
foreach ($rows as &$r) {
|
|
$r["root_causes"] = json_decode($r["root_causes"], true);
|
|
$r["countermeasures"] = json_decode($r["countermeasures"], true);
|
|
}
|
|
echo json_encode(["tenant"=>$tenant,"count"=>count($rows),"reports"=>$rows]);
|
|
break;
|
|
|
|
case "lean6sigma-dashboard":
|
|
$tenant = $_GET["tenant"] ?? "weval";
|
|
$muda = $pdo->prepare("SELECT COUNT(*) as c, SUM(impact_hours) as h, SUM(impact_euro) as e FROM weval.muda_entries WHERE tenant_id=?");
|
|
$muda->execute([$tenant]);
|
|
$m = $muda->fetch(PDO::FETCH_ASSOC);
|
|
$poka = $pdo->prepare("SELECT COUNT(*) as c, AVG(efficiency_pct) as avg FROM weval.poka_yoke WHERE tenant_id=? AND status='active'");
|
|
$poka->execute([$tenant]);
|
|
$p = $poka->fetch(PDO::FETCH_ASSOC);
|
|
$kaizen = $pdo->prepare("SELECT COUNT(*) as c, SUM(savings_euro) as saved FROM weval.kaizen_events WHERE tenant_id=?");
|
|
$kaizen->execute([$tenant]);
|
|
$k = $kaizen->fetch(PDO::FETCH_ASSOC);
|
|
$andon_open = $pdo->prepare("SELECT COUNT(*) FROM weval.andon_alerts WHERE tenant_id=? AND status='open'");
|
|
$andon_open->execute([$tenant]);
|
|
$five_s_avg = $pdo->prepare("SELECT AVG(total_score) FROM weval.five_s_audits WHERE tenant_id=?");
|
|
$five_s_avg->execute([$tenant]);
|
|
$pdca_active = $pdo->prepare("SELECT COUNT(*) FROM weval.pdca_cycles WHERE tenant_id=? AND phase != 'act'");
|
|
$pdca_active->execute([$tenant]);
|
|
$a3_open = $pdo->prepare("SELECT COUNT(*) FROM weval.a3_reports WHERE tenant_id=? AND status IN ('draft','in-progress')");
|
|
$a3_open->execute([$tenant]);
|
|
$gemba = $pdo->prepare("SELECT COUNT(*), SUM(muda_spotted) FROM weval.gemba_walks WHERE tenant_id=?");
|
|
$gemba->execute([$tenant]);
|
|
$g = $gemba->fetch(PDO::FETCH_NUM);
|
|
|
|
$five_s_val = floatval($five_s_avg->fetchColumn() ?? 0);
|
|
$andon_o = intval($andon_open->fetchColumn());
|
|
$pdca_a = intval($pdca_active->fetchColumn());
|
|
$a3_o = intval($a3_open->fetchColumn());
|
|
echo json_encode([
|
|
"tenant" => $tenant,
|
|
"muda" => ["count"=>intval($m["c"]),"impact_hours"=>floatval($m["h"]),"impact_euro"=>floatval($m["e"])],
|
|
"poka_yoke" => ["count"=>intval($p["c"]),"avg_efficiency_pct"=>round(floatval($p["avg"]),1)],
|
|
"kaizen" => ["count"=>intval($k["c"]),"total_savings_euro"=>floatval($k["saved"])],
|
|
"andon_open" => $andon_o,
|
|
"five_s_avg_score" => round(floatval($five_s_val),1),
|
|
"pdca_active" => $pdca_a,
|
|
"a3_open" => $a3_o,
|
|
"gemba" => ["walks"=>intval($g[0]),"muda_spotted"=>intval($g[1])],
|
|
"maturity_score" => round((min(25, floatval($five_s_val ?? 0))/25 * 30) + (min(100, floatval($p["avg"] ?? 0))/100 * 30) + (min(10, intval($k["c"]))/10 * 20) + (min(5, intval($g[0]))/5 * 20), 1)
|
|
]);
|
|
break;
|
|
|
|
|
|
case "universal-connectors":
|
|
$cat = $_GET["category"] ?? null;
|
|
$search = $_GET["q"] ?? null;
|
|
$sql = "SELECT connector_code, connector_name, category, auth_type, base_url, docs_url, webhook_support, realtime_support, status, use_cases FROM weval.universal_connectors WHERE 1=1";
|
|
$params = [];
|
|
if ($cat) { $sql .= " AND category=?"; $params[] = $cat; }
|
|
if ($search) { $sql .= " AND (connector_name ILIKE ? OR connector_code ILIKE ?)"; $params[] = "%$search%"; $params[] = "%$search%"; }
|
|
$sql .= " ORDER BY category, connector_name";
|
|
$stmt = $pdo->prepare($sql); $stmt->execute($params);
|
|
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
foreach ($rows as &$r) $r["use_cases"] = json_decode($r["use_cases"] ?? "[]", true);
|
|
$categories = $pdo->query("SELECT category, COUNT(*) as c FROM weval.universal_connectors GROUP BY category ORDER BY c DESC")->fetchAll(PDO::FETCH_ASSOC);
|
|
echo json_encode(["total"=>count($rows), "by_category"=>$categories, "connectors"=>$rows]);
|
|
break;
|
|
|
|
case "universal-stats":
|
|
$stats = [];
|
|
$stats["total"] = (int)$pdo->query("SELECT COUNT(*) FROM weval.universal_connectors")->fetchColumn();
|
|
$stats["by_category"] = $pdo->query("SELECT category, COUNT(*) as c FROM weval.universal_connectors GROUP BY category ORDER BY c DESC")->fetchAll(PDO::FETCH_ASSOC);
|
|
$stats["by_auth"] = $pdo->query("SELECT auth_type, COUNT(*) as c FROM weval.universal_connectors GROUP BY auth_type ORDER BY c DESC")->fetchAll(PDO::FETCH_ASSOC);
|
|
$stats["webhook_enabled"] = (int)$pdo->query("SELECT COUNT(*) FROM weval.universal_connectors WHERE webhook_support=true")->fetchColumn();
|
|
$stats["realtime_enabled"] = (int)$pdo->query("SELECT COUNT(*) FROM weval.universal_connectors WHERE realtime_support=true")->fetchColumn();
|
|
echo json_encode($stats);
|
|
break;
|
|
|
|
|
|
default:
|
|
echo json_encode([
|
|
"service" => "WEVIA EM API",
|
|
"version" => "1.0-godmode-17avr",
|
|
"endpoints" => [
|
|
"/api/em/agents-registry?tenant=weval&dept=?",
|
|
"/api/em/vsm?tenant=weval (list) or /api/em/vsm/{dept}",
|
|
"/api/em/bpmn-routines?tenant=weval",
|
|
"/api/em/dmaic/{tenant}/{vs_id}",
|
|
"/api/em/kpi/live?tenant=weval&dept=?",
|
|
"/api/em/poc/start (POST)",
|
|
"/api/em/plans",
|
|
"/api/em/tenant/bootstrap (POST)",
|
|
"/api/em/audit?tenant=weval",
|
|
"/api/em/erp-connectors",
|
|
"/api/em/ai-providers",
|
|
"/api/em/industry-templates?sector=?",
|
|
"/api/em/tenant-integrations?tenant=X",
|
|
"POST /api/em/tenant-integrations/connect",
|
|
"/api/em/scalability",
|
|
"/api/em/muda?tenant=&type=",
|
|
"/api/em/poka-yoke?tenant=",
|
|
"/api/em/kaizen?tenant=",
|
|
"/api/em/gemba?tenant=",
|
|
"/api/em/pdca?tenant=",
|
|
"/api/em/andon?tenant=&status=",
|
|
"/api/em/five-s?tenant=",
|
|
"/api/em/a3?tenant=",
|
|
"/api/em/lean6sigma-dashboard?tenant=",
|
|
"/api/em/universal-connectors?category=&q=",
|
|
"/api/em/universal-stats"
|
|
]
|
|
]);
|
|
}
|