declastruct-stripe-sdk
Version:
declarative control of stripe constructs, via declastruct
114 lines • 5.14 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.setInvoiceItem = void 0;
const domain_objects_1 = require("domain-objects");
const hash_fns_1 = require("hash-fns");
const helpful_errors_1 = require("helpful-errors");
const type_fns_1 = require("type-fns");
const castToDeclaredStripeInvoiceItem_1 = require("../cast/castToDeclaredStripeInvoiceItem");
const getCustomer_1 = require("../customer/getCustomer");
const setCoupon_1 = require("../discount/coupon/setCoupon");
const getInvoice_1 = require("../invoice/getInvoice");
const getProduct_1 = require("../product/getProduct");
const getInvoiceItem_1 = require("./getInvoiceItem");
/**
* .what = sets an invoice item
*/
const setInvoiceItem = async (input, context) => {
// define the desired invoice item state
const itemDesired = input.finsert ??
input.upsert ??
helpful_errors_1.UnexpectedCodePathError.throw('expected either finsert or upsert to be defined', { input });
// resolve the invoice ref
const invoiceFound = await (0, getInvoice_1.getInvoice)({
by: {
ref: itemDesired.invoiceRef,
},
}, context);
if (!invoiceFound)
throw new helpful_errors_1.BadRequestError('can not resolve item.invoiceRef', { input });
// resolve the customer ref
const customerFound = await (0, getCustomer_1.getCustomer)({
by: {
ref: invoiceFound.customerRef,
},
}, context);
if (!customerFound)
throw new helpful_errors_1.BadRequestError('can not resolve item.invoice.customerRef', {
invoiceFound,
});
// resolve the product ref
const productFound = await (0, getProduct_1.getProduct)({
by: {
ref: itemDesired.productRef,
},
}, context);
if (!productFound)
throw new helpful_errors_1.BadRequestError('can not resolve item.productRef', { input });
// lookup the item
const itemFound = await (0, getInvoiceItem_1.getInvoiceItem)({
by: {
unique: {
invoiceRef: invoiceFound,
exid: itemDesired.exid,
},
},
}, context);
// define how to get the desired discounts
const getDiscountsDesired = async () => !itemDesired.discounts
? '' // per stripe, "pass an empty string to remove existing discounts"
: await Promise.all(itemDesired.discounts.map(async (discountDesired) => {
const coupon = await (0, setCoupon_1.setCoupon)({ insert: discountDesired }, // unfortunately, stripe has no unique key for coupons, so we must always insert 🥲
context);
return { coupon: coupon.id };
}));
// sanity check that if the product exists, their id matches the user's expectations, if any
const primaryIdFound = itemFound?.id;
const primaryIdExpected = itemDesired.id;
if (primaryIdFound &&
primaryIdExpected &&
primaryIdExpected !== primaryIdFound)
throw new helpful_errors_1.UnexpectedCodePathError('asked to setItem with a desired.primary=id which does not match the found.primary=id', {
primaryIdExpected,
primaryIdFound,
itemFound,
});
// if the item was found, then handle that
if (itemFound) {
// if asked to finsert, then we can return it now
if (input.finsert)
return itemFound;
// if asked to upsert, then we can update it now
if (input.upsert) {
const invoiceUpdated = await context.stripe.invoiceItems.update(itemFound.id, {
description: input.upsert.description ?? undefined,
metadata: input.upsert.metadata ?? undefined,
discounts: await getDiscountsDesired(),
price: (await context.stripe.products.retrieve(productFound.id)).default_price,
expand: ['discounts'],
});
return (0, castToDeclaredStripeInvoiceItem_1.castToDeclaredStripeInvoiceItem)(invoiceUpdated);
}
}
// otherwise, create the item
const itemCreated = await context.stripe.invoiceItems.create({
invoice: invoiceFound.id,
customer: customerFound.id,
description: itemDesired.description ?? undefined,
metadata: {
exid: itemDesired.exid,
...(0, type_fns_1.omit)(itemDesired.metadata ?? {}, ['exid']),
},
discounts: await getDiscountsDesired(),
price: (await context.stripe.products.retrieve(productFound.id)).default_price,
expand: ['discounts'],
}, {
idempotencyKey: (0, hash_fns_1.toHashSha256Sync)([
'v1.0.0',
(0, domain_objects_1.serialize)((0, type_fns_1.pick)(itemDesired, ['invoiceRef', 'exid'])), // make it idempotent on the unique keys; // todo: use domain-objects.getUniqueKeys({ of: DeclaredStripeInvoice }) instead of hardcoding the keys
].join(';')),
});
return (0, castToDeclaredStripeInvoiceItem_1.castToDeclaredStripeInvoiceItem)(itemCreated);
};
exports.setInvoiceItem = setInvoiceItem;
//# sourceMappingURL=setInvoiceItem.js.map