-
Notifications
You must be signed in to change notification settings - Fork 336
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
chore(rethinkdb): OrganizationUser: Phase 2 #9953
Changes from 68 commits
bfa5c21
7ac086e
9844960
62e123c
c38f86c
d318560
16843dc
abb3bdf
9911448
af03b31
2a3c0ca
8dfa870
3b48d22
24da04b
c60e502
0d2c7d7
9ef9346
76aeff9
0830c8e
a12b08a
a732657
954503d
c7775ad
d53aca4
6689e39
a6fd0d3
00964a8
50ca56b
b220f22
22ca4f3
9c55acd
9dfd35c
654aa42
ebbea29
7dbea0d
3fd2236
c552ea6
50d9e77
b7c092d
fe9efe9
4d838f3
34b05bf
02aa23d
dfba81e
81d68b7
f4f5ede
dcbcd78
b329fd3
0a549d6
5f6bdfc
21876d9
af856f2
129d1a9
6e368a4
27b0cf2
b5422dd
3c061e2
1cdf979
473c0c5
49be1bc
65614c6
ca01882
44d153e
303f493
3c3b46c
3e3634c
8d33999
78dcb46
24a2698
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -1,3 +1,4 @@ | ||||||||||||||||||||||||||||
import {sql} from 'kysely' | ||||||||||||||||||||||||||||
import {InvoiceItemType} from 'parabol-client/types/constEnums' | ||||||||||||||||||||||||||||
import getRethink from '../../database/rethinkDriver' | ||||||||||||||||||||||||||||
import {RDatum} from '../../database/stricterR' | ||||||||||||||||||||||||||||
|
@@ -36,7 +37,7 @@ const maybeUpdateOrganizationActiveDomain = async ( | |||||||||||||||||||||||||||
return | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
// don't modify if we can't guess the domain or the domain we guess is the current domain | ||||||||||||||||||||||||||||
const domain = await getActiveDomainForOrgId(orgId) | ||||||||||||||||||||||||||||
const domain = await getActiveDomainForOrgId(orgId, dataLoader) | ||||||||||||||||||||||||||||
if (!domain || domain === activeDomain) return | ||||||||||||||||||||||||||||
organization.activeDomain = domain | ||||||||||||||||||||||||||||
const pg = getKysely() | ||||||||||||||||||||||||||||
|
@@ -52,13 +53,19 @@ const changePause = (inactive: boolean) => async (_orgIds: string[], user: IUser | |||||||||||||||||||||||||||
email, | ||||||||||||||||||||||||||||
isActive: !inactive | ||||||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||||
return Promise.all([ | ||||||||||||||||||||||||||||
await Promise.all([ | ||||||||||||||||||||||||||||
updateUser( | ||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||
inactive | ||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||
userId | ||||||||||||||||||||||||||||
), | ||||||||||||||||||||||||||||
getKysely() | ||||||||||||||||||||||||||||
.updateTable('OrganizationUser') | ||||||||||||||||||||||||||||
.set({inactive}) | ||||||||||||||||||||||||||||
.where('userId', '=', userId) | ||||||||||||||||||||||||||||
.where('removedAt', 'is', null) | ||||||||||||||||||||||||||||
.execute(), | ||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Redundant RethinkDB update operations. The update operations for - getKysely()
- .updateTable('OrganizationUser')
- .set({inactive})
- .where('userId', '=', userId)
- .where('removedAt', 'is', null)
- .execute(),
- r
- .table('OrganizationUser')
- .getAll(userId, {index: 'userId'})
- .filter({removedAt: null})
- .update({inactive})
- .run()
+ getKysely()
+ .updateTable('OrganizationUser')
+ .set({inactive})
+ .where('userId', '=', userId)
+ .where('removedAt', 'is', null)
+ .execute() Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||
r | ||||||||||||||||||||||||||||
.table('OrganizationUser') | ||||||||||||||||||||||||||||
.getAll(userId, {index: 'userId'}) | ||||||||||||||||||||||||||||
|
@@ -73,33 +80,28 @@ const addUser = async (orgIds: string[], user: IUser, dataLoader: DataLoaderWork | |||||||||||||||||||||||||||
const r = await getRethink() | ||||||||||||||||||||||||||||
const [rawOrganizations, organizationUsers] = await Promise.all([ | ||||||||||||||||||||||||||||
dataLoader.get('organizations').loadMany(orgIds), | ||||||||||||||||||||||||||||
r | ||||||||||||||||||||||||||||
.table('OrganizationUser') | ||||||||||||||||||||||||||||
.getAll(userId, {index: 'userId'}) | ||||||||||||||||||||||||||||
.orderBy(r.desc('newUserUntil')) | ||||||||||||||||||||||||||||
.coerceTo('array') | ||||||||||||||||||||||||||||
.run() | ||||||||||||||||||||||||||||
dataLoader.get('organizationUsersByUserId').load(userId) | ||||||||||||||||||||||||||||
]) | ||||||||||||||||||||||||||||
dataLoader.get('organizationUsersByUserId').clear(userId) | ||||||||||||||||||||||||||||
const organizations = rawOrganizations.filter(isValid) | ||||||||||||||||||||||||||||
const docs = orgIds.map((orgId) => { | ||||||||||||||||||||||||||||
const oldOrganizationUser = organizationUsers.find( | ||||||||||||||||||||||||||||
(organizationUser) => organizationUser.orgId === orgId | ||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||
const organization = organizations.find((organization) => organization.id === orgId)! | ||||||||||||||||||||||||||||
// continue the grace period from before, if any OR set to the end of the invoice OR (if it is a free account) no grace period | ||||||||||||||||||||||||||||
const newUserUntil = | ||||||||||||||||||||||||||||
(oldOrganizationUser && oldOrganizationUser.newUserUntil) || | ||||||||||||||||||||||||||||
organization.periodEnd || | ||||||||||||||||||||||||||||
new Date() | ||||||||||||||||||||||||||||
return new OrganizationUser({ | ||||||||||||||||||||||||||||
id: oldOrganizationUser?.id, | ||||||||||||||||||||||||||||
orgId, | ||||||||||||||||||||||||||||
userId, | ||||||||||||||||||||||||||||
newUserUntil, | ||||||||||||||||||||||||||||
tier: organization.tier | ||||||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
await getKysely() | ||||||||||||||||||||||||||||
.insertInto('OrganizationUser') | ||||||||||||||||||||||||||||
.values(docs) | ||||||||||||||||||||||||||||
.onConflict((oc) => oc.doNothing()) | ||||||||||||||||||||||||||||
.execute() | ||||||||||||||||||||||||||||
await r.table('OrganizationUser').insert(docs, {conflict: 'replace'}).run() | ||||||||||||||||||||||||||||
await Promise.all( | ||||||||||||||||||||||||||||
orgIds.map((orgId) => { | ||||||||||||||||||||||||||||
|
@@ -111,7 +113,13 @@ const addUser = async (orgIds: string[], user: IUser, dataLoader: DataLoaderWork | |||||||||||||||||||||||||||
const deleteUser = async (orgIds: string[], user: IUser) => { | ||||||||||||||||||||||||||||
const r = await getRethink() | ||||||||||||||||||||||||||||
orgIds.forEach((orgId) => analytics.userRemovedFromOrg(user, orgId)) | ||||||||||||||||||||||||||||
return r | ||||||||||||||||||||||||||||
await getKysely() | ||||||||||||||||||||||||||||
.updateTable('OrganizationUser') | ||||||||||||||||||||||||||||
.set({removedAt: sql`CURRENT_TIMESTAMP`}) | ||||||||||||||||||||||||||||
.where('userId', '=', user.id) | ||||||||||||||||||||||||||||
.where('orgId', 'in', orgIds) | ||||||||||||||||||||||||||||
.execute() | ||||||||||||||||||||||||||||
await r | ||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Redundant RethinkDB update operations. The update operations for - await getKysely()
- .updateTable('OrganizationUser')
- .set({removedAt: sql`CURRENT_TIMESTAMP`})
- .where('userId', '=', user.id)
- .where('orgId', 'in', orgIds)
- .execute()
- await r
- .table('OrganizationUser')
- .getAll(user.id, {index: 'userId'})
- .filter((row: RDatum) => r.expr(orgIds).contains(row('orgId')))
- .update({
- removedAt: new Date()
- })
- .run()
+ await getKysely()
+ .updateTable('OrganizationUser')
+ .set({removedAt: sql`CURRENT_TIMESTAMP`})
+ .where('userId', '=', user.id)
+ .where('orgId', 'in', orgIds)
+ .execute() Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||
.table('OrganizationUser') | ||||||||||||||||||||||||||||
.getAll(user.id, {index: 'userId'}) | ||||||||||||||||||||||||||||
.filter((row: RDatum) => r.expr(orgIds).contains(row('orgId'))) | ||||||||||||||||||||||||||||
|
@@ -152,7 +160,6 @@ export default async function adjustUserCount( | |||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
const dbAction = dbActionTypeLookup[type] | ||||||||||||||||||||||||||||
await dbAction(orgIds, user, dataLoader) | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
const auditEventType = auditEventTypeLookup[type] | ||||||||||||||||||||||||||||
await insertOrgUserAudit(orgIds, userId, auditEventType) | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -1,5 +1,3 @@ | ||||||||||||||||
import getRethink from '../../database/rethinkDriver' | ||||||||||||||||
import {RDatum} from '../../database/stricterR' | ||||||||||||||||
import {DataLoaderWorker} from '../../graphql/graphql' | ||||||||||||||||
import {OrganizationSource} from '../../graphql/public/types/Organization' | ||||||||||||||||
import {analytics} from '../../utils/analytics/analytics' | ||||||||||||||||
|
@@ -9,31 +7,23 @@ const sendEnterpriseOverageEvent = async ( | |||||||||||||||
organization: OrganizationSource, | ||||||||||||||||
dataLoader: DataLoaderWorker | ||||||||||||||||
) => { | ||||||||||||||||
const r = await getRethink() | ||||||||||||||||
const manager = getStripeManager() | ||||||||||||||||
const {id: orgId, stripeSubscriptionId} = organization | ||||||||||||||||
if (!stripeSubscriptionId) return | ||||||||||||||||
const [orgUserCount, subscriptionItem] = await Promise.all([ | ||||||||||||||||
r | ||||||||||||||||
.table('OrganizationUser') | ||||||||||||||||
.getAll(orgId, {index: 'orgId'}) | ||||||||||||||||
.filter({removedAt: null, inactive: false}) | ||||||||||||||||
.count() | ||||||||||||||||
.run(), | ||||||||||||||||
const [orgUsers, subscriptionItem] = await Promise.all([ | ||||||||||||||||
dataLoader.get('organizationUsersByOrgId').load(orgId), | ||||||||||||||||
manager.getSubscriptionItem(stripeSubscriptionId) | ||||||||||||||||
]) | ||||||||||||||||
const activeOrgUsers = orgUsers.filter(({inactive}) => !inactive) | ||||||||||||||||
const orgUserCount = activeOrgUsers.length | ||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider using To improve readability, consider using the - const activeOrgUsers = orgUsers.filter(({inactive}) => !inactive)
- const orgUserCount = activeOrgUsers.length
+ const orgUserCount = orgUsers.filter(({inactive}) => !inactive).length Committable suggestion
Suggested change
|
||||||||||||||||
if (!subscriptionItem) return | ||||||||||||||||
|
||||||||||||||||
const quantity = subscriptionItem.quantity | ||||||||||||||||
if (!quantity) return | ||||||||||||||||
if (orgUserCount > quantity) { | ||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider logging the error. Instead of silently catching errors in - sendEnterpriseOverageEvent(org, dataLoader).catch()
+ sendEnterpriseOverageEvent(org, dataLoader).catch((error) => {
+ console.error(`Error processing enterprise organization ${org.id}:`, error)
+ }) Committable suggestion
Suggested change
|
||||||||||||||||
const billingLeaderOrgUser = await r | ||||||||||||||||
.table('OrganizationUser') | ||||||||||||||||
.getAll(orgId, {index: 'orgId'}) | ||||||||||||||||
.filter({removedAt: null}) | ||||||||||||||||
.filter((row: RDatum) => r.expr(['BILLING_LEADER', 'ORG_ADMIN']).contains(row('role'))) | ||||||||||||||||
.nth(0) | ||||||||||||||||
.run() | ||||||||||||||||
const billingLeaderOrgUser = orgUsers.find( | ||||||||||||||||
({role}) => role && ['BILLING_LEADER', 'ORG_ADMIN'].includes(role) | ||||||||||||||||
)! | ||||||||||||||||
const {id: userId} = billingLeaderOrgUser | ||||||||||||||||
const user = await dataLoader.get('users').loadNonNull(userId) | ||||||||||||||||
analytics.enterpriseOverUserLimit(user, orgId) | ||||||||||||||||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -21,6 +21,13 @@ import sendTeamsLimitEmail from './sendTeamsLimitEmail' | |||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
const enableUsageStats = async (userIds: string[], orgId: string) => { | ||||||||||||||||||||||||||||||
const pg = getKysely() | ||||||||||||||||||||||||||||||
await pg | ||||||||||||||||||||||||||||||
.updateTable('OrganizationUser') | ||||||||||||||||||||||||||||||
.set({suggestedTier: 'team'}) | ||||||||||||||||||||||||||||||
.where('orgId', '=', orgId) | ||||||||||||||||||||||||||||||
.where('userId', 'in', userIds) | ||||||||||||||||||||||||||||||
.where('removedAt', 'is', null) | ||||||||||||||||||||||||||||||
.execute() | ||||||||||||||||||||||||||||||
await r | ||||||||||||||||||||||||||||||
.table('OrganizationUser') | ||||||||||||||||||||||||||||||
.getAll(r.args(userIds), {index: 'userId'}) | ||||||||||||||||||||||||||||||
|
@@ -87,6 +94,13 @@ export const maybeRemoveRestrictions = async (orgId: string, dataLoader: DataLoa | |||||||||||||||||||||||||||||
.set({tierLimitExceededAt: null, scheduledLockAt: null, lockedAt: null}) | ||||||||||||||||||||||||||||||
.where('id', '=', orgId) | ||||||||||||||||||||||||||||||
.execute(), | ||||||||||||||||||||||||||||||
pg | ||||||||||||||||||||||||||||||
.updateTable('OrganizationUser') | ||||||||||||||||||||||||||||||
.set({suggestedTier: 'starter'}) | ||||||||||||||||||||||||||||||
.where('orgId', '=', orgId) | ||||||||||||||||||||||||||||||
.where('userId', 'in', billingLeadersIds) | ||||||||||||||||||||||||||||||
.where('removedAt', 'is', null) | ||||||||||||||||||||||||||||||
.execute(), | ||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Redundant RethinkDB update operations. The update operations for - await pg
- .updateTable('OrganizationUser')
- .set({suggestedTier: 'starter'})
- .where('orgId', '=', orgId)
- .where('userId', 'in', billingLeadersIds)
- .where('removedAt', 'is', null)
- .execute(),
- r
- .table('OrganizationUser')
- .getAll(r.args(billingLeadersIds), {index: 'userId'})
- .filter({orgId})
- .update({suggestedTier: 'starter'})
- .run(),
+ await pg
+ .updateTable('OrganizationUser')
+ .set({suggestedTier: 'starter'})
+ .where('orgId', '=', orgId)
+ .where('userId', 'in', billingLeadersIds)
+ .where('removedAt', 'is', null)
+ .execute() Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||
r | ||||||||||||||||||||||||||||||
.table('OrganizationUser') | ||||||||||||||||||||||||||||||
.getAll(r.args(billingLeadersIds), {index: 'userId'}) | ||||||||||||||||||||||||||||||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -11,9 +11,10 @@ import {getStripeManager} from '../../utils/stripe' | |||||||||||||||||||||||||||||||||
*/ | ||||||||||||||||||||||||||||||||||
const updateSubscriptionQuantity = async (orgId: string, logMismatch?: boolean) => { | ||||||||||||||||||||||||||||||||||
const r = await getRethink() | ||||||||||||||||||||||||||||||||||
const pg = getKysely() | ||||||||||||||||||||||||||||||||||
const manager = getStripeManager() | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
const org = await getKysely() | ||||||||||||||||||||||||||||||||||
const org = await pg | ||||||||||||||||||||||||||||||||||
.selectFrom('Organization') | ||||||||||||||||||||||||||||||||||
.selectAll() | ||||||||||||||||||||||||||||||||||
.where('id', '=', orgId) | ||||||||||||||||||||||||||||||||||
|
@@ -34,15 +35,29 @@ const updateSubscriptionQuantity = async (orgId: string, logMismatch?: boolean) | |||||||||||||||||||||||||||||||||
return | ||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
const [orgUserCount, teamSubscription] = await Promise.all([ | ||||||||||||||||||||||||||||||||||
const [orgUserCountRes, orgUserCount, teamSubscription] = await Promise.all([ | ||||||||||||||||||||||||||||||||||
pg | ||||||||||||||||||||||||||||||||||
.selectFrom('OrganizationUser') | ||||||||||||||||||||||||||||||||||
.select(({fn}) => fn.count<number>('id').as('count')) | ||||||||||||||||||||||||||||||||||
.where('orgId', '=', orgId) | ||||||||||||||||||||||||||||||||||
.where('removedAt', 'is', null) | ||||||||||||||||||||||||||||||||||
.where('inactive', '=', false) | ||||||||||||||||||||||||||||||||||
.executeTakeFirstOrThrow(), | ||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use PostgreSQL exclusively for user count The code currently uses both PostgreSQL and RethinkDB to count organization users. This redundancy can be removed by using only PostgreSQL. - const [orgUserCountRes, orgUserCount, teamSubscription] = await Promise.all([
- pg
- .selectFrom('OrganizationUser')
- .select(({fn}) => fn.count<number>('id').as('count'))
- .where('orgId', '=', orgId)
- .where('removedAt', 'is', null)
- .where('inactive', '=', false)
- .executeTakeFirstOrThrow(),
- r
- .table('OrganizationUser')
- .getAll(orgId, {index: 'orgId'})
- .filter({removedAt: null, inactive: false})
- .count()
- .run(),
+ const [orgUserCountRes, teamSubscription] = await Promise.all([
+ pg
+ .selectFrom('OrganizationUser')
+ .select(({fn}) => fn.count<number>('id').as('count'))
+ .where('orgId', '=', orgId)
+ .where('removedAt', 'is', null)
+ .where('inactive', '=', false)
+ .executeTakeFirstOrThrow(), Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||
r | ||||||||||||||||||||||||||||||||||
.table('OrganizationUser') | ||||||||||||||||||||||||||||||||||
.getAll(orgId, {index: 'orgId'}) | ||||||||||||||||||||||||||||||||||
.filter({removedAt: null, inactive: false}) | ||||||||||||||||||||||||||||||||||
.count() | ||||||||||||||||||||||||||||||||||
.run(), | ||||||||||||||||||||||||||||||||||
await manager.getSubscriptionItem(stripeSubscriptionId) | ||||||||||||||||||||||||||||||||||
manager.getSubscriptionItem(stripeSubscriptionId) | ||||||||||||||||||||||||||||||||||
]) | ||||||||||||||||||||||||||||||||||
if (orgUserCountRes.count !== orgUserCount) { | ||||||||||||||||||||||||||||||||||
sendToSentry(new Error('OrganizationUser count mismatch'), { | ||||||||||||||||||||||||||||||||||
tags: { | ||||||||||||||||||||||||||||||||||
orgId | ||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||
if ( | ||||||||||||||||||||||||||||||||||
teamSubscription && | ||||||||||||||||||||||||||||||||||
teamSubscription.quantity !== undefined && | ||||||||||||||||||||||||||||||||||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -5,7 +5,6 @@ export type OrgUserRole = 'BILLING_LEADER' | 'ORG_ADMIN' | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
interface Input { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
orgId: string | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
userId: string | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
newUserUntil?: Date | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
id?: string | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
inactive?: boolean | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
joinedAt?: Date | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -20,36 +19,23 @@ export default class OrganizationUser { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
suggestedTier: TierEnum | null | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
inactive: boolean | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
joinedAt: Date | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
newUserUntil: Date | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
orgId: string | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
removedAt: Date | null | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
role: OrgUserRole | null | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
userId: string | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
tier: TierEnum | null | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
tier: TierEnum | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
trialStartDate?: Date | null | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
constructor(input: Input) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
suggestedTier, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
userId, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
id, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
removedAt, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
inactive, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
orgId, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
joinedAt, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
newUserUntil, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
role, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
tier | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} = input | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const {suggestedTier, userId, id, removedAt, inactive, orgId, joinedAt, role, tier} = input | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
this.id = id || generateUID() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
this.suggestedTier = suggestedTier || null | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
this.inactive = inactive || false | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
this.joinedAt = joinedAt || new Date() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
this.newUserUntil = newUserUntil || new Date() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
this.orgId = orgId | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
this.removedAt = removedAt || null | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
this.role = role || null | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
this.userId = userId | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
this.tier = tier || null | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
this.tier = tier || 'starter' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use default parameters in the constructor. Instead of setting default values inside the constructor body, use default parameters. This improves readability and reduces redundancy. constructor({
suggestedTier = null,
userId,
id = generateUID(),
removedAt = null,
inactive = false,
orgId,
joinedAt = new Date(),
role = null,
tier = 'starter'
}: Input) {
this.id = id
this.suggestedTier = suggestedTier
this.inactive = inactive
this.joinedAt = joinedAt
this.orgId = orgId
this.removedAt = removedAt
this.role = role
this.userId = userId
this.tier = tier
} Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Redundant RethinkDB update operations.
The update operations for
Organization
can be refactored to use only PostgreSQL, aligning with the rest of the migration.Committable suggestion