UNPKG

@fabrix/spool-cart

Version:

Spool - eCommerce Spool for Fabrix

402 lines (401 loc) 17.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const common_1 = require("@fabrix/fabrix/dist/common"); const errors_1 = require("@fabrix/spool-sequelize/dist/errors"); const enums_1 = require("../../enums"); const enums_2 = require("../../enums"); class FulfillmentService extends common_1.FabrixService { publish(type, event, options = {}) { if (this.app.services.EventsService) { options.include = options.include || [{ model: this.app.models.EventItem.instance, as: 'objects' }]; return this.app.services.EventsService.publish(type, event, options); } this.app.log.debug('spool-events is not installed, please install it to use publish'); return Promise.resolve(); } sendFulfillment(order, fulfillment, options = {}) { const Order = this.app.models['Order']; const Fulfillment = this.app.models['Fulfillment']; let resOrder, resFulfillment; return Order.resolve(order, { transaction: options.transaction || null }) .then(_order => { if (!_order) { throw new Error('Order not found'); } resOrder = _order; return Fulfillment.resolve(fulfillment, { transaction: options.transaction || null }); }) .then(_fulfillment => { if (!_fulfillment) { throw new errors_1.ModelError('E_NOT_FOUND', 'Fulfillment not found'); } resFulfillment = _fulfillment; return resFulfillment.resolveOrderItems({ transaction: options.transaction || null }); }) .then(() => { if (!resFulfillment.order_items) { throw new Error('Fulfillment missing order_items'); } if (resFulfillment.service === enums_1.FULFILLMENT_SERVICE.MANUAL && !resFulfillment.order_items.some(i => i.requires_shipping === true)) { resFulfillment.fulfilled(); return Fulfillment.sequelize.Promise.mapSeries(resFulfillment.order_items, item => { item.fulfillment_status = resFulfillment.status; return item.save({ hooks: false, transaction: options.transaction || null }); }); } else if (resFulfillment.service === enums_1.FULFILLMENT_SERVICE.MANUAL && resFulfillment.order_items.some(i => i.requires_shipping === true)) { resFulfillment.sent(); return Fulfillment.sequelize.Promise.mapSeries(resFulfillment.order_items, item => { item.fulfillment_status = resFulfillment.status; return item.save({ hooks: false, transaction: options.transaction || null }); }); } else { return this.app.services.FulfillmentGenericService.createOrder(resFulfillment, resFulfillment.service) .then(result => { resFulfillment[result.status](); return Fulfillment.sequelize.Promise.mapSeries(resFulfillment.order_items, item => { item.fulfillment_status = resFulfillment.status; return item.save({ hooks: false, transaction: options.transaction || null }); }); }); } }) .then(() => { return resFulfillment.saveFulfillmentStatus({ transaction: options.transaction || null }); }) .then(() => { const event = { object_id: resFulfillment.order_id, object: 'order', objects: [{ order: resOrder.id }, { customer: resOrder.customer_id }, { fulfillment: resFulfillment.id }], type: `order.fulfillment.${resFulfillment.status}`, message: `Order ${resOrder.name} fulfillment ID ${resFulfillment.id} ${resFulfillment.status}`, data: resFulfillment }; return this.publish(event.type, event, { save: true, transaction: options.transaction || null }); }) .then(event => { return resFulfillment; }); } updateFulfillment(fulfillment, options = {}) { const Fulfillment = this.app.models['Fulfillment']; let resFulfillment; return Fulfillment.resolve(fulfillment, { transaction: options.transaction || null }) .then(_fulfillment => { if (!_fulfillment) { throw new Error('Fulfillment not found'); } if ([enums_2.FULFILLMENT_STATUS.FULFILLED, enums_2.FULFILLMENT_STATUS.CANCELLED].indexOf(_fulfillment.status) > -1) { throw new Error(`Fulfillment status must be ${enums_2.FULFILLMENT_STATUS.PENDING}, ${enums_2.FULFILLMENT_STATUS.NONE}, ${enums_2.FULFILLMENT_STATUS.PARTIAL}, ${enums_2.FULFILLMENT_STATUS.SENT} to update`); } resFulfillment = _fulfillment; if ([enums_2.FULFILLMENT_STATUS.NONE, enums_2.FULFILLMENT_STATUS.PENDING].indexOf(resFulfillment.status) > -1) { return; } else if ([enums_2.FULFILLMENT_STATUS.SENT, enums_2.FULFILLMENT_STATUS.PARTIAL].indexOf(resFulfillment.status) > -1) { return this.app.services.FulfillmentGenericService.updateOrder(resFulfillment, resFulfillment.service); } else { return; } }) .then(() => { return resFulfillment.saveFulfillmentStatus({ transaction: options.transaction || null }); }); } cancelFulfillment(fulfillment, options = {}) { const Fulfillment = this.app.models['Fulfillment']; let resFulfillment; return Fulfillment.resolve(fulfillment, { transaction: options.transaction || null }) .then(_fulfillment => { if (!_fulfillment) { throw new Error('Fulfillment not found'); } if ([enums_2.FULFILLMENT_STATUS.FULFILLED, enums_2.FULFILLMENT_STATUS.CANCELLED].indexOf(_fulfillment.status) > -1) { throw new Error(`Fulfillment status must be ${enums_2.FULFILLMENT_STATUS.PENDING}, ${enums_2.FULFILLMENT_STATUS.NONE}, ${enums_2.FULFILLMENT_STATUS.PARTIAL}, ${enums_2.FULFILLMENT_STATUS.SENT} to be cancelled`); } resFulfillment = _fulfillment; return resFulfillment.resolveOrderItems({ transaction: options.transaction || null }); }) .then(() => { if ([enums_2.FULFILLMENT_STATUS.NONE, enums_2.FULFILLMENT_STATUS.PENDING].indexOf(resFulfillment.status) > -1) { return; } else if (resFulfillment.service === enums_1.FULFILLMENT_SERVICE.MANUAL) { return; } else { return this.app.services.FulfillmentGenericService.destroyOrder(resFulfillment, resFulfillment.service); } }) .then(() => { resFulfillment.cancelled(); return resFulfillment.fulfillUpdate({ status: enums_2.FULFILLMENT_STATUS.CANCELLED }, { transaction: options.transaction || null }); }) .then(() => { return resFulfillment.save({ transaction: options.transaction || null }); }); } addOrCreateFulfillmentItem(item, options = {}) { const OrderItem = this.app.models['OrderItem']; const Fulfillment = this.app.models['Fulfillment']; let resOrderItem, resFulfillment; return OrderItem.resolve(item, { transaction: options.transaction || null }) .then(_item => { if (!_item) { throw new errors_1.ModelError('E_NOT_FOUND', 'Order Item not Found'); } resOrderItem = _item; return Fulfillment.findOne({ where: { order_id: resOrderItem.order_id, service: resOrderItem.fulfillment_service }, include: [ { model: OrderItem.instance, as: 'order_items' } ], transaction: options.transaction || null }); }) .then(_fulfillment => { if (_fulfillment) { resFulfillment = _fulfillment; return resFulfillment.addOrder_item(resOrderItem, { hooks: false, individualHooks: false, returning: false, transaction: options.transaction || null }) .then(() => { return resFulfillment.reload({ transaction: options.transaction || null }) .then(() => { return resFulfillment.saveFulfillmentStatus({ transaction: options.transaction || null }); }); }) .then(() => { return this.updateFulfillment(resFulfillment, { transaction: options.transaction || null }); }); } else { return Fulfillment.create({ order_id: resOrderItem.order_id, service: resOrderItem.fulfillment_service, }, { include: [ { model: OrderItem.instance, as: 'order_items' } ], transaction: options.transaction || null }) .then(_newFulfillment => { if (!_newFulfillment) { throw new Error('Fulfillment was not created'); } resFulfillment = _newFulfillment; return resFulfillment.addOrder_item(resOrderItem, { hooks: false, individualHooks: false, returning: false, transaction: options.transaction || null }) .then(() => { return resFulfillment.reload({ transaction: options.transaction || null }) .then(() => { return resFulfillment.saveFulfillmentStatus({ transaction: options.transaction || null }); }); }) .then(() => { return this.updateFulfillment(resFulfillment, { transaction: options.transaction || null }); }); }); } }) .then(() => { return resOrderItem.reload({ transaction: options.transaction || null }); }); } updateFulfillmentItem(item, options = {}) { const OrderItem = this.app.models['OrderItem']; const Fulfillment = this.app.models['Fulfillment']; let resOrderItem, resFulfillment; return OrderItem.resolve(item, { transaction: options.transaction || null }) .then(_item => { if (!_item) { throw new errors_1.ModelError('E_NOT_FOUND', 'Order Item not Found'); } resOrderItem = _item; return Fulfillment.findOne({ where: { order_id: resOrderItem.order_id, service: resOrderItem.fulfillment_service }, include: [ { model: OrderItem.instance, as: 'order_items' } ], transaction: options.transaction || null }); }) .then(fulfillment => { if (!fulfillment) { throw new errors_1.ModelError('E_NOT_FOUND', 'Fulfillment not found'); } resFulfillment = fulfillment; return resFulfillment.hasOrder_item(resOrderItem.id, { transaction: options.transaction || null }); }) .then(hasOrderItem => { if (!hasOrderItem) { return resFulfillment.addOrder_item(resOrderItem, { hooks: false, individualHooks: false, returning: false, transaction: options.transaction || null }); } else { return; } }) .then(() => { return resFulfillment.reload({ transaction: options.transaction || null }); }) .then(() => { return resFulfillment.saveFulfillmentStatus({ transaction: options.transaction || null }); }) .then(() => { return this.updateFulfillment(resFulfillment, { transaction: options.transaction || null }); }) .then(() => { return resOrderItem.reload({ transaction: options.transaction || null }); }); } removeFulfillmentItem(item, options = {}) { const OrderItem = this.app.models['OrderItem']; const Fulfillment = this.app.models['Fulfillment']; let resOrderItem, resFulfillment; return OrderItem.resolve(item, options) .then(_item => { if (!_item) { throw new Error('Order Item not Found'); } resOrderItem = _item; return Fulfillment.findOne({ where: { order_id: resOrderItem.order_id, service: resOrderItem.fulfillment_service }, include: [ { model: OrderItem.instance, as: 'order_items' } ], transaction: options.transaction || null }); }) .then(fulfillment => { if (!fulfillment) { throw new errors_1.ModelError('E_NOT_FOUND', 'Fulfillment not found'); } resFulfillment = fulfillment; return resFulfillment.hasOrder_item(resOrderItem, { transaction: options.transaction || null }); }) .then(hasOrderItem => { if (hasOrderItem && resOrderItem.quantity === 0) { return resFulfillment.removeOrder_item(resOrderItem, { hooks: false, individualHooks: false, returning: false, transaction: options.transaction || null }); } else { return; } }) .then(() => { return resFulfillment.reload({ transaction: options.transaction || null }); }) .then(() => { return resFulfillment.saveFulfillmentStatus({ transaction: options.transaction || null }); }) .then(() => { return this.updateFulfillment(resFulfillment, { transaction: options.transaction || null }); }) .then(() => { return resOrderItem; }); } manualUpdateFulfillment(fulfillment, options = {}) { const Fulfillment = this.app.models['Fulfillment']; let resFulfillment; return Fulfillment.resolve(fulfillment, { transaction: options.transaction || null }) .then(_fulfillment => { if (!_fulfillment) { throw new Error('Fulfillment not found'); } resFulfillment = _fulfillment; return resFulfillment.fulfillUpdate(fulfillment, { transaction: options.transaction || null }); }) .then((_update) => { return resFulfillment.save({ transaction: options.transaction || null }); }); } beforeCreate(fulfillment, options) { return Promise.resolve(fulfillment); } beforeUpdate(fulfillment, options) { return Promise.resolve(fulfillment); } afterCreate(fulfillment, options) { return fulfillment.reconcileFulfillmentStatus({ transaction: options.transaction || null }); } afterUpdate(fulfillment, options) { return fulfillment.reconcileFulfillmentStatus({ transaction: options.transaction || null }); } beforeEventCreate(fulfillment, options) { return Promise.resolve(fulfillment); } beforeEventUpdate(fulfillment, options) { return Promise.resolve(fulfillment); } afterEventCreate(fulfillment, options) { return Promise.resolve(fulfillment); } afterEventUpdate(fulfillment, options) { return Promise.resolve(fulfillment); } } exports.FulfillmentService = FulfillmentService;