@fabrix/spool-cart
Version:
Spool - eCommerce Spool for Fabrix
358 lines (357 loc) • 11.8 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 enums_1 = require("../../enums");
class ShopResolver 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(shop, options = {}) {
return Promise.resolve(shop);
}
resolveById(shop, options = {}) {
return this.findById(shop.id, options)
.then(resShop => {
if (!resShop && options.reject !== false) {
throw new errors_1.ModelError('E_NOT_FOUND', `Shop ${shop.id} not found`);
}
return resShop;
});
}
resolveByToken(shop, options = {}) {
return this.findOne(this.app.services.SequelizeService.mergeOptionDefaults(options, {
where: {
token: shop.token
}
}))
.then(resShop => {
if (!resShop && options.reject !== false) {
throw new errors_1.ModelError('E_NOT_FOUND', `Shop token ${shop.token} not found`);
}
return resShop;
});
}
resolveByHandle(shop, options = {}) {
return this.findOne(this.app.services.SequelizeService.mergeOptionDefaults(options, {
where: {
handle: shop.handle
}
}))
.then(resShop => {
if (!resShop && options.reject !== false) {
throw new errors_1.ModelError('E_NOT_FOUND', `Shop handle ${shop.handle} not found`);
}
return resShop;
});
}
resolveByNumber(shop, options = {}) {
return this.findById(shop, options)
.then(resShop => {
if (!resShop && options.reject !== false) {
throw new errors_1.ModelError('E_NOT_FOUND', `Shop ${shop.token} not found`);
}
return resShop;
});
}
resolveByString(shop, options = {}) {
return this.findOne(this.app.services.SequelizeService.mergeOptionDefaults(options, {
where: {
code: shop
}
}))
.then(resShop => {
if (!resShop && options.reject !== false) {
throw new errors_1.ModelError('E_NOT_FOUND', `Shop ${shop} not found`);
}
return resShop;
});
}
resolveDefault(options = {}) {
return this.findOne({
transaction: options.transaction || null
})
.then(resShop => {
if (!resShop && options.reject !== false) {
throw new errors_1.ModelError('E_NOT_FOUND', 'Shop not found');
}
return resShop;
});
}
resolve(shop, options = {}) {
const resolvers = {
'instance': shop instanceof this.instance,
'id': !!(shop && lodash_1.isObject(shop) && shop.id),
'token': !!(shop && lodash_1.isObject(shop) && shop.token),
'handle': !!(shop && lodash_1.isObject(shop) && shop.handle),
'number': !!(shop && lodash_1.isNumber(shop)),
'string': !!(shop && lodash_1.isString(shop)),
'default': options.default === true
};
const type = Object.keys(resolvers).find((key) => resolvers[key]);
switch (type) {
case 'instance': {
return this.resolveByInstance(shop, options);
}
case 'id': {
return this.resolveById(shop, options);
}
case 'token': {
return this.resolveByToken(shop, options);
}
case 'handle': {
return this.resolveByHandle(shop, options);
}
case 'number': {
return this.resolveByNumber(shop, options);
}
case 'string': {
return this.resolveByString(shop, options);
}
case 'default': {
return this.resolveDefault(options);
}
default: {
const err = new Error(`Unable to resolve Shop ${shop}`);
return Promise.reject(err);
}
}
}
transformShops(shops = [], options = {}) {
const ShopModel = this;
const Sequelize = ShopModel.sequelize;
shops = shops.map(shop => {
if (shop && lodash_1.isNumber(shop)) {
return { id: shop };
}
else if (shop && lodash_1.isString(shop)) {
shop = { name: shop };
return shop;
}
else if (shop && lodash_1.isObject(shop)) {
return shop;
}
});
shops = shops.filter(shop => shop);
return Sequelize.Promise.mapSeries(shops, shop => {
return ShopModel.findOne({
where: lodash_1.pick(shop, ['id', 'handle']),
attributes: ['id', 'name', 'handle'],
transaction: options.transaction || null
})
.then(foundShop => {
if (foundShop) {
return lodash_1.extend(foundShop, shop);
}
else {
return ShopModel.create(shop, {
transaction: options.transaction || null
});
}
});
});
}
}
exports.ShopResolver = ShopResolver;
class Shop extends common_1.FabrixModel {
static get resolver() {
return ShopResolver;
}
static config(app, Sequelize) {
return {
options: {
underscored: true,
enums: {
UNITS: enums_1.UNITS
},
scopes: {
live: {
where: {
live_mode: true
}
}
},
hooks: {
beforeValidate: [
(shop, options) => {
if (!shop.handle && shop.name) {
shop.handle = shop.name;
}
}
]
}
}
};
}
static schema(app, Sequelize) {
return {
name: {
type: Sequelize.STRING,
allowNull: false
},
handle: {
type: Sequelize.STRING,
allowNull: false,
unique: true,
set: function (val) {
this.setDataValue('handle', app.services.ProxyCartService.handle(val));
}
},
phone: {
type: Sequelize.STRING
},
primary_locale: {
type: Sequelize.STRING,
defaultValue: 'en-us',
allowNull: false
},
address_id: {
type: Sequelize.INTEGER
},
currency: {
type: Sequelize.STRING,
defaultValue: 'USD',
allowNull: false
},
host: {
type: Sequelize.STRING,
allowNull: false
},
email: {
type: Sequelize.STRING,
validate: {
isEmail: true
}
},
money_format: {
type: Sequelize.STRING,
defaultValue: '$',
allowNull: false
},
money_with_currency_format: {
type: Sequelize.STRING,
defaultValue: '$ USD',
allowNull: false
},
tax_shipping: {
type: Sequelize.BOOLEAN,
defaultValue: false
},
taxes_included: {
type: Sequelize.BOOLEAN,
defaultValue: false
},
county_taxes: {
type: Sequelize.BOOLEAN
},
timezone: {
type: Sequelize.STRING,
defaultValue: '(GMT-05:00) Eastern Time',
allowNull: false
},
iana_timezone: {
type: Sequelize.STRING,
defaultValue: 'America/New_York',
allowNull: false
},
weight_unit: {
type: Sequelize.ENUM,
values: Object.values(enums_1.UNITS),
defaultValue: enums_1.UNITS.G
},
live_mode: {
type: Sequelize.BOOLEAN,
defaultValue: app.config.get('cart.live_mode')
}
};
}
static associate(models) {
models.Shop.belongsTo(models.Address, {
as: 'address'
});
models.Shop.belongsToMany(models.Address, {
as: 'addresses',
foreignKey: 'model_id',
through: {
model: models.ItemAddress,
scope: {
model: 'shop'
},
constraints: false
},
constraints: false
});
models.Shop.hasMany(models.Cart, {
as: 'carts',
foreignKey: 'shop_id'
});
models.Shop.belongsToMany(models.Order, {
as: 'orders',
through: {
model: models.ShopOrder,
unique: true,
},
foreignKey: 'shop_id'
});
models.Shop.hasMany(models.OrderItem, {
as: 'order_items',
foreignKey: 'shop_id'
});
models.Shop.belongsToMany(models.Product, {
as: 'products',
through: {
model: models.ShopProduct,
foreignKey: 'shop_id',
unique: false,
},
});
models.Shop.belongsToMany(models.ProductVariant, {
as: 'variants',
through: {
model: models.ShopProduct,
foreignKey: 'shop_id',
unique: false,
},
});
models.Shop.belongsToMany(models.User, {
as: 'users',
through: {
model: models.ShopUser,
unique: true,
},
foreignKey: 'shop_id'
});
models.Shop.belongsToMany(models.Customer, {
as: 'customers',
through: {
model: models.ShopCustomer,
unique: true,
},
foreignKey: 'shop_id'
});
}
}
exports.Shop = Shop;