UNPKG

@fabrix/spool-cart

Version:

Spool - eCommerce Spool for Fabrix

549 lines (548 loc) 20.4 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 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; }); } };