-
Notifications
You must be signed in to change notification settings - Fork 30
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
nicoll/splits automation #1771
nicoll/splits automation #1771
Changes from all commits
70ec0e8
84049fd
3d7a59a
ed0c379
40994b2
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 |
---|---|---|
|
@@ -32,7 +32,11 @@ export const loadSanityProduct = async ( | |
}, | ||
image{ | ||
url | ||
} | ||
}, | ||
"instructor": contributors[0].contributor->{ | ||
userId, | ||
name, | ||
Comment on lines
+36
to
+38
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. I'm not a huge fan of this and we should probably not hard code a zero-index lookup here and consider multiple instructors immediately. |
||
}, | ||
}`, | ||
) => { | ||
const sanityProductData = await sanityWriteClient.fetch(query, {id}) | ||
|
@@ -67,6 +71,10 @@ export const BaseSanityProductSchema = z.object({ | |
}) | ||
.nullable() | ||
.optional(), | ||
instructor: z | ||
.object({userId: z.string(), name: z.string()}) | ||
.optional() | ||
.nullable(), | ||
}) | ||
|
||
export type BaseSanityProduct = z.infer<typeof BaseSanityProductSchema> |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -35,6 +35,7 @@ export const sanityProductCreated = inngest.createFunction( | |
upgradableTo, | ||
state, | ||
type, | ||
instructor, | ||
} = sanityProduct | ||
|
||
const productStatus = state === 'active' ? 1 : 0 | ||
|
@@ -82,6 +83,114 @@ export const sanityProductCreated = inngest.createFunction( | |
}) | ||
}) | ||
|
||
type SplitInfo = { | ||
type: string | ||
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. type here is could use a discriminated union so that the |
||
percent: number | ||
userId: string | undefined | null | ||
} | ||
|
||
type Splits = { | ||
skill: SplitInfo | ||
owner: SplitInfo | ||
contributor?: SplitInfo | ||
} | ||
|
||
const defineSplits = await step.run( | ||
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. define splits based on contributor and moduleType |
||
'define splits', | ||
async (): Promise<Splits> => { | ||
const OWNER_ID = '4ef27e5f-00b4-4aa3-b3c4-4a58ae76f50b' | ||
const isOwnerInstructor = instructor?.userId === OWNER_ID | ||
const isSelfPaced = type === 'self-paced' | ||
|
||
let splits: Splits = { | ||
skill: { | ||
type: 'skill', | ||
percent: 0, | ||
userId: null, | ||
}, | ||
owner: { | ||
type: 'owner', | ||
percent: 0, | ||
userId: OWNER_ID, | ||
}, | ||
} | ||
|
||
if (isOwnerInstructor) { | ||
if (isSelfPaced) { | ||
splits.skill.percent = 0.4 | ||
splits.owner.percent = 0.6 | ||
} else { | ||
splits.skill.percent = 0.15 | ||
splits.owner.percent = 0.85 | ||
} | ||
} else { | ||
if (isSelfPaced) { | ||
splits.skill.percent = 0.5 | ||
splits.owner.percent = 0.2 | ||
splits.contributor = { | ||
type: 'contributor', | ||
percent: 0.3, | ||
userId: instructor?.userId, | ||
} | ||
} else { | ||
splits.skill.percent = 0.15 | ||
splits.owner.percent = 0.15 | ||
splits.contributor = { | ||
type: 'contributor', | ||
percent: 0.7, | ||
userId: instructor?.userId, | ||
} | ||
} | ||
} | ||
Comment on lines
+118
to
+144
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. This is kind of harsh, but I am concerned with it's hard-coding very specific business values and mutating an object through another object. To the extent that I think we might need to rethink the entire data model and implementation of the PR. We can keep trying like this or write a plan, diagram the flows, etc before implementing I'd rather have it just manually added to the database. 😬 |
||
|
||
return splits | ||
}, | ||
) | ||
|
||
const createSplits = await step.run( | ||
'create splits in database', | ||
async () => { | ||
const skillSplit = await prisma.productRevenueSplit.create({ | ||
data: { | ||
id: v4(), | ||
type: defineSplits.skill.type, | ||
productId: product.id, | ||
percent: defineSplits.skill.percent, | ||
userId: defineSplits.skill.userId, | ||
}, | ||
}) | ||
|
||
const ownerSplit = await prisma.productRevenueSplit.create({ | ||
data: { | ||
id: v4(), | ||
type: defineSplits.owner.type, | ||
productId: product.id, | ||
percent: defineSplits.owner.percent, | ||
userId: defineSplits.owner.userId, | ||
}, | ||
}) | ||
|
||
let contributorSplit = null | ||
if (defineSplits.contributor) { | ||
contributorSplit = await prisma.productRevenueSplit.create({ | ||
data: { | ||
id: v4(), | ||
type: defineSplits.contributor.type, | ||
productId: product.id, | ||
percent: defineSplits.contributor.percent, | ||
userId: defineSplits.contributor.userId, | ||
}, | ||
}) | ||
} | ||
|
||
return { | ||
skillSplit, | ||
ownerSplit, | ||
contributorSplit, | ||
} | ||
}, | ||
) | ||
|
||
const merchantAccount = await step.run('get merchant account', async () => { | ||
return await prisma.merchantAccount.findFirst({ | ||
where: { | ||
|
@@ -167,6 +276,7 @@ export const sanityProductCreated = inngest.createFunction( | |
price, | ||
stripeProduct, | ||
stripePrice, | ||
createSplits, | ||
} | ||
} else { | ||
throw new Error('No merchant account found') | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -41,6 +41,7 @@ export const sanityProductUpdated = inngest.createFunction( | |
upgradableTo, | ||
state, | ||
type, | ||
instructor, | ||
} = sanityProduct | ||
|
||
if (!productId) { | ||
|
@@ -257,6 +258,169 @@ export const sanityProductUpdated = inngest.createFunction( | |
}, | ||
) | ||
|
||
const currentSplits = await step.run('get current splits', async () => { | ||
return await prisma.productRevenueSplit.findMany({ | ||
where: { | ||
productId: product.id, | ||
}, | ||
}) | ||
}) | ||
|
||
const splitsNeedUpdate = ( | ||
currentSplits: any[], | ||
instructor: any, | ||
type: string, | ||
): boolean => { | ||
const OWNER_ID = '4ef27e5f-00b4-4aa3-b3c4-4a58ae76f50b' | ||
|
||
const currentContributorSplit = currentSplits.find( | ||
(split) => split.type === 'contributor', | ||
) | ||
|
||
const isOwnerInstructor = instructor?.userId === OWNER_ID | ||
const wasOwnerInstructor = !currentContributorSplit | ||
|
||
if (isOwnerInstructor !== wasOwnerInstructor) { | ||
return true | ||
} | ||
|
||
if ( | ||
currentContributorSplit && | ||
instructor?.userId !== currentContributorSplit.userId | ||
) { | ||
return true | ||
} | ||
|
||
const currentProductType = | ||
currentSplits.length > 0 ? (currentSplits[0] as any).productType : null | ||
|
||
if (currentProductType !== type) { | ||
return true | ||
} | ||
|
||
return false | ||
} | ||
|
||
const needsSplitUpdate = await step.run( | ||
'check if splits need update', | ||
async () => { | ||
return splitsNeedUpdate(currentSplits, instructor, type) | ||
}, | ||
) | ||
|
||
type SplitInfo = { | ||
type: string | ||
percent: number | ||
userId: string | undefined | null | ||
} | ||
|
||
type Splits = { | ||
skill: SplitInfo | ||
owner: SplitInfo | ||
contributor?: SplitInfo | ||
} | ||
Comment on lines
+311
to
+321
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. super important to have types exist in 1 spot only |
||
|
||
if (needsSplitUpdate) { | ||
const defineSplits = await step.run( | ||
'define splits', | ||
async (): Promise<Splits> => { | ||
const OWNER_ID = '4ef27e5f-00b4-4aa3-b3c4-4a58ae76f50b' | ||
const isOwnerInstructor = instructor?.userId === OWNER_ID | ||
const isSelfPaced = type === 'self-paced' | ||
|
||
let splits: Splits = { | ||
skill: { | ||
type: 'skill', | ||
percent: 0, | ||
userId: null, | ||
}, | ||
owner: { | ||
type: 'owner', | ||
percent: 0, | ||
userId: OWNER_ID, | ||
}, | ||
} | ||
|
||
if (isOwnerInstructor) { | ||
if (isSelfPaced) { | ||
splits.skill.percent = 0.4 | ||
splits.owner.percent = 0.6 | ||
} else { | ||
splits.skill.percent = 0.15 | ||
splits.owner.percent = 0.85 | ||
} | ||
} else { | ||
if (isSelfPaced) { | ||
splits.skill.percent = 0.5 | ||
splits.owner.percent = 0.2 | ||
splits.contributor = { | ||
type: 'contributor', | ||
percent: 0.3, | ||
userId: instructor?.userId, | ||
} | ||
} else { | ||
splits.skill.percent = 0.15 | ||
splits.owner.percent = 0.15 | ||
splits.contributor = { | ||
type: 'contributor', | ||
percent: 0.7, | ||
userId: instructor?.userId, | ||
} | ||
} | ||
} | ||
|
||
return splits | ||
}, | ||
) | ||
Comment on lines
+344
to
+374
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. oh, looks like it's all repeated |
||
|
||
await step.run('update splits in database', async () => { | ||
await prisma.productRevenueSplit.deleteMany({ | ||
where: { | ||
productId: product.id, | ||
}, | ||
}) | ||
|
||
const skillSplit = await prisma.productRevenueSplit.create({ | ||
data: { | ||
id: v4(), | ||
type: defineSplits.skill.type, | ||
productId: product.id, | ||
percent: defineSplits.skill.percent, | ||
userId: defineSplits.skill.userId, | ||
}, | ||
}) | ||
|
||
const ownerSplit = await prisma.productRevenueSplit.create({ | ||
data: { | ||
id: v4(), | ||
type: defineSplits.owner.type, | ||
productId: product.id, | ||
percent: defineSplits.owner.percent, | ||
userId: defineSplits.owner.userId, | ||
}, | ||
}) | ||
|
||
let contributorSplit = null | ||
if (defineSplits.contributor) { | ||
contributorSplit = await prisma.productRevenueSplit.create({ | ||
data: { | ||
id: v4(), | ||
type: defineSplits.contributor.type, | ||
productId: product.id, | ||
percent: defineSplits.contributor.percent, | ||
userId: defineSplits.contributor.userId, | ||
}, | ||
}) | ||
} | ||
|
||
return { | ||
skillSplit, | ||
ownerSplit, | ||
contributorSplit, | ||
} | ||
}) | ||
} | ||
|
||
return {updatedProduct, updatedStripeProduct} | ||
}, | ||
) |
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.
went ahead and deleted this section