@fabrix/spool-cart
Version:
Spool - eCommerce Spool for Fabrix
549 lines (548 loc) • 20.4 kB
JavaScript
"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 queryDefaults_1 = require("../utils/queryDefaults");
const enums_1 = require("../../enums");
const enums_2 = require("../../enums");
const enums_3 = require("../../enums");
const enums_4 = require("../../enums");
const enums_5 = require("../../enums");
const enums_6 = require("../../enums");
class CollectionResolver extends spool_sequelize_1.SequelizeResolver {
findByIdDefault(id, options = {}) {
options = this.app.services.SequelizeService.mergeOptionDefaults(queryDefaults_1.Collection.default(this.app), options);
return this.findById(id, options);
}
findByHandleDefault(handle, options = {}) {
options = this.app.services.SequelizeService.mergeOptionDefaults(queryDefaults_1.Collection.default(this.app), {
where: {
handle: handle
}
}, options);
return this.findOne(options);
}
findOneDefault(options = {}) {
options = this.app.services.SequelizeService.mergeOptionDefaults(queryDefaults_1.Collection.default(this.app), options);
return this.findOne(options);
}
findAllDefault(options = {}) {
options = this.app.services.SequelizeService.mergeOptionDefaults(queryDefaults_1.Collection.default(this.app), options);
return this.findAll(options);
}
findAndCountDefault(options = {}) {
options = this.app.services.SequelizeService.mergeOptionDefaults(queryDefaults_1.Collection.findAndCountDefault(this.app), options);
return this.findAndCountAll(options);
}
resolveByInstance(collection, options = {}) {
return Promise.resolve(collection);
}
resolveById(collection, options = {}) {
return this.findById(collection.id, options)
.then(resUser => {
if (!resUser && options.reject !== false) {
throw new errors_1.ModelError('E_NOT_FOUND', `Collection ${collection.id} not found`);
}
return resUser;
});
}
resolveByHandle(collection, options = {}) {
return this.findOne(lodash_1.defaultsDeep({
where: {
handle: collection.handle
}
}, options))
.then(resUser => {
if (!resUser && options.reject !== false) {
throw new errors_1.ModelError('E_NOT_FOUND', `Collection handle ${collection.handle} not found`);
}
return resUser;
});
}
resolveByNumber(collection, options = {}) {
return this.findById(collection, options)
.then(resUser => {
if (!resUser && options.reject !== false) {
throw new errors_1.ModelError('E_NOT_FOUND', `Collection ${collection.token} not found`);
}
return resUser;
});
}
resolveByString(collection, options = {}) {
return this.findOne(lodash_1.defaultsDeep({
where: {
handle: collection
}
}, options))
.then(resUser => {
if (!resUser && options.reject !== false) {
throw new errors_1.ModelError('E_NOT_FOUND', `Collection ${collection} not found`);
}
return resUser;
});
}
resolve(collection, options = {}) {
const resolvers = {
'instance': collection instanceof this.instance,
'id': !!(collection && lodash_1.isObject(collection) && collection.id),
'handle': !!(collection && lodash_1.isObject(collection) && collection.handle),
'number': !!(collection && lodash_1.isNumber(collection)),
'string': !!(collection && lodash_1.isString(collection))
};
const type = Object.keys(resolvers).find((key) => resolvers[key]);
switch (type) {
case 'instance': {
return this.resolveByInstance(collection, options);
}
case 'id': {
return this.resolveById(collection, options);
}
case 'handle': {
return this.resolveByHandle(collection, options);
}
case 'number': {
return this.resolveByNumber(collection, options);
}
case 'string': {
return this.resolveByString(collection, options);
}
default: {
const err = new Error(`Unable to resolve Collection ${collection}`);
return Promise.reject(err);
}
}
}
resolveOrCreate(collection, options = {}) {
options.reject = false;
return this.resolve(collection, options)
.then(_collection => {
if (!_collection) {
if (lodash_1.isString(collection)) {
collection = {
handle: this.app.services.ProxyCartService.handle(collection),
title: collection
};
}
if (!collection.title && collection.handle) {
collection.title = collection.handle;
}
if (!collection.handle && collection.title) {
collection.handle = this.app.services.ProxyCartService.handle(collection.title);
}
return this.create(collection, { transaction: options.transaction || null })
.then(_createdCollection => {
return [_createdCollection, true];
});
}
else if (_collection.isNewRecord && !_collection.id) {
return this.findOrCreate({
where: {
handle: _collection.handle
},
transaction: options.transaction || null,
defaults: _collection.get({ plain: true })
})
.then(_resCollection => {
return _resCollection;
});
}
else {
return [_collection, false];
}
});
}
transformCollections(collections = [], options = {}) {
const CollectionModel = this;
const Sequelize = CollectionModel.sequelize;
collections = collections.map(collection => {
if (collection && lodash_1.isNumber(collection)) {
return { id: collection };
}
else if (collection && lodash_1.isString(collection)) {
return {
handle: this.app.services.ProxyCartService.handle(collection),
title: collection
};
}
else if (collection && lodash_1.isObject(collection) && (collection.title || collection.handle)) {
collection.handle = this.app.services.ProxyCartService.handle(collection.handle)
|| this.app.services.ProxyCartService.handle(collection.title);
return collection;
}
});
collections = collections.filter(collection => collection);
return Sequelize.Promise.mapSeries(collections, collection => {
return CollectionModel.findOne({
where: lodash_1.pick(collection, ['id', 'handle']),
attributes: ['id', 'handle', 'title'],
transaction: options.transaction || null
})
.then(foundCollectionModel => {
if (foundCollectionModel) {
return lodash_1.extend(foundCollectionModel, collection);
}
else {
return this.app.services.CollectionService.create(collection, {
transaction: options.transaction || null
})
.then(createdCollectionModel => {
return lodash_1.extend(createdCollectionModel, collection);
});
}
});
});
}
reverseTransformCollections(collections) {
collections = collections || [];
collections.map(collection => {
if (collection && lodash_1.isString(collection)) {
return collection;
}
else if (collection && collection.title) {
return collection.title;
}
});
return collections;
}
}
exports.CollectionResolver = CollectionResolver;
class Collection extends common_1.FabrixModel {
static get resolver() {
return CollectionResolver;
}
static config(app, Sequelize) {
return {
options: {
underscored: true,
enums: {
COLLECTION_SORT_ORDER: enums_1.COLLECTION_SORT_ORDER,
COLLECTION_PURPOSE: enums_2.COLLECTION_PURPOSE,
COLLECTION_DISCOUNT_SCOPE: enums_3.COLLECTION_DISCOUNT_SCOPE,
COLLECTION_DISCOUNT_TYPE: enums_4.COLLECTION_DISCOUNT_TYPE,
COLLECTION_TAX_TYPE: enums_5.COLLECTION_TAX_TYPE,
},
scopes: {
live: {
where: {
live_mode: true
}
}
},
hooks: {
beforeValidate: [
(collection, options) => {
if (!collection.handle && collection.title) {
collection.handle = collection.title;
}
}
],
beforeCreate: [
(collection, options) => {
if (collection.body) {
const bodyDoc = app.services.RenderGenericService.renderSync(collection.body);
collection.body_html = bodyDoc.document;
}
if (collection.excerpt) {
const excerptDoc = app.services.RenderGenericService.renderSync(collection.excerpt);
collection.excerpt_html = excerptDoc.document;
}
}
],
beforeUpdate: [
(collection, options) => {
if (collection.body) {
const bodyDoc = app.services.RenderGenericService.renderSync(collection.body);
collection.body_html = bodyDoc.document;
}
if (collection.excerpt) {
const excerptDoc = app.services.RenderGenericService.renderSync(collection.excerpt);
collection.excerpt_html = excerptDoc.document;
}
}
]
}
}
};
}
static schema(app, Sequelize) {
return {
handle: {
type: Sequelize.STRING,
allowNull: false,
unique: true,
set: function (val) {
this.setDataValue('handle', app.services.ProxyCartService.splitHandle(val) || null);
}
},
title: {
type: Sequelize.STRING,
allowNull: false,
set: function (val) {
this.setDataValue('title', app.services.ProxyCartService.title(val));
}
},
seo_title: {
type: Sequelize.STRING,
set: function (val) {
this.setDataValue('seo_title', app.services.ProxyCartService.title(val));
}
},
seo_description: {
type: Sequelize.TEXT,
set: function (val) {
this.setDataValue('seo_description', app.services.ProxyCartService.description(val));
}
},
primary_purpose: {
type: Sequelize.ENUM,
values: lodash_1.values(enums_2.COLLECTION_PURPOSE),
defaultValue: enums_2.COLLECTION_PURPOSE.GROUP
},
shop_id: {
type: Sequelize.INTEGER
},
description: {
type: Sequelize.TEXT
},
excerpt: {
type: Sequelize.TEXT
},
excerpt_html: {
type: Sequelize.TEXT
},
body: {
type: Sequelize.TEXT
},
body_html: {
type: Sequelize.TEXT
},
published: {
type: Sequelize.BOOLEAN,
defaultValue: true
},
published_at: {
type: Sequelize.DATE,
defaultValue: Sequelize.NOW
},
published_scope: {
type: Sequelize.STRING,
defaultValue: 'global'
},
unpublished_at: {
type: Sequelize.DATE
},
position: {
type: Sequelize.INTEGER,
defaultValue: 0
},
sort_order: {
type: Sequelize.ENUM,
values: lodash_1.values(enums_1.COLLECTION_SORT_ORDER),
defaultValue: enums_1.COLLECTION_SORT_ORDER.ALPHA_DESC
},
tax_type: {
type: Sequelize.ENUM,
values: lodash_1.values(enums_5.COLLECTION_TAX_TYPE),
defaultValue: enums_5.COLLECTION_TAX_TYPE.PERCENTAGE
},
tax_rate: {
type: Sequelize.FLOAT,
defaultValue: 0.0
},
tax_percentage: {
type: Sequelize.FLOAT,
defaultValue: 0.0
},
tax_name: {
type: Sequelize.STRING
},
shipping_type: {
type: Sequelize.ENUM,
values: lodash_1.values(enums_6.COLLECTION_SHIPPING_TYPE),
defaultValue: enums_6.COLLECTION_SHIPPING_TYPE.PERCENTAGE
},
shipping_rate: {
type: Sequelize.FLOAT,
defaultValue: 0.0
},
shipping_percentage: {
type: Sequelize.FLOAT,
defaultValue: 0.0
},
shipping_name: {
type: Sequelize.STRING
},
shipping_product_exclude: {
type: Sequelize.JSONB,
defaultValue: []
},
tax_product_exclude: {
type: Sequelize.JSONB,
defaultValue: []
},
live_mode: {
type: Sequelize.BOOLEAN,
defaultValue: app.config.get('cart.live_mode')
}
};
}
static associate(models) {
models.Collection.belongsToMany(models.Product, {
as: 'products',
through: {
model: models.ItemCollection,
unique: false,
scope: {
model: 'product'
},
constraints: false
},
foreignKey: 'collection_id',
otherKey: 'model_id',
constraints: false
});
models.Collection.belongsToMany(models.Collection, {
as: 'collections',
through: {
model: models.ItemCollection,
unique: false,
scope: {
model: 'collection'
},
constraints: false
},
foreignKey: 'collection_id',
otherKey: 'model_id',
constraints: false
});
models.Collection.belongsToMany(models.Customer, {
as: 'customers',
through: {
model: models.ItemCollection,
unique: false,
scope: {
model: 'customer'
},
constraints: false
},
foreignKey: 'collection_id',
otherKey: 'model_id',
constraints: false
});
models.Collection.belongsToMany(models.Discount, {
as: 'discounts',
through: {
model: models.ItemDiscount,
unique: false,
scope: {
model: 'collection'
}
},
foreignKey: 'model_id',
constraints: false
});
models.Collection.belongsToMany(models.Image, {
as: 'images',
through: {
model: models.ItemImage,
unique: false,
scope: {
model: 'collection'
},
constraints: false
},
foreignKey: 'model_id',
constraints: false
});
models.Collection.hasOne(models.Metadata, {
as: 'metadata',
foreignKey: 'collection_id'
});
models.Collection.belongsToMany(models.Tag, {
as: 'tags',
through: {
model: models.ItemTag,
unique: false,
scope: {
model: 'collection'
}
},
foreignKey: 'model_id',
otherKey: 'tag_id',
constraints: false
});
}
}
exports.Collection = Collection;
Collection.prototype.toJSON = function () {
const resp = this instanceof this.app.models['Collection'].instance ? this.get({ plain: true }) : this;
if (resp.tags) {
resp.tags = resp.tags.map(tag => {
if (tag && lodash_1.isString(tag)) {
return tag;
}
else if (tag && tag.name && tag.name !== '') {
return tag.name;
}
});
}
if (resp.metadata) {
if (typeof resp.metadata.data !== 'undefined') {
resp.metadata = resp.metadata.data;
}
}
return resp;
};
Collection.prototype.resolveMetadata = function (options = {}) {
if (this.metadata
&& this.metadata instanceof this.app.models['Metadata'].instance
&& options.reload !== true) {
return Promise.resolve(this);
}
else {
return this.getMetadata({ transaction: options.transaction || null })
.then(_metadata => {
_metadata = _metadata || { collection_id: this.id };
this.metadata = _metadata;
this.setDataValue('metadata', _metadata);
this.set('metadata', _metadata);
return this;
});
}
};
Collection.prototype.resolveDiscounts = function (options = {}) {
if (this.discounts
&& this.discount.every(d => d instanceof this.app.models['Discount'].instance)
&& options.reload !== true) {
return Promise.resolve(this);
}
else {
return this.getDiscounts({ transaction: options.transaction || null })
.then(_discounts => {
_discounts = _discounts || [];
this.discounts = _discounts;
this.setDataValue('discounts', _discounts);
this.set('discounts', _discounts);
return this;
});
}
};
Collection.prototype.resolveProducts = function (options = {}) {
if (this.products
&& this.product.every(p => p instanceof this.app.models['Product'].instance)
&& options.reload !== true) {
return Promise.resolve(this);
}
else {
return this.getProducts(options)
.then(_products => {
_products = _products || [];
this.products = _products;
this.setDataValue('products', _products);
this.set('products', _products);
return this;
});
}
};