use serde::{Deserialize, Serialize};
use super::error::TransferError;
use super::operator::ResponsibleOperator;
use super::record::TransferRecord;
use super::status::TransferStatus;
use crate::domain::passport::PassportId;
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TransferChain {
pub passport_id: PassportId,
pub original_operator: ResponsibleOperator,
pub transfers: Vec<TransferRecord>,
}
impl TransferChain {
#[must_use]
pub fn new(passport_id: PassportId, original_operator: ResponsibleOperator) -> Self {
Self {
passport_id,
original_operator,
transfers: Vec::new(),
}
}
pub fn current_operator(&self) -> &ResponsibleOperator {
self.transfers
.iter()
.rev()
.find(|t| t.is_complete())
.map(|t| &t.to_operator)
.unwrap_or(&self.original_operator)
}
pub fn transfer_count(&self) -> usize {
self.transfers.iter().filter(|t| t.is_complete()).count()
}
pub fn initiate_transfer(&mut self, record: TransferRecord) -> Result<(), TransferError> {
let current = self.current_operator();
if record.from_operator.did != current.did {
return Err(TransferError::OperatorMismatch {
expected: current.did.clone(),
got: record.from_operator.did.clone(),
});
}
let has_pending = self.transfers.iter().any(|t| {
t.status() == TransferStatus::Initiated || t.status() == TransferStatus::Accepted
});
if has_pending {
return Err(TransferError::TransferAlreadyPending);
}
self.transfers.push(record);
Ok(())
}
}