Skip to content

Commit

Permalink
Merge pull request #237 from hql287/reimplement-invoice-update
Browse files Browse the repository at this point in the history
Reimplemented invoice update action. Fix #227
  • Loading branch information
hql287 authored Mar 2, 2018
2 parents d7c5901 + 90c1450 commit 355341e
Show file tree
Hide file tree
Showing 9 changed files with 289 additions and 107 deletions.
72 changes: 62 additions & 10 deletions app/actions/__tests__/invoices.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ it('getInvoices should create GET_INVOICES action', () => {
});
});

it('saveInvoice should create SAVE_INVOICE action', () => {
it('saveInvoice should create INVOICE_SAVE action', () => {
const invoiceData = {
_id: 'jon_snow',
fulname: 'Jon Snow',
Expand All @@ -19,21 +19,73 @@ it('saveInvoice should create SAVE_INVOICE action', () => {
});
});

it('deleteInvoice should create DELETE_INVOICE action', () => {
it('newInvoiceFromContact should create INVOICE_NEW_FROM_CONTACT action', () => {
const contactData = {
_id: 'jon_snow',
fulname: 'Jon Snow',
email: '[email protected]',
};
expect(actions.newInvoiceFromContact(contactData)).toEqual({
type: ACTION_TYPES.INVOICE_NEW_FROM_CONTACT,
payload: contactData,
});
});

it('deleteInvoice should create INVOICE_DELETE action', () => {
expect(actions.deleteInvoice('jon_snow')).toEqual({
type: ACTION_TYPES.INVOICE_DELETE,
payload: 'jon_snow',
});
});

it('newInvoiceFromContact should create INVOICE_NEW_FROM_CONTACT action', () => {
const contact = {
id: 'abcxyz',
name: 'Jon Snow',
company: 'HBO',
it('editInvoice should create INVOICE_EDIT action', () => {
const invoiceData = {
_id: 'jon_snow',
fulname: 'Jon Snow',
email: '[email protected]',
};
expect(actions.newInvoiceFromContact(contact)).toEqual({
type: ACTION_TYPES.INVOICE_NEW_FROM_CONTACT,
payload: contact,
expect(actions.editInvoice(invoiceData)).toEqual({
type: ACTION_TYPES.INVOICE_EDIT,
payload: invoiceData,
});
});

it('updateInvoice should create INVOICE_UPDATE action', () => {
const invoiceData = {
_id: 'jon_snow',
fulname: 'Jon Snow',
email: '[email protected]',
};
expect(actions.updateInvoice(invoiceData)).toEqual({
type: ACTION_TYPES.INVOICE_UPDATE,
payload: invoiceData,
});
});

it('setInvoiceStatus should create INVOICE_SET_STATUS action', () => {
const invoiceID = 'jon_snow';
const status = 'pending';
expect(actions.setInvoiceStatus(invoiceID, status)).toEqual({
type: ACTION_TYPES.INVOICE_SET_STATUS,
payload: {
invoiceID: 'jon_snow',
status: 'pending',
},
});
});

it('saveInvoiceConfigs should create INVOICE_CONFIGS_SAVE action', () => {
const invoiceID = 'jon_snow';
const configs = {
color: 'red'
};
expect(actions.saveInvoiceConfigs(invoiceID, configs)).toEqual({
type: ACTION_TYPES.INVOICE_CONFIGS_SAVE,
payload: {
invoiceID: 'jon_snow',
configs: {
color: 'red'
}
}
});
});
34 changes: 14 additions & 20 deletions app/actions/invoices.jsx
Original file line number Diff line number Diff line change
@@ -1,45 +1,39 @@
import * as ACTION_TYPES from '../constants/actions.jsx';
import { createAction } from 'redux-actions';

// Get All Invoices
export const getInvoices = createAction(ACTION_TYPES.INVOICE_GET_ALL);

// Save an Invoice
export const saveInvoice = createAction(
ACTION_TYPES.INVOICE_SAVE,
invoiceData => invoiceData
);

export const saveInvoiceConfigs = createAction(
ACTION_TYPES.INVOICE_CONFIGS_SAVE,
(invoiceID, configs) => ({ invoiceID, configs })
export const newInvoiceFromContact = createAction(
ACTION_TYPES.INVOICE_NEW_FROM_CONTACT,
contact => contact
);

export const deleteInvoice = createAction(
ACTION_TYPES.INVOICE_DELETE,
invoiceID => invoiceID
);

// Edit an Invoice
export const editInvoice = createAction(
ACTION_TYPES.INVOICE_EDIT,
invoiceData => invoiceData
);

export const updateInvoice = createAction(
ACTION_TYPES.INVOICE_UPDATE,
(invoiceID, data) => ({ invoiceID, data })
);

// New Invoice from Contact
export const newInvoiceFromContact = createAction(
ACTION_TYPES.INVOICE_NEW_FROM_CONTACT,
contact => contact
updatedInvoice => updatedInvoice
);

// Delete an invoice
export const deleteInvoice = createAction(
ACTION_TYPES.INVOICE_DELETE,
invoiceID => invoiceID
);

// set the status of an invoice (pending/paid/etc.)
export const setInvoiceStatus = createAction(
ACTION_TYPES.INVOICE_SET_STATUS,
(invoiceID, status) => ({ invoiceID, status })
);

export const saveInvoiceConfigs = createAction(
ACTION_TYPES.INVOICE_CONFIGS_SAVE,
(invoiceID, configs) => ({ invoiceID, configs })
);
11 changes: 11 additions & 0 deletions app/helpers/__mocks__/pouchDB.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,16 @@ const updateDoc = jest.fn(
})
);

const getSingleDoc = jest.fn(
(dbName, docID) =>
new Promise((resolve, reject) => {
!dbName && reject(new Error('No database found!'));
!docID && reject(new Error('No docID found!'));
dbName === 'contacts' && resolve([...mockData.contactsRecords][0]);
dbName === 'invoices' && resolve([...mockData.invoicesRecords][0]);
})
);

const deleteDoc = jest.fn(
(dbName, docId) =>
new Promise((resolve, reject) => {
Expand All @@ -83,6 +93,7 @@ const deleteDoc = jest.fn(

module.exports = {
getAllDocs,
getSingleDoc,
saveDoc,
updateDoc,
deleteDoc,
Expand Down
31 changes: 31 additions & 0 deletions app/helpers/__tests__/form.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import faker from 'faker';
import uuidv4 from 'uuid/v4';
import i18n from '../../../i18n/i18n';
import omit from 'lodash';

// Helpers to test
import {
Expand Down Expand Up @@ -267,6 +268,36 @@ describe('getInvoiceData', () => {
const invoiceData = getInvoiceData(newFormData);
expect(invoiceData.invoiceID).toEqual('Invoice: 123-456-789');
});

it('should return correct metadata on editMode', () => {
const invoiceID = uuidv4();
const invoiceRev = uuidv4();
const createdDate = Date.now();
const newFormData = Object.assign({}, formData, {
settings: Object.assign({}, formData.settings, {
editMode: Object.assign({}, formData.settings.editMode, {
active: true,
data: Object.assign({}, omit(formData, ['settings, savedSettings']),
{
_id: invoiceID,
_rev: invoiceRev,
created_at: createdDate
}
)
}),
}),
});
const invoiceData = getInvoiceData(newFormData);
expect(invoiceData._id).toEqual(invoiceID);
expect(invoiceData._rev).toEqual(invoiceRev);
expect(invoiceData.created_at).toEqual(createdDate);
});

// TODO
it('set status as pending when creating a new invoice');
it('always generate _id when creating a new invoice');
it('does not include _rev when creating a new invoice');
it('always recalculate subTotal and grandTotal');
});

describe('validateFormData', () => {
Expand Down
5 changes: 3 additions & 2 deletions app/helpers/form.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,12 @@ function getInvoiceData(formData) {

// Return final value
return Object.assign({}, invoiceData, {
// Reuse existing data
// Metadata
_id: editMode.active ? editMode.data._id : uuidv4(),
_rev: editMode.active ? editMode.data._rev : null,
created_at: editMode.active ? editMode.data.created_at : Date.now(),
status: editMode.active ? editMode.data.status: 'pending',
// Calculate subtotal & grandTotal
// Alway calculate subtotal & grandTotal
subtotal: getInvoiceValue(invoiceData).subtotal,
grandTotal: getInvoiceValue(invoiceData).grandTotal,
});
Expand Down
16 changes: 6 additions & 10 deletions app/helpers/pouchDB.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ const invoicesMigrations = {
placement: 'before',
separator: 'commaDot',
fraction: 2,
}
},
});
return newDoc;
},
Expand All @@ -81,9 +81,9 @@ const invoicesMigrations = {
dueDate: {
selectedDate: doc.dueDate,
useCustom: true,
}
},
});
}
},
};

runMigration(
Expand Down Expand Up @@ -176,17 +176,13 @@ const deleteDoc = (dbName, doc) =>
});

// Update A Document
const updateDoc = (dbName, docId, updatedDoc) =>
const updateDoc = (dbName, updatedDoc) =>
new Promise((resolve, reject) => {
setDB(dbName)
.then(db =>
db
.get(docId)
.then(record =>
db
.put(Object.assign(record, updatedDoc))
.then(getAllDocs(dbName).then(allDocs => resolve(allDocs)))
)
.put(updatedDoc)
.then(getAllDocs(dbName).then(allDocs => resolve(allDocs)))
)
.catch(err => reject(err));
});
Expand Down
7 changes: 3 additions & 4 deletions app/middlewares/FormMW.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,14 @@ const FormMW = ({ dispatch, getState }) => next => action => {
// Validate Form Data
if (!validateFormData(currentFormData)) return;
const currentInvoiceData = getInvoiceData(currentFormData);
// Check Edit Mode
// UPDATE DOC
if (currentFormData.settings.editMode.active) {
const invoiceId = currentFormData.settings.editMode.data._id;
// Update existing invoice
dispatch(InvoicesActions.updateInvoice(invoiceId, currentInvoiceData));
dispatch(InvoicesActions.updateInvoice(currentInvoiceData));
// Change Tab to invoices
dispatch(UIActions.changeActiveTab('invoices'));
} else {
// Save Invoice To DB
// CREATE DOC
dispatch(InvoicesActions.saveInvoice(currentInvoiceData));
}
// Save Contact to DB if it's a new one
Expand Down
Loading

0 comments on commit 355341e

Please sign in to comment.