feat(activation): wire autoFlagPreExistingSlackAccess into self-serve paths
Replaces the per-file inviteToSlack helpers with a single auto-flag call. Self-serve activation paths now check for pre-existing workspace membership (silent on miss) instead of attempting an admin-only invite. - helcim/subscription.post.js: removed local inviteToSlack; both free- and paid-tier activation branches now call the helper, then notifyNewMember with the canonical 'manual_invitation_required' arg. - members/create.post.js: same shape — helper + canonical notify arg. - invite/accept.post.js (free-tier branch): added the helper call after member creation. Free-tier had no prior Slack call (audit confirmed); paid-tier remains untouched and activates via the Helcim webhook. Admin-created and CSV-imported members intentionally do NOT call the helper — admins flip the flag manually after sending the invite. Test stub for autoFlagPreExistingSlackAccess added to server setup.
This commit is contained in:
parent
b1d8cb1966
commit
55029e7eb7
5 changed files with 262 additions and 152 deletions
|
|
@ -8,77 +8,6 @@ import { createHelcimSubscription, generateIdempotencyKey, listHelcimCustomerTra
|
|||
import { sendWelcomeEmail } from '../../utils/resend.js'
|
||||
import { upsertPaymentFromHelcim } from '../../utils/payments.js'
|
||||
|
||||
// Function to invite member to Slack
|
||||
async function inviteToSlack(member) {
|
||||
try {
|
||||
const slackService = getSlackService()
|
||||
if (!slackService) {
|
||||
console.warn('Slack service not configured, skipping invitation')
|
||||
return
|
||||
}
|
||||
|
||||
console.log(`Processing Slack invitation for ${member.email}...`)
|
||||
|
||||
const inviteResult = await slackService.inviteUserToSlack(
|
||||
member.email,
|
||||
member.name
|
||||
)
|
||||
|
||||
if (inviteResult.success) {
|
||||
const update = {}
|
||||
if (inviteResult.status === 'existing_user_added_to_channel' ||
|
||||
inviteResult.status === 'user_already_in_channel' ||
|
||||
inviteResult.status === 'new_user_invited_to_workspace') {
|
||||
update.slackInviteStatus = 'sent'
|
||||
update.slackUserId = inviteResult.userId
|
||||
update.slackInvited = true
|
||||
} else {
|
||||
update.slackInviteStatus = 'pending'
|
||||
update.slackInvited = false
|
||||
}
|
||||
await Member.findByIdAndUpdate(
|
||||
member._id,
|
||||
{ $set: update },
|
||||
{ runValidators: false }
|
||||
)
|
||||
|
||||
// Send notification to vetting channel
|
||||
await slackService.notifyNewMember(
|
||||
member.name,
|
||||
member.email,
|
||||
member.circle,
|
||||
member.contributionAmount,
|
||||
inviteResult.status
|
||||
)
|
||||
|
||||
console.log(`Successfully processed Slack invitation for ${member.email}: ${inviteResult.status}`)
|
||||
} else {
|
||||
await Member.findByIdAndUpdate(
|
||||
member._id,
|
||||
{ $set: { slackInviteStatus: 'failed' } },
|
||||
{ runValidators: false }
|
||||
)
|
||||
|
||||
console.error(`Failed to process Slack invitation for ${member.email}: ${inviteResult.error}`)
|
||||
// Don't throw error - subscription creation should still succeed
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error during Slack invitation process:', error)
|
||||
|
||||
try {
|
||||
await Member.findByIdAndUpdate(
|
||||
member._id,
|
||||
{ $set: { slackInviteStatus: 'failed' } },
|
||||
{ runValidators: false }
|
||||
)
|
||||
} catch (saveError) {
|
||||
console.error('Failed to update member Slack status:', saveError)
|
||||
}
|
||||
|
||||
// Don't throw error - subscription creation should still succeed
|
||||
}
|
||||
}
|
||||
|
||||
export default defineEventHandler(async (event) => {
|
||||
try {
|
||||
// Membership signup completes subscription before email verify; allow the
|
||||
|
|
@ -109,7 +38,21 @@ export default defineEventHandler(async (event) => {
|
|||
|
||||
logActivity(member._id, 'subscription_created', { amount: body.contributionAmount })
|
||||
|
||||
await inviteToSlack(member)
|
||||
await autoFlagPreExistingSlackAccess(member)
|
||||
try {
|
||||
const slackService = getSlackService()
|
||||
if (slackService) {
|
||||
await slackService.notifyNewMember(
|
||||
member.name,
|
||||
member.email,
|
||||
member.circle,
|
||||
member.contributionAmount,
|
||||
'manual_invitation_required'
|
||||
)
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('[slack] notifyNewMember failed:', err)
|
||||
}
|
||||
if (isFirstActivation) await sendWelcomeEmail(member)
|
||||
|
||||
return {
|
||||
|
|
@ -207,7 +150,21 @@ export default defineEventHandler(async (event) => {
|
|||
console.error('[payments] initial charge log failed, will be picked up by reconciliation:', err?.message || err)
|
||||
}
|
||||
|
||||
await inviteToSlack(member)
|
||||
await autoFlagPreExistingSlackAccess(member)
|
||||
try {
|
||||
const slackService = getSlackService()
|
||||
if (slackService) {
|
||||
await slackService.notifyNewMember(
|
||||
member.name,
|
||||
member.email,
|
||||
member.circle,
|
||||
member.contributionAmount,
|
||||
'manual_invitation_required'
|
||||
)
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('[slack] notifyNewMember failed:', err)
|
||||
}
|
||||
if (isFirstActivation) await sendWelcomeEmail(member)
|
||||
|
||||
return {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue