Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

membership.js 6.2KB

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