/api/administrator/subscriptions/set-subscription-item-quantity (PATCH)
Account information like email addresses is generated with faker-js it is not real user information.
await global.api.administrator.subscriptions.SetSubscriptionItemQuantity.patch(req)Returns object
{
"subscriptionitemid": "si_LwH2utTWirH5Al",
"object": "subscriptionitem",
"stripeObject": {
"id": "si_LwH2utTWirH5Al",
"object": "subscription_item",
"billing_thresholds": null,
"created": 1656123144,
"metadata": {},
"plan": {
"id": "price_1LEOTvHHqepMFuCX8HIW4TyS",
"object": "plan",
"active": true,
"aggregate_usage": null,
"amount": 1000,
"amount_decimal": "1000",
"billing_scheme": "per_unit",
"created": 1656123139,
"currency": "usd",
"interval": "month",
"interval_count": 1,
"livemode": false,
"metadata": {},
"nickname": null,
"product": "prod_LwH1an3p1Z06qm",
"tiers_mode": null,
"transform_usage": null,
"trial_period_days": null,
"usage_type": "licensed"
},
"price": {
"id": "price_1LEOTvHHqepMFuCX8HIW4TyS",
"object": "price",
"active": true,
"billing_scheme": "per_unit",
"created": 1656123139,
"currency": "usd",
"custom_unit_amount": null,
"livemode": false,
"lookup_key": null,
"metadata": {},
"nickname": null,
"product": "prod_LwH1an3p1Z06qm",
"recurring": {
"aggregate_usage": null,
"interval": "month",
"interval_count": 1,
"trial_period_days": null,
"usage_type": "licensed"
},
"tax_behavior": "inclusive",
"tiers_mode": null,
"transform_quantity": null,
"type": "recurring",
"unit_amount": 1000,
"unit_amount_decimal": "1000"
},
"quantity": 2,
"subscription": "sub_1LEOTzHHqepMFuCXyM7BIVa5",
"tax_rates": []
},
"accountid": "acct_eee1fc16c16fd3b1",
"subscriptionid": "sub_1LEOTzHHqepMFuCXyM7BIVa5",
"customerid": "cus_LwH1nGrJqfdUnV",
"appid": "tests_1656123138",
"createdAt": "2022-06-25T02:12:27.599Z",
"updatedAt": "2022-06-25T02:12:29.760Z"
}
Exceptions
These exceptions are thrown (NodeJS) or returned as JSON (HTTP) if you provide incorrect data or do not meet the requirements:
Exception | Circumstances |
---|---|
invalid-quantity | invalid posted quantity |
invalid posted quantity is unchanged | |
invalid posted quantity is negative | |
invalid posted quantity is zero | |
invalid-subscriptionitemid | missing querystring subscriptionitemid |
invalid querystring subscriptionitemid |
NodeJS source (view on github)
const dashboard = require('@layeredapps/dashboard')
const stripeCache = require('../../../../stripe-cache.js')
const subscriptions = require('../../../../../index.js')
module.exports = {
patch: async (req) => {
if (!req.query || !req.query.subscriptionitemid) {
throw new Error('invalid-subscriptionitemid')
}
const subscriptionItem = await global.api.administrator.subscriptions.SubscriptionItem.get(req)
if (!subscriptionItem) {
throw new Error('invalid-subscriptionitemid')
}
if (!req.body || !req.body.quantity) {
throw new Error('invalid-quantity')
}
try {
const quantity = parseInt(req.body.quantity, 10)
if (quantity < 1 || quantity.toString() !== req.body.quantity) {
throw new Error('invalid-quantity')
}
if (subscriptionItem.stripeObject.quantity === quantity) {
throw new Error('invalid-quantity')
}
} catch (error) {
throw new Error('invalid-quantity')
}
const updateInfo = {
items: [{
id: req.query.subscriptionitemid,
quantity: req.body.quantity
}]
}
const subscriptionNow = await stripeCache.execute('subscriptions', 'update', subscriptionItem.subscriptionid, updateInfo, req.stripeKey)
if (!subscriptionNow) {
throw new Error('unknown-error')
}
await subscriptions.Storage.Subscription.update({
stripeObject: subscriptionNow
}, {
where: {
subscriptionid: subscriptionItem.subscriptionid,
appid: req.appid || global.appid
}
})
for (const item of subscriptionNow.items.data) {
if (item.id !== req.query.subscriptionitemid) {
continue
}
await subscriptions.Storage.SubscriptionItem.update({
stripeObject: item
}, {
where: {
subscriptionitemid: subscriptionItem.subscriptionitemid,
appid: req.appid || global.appid
}
})
break
}
await dashboard.StorageCache.remove(subscriptionItem.subscriptionid)
await dashboard.StorageCache.remove(req.query.subscriptionitemid)
return global.api.administrator.subscriptions.SubscriptionItem.get(req)
}
}
Test source (view on github)
/* eslint-env mocha */
const assert = require('assert')
const TestHelper = require('../../../../../test-helper.js')
const TestStripeAccounts = require('../../../../../test-stripe-accounts.js')
const DashboardTestHelper = require('@layeredapps/dashboard/test-helper.js')
describe('/api/administrator/subscriptions/set-subscription-item-quantity', function () {
before(TestHelper.disableMetrics)
after(TestHelper.enableMetrics)
let cachedResponses
async function bundledData (retryNumber) {
if (retryNumber > 0) {
cachedResponses = {}
}
if (cachedResponses && cachedResponses.finished) {
return
}
cachedResponses = {}
await TestHelper.setupBefore()
await DashboardTestHelper.setupBeforeEach()
await TestHelper.setupBeforeEach()
const administrator = await TestStripeAccounts.createOwnerWithPrice()
const user = await TestStripeAccounts.createUserWithPaidSubscription(administrator.price)
// missing and invalid id
let req = TestHelper.createRequest('/api/administrator/subscriptions/set-subscription-item-quantity')
req.account = administrator.account
req.session = administrator.session
req.body = {
quantity: '10'
}
try {
await req.patch()
} catch (error) {
cachedResponses.missing = error.message
}
req = TestHelper.createRequest('/api/administrator/subscriptions/set-subscription-item-quantity?subscriptionitemid=invalid')
req.account = administrator.account
req.session = administrator.session
req.body = {
quantity: '10'
}
try {
await req.patch()
} catch (error) {
cachedResponses.invalid = error.message
}
// invalid quantity
req = TestHelper.createRequest(`/api/administrator/subscriptions/set-subscription-item-quantity?subscriptionitemid=${user.subscription.stripeObject.items.data[0].id}`)
req.account = administrator.account
req.session = administrator.session
req.body = {
quantity: 'letters',
itemid: user.subscription.stripeObject.items.data[0].id
}
try {
await req.patch()
} catch (error) {
cachedResponses.invalidQuantity = error.message
}
req = TestHelper.createRequest(`/api/administrator/subscriptions/set-subscription-item-quantity?subscriptionitemid=${user.subscription.stripeObject.items.data[0].id}`)
req.account = administrator.account
req.session = administrator.session
req.body = {
quantity: '1',
itemid: user.subscription.stripeObject.items.data[0].id
}
try {
await req.patch()
} catch (error) {
cachedResponses.unchangedQuantity = error.message
}
req = TestHelper.createRequest(`/api/administrator/subscriptions/set-subscription-item-quantity?subscriptionitemid=${user.subscription.stripeObject.items.data[0].id}`)
req.account = administrator.account
req.session = administrator.session
req.body = {
quantity: '-1',
itemid: user.subscription.stripeObject.items.data[0].id
}
try {
await req.patch()
} catch (error) {
cachedResponses.negativeQuantity = error.message
}
req = TestHelper.createRequest(`/api/administrator/subscriptions/set-subscription-item-quantity?subscriptionitemid=${user.subscription.stripeObject.items.data[0].id}`)
req.account = administrator.account
req.session = administrator.session
req.body = {
quantity: '0',
itemid: user.subscription.stripeObject.items.data[0].id
}
try {
await req.patch()
} catch (error) {
cachedResponses.zeroQuantity = error.message
}
// returns
req = TestHelper.createRequest(`/api/administrator/subscriptions/set-subscription-item-quantity?subscriptionitemid=${user.subscription.stripeObject.items.data[0].id}`)
req.account = administrator.account
req.session = administrator.session
req.body = {
quantity: '2',
itemid: user.subscription.stripeObject.items.data[0].id
}
req.filename = __filename
req.saveResponse = true
cachedResponses.returns = await req.patch()
cachedResponses.finished = true
}
describe('exceptions', () => {
describe('invalid-subscriptionitemid', () => {
it('missing querystring subscriptionitemid', async function () {
await bundledData(this.test.currentRetry())
const errorMessage = cachedResponses.missing
assert.strictEqual(errorMessage, 'invalid-subscriptionitemid')
})
it('invalid querystring subscriptionitemid', async function () {
await bundledData(this.test.currentRetry())
const errorMessage = cachedResponses.invalid
assert.strictEqual(errorMessage, 'invalid-subscriptionitemid')
})
})
describe('invalid-quantity', () => {
it('invalid posted quantity', async function () {
await bundledData(this.test.currentRetry())
const errorMessage = cachedResponses.invalidQuantity
assert.strictEqual(errorMessage, 'invalid-quantity')
})
it('invalid posted quantity is unchanged', async function () {
await bundledData(this.test.currentRetry())
const errorMessage = cachedResponses.unchangedQuantity
assert.strictEqual(errorMessage, 'invalid-quantity')
})
it('invalid posted quantity is negative', async function () {
await bundledData(this.test.currentRetry())
const errorMessage = cachedResponses.negativeQuantity
assert.strictEqual(errorMessage, 'invalid-quantity')
})
it('invalid posted quantity is zero', async function () {
await bundledData(this.test.currentRetry())
const errorMessage = cachedResponses.zeroQuantity
assert.strictEqual(errorMessage, 'invalid-quantity')
})
})
})
describe('returns', () => {
it('object', async () => {
const subscriptionItemNow = cachedResponses.returns
assert.strictEqual(subscriptionItemNow.stripeObject.quantity, 2)
})
})
})