fix(dimentorin): resolve mentor profile id to user id before booking session
This commit is contained in:
@@ -29,6 +29,8 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
drop_and_create_table(&db, builder, "app_mentors", auth::mentors::Entity).await?;
|
drop_and_create_table(&db, builder, "app_mentors", auth::mentors::Entity).await?;
|
||||||
drop_and_create_table(&db, builder, "app_sessions", auth::sessions::Entity)
|
drop_and_create_table(&db, builder, "app_sessions", auth::sessions::Entity)
|
||||||
.await?;
|
.await?;
|
||||||
|
drop_and_create_table(&db, builder, "app_articles", common::articles::Entity)
|
||||||
|
.await?;
|
||||||
|
|
||||||
drop_and_create_table(&db, builder, "events", common::events::Entity).await?;
|
drop_and_create_table(&db, builder, "events", common::events::Entity).await?;
|
||||||
drop_and_create_table(&db, builder, "testimonials", common::testimonials::Entity)
|
drop_and_create_table(&db, builder, "testimonials", common::testimonials::Entity)
|
||||||
|
|||||||
@@ -0,0 +1,73 @@
|
|||||||
|
use async_trait::async_trait;
|
||||||
|
use paginator_utils::{PaginatorResponse, PaginatorResponseMeta};
|
||||||
|
use std::sync::Arc;
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
use super::super::domain::article::ArticleEntity;
|
||||||
|
use super::super::domain::article_types::{ArticleDetail, ArticleListItem, CreateArticleCommand};
|
||||||
|
use super::super::domain::repository::ArticleRepository;
|
||||||
|
use super::super::domain::service::ArticleService;
|
||||||
|
use imphnen_utils::AppError;
|
||||||
|
|
||||||
|
pub struct ArticleServiceImpl {
|
||||||
|
repo: Arc<dyn ArticleRepository>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ArticleServiceImpl {
|
||||||
|
pub fn new(repo: Arc<dyn ArticleRepository>) -> Self {
|
||||||
|
Self { repo }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl ArticleService for ArticleServiceImpl {
|
||||||
|
async fn list(
|
||||||
|
&self,
|
||||||
|
page: u64,
|
||||||
|
per_page: u64,
|
||||||
|
category: Option<String>,
|
||||||
|
) -> Result<PaginatorResponse<ArticleListItem>, AppError> {
|
||||||
|
let result = self.repo.find_all_paginated(page, per_page, category).await?;
|
||||||
|
let items: Vec<ArticleListItem> = result
|
||||||
|
.data
|
||||||
|
.into_iter()
|
||||||
|
.map(ArticleListItem::from)
|
||||||
|
.collect();
|
||||||
|
Ok(PaginatorResponse {
|
||||||
|
data: items,
|
||||||
|
meta: result.meta,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_by_id(&self, id: Uuid) -> Result<ArticleDetail, AppError> {
|
||||||
|
let entity = self.repo.find_by_id(id).await?;
|
||||||
|
Ok(ArticleDetail::from(entity))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_by_slug(&self, slug: &str) -> Result<ArticleDetail, AppError> {
|
||||||
|
let entity = self.repo.find_by_slug(slug).await?;
|
||||||
|
Ok(ArticleDetail::from(entity))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn categories(&self) -> Result<Vec<String>, AppError> {
|
||||||
|
self.repo.find_categories().await
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn create(&self, cmd: CreateArticleCommand) -> Result<ArticleDetail, AppError> {
|
||||||
|
let entity = ArticleEntity {
|
||||||
|
id: Uuid::new_v4(),
|
||||||
|
title: cmd.title,
|
||||||
|
slug: cmd.slug,
|
||||||
|
category: cmd.category,
|
||||||
|
excerpt: cmd.excerpt,
|
||||||
|
content: cmd.content,
|
||||||
|
cover_url: cmd.cover_url,
|
||||||
|
author_name: cmd.author_name,
|
||||||
|
is_published: true,
|
||||||
|
created_at: chrono::Utc::now(),
|
||||||
|
updated_at: chrono::Utc::now(),
|
||||||
|
};
|
||||||
|
self.repo.create(entity.clone()).await?;
|
||||||
|
Ok(ArticleDetail::from(entity))
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
pub mod article_service;
|
||||||
|
|
||||||
|
pub use article_service::ArticleServiceImpl;
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
use chrono::{DateTime, Utc};
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct ArticleEntity {
|
||||||
|
pub id: Uuid,
|
||||||
|
pub title: String,
|
||||||
|
pub slug: String,
|
||||||
|
pub category: String,
|
||||||
|
pub excerpt: String,
|
||||||
|
pub content: String,
|
||||||
|
pub cover_url: Option<String>,
|
||||||
|
pub author_name: Option<String>,
|
||||||
|
pub is_published: bool,
|
||||||
|
pub created_at: DateTime<Utc>,
|
||||||
|
pub updated_at: DateTime<Utc>,
|
||||||
|
}
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
use chrono::{DateTime, Utc};
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
use super::article::ArticleEntity;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct ArticleListItem {
|
||||||
|
pub id: Uuid,
|
||||||
|
pub title: String,
|
||||||
|
pub slug: String,
|
||||||
|
pub category: String,
|
||||||
|
pub excerpt: String,
|
||||||
|
pub cover_url: Option<String>,
|
||||||
|
pub author_name: Option<String>,
|
||||||
|
pub created_at: DateTime<Utc>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct ArticleDetail {
|
||||||
|
pub id: Uuid,
|
||||||
|
pub title: String,
|
||||||
|
pub slug: String,
|
||||||
|
pub category: String,
|
||||||
|
pub excerpt: String,
|
||||||
|
pub content: String,
|
||||||
|
pub cover_url: Option<String>,
|
||||||
|
pub author_name: Option<String>,
|
||||||
|
pub is_published: bool,
|
||||||
|
pub created_at: DateTime<Utc>,
|
||||||
|
pub updated_at: DateTime<Utc>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct CreateArticleCommand {
|
||||||
|
pub title: String,
|
||||||
|
pub slug: String,
|
||||||
|
pub category: String,
|
||||||
|
pub excerpt: String,
|
||||||
|
pub content: String,
|
||||||
|
pub cover_url: Option<String>,
|
||||||
|
pub author_name: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ArticleEntity> for ArticleListItem {
|
||||||
|
fn from(e: ArticleEntity) -> Self {
|
||||||
|
Self {
|
||||||
|
id: e.id,
|
||||||
|
title: e.title,
|
||||||
|
slug: e.slug,
|
||||||
|
category: e.category,
|
||||||
|
excerpt: e.excerpt,
|
||||||
|
cover_url: e.cover_url,
|
||||||
|
author_name: e.author_name,
|
||||||
|
created_at: e.created_at,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ArticleEntity> for ArticleDetail {
|
||||||
|
fn from(e: ArticleEntity) -> Self {
|
||||||
|
Self {
|
||||||
|
id: e.id,
|
||||||
|
title: e.title,
|
||||||
|
slug: e.slug,
|
||||||
|
category: e.category,
|
||||||
|
excerpt: e.excerpt,
|
||||||
|
content: e.content,
|
||||||
|
cover_url: e.cover_url,
|
||||||
|
author_name: e.author_name,
|
||||||
|
is_published: e.is_published,
|
||||||
|
created_at: e.created_at,
|
||||||
|
updated_at: e.updated_at,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
pub mod article;
|
||||||
|
pub mod article_types;
|
||||||
|
pub mod repository;
|
||||||
|
pub mod service;
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
use async_trait::async_trait;
|
||||||
|
use paginator_utils::PaginatorResponse;
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
use super::article::ArticleEntity;
|
||||||
|
use imphnen_utils::AppError;
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
pub trait ArticleRepository: Send + Sync {
|
||||||
|
async fn find_all_paginated(
|
||||||
|
&self,
|
||||||
|
page: u64,
|
||||||
|
per_page: u64,
|
||||||
|
category: Option<String>,
|
||||||
|
) -> Result<PaginatorResponse<ArticleEntity>, AppError>;
|
||||||
|
async fn find_by_id(&self, id: Uuid) -> Result<ArticleEntity, AppError>;
|
||||||
|
async fn find_by_slug(&self, slug: &str) -> Result<ArticleEntity, AppError>;
|
||||||
|
async fn find_categories(&self) -> Result<Vec<String>, AppError>;
|
||||||
|
async fn create(&self, entity: ArticleEntity) -> Result<Uuid, AppError>;
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
use async_trait::async_trait;
|
||||||
|
use paginator_utils::PaginatorResponse;
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
use super::article_types::{ArticleDetail, ArticleListItem, CreateArticleCommand};
|
||||||
|
use imphnen_utils::AppError;
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
pub trait ArticleService: Send + Sync {
|
||||||
|
async fn list(
|
||||||
|
&self,
|
||||||
|
page: u64,
|
||||||
|
per_page: u64,
|
||||||
|
category: Option<String>,
|
||||||
|
) -> Result<PaginatorResponse<ArticleListItem>, AppError>;
|
||||||
|
async fn get_by_id(&self, id: Uuid) -> Result<ArticleDetail, AppError>;
|
||||||
|
async fn get_by_slug(&self, slug: &str) -> Result<ArticleDetail, AppError>;
|
||||||
|
async fn categories(&self) -> Result<Vec<String>, AppError>;
|
||||||
|
async fn create(
|
||||||
|
&self,
|
||||||
|
cmd: CreateArticleCommand,
|
||||||
|
) -> Result<ArticleDetail, AppError>;
|
||||||
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
pub mod postgres_article_queries;
|
||||||
|
pub mod postgres_article_repository;
|
||||||
+92
@@ -0,0 +1,92 @@
|
|||||||
|
use super::super::super::domain::article::ArticleEntity;
|
||||||
|
use imphnen_entities::seaorm::common::articles::{
|
||||||
|
Column as ArticleColumn, Entity as ArticlesEntity, Model as ArticleModel,
|
||||||
|
};
|
||||||
|
use imphnen_utils::AppError;
|
||||||
|
use paginator_utils::{PaginatorResponse, PaginatorResponseMeta};
|
||||||
|
use sea_orm::prelude::*;
|
||||||
|
use sea_orm::{EntityTrait, Order, PaginatorTrait, QueryFilter, QueryOrder};
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
pub fn model_to_entity(model: ArticleModel) -> ArticleEntity {
|
||||||
|
ArticleEntity {
|
||||||
|
id: model.id,
|
||||||
|
title: model.title,
|
||||||
|
slug: model.slug,
|
||||||
|
category: model.category,
|
||||||
|
excerpt: model.excerpt,
|
||||||
|
content: model.content,
|
||||||
|
cover_url: model.cover_url,
|
||||||
|
author_name: model.author_name,
|
||||||
|
is_published: model.is_published,
|
||||||
|
created_at: model.created_at,
|
||||||
|
updated_at: model.updated_at,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn find_all_paginated(
|
||||||
|
db: &Arc<DatabaseConnection>,
|
||||||
|
page: u64,
|
||||||
|
per_page: u64,
|
||||||
|
category: Option<String>,
|
||||||
|
) -> Result<PaginatorResponse<ArticleEntity>, AppError> {
|
||||||
|
let mut query = ArticlesEntity::find().filter(ArticleColumn::IsPublished.eq(true));
|
||||||
|
|
||||||
|
if let Some(cat) = category.filter(|c| !c.is_empty()) {
|
||||||
|
query = query.filter(ArticleColumn::Category.eq(cat));
|
||||||
|
}
|
||||||
|
|
||||||
|
query = query.order_by(ArticleColumn::CreatedAt, Order::Desc);
|
||||||
|
|
||||||
|
let paginator = query.paginate(db.as_ref(), per_page);
|
||||||
|
let total = paginator
|
||||||
|
.num_items()
|
||||||
|
.await
|
||||||
|
.map_err(|e| AppError::InternalServerError(e.to_string()))?;
|
||||||
|
let articles = paginator
|
||||||
|
.fetch_page(page.saturating_sub(1))
|
||||||
|
.await
|
||||||
|
.map_err(|e| AppError::InternalServerError(e.to_string()))?;
|
||||||
|
|
||||||
|
let data = articles.into_iter().map(model_to_entity).collect();
|
||||||
|
let meta = PaginatorResponseMeta::new(page, per_page, total as u32);
|
||||||
|
Ok(PaginatorResponse { data, meta })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn find_by_id(
|
||||||
|
db: &Arc<DatabaseConnection>,
|
||||||
|
id: Uuid,
|
||||||
|
) -> Result<ArticleEntity, AppError> {
|
||||||
|
let model = ArticlesEntity::find_by_id(id)
|
||||||
|
.filter(ArticleColumn::IsPublished.eq(true))
|
||||||
|
.one(db.as_ref())
|
||||||
|
.await
|
||||||
|
.map_err(|e| AppError::InternalServerError(e.to_string()))?
|
||||||
|
.ok_or_else(|| AppError::NotFoundError("Article not found".to_string()))?;
|
||||||
|
Ok(model_to_entity(model))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn find_by_slug(
|
||||||
|
db: &Arc<DatabaseConnection>,
|
||||||
|
slug: &str,
|
||||||
|
) -> Result<ArticleEntity, AppError> {
|
||||||
|
let model = ArticlesEntity::find()
|
||||||
|
.filter(ArticleColumn::Slug.eq(slug))
|
||||||
|
.filter(ArticleColumn::IsPublished.eq(true))
|
||||||
|
.one(db.as_ref())
|
||||||
|
.await
|
||||||
|
.map_err(|e| AppError::InternalServerError(e.to_string()))?
|
||||||
|
.ok_or_else(|| AppError::NotFoundError("Article not found".to_string()))?;
|
||||||
|
Ok(model_to_entity(model))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn find_categories(db: &Arc<DatabaseConnection>) -> Result<Vec<String>, AppError> {
|
||||||
|
let rows = ArticlesEntity::find()
|
||||||
|
.select_only()
|
||||||
|
.column(ArticleColumn::Category)
|
||||||
|
.distinct()
|
||||||
|
.all(db.as_ref())
|
||||||
|
.await
|
||||||
|
.map_err(|e| AppError::InternalServerError(e.to_string()))?;
|
||||||
|
Ok(rows.into_iter().map(|r| r.category).collect())
|
||||||
|
}
|
||||||
+67
@@ -0,0 +1,67 @@
|
|||||||
|
use super::postgres_article_queries::{
|
||||||
|
find_all_paginated, find_by_id, find_by_slug, find_categories,
|
||||||
|
};
|
||||||
|
use super::super::super::domain::article::ArticleEntity;
|
||||||
|
use super::super::super::domain::repository::ArticleRepository;
|
||||||
|
use imphnen_entities::seaorm::common::articles::{ActiveModel, Column as ArticleColumn};
|
||||||
|
use imphnen_utils::AppError;
|
||||||
|
use async_trait::async_trait;
|
||||||
|
use paginator_utils::PaginatorResponse;
|
||||||
|
use sea_orm::{ActiveModelTrait, ColumnTrait, DatabaseConnection, EntityTrait, QueryFilter, Set};
|
||||||
|
use std::sync::Arc;
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
pub struct PostgresArticleRepository {
|
||||||
|
db: Arc<DatabaseConnection>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PostgresArticleRepository {
|
||||||
|
pub fn new(db: DatabaseConnection) -> Self {
|
||||||
|
Self { db: Arc::new(db) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl ArticleRepository for PostgresArticleRepository {
|
||||||
|
async fn find_all_paginated(
|
||||||
|
&self,
|
||||||
|
page: u64,
|
||||||
|
per_page: u64,
|
||||||
|
category: Option<String>,
|
||||||
|
) -> Result<PaginatorResponse<ArticleEntity>, AppError> {
|
||||||
|
find_all_paginated(&self.db, page, per_page, category).await
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn find_by_id(&self, id: Uuid) -> Result<ArticleEntity, AppError> {
|
||||||
|
find_by_id(&self.db, id).await
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn find_by_slug(&self, slug: &str) -> Result<ArticleEntity, AppError> {
|
||||||
|
find_by_slug(&self.db, slug).await
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn find_categories(&self) -> Result<Vec<String>, AppError> {
|
||||||
|
find_categories(&self.db).await
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn create(&self, entity: ArticleEntity) -> Result<Uuid, AppError> {
|
||||||
|
let active = ActiveModel {
|
||||||
|
id: sea_orm::ActiveValue::Set(entity.id),
|
||||||
|
title: Set(entity.title),
|
||||||
|
slug: Set(entity.slug),
|
||||||
|
category: Set(entity.category),
|
||||||
|
excerpt: Set(entity.excerpt),
|
||||||
|
content: Set(entity.content),
|
||||||
|
cover_url: Set(entity.cover_url),
|
||||||
|
author_name: Set(entity.author_name),
|
||||||
|
is_published: Set(entity.is_published),
|
||||||
|
created_at: Set(entity.created_at),
|
||||||
|
updated_at: Set(entity.updated_at),
|
||||||
|
};
|
||||||
|
active
|
||||||
|
.insert(self.db.as_ref())
|
||||||
|
.await
|
||||||
|
.map_err(|e| AppError::InternalServerError(e.to_string()))?;
|
||||||
|
Ok(entity.id)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
pub mod domain;
|
||||||
|
pub mod application;
|
||||||
|
pub mod infrastructure;
|
||||||
|
|
||||||
|
pub use infrastructure::http::routes::{articles_public_routes, articles_protected_routes};
|
||||||
@@ -12,7 +12,13 @@ use axum::{
|
|||||||
use imphnen_libs::{ValidatedJson, decode_access_token};
|
use imphnen_libs::{ValidatedJson, decode_access_token};
|
||||||
use imphnen_utils::AppError;
|
use imphnen_utils::AppError;
|
||||||
use imphnen_utils::ApiSuccess;
|
use imphnen_utils::ApiSuccess;
|
||||||
|
use imphnen_entities::seaorm::auth::mentors::{
|
||||||
|
Column as MentorColumn, Entity as MentorsEntity,
|
||||||
|
};
|
||||||
|
use imphnen_libs::AppState;
|
||||||
|
use sea_orm::{ColumnTrait, EntityTrait, QueryFilter};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
fn extract_user_id(headers: &HeaderMap) -> Result<String, AppError> {
|
fn extract_user_id(headers: &HeaderMap) -> Result<String, AppError> {
|
||||||
let token = headers
|
let token = headers
|
||||||
@@ -43,14 +49,23 @@ fn extract_user_id(headers: &HeaderMap) -> Result<String, AppError> {
|
|||||||
)]
|
)]
|
||||||
pub async fn post_book_session(
|
pub async fn post_book_session(
|
||||||
headers: HeaderMap,
|
headers: HeaderMap,
|
||||||
|
Extension(state): Extension<AppState>,
|
||||||
Extension(service): Extension<Arc<dyn SessionService>>,
|
Extension(service): Extension<Arc<dyn SessionService>>,
|
||||||
Path(mentor_id): Path<String>,
|
Path(mentor_id): Path<String>,
|
||||||
ValidatedJson(dto): ValidatedJson<BookSessionRequestDto>,
|
ValidatedJson(dto): ValidatedJson<BookSessionRequestDto>,
|
||||||
) -> Result<impl IntoResponse, AppError> {
|
) -> Result<impl IntoResponse, AppError> {
|
||||||
let user_id = extract_user_id(&headers)?;
|
let user_id = extract_user_id(&headers)?;
|
||||||
|
let mentor_uuid = Uuid::parse_str(&mentor_id).map_err(|_| {
|
||||||
|
AppError::BadRequestError("Invalid mentor ID format".to_string())
|
||||||
|
})?;
|
||||||
|
// Resolve mentor profile id -> user id (sessions.mentor_id FK ke app_users)
|
||||||
|
let mentor = MentorsEntity::find_by_id(mentor_uuid)
|
||||||
|
.one(&state.postgres_connection.conn)
|
||||||
|
.await?
|
||||||
|
.ok_or_else(|| AppError::NotFoundError("Mentor not found".to_string()))?;
|
||||||
let resp = BookSessionResponseDto::from(
|
let resp = BookSessionResponseDto::from(
|
||||||
service
|
service
|
||||||
.book_session(mentor_id, user_id, dto.into())
|
.book_session(mentor.user_id.to_string(), user_id, dto.into())
|
||||||
.await?,
|
.await?,
|
||||||
);
|
);
|
||||||
Ok(ApiSuccess(resp))
|
Ok(ApiSuccess(resp))
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
use chrono::{DateTime, Utc};
|
||||||
|
use sea_orm::entity::prelude::*;
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
|
||||||
|
#[sea_orm(table_name = "app_articles")]
|
||||||
|
pub struct Model {
|
||||||
|
#[sea_orm(primary_key, default = "gen_random_uuid()", auto_increment = false)]
|
||||||
|
pub id: Uuid,
|
||||||
|
|
||||||
|
pub title: String,
|
||||||
|
|
||||||
|
pub slug: String,
|
||||||
|
|
||||||
|
pub category: String,
|
||||||
|
|
||||||
|
pub excerpt: String,
|
||||||
|
|
||||||
|
pub content: String,
|
||||||
|
|
||||||
|
#[sea_orm(nullable)]
|
||||||
|
pub cover_url: Option<String>,
|
||||||
|
|
||||||
|
#[sea_orm(nullable)]
|
||||||
|
pub author_name: Option<String>,
|
||||||
|
|
||||||
|
pub is_published: bool,
|
||||||
|
|
||||||
|
pub created_at: DateTime<Utc>,
|
||||||
|
|
||||||
|
pub updated_at: DateTime<Utc>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
||||||
|
pub enum Relation {}
|
||||||
|
|
||||||
|
impl ActiveModelBehavior for ActiveModel {}
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
pub mod articles;
|
||||||
pub mod audit_log;
|
pub mod audit_log;
|
||||||
pub mod enum_impls;
|
pub mod enum_impls;
|
||||||
pub mod enums;
|
pub mod enums;
|
||||||
|
|||||||
Reference in New Issue
Block a user