Skip to content

Commit

Permalink
fix(supplier): generate creditors from groups
Browse files Browse the repository at this point in the history
This commit fixes a long-standing bug in the suppliers page.  The
suppliers previously used Creditors instead of Creditor Groups which
have no way to be created independently of the supplier.  The client
page has been refactored to choose creditor groups from a dropdown and
the server now generates a new creditor UUID when creating a supplier.

Closes #754.
  • Loading branch information
Jonathan Niles authored and jniles committed Sep 28, 2016
1 parent b1177db commit 071376d
Show file tree
Hide file tree
Showing 7 changed files with 237 additions and 260 deletions.
25 changes: 4 additions & 21 deletions client/src/js/services/CreditorGroupService.js
Original file line number Diff line number Diff line change
@@ -1,31 +1,14 @@
angular.module('bhima.services')
.service('CreditorGroupService', CreditorGroupService);
.service('CreditorGroupService', CreditorGroupService);

CreditorGroupService.$inject = ['$http', 'util'];
CreditorGroupService.$inject = ['PrototypeApiService'];

/**
* Creditor Group Service
*
* This service implements CRUD operations for the /creditor_groups API endpoint
*/
function CreditorGroupService($http, util) {
var service = this;
var baseUrl = '/creditor_groups/';

/** Exposed method read */
service.read = read;

/**
* @method read
* @param {string} uuid The creditor group uuid
* @param {object} parameters The query string object
* @description This function is responsible for getting creditor groups
*/
function read(uuid, parameters) {
var url = baseUrl.concat(uuid || '');
return $http.get(url, { params : parameters })
.then(util.unwrapHttpResponse);
}

function CreditorGroupService(Api) {
var service = Api('/creditor_groups/');
return service;
}
150 changes: 61 additions & 89 deletions client/src/partials/suppliers/suppliers.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<div class="bhima-title">
<ol class="headercrumb">
<li class="static">{{ "TREE.ADMIN" | translate }}</li>
<li class="active">{{ "SUPPLIER.TITLE" | translate }}</li>
<li class="title">{{ "SUPPLIER.TITLE" | translate }}</li>
</ol>

<div class="toolbar">
Expand Down Expand Up @@ -31,21 +31,23 @@
<tr>
<th>{{ "TABLE.COLUMNS.NAME" | translate }}</th>
<th>{{ "TABLE.COLUMNS.PHONE" | translate }}</th>
<th><span class="glyphicon glyphicon-lock"></span></th>
<th>{{ "TABLE.COLUMNS.ACTION" | translate }}</th>
</tr>
</thead>
<tbody>
<tr ng-if="SupplierCtrl.session.loading" class="text-center">
<td colspan="4"><loading-indicator></loading-indicator></td>
<tr ng-if="SupplierCtrl.loading" class="text-center">
<td colspan="3"><loading-indicator></loading-indicator></td>
</tr>
<tr ng-repeat="supplier in SupplierCtrl.suppliers | orderBy:'display_name'">
<td>{{ supplier.display_name }}</td>
<tr ng-repeat="supplier in (SupplierCtrl.suppliers | orderBy:'display_name') track by supplier.uuid">
<td>{{ supplier.display_name }} <i class="fa fa-lock" ng-show="supplier.locked"></i></td>
<td>{{ supplier.phone | telephone }}</td>
<td><i class="fa fa-check" ng-show="supplier.locked"></i></td>
<td><a class="btn btn-xs btn-default" id="supplier-upd-{{$index+1}}" ng-click="SupplierCtrl.update(supplier)"><span class="glyphicon glyphicon-pencil"></span></a></td>
<td>
<a id="supplier-upd-{{$index+1}}" ng-click="SupplierCtrl.update(supplier)" href>
<i class="fa fa-pencil-square-o"></i> {{ "FORM.BUTTONS.UPDATE" | translate }}
</a>
</td>
</tr>
<tr ng-if="!SupplierCtrl.suppliers.length">
<tr ng-if="!SupplierCtrl.suppliers.length && !SupplierCtrl.loading">
<td colspan="5">{{ "SUPPLIER.NO_SUPPLIER" | translate }}</td>
</tr>
</tbody>
Expand All @@ -61,20 +63,6 @@ <h4>{{ "SUPPLIER.TITLE" | translate }}</h4>
</div>
</div>

<!-- Success saving Feed Back -->
<div ng-switch-when="create_success">
<div class="alert alert-success" id="create_success">
<h4>{{ "FORM.INFO.SAVE_SUCCESS" | translate }}</h4>
</div>
</div>

<!-- Success updating feedBack -->
<div ng-switch-when="update_success">
<div class="alert alert-success" id="update_success">
<h4>{{ "FORM.INFO.UPDATE_SUCCESS" | translate }} </h4>
</div>
</div>

<!-- Form for adding supplier -->
<div class="panel panel-primary" ng-switch-when="create">
<div class="panel-heading">{{ "SUPPLIER.NEW_SUPPLIER" | translate }}</div>
Expand All @@ -98,12 +86,12 @@ <h4>{{ "FORM.INFO.UPDATE_SUCCESS" | translate }} </h4>

<hr>

<div class="form-group" ng-class="{ 'has-error' : CreateForm.$submitted && CreateForm.creditor_uuid.$invalid }">
<div class="form-group" ng-class="{ 'has-error' : CreateForm.$submitted && CreateForm.creditor_group_uuid.$invalid }">
<label class="control-label">{{ "FORM.LABELS.GROUP" | translate }}</label>
<select class="form-control" name="creditor_uuid" ng-model="SupplierCtrl.supplier.creditor_uuid" ng-options="creditor.uuid as creditor.text for creditor in SupplierCtrl.creditors | orderBy:'name'" required>
<option value="" disabled> -- {{ "FORM.SELECT.CREDITOR" | translate }} -- </option>
<select class="form-control" name="creditor_group_uuid" ng-model="SupplierCtrl.supplier.creditor_group_uuid" ng-options="group.uuid as group.name for group in SupplierCtrl.groups | orderBy:'name'" required>
<option value="" disabled>{{ "FORM.SELECT.CREDITOR_GROUP" | translate }}</option>
</select>
<div class="help-block" ng-messages="CreateForm.creditor_uuid.$error" ng-show="CreateForm.$submitted">
<div class="help-block" ng-messages="CreateForm.creditor_group_uuid.$error" ng-show="CreateForm.$submitted">
<div ng-messages-include="partials/templates/messages.tmpl.html"></div>
</div>
</div>
Expand Down Expand Up @@ -135,43 +123,36 @@ <h4>{{ "FORM.INFO.UPDATE_SUCCESS" | translate }} </h4>
</label>
</div>

<hr>
<h3> {{ "FORM.LABELS.OPTIONAL_INFO" | translate }} </h3>
<hr>
<fieldset>
<legend>{{ "FORM.LABELS.OPTIONAL_INFO" | translate }}</legend>

<div class="form-group" ng-class="{ 'has-error' : CreateForm.$submitted && CreateForm.address_2.$invalid }">
<label class="control-label">{{ "FORM.LABELS.ADDR_2" | translate }}</label>
<input type="address" class="form-control" name="address_2" ng-model="SupplierCtrl.supplier.address_2">
</div>
<div class="form-group" ng-class="{ 'has-error' : CreateForm.$submitted && CreateForm.address_2.$invalid }">
<label class="control-label">{{ "FORM.LABELS.ADDR_2" | translate }}</label>
<input type="address" class="form-control" name="address_2" ng-model="SupplierCtrl.supplier.address_2">
</div>

<div class="form-group" ng-class="{ 'has-error' : CreateForm.$submitted && CreateForm.fax.$invalid }">
<label class="control-label">{{ "FORM.LABELS.FAX" | translate }}</label>
<input type="text" class="form-control" name="fax" ng-model="SupplierCtrl.supplier.fax">
</div>
<div class="form-group" ng-class="{ 'has-error' : CreateForm.$submitted && CreateForm.fax.$invalid }">
<label class="control-label">{{ "FORM.LABELS.FAX" | translate }}</label>
<input type="text" class="form-control" name="fax" ng-model="SupplierCtrl.supplier.fax">
</div>

<div class="form-group" ng-class="{ 'has-error' : CreateForm.$submitted && CreateForm.note.$invalid }">
<label class="control-label" for="note">{{ "FORM.LABELS.NOTES" | translate }}</label>
<textarea class="form-control" name="note" ng-maxlength="SupplierCtrl.maxLength" ng-model="SupplierCtrl.supplier.note" rows="3"></textarea>
<div class="help-block" ng-messages="CreateForm.note.$error" ng-show="CreateForm.$submitted">
<div ng-messages-include="partials/templates/messages.tmpl.html"></div>
<div class="form-group" ng-class="{ 'has-error' : CreateForm.$submitted && CreateForm.note.$invalid }">
<label class="control-label" for="note">{{ "FORM.LABELS.NOTES" | translate }}</label>
<textarea class="form-control" name="note" ng-maxlength="SupplierCtrl.maxLength" ng-model="SupplierCtrl.supplier.note" rows="3"></textarea>
<div class="help-block" ng-messages="CreateForm.note.$error" ng-show="CreateForm.$submitted">
<div ng-messages-include="partials/templates/messages.tmpl.html"></div>
</div>
</div>
</div>
</fieldset>

<div class="form-group">
<button class="btn btn-default" id="submit-supplier" type="submit" data-method="submit">
<button class="btn btn-default" type="submit" data-method="submit">
{{ "FORM.BUTTONS.SAVE" | translate }}
</button>
<button class="btn btn-default" type="button" ng-click="SupplierCtrl.cancel()" data-method="cancel">
{{ "FORM.BUTTONS.RESET" | translate }}
</button>
</div>

<!-- error feedback area -->
<div ng-if="SupplierCtrl.state.errored && CreateForm.$submitted"
class="text-danger" data-role="feedback" style="margin-top:10px;">
<i class="glyphicon glyphicon-remove-sign"></i> {{ "FORM.ERRORS.HAS_ERRORS" | translate }}
</div>

</form>
</div>
</div>
Expand All @@ -189,21 +170,20 @@ <h3> {{ "FORM.LABELS.OPTIONAL_INFO" | translate }} </h3>
</div>
</div>

<div class="form-group" ng-class="{ 'has-error' : UpdateForm.$submitted && UpdateForm.international.$invalid }">
<label class="control-label">
<input type="checkbox" name="international" ng-true-value="1" ng-false-value="0"
ng-model="SupplierCtrl.supplier.international"> {{ "FORM.LABELS.INTL" | translate }}
<div class="checkbox">
<label>
<input type="checkbox" name="international" ng-true-value="1" ng-false-value="0" ng-model="SupplierCtrl.supplier.international"> {{ "FORM.LABELS.INTL" | translate }}
</label>
</div>

<hr>

<div class="form-group" ng-class="{ 'has-error' : UpdateForm.$submitted && UpdateForm.creditor_uuid.$invalid }">
<div class="form-group" ng-class="{ 'has-error' : UpdateForm.$submitted && UpdateForm.creditor_group_uuid.$invalid }">
<label class="control-label">{{ "FORM.LABELS.GROUP" | translate }}</label>
<select class="form-control" name="creditor_uuid" ng-model="SupplierCtrl.supplier.creditor_uuid" ng-options="creditor.uuid as creditor.text for creditor in SupplierCtrl.creditors | orderBy:'name'" required>
<option value="" disabled> -- {{ "FORM.SELECT.CREDITOR" | translate }} -- </option>
<select class="form-control" name="creditor_group_uuid" ng-model="SupplierCtrl.supplier.creditor_group_uuid" ng-options="group.uuid as group.name for group in SupplierCtrl.groups | orderBy:'name'" required>
<option value="" disabled>{{ "FORM.SELECT.CREDITOR_GROUP" | translate }}</option>
</select>
<div class="help-block" ng-messages="UpdateForm.creditor_uuid.$error" ng-show="UpdateForm.$submitted">
<div class="help-block" ng-messages="UpdateForm.creditor_group_uuid.$error" ng-show="UpdateForm.$submitted">
<div ng-messages-include="partials/templates/messages.tmpl.html"></div>
</div>
</div>
Expand All @@ -228,53 +208,45 @@ <h3> {{ "FORM.LABELS.OPTIONAL_INFO" | translate }} </h3>
</div>
</div>

<div class="form-group" ng-class="{ 'has-error' : UpdateForm.$submitted && UpdateForm.locked.$invalid }">
<label class="control-label">
<input type="checkbox" name="locked" ng-true-value="1" ng-false-value="0"
ng-model="SupplierCtrl.supplier.locked"> {{ "FORM.LABELS.LOCKED" | translate }}
<div class="checkbox">
<label>
<input type="checkbox" name="locked" ng-true-value="1" ng-false-value="0" ng-model="SupplierCtrl.supplier.locked"> {{ "FORM.LABELS.LOCKED" | translate }}
</label>
</div>

<hr>
<h3> {{ "FORM.LABELS.OPTIONAL_INFO" | translate }} </h3>
<hr>
<fieldset>
<legend>{{ "FORM.LABELS.OPTIONAL_INFO" | translate }}</legend>

<div class="form-group" ng-class="{ 'has-error' : UpdateForm.$submitted && UpdateForm.address_2.$invalid }">
<label class="control-label">{{ "FORM.LABELS.ADDR_2" | translate }}</label>
<input type="address" class="form-control" name="address_2" ng-model="SupplierCtrl.supplier.address_2">
</div>
<div class="form-group" ng-class="{ 'has-error' : UpdateForm.$submitted && UpdateForm.address_2.$invalid }">
<label class="control-label">{{ "FORM.LABELS.ADDR_2" | translate }}</label>
<input type="address" class="form-control" name="address_2" ng-model="SupplierCtrl.supplier.address_2">
</div>

<div class="form-group" ng-class="{ 'has-error' : UpdateForm.$submitted && UpdateForm.fax.$invalid }">
<label class="control-label">{{ "FORM.LABELS.FAX" | translate }}</label>
<input type="text" class="form-control" name="fax" ng-model="SupplierCtrl.supplier.fax">
</div>
<div class="form-group" ng-class="{ 'has-error' : UpdateForm.$submitted && UpdateForm.fax.$invalid }">
<label class="control-label">{{ "FORM.LABELS.FAX" | translate }}</label>
<input type="text" class="form-control" name="fax" ng-model="SupplierCtrl.supplier.fax">
</div>

<div class="form-group" ng-class="{ 'has-error' : UpdateForm.$submitted && UpdateForm.note.$invalid }">
<label class="control-label" for="note">{{ "FORM.LABELS.NOTES" | translate }}</label>
<textarea class="form-control" name="note" ng-maxlength="SupplierCtrl.maxLength" ng-model="SupplierCtrl.supplier.note" rows="3"></textarea>
<div class="help-block" ng-messages="UpdateForm.note.$error" ng-show="UpdateForm.$submitted">
<div ng-messages-include="partials/templates/messages.tmpl.html"></div>
<div class="form-group" ng-class="{ 'has-error' : UpdateForm.$submitted && UpdateForm.note.$invalid }">
<label class="control-label" for="note">{{ "FORM.LABELS.NOTES" | translate }}</label>
<textarea class="form-control" name="note" ng-maxlength="SupplierCtrl.maxLength" ng-model="SupplierCtrl.supplier.note" rows="3"></textarea>
<div class="help-block" ng-messages="UpdateForm.note.$error" ng-show="UpdateForm.$submitted">
<div ng-messages-include="partials/templates/messages.tmpl.html"></div>
</div>
</div>
</div>

</fieldset>
<div class="form-group">
<button class="btn btn-default" id="change_supplier" type="submit" data-method="submit">
<button class="btn btn-default" type="submit" data-method="submit">
{{ "FORM.BUTTONS.SAVE" | translate }}
</button>
<button class="btn btn-default" type="button" ng-click="SupplierCtrl.cancel()" data-method="cancel">
{{ "FORM.BUTTONS.RESET" | translate }}
</button>
</div>

<!-- error feedback area -->
<div ng-if="SupplierCtrl.state.errored && UpdateForm.$submitted"
class="text-danger" data-role="feedback" style="margin-top:10px;">
<i class="glyphicon glyphicon-remove-sign"></i> {{ "FORM.ERRORS.HAS_ERRORS" | translate }}
</div>
</form>
</div>
</div>

</div>
</div>
</div>
Expand Down
54 changes: 30 additions & 24 deletions client/src/partials/suppliers/suppliers.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
// TODO Handle HTTP exception errors (displayed contextually on form)
angular.module('bhima.controllers')
.controller('SupplierController', SupplierController);
.controller('SupplierController', SupplierController);

SupplierController.$inject = [
'SupplierService', 'CreditorService', 'util'
'SupplierService', 'CreditorGroupService', 'util', 'NotifyService'
];

function SupplierController(supplierService, creditorService, util) {
function SupplierController(Suppliers, CreditorGroups, util, Notify) {
var vm = this;

vm.view = 'default';
Expand All @@ -19,20 +18,17 @@ function SupplierController(supplierService, creditorService, util) {
vm.cancel = cancel;

vm.maxLength = util.maxTextLength;

function handler(error) {
console.error(error);
}
vm.loading = false;

// fired on startup
function startup() {
// start up loading indicator
vm.loading = true;

// load Creditors
creditorService.read().then(function (data) {
vm.creditors = data;
}).catch(handler);
CreditorGroups.read()
.then(function (groups) {
vm.groups = groups;
})
.catch(Notify.handleError);

// load suppliers
refreshSuppliers();
Expand All @@ -42,7 +38,6 @@ function SupplierController(supplierService, creditorService, util) {
vm.view = 'default';
}


function create() {
vm.view = 'create';
vm.supplier = {};
Expand All @@ -55,21 +50,30 @@ function SupplierController(supplierService, creditorService, util) {
vm.supplier = data;
}

function toggleLoadingIndicator() {
vm.loading = !vm.loading;
}

// refresh the displayed Suppliers
function refreshSuppliers() {
return supplierService.read(null,{ detailed : 1 })
.then(function (data) {
vm.suppliers = data;
vm.loading = false;
});

// start up loading indicator
toggleLoadingIndicator();

return Suppliers.read(null, { detailed : 1 })
.then(function (suppliers) {
vm.suppliers = suppliers;
})
.catch(Notify.handleError)
.finally(toggleLoadingIndicator);
}

// form submission
function submit(form) {

// stop submission if the form is invalid
if (form.$invalid) {
vm.state.errored = true;
Notify.danger('FORM.ERRORS.HAS_ERRORS');
return;
}

Expand All @@ -79,17 +83,19 @@ function SupplierController(supplierService, creditorService, util) {
var supplier = angular.copy(vm.supplier);

promise = (creation) ?
supplierService.create(supplier) :
supplierService.update(supplier.uuid, supplier);
Suppliers.create(supplier) :
Suppliers.update(supplier.uuid, supplier);

promise
.then(function (response) {
return refreshSuppliers();
})
.then(function () {
vm.view = creation ? 'create_success' : 'update_success';
var message = creation ? 'FORM.INFO.CREATE_SUCCESS' : 'FORM.INFO.UPDATE_SUCCESS';
Notify.success(message);
vm.view = 'default';
})
.catch(handler);
.catch(Notify.handleError);
}

startup();
Expand Down
Loading

0 comments on commit 071376d

Please sign in to comment.