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

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