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

membership.js 6.6KB

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