@fabrix/spool-cart
Version:
Spool - eCommerce Spool for Fabrix
402 lines (401 loc) • 17.4 kB
JavaScript
"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;