feat(CC-087): add ERP main page (entity sync table, setup steps, arch restriction warning)
This commit is contained in:
parent
a773675f25
commit
0153cdfbb3
1 changed files with 89 additions and 0 deletions
89
src/app/dashboard/erp/page.tsx
Normal file
89
src/app/dashboard/erp/page.tsx
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
'use client';
|
||||
|
||||
import Link from 'next/link';
|
||||
|
||||
const ERP_ENTITIES = [
|
||||
{ name: 'Clienți (Customer)', dir: '→', desc: 'ERPNext → CEO OS (sync unilateral)' },
|
||||
{ name: 'Facturi (Invoice)', dir: '→', desc: 'ERPNext → CEO OS (tranzacții financiare)' },
|
||||
{ name: 'Proiecte (Project)', dir: '↔', desc: 'Bidirectional cu aprobare manuală' },
|
||||
{ name: 'Stoc (Item)', dir: '→', desc: 'ERPNext → CEO OS (read-only)' },
|
||||
{ name: 'Salarii (Salary Slip)', dir: '→', desc: 'ERPNext → CEO OS (privat, confidential)' },
|
||||
{ name: 'Contracte (PO/SO)', dir: '→', desc: 'ERPNext → CEO OS (ca documente)' },
|
||||
];
|
||||
|
||||
const SETUP_STEPS = [
|
||||
{ n: 1, label: 'ERPNext server activ', status: 'done', desc: 'ERPNext rulează pe serverul Hetzner (port 8080).' },
|
||||
{ n: 2, label: 'API Key ERPNext', status: 'todo', desc: 'Generează API Key + Secret în ERPNext → User → API Access.' },
|
||||
{ n: 3, label: 'Adapter ceo-api', status: 'todo', desc: 'Serviciu ERP sync în ceo-api (GET /v1/erp/status, POST /v1/erp/sync).' },
|
||||
{ n: 4, label: 'Flux date activ', status: 'planned', desc: 'Sincronizare automată la intervale configurabile.' },
|
||||
];
|
||||
|
||||
export default function ERPPage() {
|
||||
return (
|
||||
<div className="max-w-3xl space-y-6 p-6">
|
||||
<div>
|
||||
<h1 className="font-display text-2xl font-semibold text-ink">ERP & Contabilitate</h1>
|
||||
<p className="text-sm text-ink-faint mt-1">Integrare ERPNext — sincronizare financiară și operațională.</p>
|
||||
</div>
|
||||
|
||||
<div className="card p-4 bg-warn/5 border-warn/30 space-y-1">
|
||||
<p className="text-xs font-semibold text-warn">ERPNext neconectat la CEO OS</p>
|
||||
<p className="text-xs text-ink-faint">
|
||||
ERPNext rulează pe server (port 8080) dar API-ul de sincronizare nu este configurat.
|
||||
CEO OS nu scrie niciodată direct în baza de date ERP — datele curg exclusiv prin adaptorul API.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Architecture rule */}
|
||||
<div className="card p-4 bg-signal-danger/5 border-signal-danger/30 space-y-1">
|
||||
<p className="text-xs font-semibold text-signal-danger">Regulă arhitecturală CRITICĂ</p>
|
||||
<p className="text-xs text-ink-faint">
|
||||
CEO OS nu scrie niciodată direct în baza de date ERPNext.
|
||||
Toate modificările merg prin API-ul ERPNext, care validează și înregistrează tranzacțiile conform regulilor contabile.
|
||||
Orice scriere directă în BD ar corupe integritatea contabilă.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Entity sync table */}
|
||||
<div className="card p-5 space-y-3">
|
||||
<p className="text-xs font-semibold uppercase tracking-wider text-ink-faint">Entități sincronizate (planificat)</p>
|
||||
<div className="space-y-2">
|
||||
{ERP_ENTITIES.map((e) => (
|
||||
<div key={e.name} className="flex items-start gap-3 p-2 rounded-lg bg-muted/30">
|
||||
<div className="flex-1 min-w-0">
|
||||
<p className="text-sm font-medium text-ink">{e.name}</p>
|
||||
<p className="text-[10px] text-ink-faint">{e.desc}</p>
|
||||
</div>
|
||||
<span className={`text-sm font-bold shrink-0 ${e.dir === '↔' ? 'text-warn' : 'text-primary'}`}>{e.dir}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<p className="text-[10px] text-ink-faint">→ = ERPNext → CEO OS (read) | ↔ = bidirectional cu aprobare</p>
|
||||
</div>
|
||||
|
||||
{/* Setup steps */}
|
||||
<div className="space-y-3">
|
||||
<p className="text-xs font-semibold uppercase tracking-wider text-ink-faint">Pași de configurare</p>
|
||||
{SETUP_STEPS.map((step) => (
|
||||
<div key={step.n} className="card p-3 flex items-start gap-3">
|
||||
<div className={`w-6 h-6 rounded-full flex items-center justify-center text-xs font-bold shrink-0 ${
|
||||
step.status === 'done' ? 'bg-signal-ok/20 text-signal-ok' :
|
||||
step.status === 'todo' ? 'bg-warn/20 text-warn' :
|
||||
'bg-muted text-ink-faint'}`}>
|
||||
{step.status === 'done' ? '✓' : step.n}
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm font-medium text-ink">{step.label}</p>
|
||||
<p className="text-[10px] text-ink-faint mt-0.5">{step.desc}</p>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="flex flex-wrap gap-3 text-xs">
|
||||
<Link href="/dashboard/integrations/erp" className="text-primary hover:underline">Detalii integrare ERP →</Link>
|
||||
<Link href="/dashboard/finance" className="text-primary hover:underline">Finance Dashboard →</Link>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Loading…
Reference in a new issue