Skip to content
This repository has been archived by the owner on Jan 9, 2023. It is now read-only.

Fix math in InventoryPurchaseItem.costPerUnit and add math util for rounding #864

Merged
merged 7 commits into from
Dec 14, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion app/mixins/number-format.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export default Ember.Mixin.create({
if (Math.round(value) === value) {
returnValue = Number(value).toString();
} else {
returnValue = Number(value).toFixed(2);
returnValue = this._round100(value).toFixed(2);
}
if (returnAsNumber) {
return Number(returnValue);
Expand All @@ -61,6 +61,11 @@ export default Ember.Mixin.create({

_validNumber(number) {
return (!Ember.isEmpty(number) && !isNaN(number) && number > 0);
},

_round100(number) {
let tempNumber = 100 * number;
return Math.round(tempNumber) / 100;
}

});
5 changes: 3 additions & 2 deletions app/models/inv-purchase.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import AbstractModel from 'hospitalrun/models/abstract';
import DS from 'ember-data';
import Ember from 'ember';
import LocationName from 'hospitalrun/mixins/location-name';
import NumberFormat from 'hospitalrun/mixins/number-format';

function defaultQuantityGroups() {
return [];
Expand All @@ -13,7 +14,7 @@ function defaultQuantityGroups() {
* items to be shown as inventory items since the pouchdb adapter does a
* retrieve for keys starting with 'inventory' to fetch inventory items.
*/
let InventoryPurchaseItem = AbstractModel.extend(LocationName, {
let InventoryPurchaseItem = AbstractModel.extend(LocationName, NumberFormat, {
purchaseCost: DS.attr('number'),
lotNumber: DS.attr('string'),
dateReceived: DS.attr('date'),
Expand All @@ -23,7 +24,7 @@ let InventoryPurchaseItem = AbstractModel.extend(LocationName, {
if (Ember.isEmpty(purchaseCost) || Ember.isEmpty(quantity) || purchaseCost === 0 || quantity === 0) {
return 0;
}
return Number((purchaseCost / quantity).toFixed(2));
return this._numberFormat(purchaseCost / quantity, true);
}.property('purchaseCost', 'originalQuantity'),
originalQuantity: DS.attr('number'),
currentQuantity: DS.attr('number'),
Expand Down
59 changes: 59 additions & 0 deletions tests/unit/mixins/number-format-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import NumberFormat from 'hospitalrun/mixins/number-format';
import { moduleFor, test } from 'ember-qunit';
import Ember from 'ember';

moduleFor('mixin:number-format', 'Unit | Mixin | number-format');

test('_calculateTotal', function(assert) {
let records = [5, 5, 6].map((id) => Ember.Object.create({ id }));
let numberFormat = Ember.Object.extend(NumberFormat).create({ records });

assert.strictEqual(numberFormat._calculateTotal('records', 'id'), 16, 'Should add property array');
});

test('_calculateTotal property name', function(assert) {
let records = [5, 2, 3].map((id) => Ember.Object.create({ id }));
let numberFormat = Ember.Object.extend(NumberFormat).create();

assert.strictEqual(numberFormat._calculateTotal(records, 'id'), 10, 'Should add passed in array');
});

test('_calculateTotal invalid number', function(assert) {
let records = [5, 'test', 3].map((id) => Ember.Object.create({ id }));
let numberFormat = Ember.Object.extend(NumberFormat).create({ records });

assert.strictEqual(numberFormat._calculateTotal('records', 'id'), 8, 'Should treat invalid number as 0');
});

test('_numberFormat', function(assert) {
let numberFormat = Ember.Object.extend(NumberFormat).create();

assert.strictEqual(numberFormat._numberFormat(), undefined, 'Should return undefined for no argument');
assert.strictEqual(numberFormat._numberFormat('test'), undefined, 'Should return undefined for no number');
assert.strictEqual(numberFormat._numberFormat(12), '12', 'Should return basic int as string');
assert.strictEqual(numberFormat._numberFormat(12, true), 12, 'Should return basic int as number');
assert.strictEqual(numberFormat._numberFormat(12.2, true), 12.2, 'Should round tenths properly');
assert.strictEqual(numberFormat._numberFormat(12.2), '12.20', 'Should pad decial to two places');
assert.strictEqual(numberFormat._numberFormat(35.555, true), 35.56, 'Should round 35.555 to 35.56');
assert.strictEqual(numberFormat._numberFormat(35.555), '35.56', 'Should return 35.555 as string "35.56"');
});

test('_getValidNumber', function(assert) {
let numberFormat = Ember.Object.extend(NumberFormat).create();

assert.strictEqual(numberFormat._getValidNumber(), 0, 'Should return 0 for no argument');
assert.strictEqual(numberFormat._getValidNumber('test'), 0, 'Should return 0 for invalid number');
assert.strictEqual(numberFormat._getValidNumber(NaN), 0, 'Should return 0 for NaN');
assert.strictEqual(numberFormat._getValidNumber('12.2'), 12.2, 'Should convert string to number');
assert.strictEqual(numberFormat._getValidNumber(1), 1, 'Should return basic int');
});

test('_validNumber', function(assert) {
let numberFormat = Ember.Object.extend(NumberFormat).create();

assert.strictEqual(numberFormat._validNumber(1), true, 'Should return true for basic int');
assert.strictEqual(numberFormat._validNumber(1.5), true, 'Should return true for float');
assert.strictEqual(numberFormat._validNumber('1'), true, 'Should return true for numeric string');
assert.strictEqual(numberFormat._validNumber(-1), false, 'Should return false for negative');
assert.strictEqual(numberFormat._validNumber('test'), false, 'Should return false for non numeric string');
});
55 changes: 55 additions & 0 deletions tests/unit/models/inv-purchase-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { moduleForModel, test } from 'ember-qunit';

import { testValidPropertyValues, testInvalidPropertyValues } from '../../helpers/validate-properties';

moduleForModel('inv-purchase', 'Unit | Model | inv-purchase', {
needs: [
'ember-validations@validator:local/numericality',
'ember-validations@validator:local/presence'
]
});

test('costPerUnit', function(assert) {
let inventoryPurchaseItem = this.subject({
purchaseCost: 12.50,
originalQuantity: 5
});

assert.strictEqual(inventoryPurchaseItem.get('costPerUnit'), 2.5);
});

test('costPerUnit properly round', function(assert) {
let inventoryPurchaseItem = this.subject({
purchaseCost: 71.11,
originalQuantity: 2
});

assert.strictEqual(inventoryPurchaseItem.get('costPerUnit'), 35.56);
});

test('costPerUnit invalid input', function(assert) {
let inventoryPurchaseItem = this.subject({
purchaseCost: 0,
originalQuantity: 5
});

assert.strictEqual(inventoryPurchaseItem.get('costPerUnit'), 0);
});

test('costPerUnit 0 input', function(assert) {
let inventoryPurchaseItem = this.subject({
purchaseCost: 12.50,
originalQuantity: 0
});

assert.strictEqual(inventoryPurchaseItem.get('costPerUnit'), 0);
});

testValidPropertyValues('purchaseCost', [123, 123.0, '123']);
testInvalidPropertyValues('purchaseCost', ['test', undefined]);

testValidPropertyValues('originalQuantity', [0, 123, '0']);
testInvalidPropertyValues('originalQuantity', [-1, '-1', undefined]);

testValidPropertyValues('vendor', ['test']);
testInvalidPropertyValues('vendor', [undefined]);