Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

membership.js 6.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. const Schmervice = require('@hapipal/schmervice')
  2. module.exports = class MembershipService extends Schmervice.Service {
  3. constructor(...args) {
  4. super(...args)
  5. }
  6. /**
  7. * Internal method to get list of grouping_ids for this user
  8. * @param {number} profileId
  9. * @returns {Array} List of all grouping_ids for user
  10. */
  11. async _getGroupIdsForProfileId(profileId) {
  12. const { Membership } = this.server.models()
  13. /** Grab every Membership associated with this id */
  14. const allMemberships = await Membership.query().where(
  15. 'profile_id',
  16. profileId,
  17. )
  18. /** Copy a list of the just the Groupings */
  19. const groupingIdsToGrab = allMemberships.map(
  20. membership => membership.grouping_id,
  21. )
  22. /** Uncomment to dedupe the list just in case */
  23. return [...new Set(groupingIdsToGrab)]
  24. }
  25. /**
  26. * Internal method to create a new grouping
  27. * @param {*} groupingToTry
  28. * @param {*} txn
  29. * @returns
  30. */
  31. async _createGrouping(groupingToTry, txn) {
  32. const { Grouping } = this.server.models()
  33. const groupingInfo = {
  34. grouping_name: groupingToTry.grouping_name,
  35. grouping_type: groupingToTry.grouping_type,
  36. }
  37. return await Grouping.query(txn).insert(groupingInfo)
  38. }
  39. async findOrCreateGrouping(groupingToTry) {
  40. let idToReturn = groupingToTry.grouping_id
  41. if (!idToReturn) {
  42. /** ?: For some reason this returns the key id */
  43. const grouping = await this._createGrouping(groupingToTry)
  44. idToReturn = grouping.id
  45. }
  46. return idToReturn
  47. }
  48. /**
  49. * Get a list of groupings for user
  50. * @param {number} profileId
  51. * @returns {Array}
  52. */
  53. async findGroupingsById(profileId) {
  54. const { Grouping } = this.server.models()
  55. const dedupedGroupings = await this._getGroupIdsForProfileId(profileId)
  56. /** Grab just the Groupings this id has a Membership for */
  57. return await Grouping.query()
  58. .throwIfNotFound()
  59. .whereIn('grouping_id', dedupedGroupings)
  60. }
  61. async _groupingIdsInCommon(profileId, targetId) {
  62. const dedupedUserGroupingIds = await this._getGroupIdsForProfileId(
  63. profileId,
  64. )
  65. const dedupedTargetGroupingIds = await this._getGroupIdsForProfileId(
  66. targetId,
  67. )
  68. /** Return true if both people have a group in common */
  69. return dedupedUserGroupingIds.filter(groupingId =>
  70. dedupedTargetGroupingIds.includes(groupingId),
  71. )
  72. }
  73. async _patchMembership(memberships, profileId, patch) {
  74. const { Membership } = this.server.models()
  75. /** Set membership as active only if the user initiates it */
  76. for (let membershipInfo of memberships) {
  77. await Membership.query()
  78. .where('membership_id', membershipInfo.membership_id)
  79. .where('user_id', profileId)
  80. .patch(patch)
  81. }
  82. }
  83. async attemptMatch(profileId, targetId) {
  84. const { Membership } = this.server.models()
  85. /** If both people have groups in common */
  86. const matchingGroupingIds = await this._groupingIdsInCommon(
  87. profileId,
  88. targetId,
  89. )
  90. if (matchingGroupingIds.length) {
  91. /** Grab all memberships associated with groupingIds */
  92. const memberships = await Membership.query().whereIn(
  93. 'grouping_id',
  94. matchingGroupingIds,
  95. )
  96. /** Set membership as active only if the user initiates it */
  97. await this._patchMembership(memberships, profileId, {
  98. is_active: true,
  99. })
  100. /** Make a new query to get updated information */
  101. return await Membership.query().whereIn(
  102. 'grouping_id',
  103. matchingGroupingIds,
  104. )
  105. }
  106. }
  107. /**
  108. * Check for grouping membership then add membership record and set to active
  109. * or create a new grouping and add membership record for user and membership record for target
  110. * @param {number} profileId
  111. * @param {number} targetId
  112. * @param {object} groupingToWrite
  113. * @param {string} role
  114. * @returns
  115. */
  116. async joinGrouping(profileId, targetId, groupingToWrite, role, txn) {
  117. const { Membership } = this.server.models()
  118. /** If both people have groups in common */
  119. const matchingGroupingIds = await this._groupingIdsInCommon(
  120. profileId,
  121. targetId,
  122. )
  123. if (matchingGroupingIds.length) {
  124. /** Grab all memberships associated with groupingIds */
  125. const memberships = await Membership.query().whereIn(
  126. 'grouping_id',
  127. matchingGroupingIds,
  128. )
  129. /** Set membership as active only if the user initiates it */
  130. await this._patchMembership(memberships, profileId, {
  131. is_active: true,
  132. })
  133. /** Make a new query to get updated information */
  134. return await Membership.query().whereIn(
  135. 'grouping_id',
  136. matchingGroupingIds,
  137. )
  138. } else {
  139. /**
  140. * If both have NO grouping in common create a membership
  141. * for both to new group but set membership as inactive for target
  142. * */
  143. /** Check if the grouping exists and if NOT creat it */
  144. const groupingId = await this.findOrCreateGrouping(groupingToWrite)
  145. const userMembership = await Membership.query(txn).insert({
  146. profile_id: profileId,
  147. grouping_id: groupingId,
  148. membership_type: role,
  149. can_edit: false,
  150. is_active: true,
  151. })
  152. const targetMembership = await Membership.query(txn).insert({
  153. profile_id: profileId,
  154. grouping_id: groupingId,
  155. membership_type: role,
  156. can_edit: false,
  157. is_active: false,
  158. })
  159. return [userMembership, targetMembership]
  160. }
  161. }
  162. /**
  163. * Remove membership record based on grouping_id
  164. * @param {number} profileId
  165. * @param {number} groupingId
  166. * @returns
  167. */
  168. async leaveGrouping(profileId, groupingId) {
  169. const { Membership } = this.server.models()
  170. const dedupedGroupings = await this._getGroupIdsForProfileId(profileId)
  171. /** Do NOTHING if NOT in Grouping */
  172. if (!dedupedGroupings.includes(groupingId)) return
  173. return await Membership.query()
  174. .delete()
  175. .where('grouping_id', groupingId)
  176. }
  177. }