| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125 |
- #!/usr/bin/env node
- import minimist from 'minimist'
- import { setTimeout } from 'node:timers/promises'
- import { scriptRunner } from '../lib/ScriptRunner.mjs'
- import { getRegionClient } from '../../modules/subscriptions/app/src/StripeClient.mjs'
- // eslint-disable-next-line import/no-unresolved
- import * as csv from 'csv/sync'
- import { readFile } from 'node:fs/promises'
- /**
- * This script creates Stripe coupons and promotion codes from a CSV file.
- *
- * Usage:
- * node scripts/stripe/create_coupons.mjs --region=us INPUT.CSV
- *
- * Options:
- * --region=us|uk Required. Stripe region to process (us or uk)
- *
- * CSV Format:
- * name,percent_off,duration,code,max_redemptions
- */
- async function main(trackProgress) {
- const args = minimist(process.argv.slice(2), {
- string: ['region'],
- })
- const inputCSV = args._[0]
- const region = args.region
- await trackProgress(
- `Starting script for Stripe ${region.toUpperCase()} region`
- )
- const file = await readFile(inputCSV, { encoding: 'utf8' })
- const couponsToCreate = csv.parse(file, { columns: true })
- await trackProgress(
- `Successfully parsed "${inputCSV}" CSV file with ${couponsToCreate.length} coupons and promotion codes to create`
- )
- const client = getRegionClient(region)
- const stripeCoupons = await client.stripe.coupons.list({ limit: 100 })
- const existingCoupons = stripeCoupons.data.reduce((acc, curr) => {
- acc[curr.name] = curr.id
- return acc
- }, {})
- await trackProgress(
- `Successfully parsed ${Object.keys(existingCoupons).length} existing coupons for verification`
- )
- let couponsCreated = 0
- let promotionCodesCreated = 0
- let promotionCodesExisted = 0
- const errors = []
- for (const toCreate of couponsToCreate) {
- try {
- let targetCouponId = existingCoupons[toCreate.name]
- if (!targetCouponId) {
- const createdCoupon = await client.stripe.coupons.create({
- name: toCreate.name,
- percent_off: parseFloat(toCreate.percent_off),
- duration: toCreate.duration,
- })
- targetCouponId = createdCoupon.id
- existingCoupons[toCreate.name] = targetCouponId
- couponsCreated++
- }
- const promotionPayload = {
- coupon: targetCouponId,
- code: toCreate.code,
- }
- const maxRedemptions = parseInt(toCreate.max_redemptions, 10)
- if (maxRedemptions > 0) {
- promotionPayload.max_redemptions = maxRedemptions
- }
- await client.stripe.promotionCodes.create(promotionPayload)
- promotionCodesCreated++
- } catch (error) {
- if (
- error.message.includes('promotion code') &&
- error.message.includes('already exists')
- ) {
- promotionCodesExisted++
- } else {
- await trackProgress(`Failed to create coupon "${toCreate}"`)
- await trackProgress(error.message)
- errors.push(toCreate.name)
- }
- }
- if (promotionCodesCreated > 10 && promotionCodesCreated % 10 === 0) {
- await trackProgress(
- `Promotion codes created: ${promotionCodesCreated}, existed: ${promotionCodesExisted}`
- )
- await setTimeout(10)
- }
- }
- await trackProgress(`\n\nCoupons created: ${couponsCreated}`)
- await trackProgress(`Promotion codes created: ${promotionCodesCreated}`)
- await trackProgress(`Promotion codes existed: ${promotionCodesExisted}`)
- if (errors.length > 0) {
- await trackProgress(
- `Could not create the following coupons: ${errors.join(', ')}`
- )
- } else {
- await trackProgress(
- `Successfully created ${couponsToCreate.length} coupon(s) and promotion code(s).`
- )
- }
- }
- // Execute the script using the runner
- try {
- await scriptRunner(main)
- process.exit(0)
- } catch (error) {
- console.error('Script failed:', error.message)
- process.exit(1)
- }
|