Skip to content

Commit

Permalink
refactor(invoices): use FilterService on client
Browse files Browse the repository at this point in the history
This commit migrates the client side of the Invoice Registry to use the
FilterService.  To do this, the logic is heavily changed in the Invoice
Registry controller, removing the old DeprecatedFilterService and
replacing it completely.  The InvoiceService now manages caching
filters.  Additionally, the form is separated in two tabs with default
filters and specialized filters.

I've also taken the liberty to remove some style hacks and implemented a
search-modal class in bhima-bootstrap.less.  This class simply
transplants the styles to a location where they can be shared.

Progress towards Third-Culture-Software#1749.
  • Loading branch information
jniles committed Jun 2, 2017
1 parent 78ece43 commit 7707eeb
Show file tree
Hide file tree
Showing 9 changed files with 5,453 additions and 303 deletions.
15 changes: 10 additions & 5 deletions client/src/less/bhima-bootstrap.less
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,7 @@
@ima-light-orange: #fdba64;
@ima-light-blue: #6fbdee;

/** @todo move all structure code into less with configurable variables */
/**
* Application structure variables - these widths are used to determine how much
/** @todo move all structure code into less with configurable variables */ /** * Application structure variables - these widths are used to determine how much
* space the tree navigation takes up in its `expanded` and `collapsed` states.
*/
@expanded-offset: 260px;
Expand Down Expand Up @@ -266,6 +264,13 @@ input[type=number] {-moz-appearance: textfield;}

/* large button as menu */
.bg-ima-dark-blue { background: @ima-dark-blue; }
.bg-ima-dark-blue .value,
.bg-ima-dark-blue .uilabel
.bg-ima-dark-blue .value,
.bg-ima-dark-blue .uilabel
{ color: white !important; }

