agmission/Development/server/model/subscription.js

134 lines
3.9 KiB
JavaScript

const Schema = require('mongoose').Schema;
const SubStatus = Object.freeze({
ACTIVE: "active", PAST_DUE: "past_due", UNPAID: "unpaid", CANCELED: "canceled", INCOMPLETE: "incomplete", INCOMPLETE_EXPIRED: "incomplete_expired", TRIALING: "trialing", PAUSED: "paused"
});
const InvStatus = Object.freeze({ DRAFT: 'draft', OPEN: 'open', PAID: 'paid', UNCOLLECTIBLE: 'uncollectible', VOID: 'void' });
const ChrgStatus = Object.freeze({ SUCCEEDED: 'succeeded', PENDING: 'pending', FAILED: 'failed' });
const SubType = Object.freeze({
PACKAGE: "package", ADDON: "addon"
});
const RecurType = Object.freeze({
MONTH: "month", YEAR: "year", WEEK: "week", day: "day"
});
const AutoTaxStatus = Object.freeze({
SUPPORTED: 'supported', NOT_COLLECTING: 'not_collecting'
});
const SubFields = Object.freeze({
ID: 'id',
METADATA: 'metadata',
TYPE: 'type',
PRICE: 'price',
QUANTITY: 'quantity',
TIER: 'tier',
MAX_VEHICLES: 'maxVehicles', // Custom, only use in metadata
MAX_ACRES: 'maxAcres', // Custom, only use in metadata
LEVEL: 'level',
STATUS: 'status',
TAX: 'tax',
REFUNDED: 'refunded',
LIMIT: 'limit',
DEFAULT_PAYMENT_METHOD: 'default_payment_method',
DEFAULT_SOURCE: 'default_source',
NAME: 'name',
BILLING_DETAILS: 'billing_details', // PM Object's billing_details
'CARD': 'card',
EXP_MONTH: 'exp_month',
EXP_YEAR: 'exp_year'
});
const Events = Object.freeze({
CUST_SUB_TRIAL_WILL_END: 'customer.subscription.trial_will_end',
CUST_SUB_DELETED: "customer.subscription.deleted",
CUST_SUB_CREATED: "customer.subscription.created",
CUST_SUB_UPDATED: "customer.subscription.updated",
INV_UPCOMING: 'invoice.upcoming',
INV_PAID: "invoice.paid",
INV_PM_SUCCEEDED: "invoice.payment_succeeded",
INV_PM_FAILED: "invoice.payment_failed",
INV_FIN_FAILED: "invoice.finalization_failed",
INV_PM_ACT_REQUIRED: "invoice.payment_action_required",
CHARGE_RFD_UPDATED: "charge.refund.updated",
CHARGE_SUCCEEDED: "charge.succeeded"
});
function isTaxableCountry(country) {
return country && country == 'CA';
}
function isValidTaxStatus(status) {
return [AutoTaxStatus.SUPPORTED, AutoTaxStatus.NOT_COLLECTING].includes(status);
}
function isFinalSubStatus(status) {
return [SubStatus.CANCELED, SubStatus.INCOMPLETE_EXPIRED].includes(status);
}
/*
Subscription information
[
{
id: subscription id,
type: 'PACKAGE'/'ADDON',
status: subscription status, // Need to handle user action when value other than 'active', especially 'incomplete' for user actions
periodStart: subscription current_period_start,
periodEnd: subscription current_period_end,
items: [
price: 'lookup_key',
quantity: '' // optional for package or can be 1
],
}
]
*/
const subscriptionSchema = new Schema({
id: String,
type: {
type: String,
enum: {
values: Object.values(SubType),
message: '{VALUE} for subscription \'type\' is not supported'
}
},
status: {
type: String,
enum: {
values: Object.values(SubStatus),
message: '{VALUE} for subscription \'status\' is not supported'
}
},
periodStart: Number,
periodEnd: Number,
items: [
{
price: String,
quantity: {
type: Number, required: false,
min: [1, 'quantity must be at least 1'],
max: [100, 'quantity must be at max of 100']
},
metadata: Schema.Types.Mixed
}
],
// billing cycles: monthly, yearly, quarterly, etc.
recurring: {
interval: {
type: String,
enum: {
values: Object.values(RecurType),
message: '{VALUE} for subscription \'recurring\' is not supported'
}
},
intervalCount: { type: Number, default: 1 }
},
cancelAtPeriodEnd: Boolean,
trialEnd: Number
});
module.exports = {
subscriptionSchema, SubStatus, SubType, SubFields, Events, InvStatus, ChrgStatus, isTaxableCountry, AutoTaxStatus, isValidTaxStatus, isFinalSubStatus
}