Dev-Portal Front UI — Models Page

User Manual + Implementation Spec (Draft / English)

Message to the offshore team (please read first)

Before you start implementing, please validate that you fully understand this specification and are confident you can deliver exactly as described.
If anything is unclear or seems infeasible, stop and ask questions first (do not start with assumptions).
We want to proceed only after you confirm that you can implement this spec as-is.


0. Goal (What this page is for)

The Models page lists the models that are currently managed/used in Dev-Portal.
Users can do two things:

  1. Create New Model (New)
  2. Import Existing Model (Import from Odoo metadata via src tables)

This page is intentionally kept simple. If we can implement this page correctly, the overall foundation will be ready.


1. Scope (Must / Not Required)

1.1 Must (Required in this task)

  • Display a list of models (base table: public.portal_model)
  • Display “custom field count” per model (aggregated from public.portal_fields)
  • Provide two actions:
    • New: create a model row in portal_model (ONLY)
    • Import Existing: call an API that imports model + fields + views from src tables into portal tables

1.2 Not required (Out of scope for now)

  • Smart button import (portal_smart_button) NOT required
  • Menu import (portal_menu) NOT required
  • Odoo screen navigation NOT required
  • “Applied/Approved” status reconciliation with Odoo NOT required
    (If UI shows such labels, mark them as “not implemented yet” or hide them.)

2. Source of Truth and Data Flow

2.1 Source of Truth

Odoo metadata is continuously synchronized into Dev-Portal “src” tables via RPC.
For this task, assume src tables are always up-to-date and are the single source of truth for import.

  • public.portal_fields_src (up-to-date via Odoo RPC)
  • public.portal_view_src (up-to-date via Odoo RPC)

2.2 Portal-managed tables (UI reads / API writes)

  • public.portal_model (one row per model shown in the list)
  • public.portal_fields (field definitions; used for counts and later pages)
  • public.portal_view_common (model-centric common view settings)
  • public.portal_view (view-type specific settings)

3. Data Relationships (Important: 1:1 between model and view_common)

Assumption for this project:

  • portal_model and portal_view_common are 1:1
  • portal_view_common and portal_view are 1:N (per view_type)
  • portal_model and portal_fields are 1:N

3.1 ER (simplified)

portal_model (1) ── 1:1 ── portal_view_common (1) ──< portal_view (N)
portal_model (1) ─────────< portal_fields (N)

3.2 Uniqueness constraints assumed by implementation

  • portal_view_common: one row per model
    • recommended uniqueness: UNIQUE (model)
  • portal_view: one row per view type under the same common
    • UNIQUE (common_id, view_type) (already in the provided DDL)

4. UI Specification — Models Page

4.1 List display

The page displays all records from portal_model.
Each model card (or list row) should show at minimum:

  • Model label (display name)
  • Model technical name (e.g., sale.order)
  • Model table name (e.g., sale_order)
  • Custom field count (aggregated from portal_fields for that model)
  • Notes (optional)
  • Updated date (optional)

4.2 Actions / Buttons

Two buttons at the top:

  • + New
  • Import Existing

Important:

  • New and Import Existing are different operations and must be clearly labeled.
  • Import Existing must be performed via API only (frontend must not manipulate DB directly).

5. Feature: Create New Model (New)

5.1 Purpose

Register a new model as a Dev-Portal-managed model.
It does NOT require the model to already exist in Odoo.

5.2 Minimal input fields (UI)

  • model (technical name) — e.g., x_custom.order
  • model_table — e.g., x_custom_order
  • label or label_i18n.ja_JP — e.g., “Custom Order”
  • notes (optional)

5.3 Database behavior (must)

  • Insert exactly one row into public.portal_model
  • Do NOT create any related records:
    • portal_fields remains 0 rows for this model
    • portal_view_common remains 0 rows for this model
    • portal_view remains 0 rows for this model

Result: the model is created as an “empty shell” with no fields or views.


6. Feature: Import Existing Model (Import Existing) — API-driven

6.1 Purpose

Import an already-existing Odoo model into Dev-Portal by reading the latest metadata from src tables and upserting into portal tables.

6.2 Frontend responsibility (must)

Frontend does only:

  1. User selects/inputs a target model name (e.g., sale.order)
  2. Frontend calls the Import API
  3. On success: refresh list (re-fetch portal_model and field counts)
  4. On failure: show error and allow retry

All extraction / mapping / upsert logic is on the API side.

6.3 Import API — expected contract (example)

Endpoint name may differ, but the behavior must match.

  • HTTP: POST /portal/models/import (example)
  • Header: Idempotency-Key: <uuid> (required for POST)
  • Body { "model": "sale.order" }

6.4 Import API — required server-side behavior (must)

When importing a model X:

(A) Upsert portal_model (1 row)

  • Create or update public.portal_model for model X

(B) Upsert portal_fields (N rows)

  • Read all rows from public.portal_fields_src where model = X
  • Upsert them into public.portal_fields

(C) Upsert portal_view_common (1 row; model-centric)

  • Read rows from public.portal_view_src where model = X (likely multiple rows)
  • Create or update exactly one row in public.portal_view_common for model X

(D) Upsert portal_view (N rows; per view_type)

  • Using the portal_view_common.id as common_id, upsert one row per view_type
  • Key must be (common_id, view_type) (no duplicates)

Explicitly NOT included (out of scope):

  • Smart button import: do not touch portal_smart_button
  • Menu import: do not touch portal_menu

6.5 Idempotency (must)

Importing the same model multiple times must:

  • Not create duplicates
  • Update existing records via UPSERT
  • Keep portal_view_common at exactly one row per model
  • Keep portal_view at exactly one row per (common_id, view_type)

6.6 Suggested response payload (example)

Return counts so the UI can show a success message:

{
  "status": "ok",
  "model": "sale.order",
  "upserted": {
    "portal_model": 1,
    "portal_fields": 128,
    "portal_view_common": 1,
    "portal_view": 5
  }
}

7. Acceptance Criteria (Definition of Done)

This task is considered complete when:

  1. Models page lists all records in portal_model
  2. New creates exactly one row in portal_model and creates no fields/views
  3. Import Existing calls an API, and the API imports from:
    • portal_fields_srcportal_fields
    • portal_view_srcportal_view_common (1 row per model) and portal_view (per view_type)
  4. Custom field count updates correctly after import
  5. Smart buttons and menus are not imported (not implemented)

Comments

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です