選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

membership.js 6.5KB

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