application: channels bounded context
CQRS use cases (create/update/delete/get/list/list_by_owner), ownership checks, auto-snapshot on config change. Channel setters added to domain model.
This commit is contained in:
68
crates/application/src/channels/update.rs
Normal file
68
crates/application/src/channels/update.rs
Normal file
@@ -0,0 +1,68 @@
|
||||
use domain::events::DomainEvent;
|
||||
use domain::models::Channel;
|
||||
use domain::value_objects::{ChannelId, UserId};
|
||||
use domain::{DomainError, DomainResult};
|
||||
|
||||
use super::commands::UpdateChannelCommand;
|
||||
use super::deps::ChannelCommandDeps;
|
||||
|
||||
/// Update an existing channel.
|
||||
///
|
||||
/// Flow: find channel -> verify ownership -> snapshot config if changed ->
|
||||
/// apply updates -> save -> publish event -> return.
|
||||
pub async fn execute(deps: &ChannelCommandDeps, cmd: UpdateChannelCommand) -> DomainResult<Channel> {
|
||||
let channel_id = ChannelId::from(cmd.channel_id);
|
||||
let owner_id = UserId::from(cmd.owner_id);
|
||||
|
||||
let mut channel = deps
|
||||
.channel_query
|
||||
.find_by_id(channel_id)
|
||||
.await?
|
||||
.ok_or(DomainError::ChannelNotFound(cmd.channel_id))?;
|
||||
|
||||
// Ownership check
|
||||
if channel.owner_id() != owner_id {
|
||||
return Err(DomainError::forbidden("You don't own this channel"));
|
||||
}
|
||||
|
||||
// Auto-snapshot the current config before overwriting
|
||||
if cmd.schedule_config.is_some() {
|
||||
deps.channel_command
|
||||
.save_config_snapshot(channel_id, channel.schedule_config(), None)
|
||||
.await?;
|
||||
}
|
||||
|
||||
// Apply partial updates
|
||||
if let Some(name) = cmd.name {
|
||||
channel.set_name(name);
|
||||
}
|
||||
if let Some(description) = cmd.description {
|
||||
channel.set_description(description);
|
||||
}
|
||||
if let Some(timezone) = cmd.timezone {
|
||||
channel.set_timezone(timezone);
|
||||
}
|
||||
if let Some(config) = cmd.schedule_config {
|
||||
channel.set_schedule_config(config);
|
||||
}
|
||||
if let Some(policy) = cmd.recycle_policy {
|
||||
channel.set_recycle_policy(policy);
|
||||
}
|
||||
if let Some(auto) = cmd.auto_schedule {
|
||||
channel.set_auto_schedule(auto);
|
||||
}
|
||||
|
||||
deps.channel_command.save(&channel).await?;
|
||||
|
||||
deps.event_publisher
|
||||
.publish(DomainEvent::ChannelUpdated {
|
||||
channel_id: channel.id(),
|
||||
})
|
||||
.await?;
|
||||
|
||||
Ok(channel)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[path = "tests/update.rs"]
|
||||
mod tests;
|
||||
Reference in New Issue
Block a user