vendure-plugin-payment-terms
Version:
This plugin allows certain customers to pay using Payment Terms. Payment Terms are when a customer is allowed to make a payment a certain number of days after an invoice is due.
172 lines (171 loc) • 9.18 kB
JavaScript
;
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.VendurePluginPaymentTerms = void 0;
const core_1 = require("@vendure/core");
const payment_eligibilty_checker_1 = require("./api/payment-eligibilty-checker");
const payment_handler_1 = require("./api/payment-handler");
const schedule_1 = require("@nestjs/schedule");
const cron_1 = require("cron");
const rxjs_1 = require("rxjs");
require("./api/types");
const dayjs_1 = __importDefault(require("dayjs"));
const payment_terms_event_1 = require("./api/payment-terms-event");
const constants_1 = require("./constants");
const payment_method_quote_field_resolver_1 = require("./api/payment-method-quote-field.resolver");
const schema_1 = require("./api/schema");
const payment_method_checker_config_arg_fix_resolver_1 = require("./api/payment-method-checker-config-arg-fix.resolver");
const CRON_JOB_PREFIX = `VendurePluginPaymentTerms`;
let VendurePluginPaymentTerms = class VendurePluginPaymentTerms {
constructor(eventBus, conn, orderService, schedulerRegistry) {
this.eventBus = eventBus;
this.conn = conn;
this.orderService = orderService;
this.schedulerRegistry = schedulerRegistry;
}
onApplicationBootstrap() {
this.eventBus.ofType(core_1.CustomerEvent).pipe((0, rxjs_1.filter)((e) => e.type !== 'deleted' && !!e.entity.customFields.paymentTermsInDays && !!e.entity.emailAddress)).subscribe(({ entity, ctx }) => {
const jobName = this.getCronJobNameForCustomer(entity);
// const testCronTime=`40 * * * * *`
try {
const job = this.schedulerRegistry.getCronJob(jobName);
const lastTimeExecuted = job.lastDate();
let everyThisDayFromNow = 0;
let dueDate;
if (lastTimeExecuted) {
dueDate = (0, dayjs_1.default)(lastTimeExecuted).add(entity.customFields.paymentTermsInDays ?? 0, 'days');
everyThisDayFromNow = dueDate.diff(new Date(), 'days');
}
else {
everyThisDayFromNow = (entity.customFields.paymentTermsInDays ?? 0);
dueDate = (0, dayjs_1.default)(new Date()).add(everyThisDayFromNow, 'days');
}
everyThisDayFromNow = Math.round(everyThisDayFromNow);
const realCronTimeFormat = `0 0 */${everyThisDayFromNow} * *`;
job.setTime(new cron_1.CronTime(realCronTimeFormat));
core_1.Logger.info(`The next payment due remainder for ${entity.emailAddress} is reset to ${(0, dayjs_1.default)(job.nextDate().toJSDate()).locale('en').format('ddd, MMM D, YYYY h:mm A')}`, constants_1.loggerCtx);
}
catch (e) {
//no existing cron Job, create new one
const everyThisDayFromNow = Math.round((entity.customFields.paymentTermsInDays ?? 0));
const realCronTimeFormat = `0 0 */${everyThisDayFromNow} * *`;
const job = new cron_1.CronJob(realCronTimeFormat, async () => {
core_1.Logger.info(`Notifying ${entity.emailAddress} to update his Payment Terms`);
//fire the event
const orderRepo = this.conn.getRepository(ctx, core_1.Order);
const notRemindedCustomerOrders = await orderRepo.createQueryBuilder('order')
.leftJoinAndSelect('order.customer', 'customer')
.leftJoinAndSelect('order.lines', 'line')
.where('customer.id=:customerId', { customerId: entity.id })
.andWhere('order.customFields.notReminded')
.getMany();
const orderUpdatePromises = [];
for (let order of notRemindedCustomerOrders) {
this.eventBus.publish(new payment_terms_event_1.PaymentTermsDueEvent(ctx, entity, order));
orderUpdatePromises.push(this.orderService.updateCustomFields(ctx, order.id, { ...order.customFields, notReminded: false }));
}
await Promise.all(orderUpdatePromises);
});
this.schedulerRegistry.addCronJob(jobName, job);
job.start();
core_1.Logger.info(`The next payment due remainder for ${entity.emailAddress} is set to ${(0, dayjs_1.default)(job.nextDate().toJSDate()).locale('en').format('ddd, MMM D, YYYY h:mm A')}`, constants_1.loggerCtx);
}
});
this.eventBus.ofType(core_1.CustomerEvent).pipe((0, rxjs_1.filter)((e) => e.type === 'deleted')).subscribe(({ entity }) => {
try {
const name = this.getCronJobNameForCustomer(entity);
const job = this.schedulerRegistry.getCronJob(name);
job.stop();
this.schedulerRegistry.deleteCronJob(name);
core_1.Logger.info(`Stopped the payment due remainder for ${entity.emailAddress}`, constants_1.loggerCtx);
}
catch (e) {
//no cron Job for customer, ignore
}
});
}
getCronJobNameForCustomer(customer) {
return `${CRON_JOB_PREFIX}-${customer.emailAddress}`;
}
};
VendurePluginPaymentTerms = __decorate([
(0, core_1.VendurePlugin)({
imports: [core_1.PluginCommonModule, schedule_1.ScheduleModule.forRoot()],
shopApiExtensions: { resolvers: [payment_method_quote_field_resolver_1.PaymentMethodQuoteFieldResolver], schema: schema_1.shopApiExtensions },
adminApiExtensions: { resolvers: [payment_method_checker_config_arg_fix_resolver_1.OverridePaymentMethodResolver] },
configuration: (config) => {
if (config.paymentOptions.paymentMethodEligibilityCheckers?.length) {
config.paymentOptions.paymentMethodEligibilityCheckers.push(payment_eligibilty_checker_1.paymentTermsEligibilityChecker);
}
else {
config.paymentOptions.paymentMethodEligibilityCheckers = [payment_eligibilty_checker_1.paymentTermsEligibilityChecker];
}
config.paymentOptions.paymentMethodHandlers.push(payment_handler_1.paymentWithTermsHandler);
config.customFields.Customer.push({
name: 'paymentTermsInDays',
type: 'float',
defaultValue: 0,
public: false,
ui: { component: 'number-form-input', suffix: 'days' },
label: [
{
languageCode: core_1.LanguageCode.en,
value: 'Payment Terms'
}
]
}, {
name: 'paymentLimit',
defaultValue: 0,
type: 'int',
public: false,
ui: { component: 'currency-form-input' },
label: [
{
languageCode: core_1.LanguageCode.en,
value: 'Payment Limit'
}
]
});
config.customFields.Address.push({
name: 'vat',
label: [
{ languageCode: core_1.LanguageCode.en, value: 'VAT Number' }
],
type: 'string'
}, {
name: 'purchaseOrder',
label: [
{ languageCode: core_1.LanguageCode.en, value: 'Purchase Order (PO) Number' }
],
type: 'string'
});
config.customFields.Order.push({
name: 'notReminded',
type: 'boolean',
public: false,
readonly: true,
defaultValue: true,
label: [
{ languageCode: core_1.LanguageCode.en, value: 'Not Reminded' }
],
});
return config;
}
}),
__metadata("design:paramtypes", [core_1.EventBus,
core_1.TransactionalConnection,
core_1.OrderService,
schedule_1.SchedulerRegistry])
], VendurePluginPaymentTerms);
exports.VendurePluginPaymentTerms = VendurePluginPaymentTerms;