# Schema Nickel para el módulo `crm` (Cliente + Oportunidad + Interaccion).
#
# Un CRM: clientes, oportunidades de venta que recorren un pipeline e
# interacciones registradas. El kernel de Nakui valida cada entity
# contra el contract de su record — antes y después de cada morfismo.

let non_empty_string = std.contract.from_predicate (fun s =>
  std.is_string s && std.string.length s > 0
) in

let positive_int = std.contract.from_predicate (fun n =>
  std.is_number n && n > 0
) in

let currency_iso = std.contract.from_predicate (fun s =>
  std.is_string s && std.string.length s == 3
) in

# Etapas del pipeline de ventas. `ganada` y `perdida` son terminales.
let etapa_pipeline = std.contract.from_predicate (fun s =>
  std.is_string s
    && std.array.elem s
      ["prospecto", "calificado", "propuesta", "negociacion", "ganada", "perdida"]
) in

let canal_interaccion = std.contract.from_predicate (fun s =>
  std.is_string s && std.array.elem s ["llamada", "email", "reunion"]
) in

{
  Cliente = {
    id | String,
    nombre | non_empty_string,
    email | non_empty_string,
    empresa | String,
  },

  Oportunidad = {
    id | String,
    cliente_id | String,
    titulo | non_empty_string,
    monto | positive_int,
    currency | currency_iso,
    etapa | etapa_pipeline,
    timestamp | String,
  },

  Interaccion = {
    id | String,
    cliente_id | String,
    canal | canal_interaccion,
    nota | String,
    timestamp | String,
  },
}
