@@ -584,13 +584,13 @@ export class BookingFormService extends AsyncHandler {
584584 details . loading ( i18n ( 'BOOKINGS.CONFIRM_LOADING' ) ) ;
585585 if ( options . group ) {
586586 await this . postFormForGroup ( ) . catch ( ( _ ) => {
587- notifyError ( JSON . stringify ( _ ) ) ;
587+ notifyError ( this . _error_message ( _ ) ) ;
588588 details . close ( ) ;
589589 throw _ ;
590590 } ) ;
591591 } else
592592 await this . postForm ( ) . catch ( ( _ ) => {
593- notifyError ( JSON . stringify ( _ ) ) ;
593+ notifyError ( this . _error_message ( _ ) ) ;
594594 details . close ( ) ;
595595 throw _ ;
596596 } ) ;
@@ -778,7 +778,8 @@ export class BookingFormService extends AsyncHandler {
778778 if ( ! group ) throw i18n ( 'BOOKINGS.GROUP_NOT_SET' ) ;
779779 const rollback_on_group_error =
780780 this . setting ( 'rollback_group_bookings' ) === true ;
781- const extra_members = members . filter (
781+ const member_list = members || [ ] ;
782+ const extra_members = member_list . filter (
782783 ( _ ) => _ . email !== currentUser ( ) . email ,
783784 ) ;
784785 if ( extra_members . length <= 0 ) throw i18n ( 'BOOKINGS.GROUP_NO_MEMBERS' ) ;
@@ -788,9 +789,12 @@ export class BookingFormService extends AsyncHandler {
788789 ( _ ) => _ . id === form . asset_id || _ . map_id === form . asset_id ,
789790 ) ;
790791 if ( ! active_resource ) {
791- throw 'Selected resource is no longer available' ;
792+ throw i18n ( 'BOOKINGS.DESK_AVAILABLE_ERROR' ) ;
792793 }
793794 const level = this . _org . levelWithID ( [ active_resource . zone ?. id ] ) ;
795+ if ( ! level ?. map_id ) {
796+ throw i18n ( 'BOOKINGS.GROUP_MAP_UNAVAILABLE' ) ;
797+ }
794798 const resources = [
795799 active_resource ,
796800 ...( await this . _getNearbyResources (
@@ -804,18 +808,37 @@ export class BookingFormService extends AsyncHandler {
804808 [ currentUser ( ) , ...extra_members ] ,
805809 'email' ,
806810 ) ;
811+ if ( resources . length < group_members . length ) {
812+ throw i18n ( 'BOOKINGS.GROUP_INSUFFICIENT_RESOURCES' , {
813+ available : resources . length ,
814+ members : group_members . length ,
815+ } ) ;
816+ }
817+ const unavailable_errors : string [ ] = [ ] ;
807818 const available = await Promise . all (
808- group_members . map ( ( _ , idx ) => {
819+ group_members . map ( async ( member , idx ) => {
809820 const resource = resources [ idx ] ;
810- if ( ! resource ) return false ;
811- return this . _checkResourceAvailable (
812- {
813- ...form ,
814- asset_id : resource . map_id || resource . id ,
815- user_email : _ . email ,
816- } ,
817- type ,
818- ) ;
821+ if ( ! resource ) {
822+ unavailable_errors . push (
823+ `${ member . name || member . email } : ${ i18n ( 'BOOKINGS.GROUP_MEMBER_NO_RESOURCE' ) } ` ,
824+ ) ;
825+ return false ;
826+ }
827+ try {
828+ return await this . _checkResourceAvailable (
829+ {
830+ ...form ,
831+ asset_id : resource . map_id || resource . id ,
832+ user_email : member . email ,
833+ } ,
834+ type ,
835+ ) ;
836+ } catch ( error ) {
837+ unavailable_errors . push (
838+ `${ member . name || member . email } : ${ this . _error_message ( error ) } ` ,
839+ ) ;
840+ return false ;
841+ }
819842 } ) ,
820843 ) ;
821844 const unavailable = group_members . filter ( ( _ , idx ) => ! available [ idx ] ) ;
@@ -858,27 +881,43 @@ export class BookingFormService extends AsyncHandler {
858881 : [ this . _org . organisation . id , this . _org . region ?. id ]
859882 ) . filter ( ( _ ) => _ ) ,
860883 } ) ;
861- const bkn = await this . postForm ( true ) ;
884+ const bkn = await this . postForm ( true ) . catch ( ( error ) => {
885+ throw `${ user . name || user . email } : ${ this . _error_message ( error ) } ` ;
886+ } ) ;
862887 if ( bkn ?. id ) booking_ids . push ( bkn . id ) ;
863888 if ( bkn . id && ! id ) id = bkn . id ;
864889 if ( bkn . user_email === currentUser ( ) . email ) user_booking = bkn ;
865890 }
866891 if ( unavailable . length ) {
892+ const unavailable_error = unavailable_errors . length
893+ ? unavailable_errors . join ( '\n' )
894+ : group_error ;
867895 if ( rollback_on_group_error ) {
868896 await this . rollbackGroupBookings ( booking_ids ) ;
869- throw group_error ;
897+ throw unavailable_error ;
870898 }
871- notifyWarn ( group_error ) ;
899+ notifyWarn ( unavailable_error ) ;
872900 }
873901 } catch ( error ) {
874902 if ( rollback_on_group_error && booking_ids . length ) {
875903 await this . rollbackGroupBookings ( booking_ids ) ;
876904 }
877- throw error ;
905+ throw this . _error_message ( error ) ;
878906 }
879907 return user_booking ;
880908 }
881909
910+ private _error_message ( error : any ) {
911+ if ( typeof error === 'string' ) return error ;
912+ if ( error instanceof Error && error . message ) return error . message ;
913+ if ( typeof error ?. error === 'string' ) return error . error ;
914+ if ( typeof error ?. message === 'string' ) return error . message ;
915+ if ( typeof error ?. error ?. message === 'string' ) {
916+ return error . error . message ;
917+ }
918+ return i18n ( 'BOOKINGS.ERROR_GENERIC' ) ;
919+ }
920+
882921 private async rollbackGroupBookings ( booking_ids : string [ ] ) {
883922 const rollback_errors = (
884923 await Promise . allSettled (
0 commit comments