UNPKG

@fabrix/spool-cart

Version:

Spool - eCommerce Spool for Fabrix

1,175 lines (1,174 loc) 45.4 kB
"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;