@@ -714,4 +714,172 @@ module.exports = class ProgramUsersHelper {
714714 }
715715 }
716716 }
717+
718+ /**
719+ * Check if logged-in user has the participant assigned in programUsers
720+ * @method
721+ * @name checkParticipantAssigned
722+ * @param {String } loggedInUserId - logged in user's userId
723+ * @param {String } participantUserId - participant's userId to check
724+ * @param {String } participantEntityId - participant's entityId to check
725+ * @param {String } tenantId - tenant ID
726+ * @returns {Promise<Object> } result with success status and programUsers document if found
727+ */
728+ static async checkParticipantAssigned ( loggedInUserId , participantUserId , participantEntityId , tenantId ) {
729+ try {
730+ // Find programUsers document where logged-in user is the userId and has the participant in entities
731+ const query = {
732+ userId : loggedInUserId . toString ( ) ,
733+ tenantId : tenantId ,
734+ entities : {
735+ $elemMatch : {
736+ $or : [
737+ { userId : participantUserId . toString ( ) } ,
738+ { userId : participantEntityId . toString ( ) } ,
739+ { entityId : participantEntityId . toString ( ) } ,
740+ { externalId : participantEntityId . toString ( ) } ,
741+ ] ,
742+ } ,
743+ } ,
744+ }
745+
746+ const programUserDoc = await programUsersQueries . programUsersDocument ( query , [
747+ '_id' ,
748+ 'userId' ,
749+ 'entities' ,
750+ 'programId' ,
751+ 'programExternalId' ,
752+ ] )
753+
754+ if ( ! programUserDoc || programUserDoc . length === 0 ) {
755+ return {
756+ success : false ,
757+ message : 'Participant not assigned to logged-in user' ,
758+ }
759+ }
760+
761+ // Find the specific entity
762+ const doc = programUserDoc [ 0 ]
763+ const entity = doc . entities ?. find (
764+ ( e ) =>
765+ e . userId == participantUserId ||
766+ e . userId == participantEntityId ||
767+ e . entityId == participantEntityId ||
768+ e . externalId == participantEntityId
769+ )
770+
771+ if ( ! entity ) {
772+ return {
773+ success : false ,
774+ message : 'Participant entity not found in programUsers' ,
775+ }
776+ }
777+
778+ return {
779+ success : true ,
780+ programUserDoc : doc ,
781+ entity : entity ,
782+ }
783+ } catch ( error ) {
784+ console . error ( 'Error checking participant assignment:' , error )
785+ return {
786+ success : false ,
787+ message : error . message || 'Error checking participant assignment' ,
788+ }
789+ }
790+ }
791+
792+ /**
793+ * Update entity location/profile information
794+ * Similar to user/update but validates that logged-in user has participant assigned
795+ * @method
796+ * @name updateEntityLocation
797+ * @param {Object } data - request body data
798+ * @param {String } data.userId - participant's userId to update
799+ * @param {String } data.entityId - participant's entityId (optional, can use userId)
800+ * @param {Object } data.updateData - profile data to update (province, site, address, etc.)
801+ * @param {Object } userDetails - logged in user details
802+ * @returns {Object } result with status and updated user data
803+ */
804+ static async updateEntityLocation ( data , userDetails ) {
805+ try {
806+ const { userId, entityId, updateData } = data
807+ const loggedInUserId = userDetails . userInformation ?. userId
808+ const tenantId = userDetails . userInformation ?. tenantId
809+ const userToken = userDetails . userToken
810+
811+ // Validate required fields
812+ if ( ! userId ) {
813+ return {
814+ success : false ,
815+ status : HTTP_STATUS_CODE . bad_request . status ,
816+ message : 'userId is required' ,
817+ }
818+ }
819+
820+ if ( ! updateData || typeof updateData !== 'object' || Object . keys ( updateData ) . length === 0 ) {
821+ return {
822+ success : false ,
823+ status : HTTP_STATUS_CODE . bad_request . status ,
824+ message : 'updateData is required and must be a non-empty object' ,
825+ }
826+ }
827+
828+ // Use entityId if provided, otherwise use userId
829+ const participantIdentifier = entityId || userId
830+
831+ // Check if logged-in user has this participant assigned
832+ const assignmentCheck = await this . checkParticipantAssigned (
833+ loggedInUserId ,
834+ userId ,
835+ participantIdentifier ,
836+ tenantId
837+ )
838+
839+ if ( ! assignmentCheck . success ) {
840+ return {
841+ success : false ,
842+ status : HTTP_STATUS_CODE . forbidden . status ,
843+ message : assignmentCheck . message || 'You do not have permission to update this participant' ,
844+ }
845+ }
846+
847+ // Get tenant code and organization ID from userDetails
848+ const tenantCode =
849+ userDetails . userInformation ?. tenantCode || userDetails . userInformation ?. tenantId || tenantId
850+ const organizationId = userDetails . userInformation ?. organizationId
851+
852+ // Call user service to update the participant's profile using org-admin endpoint
853+ const updateResult = await userService . updateProfile (
854+ userId ,
855+ updateData ,
856+ userToken ,
857+ tenantCode ,
858+ organizationId
859+ )
860+
861+ if ( ! updateResult . success ) {
862+ return {
863+ success : false ,
864+ status : HTTP_STATUS_CODE . bad_request . status ,
865+ message : updateResult . message || 'Failed to update participant profile' ,
866+ error : updateResult . error ,
867+ }
868+ }
869+
870+ return {
871+ success : true ,
872+ status : HTTP_STATUS_CODE . ok . status ,
873+ message : 'Participant profile updated successfully' ,
874+ result : updateResult . data ,
875+ }
876+ } catch ( error ) {
877+ console . error ( 'Error updating participant location:' , error )
878+ return {
879+ success : false ,
880+ status : HTTP_STATUS_CODE . internal_server_error . status ,
881+ message : error . message || 'Internal server error' ,
882+ }
883+ }
884+ }
717885}
0 commit comments