UNPKG

@fabrix/spool-cart

Version:

Spool - eCommerce Spool for Fabrix

322 lines (321 loc) 11 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const common_1 = require("@fabrix/fabrix/dist/common"); const spool_sequelize_1 = require("@fabrix/spool-sequelize"); const errors_1 = require("@fabrix/spool-sequelize/dist/errors"); const lodash_1 = require("lodash"); const shortId = require("shortid"); class SourceResolver extends spool_sequelize_1.SequelizeResolver { batch(options, batch) { const self = this; options.limit = options.limit || 100; options.offset = options.offset || 0; options.regressive = options.regressive || false; const recursiveQuery = function (options) { let count = 0; return self.findAndCountAll(options) .then(results => { count = results.count; return batch(results.rows); }) .then(batched => { if (count >= (options.regressive ? options.limit : options.offset + options.limit)) { options.offset = options.regressive ? 0 : options.offset + options.limit; return recursiveQuery(options); } else { return Promise.resolve(); } }); }; return recursiveQuery(options); } resolveByInstance(source, options = {}) { return Promise.resolve(source); } resolveById(source, options = {}) { return this.findById(source.id, options) .then(resUser => { if (!resUser && options.reject !== false) { throw new errors_1.ModelError('E_NOT_FOUND', `Source ${source.id} not found`); } return resUser; }); } resolveByToken(source, options = {}) { return this.findOne(this.app.services.SequelizeService.mergeOptionDefaults(options, { where: { token: source.token } })) .then(resUser => { if (!resUser && options.reject !== false) { throw new errors_1.ModelError('E_NOT_FOUND', `Source token ${source.token} not found`); } return resUser; }); } resolveByNumber(source, options = {}) { return this.findById(source, options) .then(resUser => { if (!resUser && options.reject !== false) { throw new errors_1.ModelError('E_NOT_FOUND', `Source ${source.token} not found`); } return resUser; }); } resolveByString(source, options = {}) { return this.findOne(this.app.services.SequelizeService.mergeOptionDefaults(options, { where: { token: source } })) .then(resUser => { if (!resUser && options.reject !== false) { throw new errors_1.ModelError('E_NOT_FOUND', `Source ${source} not found`); } return resUser; }); } resolve(source, options = {}) { const resolvers = { 'instance': source instanceof this.instance, 'id': !!(source && lodash_1.isObject(source) && source.id), 'token': !!(source && lodash_1.isObject(source) && source.token), 'number': !!(source && lodash_1.isNumber(source)), 'string': !!(source && lodash_1.isString(source)) }; const type = Object.keys(resolvers).find((key) => resolvers[key]); switch (type) { case 'instance': { return this.resolveByInstance(source, options); } case 'id': { return this.resolveById(source, options); } case 'token': { return this.resolveByToken(source, options); } case 'number': { return this.resolveByNumber(source, options); } case 'string': { return this.resolveByString(source, options); } default: { const err = new Error(`Unable to resolve Source ${source}`); return Promise.reject(err); } } } } exports.SourceResolver = SourceResolver; class Source extends common_1.FabrixModel { static get resolver() { return SourceResolver; } static config(app, Sequelize) { return { options: { underscored: true, scopes: { live: { where: { live_mode: true } } }, hooks: { beforeCreate: [ (values, options) => { if (!values.token) { values.token = `source_${shortId.generate()}`; } } ], afterCreate: [ (values, options) => { return app.services.AccountService.afterSourceCreate(values) .catch(err => { return Promise.reject(err); }); } ], afterDestroy: [ (values, options) => { return app.services.AccountService.afterSourceDestroy(values) .catch(err => { return Promise.reject(err); }); } ] } } }; } static schema(app, Sequelize) { return { customer_id: { type: Sequelize.INTEGER, allowNull: false }, account_id: { type: Sequelize.INTEGER, allowNull: true }, token: { type: Sequelize.STRING, unique: true }, gateway: { type: Sequelize.STRING, defaultValue: 'payment_processor' }, account_foreign_key: { type: Sequelize.STRING, allowNull: false }, account_foreign_id: { type: Sequelize.STRING, allowNull: false }, foreign_key: { type: Sequelize.STRING, allowNull: false }, foreign_id: { type: Sequelize.STRING, allowNull: false }, is_default: { type: Sequelize.BOOLEAN, defaultValue: false }, payment_details: { type: Sequelize.JSONB, defaultValue: {} }, live_mode: { type: Sequelize.BOOLEAN, defaultValue: app.config.get('cart.live_mode') } }; } static associate(models) { models.Source.belongsTo(models.Account, {}); models.Source.belongsTo(models.Customer, {}); models.Source.hasMany(models.Transaction, { as: 'transactions', }); } } exports.Source = Source; Source.prototype.getBrand = function () { let brand = this.gateway; if (this.payment_details && this.payment_details.credit_card_company) { brand = this.payment_details.credit_card_company; } return brand; }; Source.prototype.getType = function () { let type; switch (this.payment_details.type) { case 'credit_card': type = 'Credit Card'; break; case 'debit_card': type = 'Debit Card'; break; default: type = 'Payment Method'; } return type; }; Source.prototype.getLast4 = function () { let last4 = '****'; if (this.payment_details && this.payment_details.credit_card_last4) { last4 = this.payment_details.credit_card_last4; } return last4; }; Source.prototype.getExpiration = function () { let expiration = 'MM/YYYY'; if (this.payment_details && this.payment_details.credit_card_exp_year && this.payment_details.credit_card_exp_month) { expiration = `${this.payment_details.credit_card_exp_month}/${this.payment_details.credit_card_exp_year}`; } return expiration; }; Source.prototype.notifyCustomer = function (preNotification, options = {}) { options = options || {}; if (this.customer_id) { return this.resolveCustomer({ attributes: ['id', 'email', 'company', 'first_name', 'last_name', 'full_name'], transaction: options.transaction || null, reload: options.reload || null }) .then(() => { if (this.Customer && this.Customer instanceof this.app.models['Customer'].instance) { return this.Customer.notifyUsers(preNotification, { transaction: options.transaction || null }); } else { return; } }) .then(() => { return this; }); } else { return Promise.resolve(this); } }; Source.prototype.resolveCustomer = function (options = {}) { if (this.Customer && this.Customer instanceof this.app.models['Customer'].instance && options.reload !== true) { return Promise.resolve(this); } else if (!this.customer_id) { return Promise.resolve(this); } else { return this.getCustomer({ transaction: options.transaction || null }) .then(_customer => { _customer = _customer || null; this.Customer = _customer; this.setDataValue('Customer', _customer); this.set('Customer', _customer); return this; }); } }; Source.prototype.sendExpiredEmail = function (options = {}) { return this.app.emails.Source.expired(this, { send_email: this.app.config.get('cart.emails.sourceExpired') }, { transaction: options.transaction || null }) .then(email => { return this.notifyCustomer(email, { transaction: options.transaction || null }); }) .catch(err => { this.app.log.error(err); return; }); }; Source.prototype.sendWillExpireEmail = function (options = {}) { return this.app.emails.Source.willExpire(this, { send_email: this.app.config.get('cart.emails.sourceWillExpire') }, { transaction: options.transaction || null }) .then(email => { return this.notifyCustomer(email, { transaction: options.transaction || null }); }) .catch(err => { this.app.log.error(err); return; }); };