Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

membership.js 7.0KB

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