58775d4
ZhenYi
refactor: update database write logic and normalize API paths for improved clarity and consistency
58775d4
use export::pagination::Page;
use models::pull_request::{pull_request_review, pull_request_reviewer, pull_requests};
use sea_orm::{
ColumnTrait, EntityTrait, PaginatorTrait, QueryFilter, QueryOrder, QuerySelect, Select,
};
use serde::{Deserialize, Serialize};
use utoipa::{IntoParams, ToSchema};
use uuid::Uuid;
use crate::errors::PullError;
use crate::services::pulls::PullDto;
use crate::services::service::PullService;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "kebab-case")]
pub enum InboxScope {
Created,
ReviewRequested,
Reviewed,
}
#[derive(Debug, Clone, Default, Deserialize, IntoParams)]
pub struct InboxQuery {
/// open | closed | merged | all
#[serde(default)]
pub state: Option<String>,
#[serde(default)]
pub limit: Option<u64>,
#[serde(default)]
pub offset: Option<u64>,
}
pub type InboxPage = Page<PullDto>;
impl PullService {
pub async fn list_inbox(
&self,
caller: i64,
scope: InboxScope,
query: InboxQuery,
) -> Result<InboxPage, PullError> {
let limit = query.limit.unwrap_or(50).clamp(1, 100);
let offset = query.offset.unwrap_or(0);
let base: Select<pull_requests::Entity> = match scope {
InboxScope::Created => {
pull_requests::Entity::find().filter(pull_requests::Column::AuthorId.eq(caller))
}
InboxScope::ReviewRequested => {
let ids: Vec<Uuid> = pull_request_reviewer::Entity::find()
.filter(pull_request_reviewer::Column::UserId.eq(caller))
.all(self.db_read())
.await?
.into_iter()
.map(|row| row.pull_request_id)
.collect();
pull_requests::Entity::find().filter(pull_requests::Column::Id.is_in(ids))
}
InboxScope::Reviewed => {
let ids: Vec<Uuid> = pull_request_review::Entity::find()
.filter(pull_request_review::Column::UserId.eq(caller))
.all(self.db_read())
.await?
.into_iter()
.map(|row| row.pull_request_id)
.collect();
pull_requests::Entity::find().filter(pull_requests::Column::Id.is_in(ids))
}
};
let mut select = match query.state.as_deref().unwrap_or("open") {
"all" => base,
"closed" => base
.filter(pull_requests::Column::HasMerged.eq(false))
.filter(pull_requests::Column::ClosedAt.is_not_null()),
"merged" => base.filter(pull_requests::Column::HasMerged.eq(true)),
"open" => base
.filter(pull_requests::Column::HasMerged.eq(false))
.filter(pull_requests::Column::ClosedAt.is_null()),
other => {
return Err(PullError::BadRequest(format!("unknown state `{other}`")));
}
};
let total = select.clone().count(self.db_read()).await? as i64;
select = select.order_by_desc(pull_requests::Column::UpdatedAt);
let rows = select
.limit(limit)
.offset(offset)
.all(self.db_read())
.await?;
let users = self.pull_users(&rows).await?;
Ok(Page {
items: rows
.iter()
.map(|row| PullService::dto(row, &users))
.collect(),
total,
limit,
offset,
})
}
}