diff --git a/.env.development b/.env.development index 8dd6fee44c..899164f988 100644 --- a/.env.development +++ b/.env.development @@ -13,7 +13,6 @@ SESS_RESAVE=0 SESS_UNSET='destroy' LOG_LEVEL='warn' -# LOG_LEVEL='warn' # LOG_LEVEL='debug' UPLOAD_DIR='client/upload' diff --git a/client/src/i18n/en/patient_registry.json b/client/src/i18n/en/patient_registry.json index b9b01cc01e..08213ccab3 100644 --- a/client/src/i18n/en/patient_registry.json +++ b/client/src/i18n/en/patient_registry.json @@ -1,12 +1,17 @@ -{"PATIENT_REGISTRY":{"CARD":"Card", -"DAY":"day", -"DAYS":"days", -"INVOICES":"View Invoices", -"INVOICE": "Invoice", -"MONTH":"month", -"MONTHS":"months", -"PAYMENTS":"View Cash Payments", -"YEAR_OLD":"year old", -"YEARS_OLD":"years old", -"TITLE":"Patients", -"RECORD":"Record"}} \ No newline at end of file +{ + "PATIENT_REGISTRY":{ + "CARD":"Card", + "DAY":"day", + "DAYS":"days", + "INVOICES":"View Invoices", + "INVOICE": "Invoice", + "VOUCHERS" : "View Vouchers", + "MONTH":"month", + "MONTHS":"months", + "PAYMENTS":"View Cash Payments", + "YEAR_OLD":"year old", + "YEARS_OLD":"years old", + "TITLE":"Patients", + "RECORD":"Record" + } +} diff --git a/client/src/i18n/en/vouchers.json b/client/src/i18n/en/vouchers.json index 6f8bcb3249..866b5f8d40 100644 --- a/client/src/i18n/en/vouchers.json +++ b/client/src/i18n/en/vouchers.json @@ -1,56 +1,70 @@ -{"VOUCHERS":{"COMPLEX":{"ADD_ITEMS":"Add item(s)", -"CASH_PAYMENT":"Cash Payment", -"CREATE_SUCCESS":"Successfully posted", -"CREATE_ERROR":"An error occurred when post", -"CREDITOR":"Creditor (C)", -"DEBTOR":"Debtor (D)", -"DEB_CRED":"Debtor/Creditor", -"DESCRIPTION":"This module allows you to make advanced journal transactions manually", -"ENTITY":"Entity (Debtor/Creditor)", -"ERROR_ACCOUNT":"Selected accounts are invalid", -"ERROR_AMOUNT":"Amount's values are invalid", -"ERROR_TOTALS":"The totals are not balanced", -"ERROR_PRECISION":"The amounts entered cannot have more than 4 decimal places in precision", -"INVALID_VALUES":"There are invalid values detected", -"PATIENT_INVOICE":"Patient Invoice", -"REFERENCE":"Reference", -"ROWS":"Row(s)", -"SELECT_DOCUMENT_TYPE":"Please select the document type", -"TITLE":"Advanced Journal Vouchers", -"VALID_TOTALS":"Transactions are valid (balanced transaction)", -"VOUCHER":"Voucher"}, -"TYPES":{"SUPPORT_PAYMENT_DESCRIPTION":"Debt transfer from {{ patientName }} ({{ patientReference}}) for invoice {{ invoiceReference }}."}, -"GLOBAL":{"CASHFLOW_OPTION":"Cashflow Option", -"TRANSFER_DESCRIPTION": "Transfer: From {{ fromAccount }} to {{ toAccount }} for {{ amount }} {{ symbol }}", -"CONVENTION_INVOICES":"Convention - Invoices payment", -"SUPPORT_FORM":"Patients Support - Form", -"SUPPORT_TEXT":"When the above two fields are filled in, we will look for open debts for the patient to assign to the \"Support Patient\" Account.", -"IMPORT_TRANSACTION":"Import transactions", -"GENERIC_EXPENSE":"Generic Expense", -"GENERIC_INCOME":"Generic Income", -"ORIGIN_ACCOUNT":"Provenance Account", -"DESTINATION_ACCOUNT":"Destination Account", -"TRANSFER_ACCOUNT":"Transfer Account", -"CASH_TRANSFER":"Cash Transfer", -"REPORT":"Voucher Report", -"TITLE":"Voucher", -"TRANSFER_TYPE_INFO":"Transaction Type in case we have either incomes or expenses", -"USE_FINANCIAL_ACCOUNT":"Use of cashes or banks accounts in this transaction", -"RECEIPT":{"SUCCESS":"Voucher Payment recorded successfully."}, -"ERROR_SAME_ACCOUNT":"You cannot use the same account twice to in this transaction. Please select two different accounts."}, -"SIMPLE":{"CASH_PAYMENT":"Client Payment", -"CASH_RETURN":"Cash Return (Payback)", -"CONVENTION_PAYMENT":"Convention Payment", -"CREDIT_NOTE":"Credit Note", -"EXPENSE":"Expenses", -"INCOME":"Incomes", -"INVOICING":"Invoicing", -"SALARY_PAYMENT":"Salary Payment", -"GENERIC_EXPENSE":"Other Expenses", -"GENERIC_INCOME":"Other Incomes", -"PURCHASES":"Purchases", -"SUPPORT_INCOME":"Support Incomes", -"TITLE":"Simple Voucher", -"TRANSFER":"Money Transfer", -"TRANSFER_PATIENT_INVOICE_AMOUNT":"Patient Invoice Debt Transfer"}, -"REPORT":"Report"}} \ No newline at end of file +{ + "VOUCHERS" : { + "COMPLEX":{ + "ADD_ITEMS":"Add item(s)", + "CASH_PAYMENT":"Cash Payment", + "CREATE_SUCCESS":"Successfully posted", + "CREATE_ERROR":"An error occurred when post", + "CREDITOR":"Creditor (C)", + "DEBTOR":"Debtor (D)", + "DEB_CRED":"Debtor/Creditor", + "DESCRIPTION":"This module allows you to make advanced journal transactions manually", + "ENTITY":"Entity (Debtor/Creditor)", + "ERROR_ACCOUNT":"Selected accounts are invalid", + "ERROR_AMOUNT":"Amount's values are invalid", + "ERROR_TOTALS":"The totals are not balanced", + "ERROR_PRECISION":"The amounts entered cannot have more than 4 decimal places in precision", + "INVALID_VALUES":"There are invalid values detected", + "PATIENT_INVOICE":"Patient Invoice", + "REFERENCE":"Reference", + "ROWS":"Row(s)", + "SELECT_DOCUMENT_TYPE":"Please select the document type", + "TITLE":"Advanced Journal Vouchers", + "VALID_TOTALS":"Transactions are valid (balanced transaction)", + "VOUCHER":"Voucher" + }, + "TYPES":{ + "SUPPORT_PAYMENT_DESCRIPTION":"Debt transfer from {{ patientName }} ({{ patientReference}}) for invoice {{ invoiceReference }}." + }, + "GLOBAL":{ + "CASHFLOW_OPTION":"Cashflow Option", + "TRANSFER_DESCRIPTION": "Transfer: From {{ fromAccount }} to {{ toAccount }} for {{ amount }} {{ symbol }}", + "CONVENTION_INVOICES":"Convention - Invoices payment", + "SUPPORT_FORM":"Patients Support - Form", + "SUPPORT_TEXT":"When the above two fields are filled in, we will look for open debts for the patient to assign to the \"Support Patient\" Account.", + "IMPORT_TRANSACTION":"Import transactions", + "GENERIC_EXPENSE":"Generic Expense", + "GENERIC_INCOME":"Generic Income", + "ORIGIN_ACCOUNT":"Provenance Account", + "DESTINATION_ACCOUNT":"Destination Account", + "TRANSFER_ACCOUNT":"Transfer Account", + "CASH_TRANSFER":"Cash Transfer", + "REPORT":"Voucher Report", + "TITLE":"Voucher", + "TRANSFER_TYPE_INFO":"Transaction Type in case we have either incomes or expenses", + "USE_FINANCIAL_ACCOUNT":"Use of cashes or banks accounts in this transaction", + "RECEIPT":{ + "SUCCESS":"Voucher Payment recorded successfully." + }, + "ERROR_SAME_ACCOUNT":"You cannot use the same account twice to in this transaction. Please select two different accounts." + }, + "SIMPLE":{ + "CASH_PAYMENT":"Client Payment", + "CASH_RETURN":"Cash Return (Payback)", + "CONVENTION_PAYMENT":"Convention Payment", + "CREDIT_NOTE":"Credit Note", + "EXPENSE":"Expenses", + "INCOME":"Incomes", + "INVOICING":"Invoicing", + "SALARY_PAYMENT":"Salary Payment", + "GENERIC_EXPENSE":"Other Expenses", + "GENERIC_INCOME":"Other Incomes", + "PURCHASES":"Purchases", + "SUPPORT_INCOME":"Support Incomes", + "TITLE":"Simple Voucher", + "TRANSFER":"Money Transfer", + "TRANSFER_PATIENT_INVOICE_AMOUNT":"Patient Invoice Debt Transfer" + }, + "REPORT":"Report" + } +} diff --git a/client/src/i18n/fr/patient_registry.json b/client/src/i18n/fr/patient_registry.json index 41ec6bb66e..aba5ea2eb0 100644 --- a/client/src/i18n/fr/patient_registry.json +++ b/client/src/i18n/fr/patient_registry.json @@ -1,12 +1,17 @@ -{"PATIENT_REGISTRY":{"CARD":"Carte", -"DAY":"jour", -"DAYS":"jours", -"INVOICES":"Les factures", -"INVOICE":"La facture", -"MONTH":"mois", -"MONTHS":"mois", -"PAYMENTS":"Les paiements", -"RECORD":"Enregistrement", -"YEAR_OLD":"an", -"YEARS_OLD":"ans", -"TITLE":"Registre des patients"}} \ No newline at end of file +{ + "PATIENT_REGISTRY":{ + "CARD":"Carte", + "DAY":"jour", + "DAYS":"jours", + "INVOICES":"Les Factures", + "VOUCHERS":"Les Bordereaux", + "INVOICE":"La facture", + "MONTH":"mois", + "MONTHS":"mois", + "PAYMENTS":"Les Paiements", + "RECORD":"Enregistrement", + "YEAR_OLD":"an", + "YEARS_OLD":"ans", + "TITLE":"Registre des Patients" + } +} diff --git a/client/src/js/services/FilterService.js b/client/src/js/services/FilterService.js index 110b493434..3050f5b5c9 100644 --- a/client/src/js/services/FilterService.js +++ b/client/src/js/services/FilterService.js @@ -82,7 +82,7 @@ function FilterService(Store) { // return filters for the view - this method will always be compatible with the bhFilter component FilterList.prototype.formatView = function formatView() { var activeFilters = this._filterActiveFilters(); - var activeKeys = activeFilters.map(function (filter) { return filter._key; }); + var activeKeys = activeFilters.map(function (filter) { return filter._key; }); function keysInActive(filter) { return activeKeys.indexOf(filter._key) !== -1; } diff --git a/client/src/modules/patients/templates/action.cell.html b/client/src/modules/patients/templates/action.cell.html index b451137e52..5997bd34e1 100644 --- a/client/src/modules/patients/templates/action.cell.html +++ b/client/src/modules/patients/templates/action.cell.html @@ -32,5 +32,10 @@ PATIENT_REGISTRY.PAYMENTS +
  • + + PATIENT_REGISTRY.VOUCHERS + +
  • diff --git a/client/src/modules/vouchers/voucher-registry.ctrl.js b/client/src/modules/vouchers/voucher-registry.ctrl.js index e4b07ef421..cc4180abf0 100644 --- a/client/src/modules/vouchers/voucher-registry.ctrl.js +++ b/client/src/modules/vouchers/voucher-registry.ctrl.js @@ -144,10 +144,6 @@ function VoucherController(Vouchers, Notify, uiGridGroupingConstants, Receipts.voucher(uuid); } - function isEmpty(object) { - return Object.keys(object).length === 0; - } - function load(filters) { // flush error and loading states vm.hasError = false; @@ -212,6 +208,15 @@ function VoucherController(Vouchers, Notify, uiGridGroupingConstants, // initialize module function startup() { + var changes; + + if ($state.params.filters.length) { + changes = angular.copy($state.params.filters); + + Vouchers.filters.replaceFilters(changes); + Vouchers.cacheFilters(); + } + Vouchers.transactionType() .then(function (store) { vm.transactionTypes = store; @@ -228,7 +233,7 @@ function VoucherController(Vouchers, Notify, uiGridGroupingConstants, // column configuration has direct access to the grid API to alter the current // state of the columns - this will be saved if the user saves the grid configuration gridColumns.openConfigurationModal(); - }; + } vm.saveGridState = state.saveGridState; @@ -236,7 +241,7 @@ function VoucherController(Vouchers, Notify, uiGridGroupingConstants, function clearGridState() { state.clearGridState(); $state.reload(); - }; + } startup(); } diff --git a/client/src/modules/vouchers/vouchers.routes.js b/client/src/modules/vouchers/vouchers.routes.js index bc64e834b9..627ea8461d 100644 --- a/client/src/modules/vouchers/vouchers.routes.js +++ b/client/src/modules/vouchers/vouchers.routes.js @@ -18,6 +18,9 @@ angular.module('bhima.routes') url : '/vouchers', controller : 'VoucherController as VoucherCtrl', templateUrl : 'modules/vouchers/voucher-registry.html', + params : { + filters : [], + }, }) .state('simpleVouchers.barcode', { diff --git a/client/src/modules/vouchers/vouchers.service.js b/client/src/modules/vouchers/vouchers.service.js index a306f0eba3..3ed9d109ad 100644 --- a/client/src/modules/vouchers/vouchers.service.js +++ b/client/src/modules/vouchers/vouchers.service.js @@ -37,21 +37,20 @@ function VoucherService(Api, $http, TransactionTypeStore, Modal, voucherFilters.registerDefaultFilters([ { key : 'period', label : 'TABLE.COLUMNS.PERIOD', valueFilter : 'translate' }, - { key : 'custom_period_start', label : 'PERIODS.START', comparitor: '>', valueFilter : 'date' }, - { key : 'custom_period_end', label : 'PERIODS.END', comparitor: '<', valueFilter : 'date' }, + { key : 'custom_period_start', label : 'PERIODS.START', comparitor : '>', valueFilter : 'date' }, + { key : 'custom_period_end', label : 'PERIODS.END', comparitor : '<', valueFilter : 'date' }, { key : 'limit', label : 'FORM.LABELS.LIMIT' }]); voucherFilters.registerCustomFilters([ - { key: 'user_id', label: 'FORM.LABELS.USER' }, - { key: 'reference', label: 'FORM.LABELS.REFERENCE' }, - { key: 'dateFrom', label: 'FORM.LABELS.DATE', comparitor: '>', valueFilter: 'date' }, - { key: 'dateTo', label: 'FORM.LABELS.DATE', comparitor: '<', valueFilter: 'date' }, - { key: 'reversed', label: 'FORM.INFO.ANNULLED' }, - { key: 'description', label: 'FORM.LABELS.DESCRIPTION' }, - { key: 'type_ids', label: 'FORM.LABELS.TRANSACTION_TYPE' }]); - - - if(filterCache.filters){ + { key : 'user_id', label : 'FORM.LABELS.USER' }, + { key : 'reference', label : 'FORM.LABELS.REFERENCE' }, + { key : 'reversed', label : 'FORM.INFO.ANNULLED' }, + { key : 'description', label : 'FORM.LABELS.DESCRIPTION' }, + { key : 'entity_uuid', label : 'FORM.LABELS.ENTITY' }, + { key : 'type_ids', label : 'FORM.LABELS.TRANSACTION_TYPE' }]); + + + if (filterCache.filters) { voucherFilters.loadCache(filterCache.filters); } @@ -78,16 +77,16 @@ function VoucherService(Api, $http, TransactionTypeStore, Modal, function removeFilter(key) { voucherFilters.resetFilterState(key); - }; + } // load filters from cache function cacheFilters() { filterCache.filters = voucherFilters.formatCache(); - }; + } function loadCachedFilters() { voucherFilters.loadCache(filterCache.filters || {}); - }; + } // returns true if the key starts with an underscore function isInternalKey(key) { @@ -111,7 +110,6 @@ function VoucherService(Api, $http, TransactionTypeStore, Modal, * Wraps the prototype create method. */ function create(voucher) { - var v = angular.copy(voucher); // format items for posting, removing validation keys and unlinking old objects @@ -169,7 +167,7 @@ function VoucherService(Api, $http, TransactionTypeStore, Modal, // return serialized options return $httpParamSerializer(options); - }; + } /** * @function openSearchModal diff --git a/server/controllers/finance/vouchers.js b/server/controllers/finance/vouchers.js index 1259c3470d..4c166544dd 100644 --- a/server/controllers/finance/vouchers.js +++ b/server/controllers/finance/vouchers.js @@ -108,16 +108,18 @@ function lookupVoucher(vUuid) { } function find(options) { + db.convert(options, ['uuid', 'reference_uuid', 'entity_uuid']); + const filters = new FilterParser(options, { tableAlias : 'v', autoParseStatements : false }); const referenceStatement = `CONCAT_WS('.', '${entityIdentifier}', p.abbr, v.reference) = ?`; let typeIds = []; - if(options.type_ids) { + if (options.type_ids) { typeIds = typeIds.concat(options.type_ids); } const sql = ` - SELECT + SELECT BUID(v.uuid) as uuid, v.date, v.project_id, v.currency_id, v.amount, v.description, v.user_id, v.type_id, u.display_name, transaction_type.text, CONCAT_WS('.', '${entityIdentifier}', p.abbr, v.reference) AS reference, @@ -139,7 +141,10 @@ function find(options) { filters.fullText('description'); - filters.custom('type_ids', 'v.type_id IN (?)', typeIds); + // @todo - could this be improved + filters.custom('entity_uuid', 'v.uuid IN (SELECT DISTINCT voucher_uuid FROM voucher_item WHERE entity_uuid = ?)'); + + filters.custom('type_ids', 'v.type_id IN (?)', typeIds); // @todo - could this be improved filters.custom('account_id', 'v.uuid IN (SELECT DISTINCT voucher_uuid FROM voucher_item WHERE account_id = ?)');