1
- use super :: error:: { EntityApiErrorKind , Error } ;
1
+ use super :: {
2
+ error:: { EntityApiErrorKind , Error } ,
3
+ organization,
4
+ } ;
2
5
use crate :: user;
3
6
use chrono:: Utc ;
4
7
use entity:: {
@@ -16,17 +19,42 @@ use slugify::slugify;
16
19
17
20
pub async fn create (
18
21
db : & impl ConnectionTrait ,
22
+ organization_id : Id ,
19
23
coaching_relationship_model : Model ,
20
- ) -> Result < Model , Error > {
24
+ ) -> Result < CoachingRelationshipWithUserNames , Error > {
21
25
debug ! (
22
26
"New Coaching Relationship Model to be inserted: {:?}" ,
23
27
coaching_relationship_model
24
28
) ;
25
29
30
+ let coach = user:: find_by_id ( db, coaching_relationship_model. coach_id ) . await ?;
31
+ let coachee = user:: find_by_id ( db, coaching_relationship_model. coachee_id ) . await ?;
32
+
33
+ let coach_organization_ids = organization:: find_by_user ( db, coach. id )
34
+ . await ?
35
+ . iter ( )
36
+ . map ( |org| org. id )
37
+ . collect :: < Vec < Id > > ( ) ;
38
+ let coachee_organization_ids = organization:: find_by_user ( db, coachee. id )
39
+ . await ?
40
+ . iter ( )
41
+ . map ( |org| org. id )
42
+ . collect :: < Vec < Id > > ( ) ;
43
+
44
+ // Check that the coach and coachee belong to the correct organization
45
+ if !coach_organization_ids. contains ( & organization_id)
46
+ || !coachee_organization_ids. contains ( & organization_id)
47
+ {
48
+ error ! ( "Coach and coachee do not belong to the correct organization, not creating requested new coaching relationship between coach: {:?} and coachee: {:?} for organization: {:?}." , coaching_relationship_model. coach_id, coaching_relationship_model. coachee_id, organization_id) ;
49
+ return Err ( Error {
50
+ source : None ,
51
+ error_kind : EntityApiErrorKind :: ValidationError ,
52
+ } ) ;
53
+ }
54
+
26
55
// Coaching Relationship must be unique within the context of an organization
27
56
// Note: this is enforced at the database level as well
28
- let existing_coaching_relationships =
29
- find_by_organization ( db, coaching_relationship_model. organization_id ) . await ?;
57
+ let existing_coaching_relationships = find_by_organization ( db, organization_id) . await ?;
30
58
let existing_coaching_relationship = existing_coaching_relationships. iter ( ) . find ( |cr| {
31
59
cr. coach_id == coaching_relationship_model. coach_id
32
60
&& cr. coachee_id == coaching_relationship_model. coachee_id
@@ -46,15 +74,27 @@ pub async fn create(
46
74
let slug = slugify ! ( format!( "{} {}" , coach. first_name, coachee. first_name) . as_str( ) ) ;
47
75
48
76
let coaching_relationship_active_model: ActiveModel = ActiveModel {
49
- organization_id : Set ( coaching_relationship_model . organization_id ) ,
77
+ organization_id : Set ( organization_id) ,
50
78
coach_id : Set ( coaching_relationship_model. coach_id ) ,
51
79
coachee_id : Set ( coaching_relationship_model. coachee_id ) ,
52
80
slug : Set ( slug) ,
53
81
created_at : Set ( now. into ( ) ) ,
54
82
updated_at : Set ( now. into ( ) ) ,
55
83
..Default :: default ( )
56
84
} ;
57
- Ok ( coaching_relationship_active_model. insert ( db) . await ?)
85
+ let inserted: Model = coaching_relationship_active_model. insert ( db) . await ?;
86
+
87
+ Ok ( CoachingRelationshipWithUserNames {
88
+ id : inserted. id ,
89
+ coach_id : inserted. coach_id ,
90
+ coachee_id : inserted. coachee_id ,
91
+ coach_first_name : coach. first_name ,
92
+ coach_last_name : coach. last_name ,
93
+ coachee_first_name : coachee. first_name ,
94
+ coachee_last_name : coachee. last_name ,
95
+ created_at : inserted. created_at ,
96
+ updated_at : inserted. updated_at ,
97
+ } )
58
98
}
59
99
60
100
pub async fn find_by_id ( db : & DatabaseConnection , id : Id ) -> Result < Model , Error > {
@@ -206,7 +246,7 @@ pub async fn delete_by_user_id(db: &impl ConnectionTrait, user_id: Id) -> Result
206
246
207
247
// A convenient combined struct that holds the results of looking up the Users associated
208
248
// with the coach/coachee ids. This should be used as an implementation detail only.
209
- #[ derive( FromQueryResult , Debug ) ]
249
+ #[ derive( FromQueryResult , Debug , PartialEq ) ]
210
250
pub struct CoachingRelationshipWithUserNames {
211
251
pub id : Id ,
212
252
pub coach_id : Id ,
@@ -337,26 +377,76 @@ mod tests {
337
377
#[ tokio:: test]
338
378
async fn create_returns_validation_error_for_duplicate_relationship ( ) -> Result < ( ) , Error > {
339
379
use entity:: coaching_relationships:: Model ;
340
- use sea_orm:: { DatabaseBackend , MockDatabase , MockExecResult } ;
380
+ use sea_orm:: { DatabaseBackend , MockDatabase } ;
341
381
342
382
let organization_id = Id :: new_v4 ( ) ;
343
383
let coach_id = Id :: new_v4 ( ) ;
344
384
let coachee_id = Id :: new_v4 ( ) ;
385
+ let coach_organization_id = Id :: new_v4 ( ) ;
386
+ let coachee_organization_id = Id :: new_v4 ( ) ;
387
+
388
+ let coach_user = entity:: users:: Model {
389
+ id : coach_id. clone ( ) ,
390
+ first_name : "Coach" . to_string ( ) ,
391
+ last_name : "User" . to_string ( ) ,
392
+ email : "[email protected] " . to_string ( ) ,
393
+ password : "hash" . to_string ( ) ,
394
+ display_name : Some ( "Coach User" . to_string ( ) ) ,
395
+ github_username : Some ( "coach_user" . to_string ( ) ) ,
396
+ role : entity:: users:: Role :: User ,
397
+ github_profile_url : Some ( "https://github.com/coach_user" . to_string ( ) ) ,
398
+ created_at : chrono:: Utc :: now ( ) . into ( ) ,
399
+ updated_at : chrono:: Utc :: now ( ) . into ( ) ,
400
+ } ;
401
+
402
+ let coachee_user = entity:: users:: Model {
403
+ id : coachee_id. clone ( ) ,
404
+ first_name : "Coachee" . to_string ( ) ,
405
+ last_name : "User" . to_string ( ) ,
406
+ email : "[email protected] " . to_string ( ) ,
407
+ password : "hash" . to_string ( ) ,
408
+ display_name : Some ( "Coachee User" . to_string ( ) ) ,
409
+ github_username : Some ( "coachee_user" . to_string ( ) ) ,
410
+ role : entity:: users:: Role :: User ,
411
+ github_profile_url : Some ( "https://github.com/coachee_user" . to_string ( ) ) ,
412
+ created_at : chrono:: Utc :: now ( ) . into ( ) ,
413
+ updated_at : chrono:: Utc :: now ( ) . into ( ) ,
414
+ } ;
415
+
416
+ let coaching_relationships = vec ! [ Model {
417
+ id: Id :: new_v4( ) ,
418
+ organization_id: organization_id. clone( ) ,
419
+ coach_id: coach_id. clone( ) ,
420
+ coachee_id: coachee_id. clone( ) ,
421
+ slug: "coach-coachee" . to_string( ) ,
422
+ created_at: chrono:: Utc :: now( ) . into( ) ,
423
+ updated_at: chrono:: Utc :: now( ) . into( ) ,
424
+ } ] ;
425
+
426
+ let coach_organization = entity:: organizations:: Model {
427
+ id : coach_organization_id,
428
+ name : "Organization" . to_string ( ) ,
429
+ slug : "organization" . to_string ( ) ,
430
+ logo : None ,
431
+ created_at : chrono:: Utc :: now ( ) . into ( ) ,
432
+ updated_at : chrono:: Utc :: now ( ) . into ( ) ,
433
+ } ;
434
+
435
+ let coachee_organization = entity:: organizations:: Model {
436
+ id : coachee_organization_id,
437
+ name : "Organization" . to_string ( ) ,
438
+ slug : "organization" . to_string ( ) ,
439
+ logo : None ,
440
+ created_at : chrono:: Utc :: now ( ) . into ( ) ,
441
+ updated_at : chrono:: Utc :: now ( ) . into ( ) ,
442
+ } ;
345
443
346
444
let db = MockDatabase :: new ( DatabaseBackend :: Postgres )
347
- . append_query_results ( vec ! [ vec![ Model {
348
- id: Id :: new_v4( ) ,
349
- organization_id: organization_id. clone( ) ,
350
- coach_id: coach_id. clone( ) ,
351
- coachee_id: coachee_id. clone( ) ,
352
- slug: "coach-coachee" . to_string( ) ,
353
- created_at: chrono:: Utc :: now( ) . into( ) ,
354
- updated_at: chrono:: Utc :: now( ) . into( ) ,
355
- } ] ] )
356
- . append_exec_results ( vec ! [ MockExecResult {
357
- last_insert_id: 0 ,
358
- rows_affected: 1 ,
359
- } ] )
445
+ . append_query_results ( vec ! [ vec![ coach_user] ] )
446
+ . append_query_results ( vec ! [ vec![ coachee_user] ] )
447
+ . append_query_results ( vec ! [ vec![ coach_organization] ] )
448
+ . append_query_results ( vec ! [ vec![ coachee_organization] ] )
449
+ . append_query_results ( vec ! [ coaching_relationships] )
360
450
. into_connection ( ) ;
361
451
362
452
let model = Model {
@@ -369,7 +459,8 @@ mod tests {
369
459
updated_at : chrono:: Utc :: now ( ) . into ( ) ,
370
460
} ;
371
461
372
- let result = create ( & db, model) . await ;
462
+ let result = create ( & db, organization_id, model) . await ;
463
+ println ! ( "Result: {:?}" , result) ;
373
464
assert ! (
374
465
result
375
466
== Err ( Error {
0 commit comments