/* experimental usage of the search-modal */
.search-modal {
overflow : auto;
max-height:600px;
padding:0px;
}
4 changes: 1 addition & 3 deletions client/src/modules/cash/payments/registry.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@ function CashPaymentRegistryController(
vm.filter = filter;

// global variables
// vm.filters = { lang: Languages.key };
vm.filtersFmt = [];
vm.gridOptions = {};
vm.enterprise = Session.enterprise;
vm.bhConstants = bhConstants;
Expand Down Expand Up @@ -137,7 +135,7 @@ function CashPaymentRegistryController(
toggleLoadingIndicator();

var request = Cash.read(null, filters);

request.then(function (rows) {
rows.forEach(function (row) {
var hasCreditNote = row.reversed;
Expand Down
6 changes: 5 additions & 1 deletion client/src/modules/cash/payments/templates/search.modal.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
angular.module('bhima.controllers')
.controller('SearchCashPaymentModalController', SearchCashPaymentModalController);

// dependencies injections
SearchCashPaymentModalController.$inject = [
'CashboxService', 'NotifyService', '$uibModalInstance', 'filters', 'Store', 'PeriodService', 'util', 'DebtorGroupService',
];

/**
* Search Cash Payment controller
*
* @description
* This controller powers the Invoice Search modal. Invoices are passed in from the registry as
* POJO and are attached to the view. They are modified here and returned to the parent controller
* as a POJO.
*/
function SearchCashPaymentModalController(Cashboxes, Notify, Instance, filters, Store, Periods, util, DebtorGroups) {
var vm = this;
Expand Down
125 changes: 70 additions & 55 deletions client/src/modules/invoices/patientInvoice.service.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,28 @@ angular.module('bhima.services')
.service('PatientInvoiceService', PatientInvoiceService);

PatientInvoiceService.$inject = [
'$uibModal', 'util', 'SessionService', 'PrototypeApiService', 'DepricatedFilterService'
'$uibModal', 'SessionService', 'PrototypeApiService', 'FilterService', 'appcache', 'PeriodService',
];

/**
* @module
* Patient Invoice Service
*
* Allows direct querying of the /invoices API. Normally this should be done
* through the PatientService, but for queries not tied to particular patients,
* this service is particularly useful.
* @description
* This service wraps the /invoices URL and all CRUD on the underlying tables
* takes place through this service.
*/
function PatientInvoiceService(Modal, util, Session, Api, Filters) {
function PatientInvoiceService(Modal, Session, Api, Filters, AppCache, Periods) {
var service = new Api('/invoices/');

var filter = new Filters();
var invoiceFilters = new Filters();
var filterCache = new AppCache('cash-filters');

service.create = create;
service.openSearchModal = openSearchModal;
service.formatFilterParameters = formatFilterParameters;
service.openCreditNoteModal = openCreditNoteModal;
service.balance = balance;
service.filters = invoiceFilters;

/**
* @method create
Expand Down Expand Up @@ -55,7 +57,7 @@ function PatientInvoiceService(Modal, util, Session, Api, Filters) {

cp.description = description;

return Api.create.call(this, { invoice: cp });
return Api.create.call(this, { invoice : cp });
}

/**
Expand Down Expand Up @@ -83,7 +85,6 @@ function PatientInvoiceService(Modal, util, Session, Api, Filters) {
delete item._invalid;
delete item._initialised;
delete item._hasPriceList;

return item;
}

Expand All @@ -96,13 +97,13 @@ function PatientInvoiceService(Modal, util, Session, Api, Filters) {
keyboard : false,
backdrop : 'static',
controller : 'InvoiceRegistrySearchModalController as ModalCtrl',
resolve: {
filters : function filtersProvider() { return filters; }
}
resolve : {
filters : function filtersProvider() { return filters; },
},
}).result;
}

//open a dialog box to Cancel Credit Note
// open a dialog box to Cancel Credit Note
function openCreditNoteModal(invoice) {
return Modal.open({
templateUrl : 'modules/invoices/registry/modalCreditNote.html',
Expand All @@ -115,49 +116,63 @@ function PatientInvoiceService(Modal, util, Session, Api, Filters) {
}, true).result;
}

/**
* This function prepares the headers for invoice properties which were filtered,
* Special treatment occurs when processing data related to the date
* @todo - this might be better in its own service
*/
function formatFilterParameters(params) {
var columns = [
{ field: 'service_id', displayName: 'FORM.LABELS.SERVICE' },
{ field: 'user_id', displayName: 'FORM.LABELS.USER' },
{ field: 'reference', displayName: 'FORM.LABELS.REFERENCE' },
{ field: 'debtor_uuid', displayName: 'FORM.LABELS.CLIENT' },
{ field : 'patientReference', displayName: 'FORM.LABELS.REFERENCE_PATIENT'},
{ field: 'billingDateFrom', displayName: 'FORM.LABELS.DATE', comparitor: '>', ngFilter:'date' },
{ field: 'billingDateTo', displayName: 'FORM.LABELS.DATE', comparitor: '<', ngFilter:'date' },
{ field: 'reversed', displayName : 'FORM.INFO.CREDIT_NOTE' },
{ field: 'defaultPeriod', displayName : 'TABLE.COLUMNS.PERIOD', ngFilter : 'translate' },
{ field: 'cash_uuid', displayName : 'FORM.INFO.PAYMENT' },
{ field: 'defaultPeriod', displayName : 'TABLE.COLUMNS.PERIOD', ngFilter : 'translate' },
{ field: 'debtor_group_uuid', displayName: 'FORM.LABELS.DEBTOR_GROUP' }
];

// returns columns from filters
return columns.filter(function (column) {
var LIMIT_UUID_LENGTH = 6;
var value = params[column.field];

if (angular.isDefined(value)) {
column.value = value;

if (column.field === 'cash_uuid' || column.field === 'debtor_group_uuid') {
column.value = column.value.slice(0, LIMIT_UUID_LENGTH).concat('...');
}

// @FIXME tempoarary hack for default period
if (column.field === 'defaultPeriod') {
column.value = filter.lookupPeriod(value).label;
}
return true;
} else {
return false;
}
});
invoiceFilters.registerDefaultFilters([
{ key : 'period', label : 'TABLE.COLUMNS.PERIOD', valueFilter : 'translate' },
{ key : 'custom_period_start', label : 'PERIODS.START', valueFilter : 'date' },
{ key : 'custom_period_end', label : 'PERIODS.END', valueFilter : 'date' },
{ key : 'limit', label : 'FORM.LABELS.LIMIT' }]);

invoiceFilters.registerCustomFilters([
{ key : 'service_id', label : 'FORM.LABELS.SERVICE' },
{ key : 'user_id', label : 'FORM.LABELS.USER' },
{ key : 'reference', label : 'FORM.LABELS.REFERENCE' },
{ key : 'debtor_uuid', label : 'FORM.LABELS.CLIENT' },
{ key : 'patientReference', label : 'FORM.LABELS.REFERENCE_PATIENT' },
{ key : 'billingDateFrom', label : 'FORM.LABELS.DATE', comparitor : '>', valueFilter : 'date' },
{ key : 'billingDateTo', label : 'FORM.LABELS.DATE', comparitor : '<', valueFilter : 'date' },
{ key : 'reversed', label : 'FORM.INFO.CREDIT_NOTE' },
{ key : 'defaultPeriod', label : 'TABLE.COLUMNS.PERIOD', valueFilter : 'translate' },
{ key : 'cash_uuid', label : 'FORM.INFO.PAYMENT' },
]);

if (filterCache.filters) {
// load cached filter definition if it exists
invoiceFilters.loadCache(filterCache.filters);
}

// once the cache has been loaded - ensure that default filters are provided appropriate values
assignDefaultFilters();

function assignDefaultFilters() {
// get the keys of filters already assigned - on initial load this will be empty
var assignedKeys = Object.keys(invoiceFilters.formatHTTP());

// assign default period filter
var periodDefined =
service.util.arrayIncludes(assignedKeys, ['period', 'custom_period_start', 'custom_period_end']);

if (!periodDefined) {
invoiceFilters.assignFilters(Periods.defaultFilters());
}

// assign default limit filter
if (assignedKeys.indexOf('limit') === -1) {
invoiceFilters.assignFilter('limit', 100);
}
}

service.removeFilter = function removeFilter(key) {
invoiceFilters.resetFilterState(key);
};

// load filters from cache
service.cacheFilters = function cacheFilters() {
filterCache.filters = invoiceFilters.formatCache();
};

service.loadCachedFilters = function loadCachedFilters() {
invoiceFilters.loadCache(filterCache.filters || {});
};

return service;
}
22 changes: 6 additions & 16 deletions client/src/modules/invoices/registry/registry.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
<span class="fa fa-search"></span> <span translate>FORM.BUTTONS.SEARCH</span>
</button>
</div>

<div class="toolbar-item">
<bh-pdf-print pdf-url="/reports/finance/invoices"
options="InvoiceRegistryCtrl.filters">
Expand All @@ -23,30 +24,19 @@
<div class="toolbar-item">
<bh-renderer-dropdown
report-url="/reports/finance/invoices"
report-options="CPRCtrl.filters">
report-options="InvoiceRegistryCtrl.filters">
</bh-renderer-dropdown>
</div>
</div>
</div>
</div>

<div class="flex-util bh-filter-bar" ng-show="InvoiceRegistryCtrl.filtersFmt.length > 0">
<bh-filters-applied
<div class="flex-util bh-filter-bar">
<bh-filters
style="max-width:90%"
filters="InvoiceRegistryCtrl.filtersFmt"
filters="InvoiceRegistryCtrl.latestViewFilters"
on-remove-filter="InvoiceRegistryCtrl.onRemoveFilter(filter)">
</bh-filters-applied>

<!-- @FIXME patch hack -->
<a
href
ng-if="InvoiceRegistryCtrl.filter.customFiltersApplied(InvoiceRegistryCtrl.filters)"
ng-click="InvoiceRegistryCtrl.clearFilters()"
class="text-danger"
data-method="clear">
<i class="fa fa-close text-danger"></i>
<span translate>FORM.INFO.CLEAR_FILTERS</span>
</a>
</bh-filters>
</div>

<div class="flex-content">
Expand Down
Loading

0 comments on commit 7707eeb

Please sign in to comment.