@fabrix/spool-cart
Version:
Spool - eCommerce Spool for Fabrix
1,175 lines (1,174 loc) • 45.4 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const common_1 = require("@fabrix/fabrix/dist/common");
const _ = require("lodash");
const errors_1 = require("@fabrix/spool-sequelize/dist/errors");
const enums_1 = require("../../enums");
class CustomerService 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();
}
create(customer, options) {
options = options || {};
const Account = this.app.models['Account'];
const Address = this.app.models['Address'];
const Cart = this.app.models['Cart'];
const Customer = this.app.models['Customer'];
const Metadata = this.app.models['Metadata'];
const Tag = this.app.models['Tag'];
const User = this.app.models['User'];
if (customer.cart) {
customer.default_cart = customer.cart;
delete customer.cart;
}
if (!customer.default_address && customer.shipping_address) {
customer.default_address = customer.shipping_address;
}
if (!customer.shipping_address && customer.default_address) {
customer.shipping_address = customer.default_address;
}
if (!customer.billing_address && customer.default_address) {
customer.billing_address = customer.default_address;
}
let resCustomer;
return Customer.create({
first_name: customer.first_name,
last_name: customer.last_name,
email: customer.email,
phone: customer.phone,
company: customer.company,
note: customer.note,
accepts_marketing: customer.accepts_marketing,
state: customer.state,
tax_exempt: customer.tax_exempt,
verified_email: customer.verified_email,
metadata: Metadata.transform(customer.metadata || {}),
account_balance: customer.account_balance,
type: customer.type
}, {
include: [
{
model: Address.instance,
as: 'shipping_address'
},
{
model: Address.instance,
as: 'billing_address'
},
{
model: Address.instance,
as: 'default_address'
},
{
model: Cart.instance,
as: 'default_cart'
},
{
model: Tag.instance,
as: 'tags'
},
{
model: Metadata.instance,
as: 'metadata'
},
],
transaction: options.transaction || null
})
.then(_customer => {
if (!_customer) {
throw new Error('Customer could not be created');
}
resCustomer = _customer;
if (customer.shipping_address && !_.isEmpty(customer.shipping_address)) {
return resCustomer.updateShippingAddress(customer.shipping_address, { transaction: options.transaction || null });
}
return;
})
.then(() => {
if (customer.billing_address && !_.isEmpty(customer.billing_address)) {
return resCustomer.updateBillingAddress(customer.billing_address, { transaction: options.transaction || null });
}
return;
})
.then(() => {
if (customer.default_address && !_.isEmpty(customer.default_address)) {
return resCustomer.updateDefaultAddress(customer.default_address, { transaction: options.transaction || null });
}
return;
})
.then(() => {
if (customer.tags && customer.tags.length > 0) {
customer.tags = _.sortedUniq(customer.tags.filter(n => n));
return Tag.transformTags(customer.tags, { transaction: options.transaction || null });
}
return;
})
.then(tags => {
if (tags && tags.length > 0) {
return resCustomer.setTags(tags.map(tag => tag.id), { transaction: options.transaction || null });
}
return;
})
.then(tags => {
if (customer.default_cart) {
return Cart.resolve(customer.default_cart, { transaction: options.transaction || null });
}
return;
})
.then(cart => {
if (cart) {
return resCustomer.setDefault_cart(cart.id, { transaction: options.transaction || null });
}
})
.then(cart => {
if (customer.accounts && customer.accounts.length > 0) {
return Customer.sequelize.Promise.mapSeries(customer.accounts, account => {
account.customer_id = resCustomer.id;
account.email = resCustomer.email;
return this.app.services.AccountService.findAndCreate(account, {
transaction: options.transaction || null
});
});
}
else {
return this.app.services.PaymentGenericService.createCustomer(resCustomer)
.then(serviceCustomer => {
let resAccount;
return Account.create({
customer_id: resCustomer.id,
email: resCustomer.email,
is_default: true,
gateway: serviceCustomer.gateway,
foreign_id: serviceCustomer.foreign_id,
foreign_key: serviceCustomer.foreign_key,
data: serviceCustomer.data
}, {
transaction: options.transaction || null
})
.then(account => {
if (!account) {
throw new Error('Account was not created');
}
resAccount = account;
const event = {
object_id: account.customer_id,
object: 'customer',
objects: [{
customer: account.customer_id
}, {
account: account.id
}],
type: 'customer.account.created',
message: `Customer account ${account.foreign_id} created on ${account.gateway}`,
data: account
};
return this.publish(event.type, event, {
save: true,
transaction: options.transaction || null
});
})
.then(event => {
return [resAccount];
});
});
}
})
.then(accounts => {
if (accounts && accounts.length > 0) {
return resCustomer.setAccounts(accounts.map(account => account.id), {
transaction: options.transaction || null
});
}
return;
})
.then(accounts => {
if (customer.users && customer.users.length > 0) {
return Customer.sequelize.Promise.mapSeries(customer.users, user => {
user.current_customer_id = resCustomer.id;
if (user instanceof User.instance) {
return user.save({ transaction: options.transaction || null });
}
user.passports = {
protocol: 'local'
};
return User.create(user, {
include: [
{
model: this.app.models['Passport'].instance,
as: 'passports'
}
],
transaction: options.transaction || null
});
});
}
return [];
})
.then(users => {
if (users && users.length > 0) {
return resCustomer.setUsers(users.map(user => user.id), {
transaction: options.transaction || null
});
}
return [];
})
.then(users => {
const event = {
object_id: resCustomer.id,
object: 'customer',
objects: [{
customer: resCustomer.id
}],
type: 'customer.created',
message: `Customer ${resCustomer.getSalutation()} created`,
data: resCustomer
};
return this.publish(event.type, event, {
save: true,
transaction: options.transaction || null
});
})
.then(event => {
return Customer.findByIdDefault(resCustomer.id, { transaction: options.transaction || null });
});
}
update(customer, options) {
options = options || {};
const Customer = this.app.models['Customer'];
const Tag = this.app.models['Tag'];
if (!customer.id) {
const err = new errors_1.ModelError('E_NOT_FOUND', 'Customer is missing id');
return Promise.reject(err);
}
let resCustomer;
return Customer.findByIdDefault(customer.id, options)
.then(_customer => {
if (!_customer) {
throw new errors_1.ModelError('E_NOT_FOUND', 'Customer not found');
}
resCustomer = _customer;
const update = _.omit(customer, ['tags', 'metadata', 'shipping_address', 'billing_address', 'default_address']);
return resCustomer.update(update);
})
.then(updatedCustomer => {
if (customer.tags && customer.tags.length > 0) {
customer.tags = _.sortedUniq(customer.tags.filter(n => n));
return Tag.transformTags(customer.tags, { transaction: options.transaction || null });
}
return;
})
.then(tags => {
if (tags && tags.length > 0) {
return resCustomer.setTags(tags.map(tag => tag.id), { transaction: options.transaction || null });
}
return;
})
.then(() => {
if (customer.metadata) {
resCustomer.metadata.data = customer.metadata || {};
return resCustomer.metadata.save({ transaction: options.transaction || null });
}
return;
})
.then(() => {
if (customer.shipping_address) {
return resCustomer.updateShippingAddress(customer.shipping_address, { transaction: options.transaction || null });
}
return;
})
.then(() => {
if (customer.billing_address) {
return resCustomer.updateBillingAddress(customer.billing_address, { transaction: options.transaction || null });
}
return;
})
.then(() => {
if (customer.default_address) {
return resCustomer.updateDefaultAddress(customer.default_address, { transaction: options.transaction || null });
}
return;
})
.then(defaultAddress => {
const event = {
object_id: resCustomer.id,
object: 'customer',
objects: [{
customer: resCustomer.id
}],
type: 'customer.updated',
message: `Customer ${resCustomer.getSalutation()} updated`,
data: resCustomer
};
return this.publish(event.type, event, {
save: true,
transaction: options.transaction || null
});
})
.then(event => {
return Customer.findByIdDefault(resCustomer.id, { transaction: options.transaction || null });
});
}
accountBalance(customer, options = {}) {
const Customer = this.app.models.Customer;
let price = 0;
let type = 'credit';
if (!customer.id) {
const err = new errors_1.ModelError('E_NOT_FOUND', 'Customer is missing id');
return Promise.reject(err);
}
let resCustomer;
return Customer.resolve(customer, {
transaction: options.transaction || null,
create: false
})
.then(_customer => {
if (!_customer) {
throw new errors_1.ModelError('E_NOT_FOUND', 'Customer was not found');
}
if (!(_customer instanceof Customer.instance)) {
throw new Error('Did not resolve instance of Customer');
}
resCustomer = _customer;
if (resCustomer.account_balance > customer.account_balance) {
type = 'debit';
price = Math.max(0, resCustomer.account_balance - customer.account_balance);
}
else {
type = 'credit';
price = Math.max(0, customer.account_balance - resCustomer.account_balance);
}
return resCustomer.logAccountBalance(type, price, null, null, null, { transaction: options.transaction || null });
})
.then(() => {
return resCustomer.save({ transaction: options.transaction || null });
})
.then(event => {
return Customer.findByIdDefault(resCustomer.id, { transaction: options.transaction || null });
});
}
addCart(customer, cart) {
const Customer = this.app.models.Customer;
const customerId = _.isObject(customer) ? customer.id : customer;
const cartId = _.isObject(cart) ? cart.id : cart;
if (!customerId || !cartId) {
const err = new Error(`Can not Associate ${customerId} with ${cartId} because it is invalid`);
return Promise.reject(err);
}
let resCustomer;
return Customer.findById(customerId)
.then(_customer => {
if (!_customer) {
throw new errors_1.ModelError('E_NOT_FOUND', 'Customer not found');
}
resCustomer = _customer;
return resCustomer.hasCart(cartId);
})
.then(hasCart => {
if (!hasCart) {
return resCustomer.addCart(cartId);
}
return;
})
.then(() => {
return resCustomer;
});
}
removeCart(customer, cart) {
const Customer = this.app.models.Customer;
const customerId = _.isObject(customer) ? customer.id : customer;
const cartId = _.isObject(cart) ? cart.id : cart;
let resCustomer;
return Customer.findById(customerId)
.then(_customer => {
if (!_customer) {
throw new errors_1.ModelError('E_NOT_FOUND', 'Customer not found');
}
resCustomer = _customer;
return resCustomer.hasCart(cartId);
})
.then(hasCart => {
if (hasCart) {
return resCustomer.removeCart(cartId);
}
return;
})
.then(() => {
return resCustomer;
});
}
setDefaultCartForCustomer(customer, cart) {
const Customer = this.app.models.Customer;
const customerId = _.isObject(customer) ? customer.id : customer;
const cartId = _.isObject(cart) ? cart.id : cart;
if (!customerId || !cartId) {
const err = new Error(`Can not Associate ${customerId} with ${cartId} because it is invalid`);
return Promise.reject(err);
}
return Customer.findById(customerId)
.then(_customer => {
return _customer.setDefault_cart(cartId);
})
.then(updatedCustomer => {
return updatedCustomer;
});
}
addTag(customer, tag) {
const Customer = this.app.models['Customer'];
const Tag = this.app.models['Tag'];
let resCustomer, resTag;
return Customer.resolve(customer, { create: false })
.then(_customer => {
if (!_customer) {
throw new errors_1.ModelError('E_NOT_FOUND', 'Customer not found');
}
resCustomer = _customer;
return Tag.resolve(tag);
})
.then(_tag => {
if (!_tag) {
throw new errors_1.ModelError('E_NOT_FOUND', 'Customer not found');
}
resTag = _tag;
return resCustomer.hasTag(resTag.id);
})
.then(hasTag => {
if (!hasTag) {
return resCustomer.addTag(resTag.id);
}
return resCustomer;
})
.then(_tag => {
return Customer.findByIdDefault(resCustomer.id);
});
}
removeTag(customer, tag) {
const Customer = this.app.models['Customer'];
const Tag = this.app.models['Tag'];
let resCustomer, resTag;
return Customer.resolve(customer, { create: false })
.then(_customer => {
if (!_customer) {
throw new errors_1.ModelError('E_NOT_FOUND', 'Customer not found');
}
resCustomer = _customer;
return Tag.resolve(tag);
})
.then(_tag => {
if (!_tag) {
throw new errors_1.ModelError('E_NOT_FOUND', 'Customer not found');
}
resTag = _tag;
return resCustomer.hasTag(resTag.id);
})
.then(hasTag => {
if (hasTag) {
return resCustomer.removeTag(resTag.id);
}
return resCustomer;
})
.then(_tag => {
return Customer.findByIdDefault(resCustomer.id);
});
}
addCollections(customer, collections, options) {
options = options || {};
if (!Array.isArray(collections)) {
collections = [collections];
}
const Sequelize = this.app.models['Customer'].sequelize;
return Sequelize.transaction(t => {
return Sequelize.Promise.mapSeries(collections, collection => {
return this.addCollection(customer, collection, {
transaction: t
});
});
});
}
addCollection(customer, collection, options = {}) {
const Customer = this.app.models['Customer'];
const Collection = this.app.models['Collection'];
let resCustomer, resCollection;
return Customer.resolve(customer, { create: false })
.then(_customer => {
if (!_customer) {
throw new errors_1.ModelError('E_NOT_FOUND', 'Customer not found');
}
resCustomer = _customer;
return Collection.resolve(collection, {
transaction: options.transaction || null,
reject: true
});
})
.then(_collection => {
if (!_collection) {
throw new errors_1.ModelError('E_NOT_FOUND', 'Customer not found');
}
resCollection = _collection;
return resCustomer.hasCollection(resCollection.id);
})
.then(hasCollection => {
if (!hasCollection) {
return resCustomer.addCollection(resCollection.id);
}
return resCustomer;
})
.then(_collection => {
return resCollection;
});
}
removeCollection(customer, collection, options = {}) {
const Customer = this.app.models['Customer'];
const Collection = this.app.models['Collection'];
let resCustomer, resCollection;
return Customer.resolve(customer, {
transaction: options.transaction || null,
create: false
})
.then(_customer => {
if (!_customer) {
throw new errors_1.ModelError('E_NOT_FOUND', 'Customer not found');
}
resCustomer = _customer;
return Collection.resolve(collection, {
transaction: options.transaction || null,
reject: true
});
})
.then(_collection => {
if (!_collection) {
throw new errors_1.ModelError('E_NOT_FOUND', 'Customer not found');
}
resCollection = _collection;
return resCustomer.hasCollection(resCollection.id);
})
.then(hasCollection => {
if (hasCollection) {
return resCustomer.removeCollection(resCollection.id);
}
return resCustomer;
})
.then(_collection => {
return resCollection;
});
}
addAddress(customer, address, type, options = {}) {
const Customer = this.app.models['Customer'];
const Address = this.app.models['Address'];
let resCustomer;
return Customer.resolve(customer, {
transaction: options.transaction || null,
create: false
})
.then(_customer => {
if (!_customer) {
throw new Error('Unable to resolve Customer');
}
resCustomer = _customer;
if (type === 'shipping') {
return resCustomer.updateShippingAddress(address, { transaction: options.transaction || null })
.then(update => {
return update.shipping_address;
});
}
return address;
})
.then(shippingAddress => {
if (type === 'billing') {
return resCustomer.updateBillingAddress(shippingAddress, { transaction: options.transaction || null })
.then(update => {
return update.billing_address;
});
}
return shippingAddress;
})
.then(billingAddress => {
if (type === 'default') {
return resCustomer.updateDefaultAddress(billingAddress, { transaction: options.transaction || null })
.then(update => {
return update.default_address;
});
}
return billingAddress;
})
.then(defaultAddress => {
if (!type) {
if (defaultAddress.id || defaultAddress.token) {
return Address.resolve(defaultAddress, { transaction: options.transaction || null })
.then(foundAddress => {
return resCustomer.addAddress(foundAddress.id, { transaction: options.transaction || null })
.then(() => {
return foundAddress;
});
});
}
else {
return resCustomer.createAddress(defaultAddress, { transaction: options.transaction || null });
}
}
return defaultAddress;
})
.then(resAddress => {
return resAddress;
});
}
addCustomers(customer, customers, options = {}) {
if (!Array.isArray(customers)) {
customers = [customers];
}
const Sequelize = this.app.models['Customer'].sequelize;
return Sequelize.transaction(t => {
return Sequelize.Promise.mapSeries(customers, subcustomer => {
return this.addCustomer(customer, subcustomer, {
transaction: t
});
});
});
}
addCustomer(customer, subcustomer, options = {}) {
const Customer = this.app.models['Customer'];
let resCustomer, resSubcustomer;
return Customer.resolve(customer, { transaction: options.transaction || null })
.then(_customer => {
if (!_customer) {
throw new Error('Customer Could Not Be Resolved');
}
resCustomer = _customer;
return Customer.resolve(subcustomer, { transaction: options.transaction || null });
})
.then(_customer => {
if (!_customer) {
throw new Error('Customer Could Not Be Resolved');
}
resSubcustomer = _customer;
return this.app.models.ItemCustomer.findOne({
where: {
customer_id: resCustomer.id,
model_id: resSubcustomer.id,
model: 'customer'
},
transaction: options.transaction || null
});
})
.then((hasCustomer = false) => {
if (hasCustomer) {
return;
}
return this.app.models.ItemCustomer.create({
customer_id: resCustomer.id,
model_id: resSubcustomer.id,
model: 'customer'
}, { transaction: options.transaction });
})
.then((added = false) => {
if (added) {
const event = {
object_id: resCustomer.id,
object: 'customer',
objects: [{
customer: resSubcustomer.id,
}],
type: 'customer.customer.added',
message: `Customer ${resSubcustomer.getSalutation()} added to Customer ${resCustomer.getSalutation()}`,
data: {
customer: resCustomer,
subcustomer: resSubcustomer
}
};
return this.publish(event.type, event, {
save: true,
transaction: options.transaction || null
});
}
return;
})
.then(event => {
return resSubcustomer;
});
}
removeCustomers(customer, customers, options = {}) {
if (!Array.isArray(customers)) {
customers = [customers];
}
const Sequelize = this.app.models['Customer'].sequelize;
return Sequelize.transaction(t => {
return Sequelize.Promise.mapSeries(customers, subcustomer => {
return this.removeCustomer(customer, subcustomer, {
transaction: t
});
});
});
}
removeCustomer(customer, subcustomer, options = {}) {
const Customer = this.app.models['Customer'];
let resCustomer, resSubcustomer;
return Customer.resolve(customer, { transaction: options.transaction || null })
.then(_customer => {
if (!_customer) {
throw new Error('Customer Could Not Be Resolved');
}
resCustomer = _customer;
return Customer.resolve(subcustomer, { transaction: options.transaction || null });
})
.then(_customer => {
if (!_customer) {
throw new Error('Customer Could Not Be Resolved');
}
resSubcustomer = _customer;
return this.app.models.ItemCustomer.findOne({
where: {
customer_id: resCustomer.id,
model_id: resSubcustomer.id,
model: 'customer'
},
transaction: options.transaction || null
});
})
.then(hasCustomer => {
if (hasCustomer) {
return this.app.models.ItemCustomer.destroy({
where: {
customer_id: resCustomer.id,
model_id: resSubcustomer.id,
model: 'customer'
},
transaction: options.transaction
});
}
return;
})
.then((removed = false) => {
if (removed) {
const event = {
object_id: resCustomer.id,
object: 'customer',
objects: [{
customer: resSubcustomer.id,
}],
type: 'customer.customer.removed',
message: `Customer ${resSubcustomer.getSalutation()} removed from Customer ${resCustomer.getSalutation()}`,
data: {
customer: resCustomer,
subcustomer: resSubcustomer
}
};
return this.publish(event.type, event, {
save: true,
transaction: options.transaction || null
});
}
return;
})
.then(event => {
return resSubcustomer;
});
}
addUsers(customer, users, options = {}) {
if (!Array.isArray(users)) {
users = [users];
}
const Sequelize = this.app.models['Customer'].sequelize;
return Sequelize.transaction(t => {
return Sequelize.Promise.mapSeries(users, user => {
return this.addUser(customer, user, {
transaction: t
});
});
});
}
addUser(customer, user, options = {}) {
let resCustomer, resUser;
return this.app.models['Customer'].resolve(customer, { transaction: options.transaction || null })
.then(_customer => {
if (!_customer) {
throw new Error('Customer Could Not Be Resolved');
}
resCustomer = _customer;
return this.app.models['User'].resolve(user, { transaction: options.transaction || null });
})
.then(_user => {
if (!_user) {
throw new Error('User Could Not Be Resolved');
}
resUser = _user;
return resCustomer.hasUser(resUser.id, { transaction: options.transaction || null });
})
.then(hasUser => {
if (hasUser) {
return;
}
return resCustomer.addUser(resUser.id, { transaction: options.transaction || null });
})
.then(() => {
return resUser;
});
}
inviteUser(customer, user, options = {}) {
}
inviteUserAccepted(customer, user, options) {
}
removeUser(customer, user, options = {}) {
let resCustomer, resUser;
return this.app.models['Customer'].resolve(customer, { transaction: options.transaction || null })
.then(_customer => {
if (!_customer) {
throw new Error('Customer Could Not Be Resolved');
}
resCustomer = _customer;
return this.app.models['User'].resolve(user, { transaction: options.transaction || null });
})
.then(_user => {
if (!_user) {
throw new Error('User Could Not Be Resolved');
}
resUser = _user;
return resCustomer.hasUser(resUser.id, { transaction: options.transaction || null });
})
.then(hasUser => {
if (hasUser) {
return;
}
return resCustomer.removeUser(resUser.id, { transaction: options.transaction || null });
})
.then(() => {
return resUser;
});
}
updateAddress(customer, address, type, options) {
options = options || {};
const Customer = this.app.models['Customer'];
const Address = this.app.models['Address'];
let resCustomer;
return Customer.resolve(customer, { transaction: options.transaction || null, create: false })
.then(_customer => {
if (!_customer) {
throw new Error('Unable to resolve Customer');
}
resCustomer = _customer;
return Address.resolve(address, { transaction: options.transaction || null });
})
.then(foundAddress => {
if (!foundAddress) {
throw new Error('Address could not resolve');
}
return foundAddress.merge(address).save({ transaction: options.transaction || null });
})
.then(updatedAddress => {
if (type === 'shipping') {
return resCustomer.updateShippingAddress(updatedAddress, { transaction: options.transaction || null })
.then(update => {
return update.shipping_address;
});
}
return updatedAddress;
})
.then(shippingAddress => {
if (type === 'billing') {
return resCustomer.updateBillingAddress(shippingAddress, { transaction: options.transaction || null })
.then(update => {
return update.billing_address;
});
}
return shippingAddress;
})
.then(billingAddress => {
if (type === 'default') {
return resCustomer.updateDefaultAddress(billingAddress, { transaction: options.transaction || null })
.then(update => {
return update.default_address;
});
}
return billingAddress;
})
.then(defaultAddress => {
if (!type) {
if (defaultAddress.id || defaultAddress.token) {
return Address.resolve(defaultAddress, { transaction: options.transaction || null })
.then(foundAddress => {
return resCustomer.addAddress(foundAddress.id, { transaction: options.transaction || null })
.then(() => {
return foundAddress;
});
});
}
else {
return resCustomer.createAddress(defaultAddress, { transaction: options.transaction || null });
}
}
return defaultAddress;
})
.then(resAddress => {
return resAddress;
});
}
removeAddress(customer, address, options) {
options = options || {};
const Customer = this.app.models['Customer'];
const Address = this.app.models['Address'];
let resCustomer, resAddress;
return Customer.resolve(customer, { transaction: options.transaction || null, create: false })
.then(foundCustomer => {
if (!foundCustomer) {
throw new Error('Customer could not resolve');
}
resCustomer = foundCustomer;
return Address.resolve(address, { transaction: options.transaction || null });
})
.then(foundAddress => {
if (!foundAddress) {
throw new Error('Address could not resolve');
}
resAddress = foundAddress;
return resCustomer.removeAddress(resAddress.id, { transaction: options.transaction || null });
})
.then(destroyedAddress => {
return resAddress;
});
}
setAddresses(customer, options) {
options = options || {};
const Customer = this.app.models['Customer'];
let resCustomer;
return Customer.resolve(customer, { transaction: options.transaction || null, create: false })
.then(_customer => {
resCustomer = _customer;
if (resCustomer.shipping_address_id && resCustomer.changed('shipping_address_id')) {
return resCustomer.hasAddress(resCustomer.shipping_address_id, {
address: 'shipping',
transaction: options.transaction || null
});
}
return false;
})
.then(hasShipping => {
if (!hasShipping && resCustomer.shipping_address_id && resCustomer.changed('shipping_address_id')) {
return resCustomer.addAddress(resCustomer.shipping_address_id, {
address: 'shipping',
transaction: options.transaction || null
});
}
return;
})
.then(() => {
if (resCustomer.billing_address_id && resCustomer.changed('billing_address_id')) {
return resCustomer.hasAddress(resCustomer.billing_address_id, {
address: 'billing',
transaction: options.transaction || null
});
}
return false;
})
.then(hasBilling => {
if (!hasBilling && resCustomer.billing_address_id && resCustomer.changed('billing_address_id')) {
return resCustomer.addAddress(resCustomer.billing_address_id, {
address: 'billing',
transaction: options.transaction || null
});
}
return;
})
.then(() => {
if (resCustomer.default_address_id && resCustomer.changed('default_address_id')) {
return resCustomer.hasAddress(resCustomer.default_address_id, {
address: 'default',
transaction: options.transaction || null
});
}
return false;
})
.then(hasDefault => {
if (!hasDefault && resCustomer.default_address_id && resCustomer.changed('default_address_id')) {
return resCustomer.addAddress(resCustomer.default_address_id, {
address: 'default',
transaction: options.transaction || null
});
}
return;
})
.then(() => {
return resCustomer;
});
}
afterCreate(customer, options) {
options = options || {};
return this.setAddresses(customer, options)
.then(customerAddresses => {
this.publish('customer.created', customer);
return customer;
});
}
afterUpdate(customer, options) {
options = options || {};
this.publish('customer.updated', customer);
let updateAccounts = false;
let updateAddresses = false;
const accountUpdates = {};
if (customer.changed('email')) {
updateAccounts = true;
accountUpdates.email = customer.email;
}
if (customer.changed('shipping_address_id') || customer.changed('billing_address_id') || customer.changed('default_address_id')) {
updateAddresses = true;
}
return Promise.resolve()
.then(() => {
if (updateAddresses) {
return this.setAddresses(customer, options);
}
return;
})
.then(() => {
if (updateAccounts) {
return this.app.models['Account'].findAll({
where: {
customer_id: customer.id
}
})
.then(accounts => {
return Promise.all(accounts.map(account => {
return this.app.services.AccountService.update(account, accountUpdates);
}));
})
.then(updatedAccounts => {
return customer;
});
}
return;
})
.then(() => {
return customer;
});
}
createCustomerSource(customer, source, options = {}) {
const Account = this.app.models['Account'];
return Account.findOne({
where: {
customer_id: customer.id,
gateway: source.gateway
}
})
.then(account => {
if (!account) {
throw new Error('Account not found');
}
return this.app.services.AccountService.addSource(account, source.gateway_token, options);
});
}
findCustomerSource(customer, source, options = {}) {
const Account = this.app.models['Account'];
return Account.findOne({
where: {
customer_id: customer.id,
gateway: source.gateway
}
})
.then(account => {
source.account_id = account.id;
return this.app.services.AccountService.findSource(account, source, options);
});
}
syncCustomerSources(customer, account, options = {}) {
const Account = this.app.models['Account'];
return Account.findOne({
where: {
customer_id: customer.id,
gateway: account.gateway
}
})
.then(_account => {
return this.app.services.AccountService.syncSources(_account, options);
});
}
updateCustomerSource(customer, source, updates) {
const Account = this.app.models['Account'];
return Account.findOne({
where: {
customer_id: customer.id,
gateway: source.gateway
}
})
.then(account => {
source.account_id = account.id;
return this.app.services.AccountService.updateSource(account, source, updates);
});
}
enable(customer, options) {
options = options || {};
const Customer = this.app.models['Customer'];
let resCustomer;
return Customer.resolve(customer, options)
.then(_customer => {
if (!_customer) {
throw new errors_1.ModelError('E_NOT_FOUND', 'Customer not found');
}
resCustomer = _customer;
return resCustomer.update({ state: enums_1.CUSTOMER_STATE.ENABLED });
})
.then(() => {
const event = {
object_id: resCustomer.id,
object: 'customer',
objects: [{
customer: resCustomer.id
}],
type: 'customer.enabled',
message: `Customer ${resCustomer.getSalutation()} enabled`,
data: resCustomer
};
return this.publish(event.type, event, {
save: true,
transaction: options.transaction || null
});
})
.then(event => {
return resCustomer;
});
}
disable(customer, options) {
options = options || {};
const Customer = this.app.models['Customer'];
let resCustomer;
return Customer.resolve(customer, options)
.then(_customer => {
if (!_customer) {
throw new errors_1.ModelError('E_NOT_FOUND', 'Customer not found');
}
resCustomer = _customer;
return resCustomer.update({ state: enums_1.CUSTOMER_STATE.DISABLED });
})
.then(_customer => {
const event = {
object_id: resCustomer.id,
object: 'customer',
objects: [{
customer: resCustomer.id
}],
type: 'customer.disabled',
message: `Customer ${resCustomer.getSalutation()} disabled`,
data: resCustomer
};
return this.publish(event.type, event, {
save: true,
transaction: options.transaction || null
});
})
.then(event => {
return resCustomer;
});
}
removeCustomerSource(customer, source, options = {}) {
const Source = this.app.models['Source'];
return Source.resolve(source)
.then(_source => {
return this.app.services.AccountService.removeSource(_source, options);
});
}
}
exports.CustomerService = CustomerService;