diff --git a/lib/core.js b/lib/core.js index 04d6df500..8cc9578bd 100644 --- a/lib/core.js +++ b/lib/core.js @@ -23,6 +23,7 @@ const HELPERS = { reports: { file: 'reports' }, manualjournals: { file: 'manualjournals' }, repeatinginvoices: { file: 'repeatinginvoices' }, + contactGroups: { file: 'contactgroups' }, }; function Core(application) { diff --git a/lib/entities/accounting/contactgroup.js b/lib/entities/accounting/contactgroup.js new file mode 100644 index 000000000..79bb82489 --- /dev/null +++ b/lib/entities/accounting/contactgroup.js @@ -0,0 +1,82 @@ +'use strict'; + +const _ = require('lodash'); +const Entity = require('../entity'); +const ContactSchema = require('./contact').ContactSchema; + +const ContactGroupSchema = Entity.SchemaObject({ + ContactGroupID: { type: String, toObject: 'always' }, + Name: { type: String, toObject: 'always' }, + Status: { type: String, toObject: 'always' }, + Contacts: [ContactSchema], +}); + +const ContactGroup = Entity.extend(ContactGroupSchema, { + constructor: function(application, data, options) { + this.Entity.apply(this, arguments); + }, + initialize: function(data, options) {}, + save: function(options) { + const self = this; + let path = ''; + let method = ''; + if (this.ContactGroupID) { + path = `ContactGroups/${this.ContactGroupID}`; + method = 'post'; + } else { + path = 'ContactGroups'; + method = 'put'; + } + return this.application.putOrPostEntity( + method, + path, + JSON.stringify(self), + { + entityPath: 'ContactGroups', + entityConstructor: function(data) { + return self.application.core.contactGroups.newContactGroup(data); + }, + } + ); + }, + saveContacts: function(contacts) { + const self = this; + const path = `ContactGroups/${this.ContactGroupID}/Contacts`; + const method = 'put'; + + if (!_.isArray(contacts)) { + contacts = [contacts]; + } + + const payload = { + Contacts: contacts, + }; + + return this.application.putOrPostEntity( + method, + path, + JSON.stringify(payload), + { + entityPath: 'Contacts', + entityConstructor: function(data) { + return self.application.core.contacts.newContact(data); + }, + } + ); + }, + deleteContact: function(contactID) { + return this.deleteContacts(contactID); + }, + deleteContacts: function(contactID) { + let path = `ContactGroups/${this.ContactGroupID}/Contacts/`; + + if (contactID) { + path += contactID; + } + + return this.application.deleteEntities(path); + }, +}); + +module.exports.ContactGroup = ContactGroup; +module.exports.ContactGroupSchema = ContactGroupSchema; diff --git a/lib/entity_helpers/accounting/contactgroups.js b/lib/entity_helpers/accounting/contactgroups.js new file mode 100644 index 000000000..b9bcf6417 --- /dev/null +++ b/lib/entity_helpers/accounting/contactgroups.js @@ -0,0 +1,35 @@ +'use strict'; + +const _ = require('lodash'); +const EntityHelper = require('../entity_helper'); +const ContactGroup = require('../../entities/accounting/contactgroup').ContactGroup; + +const ContactGroups = EntityHelper.extend({ + constructor: function(application, options) { + EntityHelper.call( + this, + application, + Object.assign({ entityPlural: 'ContactGroups' }, options) + ); + }, + newContactGroup: function(data, options) { + return new ContactGroup(this.application, data, options); + }, + getContactGroups: function(options) { + return this.getEntities(this.setUpOptions(options)); + }, + getContactGroup: function(id) { + return this.getContactGroups({ id }).then(contactGroups => + _.first(contactGroups) + ); + }, + setUpOptions: function(options) { + const self = this; + const clonedOptions = _.clone(options || {}); + clonedOptions.entityPath = 'ContactGroups'; + clonedOptions.entityConstructor = data => self.newContactGroup(data); + return clonedOptions; + } +}); + +module.exports = ContactGroups; diff --git a/test/core/contactgroups_tests.js b/test/core/contactgroups_tests.js new file mode 100644 index 000000000..4e47055fc --- /dev/null +++ b/test/core/contactgroups_tests.js @@ -0,0 +1,184 @@ +'use strict'; + +const common = require('../common/common'); +const functions = require('../common/functions'); + +const expect = common.expect; +const wrapError = functions.wrapError; + +const validateContactGroup = contactGroup => { + if (!contactGroup) { + return false; + } + + expect(contactGroup.ContactGroupID).to.be.a('String'); + expect(contactGroup.Name).to.be.a('String'); + expect(contactGroup.Status).to.be.a('String'); + expect(contactGroup.Contacts.length).to.be.a('Number'); + contactGroup.Contacts.forEach(contact => { + expect(contact.ContactID).to.be.a('String'); + expect(contact.Name).to.be.a('String'); + }); + + return true; +}; + +describe('Contact Groups', () => { + let contactGroupID = ''; + const sampleContactGroup = { + Name: `Test Contact Group: ${Math.random()}`, + Status: 'ACTIVE', + }; + it('get all', done => { + common.currentApp.core.contactGroups + .getContactGroups() + .then(contactGroups => { + expect(contactGroups).to.have.length.greaterThan(0); + contactGroups.forEach(contactGroup => { + expect(validateContactGroup(contactGroup)).to.equal(true); + contactGroupID = contactGroup.ContactGroupID; + }); + done(); + }) + .catch(err => { + console.error(err); + done(wrapError(err)); + }); + }); + + it('get single', done => { + common.currentApp.core.contactGroups + .getContactGroup(contactGroupID) + .then(contactGroup => { + expect(validateContactGroup(contactGroup)).to.equal(true); + done(); + }) + .catch(err => { + console.error(err); + done(wrapError(err)); + }); + }); + + it('creates a contact group', done => { + const contactGroup = common.currentApp.core.contactGroups.newContactGroup( + sampleContactGroup + ); + + contactGroup + .save() + .then(response => { + expect(validateContactGroup(response.entities[0])).to.equal(true); + sampleContactGroup.ContactGroupID = response.entities[0].ContactGroupID; + done(); + }) + .catch(err => { + console.error(err); + done(wrapError(err)); + }); + }); + + it('Updates a contact group', done => { + const updatedName = `Updated ${Math.random()}`; + common.currentApp.core.contactGroups + .getContactGroup(sampleContactGroup.ContactGroupID) + .then(contactGroup => { + expect(validateContactGroup(contactGroup)).to.equal(true); + contactGroup.Name = updatedName; + return contactGroup.save(); + }) + .then(response => { + expect(validateContactGroup(response.entities[0])).to.equal(true); + expect(response.entities[0].Name).to.equal(updatedName); + done(); + }) + .catch(err => { + console.error(err); + done(wrapError(err)); + }); + }); + + it('Adds a contact to a contact group', done => { + const sampleContacts = []; + common.currentApp.core.contacts + .getContacts() + .then(contacts => { + for (let i = 0; i < 5; i += 1) { + sampleContacts.push({ + ContactID: contacts[i].ContactID, + }); + } + }) + .then(() => + common.currentApp.core.contactGroups.getContactGroup( + sampleContactGroup.ContactGroupID + ) + ) + .then(contactGroup => { + expect(validateContactGroup(contactGroup)).to.equal(true); + return contactGroup.saveContacts(sampleContacts); + }) + .then(response => { + response.entities.forEach((contact, idx) => { + expect(contact.ContactID).to.equal(sampleContacts[idx].ContactID); + }); + done(); + }) + .catch(err => { + console.error(err); + done(wrapError(err)); + }); + }); + + it('Deletes a specific contact from a contact group', done => { + let contactIDToRemove = ''; + common.currentApp.core.contactGroups + .getContactGroup(sampleContactGroup.ContactGroupID) + .then(contactGroup => { + expect(validateContactGroup(contactGroup)).to.equal(true); + contactIDToRemove = contactGroup.Contacts[0].ContactID; + return contactGroup.deleteContact(contactIDToRemove); + }) + .then(() => { + done(); + }) + .catch(err => { + console.error(err); + done(wrapError(err)); + }); + }); + + it('Deletes all contacts from a contact group', done => { + common.currentApp.core.contactGroups + .getContactGroup(sampleContactGroup.ContactGroupID) + .then(contactGroup => { + expect(validateContactGroup(contactGroup)).to.equal(true); + return contactGroup.deleteContacts(); + }) + .then(() => { + done(); + }) + .catch(err => { + console.error(err); + done(wrapError(err)); + }); + }); + + it('Deletes a contact group', done => { + common.currentApp.core.contactGroups + .getContactGroup(sampleContactGroup.ContactGroupID) + .then(contactGroup => { + expect(validateContactGroup(contactGroup)).to.equal(true); + contactGroup.Status = 'DELETED'; + return contactGroup.save(); + }) + .then(response => { + expect(validateContactGroup(response.entities[0])).to.equal(true); + expect(response.entities[0].Status).to.equal('DELETED'); + done(); + }) + .catch(err => { + console.error(err); + done(wrapError(err)); + }); + }); +}); diff --git a/test/testrunner.js b/test/testrunner.js index 5e6af26ba..3aaa36e27 100644 --- a/test/testrunner.js +++ b/test/testrunner.js @@ -52,6 +52,7 @@ describe('Accounting API Tests', () => { 'repeatinginvoice_tests', `${__dirname}/core/repeatinginvoice_tests.js` ); + importTest('contactgroups_tests', `${__dirname}/core/contactgroups_tests.js`); }); describe.skip('Payroll API Tests', () => {