crates/monetize-server/src/estate_order/standing.rs
//! **THE ESTATES THAT EXIST** (owner 2026-10-29, lane OVW-CLEAN) — what the console's Overview
//! lists, decided here and only rendered there (`Estates.Overview`).
//!
//! The box keeps two records of an estate: the fleet's (the guardian's store: an estate declared
//! at a join, at a sold estate's install, from `[products.<id>] instance`) and the shop's run (an
//! order, from `ordered` to `terminated`). Neither is ever forgotten by a terminate: the run is
//! kept as the estate's history and the fleet's estate row stays (only its boxes go). So every
//! estate this box ever laid or heard of has a record, and each record is classified ONCE, here
//! ([`standing`]):
//!
//! * **installed**: a box of it reported in (or this box laid one), or its run is delivered;
//! * **laying**: its run is ordered, paid, laying, installing, or owed (paid, waiting for the
//! operator's retry or refund);
//! * **ended**: its run ended (terminated, refunded, released, deleted) and no box of it reports;
//! * **never installed**: no run, and no box of it ever reported in.
//!
//! Installed and laying are the Overview's rows; ended and never installed are its one quiet
//! line. A declared operator site with no row is the slot's to start by its name
//! ([`super::new_estate`]).
use std::collections::BTreeMap;
use super::{phase, EstateRun};
use crate::state::AppState;
/// **Where an estate stands**, as the Overview groups it.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Standing {
Installed,
Laying,
Ended,
NeverInstalled,
}
impl Standing {
/// The wire's word.
pub fn as_str(self) -> &'static str {
match self {
Standing::Installed => "installed",
Standing::Laying => "laying",
Standing::Ended => "ended",
Standing::NeverInstalled => "never_installed",
}
}
/// An Overview row (it exists); else the quiet line.
pub fn is_row(self) -> bool {
matches!(self, Standing::Installed | Standing::Laying)
}
}
/// Pure: **the one classification** — `machines`: some box of the estate reported in at least
/// once, or this box laid one; `run`: the phase of its newest run, if it has one.
///
/// * A delivered run (`captured`, `grace`, `suspended`, `deleting`) or one being terminated
/// still stands: installed.
/// * A run on its way (`ordered` … `paired`) is laying, whatever reports. A setup that failed
/// (`failed`, `owed`) is laying too, unless boxes of it report: then something of it stands.
/// * An ended run (`terminated`, `refunded`, `released`, `deleted`) is ended, unless a box of it
/// reports AGAIN (a terminate forgets every box, so a report after it is a new life).
/// * No run: installed when a box reported, else never installed.
pub fn standing(machines: bool, run: Option<&str>) -> Standing {
match run {
Some(p) if phase::is_gone(p) => {
if machines {
Standing::Installed
} else {
Standing::Ended
}
}
Some(p) if phase::is_term(p) || p == phase::TERMINATING => Standing::Installed,
Some(p) if matches!(p, phase::FAILED | phase::OWED) && machines => Standing::Installed,
Some(_) => Standing::Laying,
None if machines => Standing::Installed,
None => Standing::NeverInstalled,
}
}
/// When `run` moved to its phase, if its history says.
fn since(run: &EstateRun) -> Option<u64> {
run.history
.iter()
.rev()
.find(|t| t.phase == run.phase)
.map(|t| t.at_ms)
}
/// [`words_of`] for a record: its run's phase and when it moved there.
pub fn words(s: Standing, run: Option<&EstateRun>) -> String {
words_of(
s,
run.map(|r| r.phase.as_str()).unwrap_or_default(),
run.and_then(since),
)
}
/// Pure: **the sentence for a standing**, from its run's phase (empty: no run) and when it
/// moved there.
pub fn words_of(s: Standing, p: &str, since_ms: Option<u64>) -> String {
let on = since_ms
.map(|ms| format!(" on {}", super::iso_date(ms)))
.unwrap_or_default();
match s {
Standing::Installed => match p {
phase::TERMINATING => "being terminated: its machines are given back".into(),
phase::GRACE => "installed; its paid period ended, it runs in its grace".into(),
phase::SUSPENDED => {
"installed; suspended unpaid: its servers are stopped, its disks kept".into()
}
phase::DELETING => "installed; unpaid past its notice: being given back".into(),
_ => "installed: its machines have reported in".into(),
},
Standing::Laying => match p {
phase::ORDERED => "ordered: waiting for its payment".into(),
phase::HELD => "paid: waiting to be laid".into(),
phase::WAITING_DNS => "paid: waiting for its DNS records".into(),
phase::LAYING => "paid: being laid".into(),
phase::INSTALLING => "paid: installing".into(),
phase::PAIRED => "paid: paired, finishing its install".into(),
phase::FAILED => "paid: its setup failed and is tried again".into(),
phase::OWED => {
"paid, and it could not be set up: retry or refund it on the Sites page".into()
}
other => format!("being laid ({other})"),
},
Standing::Ended => match p {
phase::TERMINATED => format!("terminated{on}"),
phase::REFUNDED => format!("cancelled and refunded{on}"),
phase::RELEASED => format!("never paid: its order was released{on}"),
phase::DELETED => format!("unpaid: given back{on}"),
other => format!("ended ({other}){on}"),
},
Standing::NeverInstalled => "never installed: no machine of it ever reported in".into(),
}
}
/// **One estate as the Overview names it.**
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct EstateLine {
pub name: String,
pub product: String,
pub standing: &'static str,
pub words: String,
/// The fleet (the guardian) knows it: its summary can be read.
pub in_fleet: bool,
pub domain: String,
}
/// **The Overview, decided**: its rows, its quiet line, and the slot's choices.
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct Overview {
pub estates: Vec<EstateLine>,
pub ended: Vec<EstateLine>,
/// The products a new estate can be made of here ([`super::new_estate::template_of`]).
pub products: Vec<String>,
/// The operator's declared sites with no row: started from the slot by their name.
pub declared: Vec<String>,
}
/// The run's product: its own, else its site's, else the shop's.
fn product_of(state: &AppState, run: &EstateRun) -> String {
if !run.product.trim().is_empty() {
return run.product.trim().to_string();
}
crate::fleet::run_product(state, run).unwrap_or_default()
}
/// Where a run's estate is reached: a site's own domain; a sold estate's own domain, else
/// `<company>.<its site>`.
fn domain_of(state: &AppState, run: &EstateRun) -> String {
if run.site_order {
return state.registry.site_of(&run.estate).unwrap_or_default();
}
if !run.domain.trim().is_empty() {
return run.domain.trim().to_string();
}
state
.registry
.site_of(&run.estate)
.map(|s| format!("{}.{s}", run.company))
.unwrap_or_default()
}
/// **Every estate the box keeps a record of, classified** — the fleet's estates and the shop's
/// runs, one line per fleet name, by name.
pub fn overview(state: &AppState) -> Overview {
let runs = state.estates.all();
let mut lines: BTreeMap<String, EstateLine> = BTreeMap::new();
// The fleet's estates, each with its run (a site's by its label, a sold estate's by its company).
if let Some(g) = state.fleet.guardian() {
for (instance, product) in g.store.estates() {
let run = state.estates.get(&instance);
let laid = run
.as_ref()
.and_then(|r| r.laid.as_ref())
.is_some_and(|l| !l.machines.is_empty())
&& run.as_ref().is_some_and(|r| !phase::is_gone(&r.phase));
// Every role with a key, and the three every estate names (a box record is kept by role).
let mut roles = g.store.roles_of(&instance);
roles.extend(["front", "main", "twin"].map(String::from));
let machines = laid
|| roles.iter().any(|role| {
g.store
.box_record(&instance, role)
.is_some_and(|b| b.heard_unix_ms > 0)
});
let s = standing(machines, run.as_ref().map(|r| r.phase.as_str()));
let domain = run
.as_ref()
.map(|r| domain_of(state, r))
.filter(|d| !d.is_empty())
.or_else(|| state.registry.site_of(&instance))
.unwrap_or_default();
lines.insert(
instance.clone(),
EstateLine {
name: instance,
product,
standing: s.as_str(),
words: words(s, run.as_ref()),
in_fleet: true,
domain,
},
);
}
}
// The shop's runs the fleet does not know (yet): an order on its way, or one that ended
// before its estate was installed. The newest run of a name is the one kept.
for run in &runs {
let name = run.fleet_name().to_string();
if name.is_empty() || lines.contains_key(&name) {
continue;
}
let s = standing(false, Some(&run.phase));
lines.insert(
name.clone(),
EstateLine {
name,
product: product_of(state, run),
standing: s.as_str(),
words: words(s, Some(run)),
in_fleet: false,
domain: domain_of(state, run),
},
);
}
let (estates, ended): (Vec<EstateLine>, Vec<EstateLine>) = lines.into_values().partition(|l| {
l.standing == Standing::Installed.as_str() || l.standing == Standing::Laying.as_str()
});
let rows: std::collections::BTreeSet<&str> = estates.iter().map(|l| l.name.as_str()).collect();
let declared = state
.registry
.declared_estates()
.into_iter()
.filter(|(label, e)| e.operator_site && !rows.contains(label.as_str()))
.map(|(label, _)| label)
.collect();
let products = super::new_estate::products_offered(state);
Overview {
estates,
ended,
products,
declared,
}
}
#[cfg(test)]
mod tests {
use super::*;
/// ★ **Every record is classified once** (OVW-CLEAN): the run's phase first, the machines
/// that reported second.
#[test]
fn a_record_is_installed_laying_ended_or_never_installed() {
use Standing::*;
// No run: a box that reported is an install (a kit-installed site: gunnar.rs); none, never.
assert_eq!(standing(true, None), Installed);
assert_eq!(
standing(false, None),
NeverInstalled,
"declared at a join or by [products] instance, nothing ever reported"
);
// On its way: ordered, paid, laying, whatever reports.
for p in [
phase::ORDERED,
phase::HELD,
phase::WAITING_DNS,
phase::LAYING,
phase::INSTALLING,
phase::PAIRED,
] {
assert_eq!(standing(false, Some(p)), Laying, "{p}");
assert_eq!(
standing(true, Some(p)),
Laying,
"{p}: a site laid again over its old boxes is being laid"
);
}
// A setup that failed is the operator's to settle, unless something of it stands.
for p in [phase::FAILED, phase::OWED] {
assert_eq!(standing(false, Some(p)), Laying, "{p}");
assert_eq!(standing(true, Some(p)), Installed, "{p}: its boxes report");
}
// Delivered, in its term, or being ended: it stands.
for p in [
phase::CAPTURED,
phase::GRACE,
phase::SUSPENDED,
phase::DELETING,
phase::TERMINATING,
] {
assert_eq!(standing(false, Some(p)), Installed, "{p}");
}
// Ended: terminated (acme2, ignalina, polka, rickardtest, test3-holger-rs), refunded,
// released, deleted — unless a box of it reports again.
for p in [
phase::TERMINATED,
phase::REFUNDED,
phase::RELEASED,
phase::DELETED,
] {
assert_eq!(standing(false, Some(p)), Ended, "{p}");
assert_eq!(
standing(true, Some(p)),
Installed,
"{p}: a box reports after it ended"
);
}
assert!(
Installed.is_row() && Laying.is_row() && !Ended.is_row() && !NeverInstalled.is_row()
);
assert_eq!(
[Installed, Laying, Ended, NeverInstalled].map(Standing::as_str),
["installed", "laying", "ended", "never_installed"]
);
}
/// ★ The sentence names the step it stands at, and an ended one when it ended.
#[test]
fn the_words_name_the_step_and_when_it_ended() {
const OCT_27: Option<u64> = Some(1_793_059_200_000);
assert_eq!(
words_of(Standing::Laying, phase::ORDERED, None),
"ordered: waiting for its payment"
);
assert_eq!(
words_of(Standing::Laying, phase::LAYING, None),
"paid: being laid"
);
assert!(words_of(Standing::Laying, phase::OWED, None).contains("retry or refund"));
assert_eq!(
words_of(Standing::Ended, phase::TERMINATED, OCT_27),
"terminated on 2026-10-27"
);
assert_eq!(
words_of(Standing::Ended, phase::REFUNDED, OCT_27),
"cancelled and refunded on 2026-10-27"
);
assert_eq!(
words_of(Standing::Ended, phase::TERMINATED, None),
"terminated"
);
assert_eq!(
words_of(Standing::NeverInstalled, "", None),
"never installed: no machine of it ever reported in"
);
assert_eq!(
words_of(Standing::Installed, "", None),
"installed: its machines have reported in"
);
}
}