Add service for sales_persond
This commit is contained in:
parent
20828fb4a1
commit
ad88a1c983
9 changed files with 792 additions and 2 deletions
|
|
@ -5,6 +5,7 @@ use mockall::automock;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
pub mod permission;
|
pub mod permission;
|
||||||
|
pub mod sales_person;
|
||||||
pub mod slot;
|
pub mod slot;
|
||||||
|
|
||||||
pub use permission::MockPermissionDao;
|
pub use permission::MockPermissionDao;
|
||||||
|
|
|
||||||
25
dao/src/sales_person.rs
Normal file
25
dao/src/sales_person.rs
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use async_trait::async_trait;
|
||||||
|
use mockall::automock;
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
use crate::DaoError;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub struct SalesPersonEntity {
|
||||||
|
pub id: Uuid,
|
||||||
|
pub name: Arc<str>,
|
||||||
|
pub deleted: Option<time::PrimitiveDateTime>,
|
||||||
|
pub inactive: bool,
|
||||||
|
pub version: Uuid,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[automock]
|
||||||
|
#[async_trait]
|
||||||
|
pub trait SalesPersonDao {
|
||||||
|
async fn all(&self) -> Result<Arc<[SalesPersonEntity]>, DaoError>;
|
||||||
|
async fn find_by_id(&self, id: Uuid) -> Result<Option<SalesPersonEntity>, DaoError>;
|
||||||
|
async fn create(&self, entity: &SalesPersonEntity, process: &str) -> Result<(), DaoError>;
|
||||||
|
async fn update(&self, entity: &SalesPersonEntity, process: &str) -> Result<(), DaoError>;
|
||||||
|
}
|
||||||
|
|
@ -6,6 +6,7 @@ use uuid::Uuid;
|
||||||
|
|
||||||
pub mod clock;
|
pub mod clock;
|
||||||
pub mod permission;
|
pub mod permission;
|
||||||
|
pub mod sales_person;
|
||||||
pub mod slot;
|
pub mod slot;
|
||||||
pub mod user_service;
|
pub mod user_service;
|
||||||
pub mod uuid_service;
|
pub mod uuid_service;
|
||||||
|
|
|
||||||
58
service/src/sales_person.rs
Normal file
58
service/src/sales_person.rs
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use async_trait::async_trait;
|
||||||
|
use mockall::automock;
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
use crate::ServiceError;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub struct SalesPerson {
|
||||||
|
pub id: Uuid,
|
||||||
|
pub name: Arc<str>,
|
||||||
|
pub inactive: bool,
|
||||||
|
pub deleted: Option<time::PrimitiveDateTime>,
|
||||||
|
pub version: Uuid,
|
||||||
|
}
|
||||||
|
impl From<&dao::sales_person::SalesPersonEntity> for SalesPerson {
|
||||||
|
fn from(sales_person: &dao::sales_person::SalesPersonEntity) -> Self {
|
||||||
|
Self {
|
||||||
|
id: sales_person.id,
|
||||||
|
name: sales_person.name.clone(),
|
||||||
|
inactive: sales_person.inactive,
|
||||||
|
deleted: sales_person.deleted,
|
||||||
|
version: sales_person.version,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl From<&SalesPerson> for dao::sales_person::SalesPersonEntity {
|
||||||
|
fn from(sales_person: &SalesPerson) -> Self {
|
||||||
|
Self {
|
||||||
|
id: sales_person.id,
|
||||||
|
name: sales_person.name.clone(),
|
||||||
|
inactive: sales_person.inactive,
|
||||||
|
deleted: sales_person.deleted,
|
||||||
|
version: sales_person.version,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[automock(type Context=();)]
|
||||||
|
#[async_trait]
|
||||||
|
pub trait SalesPersonService {
|
||||||
|
type Context: Clone + Send + Sync + 'static;
|
||||||
|
|
||||||
|
async fn get_all(&self, context: Self::Context) -> Result<Arc<[SalesPerson]>, ServiceError>;
|
||||||
|
async fn get(&self, id: Uuid, context: Self::Context) -> Result<SalesPerson, ServiceError>;
|
||||||
|
async fn create(
|
||||||
|
&self,
|
||||||
|
item: &SalesPerson,
|
||||||
|
context: Self::Context,
|
||||||
|
) -> Result<SalesPerson, ServiceError>;
|
||||||
|
async fn update(
|
||||||
|
&self,
|
||||||
|
item: &SalesPerson,
|
||||||
|
context: Self::Context,
|
||||||
|
) -> Result<SalesPerson, ServiceError>;
|
||||||
|
async fn delete(&self, id: Uuid, context: Self::Context) -> Result<(), ServiceError>;
|
||||||
|
}
|
||||||
|
|
@ -4,6 +4,7 @@ use async_trait::async_trait;
|
||||||
|
|
||||||
pub mod clock;
|
pub mod clock;
|
||||||
pub mod permission;
|
pub mod permission;
|
||||||
|
pub mod sales_person;
|
||||||
pub mod slot;
|
pub mod slot;
|
||||||
mod test;
|
mod test;
|
||||||
pub mod uuid_service;
|
pub mod uuid_service;
|
||||||
|
|
|
||||||
183
service_impl/src/sales_person.rs
Normal file
183
service_impl/src/sales_person.rs
Normal file
|
|
@ -0,0 +1,183 @@
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use async_trait::async_trait;
|
||||||
|
use dao::sales_person::SalesPersonEntity;
|
||||||
|
use service::{sales_person::SalesPerson, ServiceError, ValidationFailureItem};
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
pub struct SalesPersonServiceImpl<SalesPersonDao, PermissionService, ClockService, UuidService>
|
||||||
|
where
|
||||||
|
SalesPersonDao: dao::sales_person::SalesPersonDao + Send + Sync,
|
||||||
|
PermissionService: service::permission::PermissionService + Send + Sync,
|
||||||
|
ClockService: service::clock::ClockService + Send + Sync,
|
||||||
|
UuidService: service::uuid_service::UuidService + Send + Sync,
|
||||||
|
{
|
||||||
|
pub sales_person_dao: Arc<SalesPersonDao>,
|
||||||
|
pub permission_service: Arc<PermissionService>,
|
||||||
|
pub clock_service: Arc<ClockService>,
|
||||||
|
pub uuid_service: Arc<UuidService>,
|
||||||
|
}
|
||||||
|
impl<SalesPersonDao, PermissionService, ClockService, UuidService>
|
||||||
|
SalesPersonServiceImpl<SalesPersonDao, PermissionService, ClockService, UuidService>
|
||||||
|
where
|
||||||
|
SalesPersonDao: dao::sales_person::SalesPersonDao + Send + Sync,
|
||||||
|
PermissionService: service::permission::PermissionService + Send + Sync,
|
||||||
|
ClockService: service::clock::ClockService + Send + Sync,
|
||||||
|
UuidService: service::uuid_service::UuidService + Send + Sync,
|
||||||
|
{
|
||||||
|
pub fn new(
|
||||||
|
sales_person_dao: Arc<SalesPersonDao>,
|
||||||
|
permission_service: Arc<PermissionService>,
|
||||||
|
clock_service: Arc<ClockService>,
|
||||||
|
uuid_service: Arc<UuidService>,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
sales_person_dao,
|
||||||
|
permission_service,
|
||||||
|
clock_service,
|
||||||
|
uuid_service,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const SALES_PERSON_SERVICE_PROCESS: &str = "sales-person-service";
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl<SalesPersonDao, PermissionService, ClockService, UuidService>
|
||||||
|
service::sales_person::SalesPersonService
|
||||||
|
for SalesPersonServiceImpl<SalesPersonDao, PermissionService, ClockService, UuidService>
|
||||||
|
where
|
||||||
|
SalesPersonDao: dao::sales_person::SalesPersonDao + Send + Sync,
|
||||||
|
PermissionService: service::permission::PermissionService + Send + Sync,
|
||||||
|
ClockService: service::clock::ClockService + Send + Sync,
|
||||||
|
UuidService: service::uuid_service::UuidService + Send + Sync,
|
||||||
|
{
|
||||||
|
type Context = PermissionService::Context;
|
||||||
|
|
||||||
|
async fn get_all(
|
||||||
|
&self,
|
||||||
|
context: Self::Context,
|
||||||
|
) -> Result<Arc<[service::sales_person::SalesPerson]>, service::ServiceError> {
|
||||||
|
self.permission_service
|
||||||
|
.check_permission("hr", context)
|
||||||
|
.await?;
|
||||||
|
Ok(self
|
||||||
|
.sales_person_dao
|
||||||
|
.all()
|
||||||
|
.await?
|
||||||
|
.iter()
|
||||||
|
.map(SalesPerson::from)
|
||||||
|
.collect())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get(
|
||||||
|
&self,
|
||||||
|
id: Uuid,
|
||||||
|
context: Self::Context,
|
||||||
|
) -> Result<service::sales_person::SalesPerson, service::ServiceError> {
|
||||||
|
self.permission_service
|
||||||
|
.check_permission("hr", context)
|
||||||
|
.await?;
|
||||||
|
self.sales_person_dao
|
||||||
|
.find_by_id(id)
|
||||||
|
.await?
|
||||||
|
.as_ref()
|
||||||
|
.map(SalesPerson::from)
|
||||||
|
.ok_or(ServiceError::EntityNotFound(id))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn create(
|
||||||
|
&self,
|
||||||
|
sales_person: &SalesPerson,
|
||||||
|
context: Self::Context,
|
||||||
|
) -> Result<SalesPerson, service::ServiceError> {
|
||||||
|
self.permission_service
|
||||||
|
.check_permission("hr", context)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
if sales_person.id != Uuid::nil() {
|
||||||
|
return Err(ServiceError::IdSetOnCreate);
|
||||||
|
}
|
||||||
|
if sales_person.version != Uuid::nil() {
|
||||||
|
return Err(ServiceError::VersionSetOnCreate);
|
||||||
|
}
|
||||||
|
|
||||||
|
let sales_person = SalesPerson {
|
||||||
|
id: self.uuid_service.new_uuid("sales-person-id"),
|
||||||
|
version: self.uuid_service.new_uuid("sales-person-version"),
|
||||||
|
..sales_person.clone()
|
||||||
|
};
|
||||||
|
self.sales_person_dao
|
||||||
|
.create(
|
||||||
|
&SalesPersonEntity::from(&sales_person),
|
||||||
|
SALES_PERSON_SERVICE_PROCESS,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
Ok(sales_person)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn update(
|
||||||
|
&self,
|
||||||
|
sales_person: &SalesPerson,
|
||||||
|
context: Self::Context,
|
||||||
|
) -> Result<SalesPerson, ServiceError> {
|
||||||
|
self.permission_service
|
||||||
|
.check_permission("hr", context)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let sales_person_entity = self
|
||||||
|
.sales_person_dao
|
||||||
|
.find_by_id(sales_person.id)
|
||||||
|
.await?
|
||||||
|
.as_ref()
|
||||||
|
.map(SalesPerson::from)
|
||||||
|
.ok_or_else(move || ServiceError::EntityNotFound(sales_person.id))?;
|
||||||
|
|
||||||
|
if sales_person.version != sales_person_entity.version {
|
||||||
|
return Err(ServiceError::EntityConflicts(
|
||||||
|
sales_person.id,
|
||||||
|
sales_person_entity.version,
|
||||||
|
sales_person.version,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
if sales_person.deleted != sales_person_entity.deleted {
|
||||||
|
return Err(ServiceError::ValidationError(
|
||||||
|
[ValidationFailureItem::ModificationNotAllowed(
|
||||||
|
"deleted".into(),
|
||||||
|
)]
|
||||||
|
.into(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
let sales_person = SalesPerson {
|
||||||
|
version: self.uuid_service.new_uuid("sales-person-version"),
|
||||||
|
..sales_person.clone()
|
||||||
|
};
|
||||||
|
|
||||||
|
self.sales_person_dao
|
||||||
|
.update(
|
||||||
|
&SalesPersonEntity::from(&sales_person),
|
||||||
|
SALES_PERSON_SERVICE_PROCESS,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
Ok(sales_person)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn delete(&self, id: Uuid, context: Self::Context) -> Result<(), ServiceError> {
|
||||||
|
self.permission_service
|
||||||
|
.check_permission("hr", context)
|
||||||
|
.await?;
|
||||||
|
let mut sales_person_entity = self
|
||||||
|
.sales_person_dao
|
||||||
|
.find_by_id(id)
|
||||||
|
.await?
|
||||||
|
.ok_or(ServiceError::EntityNotFound(id))?;
|
||||||
|
sales_person_entity.deleted = Some(self.clock_service.date_time_now());
|
||||||
|
sales_person_entity.version = self.uuid_service.new_uuid("sales-person-version");
|
||||||
|
self.sales_person_dao
|
||||||
|
.update(&sales_person_entity, SALES_PERSON_SERVICE_PROCESS)
|
||||||
|
.await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -89,8 +89,8 @@ pub fn test_conflicts<T>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn test_validation_error(
|
pub fn test_validation_error<T>(
|
||||||
result: &Result<(), service::ServiceError>,
|
result: &Result<T, service::ServiceError>,
|
||||||
validation_failure: &ValidationFailureItem,
|
validation_failure: &ValidationFailureItem,
|
||||||
fail_count: usize,
|
fail_count: usize,
|
||||||
) {
|
) {
|
||||||
|
|
|
||||||
|
|
@ -3,4 +3,6 @@ pub mod error_test;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod permission_test;
|
mod permission_test;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
pub mod sales_person;
|
||||||
|
#[cfg(test)]
|
||||||
pub mod slot;
|
pub mod slot;
|
||||||
|
|
|
||||||
519
service_impl/src/test/sales_person.rs
Normal file
519
service_impl/src/test/sales_person.rs
Normal file
|
|
@ -0,0 +1,519 @@
|
||||||
|
use super::error_test::*;
|
||||||
|
use dao::sales_person::{MockSalesPersonDao, SalesPersonEntity};
|
||||||
|
use mockall::predicate::eq;
|
||||||
|
use service::{
|
||||||
|
clock::MockClockService,
|
||||||
|
sales_person::{SalesPerson, SalesPersonService},
|
||||||
|
uuid_service::MockUuidService,
|
||||||
|
MockPermissionService,
|
||||||
|
};
|
||||||
|
use time::{Date, Month, PrimitiveDateTime, Time};
|
||||||
|
use tokio;
|
||||||
|
use uuid::{uuid, Uuid};
|
||||||
|
|
||||||
|
use crate::sales_person::SalesPersonServiceImpl;
|
||||||
|
|
||||||
|
pub struct SalesPersonServiceDependencies {
|
||||||
|
pub sales_person_dao: MockSalesPersonDao,
|
||||||
|
pub permission_service: MockPermissionService,
|
||||||
|
pub clock_service: MockClockService,
|
||||||
|
pub uuid_service: MockUuidService,
|
||||||
|
}
|
||||||
|
impl SalesPersonServiceDependencies {
|
||||||
|
pub fn build_service(
|
||||||
|
self,
|
||||||
|
) -> SalesPersonServiceImpl<
|
||||||
|
MockSalesPersonDao,
|
||||||
|
MockPermissionService,
|
||||||
|
MockClockService,
|
||||||
|
MockUuidService,
|
||||||
|
> {
|
||||||
|
SalesPersonServiceImpl::new(
|
||||||
|
self.sales_person_dao.into(),
|
||||||
|
self.permission_service.into(),
|
||||||
|
self.clock_service.into(),
|
||||||
|
self.uuid_service.into(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn build_dependencies(permission: bool, role: &'static str) -> SalesPersonServiceDependencies {
|
||||||
|
let sales_person_dao = MockSalesPersonDao::new();
|
||||||
|
let mut permission_service = MockPermissionService::new();
|
||||||
|
permission_service
|
||||||
|
.expect_check_permission()
|
||||||
|
.with(eq(role), eq(()))
|
||||||
|
.returning(move |_, _| {
|
||||||
|
if permission {
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(service::ServiceError::Forbidden)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
permission_service
|
||||||
|
.expect_check_permission()
|
||||||
|
.returning(move |_, _| Err(service::ServiceError::Forbidden));
|
||||||
|
let mut clock_service = MockClockService::new();
|
||||||
|
clock_service
|
||||||
|
.expect_time_now()
|
||||||
|
.returning(|| time::Time::from_hms(23, 42, 0).unwrap());
|
||||||
|
clock_service
|
||||||
|
.expect_date_now()
|
||||||
|
.returning(|| time::Date::from_calendar_date(2063, 4.try_into().unwrap(), 5).unwrap());
|
||||||
|
clock_service.expect_date_time_now().returning(|| {
|
||||||
|
time::PrimitiveDateTime::new(
|
||||||
|
time::Date::from_calendar_date(2063, 4.try_into().unwrap(), 5).unwrap(),
|
||||||
|
time::Time::from_hms(23, 42, 0).unwrap(),
|
||||||
|
)
|
||||||
|
});
|
||||||
|
let uuid_service = MockUuidService::new();
|
||||||
|
|
||||||
|
SalesPersonServiceDependencies {
|
||||||
|
sales_person_dao,
|
||||||
|
permission_service,
|
||||||
|
clock_service,
|
||||||
|
uuid_service,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn default_id() -> uuid::Uuid {
|
||||||
|
uuid!("67D91F86-2EC7-4FA6-8EB4-9C76A2D4C6E0")
|
||||||
|
}
|
||||||
|
pub fn alternate_id() -> uuid::Uuid {
|
||||||
|
uuid!("67D91F86-2EC7-4FA6-8EB4-9C76A2D4C6E1")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn default_version() -> uuid::Uuid {
|
||||||
|
uuid!("CCB5F4E2-8C7D-4388-AC4E-641D43ADF580")
|
||||||
|
}
|
||||||
|
pub fn alternate_version() -> uuid::Uuid {
|
||||||
|
uuid!("CCB5F4E2-8C7D-4388-AC4E-641D43ADF581")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn default_sales_person_entity() -> dao::sales_person::SalesPersonEntity {
|
||||||
|
dao::sales_person::SalesPersonEntity {
|
||||||
|
id: default_id(),
|
||||||
|
name: "John Doe".into(),
|
||||||
|
deleted: None,
|
||||||
|
inactive: false,
|
||||||
|
version: default_version(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn default_sales_person() -> service::sales_person::SalesPerson {
|
||||||
|
service::sales_person::SalesPerson {
|
||||||
|
id: default_id(),
|
||||||
|
name: "John Doe".into(),
|
||||||
|
inactive: false,
|
||||||
|
deleted: None,
|
||||||
|
version: default_version(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_get_all() {
|
||||||
|
let mut dependencies = build_dependencies(true, "hr");
|
||||||
|
dependencies.sales_person_dao.expect_all().returning(|| {
|
||||||
|
Ok([
|
||||||
|
default_sales_person_entity(),
|
||||||
|
SalesPersonEntity {
|
||||||
|
id: alternate_id(),
|
||||||
|
name: "Jane Doe".into(),
|
||||||
|
..default_sales_person_entity()
|
||||||
|
},
|
||||||
|
]
|
||||||
|
.into())
|
||||||
|
});
|
||||||
|
let sales_person_service = dependencies.build_service();
|
||||||
|
let result = sales_person_service.get_all(()).await.unwrap();
|
||||||
|
assert_eq!(2, result.len());
|
||||||
|
assert_eq!(default_sales_person(), result[0]);
|
||||||
|
assert_eq!(
|
||||||
|
service::sales_person::SalesPerson {
|
||||||
|
id: alternate_id(),
|
||||||
|
name: "Jane Doe".into(),
|
||||||
|
..default_sales_person()
|
||||||
|
},
|
||||||
|
result[1]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_get_all_no_permission() {
|
||||||
|
let dependencies = build_dependencies(false, "hr");
|
||||||
|
let sales_person_service = dependencies.build_service();
|
||||||
|
let result = sales_person_service.get_all(()).await;
|
||||||
|
test_forbidden(&result);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_get() {
|
||||||
|
let mut dependencies = build_dependencies(true, "hr");
|
||||||
|
dependencies
|
||||||
|
.sales_person_dao
|
||||||
|
.expect_find_by_id()
|
||||||
|
.with(eq(default_id()))
|
||||||
|
.times(1)
|
||||||
|
.returning(|_| Ok(Some(default_sales_person_entity())));
|
||||||
|
let sales_person_service = dependencies.build_service();
|
||||||
|
let result = sales_person_service.get(default_id(), ()).await;
|
||||||
|
assert_eq!(default_sales_person(), result.unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_get_no_permission() {
|
||||||
|
let dependencies = build_dependencies(false, "hr");
|
||||||
|
let sales_person_service = dependencies.build_service();
|
||||||
|
let result = sales_person_service.get(default_id(), ()).await;
|
||||||
|
test_forbidden(&result);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_get_not_found() {
|
||||||
|
let mut dependencies = build_dependencies(true, "hr");
|
||||||
|
dependencies
|
||||||
|
.sales_person_dao
|
||||||
|
.expect_find_by_id()
|
||||||
|
.with(eq(default_id()))
|
||||||
|
.times(1)
|
||||||
|
.returning(|_| Ok(None));
|
||||||
|
let sales_person_service = dependencies.build_service();
|
||||||
|
let result = sales_person_service.get(default_id(), ()).await;
|
||||||
|
test_not_found(&result, &default_id());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_create() {
|
||||||
|
let mut dependencies = build_dependencies(true, "hr");
|
||||||
|
dependencies
|
||||||
|
.sales_person_dao
|
||||||
|
.expect_create()
|
||||||
|
.with(
|
||||||
|
eq(default_sales_person_entity()),
|
||||||
|
eq("sales-person-service"),
|
||||||
|
)
|
||||||
|
.times(1)
|
||||||
|
.returning(|_, _| Ok(()));
|
||||||
|
dependencies
|
||||||
|
.uuid_service
|
||||||
|
.expect_new_uuid()
|
||||||
|
.with(eq("sales-person-id"))
|
||||||
|
.times(1)
|
||||||
|
.returning(|_| default_id());
|
||||||
|
dependencies
|
||||||
|
.uuid_service
|
||||||
|
.expect_new_uuid()
|
||||||
|
.with(eq("sales-person-version"))
|
||||||
|
.times(1)
|
||||||
|
.returning(|_| default_version());
|
||||||
|
let sales_person_service = dependencies.build_service();
|
||||||
|
let result = sales_person_service
|
||||||
|
.create(
|
||||||
|
&SalesPerson {
|
||||||
|
id: Uuid::nil(),
|
||||||
|
version: Uuid::nil(),
|
||||||
|
..default_sales_person()
|
||||||
|
},
|
||||||
|
(),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(result, default_sales_person());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_create_no_permission() {
|
||||||
|
let dependencies = build_dependencies(false, "hr");
|
||||||
|
let sales_person_service = dependencies.build_service();
|
||||||
|
let result = sales_person_service
|
||||||
|
.create(
|
||||||
|
&SalesPerson {
|
||||||
|
id: Uuid::nil(),
|
||||||
|
version: Uuid::nil(),
|
||||||
|
..default_sales_person()
|
||||||
|
},
|
||||||
|
(),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
test_forbidden(&result);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_create_validation() {
|
||||||
|
let mut dependencies = build_dependencies(true, "hr");
|
||||||
|
dependencies
|
||||||
|
.uuid_service
|
||||||
|
.expect_new_uuid()
|
||||||
|
.with(eq("sales-person-id"))
|
||||||
|
.returning(|_| default_id());
|
||||||
|
dependencies
|
||||||
|
.uuid_service
|
||||||
|
.expect_new_uuid()
|
||||||
|
.with(eq("sales-person-version"))
|
||||||
|
.returning(|_| default_version());
|
||||||
|
|
||||||
|
let sales_person_service = dependencies.build_service();
|
||||||
|
let result = sales_person_service
|
||||||
|
.create(
|
||||||
|
&SalesPerson {
|
||||||
|
version: Uuid::nil(),
|
||||||
|
..default_sales_person()
|
||||||
|
},
|
||||||
|
(),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
test_zero_id_error(&result);
|
||||||
|
|
||||||
|
let result = sales_person_service
|
||||||
|
.create(
|
||||||
|
&SalesPerson {
|
||||||
|
id: Uuid::nil(),
|
||||||
|
..default_sales_person()
|
||||||
|
},
|
||||||
|
(),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
test_zero_version_error(&result);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_update_no_permission() {
|
||||||
|
let dependencies = build_dependencies(false, "hr");
|
||||||
|
let sales_person_service = dependencies.build_service();
|
||||||
|
let result = sales_person_service
|
||||||
|
.update(
|
||||||
|
&SalesPerson {
|
||||||
|
name: "Jane Doe".into(),
|
||||||
|
..default_sales_person()
|
||||||
|
},
|
||||||
|
(),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
test_forbidden(&result);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_update_not_found() {
|
||||||
|
let mut dependencies = build_dependencies(true, "hr");
|
||||||
|
dependencies
|
||||||
|
.sales_person_dao
|
||||||
|
.expect_find_by_id()
|
||||||
|
.with(eq(default_id()))
|
||||||
|
.returning(|_| Ok(None));
|
||||||
|
let sales_person_service = dependencies.build_service();
|
||||||
|
let result = sales_person_service
|
||||||
|
.update(
|
||||||
|
&SalesPerson {
|
||||||
|
name: "Jane Doe".into(),
|
||||||
|
..default_sales_person()
|
||||||
|
},
|
||||||
|
(),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
test_not_found(&result, &default_id());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_update_conflicts() {
|
||||||
|
let mut dependencies = build_dependencies(true, "hr");
|
||||||
|
dependencies
|
||||||
|
.sales_person_dao
|
||||||
|
.expect_find_by_id()
|
||||||
|
.with(eq(default_id()))
|
||||||
|
.returning(|_| Ok(Some(default_sales_person_entity())));
|
||||||
|
let sales_person_service = dependencies.build_service();
|
||||||
|
let result = sales_person_service
|
||||||
|
.update(
|
||||||
|
&SalesPerson {
|
||||||
|
version: alternate_version(),
|
||||||
|
..default_sales_person()
|
||||||
|
},
|
||||||
|
(),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
test_conflicts(
|
||||||
|
&result,
|
||||||
|
&default_id(),
|
||||||
|
&default_version(),
|
||||||
|
&alternate_version(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_update_deleted_no_allowed() {
|
||||||
|
let mut dependencies = build_dependencies(true, "hr");
|
||||||
|
dependencies
|
||||||
|
.sales_person_dao
|
||||||
|
.expect_find_by_id()
|
||||||
|
.with(eq(default_id()))
|
||||||
|
.returning(|_| Ok(Some(default_sales_person_entity())));
|
||||||
|
let sales_person_service = dependencies.build_service();
|
||||||
|
let result = sales_person_service
|
||||||
|
.update(
|
||||||
|
&SalesPerson {
|
||||||
|
deleted: Some(PrimitiveDateTime::new(
|
||||||
|
Date::from_calendar_date(2000, Month::January, 1).unwrap(),
|
||||||
|
Time::from_hms(1, 0, 0).unwrap(),
|
||||||
|
)),
|
||||||
|
..default_sales_person()
|
||||||
|
},
|
||||||
|
(),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
test_validation_error(
|
||||||
|
&result,
|
||||||
|
&service::ValidationFailureItem::ModificationNotAllowed("deleted".into()),
|
||||||
|
1,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_update_inactive() {
|
||||||
|
let mut dependencies = build_dependencies(true, "hr");
|
||||||
|
dependencies
|
||||||
|
.sales_person_dao
|
||||||
|
.expect_find_by_id()
|
||||||
|
.with(eq(default_id()))
|
||||||
|
.returning(|_| Ok(Some(default_sales_person_entity())));
|
||||||
|
dependencies
|
||||||
|
.sales_person_dao
|
||||||
|
.expect_update()
|
||||||
|
.with(
|
||||||
|
eq(SalesPersonEntity {
|
||||||
|
inactive: true,
|
||||||
|
version: alternate_version(),
|
||||||
|
..default_sales_person_entity()
|
||||||
|
}),
|
||||||
|
eq("sales-person-service"),
|
||||||
|
)
|
||||||
|
.returning(|_, _| Ok(()));
|
||||||
|
dependencies
|
||||||
|
.uuid_service
|
||||||
|
.expect_new_uuid()
|
||||||
|
.with(eq("sales-person-version"))
|
||||||
|
.returning(|_| alternate_version());
|
||||||
|
let sales_person_service = dependencies.build_service();
|
||||||
|
let result = sales_person_service
|
||||||
|
.update(
|
||||||
|
&SalesPerson {
|
||||||
|
inactive: true,
|
||||||
|
..default_sales_person()
|
||||||
|
},
|
||||||
|
(),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
result,
|
||||||
|
SalesPerson {
|
||||||
|
inactive: true,
|
||||||
|
version: alternate_version(),
|
||||||
|
..default_sales_person()
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_update_name() {
|
||||||
|
let mut dependencies = build_dependencies(true, "hr");
|
||||||
|
dependencies
|
||||||
|
.sales_person_dao
|
||||||
|
.expect_find_by_id()
|
||||||
|
.with(eq(default_id()))
|
||||||
|
.returning(|_| Ok(Some(default_sales_person_entity())));
|
||||||
|
dependencies
|
||||||
|
.sales_person_dao
|
||||||
|
.expect_update()
|
||||||
|
.with(
|
||||||
|
eq(SalesPersonEntity {
|
||||||
|
name: "Jane Doe".into(),
|
||||||
|
version: alternate_version(),
|
||||||
|
..default_sales_person_entity()
|
||||||
|
}),
|
||||||
|
eq("sales-person-service"),
|
||||||
|
)
|
||||||
|
.returning(|_, _| Ok(()));
|
||||||
|
dependencies
|
||||||
|
.uuid_service
|
||||||
|
.expect_new_uuid()
|
||||||
|
.with(eq("sales-person-version"))
|
||||||
|
.returning(|_| alternate_version());
|
||||||
|
let sales_person_service = dependencies.build_service();
|
||||||
|
let result = sales_person_service
|
||||||
|
.update(
|
||||||
|
&SalesPerson {
|
||||||
|
name: "Jane Doe".into(),
|
||||||
|
..default_sales_person()
|
||||||
|
},
|
||||||
|
(),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
result,
|
||||||
|
SalesPerson {
|
||||||
|
name: "Jane Doe".into(),
|
||||||
|
version: alternate_version(),
|
||||||
|
..default_sales_person()
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_delete() {
|
||||||
|
let mut dependencies = build_dependencies(true, "hr");
|
||||||
|
dependencies
|
||||||
|
.sales_person_dao
|
||||||
|
.expect_find_by_id()
|
||||||
|
.with(eq(default_id()))
|
||||||
|
.returning(|_| Ok(Some(default_sales_person_entity())));
|
||||||
|
dependencies
|
||||||
|
.sales_person_dao
|
||||||
|
.expect_update()
|
||||||
|
.with(
|
||||||
|
eq(SalesPersonEntity {
|
||||||
|
deleted: Some(PrimitiveDateTime::new(
|
||||||
|
Date::from_calendar_date(2063, Month::April, 5).unwrap(),
|
||||||
|
Time::from_hms(23, 42, 0).unwrap(),
|
||||||
|
)),
|
||||||
|
version: alternate_version(),
|
||||||
|
..default_sales_person_entity()
|
||||||
|
}),
|
||||||
|
eq("sales-person-service"),
|
||||||
|
)
|
||||||
|
.returning(|_, _| Ok(()));
|
||||||
|
dependencies
|
||||||
|
.uuid_service
|
||||||
|
.expect_new_uuid()
|
||||||
|
.with(eq("sales-person-version"))
|
||||||
|
.returning(|_| alternate_version());
|
||||||
|
let sales_person_service = dependencies.build_service();
|
||||||
|
let result = sales_person_service.delete(default_id(), ()).await;
|
||||||
|
assert!(result.is_ok());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_delete_no_permission() {
|
||||||
|
let mut dependencies = build_dependencies(false, "hr");
|
||||||
|
dependencies
|
||||||
|
.sales_person_dao
|
||||||
|
.expect_find_by_id()
|
||||||
|
.with(eq(default_id()))
|
||||||
|
.returning(|_| Ok(Some(default_sales_person_entity())));
|
||||||
|
let sales_person_service = dependencies.build_service();
|
||||||
|
let result = sales_person_service.delete(default_id(), ()).await;
|
||||||
|
test_forbidden(&result);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_delete_not_found() {
|
||||||
|
let mut dependencies = build_dependencies(true, "hr");
|
||||||
|
dependencies
|
||||||
|
.sales_person_dao
|
||||||
|
.expect_find_by_id()
|
||||||
|
.with(eq(default_id()))
|
||||||
|
.returning(|_| Ok(None));
|
||||||
|
let sales_person_service = dependencies.build_service();
|
||||||
|
let result = sales_person_service.delete(default_id(), ()).await;
|
||||||
|
test_not_found(&result, &default_id());
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue