diff --git a/.eslintrc.js b/.eslintrc.js
index ec04cf6980..cea8c1639f 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -20,7 +20,6 @@ module.exports = {
'dymo': true,
'Filer': true,
'logDebug': true,
- 'moment': true,
'Pikaday': true,
'PouchDB': true,
'Promise': true,
diff --git a/app/adapters/application.js b/app/adapters/application.js
index d186eed259..fb1408c8d8 100644
--- a/app/adapters/application.js
+++ b/app/adapters/application.js
@@ -1,15 +1,15 @@
import Ember from 'ember';
import { Adapter } from 'ember-pouch';
-import PouchAdapterUtils from 'hospitalrun/mixins/pouch-adapter-utils';
import uuid from 'npm:uuid';
const {
+ get,
run: {
bind
}
} = Ember;
-export default Adapter.extend(PouchAdapterUtils, {
+export default Adapter.extend({
database: Ember.inject.service(),
db: Ember.computed.reads('database.mainDB'),
@@ -192,6 +192,7 @@ export default Adapter.extend(PouchAdapterUtils, {
} else if (query.containsValue) {
return this._executeContainsSearch(store, type, query);
}
+ let database = get(this, 'database');
return new Ember.RSVP.Promise((resolve, reject) => {
let db = this.get('db');
try {
@@ -203,7 +204,7 @@ export default Adapter.extend(PouchAdapterUtils, {
};
db.list(`${mapReduce}/sort/${mapReduce}`, listParams, (err, response) => {
if (err) {
- this._pouchError(reject)(err);
+ reject(database.handleErrorResponse(err));
} else {
let responseJSON = JSON.parse(response.body);
this._handleQueryResponse(responseJSON, store, type).then(resolve, reject);
@@ -212,7 +213,7 @@ export default Adapter.extend(PouchAdapterUtils, {
} else {
db.query(mapReduce, queryParams, (err, response) => {
if (err) {
- this._pouchError(reject)(err);
+ reject(database.handleErrorResponse(err));
} else {
this._handleQueryResponse(response, store, type).then(resolve, reject);
}
@@ -221,16 +222,54 @@ export default Adapter.extend(PouchAdapterUtils, {
} else {
db.allDocs(queryParams, (err, response) => {
if (err) {
- this._pouchError(reject)(err);
+ reject(database.handleErrorResponse(err));
} else {
this._handleQueryResponse(response, store, type).then(resolve, reject);
}
});
}
} catch(err) {
- this._pouchError(reject)(err);
+ reject(database.handleErrorResponse(err));
}
}, 'findQuery in application-pouchdb-adapter');
}
+ },
+
+ createRecord(store, type, record) {
+ return this._checkForErrors(this._super(store, type, record));
+ },
+
+ findAll(store, type) {
+ return this._checkForErrors(this._super(store, type));
+ },
+
+ findMany(store, type, ids) {
+ return this._checkForErrors(this._super(store, type, ids));
+ },
+
+ findHasMany(store, record, link, rel) {
+ return this._checkForErrors(this._super(store, record, link, rel));
+ },
+
+ findRecord(store, type, id) {
+ return this._checkForErrors(this._super(store, type, id));
+ },
+
+ updateRecord(store, type, record) {
+ return this._checkForErrors(this._super(store, type, record));
+ },
+
+ deleteRecord(store, type, record) {
+ return this._checkForErrors(this._super(store, type, record));
+ },
+
+ _checkForErrors(callPromise) {
+ return new Ember.RSVP.Promise((resolve, reject) => {
+ callPromise.then(resolve, (err) => {
+ let database = get(this, 'database');
+ reject(database.handleErrorResponse(err));
+ });
+ });
}
+
});
diff --git a/app/adapters/user.js b/app/adapters/user.js
index 549c7e70c6..9963727fb6 100644
--- a/app/adapters/user.js
+++ b/app/adapters/user.js
@@ -1,6 +1,9 @@
import Ember from 'ember';
import DS from 'ember-data';
import UserSession from 'hospitalrun/mixins/user-session';
+
+const { get } = Ember;
+
export default DS.RESTAdapter.extend(UserSession, {
database: Ember.inject.service(),
session: Ember.inject.service(),
@@ -82,7 +85,12 @@ export default DS.RESTAdapter.extend(UserSession, {
*/
find(store, type, id) {
let findUrl = this.endpoint + id;
- return this.ajax(findUrl, 'GET');
+ return new Ember.RSVP.Promise((resolve, reject) => {
+ this.ajax(findUrl, 'GET').then(resolve, (error) => {
+ let database = get(this, 'database');
+ reject(database.handleErrorResponse(error));
+ });
+ });
},
headers: function() {
@@ -126,8 +134,13 @@ export default DS.RESTAdapter.extend(UserSession, {
}
data = this._cleanPasswordAttrs(data);
let putURL = `${this.endpoint}${Ember.get(record, 'id')}`;
- return this.ajax(putURL, 'PUT', {
- data
+ return new Ember.RSVP.Promise((resolve, reject) => {
+ this.ajax(putURL, 'PUT', {
+ data
+ }).then(resolve, (error) => {
+ let database = get(this, 'database');
+ reject(database.handleErrorResponse(error));
+ });
});
},
@@ -153,7 +166,12 @@ export default DS.RESTAdapter.extend(UserSession, {
}
};
let allURL = `${this.endpoint}_all_docs`;
- return this.ajax(allURL, 'GET', ajaxData);
+ return new Ember.RSVP.Promise((resolve, reject) => {
+ this.ajax(allURL, 'GET', ajaxData).then(resolve, (error) => {
+ let database = get(this, 'database');
+ reject(database.handleErrorResponse(error));
+ });
+ });
},
/**
diff --git a/app/admin/address/route.js b/app/admin/address/route.js
index df0b357566..f1fe6c8dcd 100644
--- a/app/admin/address/route.js
+++ b/app/admin/address/route.js
@@ -1,25 +1,31 @@
import AbstractEditRoute from 'hospitalrun/routes/abstract-edit-route';
import Ember from 'ember';
import { translationMacro as t } from 'ember-i18n';
+import UnauthorizedError from 'hospitalrun/utils/unauthorized-error';
+
export default AbstractEditRoute.extend({
hideNewButton: true,
newTitle: t('admin.address.newTitle'),
editTitle: t('admin.address.editTitle'),
model() {
- return new Ember.RSVP.Promise(function(resolve) {
- this.get('store').find('option', 'address_options').then(function(addressOptions) {
+ return new Ember.RSVP.Promise((resolve, reject) => {
+ this.get('store').find('option', 'address_options').then((addressOptions) => {
resolve(addressOptions);
- }, function() {
- let store = this.get('store');
- let newConfig = store.push(store.normalize('option', {
- id: 'address_options',
- value: {
- address1Label: this.get('i18n').t('admin.address.addressLabel'),
- address1Include: true
- }
- }));
- resolve(newConfig);
- }.bind(this));
- }.bind(this));
+ }, (err) => {
+ if (err instanceof UnauthorizedError) {
+ reject(err);
+ } else {
+ let store = this.get('store');
+ let newConfig = store.push(store.normalize('option', {
+ id: 'address_options',
+ value: {
+ address1Label: this.get('i18n').t('admin.address.addressLabel'),
+ address1Include: true
+ }
+ }));
+ resolve(newConfig);
+ }
+ });
+ });
}
});
diff --git a/app/admin/custom-forms/edit/controller.js b/app/admin/custom-forms/edit/controller.js
index 2b3783b60d..3e1c525e1e 100644
--- a/app/admin/custom-forms/edit/controller.js
+++ b/app/admin/custom-forms/edit/controller.js
@@ -75,6 +75,7 @@ export default AbstractEditController.extend({
}),
formTypeValues: [
+ 'operativePlan',
'patient',
'socialwork',
'visit'
diff --git a/app/admin/loaddb/route.js b/app/admin/loaddb/route.js
index 6ddfc2b034..02bacd99ce 100644
--- a/app/admin/loaddb/route.js
+++ b/app/admin/loaddb/route.js
@@ -2,18 +2,24 @@ import AbstractEditRoute from 'hospitalrun/routes/abstract-edit-route';
import Ember from 'ember';
import { translationMacro as t } from 'ember-i18n';
import UserSession from 'hospitalrun/mixins/user-session';
+
+const { get, inject } = Ember;
+
export default AbstractEditRoute.extend(UserSession, {
hideNewButton: true,
editTitle: t('admin.loaddb.editTitle'),
+ database: inject.service(),
+
beforeModel() {
if (!this.currentUserCan('load_db')) {
this.transitionTo('application');
}
},
- // No model needed for import.
+ // Make sure database is available for import
model() {
- return Ember.RSVP.resolve(Ember.Object.create({}));
+ let database = get(this, 'database');
+ return database.getDBInfo().catch((err) => this.send('error', database.handleErrorResponse(err)));
}
});
diff --git a/app/admin/lookup/route.js b/app/admin/lookup/route.js
index b9daf60046..7676703b14 100644
--- a/app/admin/lookup/route.js
+++ b/app/admin/lookup/route.js
@@ -4,7 +4,7 @@ export default AbstractIndexRoute.extend({
hideNewButton: true,
pageTitle: t('admin.lookup.pageTitle'),
model() {
- return this.store.findAll('lookup');
+ return this.store.findAll('lookup').catch((error) => this.send('error', error));
},
afterModel(model) {
diff --git a/app/admin/roles/controller.js b/app/admin/roles/controller.js
index 9090003368..dba825355c 100644
--- a/app/admin/roles/controller.js
+++ b/app/admin/roles/controller.js
@@ -48,8 +48,11 @@ export default AbstractEditController.extend(UserRoles, UserSession, {
name: 'patients',
capabilities: [
'patients',
+ 'addAllergy',
'addDiagnosis',
'addNote',
+ 'addOperativePlan',
+ 'addOperationReport',
'addPhoto',
'addPatient',
'addProcedure',
@@ -163,7 +166,6 @@ export default AbstractEditController.extend(UserRoles, UserSession, {
Object.keys(defaultCapabilities).forEach((capability) => {
let capabilityRoles = defaultCapabilities[capability];
if (capabilityRoles.includes(role)) {
- console.log(`Role has capability: ${capability}`);
this.set(capability.camelize(), true);
} else {
this.set(capability.camelize(), false);
diff --git a/app/appointments/calendar/controller.js b/app/appointments/calendar/controller.js
new file mode 100644
index 0000000000..a9ba6ed23c
--- /dev/null
+++ b/app/appointments/calendar/controller.js
@@ -0,0 +1,112 @@
+import AppointmentIndexController from 'hospitalrun/appointments/index/controller';
+import AppointmentStatuses from 'hospitalrun/mixins/appointment-statuses';
+import moment from 'moment';
+import VisitTypes from 'hospitalrun/mixins/visit-types';
+import SelectValues from 'hospitalrun/utils/select-values';
+import Ember from 'ember';
+
+const {
+ computed,
+ computed: {
+ alias
+ },
+ get,
+ inject,
+ isEmpty,
+ set
+} = Ember;
+
+export default AppointmentIndexController.extend(AppointmentStatuses, VisitTypes, {
+ appointmentType: null,
+ endDate: null,
+ location: null,
+ provider: null,
+ queryParams: ['appointmentType', 'endDate', 'provider', 'status', 'startDate', 'location', 'viewType'],
+ startDate: null,
+ status: null,
+ viewType: 'agendaWeek',
+
+ appointmentsController: inject.controller('appointments'),
+ locations: alias('appointmentsController.locationList.value'),
+ physicians: alias('appointmentsController.physicianList.value'),
+
+ calendarDate: computed('startDate', function() {
+ let startDate = get(this, 'startDate');
+ if (!isEmpty(startDate)) {
+ return moment(parseInt(startDate));
+ }
+ }),
+
+ locationList: computed('locations', function() {
+ return SelectValues.selectValues(get(this, 'locations'), true);
+ }),
+
+ physicianList: computed('physicians', function() {
+ return SelectValues.selectValues(get(this, 'physicians'), true);
+ }),
+
+ _getSelectedFilteringCriteria() {
+ let rawCriteria = {
+ status: get(this, 'model.selectedStatus'),
+ type: get(this, 'model.selectedAppointmentType'),
+ provider: get(this, 'model.selectedProvider'),
+ location: get(this, 'model.selectedLocation')
+ };
+
+ return {
+ status: isEmpty(rawCriteria.status) ? null : rawCriteria.status,
+ type: isEmpty(rawCriteria.type) ? null : rawCriteria.type,
+ provider: isEmpty(rawCriteria.provider) ? null : rawCriteria.provider,
+ location: isEmpty(rawCriteria.location) ? null : rawCriteria.location
+ };
+ },
+
+ actions: {
+ clearFilteringCriteria() {
+ set(this, 'model.selectedStatus', null);
+ set(this, 'model.selectedAppointmentType', null);
+ set(this, 'model.selectedProvider', null);
+ set(this, 'model.selectedLocation', null);
+ this.send('filter');
+ },
+
+ createNewAppointment(dateClicked) {
+ let newAppointment = this.store.createRecord('appointment', {
+ appointmentType: 'Admission',
+ allDay: false,
+ selectPatient: true,
+ startDate: dateClicked.local().toDate()
+ });
+ this.send('editAppointment', newAppointment);
+ },
+
+ filter() {
+ let criteria = this._getSelectedFilteringCriteria();
+ this.setProperties({
+ appointmentType: criteria.type,
+ provider: criteria.provider,
+ status: criteria.status,
+ location: criteria.location
+ });
+ },
+
+ handleVisualConfigurationChanged(newConfiguration) {
+ this.setProperties(newConfiguration);
+ },
+
+ navigateToAppointment(calendarEvent) {
+ this.send('editAppointment', calendarEvent.referencedAppointment);
+ },
+
+ updateAppointment(calendarEvent) {
+ let appointmentToUpdate = calendarEvent.referencedAppointment;
+ let newEnd = calendarEvent.end.local().toDate();
+ let newStart = calendarEvent.start.local().toDate();
+ set(appointmentToUpdate, 'startDate', newStart);
+ set(appointmentToUpdate, 'endDate', newEnd);
+ appointmentToUpdate.save().catch((error) => {
+ this.send('error', error, 'appointments.calendar');
+ });
+ }
+ }
+});
diff --git a/app/appointments/calendar/route.js b/app/appointments/calendar/route.js
new file mode 100644
index 0000000000..45c165e759
--- /dev/null
+++ b/app/appointments/calendar/route.js
@@ -0,0 +1,98 @@
+import AppointmentIndexRoute from 'hospitalrun/appointments/index/route';
+import Ember from 'ember';
+import { translationMacro as t } from 'ember-i18n';
+
+const {
+ get,
+ isEmpty
+} = Ember;
+
+export default AppointmentIndexRoute.extend({
+ dateIntervalEnd: null,
+ dateIntervalStart: null,
+ editReturn: 'appointments.calendar',
+ filterParams: ['appointmentType', 'provider', 'status', 'location'],
+ modelName: 'appointment',
+ pageTitle: t('appointments.calendarTitle'),
+
+ queryParams: {
+ appointmentType: { refreshModel: true },
+ endDate: { refreshModel: true },
+ provider: { refreshModel: true },
+ status: { refreshModel: true },
+ startDate: { refreshModel: true },
+ location: { refreshModel: true },
+ viewType: { refreshModel: false }
+ },
+
+ model(params) {
+ return this._super(params)
+ .then(this._createCalendarEvents.bind(this))
+ .then(function(calendarEvents) {
+ calendarEvents.selectedAppointmentType = params.appointmentType;
+ calendarEvents.selectedProvider = params.provider;
+ calendarEvents.selectedStatus = params.status;
+ calendarEvents.selectedLocation = params.location;
+ return calendarEvents;
+ });
+ },
+
+ _createCalendarEvent(appointment) {
+ let title = get(appointment, 'patient.displayName');
+ let provider = get(appointment, 'provider');
+ if (!isEmpty(provider)) {
+ title = `${title}\n${provider}`;
+ }
+ let event = {
+ allDay: get(appointment, 'allDay'),
+ title,
+ start: get(appointment, 'startDate'),
+ end: get(appointment, 'endDate'),
+ referencedAppointment: appointment
+ };
+ let location = get(appointment, 'location');
+ if (isEmpty(location)) {
+ let i18n = get(this, 'i18n');
+ location = i18n.t('appointments.labels.noLocation').toString();
+ }
+ event.resourceId = location.toLowerCase();
+ return event;
+ },
+
+ _createCalendarEvents(appointments) {
+ let events = [];
+ let resources = [];
+ appointments.forEach((appointment) => {
+ let event = this._createCalendarEvent(appointment);
+ events.push(event);
+ let resourceId = get(event, 'resourceId');
+ if (!resources.findBy('id', resourceId)) {
+ resources.push({
+ id: resourceId,
+ title: get(event, 'referencedAppointment.location')
+ });
+ }
+ });
+ return {
+ events,
+ resources
+ };
+ },
+
+ _modelQueryParams(params) {
+ let { endDate, startDate } = params;
+
+ if (endDate === null || startDate === null) {
+ return this._super(params);
+ }
+ let searchOptions = {
+ startkey: [parseInt(startDate), parseInt(startDate), this._getMinPouchId()],
+ endkey: [parseInt(endDate), parseInt(endDate), this._getMaxPouchId()]
+ };
+
+ return {
+ options: searchOptions,
+ mapReduce: 'appointments_by_date'
+ };
+ }
+});
diff --git a/app/appointments/calendar/template.hbs b/app/appointments/calendar/template.hbs
new file mode 100644
index 0000000000..081002a286
--- /dev/null
+++ b/app/appointments/calendar/template.hbs
@@ -0,0 +1,42 @@
+
+
+ {{#em-form model=model submitButton=false}}
+
+ {{em-select class="col-sm-3 form-input-group"
+ label=(t "labels.status")
+ property="selectedStatus"
+ content=appointmentStatusesWithEmpty
+ }}
+ {{em-select class="col-sm-3 form-input-group"
+ label=(t "labels.type")
+ property="selectedAppointmentType"
+ content=visitTypesWithEmpty
+ }}
+ {{em-select class="col-sm-3 form-input-group"
+ label=(t 'labels.with')
+ property="selectedProvider"
+ content=physicianList
+ }}
+ {{em-select class="col-sm-3 form-input-group"
+ label=(t 'labels.location')
+ property="selectedLocation"
+ content=locationList
+ }}
+
+ {{/em-form}}
+
+ {{calendar-control events=model.events
+ defaultDate=calendarDate
+ defaultView=viewType
+ onDayClick=(action "createNewAppointment")
+ onEventClick=(action "navigateToAppointment")
+ onEventDrop=(action "updateAppointment")
+ onEventResize=(action "updateAppointment")
+ onVisualConfigurationChanged=(action "handleVisualConfigurationChanged")
+ userCanEdit=canEdit
+ }}
+
+
diff --git a/app/appointments/edit/controller.js b/app/appointments/edit/controller.js
index 06c20e1439..121815626f 100644
--- a/app/appointments/edit/controller.js
+++ b/app/appointments/edit/controller.js
@@ -4,58 +4,86 @@ import Ember from 'ember';
import PatientSubmodule from 'hospitalrun/mixins/patient-submodule';
import VisitTypes from 'hospitalrun/mixins/visit-types';
+const {
+ computed,
+ computed: {
+ alias
+ },
+ get,
+ inject,
+ set
+} = Ember;
+
export default AbstractEditController.extend(AppointmentStatuses, PatientSubmodule, VisitTypes, {
- appointmentsController: Ember.inject.controller('appointments'),
findPatientVisits: false,
+ updateCapability: 'add_appointment',
- locationList: Ember.computed.alias('appointmentsController.locationList'),
-
- lookupListsToUpdate: [{
- name: 'physicianList',
- property: 'model.provider',
- id: 'physician_list'
- }, {
- name: 'locationList',
- property: 'model.location',
- id: 'visit_location_list'
- }],
-
- physicianList: Ember.computed.alias('appointmentsController.physicianList'),
- showTime: function() {
- let allDay = this.get('model.allDay');
- let isAdmissionAppointment = this.get('isAdmissionAppointment');
- return (!allDay && isAdmissionAppointment);
- }.property('model.allDay', 'isAdmissionAppointment'),
- visitTypesList: Ember.computed.alias('appointmentsController.visitTypesList'),
+ appointmentsController: inject.controller('appointments'),
+ physicianList: alias('appointmentsController.physicianList'),
+ surgeryLocationList: alias('appointmentsController.surgeryLocationList'),
+ visitLocationList: alias('appointmentsController.locationList'),
+ visitTypesList: alias('appointmentsController.visitTypesList'),
- cancelAction: function() {
- let returnTo = this.get('model.returnTo');
+ cancelAction: computed('model.returnTo', function() {
+ let returnTo = get(this, 'model.returnTo');
if (Ember.isEmpty(returnTo)) {
return this._super();
} else {
return 'returnTo';
}
- }.property('model.returnTo'),
+ }),
- isAdmissionAppointment: function() {
- let model = this.get('model');
- let appointmentType = model.get('appointmentType');
+ isAdmissionAppointment: computed('model.appointmentType', function() {
+ let model = get(this, 'model');
+ let appointmentType = get(model, 'appointmentType');
let isAdmissionAppointment = (appointmentType === 'Admission');
return isAdmissionAppointment;
- }.property('model.appointmentType'),
+ }),
- updateCapability: 'add_appointment',
+ lookupListsToUpdate: computed('model.appointmentType', function() {
+ let appointmentType = get(this, 'model.appointmentType');
+ let lists = [{
+ name: 'physicianList',
+ property: 'model.provider',
+ id: 'physician_list'
+ }];
+ if (appointmentType === 'Surgery') {
+ lists.push({
+ name: 'visitLocationList',
+ property: 'model.location',
+ id: 'visit_location_list'
+ });
+ } else {
+ lists.push({
+ name: 'surgeryLocationList',
+ property: 'model.location',
+ id: 'procedure_locations'
+ });
+ }
+ }),
+
+ showTime: computed('model.allDay', 'isAdmissionAppointment', function() {
+ let allDay = get(this, 'model.allDay');
+ let isAdmissionAppointment = get(this, 'isAdmissionAppointment');
+ return (!allDay && isAdmissionAppointment);
+ }),
- afterUpdate() {
- this.send(this.get('cancelAction'));
+ afterUpdate(model) {
+ let i18n = get(this, 'i18n');
+ let patientInfo = {
+ patient: get(model, 'patient.displayName')
+ };
+ let message = i18n.t('appointments.messages.appointmentSaved', patientInfo);
+ let title = i18n.t('appointments.titles.appointmentSaved');
+ this.displayAlert(title, message);
},
actions: {
appointmentTypeChanged(appointmentType) {
- let model = this.get('model');
- model.set('appointmentType', appointmentType);
- let isAdmissionAppointment = this.get('isAdmissionAppointment');
- model.set('allDay', isAdmissionAppointment);
+ let model = get(this, 'model');
+ set(model, 'appointmentType', appointmentType);
+ let isAdmissionAppointment = get(this, 'isAdmissionAppointment');
+ set(model, 'allDay', isAdmissionAppointment);
}
}
});
diff --git a/app/appointments/edit/route.js b/app/appointments/edit/route.js
index be20c36b46..d9f6433b6c 100644
--- a/app/appointments/edit/route.js
+++ b/app/appointments/edit/route.js
@@ -1,19 +1,62 @@
import AbstractEditRoute from 'hospitalrun/routes/abstract-edit-route';
import Ember from 'ember';
+import moment from 'moment';
import PatientListRoute from 'hospitalrun/mixins/patient-list-route';
import { translationMacro as t } from 'ember-i18n';
+const {
+ get,
+ RSVP: {
+ resolve
+ }
+} = Ember;
+
export default AbstractEditRoute.extend(PatientListRoute, {
editTitle: t('appointments.editTitle'),
modelName: 'appointment',
+ newButtonText: t('appointments.buttons.newButton'),
+
newTitle: t('appointments.newTitle'),
- getNewData() {
- return Ember.RSVP.resolve({
+ getNewData(params) {
+ let idParam = get(this, 'idParam');
+ let newData = {
appointmentType: 'Admission',
allDay: true,
selectPatient: true,
startDate: new Date()
- });
+ };
+ if (!Ember.isEmpty(idParam) && params[idParam] === 'newsurgery') {
+ newData.appointmentType = 'Surgery';
+ newData.allDay = false;
+ newData.endDate = moment().add('1', 'hours').toDate();
+ newData.returnTo = 'appointments.theater';
+ }
+ return resolve(newData);
+ },
+
+ getScreenTitle(model) {
+ let appointmentType = get(model, 'appointmentType');
+ if (appointmentType === 'Surgery') {
+ let i18n = get(this, 'i18n');
+ let isNew = get(model, 'isNew');
+ if (isNew) {
+ return i18n.t('appointments.titles.newSurgicalAppointment');
+ } else {
+ return i18n.t('appointments.titles.editSurgicalAppointment');
+ }
+ } else {
+ return this._super(model);
+ }
+ },
+
+ model(params) {
+ let idParam = this.get('idParam');
+ let modelId = params[idParam];
+ if (!Ember.isEmpty(idParam) && (modelId.indexOf('new') === 0)) {
+ return this._createNewRecord(params);
+ } else {
+ return this._super(params);
+ }
}
});
diff --git a/app/appointments/edit/template.hbs b/app/appointments/edit/template.hbs
index 355b72aff5..8f62114fac 100644
--- a/app/appointments/edit/template.hbs
+++ b/app/appointments/edit/template.hbs
@@ -12,35 +12,49 @@
{{else}}
{{date-time-picker datePickerClass="required test-appointment-date" label=(t 'labels.date') model=model}}
{{/if}}
- {{em-checkbox label=(t 'labels.allDay') property="allDay" class="col-sm-2"}}
+ {{em-checkbox label=(t 'labels.allDay') property="allDay" class="col-sm-2 appointment-all-day"}}
-
-
-
- {{select-or-typeahead className="col-sm-6 required test-appointment-location" property="location"
- label=(t 'labels.location') list=locationList
- selection=model.location
- }}
- {{em-select class="form-input-group col-sm-3 test-appointment-status" property="status"
- label=(t 'labels.status') content=appointmentStatuses
- }}
-
+ {{else}}
+
+
+
+ {{select-list
+ content=visitTypes
+ optionLabelPath='value'
+ optionValuePath='id'
+ value=model.appointmentType
+ class='form-control'
+ id='appointmentType'
+ action=(action 'appointmentTypeChanged')
+ }}
+
+ {{select-or-typeahead className="col-sm-6 test-appointment-with" property="provider"
+ label=(t 'labels.with') list=physicianList
+ selection=model.provider
+ }}
+
+
+ {{select-or-typeahead className="col-sm-6 test-appointment-location" property="location"
+ label=(t 'labels.location') list=visitLocationList
+ selection=model.location
+ }}
+ {{em-select class="form-input-group col-sm-3 test-appointment-status" property="status"
+ label=(t 'labels.status') content=appointmentStatuses
+ }}
+
+ {{/if}}
{{em-text label=(t 'labels.notes') property="notes" rows=3 }}
{{/em-form}}
{{/edit-panel}}
diff --git a/app/appointments/index/route.js b/app/appointments/index/route.js
index 29b5d3e612..30d0494aca 100644
--- a/app/appointments/index/route.js
+++ b/app/appointments/index/route.js
@@ -1,9 +1,11 @@
import AbstractIndexRoute from 'hospitalrun/routes/abstract-index-route';
+import moment from 'moment';
import { translationMacro as t } from 'ember-i18n';
export default AbstractIndexRoute.extend({
editReturn: 'appointments.index',
modelName: 'appointment',
+ newButtonText: t('appointments.buttons.newButton'),
pageTitle: t('appointments.thisWeek'),
_getStartKeyFromItem(item) {
diff --git a/app/appointments/route.js b/app/appointments/route.js
index 1651713d2a..a16f69f3be 100644
--- a/app/appointments/route.js
+++ b/app/appointments/route.js
@@ -24,7 +24,7 @@ export default AbstractModuleRoute.extend(UserSession, {
visitProps.returnTo = 'appointments';
this.transitionTo('visits.edit', 'checkin').then(function(newRoute) {
newRoute.currentModel.setProperties(visitProps);
- newRoute.controller.getPatientDiagnoses(patient);
+ newRoute.controller.getPatientDiagnoses(patient, newRoute.currentModel);
}.bind(this));
}
},
@@ -35,6 +35,9 @@ export default AbstractModuleRoute.extend(UserSession, {
}, {
name: 'locationList',
findArgs: ['lookup', 'visit_location_list']
+ }, {
+ name: 'surgeryLocationList',
+ findArgs: ['lookup', 'procedure_locations']
}, {
name: 'visitTypesList',
findArgs: ['lookup', 'visit_types']
diff --git a/app/appointments/search/route.js b/app/appointments/search/route.js
index 542b8ee2d7..cf3639e440 100644
--- a/app/appointments/search/route.js
+++ b/app/appointments/search/route.js
@@ -1,6 +1,7 @@
import AppointmentIndexRoute from 'hospitalrun/appointments/index/route';
import DateFormat from 'hospitalrun/mixins/date-format';
import Ember from 'ember';
+import moment from 'moment';
import { translationMacro as t } from 'ember-i18n';
export default AppointmentIndexRoute.extend(DateFormat, {
diff --git a/app/appointments/search/template.hbs b/app/appointments/search/template.hbs
index ce674df356..aaa2ca7909 100644
--- a/app/appointments/search/template.hbs
+++ b/app/appointments/search/template.hbs
@@ -4,15 +4,13 @@
{{#em-form model=model submitButton=false }}
{{date-picker property="selectedStartingDate" label=(t "appointments.labels.selectedStartingDate")class="col-sm-3"}}
- {{em-select class="col-sm-3" property="selectedStatus"
+ {{em-select class="col-sm-3 form-input-group" property="selectedStatus"
label=(t "labels.status") content=appointmentStatusesWithEmpty
}}
-
-
- {{em-select class="col-sm-3" label=(t "labels.type")
+ {{em-select class="col-sm-3 form-input-group" label=(t "labels.type")
property="selectedAppointmentType" content=visitTypesWithEmpty
}}
- {{em-select class="col-sm-3" property="selectedProvider"
+ {{em-select class="col-sm-3 form-input-group" property="selectedProvider"
label=(t 'labels.with') content=physicianList
}}
diff --git a/app/appointments/theater/controller.js b/app/appointments/theater/controller.js
new file mode 100644
index 0000000000..8582ec23ca
--- /dev/null
+++ b/app/appointments/theater/controller.js
@@ -0,0 +1,21 @@
+import AppointmenCalendarController from 'hospitalrun/appointments/calendar/controller';
+
+export default AppointmenCalendarController.extend({
+ dayGroupByResource: {
+ day: {
+ groupByResource: true
+ }
+ },
+
+ actions: {
+ createNewAppointment(dateClicked) {
+ let newAppointment = this.store.createRecord('appointment', {
+ appointmentType: 'Surgery',
+ selectPatient: true,
+ startDate: dateClicked.local().toDate(),
+ endDate: dateClicked.add('1', 'hours').local().toDate()
+ });
+ this.send('editAppointment', newAppointment);
+ }
+ }
+});
diff --git a/app/appointments/theater/route.js b/app/appointments/theater/route.js
new file mode 100644
index 0000000000..1c2b01af10
--- /dev/null
+++ b/app/appointments/theater/route.js
@@ -0,0 +1,20 @@
+import AppointmenCalendarRoute from 'hospitalrun/appointments/calendar/route';
+import { translationMacro as t } from 'ember-i18n';
+
+export default AppointmenCalendarRoute.extend({
+ editReturn: 'appointments.theater',
+ newButtonText: t('appointments.buttons.scheduleSurgery'),
+ pageTitle: t('appointments.titles.theaterSchedule'),
+
+ _modelQueryParams(params) {
+ let queryParams = this._super(params);
+ queryParams.mapReduce = 'surgical_appointments_by_date';
+ return queryParams;
+ },
+
+ actions: {
+ newItem() {
+ this.transitionTo('appointments.edit', 'newsurgery');
+ }
+ }
+});
diff --git a/app/appointments/theater/template.hbs b/app/appointments/theater/template.hbs
new file mode 100644
index 0000000000..15309f8482
--- /dev/null
+++ b/app/appointments/theater/template.hbs
@@ -0,0 +1,39 @@
+
+
+ {{#em-form model=model submitButton=false}}
+
+ {{em-select class="col-sm-3 form-input-group"
+ label=(t "labels.status")
+ property="selectedStatus"
+ content=appointmentStatusesWithEmpty
+ }}
+ {{em-select class="col-sm-3 form-input-group"
+ label=(t 'labels.with')
+ property="selectedProvider"
+ content=physicianList
+ }}
+ {{em-select class="col-sm-3 form-input-group"
+ label=(t 'labels.location')
+ property="selectedLocation"
+ content=locationList
+ }}
+
+ {{/em-form}}
+
+ {{calendar-control events=model.events
+ defaultDate=calendarDate
+ defaultView=viewType
+ onDayClick=(action "createNewAppointment")
+ onEventClick=(action "navigateToAppointment")
+ onEventDrop=(action "updateAppointment")
+ onEventResize=(action "updateAppointment")
+ onVisualConfigurationChanged=(action "handleVisualConfigurationChanged")
+ resources=model.resources
+ userCanEdit=canEdit
+ views=dayGroupByResource
+ }}
+
+
diff --git a/app/appointments/today/route.js b/app/appointments/today/route.js
index 99bf32d9a1..d49223a7a0 100644
--- a/app/appointments/today/route.js
+++ b/app/appointments/today/route.js
@@ -1,4 +1,5 @@
import AppointmentIndexRoute from 'hospitalrun/appointments/index/route';
+import moment from 'moment';
import { translationMacro as t } from 'ember-i18n';
export default AppointmentIndexRoute.extend({
editReturn: 'appointments.today',
diff --git a/app/components/calendar-control.js b/app/components/calendar-control.js
new file mode 100644
index 0000000000..b8337fd15d
--- /dev/null
+++ b/app/components/calendar-control.js
@@ -0,0 +1,70 @@
+import Ember from 'ember';
+import moment from 'moment';
+
+const {
+ get,
+ isEmpty,
+ set
+} = Ember;
+
+export default Ember.Component.extend({
+ calendarHeader: {
+ center: 'agendaDay,agendaWeek,month',
+ left: 'title',
+ right: 'today prev,next'
+ },
+ defaultDate: null,
+ defaultView: 'agendaWeek',
+ height: 500,
+ onDayClick: null,
+ onEventClick: null,
+ onEventDrop: null,
+ onEventResize: null,
+ userCanEdit: false,
+
+ visualConfiguration: {
+ endDate: null,
+ startDate: null,
+ viewType: null
+ },
+
+ /**
+ * FullCalendar gives the start and end timestamps based on UTC (eg start at
+ * midnight UTC and end at 11:59PM UTC), but for our purposes we want to show
+ * users events that start at midnight their timezone and end at 11:59PM in
+ * their timezone. This function takes a UTC timestamps from fullcalendar
+ * and returns the timestamp in the users timezone (eg midnight UTC is returned
+ * as midnight EST for EST users).
+ * @param timestamp A number representing the milliseconds elapsed between
+ * 1 January 1970 00:00:00 UTC and the given date.
+ * @return String timestamp in users timezone.
+ */
+ _convertDateFromUTCToLocal(date) {
+ return moment(date.utc().format('YYYY-MM-DD HH:mm:ss')).valueOf();
+ },
+
+ actions: {
+ handleRenderingComplete(view) {
+ function configurationsDiffer(firstConfig, secondConfig) {
+ return firstConfig.startDate !== secondConfig.startDate
+ || firstConfig.endDate !== secondConfig.endDate
+ || firstConfig.viewType !== secondConfig.viewType;
+ }
+
+ let currentConfiguration = get(this, 'visualConfiguration');
+
+ let newConfiguration = {
+ startDate: this._convertDateFromUTCToLocal(view.intervalStart),
+ endDate: this._convertDateFromUTCToLocal(view.intervalEnd),
+ viewType: view.name
+ };
+
+ if (isEmpty(currentConfiguration.startDate) && isEmpty(currentConfiguration.endDate)) {
+ set(this, 'visualConfiguration', newConfiguration);
+ } else if (configurationsDiffer(currentConfiguration, newConfiguration)) {
+ set(this, 'visualConfiguration', newConfiguration);
+ get(this, 'onVisualConfigurationChanged')(newConfiguration);
+ }
+ }
+ }
+});
diff --git a/app/components/date-time-picker.js b/app/components/date-time-picker.js
index b6c47c0014..4271f4119f 100644
--- a/app/components/date-time-picker.js
+++ b/app/components/date-time-picker.js
@@ -1,4 +1,5 @@
import Ember from 'ember';
+import moment from 'moment';
const {
computed,
diff --git a/app/components/inventory-typeahead.js b/app/components/inventory-typeahead.js
index a664b8ca5c..d701aea4fa 100644
--- a/app/components/inventory-typeahead.js
+++ b/app/components/inventory-typeahead.js
@@ -5,6 +5,7 @@ export default TypeAhead.extend({
displayKey: 'name',
showQuantity: true,
i18n: Ember.inject.service(),
+ store: Ember.inject.service(),
_mapInventoryItems(item) {
let returnObj = {};
@@ -43,5 +44,19 @@ export default TypeAhead.extend({
bloodhound.clear();
bloodhound.add(content.map(this._mapInventoryItems.bind(this)));
}
- }.observes('content.[]')
+ }.observes('content.[]'),
+
+ itemSelected(selectedInventoryItem) {
+ this._super();
+ let store = this.get('store');
+ if (!Ember.isEmpty(selectedInventoryItem)) {
+ store.find('inventory', selectedInventoryItem.id).then((inventoryItem) => {
+ let model = this.get('model');
+ model.set('inventoryItem', inventoryItem);
+ Ember.run.once(this, function() {
+ model.validate().catch(Ember.K);
+ });
+ });
+ }
+ }
});
diff --git a/app/components/medication-allergy.js b/app/components/medication-allergy.js
index 441a1463a9..c79197df32 100644
--- a/app/components/medication-allergy.js
+++ b/app/components/medication-allergy.js
@@ -1,7 +1,9 @@
import Ember from 'ember';
const {
- computed
+ computed,
+ get,
+ isEmpty
} = Ember;
export default Ember.Component.extend({
@@ -35,6 +37,14 @@ export default Ember.Component.extend({
}
}),
+ showAllergies: computed('canAddAllergy', 'patient.allergies.[]', {
+ get() {
+ let canAddAllergy = get(this, 'canAddAllergy');
+ let patientAllergies = get(this, 'patient.allergies');
+ return canAddAllergy || !isEmpty(patientAllergies);
+ }
+ }),
+
modalTitle: Ember.computed('currentAllergy', function() {
let currentAllergy = this.get('currentAllergy');
let i18n = this.get('i18n');
diff --git a/app/components/modal-dialog.js b/app/components/modal-dialog.js
index da40a2dcf8..23b5c0d0b9 100644
--- a/app/components/modal-dialog.js
+++ b/app/components/modal-dialog.js
@@ -40,6 +40,7 @@ export default Ember.Component.extend({
$modal.on('hidden.bs.modal', function() {
this.sendAction('closeModalAction');
+ this.sendAction('cancelAction');
}.bind(this));
},
diff --git a/app/components/operative-procedures.js b/app/components/operative-procedures.js
new file mode 100644
index 0000000000..a9749e0c26
--- /dev/null
+++ b/app/components/operative-procedures.js
@@ -0,0 +1,44 @@
+import Ember from 'ember';
+
+const {
+ computed,
+ isEmpty,
+ get,
+ set
+} = Ember;
+
+export function addProcedure(model) {
+ let procedures = get(model, 'procedures');
+ let description = get(model, 'procedureDescription');
+ if (!isEmpty(description)) {
+ procedures.addObject({
+ description
+ });
+ set(model, 'procedureDescription', null);
+ }
+}
+
+export default Ember.Component.extend({
+ model: null,
+ procedureList: null,
+ haveProcedures: computed('model.procedures.[]', {
+ get() {
+ return !isEmpty(get(this, 'model.procedures'));
+ }
+ }),
+
+ actions: {
+ addProcedure() {
+ let model = get(this, 'model');
+ addProcedure(model);
+ },
+
+ deleteProcedure(procedureToDelete) {
+ let model = get(this, 'model');
+ let procedures = get(model, 'procedures');
+ procedures.removeObject(procedureToDelete);
+ model.validate();
+ }
+ }
+
+});
diff --git a/app/components/patient-diagnosis.js b/app/components/patient-diagnosis.js
new file mode 100644
index 0000000000..1a7219ad50
--- /dev/null
+++ b/app/components/patient-diagnosis.js
@@ -0,0 +1,83 @@
+import Ember from 'ember';
+import PatientDiagnosis from 'hospitalrun/mixins/patient-diagnosis';
+import { translationMacro as t } from 'ember-i18n';
+import UserSession from 'hospitalrun/mixins/user-session';
+
+const {
+ computed,
+ get
+} = Ember;
+
+const DIAGNOSIS_KEYS = [
+ 'diagnosisContainer',
+ 'hideInActiveDiagnoses',
+ 'diagnosisContainer.diagnoses.@each.active',
+ 'diagnosisContainer.diagnoses.@each.secondaryDiagnosis'
+];
+
+export default Ember.Component.extend(PatientDiagnosis, UserSession, {
+ i18n: Ember.inject.service(),
+ allowAddDiagnosis: false,
+ diagnosisContainer: null,
+ diagnosisProperty: null,
+ diagnosisList: null,
+ editDiagnosisAction: 'editDiagnosis',
+ hideInActiveDiagnoses: true,
+ showAddDiagnosisAction: 'showAddDiagnosis',
+ primaryDiagnosisLabel: t('patients.labels.primaryDiagnosis'),
+ secondaryDiagnosisLabel: t('patients.labels.secondaryDiagnosis'),
+
+ canAddDiagnosis: computed('allowAddDiagnosis', {
+ get() {
+ let allowAddDiagnosis = get(this, 'allowAddDiagnosis');
+ return allowAddDiagnosis && this.currentUserCan('add_diagnosis');
+ }
+ }),
+
+ havePrimaryDiagnoses: computed('primaryDiagnoses.length', {
+ get() {
+ let primaryDiagnosesLength = this.get('primaryDiagnoses.length');
+ return (primaryDiagnosesLength > 0);
+ }
+ }),
+
+ haveSecondaryDiagnoses: computed('secondaryDiagnoses.length', {
+ get() {
+ let secondaryDiagnosesLength = this.get('secondaryDiagnoses.length');
+ return (secondaryDiagnosesLength > 0);
+ }
+ }),
+
+ primaryDiagnoses: computed(...DIAGNOSIS_KEYS, {
+ get() {
+ let diagnosisContainer = this.get('diagnosisContainer');
+ let hideInActiveDiagnoses = this.get('hideInActiveDiagnoses');
+ return this.getDiagnoses(diagnosisContainer, hideInActiveDiagnoses, false);
+ }
+ }),
+
+ secondaryDiagnoses: computed(...DIAGNOSIS_KEYS, {
+ get() {
+ let diagnosisContainer = this.get('diagnosisContainer');
+ let hideInActiveDiagnoses = this.get('hideInActiveDiagnoses');
+ return this.getDiagnoses(diagnosisContainer, hideInActiveDiagnoses, true);
+ }
+ }),
+
+ showPrimaryDiagnoses: computed('canAddDiagnosis', 'havePrimaryDiagnoses', {
+ get() {
+ return this.get('canAddDiagnosis') || this.get('havePrimaryDiagnoses');
+ }
+ }),
+
+ actions: {
+ editDiagnosis(diagnosis) {
+ this.sendAction('editDiagnosisAction', diagnosis);
+ },
+
+ showAddDiagnosis() {
+ this.sendAction('showAddDiagnosisAction');
+ }
+ }
+
+});
diff --git a/app/components/patient-summary.js b/app/components/patient-summary.js
index 40a58b8bd4..b62e6db11f 100644
--- a/app/components/patient-summary.js
+++ b/app/components/patient-summary.js
@@ -1,45 +1,50 @@
import Ember from 'ember';
-import PatientDiagnosis from 'hospitalrun/mixins/patient-diagnosis';
+import UserSession from 'hospitalrun/mixins/user-session';
const {
computed,
- isEmpty
+ get,
+ isEmpty,
+ set
} = Ember;
-const DIAGNOSIS_KEYS = [
- 'diganosisContainer',
- 'hideInActiveDiagnoses',
- 'patient.diagnoses.@each.active',
- 'patient.diagnoses.@each.secondaryDiagnosis',
- 'visit.diagnoses.@each.secondaryDiagnosis'
-];
-
-export default Ember.Component.extend(PatientDiagnosis, {
+export default Ember.Component.extend(UserSession, {
+ allowAddAllergy: false,
+ allowAddDiagnosis: false,
+ allowAddOperativePlan: false,
classNames: ['patient-summary'],
- canAddDiagnosis: false,
- disablePatientLink: false,
+ diagnosisContainer: null,
diagnosisList: null,
+ disablePatientLink: false,
editDiagnosisAction: 'editDiagnosis',
+ editOperativePlanAction: 'editOperativePlan',
+ editOperationReportAction: 'editOperationReport',
editProcedureAction: 'editProcedure',
hideInActiveDiagnoses: true,
patient: null,
patientProcedures: null,
showAddDiagnosisAction: 'showAddDiagnosis',
showPatientAction: 'showPatient',
- visit: null,
- diagnosisContainer: computed('patient', 'visit', function() {
- // Pull diagnoses from visit if it is defined; otherwise pull from patient.
- let diagnosisContainer = this.get('visit');
- if (isEmpty(diagnosisContainer)) {
- diagnosisContainer = this.get('patient');
+ canAddAllergy: computed('allowAddAllergy', {
+ get() {
+ let allowAddAllergy = get(this, 'allowAddAllergy');
+ return allowAddAllergy && this.currentUserCan('add_allergy');
}
- return diagnosisContainer;
}),
- havePrimaryDiagnoses: computed('primaryDiagnoses.length', function() {
- let primaryDiagnosesLength = this.get('primaryDiagnoses.length');
- return (primaryDiagnosesLength > 0);
+ canAddOperativePlan: computed('allowAddOperativePlan', {
+ get() {
+ let allowAddOperativePlan = get(this, 'allowAddOperativePlan');
+ return allowAddOperativePlan && this.currentUserCan('add_operative_plan');
+ }
+ }),
+
+ currentOperativePlan: computed('patient.operativePlans.@each.status', {
+ get() {
+ let operativePlans = get(this, 'patient.operativePlans');
+ return operativePlans.findBy('isPlanned', true);
+ }
}),
haveProcedures: computed('patientProcedures.length', function() {
@@ -47,38 +52,28 @@ export default Ember.Component.extend(PatientDiagnosis, {
return (proceduresLength > 0);
}),
- haveSecondaryDiagnoses: computed('secondaryDiagnoses.length', function() {
- let secondaryDiagnosesLength = this.get('secondaryDiagnoses.length');
- return (secondaryDiagnosesLength > 0);
- }),
-
- primaryDiagnoses: computed(...DIAGNOSIS_KEYS, function() {
- let diagnosisContainer = this.get('diagnosisContainer');
- let hideInActiveDiagnoses = this.get('hideInActiveDiagnoses');
- return this.getDiagnoses(diagnosisContainer, hideInActiveDiagnoses, false);
-
- }),
-
- secondaryDiagnoses: computed(...DIAGNOSIS_KEYS, function() {
- let diagnosisContainer = this.get('diagnosisContainer');
- let hideInActiveDiagnoses = this.get('hideInActiveDiagnoses');
- return this.getDiagnoses(diagnosisContainer, hideInActiveDiagnoses, true);
- }),
-
shouldLinkToPatient: computed('disablePatientLink', function() {
let disablePatientLink = this.get('disablePatientLink');
return !disablePatientLink;
}),
- showPrimaryDiagnoses: computed('canAddDiagnosis', 'havePrimaryDiagnoses', function() {
- return this.get('canAddDiagnosis') || this.get('havePrimaryDiagnoses');
- }),
-
- hasAllergies: Ember.computed('patient.allergies.[]', function() {
- return Ember.computed.notEmpty('patient.allergies');
- }),
+ didReceiveAttrs() {
+ this._super(...arguments);
+ let diagnosisContainer = get(this, 'diagnosisContainer');
+ if (isEmpty(diagnosisContainer)) {
+ set(this, 'diagnosisContainer', get(this, 'patient'));
+ }
+ },
actions: {
+ addOperativePlan() {
+ this.sendAction('editOperativePlanAction');
+ },
+
+ editOperativePlan(operativePlan) {
+ this.sendAction('editOperativePlanAction', operativePlan);
+ },
+
linkToPatient() {
let shouldLink = this.get('shouldLinkToPatient');
if (shouldLink) {
@@ -96,15 +91,16 @@ export default Ember.Component.extend(PatientDiagnosis, {
},
editProcedure(procedure) {
- procedure.set('returnToVisit');
- procedure.set('returnToPatient', this.get('patient.id'));
- procedure.set('patient', this.get('patient'));
- this.sendAction('editProcedureAction', procedure);
+ let report = get(procedure, 'report');
+ if (isEmpty(report)) {
+ this.sendAction('editProcedureAction', procedure);
+ } else {
+ this.sendAction('editOperationReportAction', report);
+ }
},
showAddDiagnosis() {
this.sendAction('showAddDiagnosisAction');
}
-
}
});
diff --git a/app/components/upcoming-appointments.js b/app/components/upcoming-appointments.js
new file mode 100644
index 0000000000..7e082e37e7
--- /dev/null
+++ b/app/components/upcoming-appointments.js
@@ -0,0 +1,43 @@
+import DS from 'ember-data';
+import Ember from 'ember';
+import moment from 'moment';
+
+const { PromiseArray } = DS;
+
+const {
+ Component,
+ computed,
+ get,
+ inject,
+ isEmpty
+} = Ember;
+
+export default Component.extend({
+ patient: null,
+
+ database: inject.service(),
+ store: inject.service(),
+
+ appointments: computed('patient', function() {
+ let patient = get(this, 'patient');
+ if (!isEmpty(patient)) {
+ let database = get(this, 'database');
+ let endDate = moment().add(10, 'years').toDate().getTime();
+ let maxApptId = database.getMaxPouchId('appointment');
+ let minApptId = database.getMinPouchId('appointment');
+ let patientId = get(patient, 'id');
+ let startDate = moment().toDate().getTime();
+ let store = get(this, 'store');
+ let appointmentPromise = store.query('appointment', {
+ options: {
+ startkey: [patientId, startDate, startDate, minApptId],
+ endkey: [patientId, endDate, endDate, maxApptId]
+ },
+ mapReduce: 'appointments_by_patient'
+ });
+ return PromiseArray.create({
+ promise: appointmentPromise
+ });
+ }
+ })
+});
diff --git a/app/controllers/abstract-edit-controller.js b/app/controllers/abstract-edit-controller.js
index 20565f8355..e19dae079d 100644
--- a/app/controllers/abstract-edit-controller.js
+++ b/app/controllers/abstract-edit-controller.js
@@ -3,6 +3,9 @@ import EditPanelProps from 'hospitalrun/mixins/edit-panel-props';
import IsUpdateDisabled from 'hospitalrun/mixins/is-update-disabled';
import ModalHelper from 'hospitalrun/mixins/modal-helper';
import UserSession from 'hospitalrun/mixins/user-session';
+
+const { get } = Ember;
+
export default Ember.Controller.extend(EditPanelProps, IsUpdateDisabled, ModalHelper, UserSession, {
cancelAction: 'allItems',
@@ -158,12 +161,14 @@ export default Ember.Controller.extend(EditPanelProps, IsUpdateDisabled, ModalHe
* to skip the afterUpdate call.
*/
saveModel(skipAfterUpdate) {
- this.get('model').save().then(function(record) {
+ get(this, 'model').save().then((record) => {
this.updateLookupLists();
if (!skipAfterUpdate) {
this.afterUpdate(record);
}
- }.bind(this));
+ }).catch((error) => {
+ this.send('error', error);
+ });
},
/**
diff --git a/app/controllers/abstract-report-controller.js b/app/controllers/abstract-report-controller.js
index ca2e0c2620..6b536eefb1 100644
--- a/app/controllers/abstract-report-controller.js
+++ b/app/controllers/abstract-report-controller.js
@@ -1,6 +1,7 @@
import Ember from 'ember';
import DateFormat from 'hospitalrun/mixins/date-format';
import ModalHelper from 'hospitalrun/mixins/modal-helper';
+import moment from 'moment';
import NumberFormat from 'hospitalrun/mixins/number-format';
import PaginationProps from 'hospitalrun/mixins/pagination-props';
import PouchDbMixin from 'hospitalrun/mixins/pouchdb';
diff --git a/app/controllers/index.js b/app/controllers/index.js
index 83268c0fc9..7077613573 100644
--- a/app/controllers/index.js
+++ b/app/controllers/index.js
@@ -11,16 +11,16 @@ export default Ember.Controller.extend(UserSession, {
'Users'
],
- setupPermissions: function() {
+ setupPermissions: Ember.on('init', function() {
let permissions = this.get('defaultCapabilities');
for (let capability in permissions) {
if (this.currentUserCan(capability)) {
this.set(`userCan_${capability}`, true);
}
}
- }.on('init'),
+ }),
- activeLinks: function() {
+ activeLinks: Ember.computed('indexLinks', function() {
let activeLinks = [];
let indexLinks = this.get('indexLinks');
indexLinks.forEach(function(link) {
@@ -33,6 +33,6 @@ export default Ember.Controller.extend(UserSession, {
}
}.bind(this));
return activeLinks;
- }.property('indexLinks')
+ })
});
diff --git a/app/diagnosis/edit/template.hbs b/app/diagnosis/edit/template.hbs
index a0d1763f07..40a9d3fb61 100644
--- a/app/diagnosis/edit/template.hbs
+++ b/app/diagnosis/edit/template.hbs
@@ -27,7 +27,7 @@
{{date-picker property="date" label=(t "diagnosis.labels.date") class="col-sm-4 required"}}
- {{em-checkbox label=(t 'diagnosis.labels.secondaryDiagnosis') property="secondaryDiagnosis" class="col-sm-4"}}
+ {{em-checkbox label=(t 'diagnosis.labels.secondaryDiagnosis') property="secondaryDiagnosis" class="col-sm-4 secondary-diagnosis"}}
{{#unless model.isNew}}
{{em-checkbox label=(t 'diagnosis.labels.activeDiagnosis') property="active" class="col-sm-4"}}
{{/unless}}
diff --git a/app/dialog/controller.js b/app/dialog/controller.js
index 0851e3c8d0..33efa0164a 100644
--- a/app/dialog/controller.js
+++ b/app/dialog/controller.js
@@ -1,8 +1,19 @@
import Ember from 'ember';
+
+const { computed, get, isEmpty } = Ember;
+
export default Ember.Controller.extend({
showUpdateButton: true,
isUpdateDisabled: false,
+ cancelAction: computed('model.cancelAction', function() {
+ let cancelAction = get(this, 'model.cancelAction');
+ if (isEmpty(cancelAction)) {
+ cancelAction = 'cancel';
+ }
+ return cancelAction;
+ }),
+
actions: {
cancel() {
this.send('closeModal');
@@ -10,14 +21,18 @@ export default Ember.Controller.extend({
confirm() {
let confirmAction = this.getWithDefault('model.confirmAction', 'model.confirm');
- this.send(confirmAction, this.get('model'));
+ this.send(confirmAction, get(this, 'model'));
this.send('closeModal');
},
ok() {
- let okAction = this.get('model.okAction');
- if (!Ember.isEmpty(okAction)) {
- this.send(okAction, this.get('model'));
+ let okAction = get(this, 'model.okAction');
+ let okContext = get(this, 'model.okContext');
+ if (isEmpty(okContext)) {
+ okContext = get(this, 'model');
+ }
+ if (!isEmpty(okAction)) {
+ this.send(okAction, okContext);
}
this.send('closeModal');
}
diff --git a/app/dialog/template.hbs b/app/dialog/template.hbs
index 70443ad186..a4b79ce1ac 100644
--- a/app/dialog/template.hbs
+++ b/app/dialog/template.hbs
@@ -1,4 +1,5 @@
{{#modal-dialog
+ cancelAction=cancelAction
hideCancelButton=model.hideCancelButton
hideUpdateButton=model.hideUpdateButton
isUpdateDisabled=model.isUpdateDisabled
diff --git a/app/helpers/date-format.js b/app/helpers/date-format.js
index 0ea014d301..7f4ec8d0c3 100644
--- a/app/helpers/date-format.js
+++ b/app/helpers/date-format.js
@@ -1,4 +1,5 @@
import Ember from 'ember';
+import moment from 'moment';
export default Ember.Helper.helper(function(params, hash) {
if (!Ember.isEmpty(params[0])) {
let dateFormat = 'l';
diff --git a/app/imaging/edit/route.js b/app/imaging/edit/route.js
index ce21fd1f7c..e84f3a243b 100644
--- a/app/imaging/edit/route.js
+++ b/app/imaging/edit/route.js
@@ -2,6 +2,7 @@ import { translationMacro as t } from 'ember-i18n';
import AbstractEditRoute from 'hospitalrun/routes/abstract-edit-route';
import ChargeRoute from 'hospitalrun/mixins/charge-route';
import Ember from 'ember';
+import moment from 'moment';
import PatientListRoute from 'hospitalrun/mixins/patient-list-route';
export default AbstractEditRoute.extend(ChargeRoute, PatientListRoute, {
editTitle: t('imaging.titles.editTitle'),
diff --git a/app/inventory/batch/controller.js b/app/inventory/batch/controller.js
index b0ef3c0155..5fefc9878d 100755
--- a/app/inventory/batch/controller.js
+++ b/app/inventory/batch/controller.js
@@ -1,10 +1,9 @@
import AbstractEditController from 'hospitalrun/controllers/abstract-edit-controller';
import InventoryId from 'hospitalrun/mixins/inventory-id';
import InventoryLocations from 'hospitalrun/mixins/inventory-locations';
-import InventorySelection from 'hospitalrun/mixins/inventory-selection';
import Ember from 'ember';
import { translationMacro as t } from 'ember-i18n';
-export default AbstractEditController.extend(InventoryId, InventoryLocations, InventorySelection, {
+export default AbstractEditController.extend(InventoryId, InventoryLocations, {
doingUpdate: false,
inventoryController: Ember.inject.controller('inventory'),
inventoryItems: null,
diff --git a/app/inventory/batch/template.hbs b/app/inventory/batch/template.hbs
index ed28deae36..4c18a3cfee 100755
--- a/app/inventory/batch/template.hbs
+++ b/app/inventory/batch/template.hbs
@@ -33,7 +33,7 @@
{{number-input property="purchaseCost" label=(t 'inventory.labels.purchaseCost') class="col-sm-2 required test-inv-cost"}}
diff --git a/app/inventory/reports/controller.js b/app/inventory/reports/controller.js
index 160afd95e1..0347b19346 100644
--- a/app/inventory/reports/controller.js
+++ b/app/inventory/reports/controller.js
@@ -3,6 +3,7 @@ import Ember from 'ember';
import InventoryAdjustmentTypes from 'hospitalrun/mixins/inventory-adjustment-types';
import LocationName from 'hospitalrun/mixins/location-name';
import ModalHelper from 'hospitalrun/mixins/modal-helper';
+import moment from 'moment';
import NumberFormat from 'hospitalrun/mixins/number-format';
import SelectValues from 'hospitalrun/utils/select-values';
export default AbstractReportController.extend(LocationName, ModalHelper, NumberFormat, InventoryAdjustmentTypes, {
diff --git a/app/inventory/request/controller.js b/app/inventory/request/controller.js
index 4163b56988..5ada763eb2 100755
--- a/app/inventory/request/controller.js
+++ b/app/inventory/request/controller.js
@@ -1,10 +1,9 @@
import AbstractEditController from 'hospitalrun/controllers/abstract-edit-controller';
import FulfillRequest from 'hospitalrun/mixins/fulfill-request';
import InventoryLocations from 'hospitalrun/mixins/inventory-locations'; // inventory-locations mixin is needed for fulfill-request mixin!
-import InventorySelection from 'hospitalrun/mixins/inventory-selection';
import Ember from 'ember';
-export default AbstractEditController.extend(FulfillRequest, InventoryLocations, InventorySelection, {
+export default AbstractEditController.extend(FulfillRequest, InventoryLocations, {
inventoryController: Ember.inject.controller('inventory'),
inventoryItems: null,
cancelAction: 'allRequests',
diff --git a/app/inventory/request/template.hbs b/app/inventory/request/template.hbs
index fe18c50b58..7f265dd710 100755
--- a/app/inventory/request/template.hbs
+++ b/app/inventory/request/template.hbs
@@ -75,7 +75,7 @@
{{inventory-location-picker label=(t 'inventory.labels.pullFrom') quantityRequested=model.quantity
locationList=model.inventoryItem.availableLocations
- selectedLocations=model.inventoryLocations
+ selectedLocations=model.inventoryLocations class="inventory-location"
}}
diff --git a/app/invoices/edit/controller.js b/app/invoices/edit/controller.js
index 158d2645e2..139c7f711c 100644
--- a/app/invoices/edit/controller.js
+++ b/app/invoices/edit/controller.js
@@ -1,5 +1,6 @@
import AbstractEditController from 'hospitalrun/controllers/abstract-edit-controller';
import Ember from 'ember';
+import moment from 'moment';
import NumberFormat from 'hospitalrun/mixins/number-format';
import PatientSubmodule from 'hospitalrun/mixins/patient-submodule';
import PublishStatuses from 'hospitalrun/mixins/publish-statuses';
diff --git a/app/labs/edit/route.js b/app/labs/edit/route.js
index 6484205461..9b654c7e37 100644
--- a/app/labs/edit/route.js
+++ b/app/labs/edit/route.js
@@ -1,6 +1,7 @@
import Ember from 'ember';
import AbstractEditRoute from 'hospitalrun/routes/abstract-edit-route';
import ChargeRoute from 'hospitalrun/mixins/charge-route';
+import moment from 'moment';
import PatientListRoute from 'hospitalrun/mixins/patient-list-route';
import { translationMacro as t } from 'ember-i18n';
diff --git a/app/locales/en/translations.js b/app/locales/en/translations.js
index 1601fa4f05..472bfa93c7 100644
--- a/app/locales/en/translations.js
+++ b/app/locales/en/translations.js
@@ -41,7 +41,7 @@ export default {
imaging: 'Imaging',
inventory: 'Inventory',
patients: 'Patients',
- appointments: 'Appointments',
+ scheduling: 'Scheduling',
medication: 'Medication',
labs: 'Labs',
billing: 'Billing',
@@ -56,9 +56,9 @@ export default {
reports: 'Reports',
patientListing: 'Patient Listing',
newPatient: 'New Patient',
- thisWeek: 'This Week',
- today: 'Today',
- search: 'Search',
+ appointmentsThisWeek: 'Appointment This Week',
+ "today'sAppointments": 'Today\'s Appointments',
+ appointmentSearch: 'Appointment Search',
addAppointment: 'Add Appointment',
dispense: 'Dispense',
returnMedication: 'Return Medication',
@@ -72,11 +72,14 @@ export default {
users: 'Users',
newUser: 'New User',
admittedPatients: 'Admitted Patients',
- missed: 'Missed',
+ missedAppointments: 'Missed Appointments',
userRoles: 'User Roles',
workflow: 'Workflow',
outpatient: 'Outpatient',
- customForms: 'Custom Forms'
+ customForms: 'Custom Forms',
+ appointmentsCalendar: 'Appointments Calendar',
+ theaterSchedule: 'Theater Schedule',
+ scheduleSurgery: 'Schedule Surgery'
},
actions: {
logout: 'Logout',
@@ -134,6 +137,7 @@ export default {
includeOtherOption: 'Include Other Option',
label: 'Label',
newForm: 'New Form',
+ operativePlanFormType: 'Operative Plan and Report',
otherOptionLabel: 'Other Option Label',
patientFormType: 'Patient',
property: 'Property',
@@ -279,7 +283,10 @@ export default {
addBillingDiagnosis: 'Add Billing Diagnosis',
addNote: 'Add Note',
addSocialwork: 'Add Social Work',
- deleteNote: 'Delete Note'
+ deleteNote: 'Delete Note',
+ addOperativePlan: 'Add Operative Plan',
+ addAllergy: 'Add Allergy',
+ addOperationReport: 'Add Operation Report'
},
messages: {
roleSaved: 'The {{roleName}} role has been saved.'
@@ -469,6 +476,8 @@ export default {
newRequestPlus: '+ new request',
addVisit: 'Add Visit',
search: 'Search',
+ filter: 'Filter',
+ clear: 'Clear',
edit: 'Edit',
addLineItem: 'Add Line Item',
showFewer: 'Show Fewer',
@@ -759,15 +768,25 @@ export default {
missed: 'Missed Appointments',
searchTitle: 'Search Appointments',
todayTitle: 'Today\'s Appointments',
+ calendarTitle: 'Appointments Calendar',
messages: {
+ appointmentSaved: 'The appointment for {{patient}} has been saved.',
deleteAppointmentMessage: 'Are you sure you wish to delete this appointment?',
endTimeLaterThanStart: 'Please select an end time later than the start time.'
},
buttons: {
- newButton: '+ new appointment'
+ newButton: '+ new appointment',
+ scheduleSurgery: '+ schedule surgery'
},
labels: {
+ noLocation: 'No Location',
selectedStartingDate: 'Show Appointments On Or After'
+ },
+ titles: {
+ appointmentSaved: 'Appointment Saved',
+ editSurgicalAppointment: 'Edit Surgical Appointment',
+ newSurgicalAppointment: 'New Surgical Appointment',
+ theaterSchedule: 'Theater Schedule'
}
},
vitals: {
@@ -911,7 +930,7 @@ export default {
deletePhoto: 'Delete Photo',
deleteContact: 'Delete Contact',
savedPatient: 'Patient Saved',
- todaysOutpatients: 'Todays\' Outpatients',
+ todaysOutpatients: 'Today\'s Outpatients',
admissionsDetail: 'Admissions Detail',
admissionsSummary: 'Admissions Summary',
diagnosticTesting: 'Diagnostic Testing',
@@ -938,6 +957,8 @@ export default {
buttons: {
addExpense: 'Add Expense',
addContact: 'Add Contact',
+ addOperativePlan: 'Add Operative Plan',
+ editOperativePlan: 'Current Operative Plan',
newLab: 'New Lab',
newVisit: 'New Visit',
newMedication: 'New Medication',
@@ -947,7 +968,8 @@ export default {
newAppointment: 'New Appointment',
backToPatients: 'Back to Patient List',
newPatient: '+ new patient',
- patientCheckIn: 'Patient Check In'
+ patientCheckIn: 'Patient Check In',
+ scheduleSurgery: 'Schedule Surgery'
},
labels: {
primaryDiagnosis: 'Primary Diagnoses',
@@ -987,7 +1009,8 @@ export default {
religion: 'Religion',
parent: 'Parent/Guardian',
contacts: 'Contacts',
- sexNotEntered: 'Sex Not Entered'
+ sexNotEntered: 'Sex Not Entered',
+ operativePlan: 'Operative Plan'
},
notes: {
newNote: 'New Note for',
@@ -1123,6 +1146,28 @@ export default {
},
priceList: {
charges: '{{pricingType}} charges'
+ },
+ operativeProcedures: {
+ buttons: {
+ addProcedure: 'Add Procedure'
+ },
+ labels: {
+ procedure: 'Procedure'
+ },
+ titles: {
+ procedures: 'Procedures'
+ }
+ },
+ upcomingAppointments: {
+ labels: {
+ date: 'Date',
+ with: 'With',
+ location: 'Location',
+ type: 'Type'
+ },
+ titles: {
+ upcomingAppointments: 'Upcoming Appointments'
+ }
}
},
customForms: {
@@ -1160,5 +1205,59 @@ export default {
allergyName: 'Name',
patientAllergy: 'Patient Allergies'
}
+ },
+ operativePlan: {
+ buttons: {
+ completePlan: 'Complete Plan'
+ },
+ labels: {
+ additionalNotes: 'Additional Notes',
+ admissionInstructions: 'Instructions Upon Admission',
+ caseComplexity: 'Case Complexity',
+ completedStatus: 'Completed',
+ droppedStatus: 'Dropped',
+ operationDescription: 'Operation Description',
+ plannedStatus: 'Planned',
+ status: 'Status',
+ surgeon: 'Surgeon'
+ },
+ messages: {
+ planSaved: 'The operative plan has been saved.',
+ planCompleted: 'The operative plan has been completed. You will now be directed to the operation report.'
+ },
+ titles: {
+ editTitle: 'Edit Operative Plan',
+ newTitle: 'New Operative Plan',
+ planCompleted: 'Plan Completed',
+ planSaved: 'Plan Saved'
+ }
+ },
+ operationReport: {
+ labels: {
+ additionalNotes: 'Additional Notes',
+ assistant: 'Assistant',
+ caseComplexity: 'Case Complexity',
+ operationDescription: 'Operation Description',
+ preOpPrimaryDiagnosis: 'Pre-op Primary Diagnosis',
+ preOpSecondaryDiagnosis: 'Pre-op Secondary Diagnosis',
+ surgeon: 'Surgeon',
+ surgeryDate: 'Surgery Date'
+ },
+ messages: {
+ reportSaved: 'The operation report has been saved.'
+ },
+ titles: {
+ editTitle: 'Edit Operation Report',
+ newTitle: 'New Operation Report',
+ reportSaved: 'Report Saved'
+ }
+ },
+ application: {
+ messages: {
+ sessionExpired: 'Your session has expired. Please login to continue.'
+ },
+ titles: {
+ sessionExpired: 'Session Expired'
+ }
}
};
diff --git a/app/locales/ur/translations.js b/app/locales/ur/translations.js
new file mode 100644
index 0000000000..0fea0c536a
--- /dev/null
+++ b/app/locales/ur/translations.js
@@ -0,0 +1,1263 @@
+export default {
+ dashboard: {
+ title: 'آپ کیا کرنا چاہیں گے؟'
+ },
+ errors: {
+ inclusion: 'فہرست میں شامل نہیں ہے',
+ exclusion: 'مخصوص ہے',
+ invalid: 'غلط ہے',
+ confirmation: 'کے مماثل نہیں ہے {{attribute}}',
+ accepted: 'قبول کرنا ضروری',
+ empty: 'خالی نہیں ہو سکتا',
+ blank: 'خالی نہیں رہ سکتی',
+ present: 'خالی ہونا ضروری ہے',
+ tooLong: 'حروف {{count}}بہت طویل ہے، زیادہ سے زیادہ ',
+ tooShort: 'حروف{{count}}بہت مختصر ہے کم از کم ',
+ wrongLength: 'حروف ہونے چاہئے{{count}}غلط لمبائی ہے ',
+ notANumber: 'ایک نمبر نہیں ہے',
+ notAnInteger: 'ایک عددی ہونا لازمی ہے',
+ greaterThan: 'سے زیادہ ہونا چاہیے {{count}}',
+ greaterThanOrEqualTo: 'سے زیادہ یا برابر ہونا چاہیے {{count}}',
+ equalTo: 'کے برابر ہونا چاہیے {{count}}',
+ lessThan: 'سے کم ہونا چاہیے {{count}}',
+ lessThanOrEqualTo: 'سے کم یا برابر ہونا چاہیے {{count}}',
+ otherThan: 'سے مختلف ہونا چاہیے {{count}}',
+ odd: 'طاق ہونا ضروری ہے',
+ even: 'جفت ہونا ضروری ہے',
+ invalidNumber: 'درست نمبر نہیں',
+ result: 'براے مہربانی مکمل کرنے سے پہلے نتیجہ درج کریں'
+ },
+ dates: {
+ long: 'دن {{days}} مہینے {{months}} سال {{years}}',
+ longPlural: 'دن {{days}} مہینے {{months}} سال {{years}}',
+ longOmitYears: 'دن {{days}} مہینے {{months}}',
+ longOmitDays: 'مہینے {{months}} سال {{years}}',
+ longOmitDaysPlural: 'مہینے {{months}} سال {{years}}',
+ longOmitDaysYears: 'مہینے {{months}}',
+ shortOmitYears: 'د{{days} م{{months}}',
+ short: 'د{{days} م{{months}} س{{years}}'
+ },
+ navigation: {
+ imaging: 'امیجنگ',
+ inventory: 'انوینٹری',
+ patients: 'مریض',
+ scheduling: 'اوقات نامہ',
+ medication: 'ادویات',
+ labs: 'لیبز',
+ billing: 'بلنگ',
+ administration: 'انتظامیہ',
+ subnav: {
+ actions: 'عوامل',
+ requests: 'درخواستیں',
+ items: 'اشیاء',
+ completed: 'مکمل',
+ newRequest: 'نئی درخواست',
+ inventoryReceived: 'انوینٹری موصول',
+ reports: 'رپورٹس',
+ patientListing: 'مریض کی فہرست سازی',
+ newPatient: 'نئے مریض',
+ appointmentsThisWeek: 'اس ہفتے کی ملاقاتیں',
+ "today's Appointments": 'آج کی ملاقاتیں',
+ appointmentSearch: ' ملاقاتیں تلاش کریں',
+ addAppointment: 'ملاقات اضافہ',
+ dispense: 'تقسیم',
+ returnMedication: 'واپس دوا',
+ invoices: 'رسیدیں',
+ newInvoice: 'نئے رسید',
+ prices: 'قیمتیں',
+ priceProfiles: 'قیمت پروفائلز',
+ lookupLists: 'تلاش فہرستیں',
+ addressFields: 'ایڈریس قطعات',
+ loadDB: 'DB لوڈ کریں',
+ users: 'صارفین',
+ newUser: 'نیا صارف',
+ admittedPatients: 'جمع شدہ مریض',
+ missedAppointments: 'ضائع شدہ',
+ userRoles: 'صارف کے کردار',
+ workflow: 'ورک فلو',
+ outpatient: 'آؤٹ پیشنٹ',
+ customForms: 'کسٹم فام',
+ appointmentsCalendar: 'ملاقاتوں کا کیلنڈر',
+ theaterSchedule: 'تھیٹر اوقات نامہ',
+ scheduleSurgery: 'سرجری اوقات نامہ'
+ },
+ actions: {
+ logout: 'لاگ آوٹ',
+ login: 'لاگ ان'
+ },
+ about: 'HospitalRun کے بارے'
+ },
+ user: {
+ plusNewUser: '+ نیا صارف',
+ usersPageTile: 'صارفین کی فہرست سازی'
+ },
+ admin: {
+ addressOptions: 'ایڈرس آپشنز',
+ lookupLists: 'تلاش فہرستیں',
+ loadDb: 'DB لوڈ کریں',
+ userRoles: 'صارف کے کردار',
+ users: 'صارفین',
+ address: {
+ address1Label: 'ایڈریس 1 لیبل',
+ address2Label: 'ایڈریس 2 لیبل',
+ address3Label: 'ایڈریس 3 لیبل',
+ address4Label: 'ایڈریس 4 لیبل',
+ include1Label: '1 لیبل شامل کریں',
+ include2Label: '2 لیبل شامل کریں',
+ include3Label: '3 لیبل شامل کریں',
+ include4Label: '4 لیبل شامل کریں',
+ titles: {
+ optionsSaved: 'آپشنز محفوظ ہوگۓ'
+ },
+ messages: {
+ addressSaved: 'ایڈریس آپشنز محفوظ کرلیے گۓ ہیں'
+ },
+
+ newTitle: 'ایڈریس آپشنز',
+ editTitle: 'ایڈریس آپشنز',
+ addressLabel: 'ایڈریس'
+ },
+ customForms: {
+ buttons: {
+ addField: 'فیلڈ کا اضافہ کریں',
+ moveDown: 'نیچے منتقل کریں',
+ moveUp: 'اوپر منتقل کریں',
+ newForm: '+ نیا فام',
+ preview: 'مشاہدہ کریں'
+
+ },
+ labels: {
+ alwaysInclude: 'ہمیشہ شامل',
+ checkbox: 'چیک باکس',
+ columns: 'کالم',
+ colSpan: 'پھیلاؤ کے کالموں کی تعداد',
+ customForm: 'کسٹم فام',
+ formName: 'فارم کا نام',
+ formType: 'فارم کی قسم',
+ includeOtherOption: 'دیگر آپشن شامل کریں',
+ label: 'لیبل',
+ newForm: 'نیا فارم',
+ operativePlanFormType: 'آپریٹو پلان اور رپورٹ',
+ otherOptionLabel: 'دیگر آپشن لیبل',
+ patientFormType: 'مریض',
+ property: 'خصوصیت',
+ radio: 'ریڈیو',
+ select: 'ڈراپ ڈاؤن',
+ socialworkFormType: 'سماجی کام',
+ text: 'عبارت',
+ textarea: 'بڑی عبارت',
+ visitFormType: 'دورہ'
+ },
+ messages: {
+ deleteForm: 'کیا آپ یقینی طور پر اس کسٹم فارم کو حذف کرنا چاہتے ہیں؟',
+ formSaved: 'فارم محفوظ ہوگیا ہے {{name}} '
+ },
+ titles: {
+ customForms: 'کسٹم فارمز',
+ deleteForm: 'کسٹم فارم حذف کریں',
+ editCustomForm: 'کسٹم فارم میں ترمیم کریں',
+ fields: 'قطعات',
+ formSaved: 'فارم محفوظ ہوگیا',
+ checkboxValues: 'چیک باکس میں قیمتیں',
+ dropDownValues: 'ڈراپ ڈاؤن فہرست',
+ newCustomForm: 'نئے کسٹم فارم',
+ radioValues: 'ریڈیو میں قیمتیں'
+ }
+ },
+ loaddb: {
+ progressMessage: 'آپ کا ڈیٹابیس لوڈ کیا جا رہا ہے، براۂ مہربانی انتظار کریں.',
+ progressTitle: 'ڈیٹابیس لوڈ ہو رہا ہے',
+ displayAlertTitle: 'لوڈ کرنے کے لئے فائل کو منتخب کریں',
+ displayAlertMessage: 'لوڈ کرنے کے لئے فائل کو منتخب کیجیے.',
+ errorDisplayAlertTitle: 'لوڈ کرنے میں خامی',
+ errorDisplayAlertMessage: 'ڈیٹا بیس امپورٹ نہیں ہوسکتی. یہ خامی ہے {{error}}',
+ editTitle: 'DB لوڈ کریں'
+ },
+ lookup: {
+ alertImportListTitle: 'امپورٹ کرنے کے لئے فائل کو منتخب کریں',
+ alertImportListMessage: 'امپورٹ کرنے کے لئے فائل کو منتخب کیجیے',
+ alertImportListSaveTitle: 'لسٹ امپورٹ ہوگئ',
+ alertImportListSaveMessage: 'تلاش فہرست امپورٹ ہو گئی ہے.',
+ alertImportListUpdateTitle: 'فہرست محفوظ',
+ alertImportListUpdateMessage: 'تلاش فہرست محفوظ ہو گئی ہے.',
+ pageTitle: 'تلاش فہرستیں',
+ edit: {
+ template: {
+ addTitle: 'قیمت شامل کریں',
+ editTitle: 'قیمت ترمیم کریں',
+ updateButtonTextAdd: 'شامل کریں',
+ updateButtonTextUpdate: 'اپ ڈیٹ',
+ labelTitle: 'قدر'
+ }
+ },
+ anesthesiaTypes: 'اینستھیزیا کی اقسام',
+ anesthesiologists: 'اینستھیسیالوجسٹس',
+ billingCategories: 'بلنگ کی اقسام',
+ clinicList: 'کلینک مقامات',
+ countryList: 'ممالک',
+ diagnosisList: 'تشخیص',
+ cptCodeList: 'CPT کوڈز',
+ expenseAccountList: 'اخراجات اکاؤنٹس',
+ aisleLocationList: 'انوینٹری راہداری مقامات',
+ warehouseList: 'انوینٹری مقامات',
+ inventoryTypes: 'انوینٹری کی اقسا م',
+ imagingPricingTypes: 'امیجنگ قیمتوں کا تعین کی اقسام',
+ labPricingTypes: 'لیب کی قیمتوں کا تعین کی اقسام',
+ patientStatusList: 'مریض سٹیٹس کی فہرست',
+ physicianList: 'ڈاکٹر',
+ procedureList: 'طریقہ کار',
+ procedureLocations: 'طریقہ کار مقامات',
+ procedurePricingTypes: 'ضابطے کی قیمتوں کا تعین کی اقسام',
+ radiologists: 'ریڈیولوجسٹ',
+ unitTypes: 'یونٹ کی اقسام',
+ vendorList: 'وینڈر',
+ visitLocationList: 'دورہ مقامات',
+ visitTypes: 'دورہ کی اقسا م',
+ wardPricingTypes: 'وارڈ کی قیمتوں کا تعین کی اقسام',
+ messages: {
+ deleteLookupValue: ' {{value}} قدر حذف کرنا چاہتے ہیں؟'
+ },
+ titles: {
+ deleteLookupValue: 'قدر حذف کریں'
+ }
+ },
+ roles: {
+ capability: {
+ admin: 'انتظامیہ',
+ loadDb: 'لوڈ کریں ڈیٹا بیس',
+ updateConfig: 'اپ ڈیٹ کی ترتیب',
+ appointments: 'ملاقاتیں',
+ addAppointment: 'ملاقات اضافہ',
+ billing: 'بلنگ',
+ addCharge: 'چارج شامل کریں',
+ addPricing: 'قیمتوں کا تعین شامل کریں',
+ addPricingProfile: 'قیمتوں کا تعین پروفائل شامل کریں',
+ addInvoice: 'رسید شامل کریں',
+ addPayment: 'ادائیگی شامل کریں',
+ deleteInvoice: 'رسید کو حذف کریں',
+ deletePricing: 'قیمتوں کا تعین حذف کریں',
+ deletePricingProfile: 'قیمتوں کا تعین پروفائل حذف کریں',
+ editInvoice: 'رسید میں ترمیم کریں',
+ invoices: 'رسیدیں',
+ overrideInvoice: 'رسید کو منسوخ کردے',
+ pricing: 'قیمتوں کا تعین',
+ patients: 'مریض',
+ addDiagnosis: 'تشخیص کے لئے شامل کریں',
+ addPhoto: 'تصویر کا اضافہ کریں',
+ addPatient: 'مریض شامل کریں',
+ addProcedure: 'ضابطے شامل کریں',
+ addVisit: 'دورہ شامل کریں',
+ addVitals: 'vitals شامل کریں',
+ admitPatient: 'مریض جمع کریں',
+ deletePhoto: 'تصویر حذف',
+ deletePatient: 'مریض کو حذف کریں',
+ deleteAppointment: 'ملاقات حذف کریں',
+ deleteDiagnosis: 'تشخیس حذف کریں',
+ deleteProcedure: 'ضابطہ حذف کریں',
+ deleteSocialwork: 'سماجی کام حذف کریں',
+ deleteVitals: ' vitals حذف کریں',
+ deleteVisit: ' دورہ حذف کریں',
+ dischargePatient: 'تخریج مریض',
+ patientReports: 'مریض کی رپورٹیں',
+ visits: 'دورے',
+ medication: 'ادویات',
+ addMedication: 'ادویات شامل',
+ deleteMedication: 'ادویات حذف کریں',
+ fulfillMedication: 'ادویات پورا کریں',
+ labs: 'لیبز',
+ addLab: 'لیب شامل کریں',
+ completeLab: 'مکمل لیب',
+ deleteLab: 'لیب حذف کریں',
+ imaging: 'امیجنگ',
+ addImaging: 'امیجنگ کا اضافہ کریں',
+ completeImaging: 'مکمل امیجنگ',
+ deleteImaging: 'امیجنگ حذف کریں',
+ inventory: 'انوینٹری',
+ addInventoryRequest: 'انوینٹری کی درخواست شامل کریں',
+ addInventoryItem: 'انوینٹری آئٹم شامل کریں',
+ addInventoryPurchase: 'انوینٹری کی خریداری شامل کریں',
+ adjustInventoryLocation: 'انوینٹری مقام کو درست کریں',
+ deleteInventoryItem: 'حذف انوینٹری آئٹم',
+ fulfillInventory: 'انوینٹری پورا کریں',
+ defineUserRoles: 'صارف کے کردار کی وضاحت کریں',
+ addBillingDiagnosis: 'بلنگ تشخیص شامل کریں',
+ addNote: 'نوٹ شامل',
+ addSocialwork: 'سوشل ورک شامل',
+ deleteNote: 'نوٹ حذف کریں',
+ addOperativePlan: 'آپریٹو پلان شامل کریں',
+ addAllergy: 'الرجی کا اضافہ کریں',
+ addOperationReport: 'آپریشن رپورٹ شامل کریں'
+ },
+ messages: {
+ roleSaved: '{{roleName}} کردار محفوظ ہوگیا ہے.'
+ },
+ titles: {
+ roleSaved: 'کردار محفوظ ہوگیا ہے'
+ }
+ },
+ visitForms: {
+ labels: {
+ followup: 'فالواپ',
+ form: 'فارم',
+ initial: 'ابتدائی',
+ visitType: 'دورہ کی قسم'
+ },
+ titles: {
+ visitForms: 'دورہ فارم'
+ }
+ },
+ workflow: {
+ admissionDepositLabel: 'داخلہ جمع کی ضرورت',
+ clinicPrepaymentLabel: 'کلینک قبل از استعمال ادائیگی کی ضرورت',
+ followupPrepaymentLabel: 'تعاقب قبل از استعمال ادائیگی کی ضرورت',
+ outpatientLabLabel: 'بیرونی مریضوں کی لیب قبل از استعمال ادائیگی کی ضرورت',
+ outpatientImagingLabel: 'بیرونی مریض کی امیجنگ قبل از استعمال ادائیگی کی ضرورت',
+ outpatientMedicationLabel: 'بیرونی مریضوں کی ادویات قبل از استعمال ادائیگی کی ضرورت',
+
+ titles: {
+ optionsSaved: 'آپشنز محفوظ ہوگۓ'
+ },
+ messages: {
+ optionsSaved: 'ورک فلو آپشنز محفوظ ہوگۓ ہیں'
+ },
+
+ newTitle: 'ورک فلو آپشنز',
+ editTitle: 'ورک فلو آپشنز',
+ workflowLabel: 'فلو آپشنز'
+
+ }
+ },
+ labels: {
+ cptcode: 'CPT کوڈ',
+ loading: 'لوڈ کر رہا ہے',
+ name: 'نام',
+ note: 'نوٹ',
+ patient: 'مریض',
+ prescriber: 'تجویز کنندہ',
+ quantity: 'تعداد',
+ requestedOn: 'پر درخواست',
+ date: 'تاریخ',
+ dateOfBirth: 'پیدائش کی تاریخ',
+ dateOfBirthShort: 'DOB',
+ dateRequested: 'درخواست کی تاریخ',
+ dateCompleted: 'تاریخ مکمل',
+ description: 'تفصیل',
+ requestedBy: 'کی طرف سے درخواست',
+ fulfill: 'پورا کریں',
+ fulfillRequest: 'درخواست کو پورا کریں',
+ fulfillRequestNow: 'ابھی درخواست کو پورا کریں',
+ actions: 'عوامل',
+ action: 'عمل',
+ notes: 'نوٹس',
+ edit: 'تصیح',
+ imageOrders: 'امیج آرڈرز',
+ labOrders: 'لیب آرڈرز',
+ imagingType: 'امیجنگ قسم',
+ result: 'نتیجہ',
+ results: 'نتائج',
+ visit: 'دورہ',
+ requests: 'درخواستیں',
+ completed: 'مکمل',
+ id: 'آئی ڈی',
+ on: 'پر',
+ type: 'قسم',
+ sex: 'جنس',
+ age: 'عمر',
+ search: 'تلاش کریں',
+ username: 'یوزر نیم',
+ email: 'ای میل',
+ role: 'کردار',
+ delete: 'حذف کریں',
+ userCanAddNewValue: 'صارف نئی اقدار کا اضافہ کر سکتے ہیں',
+ value: 'قدر',
+ lookupType: 'تلاش قسم',
+ importFile: 'امپورٹ فائل',
+ fileLoadSuccessful: ' فائل لوڈ کامیابی سے ہو گئ',
+ fileToLoad: ' لوڈ کے لیے فائل',
+ fileName: 'فائل کا نام',
+ startTime: 'وقت آغاز',
+ startDate: 'شروع کرنے کی تاریخ',
+ endTime: 'آخر وقت',
+ endDate: 'تاریخ اختتام',
+ docRead: 'دستاویزات پڑھیں',
+ docWritten: 'ڈاکس سے تحریری',
+ displayName: 'دکھانے کے لیے نام',
+ password: 'پاس ورڈ',
+ editUser: 'صارف میں ترمیم کریں',
+ newUser: 'نیا صارف',
+ deleteUser: 'صارف حذف کریں',
+ medication: 'ادویات',
+ status: 'صورتحال',
+ addNewOutpatientVisit: 'نۓ بیرنی مریض کے لیے دورہ کا اضافہ کریں',
+ prescription: 'نسخے',
+ prescriptionDate: 'نسخے تاریخ',
+ billTo: 'کا بل',
+ pullFrom: 'سے کھیںچو',
+ fulfilled: 'پوری کر دی گئ',
+ deleteRequest: 'درخواست حذف کریں',
+ location: 'مقام',
+ provider: 'مھیا کرنے والا',
+ with: 'ساتھ',
+ allDay: 'تمام دن',
+ physician: 'فزیشن',
+ assisting: 'مدد',
+ anesthesia: 'اینستھیزیا',
+ procedures: 'طریقہ کار',
+ number: 'نمبر',
+ billDate: 'بل تاریخ',
+ balanceDue: 'واجب الادا',
+ amount: 'رقم',
+ datePaid: 'تاریخ ادا',
+ creditTo: 'کرنے کے لئے کریڈٹ',
+ invoiceId: 'رسید کی آئی ڈی',
+ lineItems: 'لائن آئٹمز',
+ discount: 'رعایت',
+ excess: 'اضافی',
+ price: 'قیمت',
+ total: 'کل',
+ expenseTo: 'کرنے کے اخراجات',
+ grandTotal: 'مجموعی عدد',
+ remarks: 'تبصرہ',
+ payments: 'ادائیگیاں',
+ category: 'قسم',
+ department: 'محکمہ',
+ address: 'ایڈریس',
+ country: 'ملک'
+ },
+ messages: {
+ noItemsFound: 'کوئی آئٹم نہیں ملا.',
+ noHistoryAvailable: 'کوئی سرگزشت دستیاب نہیں',
+ createNewRecord: 'ایک نیا ریکارڈ بنائیں؟',
+ createNewUser: 'ایک نیا صارف بنائیں؟',
+ noUsersFound: 'کوئی صارف دستیاب نہیں',
+ areYouSureDelete: 'کیا آپ کو یقین ہے کہ آپ {{user}} صارف کو حذف کرنا چاہتے ہیں ؟',
+ userHasBeenSaved: 'صارف محفوظ ہوگیا ہے.',
+ userSaved: ' صارف محفوظ',
+ onBehalfOf: 'کی جانب سے',
+ newPatientHasToBeCreated: 'ایک نیا مریض بنایا جانا ضروری ہے ... براہ کرم انتظار کریں ...',
+ noNotesAvailable: 'کوئی اضافی کلینکل نوٹ اس دورے کے لئے دستیاب نہیں.',
+ sorry: 'معاف کرنا، کچھ غلط ہوگیا...',
+ forAuthorizedPersons: 'یہ رپورٹ صرف مجاز افراد کے لئے ہے.',
+ requiredFieldsCorrectErrors: 'ضرورت ہے کہ خالی قطعات (* کے نشان) میں بھریں اور محفوظ کرنے سے پہلے غلطیوں کو درست کریں.',
+ saveActionException: 'محفوظ کرنے کی کوشش کرتے ہوئے ایک خرابی واقع ہوئی ہے: {{message}}',
+ reportError: 'درخواست کی رپورٹ کو پیدا کرتے وقت ایک خرابی کا سامنا ہوا۔ براہ مہربانی اپنے سسٹم ایڈمنسٹریٹر کے علم میں لائیں کہ آپ کو خرابی کا سامنا ہوا'
+ },
+ alerts: {
+ pleaseWait: 'برائے مہربانی انتظار کریں',
+ warningExclamation: 'انتباہ !!!!',
+ errorExclamation: 'خرابی !!!!',
+ reportError: ' رپورٹ کی تیاری میں خرابی'
+ },
+ headings: {
+ chargedItems: 'چارج اشیا'
+ },
+ buttons: {
+ addItem: 'آئٹم شامل کریں',
+ complete: 'مکمل',
+ cancel: 'منسوخ کریں',
+ close: 'بند کریں',
+ returnButton: 'واپسی',
+ barcode: 'بارکوڈ',
+ add: 'شامل کریں',
+ update: 'اپ ڈیٹ',
+ ok: 'ٹھیک ہے',
+ fulfill: 'پورا کریں',
+ remove: 'دور کریں',
+ delete: 'حذف کریں',
+ newUser: 'نیا صارف',
+ addValue: 'قیمت جمع کریں',
+ newNote: 'نیا نوٹ',
+ import: ' امپورٹ کریں',
+ loadFile: 'فائل لوڈ کریں',
+ newRequest: 'نئی درخواست',
+ allRequests: 'تمام درخواستیں',
+ dispense: 'تقسیم',
+ newItem: '+ نیا آئٹم',
+ newRequestPlus: '+ نئی درخواست',
+ addVisit: 'دورہ میں شامل کریں',
+ search: 'تلاش کریں',
+ filter: 'فلٹر',
+ clear: 'صاف',
+ edit: 'تصیح',
+ addLineItem: 'لائن آئٹم شامل کریں',
+ showFewer: 'کم دکھائیں',
+ showAll: 'سارے دکھائیں'
+ },
+ login: {
+ messages: {
+ signIn: 'سائن ان کریں',
+ error: 'یوزر نیم یا پاس ورڈ غلط ہے.'
+ },
+ labels: {
+ password: 'پاس ورڈ',
+ username: 'یوزر نیم',
+ signIn: 'سائن ان '
+ }
+ },
+ loading: {
+ progressBar: {
+ progress: '{{progressBarValue}}٪ مکمل'
+ },
+ messages: {
+ 0: 'سب سے تیز تیتلی پرواز کی رفتار فی گھنٹہ 12 میل ہے. کچھ کیڑے 25 میل فی گھنٹہ کی رفتار سے پرواز کر سکتے ہیں',
+ 1: ' پرندے میں صرف اللو ہیں جو نیلا رنگ دیکھ سکتے ہیں',
+ 2: 'بلی کی 100 مختلف آوازیں ہیں؛ کتے کی صرف 10 ہیں',
+ 3: 'انسان تقریر میں 72 مختلف پٹھوں کی کل استعمال کرتے ہیں',
+ 4: ' افریقہ کے براعظم میں 1،000 سے زائد مختلف زبانیں بولی جاتی ہیں',
+ 5: ' اراۓتھروفوب وہ ہے جو آسانی سے شرما جاۓ ',
+ 6: 'دنیا میں سب سے زیادہ عام فوبیا درد کا خوف ہے جو اوڈاۓنوفوبیا ہے',
+ 7: ' آپ جب بھی کھڑے ہوتے ہیں آپ کا جسم خود کو متوازن کرنے کے لیے 300 پٹھوں کا استعمال کرتا',
+ 8: 'بعض میںڈک منجمد ٹھوس ہوسکتے ہیں پھر پگھل جائیں تو بھی جی سکتے ہیں',
+ 9: 'ہماری آنکھیں پیدائش سے ہی اسی ہجم کی ہیں، لیکن ہماری ناک اور کان کبھی بڑھنا نہیں رکتی',
+ 10: 'آپ کی زبان آپ کے جسم میں واحد پٹھہ ہے جو صرف ایک طرف سے منسلک ہے',
+ 11: 'اونٹ کی تین پلکیں ہوتی ہیں جو اڑتی ریت سے بچانے کے لئے ہیں۔'
+ }
+ },
+ inventory: {
+ edit: {
+ cost: 'فی یونٹ لاگت:',
+ delivered: 'وصول کنندہ:',
+ location: 'مقام کی درستگی:',
+ prescription: 'نسخہ براۓ:',
+ pulled: 'سے نکالا:',
+ quantity: 'تکمیل پر مقدار:',
+ reason: 'وجہ:',
+ returned: 'مریض سے واپس',
+ transferredFrom: 'سے منتقل:',
+ transferredTo: 'میں منتقل کر دیا:'
+ },
+ labels: {
+ action: 'عمل',
+ add: 'شامل کریں',
+ adjust: 'درست کریں',
+ adjustmentDate: 'درستگی کی تاریخ',
+ adjustmentFor: 'درستگی براۓ',
+ adjustmentType: 'درستگی کی قسم',
+ aisle: 'راہداری',
+ aisleLocation: 'راہداری مقام',
+ allInventory: 'تمام انوینٹری',
+ availableQuantity: '{{quantity}} دستیاب',
+ billTo: 'کا بل',
+ consumePurchases: 'کھپت خریداریاں',
+ consumptionRate: 'کھپت کی شرح',
+ cost: 'لاگت',
+ costPerUnit: 'فی یونٹ لاگت',
+ crossReference: 'دوطرفی حوالہ',
+ currentQuantity: 'موجودہ مقدار',
+ dateCompleted: 'تاریخ مکمل',
+ dateEffective: 'تاریخ نافذ',
+ dateEnd: 'آخری تاریخ',
+ dateStart: 'شروع کرنے کی تاریخ',
+ dateReceived: 'تاریخ موصولی',
+ dateTransferred: 'تاریخ منتقل',
+ daysLeft: 'دن باقی',
+ deliveryAisle: 'ڈلیوری راہداری',
+ deliveryLocation: 'ترسیل کے محل وقوع',
+ distributionUnit: 'تقسیم کا یونٹ',
+ deleteItem: 'آٹم حذف کریں',
+ details: 'تفصیلات دیکھیں',
+ editItem: 'آٹم میں ترمیم',
+ expense: 'کرنے کے اخراجات',
+ expirationDate: 'میعاد ختم ہونے کی تاریخ',
+ fulfillRequest: 'درخواست کو پورا کریں',
+ fulfillRequestNow: 'ابھی درخواست کو پورا کریں',
+ gift: 'خیراتی تحفہ',
+ giftUsage: 'خیراتی تحفہ کا استعمال',
+ giftInKindNo: 'نہیں',
+ giftInKindYes: 'ہاں',
+ inventoryConsumed: 'انوینٹری کھپت',
+ inventoryItem: 'انوینٹری آئٹم',
+ inventoryObsolence: 'متروک انوینٹری',
+ invoiceItems: 'رسید اشیاء',
+ invoiceLineItem: 'رسید لائن آئٹم',
+ invoiceNumber: 'رسید نمبر',
+ item: 'آئٹم',
+ items: 'اشیاء',
+ itemNumber: 'آئٹم نمبر',
+ location: 'مقام',
+ locations: 'مقامات',
+ name: 'نام',
+ markAsConsumed: 'خرچ شدہ کے طور پر درج کریں',
+ newItem: 'نئی آٹم',
+ allItems: 'تمام چیزیں',
+ originalQuantity: 'اصل مقدار',
+ print: 'پرنٹ',
+ printBarcode: 'پرنٹ بارکوڈ',
+ printer: 'پرنٹر',
+ pullFrom: 'سے ھیںچو',
+ purchases: 'خریداری',
+ purchaseCost: 'خریداری کی لاگت',
+ purchaseInfo: 'خریداری کی معلومات',
+ quantity: 'مقدار ({{unit}})',
+ quantityAvailable: 'دستیاب مقدار',
+ quantityOnHand: 'موجودہ مقدار',
+ quantityRequested: ' درخواست کی گئی مقدار',
+ rank: 'درجہ',
+ reason: 'وجہ',
+ remove: 'دور کریں',
+ reorderPoint: ' پوائنٹ پھر ترتیب کریں',
+ requestedItems: 'درخواست کی گئی اشیاء',
+ salePricePerUnit: 'فی یونٹ فروخت کی قیمت',
+ save: 'محفوظ کریں',
+ serialNumber: 'سیریل / لوٹ نمبر',
+ total: 'کل',
+ totalCost: 'کل لاگت',
+ totalReceived: 'کل موصول: {{total}}',
+ transaction: 'ٹرانزیکشن',
+ transactions: 'ٹرانزیکشنز',
+ transfer: 'منتقلی',
+ transferFrom: 'سے منتقلی',
+ transferTo: 'مقام پر منتقلی',
+ transferToAisle: 'مقام راہداری پر منتقلی',
+ unit: 'یونٹ',
+ unitCost: 'یونٹ کی لاگت',
+ vendor: 'وینڈر',
+ vendorItemNumber: 'وینڈر آئٹم نمبر',
+ xref: 'XRef'
+ },
+ messages: {
+ adjust: ' فرق کے تخمینہ کے لئے مناسب جگہ (جگہوں) پر مقدار کو ٹھیک کریں {{difference }}.',
+ createRequest: 'ایک نئی درخواست بنائیں؟',
+ delete: ' آپ کو یقین ہے کہ آپ حذف کرنا چاہتے ہیں؟ {{name}} ',
+ itemNotFound: '
ورنہ واپس جانے کے لیے منسوخ کا بٹن دبائیں
اگر آپ ایک نیا انونٹری آئٹم تخلیق کرنا چاہتے ہیں تو ذیل میں معلومات درج کریں۔ {{item}}انونٹری آئٹم نہیں ملا۔ ',
+ loading: 'ٹراسیکشنر لوڈ ہو رہی ہے۔۔۔',
+ purchaseSaved: 'انونٹری کی خریداری کو کامیابی سے محفوظ کر لیا گیا ہے۔',
+ noRequests: 'کوئی درخواستیں نہیں ملی۔',
+ noItems: 'کوئی آئٹم نہیں ملا۔',
+ quantity: ' کے مقامات میں کل مقدار سے مماثل نہیں ہے ({{locationQuantity}})کی کل مقدار ({{quantity}})',
+ removeItem: ' آپ کو یقین ہے کہ آپ اس آٹم کو رسید سے ہٹانا چاہتے ہیں؟',
+ removeItemRequest: ' آپ کو یقین ہے کہ آپ اس آٹم کو درخواست سے ہٹانا چاہتے ہیں؟',
+ requestFulfilled: 'انونٹری کی درخواست پوری ہو گئی.',
+ requestUpdated: 'انونٹری درخواست کو اپ ڈیٹ کر دیا گیا ہے.',
+ warning: 'ضروری ہے (* کے نشان والے) قطعات میں بھرنا اور شامل کرنے سے پہلے غلطیوں کو درست کریں۔'
+ },
+ reports: {
+ rows: {
+ adjustments: 'درستگیاں',
+ adjustmentsTotal: 'کل درستگیاں',
+ balanceBegin: 'ابتدائی بقایا رقم',
+ balanceEnd: 'اختمام پر بقایا رقم',
+ category: 'قسم',
+ consumed: 'کھپت',
+ consumedGik: 'کی کھپت GiK',
+ consumedGikTotal: 'کی کھپت GiK کل',
+ consumedPuchases: 'خریداری کی کھپت',
+ consumedPurchasesTotal: 'کل خریداری کی کھپت',
+ consumedTotal: 'کل کھپت',
+ errInFinSum: '_generateFinancialSummaryReport میں خرابی: ',
+ errInFindPur: '_findInventoryItemsByPurchase میں خرابی: ',
+ errInFindReq: '_findInventoryItemsByRequest میں خرابی: ',
+ expensesFor: 'کے لئے اخراجات: ',
+ noAccount: '(کوئی اکاؤنٹ نہیں)',
+ subtotal: 'ذیلی کل: ',
+ subtotalFor: '{{account}} - {{category}}ذیلی کل ',
+ total: 'کل: ',
+ totalFor: ' کل براۓ {{var}}: ',
+ totalPurchases: 'کل خریداری',
+ transfer1: '{{quantity }} سے {{location }}',
+ trasnfer2: '{{target}} :براۓ{{source}} :منجانب'
+ },
+ adjustment: 'تفصیلی درستگی',
+ daysSupply: 'اسٹاک میں دنوں کی فراہمی',
+ expenseDetail: 'تفصیلی اخراجات',
+ expenseSum: 'خلاصہ اخراجات',
+ expiration: 'میعاد ختم ہونے کی تاریخ',
+ export: 'ایکسپورٹ رپورٹ',
+ fields: ' شامل کرنے کے قطعات',
+ finance: 'مالیات کا خلاصہ',
+ generate: 'رپورٹ بنائیں',
+ invLocation: 'محل وقوع کے اعتبار انوینٹری',
+ invValuation: 'انوینٹری کی مالیت',
+ purchaseDetail: 'تفصیلی خرید',
+ purchaseSum: 'خلاصہ خرید',
+ reportType: 'رپورٹ کی قسم',
+ stockTransferDetail: 'تفصیلی اسٹاک کی منتقلی',
+ stockTransferSum: 'خلاصہ اسٹاک کی منتقلی',
+ stockUsageDetail: 'تفصیلی اسٹاک استعمال',
+ stockUsageSum: 'خلاصہ اسٹاک استعمال',
+ titleSingleDate: '{{date}} رپورٹ {{name}}',
+ titleDateRange: '{{startDate}} - {{endDate}} رپورٹ {{name}}'
+ },
+ titles: {
+ addPurchase: 'خریداری شامل کریں',
+ addRequest: 'نئی درخواست',
+ adjustment: 'درستگی',
+ editPurchase: 'خریداری میں ترمیم کریں',
+ editRequest: 'تصیح کی گذارش',
+ inventoryItem: 'نئے انوینٹری آئٹم',
+ inventoryReport: 'انوینٹری کی رپورٹ',
+ purchaseSaved: 'انوینٹری خریداریاں محفوظ کرلی',
+ quickAddTitle: 'نئے انوینٹری آئٹم',
+ removeItem: 'آئٹم ہٹائیں',
+ requestFulfilled: 'درخواست پوری',
+ requestUpdated: 'درخواست اپ ڈیٹ ہوگئی',
+ transfer: ' اشیا منتقل کریں',
+ warning: 'انتباہ!!!'
+ }
+ },
+ imaging: {
+ pageTitle: 'امیجنگ درخواستیں',
+ sectionTitle: 'امیجنگ',
+ buttons: {
+ newButton: '+ نئے امیجنگ'
+ },
+ labels: {
+ radiologist: 'ریڈیولوجسٹ',
+ addNewVisit: '--- نیا دورہ شامل کریں ---'
+ },
+ messages: {
+ delete: ' آپ کو یقین ہے کہ آپ امیجنگ درخواست کو حذف کرنا چاہتے ہیں؟',
+ noCompleted: 'کوئی مکمل اشیاء نہیں موجود۔'
+ },
+ titles: {
+ completedImaging: 'امیجنگ مکمل',
+ editTitle: 'امیجنگ ترمیم کی گذارش',
+ newTitle: 'نئے امیجنگ گذارش'
+ },
+ alerts: {
+ completedTitle: 'امیجنگ درخواست مکمل',
+ completedMessage: 'امیجنگ درخواست کو مکمل کیا گیا ہے',
+ savedTitle: 'امیجنگ گذارش بچا لیا',
+ savedMessage: 'امیجنگ درخواست کو محفوظ کر لیا گیا ہے۔'
+ }
+ },
+ medication: {
+ pageTitle: 'ادویات کی درخواستیں',
+ sectionTitle: 'ادویات',
+ returnMedication: 'واپس دوا',
+ buttons: {
+ dispenseMedication: 'ادویات تقسیم',
+ newButton: '+ نئی درخواست',
+ returnMedication: 'واپسی دوا'
+ },
+ titles: {
+ completedMedication: 'مکمل دوا',
+ editMedicationRequest: 'ادویات میں ترمیم کی درخواست',
+ newMedicationRequest: 'نئی دوا کی گذارش'
+ },
+ messages: {
+ createNew: 'ایک نئی دوا کی درخواست بنائیں؟',
+ confirmDeletion: ' آپ کو یقین ہے کہ آپ اس دوا کی درخواست کو حذف کرنا چاہتے ہیں؟'
+ },
+ labels: {
+ refills: 'دوبارہ بھریں',
+ quantityRequested: ' درخواست کی گئی مقدار',
+ quantityDispensed: 'تقسیم یا استعمال کی گئی مقدار',
+ quantityDistributed: 'تقسیم کی گئی مقدار',
+ quantityToReturn: 'مقدار براۓ واپسی',
+ returnLocation: ' مقام واپسی',
+ returnAisle: 'واپسی راہداری',
+ returnReason: 'واپسی کی وجہ / نوٹس',
+ adjustmentDate: 'تاریخ درستگی',
+ creditToAccount: 'اکاؤنٹ کو کریڈٹ'
+ },
+ alerts: {
+ returnedTitle: 'واپس کی گئی ادویات',
+ returnedMessage: 'ادویات پر واپس کر دی گئی کا نشان لگا دیا گیا ہے۔',
+ savedTitle: 'ادویات کی درخواست محفوظ کر لی گئی',
+ savedMessage: 'ادویات کا ریکارڈ محفوظ ہوگیا ہے۔',
+ fulfilledTitle: 'ادویات درخواست پوری'
+ }
+ },
+ appointments: {
+ currentScreenTitle: 'ملاقات کی فہرست',
+ editTitle: 'ملاقات میں ترمیم کریں',
+ newTitle: 'نئی ملاقات',
+ sectionTitle: 'ملاقاتیں',
+ thisWeek: 'اس ہفتہ کی ملاقاتیں',
+ missed: 'چوک جانے والی ملاقاتیں',
+ searchTitle: 'ملاقاتیں تلاش کریں',
+ todayTitle: 'آج کی ملاقاتیں',
+ calendarTitle: ' ملاقات کا کیلنڈر',
+ messages: {
+ appointmentSaved: ' - مریض کے ساتھ ملاقات محفوظ کر لی گئی ہے {{patient}}',
+ deleteAppointmentMessage: ' آپ کو یقین ہے کہ آپ اس ملاقات کو حذف کرنا چاہتے ہیں؟',
+ endTimeLaterThanStart: 'براہ مہربانی وقت آغاز کے بعد کا ختم وقت منتخب کریں۔'
+ },
+ buttons: {
+ newButton: '+ نئی ملاقات',
+ scheduleSurgery: ' + سرجری کا وقت مقرر کریں'
+ },
+ labels: {
+ noLocation: 'کوئی مقام نہیں',
+ selectedStartingDate: 'اس تاریخ پر یا اس کے بعد کی ملاقاتیں دیکھیں'
+ },
+ titles: {
+ appointmentSaved: 'ملاقات محفوظ کر لی گئی',
+ editSurgicalAppointment: 'سرجری کی ملاقات میں ترمیم کریں',
+ newSurgicalAppointment: 'نئی سرجری کی ملاقات',
+ theaterSchedule: 'تھیٹر اوقات نامہ'
+ }
+ },
+ vitals: {
+ messages: {
+ delete: 'آپ کو یقین ہے کہ آپ ان کو حذف کرنا چاہتے ہیں؟ vitals'
+ },
+ labels: {
+ dateRecorded: 'تاریخ اندراج',
+ temperature: 'درجہ حرارت',
+ weight: 'وزن',
+ height: 'اونچائی',
+ sbp: 'SBP',
+ dbp: 'DBP',
+ heartRate: 'دل کی دھڑکن کی شرح',
+ respiratoryRate: 'سانس کی شرح'
+ }
+ },
+ visits: {
+ titles: {
+ additionalDiagnoses: 'اضافی تشخیص',
+ checkedIn: 'مریض چیک ان مکمل',
+ checkOut: 'مریض چیک آٹ',
+ checkedOut: 'مریض چیک آٹ مکمل',
+ discharged: 'مریض فارغ کر دیا گیا',
+ editVisit: 'دورہ ترمیم کریں',
+ newVisit: 'نیا دورہ',
+ patientCheckIn: 'مریض چیک ان',
+ visitSaved: 'دورہ محفوظ'
+ },
+ messages: {
+ delete: 'آپ کو یقین ہے کہ آپ اس دورے حذف کرنا چاہتے ہیں؟',
+ checkOut: 'کو چیک آٹ کرنا چاہتے ہیں؟ {{patientName}} آپ کو یقین ہے کہ آپ ',
+ checkedOut: 'چیک آٹ کر دیا گیا ہے {{patientName}} ',
+ discharged: ' کو فارغ کر دیا گیا ہے {{patientName}} ',
+ patientCheckedIn: 'چیک ان کر دیا گیا ہے {{patientName}} ',
+ patientCreatedAndCheckedIn: ' ۔ (مریض) بنا دیا گیا ہے اور چیک ان کر دیا گیا ہے {{patientName}} ',
+ visitAndPatientSaved: 'دورے اور مریض ریکارڈ محفوظ کیا گیا ہے۔',
+ visitSaved: 'دورہ کا ریکارڈ کو محفوظ کیا گیا ہے۔'
+ },
+ buttons: {
+ newProcedure: 'نئے طریقہ کار',
+ newAppointment: 'نئی ملاقات',
+ addDiagnosis: 'تشخیص کے لئے شامل کریں',
+ newVitals: 'نئے vitals',
+ checkIn: 'چیک ان',
+ checkOut: 'چیک آٹ',
+ discharge: 'فارغ کر دیں'
+ },
+ labels: {
+ diagnosis: 'تشخیص',
+ procedure: 'ضابطے',
+ procedureDate: 'ضابطے کی تاریخ',
+ authoredBy: 'کی طرف سے تحریر',
+ visitInformation: 'دورہ معلومات',
+ examiner: 'معائنہ کار',
+ status: 'دورہ کی صورتحال',
+ finalDiagnosis: 'حتمی / بلنگ تشخیص',
+ visitDate: 'دورہ کی تاریخ',
+ visitType: 'دورہ کی قسم',
+ patientToCheckIn: 'مریض کا چیک ان کرنا',
+ checkInTime: 'چیک ان',
+ checkOutTime: 'چیک آٹ',
+ appointment: 'ملاقات',
+ haveAppointment: 'ہاں',
+ noAppointment: 'نہیں',
+ ordersDone: 'آرڈرز مکمل کر دیے گئے',
+ haveDoneOrders: 'ہاں',
+ ordersNotDone: 'نہیں',
+ reasonForVisit: 'دورے کی وجہ',
+ statusAdmitted: 'داخل کر دیا گیا',
+ statusDischarged: 'فارغ کر دیا گیا',
+ statusCheckedIn: 'چیک ان کر دیا گیا',
+ statusCheckedOut: 'چیک آٹ کر دیا گیا',
+ createNewPatient: 'نیا مریض بنائیں'
+ },
+ navigation: {
+ charges: 'چارجز',
+ notes: 'نوٹس',
+ orders: 'آرڈرز',
+ procedures: 'طریقہ کار',
+ vitals: 'Vitals'
+ }
+ },
+ labs: {
+ sectionTitle: 'لیبز',
+ requestsTitle: 'لیب درخواستیں',
+ editTitle: 'لیب میں ترمیم کی درخواست',
+ newTitle: 'نئے لیب کی گذارش',
+ deleteTitle: 'درخواست حذف کریں',
+ completedTitle: 'مکمل لیبز',
+ labels: {
+ labType: 'لیب کی قسم',
+ addNewVisit: '۔۔ نیا دورہ شامل کریں ۔۔'
+ },
+ messages: {
+ noItemsFound: 'کوئی لیب موجود نہیں',
+ createNewRecord: 'ایک نیا ریکارڈ بنائیں؟',
+ confirmDeletion: 'آپ کو یقین ہے کہ آپ اس لیب کی درخواست کو حذف کرنا چاہتے ہیں؟',
+ noCompleted: 'کوئی مکمل آئٹم موجود نہیں'
+ },
+ buttons: {
+ newButton: '+ نئی لیب'
+ },
+ alerts: {
+ requestCompletedTitle: 'لیب درخواست مکمل',
+ requestCompletedMessage: 'لیب کی درخواست مکمل ہو گئی ہے',
+ requestSavedTitle: 'لیب کی درخواست محفوظ',
+ requestSavedMessage: 'لیب کی درخواست محفوظ ہو گئی ہے۔'
+ }
+ },
+ patients: {
+ navigation: {
+ photos: 'تصاویر',
+ general: 'عمومی',
+ history: 'سرگزشت',
+ appointments: 'ملاقاتیں',
+ visits: 'دورے',
+ medication: 'ادویات',
+ imaging: 'امیجنگ',
+ labs: 'لیبز',
+ socialWork: 'سماجی کام'
+ },
+ titles: {
+ addContact: 'رابطہ شامل کریں',
+ admittedPatients: 'داخل کیے گئے مریض',
+ expenses: 'اخراجات',
+ additionalContacts: 'اضافی رابطے',
+ familyInformation: 'خاندان کی معلومات',
+ delete: 'مریض کو حذف کریں',
+ new: 'نئے مریض',
+ edit: 'مریض میں ترمیم کریں',
+ patient: 'مریض رپورٹ',
+ patientListing: 'مریض کی فہرست سازی',
+ patientReport: 'مریض رپورٹ',
+ addPhoto: 'تصویر کا اضافہ کریں',
+ editPhoto: 'تصویر میں ترمیم کریں',
+ socialWork: 'خرچہ',
+ familyInfo: 'خاندانی معلومات',
+ deleteFamilyMember: 'خاندان کے فرد کو حذف کریں',
+ deleteExpense: 'خرچہ حذف کریں',
+ deletePhoto: 'تصویر حذف کریں',
+ deleteContact: 'رابطہ کریں حذف کریں',
+ savedPatient: 'مریض محفوظ ہو گیا',
+ todaysOutpatients: 'آج کے بیرونی مریضوں',
+ admissionsDetail: 'داخلوں کی تفصیل',
+ admissionsSummary: 'داخلوں کا خلاصہ',
+ diagnosticTesting: 'تشخیصی جانچ',
+ dischargesDetail: 'فارغ کرنے کی تفصیل',
+ dischargesSummary: 'فارغ کرنے کا خلاصہ',
+ proceduresDetail: 'طریقہ کار کی تفصیل',
+ proceduresSummary: 'طریقہ کار کا خلاصہ',
+ patientStatus: 'مریض کی صورتحال',
+ totalPatientDays: 'مریض کے کل دن',
+ totalPatientDaysDetailed: 'مریض کے کل دن(تفصیلی) ۔',
+ visit: 'دورہ',
+ deletePatientRecord: 'مریض ریکارڈ حذف کریں',
+ outpatientsForDate: '{{visitDate}} بیرونی مریض برائے '
+ },
+ messages: {
+ areYouSureDelete: ' کو حذف کرنا چاہتے ہیں؟ {{object}} آپ کو یقین ہے کہ آپ اس ',
+ deletePatient: ' کو حذف کرنا چاہتے ہیں؟ {{lastName}} {{firstName}} آپ کو یقین ہے کہ آپ اس مریض ',
+ noPatientsFound: 'کوئی مریض نہیں ملا۔',
+ savedPatient: ' کے لئے مریض کا ریکارڈ محفوظ ہوگیا ہے۔ {{displayName}} ',
+ notFoundQuickAdd: ' مریض نہیں مل سکا۔ اگر آپ کو ایک نیا مریض بنانا چاہتے ہیں تو ذیل میں معلومات درج کیجے۔ ورنہ واپس جانے کے کیے منسوخ کا بٹن دبائیں۔ {{patientFullName}} ',
+ createNewPatient: 'ایک نیا مریض ریکارڈ بنائیں؟',
+ deletingPatient: 'مریض اور سارے متعلقہ ریکارڈز حذف کیا جا رہا ہے'
+ },
+ buttons: {
+ addExpense: 'اخراجات میں شامل کریں',
+ addContact: 'رابطہ شامل کریں',
+ addOperativePlan: 'آپریٹو پلان میں شامل کریں',
+ editOperativePlan: 'موجودہ آپریٹو پلان',
+ newLab: 'نئی لیب',
+ newVisit: 'نیا دورہ',
+ newMedication: 'نئی دوا',
+ newImaging: 'نئی امیجنگ',
+ addFamilyMember: 'خاندان کا فرد شامل کریں',
+ newPhoto: 'نئی تصویر',
+ newAppointment: 'نئی ملاقات',
+ backToPatients: 'مریض کی فہرست پر واپس جائیں',
+ newPatient: '+ نیا مریض',
+ patientCheckIn: 'مریض کا چیک ان',
+ scheduleSurgery: 'سرجری کا وقت مقرر کریں'
+ },
+ labels: {
+ primaryDiagnosis: 'بنیادی تشخیص',
+ secondaryDiagnosis: 'ثانوی تشخیص',
+ monthlyCost: 'ماہانہ اخراجات',
+ totalMontlyExpense: 'مجموعی ماہانہ اخراجات',
+ patientType: 'مریضوں کی اقسام',
+ admissionDate: 'داخلے کی تاریخ',
+ patientDays: 'مریض کے دن',
+ dischargeDate: 'فارغ کرنے کی تاریخ',
+ admit: 'داخل کریں',
+ relationships: 'تعلقات',
+ phone: 'فون',
+ email: 'ای میل',
+ firstName: 'نام کا پہلا حصہ',
+ middleName: 'نام کا درمیانی حصہ',
+ lastName: 'نام کا آخری حصہ',
+ sex: 'جنس',
+ dob: 'DOB',
+ dateOfBirth: 'پیدائش کی تاریخ',
+ placeOfBirth: 'جائے پیدائش',
+ sources: 'ذرائع',
+ cost: 'لاگت',
+ civilStatus: 'سول حیثیت',
+ relationship: 'مریض سے تعلق',
+ education: 'تعلیم',
+ occupation: 'پیشہ',
+ income: 'آمدن',
+ insurance: 'بیمہ',
+ dateProcessed: 'عمل درآمد کی تاریخ',
+ status: 'مریض کی صورتحال',
+ externalPatientId: 'بیرونی مریض کی شناخت',
+ bloodType: 'خون کی قسم',
+ clinic: 'کلینک کی جگہ',
+ referredBy: 'کی طرف سے بھیجا گیا',
+ referredDate: 'حوالہ دینے کی تاریخ',
+ religion: 'مذہب',
+ parent: 'والدین / سرپرست',
+ contacts: 'رابطے',
+ sexNotEntered: 'جنس داخل نہیں کیا گیا',
+ operativePlan: 'آپریٹو پلان'
+ },
+ notes: {
+ newNote: 'نیا نوٹ برائے',
+ updateNote: 'کی صرف سے نوٹ اپ ڈیٹ ہورہے ہیں',
+ onBehalfOfLabel: 'کی جانب سے',
+ onBehalfOfCopy: 'کی جانب سے',
+ pleaseSelectAVisit: 'ایک دورے براہ مہربانی منتخب کریں'
+ }
+ },
+ billing: {
+ alerts: {
+ noInvoiceFound: 'کوئی رسید نہیں ملی',
+ deleteItem: '{{item}} آپ کو یقین ہے کہ آپ حذف کرنا چاہتے ہیں؟',
+ noPricingItems: 'کوئی قیمتوں کے تعیں والی اشیاء نہیں ملی',
+ noPricingProfiles: 'کوئی قیمتوں کے تعیں والی پروفائل نہیں ملی'
+ },
+ buttons: {
+ createInvoice: 'ایک رسید بنائیں؟',
+ addOverride: 'منسوخ شامل کریں'
+ },
+ labels: {
+ externalInvoiceNumber: 'بیرونی رسید #',
+ paymentProfile: 'ادائیگی پروفائل',
+ actualCharges: 'اصل قیمت',
+ insurance: 'قومی بیمہ',
+ hmoCom: 'HMO / COM',
+ paymentsDeposits: 'ادائیگی / جمع کھاتہ',
+ pricingPanelOverrides: 'قیمتوں کا تعین پروفائل کی منسوخی',
+ pricingProfile: 'قیمتوں کا تعین پروفائل',
+ discountAmount: 'ڈسکاؤنٹ رقم',
+ discountPercentage: 'رعایت فی صد'
+ }
+ },
+ print: {
+ invoice: {
+ labels: {
+ patientName: 'مریض کا نام:',
+ patientId: 'مریض #:',
+ patientAge: 'عمر:',
+ patientAddress: 'پتہ:',
+ dateAdmitted: 'داخلہ کی تاریخ:',
+ dateDischarged: 'فارغ کرنے کی تاریخ:',
+ dischargeNotes: 'فارغ کرنے کے نوٹس:',
+ remarks: 'خیالات:',
+ billedBy: 'بل منجانب:',
+ billedDate: 'بل کی تاریخ:',
+ spacer: '__________________________________________'
+ },
+ messages: {
+ whereConducted: 'میری محدودیت کے دوران کاٹ لیے گئے تھے'
+ },
+ titles: {
+ patientMember: 'مریض رکن',
+ relContact: 'تعلق / رابطہ نمبر',
+ patients: 'مریض کا',
+ billingStatement: 'بلنگ کی عبارت'
+ }
+ }
+ },
+ procedures: {
+ titles: {
+ addChargeItem: 'چارج آئٹم شامل کریں',
+ deleteChargeItem: 'چارج آئٹم حذف کریں',
+ editChargeItem: 'چارج آئٹم میں ترمیم کریں',
+ medicationUsed: 'استعمال کی گئی ادویات',
+ deleteMedicationUsed: 'استعمال کی گئی ادویات حذف کریں',
+ addMedicationUsed: 'استعمال کی گئی ادویات شامل کریں',
+ editMedicationUsed: 'استعمال کی گئی ادویات میں ترمیم کریں',
+ edit: 'ضابطے میں ترمیم کریں',
+ saved: 'ضابطے محفوظ',
+ new: 'نیا طریقہ کار'
+ },
+ labels: {
+ medicationUsed: 'استعمال کی گئی ادویات'
+ },
+ messages: {
+ deleteMedication: ' آپ کو یقین ہے کہ آپ ان ادویات کو حذف کرنا چاہتے ہیں؟',
+ delete: 'آپ کو اس طریقہ کار کو حذف کرنا چاہتے ہیں تمہیں یقین ہے؟',
+ saved: ' آپ کو یقین ہے کہ آپ اس طریقہ کار کو حذف کرنا چاہتے ہیں؟'
+ },
+ buttons: {
+ addMedication: 'ادویات شامل کریں'
+ }
+ },
+ components: {
+ chargesByTypeTab: {
+ charges: 'چارجز'
+ },
+ customFormManager: {
+ buttons: {
+ addForm: 'فارم کا اضافہ کریں'
+ }
+ },
+ sortableColumn: {
+ labels: {
+ selectAll: '(تمام منتخب کریں)'
+ }
+ },
+ dateTimePicker: {
+ amHour: '{{hour}} AM',
+ midnight: 'آدھی رات',
+ noon: 'دوپہر',
+ pmHour: '{{hour}} PM'
+ },
+ takePhoto: {
+ how: 'آپ ایک تصویر کو کس طرح شامل کرنا چاہتے ہیں؟',
+ takePhoto: 'تصویر کھینچیں',
+ uploadPhoto: 'تصویر اپ لوڈ کریں',
+ uploadFile: 'فائل اپ لوڈ کریں',
+ camera: 'کیمرہ',
+ photo: 'تصویر',
+ preview: 'پیش نظارہ'
+ },
+ quantityConv: {
+ unit: 'اکائی',
+ conversion: ' میں کیا شامل ہے؟ {{name}} 1'
+ },
+ quantityCalc: {
+ result: '{{targetUnit}} کل: {{calculated}}'
+ },
+ patientOrders: {
+ buttons: {
+ newImaging: 'نئی امیجنگ',
+ newLab: 'نئی لیب',
+ newMedication: 'نئی ادویات'
+ },
+ labels: {
+ imagingOrderType: 'امیجنگ',
+ labOrderType: 'لیب',
+ medicationOrderType: 'ادویات',
+ orderType: 'آرڈر کی قسم'
+ }
+ },
+ priceList: {
+ charges: '{{pricingType}} چارجز'
+ },
+ operativeProcedures: {
+ buttons: {
+ addProcedure: 'ضابطے شامل کریں'
+ },
+ labels: {
+ procedure: 'طریقہ کار'
+ },
+ titles: {
+ procedures: 'طریقہ کار/ ضابطے'
+ }
+ },
+ upcomingAppointments: {
+ labels: {
+ date: 'تاریخ',
+ with: 'کے ساتھ',
+ location: 'مقام',
+ type: 'قسم'
+ },
+ titles: {
+ upcomingAppointments: 'عنقریب آنے والی ملاقاتیں'
+ }
+ }
+ },
+ customForms: {
+ buttons: {
+ addForm: 'فارم شامل کریں'
+ },
+ labels: {
+ formToAdd: 'شامل کرنے کے لئے فارم'
+ },
+ titles: {
+ addCustomForm: 'کسٹم فارم شامل کریں'
+ }
+ },
+ diagnosis: {
+ labels: {
+ activeDiagnosis: 'فعال تشخیص',
+ date: 'تاریخ',
+ diagnosis: 'تشخیص',
+ secondaryDiagnosis: 'ثانوی تشخیص'
+ },
+ titles: {
+ addDiagnosis: 'تشخیص کے لئے شامل کریں',
+ editDiagnosis: 'تشخیص میں ترمیم کریں'
+ }
+ },
+ allergies: {
+ buttons: {
+ addAllergy: 'الرجی شامل کریں'
+ },
+ titles: {
+ addAllergy: 'الرجی شامل کریں',
+ editAllergy: 'الرجی میں ترمیم کریں'
+ },
+ labels: {
+ allergyName: 'نام',
+ patientAllergy: 'مریض کی الرجی'
+ }
+ },
+ operativePlan: {
+ buttons: {
+ completePlan: 'مکمل حکمت عمل'
+ },
+ labels: {
+ additionalNotes: 'اضافی نوٹس',
+ admissionInstructions: 'داخلے کی ہدایات',
+ caseComplexity: 'کیس پیچیدگی',
+ completedStatus: 'مکمل',
+ droppedStatus: 'گرا دیا',
+ operationDescription: 'آپریشن کی تفصیل',
+ plannedStatus: 'منصوبہ بندی کر لی گئی',
+ status: 'صورتحال',
+ surgeon: 'سرجن'
+ },
+ messages: {
+ planSaved: 'آپریٹو پلان محفوظ ہوگیا ہے۔',
+ planCompleted: 'آپریٹو پلان مکمل ہو چکا ہے۔ اب آپریشن رپورٹ کی طرف آپ کی رہنمائی کی جائے گی۔'
+ },
+ titles: {
+ editTitle: 'آپریٹو پلان میں ترمیم کریں',
+ newTitle: 'نیا آپریٹو پلان',
+ planCompleted: 'پلان مکمل',
+ planSaved: 'پلان محفوظ'
+ }
+ },
+ operationReport: {
+ labels: {
+ additionalNotes: 'اضافی نوٹس',
+ assistant: 'مددگار',
+ caseComplexity: 'کیس پیچیدگی',
+ operationDescription: 'آپریشن کی تفصیل',
+ preOpPrimaryDiagnosis: 'آپریشن سے پہلے بنیادی تشخیص',
+ preOpSecondaryDiagnosis: 'آپریشن سے پہلے ثانوی تشخیص',
+ surgeon: 'سرجن',
+ surgeryDate: 'سرجری تاریخ'
+ },
+ messages: {
+ reportSaved: 'آپریشن رپورٹ محفوظ ہوگئی ہے۔'
+ },
+ titles: {
+ editTitle: 'آپریشن رپورٹ میں ترمیم کریں',
+ newTitle: 'نئے آپریشن کی رپورٹ',
+ reportSaved: 'رپورٹ محفوظ ہوگئی'
+ }
+ },
+ application: {
+ messages: {
+ sessionExpired: 'آپ کا سیشن متروک ہو گیا ہے۔ کاروائی جاری رکھنے کے لاگ ان کریں'
+ },
+ titles: {
+ sessionExpired: 'سیشن کی مدت ختم ہوگئی'
+ }
+ }
+};
diff --git a/app/medication/edit/controller.js b/app/medication/edit/controller.js
index a3dc763294..9aaa6a6666 100644
--- a/app/medication/edit/controller.js
+++ b/app/medication/edit/controller.js
@@ -3,11 +3,10 @@ import AddNewPatient from 'hospitalrun/mixins/add-new-patient';
import Ember from 'ember';
import FulfillRequest from 'hospitalrun/mixins/fulfill-request';
import InventoryLocations from 'hospitalrun/mixins/inventory-locations'; // inventory-locations mixin is needed for fulfill-request mixin!
-import InventorySelection from 'hospitalrun/mixins/inventory-selection';
import PatientSubmodule from 'hospitalrun/mixins/patient-submodule';
import UserSession from 'hospitalrun/mixins/user-session';
-export default AbstractEditController.extend(AddNewPatient, InventorySelection, FulfillRequest, InventoryLocations, PatientSubmodule, UserSession, {
+export default AbstractEditController.extend(AddNewPatient, FulfillRequest, InventoryLocations, PatientSubmodule, UserSession, {
medicationController: Ember.inject.controller('medication'),
expenseAccountList: Ember.computed.alias('medicationController.expenseAccountList'),
diff --git a/app/medication/edit/route.js b/app/medication/edit/route.js
index 5adc466219..2f8c7f131a 100644
--- a/app/medication/edit/route.js
+++ b/app/medication/edit/route.js
@@ -3,6 +3,7 @@ import AbstractEditRoute from 'hospitalrun/routes/abstract-edit-route';
import Ember from 'ember';
import FulfillRequest from 'hospitalrun/mixins/fulfill-request';
import InventoryLocations from 'hospitalrun/mixins/inventory-locations'; // inventory-locations mixin is needed for fulfill-request mixin!
+import moment from 'moment';
import PatientListRoute from 'hospitalrun/mixins/patient-list-route';
import uuid from 'npm:uuid';
export default AbstractEditRoute.extend(FulfillRequest, InventoryLocations, PatientListRoute, {
diff --git a/app/medication/edit/template.hbs b/app/medication/edit/template.hbs
index 3ba1413ad9..ffac6d87b9 100644
--- a/app/medication/edit/template.hbs
+++ b/app/medication/edit/template.hbs
@@ -21,13 +21,6 @@
{{/if}}
- {{#if model.patient.allergies}}
-
-
- {{medication-allergy patient=model.patient}}
-
-
- {{/if}}
{{#if isFulfilledOrRequested}}
@@ -74,7 +67,7 @@
{{select-or-typeahead property="expenseAccount" label=(t 'labels.billTo') list=expenseAccountList selection=model.expenseAccount }}
{{inventory-location-picker label=(t 'labels.pullFrom') quantityRequested=model.quantity
locationList= model.inventoryItem.availableLocations
- selectedLocations=model.inventoryLocations
+ selectedLocations=model.inventoryLocations class="inventory-location"
}}
{{/if}}
{{/if}}
diff --git a/app/medication/return/controller.js b/app/medication/return/controller.js
index 1ccd1f084d..511cbc2eee 100644
--- a/app/medication/return/controller.js
+++ b/app/medication/return/controller.js
@@ -3,11 +3,10 @@ import AbstractEditController from 'hospitalrun/controllers/abstract-edit-contro
import Ember from 'ember';
import FulfillRequest from 'hospitalrun/mixins/fulfill-request';
import InventoryLocations from 'hospitalrun/mixins/inventory-locations'; // inventory-locations mixin is needed for fulfill-request mixin!
-import InventorySelection from 'hospitalrun/mixins/inventory-selection';
import PatientSubmodule from 'hospitalrun/mixins/patient-submodule';
import SelectValues from 'hospitalrun/utils/select-values';
-export default AbstractEditController.extend(FulfillRequest, InventoryLocations, InventorySelection, PatientSubmodule, {
+export default AbstractEditController.extend(FulfillRequest, InventoryLocations, PatientSubmodule, {
medicationController: Ember.inject.controller('medication'),
medicationList: [],
diff --git a/app/mixins/date-format.js b/app/mixins/date-format.js
index c08c6be0fb..0f9c889180 100644
--- a/app/mixins/date-format.js
+++ b/app/mixins/date-format.js
@@ -1,4 +1,5 @@
import Ember from 'ember';
+import moment from 'moment';
export default Ember.Mixin.create({
_dateFormat(value, dateFormat) {
if (Ember.isEmpty(dateFormat)) {
diff --git a/app/mixins/diagnosis-actions.js b/app/mixins/diagnosis-actions.js
index 98c79e5d7a..f0bcd50a47 100644
--- a/app/mixins/diagnosis-actions.js
+++ b/app/mixins/diagnosis-actions.js
@@ -1,14 +1,6 @@
import Ember from 'ember';
-const {
- computed
-} = Ember;
-
export default Ember.Mixin.create({
- canAddDiagnosis: computed(function() {
- return this.currentUserCan('add_diagnosis');
- }),
-
editDiagnosis(diagnosis) {
diagnosis.set('editController', this);
this.send('openModal', 'diagnosis.edit', diagnosis);
diff --git a/app/mixins/dob-days.js b/app/mixins/dob-days.js
index 0547bc3b91..cf6e1d90ee 100644
--- a/app/mixins/dob-days.js
+++ b/app/mixins/dob-days.js
@@ -1,4 +1,5 @@
import Ember from 'ember';
+import moment from 'moment';
export default Ember.Mixin.create({
convertDOBToText(birthDate, shortFormat, omitDays) {
let today = new Date();
diff --git a/app/mixins/inventory-selection.js b/app/mixins/inventory-selection.js
deleted file mode 100644
index 71b4e381ca..0000000000
--- a/app/mixins/inventory-selection.js
+++ /dev/null
@@ -1,21 +0,0 @@
-import Ember from 'ember';
-export default Ember.Mixin.create({
- selectedInventoryItem: null,
-
- /**
- * For use with the inventory-type ahead. When an inventory item is selected, resolve the selected
- * inventory item into an actual model object and set is as inventoryItem.
- */
- inventoryItemChanged: function() {
- let selectedInventoryItem = this.get('selectedInventoryItem') || this.get('model.selectedInventoryItem');
- if (!Ember.isEmpty(selectedInventoryItem)) {
- this.store.find('inventory', selectedInventoryItem.id).then(function(inventoryItem) {
- let model = this.get('model');
- model.set('inventoryItem', inventoryItem);
- Ember.run.once(this, function() {
- model.validate().catch(Ember.K);
- });
- }.bind(this));
- }
- }.observes('selectedInventoryItem', 'model.selectedInventoryItem')
-});
diff --git a/app/mixins/modal-helper.js b/app/mixins/modal-helper.js
index 4bb6075e80..d9bbdf39a7 100644
--- a/app/mixins/modal-helper.js
+++ b/app/mixins/modal-helper.js
@@ -4,17 +4,22 @@ export default Ember.Mixin.create({
* Display a message in a closable modal.
* @param title string containing the title to display.
* @param message string containing the message to display.
+ * @param okAction string containing the optional action to fire when the ok button is clicked.
+ * @param okContext object containing the context to pass to the okAction.
+ * @param cancelAction string containing the optional action to fire when the cancel button is clicked or the escape button is pressed.
*/
- displayAlert(title, message, okAction) {
+ displayAlert(title, message, okAction, okContext, cancelAction) {
let i18n = this.get('i18n');
let modalOptions = Ember.Object.extend({
updateButtonText: i18n.t('buttons.ok')
});
this.send('openModal', 'dialog', modalOptions.create({
- title,
+ cancelAction,
+ hideCancelButton: true,
message,
okAction,
- hideCancelButton: true,
+ okContext,
+ title,
updateButtonAction: 'ok'
}));
},
diff --git a/app/mixins/navigation.js b/app/mixins/navigation.js
index 1da69e266f..b6c7380402 100644
--- a/app/mixins/navigation.js
+++ b/app/mixins/navigation.js
@@ -77,41 +77,60 @@ export default Ember.Mixin.create({
]
},
{
- title: 'Appointments',
+ title: 'Scheduling',
iconClass: 'octicon-calendar',
route: 'appointments.index',
capability: 'appointments',
subnav: [
{
- title: 'This Week',
+ title: 'Appointments This Week',
iconClass: 'octicon-chevron-right',
route: 'appointments.index',
capability: 'appointments'
},
{
- title: 'Today',
+ title: 'Today\'s Appointments',
iconClass: 'octicon-chevron-right',
route: 'appointments.today',
capability: 'appointments'
},
{
- title: 'Missed',
+ title: 'Missed Appointments',
iconClass: 'octicon-chevron-right',
route: 'appointments.missed',
capability: 'appointments'
},
{
- title: 'Search',
+ title: 'Appointment Search',
iconClass: 'octicon-search',
route: 'appointments.search',
capability: 'appointments'
},
+ {
+ title: 'Appointments Calendar',
+ iconClass: 'octicon-calendar',
+ route: 'appointments.calendar',
+ capability: 'appointments'
+ },
{
title: 'Add Appointment',
iconClass: 'octicon-plus',
route: 'appointments.edit',
subroute: 'new',
capability: 'add_appointment'
+ },
+ {
+ title: 'Theater Schedule',
+ iconClass: 'octicon-calendar',
+ route: 'appointments.theater',
+ capability: 'appointments'
+ },
+ {
+ title: 'Schedule Surgery',
+ iconClass: 'octicon-plus',
+ route: 'appointments.edit',
+ subroute: 'newsurgery',
+ capability: 'add_appointment'
}
]
},
@@ -291,12 +310,6 @@ export default Ember.Mixin.create({
iconClass: 'octicon-chevron-right',
route: 'admin.roles',
capability: 'define_user_roles'
- },
- {
- title: 'Workflow',
- iconClass: 'octicon-chevron-right',
- route: 'admin.workflow',
- capability: 'update_config'
}
]
}
diff --git a/app/mixins/operative-plan-statuses.js b/app/mixins/operative-plan-statuses.js
new file mode 100644
index 0000000000..928e90390a
--- /dev/null
+++ b/app/mixins/operative-plan-statuses.js
@@ -0,0 +1,28 @@
+import Ember from 'ember';
+
+const { computed } = Ember;
+
+export const COMPLETED_STATUS = 'completed';
+export const DROPPED_STATUS = 'dropped';
+export const PLANNED_STATUS = 'planned';
+
+const STATUS_VALUES = [
+ COMPLETED_STATUS,
+ DROPPED_STATUS,
+ PLANNED_STATUS
+];
+
+export default Ember.Mixin.create({
+ planStatuses: computed(function() {
+ let i18n = this.get('i18n');
+
+ return STATUS_VALUES.map((status) => {
+ return {
+ id: status,
+ value: i18n.t(`operativePlan.labels.${status}Status`)
+ };
+ }).sort(function(a, b) {
+ return Ember.compare(a.value.toString(), b.value.toString());
+ });
+ })
+});
diff --git a/app/mixins/patient-diagnosis.js b/app/mixins/patient-diagnosis.js
index 2f907f1dd8..316078aefb 100644
--- a/app/mixins/patient-diagnosis.js
+++ b/app/mixins/patient-diagnosis.js
@@ -13,10 +13,10 @@ export default Ember.Mixin.create({
}
},
- getDiagnoses(diagnosisContainer, hideInActiveDiagnoses, secondaryDiagnoses) {
+ getDiagnoses(diagnosisContainer, hideInActiveDiagnoses, secondaryDiagnoses, diagnosisProperty = 'diagnoses') {
let diagnosesList = [];
if (!isEmpty(diagnosisContainer)) {
- let diagnoses = diagnosisContainer.get('diagnoses');
+ let diagnoses = diagnosisContainer.get(diagnosisProperty);
if (hideInActiveDiagnoses) {
diagnoses = diagnoses.filterBy('active', true);
}
diff --git a/app/mixins/patient-submodule.js b/app/mixins/patient-submodule.js
index 2b7fc314a9..85e91d01a4 100644
--- a/app/mixins/patient-submodule.js
+++ b/app/mixins/patient-submodule.js
@@ -3,7 +3,7 @@ import Ember from 'ember';
import PatientVisits from 'hospitalrun/mixins/patient-visits';
import SelectValues from 'hospitalrun/utils/select-values';
-const { isEmpty } = Ember;
+const { get, isEmpty } = Ember;
export default Ember.Mixin.create(PatientVisits, {
findPatientVisits: true, // Override to false if visits shouldn't be set when patient is selected.
@@ -69,6 +69,28 @@ export default Ember.Mixin.create(PatientVisits, {
}.bind(this));
},
+ addDiagnosisToModelAndPatient(newDiagnosis) {
+ let diagnoses = this.get('model.diagnoses');
+ diagnoses.addObject(newDiagnosis);
+ let patientDiagnoses = this.get('model.patient.diagnoses');
+ let diagnosisExists = patientDiagnoses.any((diagnosis) => {
+ return diagnosis.get('active') === true
+ && diagnosis.get('diagnosis') === newDiagnosis.get('diagnosis')
+ && diagnosis.get('secondaryDiagnosis') === newDiagnosis.get('secondaryDiagnosis');
+ });
+ if (!diagnosisExists) {
+ patientDiagnoses.addObject(newDiagnosis);
+ let patient = this.get('model.patient');
+ patient.save().then(() => {
+ this.send('update', true);
+ this.send('closeModal');
+ });
+ } else {
+ this.send('update', true);
+ this.send('closeModal');
+ }
+ },
+
_finishAddChildToVisit(objectToAdd, childName, visit, resolve, reject) {
visit.get(childName).then(function(visitChildren) {
visitChildren.addObject(objectToAdd);
@@ -125,6 +147,26 @@ export default Ember.Mixin.create(PatientVisits, {
});
},
+ getPatientDiagnoses(patient, model) {
+ let diagnoses = patient.get('diagnoses');
+ let activeDiagnoses;
+ if (!isEmpty(diagnoses)) {
+ activeDiagnoses = diagnoses.filterBy('active', true).map((diagnosis) => {
+ let description = diagnosis.get('diagnosis');
+ let newDiagnosisProperties = diagnosis.getProperties('active', 'date', 'diagnosis', 'secondaryDiagnosis');
+ newDiagnosisProperties.diagnosis = description;
+ return this.store.createRecord('diagnosis',
+ newDiagnosisProperties
+ );
+ });
+ }
+ let currentDiagnoses = get(model, 'diagnoses');
+ currentDiagnoses.clear();
+ if (!isEmpty(activeDiagnoses)) {
+ currentDiagnoses.addObjects(activeDiagnoses);
+ }
+ },
+
patientId: Ember.computed.alias('model.patient.id'),
patientSelected(/* patient */) {},
@@ -191,6 +233,19 @@ export default Ember.Mixin.create(PatientVisits, {
return promises;
},
+ saveNewDiagnoses() {
+ let diagnoses = this.get('model.diagnoses');
+ diagnoses = diagnoses.filterBy('isNew', true);
+ if (!isEmpty(diagnoses)) {
+ let savePromises = diagnoses.map((diagnoses) => {
+ return diagnoses.save();
+ });
+ return Ember.RSVP.all(savePromises);
+ } else {
+ return Ember.RSVP.resolve();
+ }
+ },
+
/**
* If visit needs to saved, save it and then display an alert message; otherwise
* just display the alert message.
diff --git a/app/mixins/pouch-adapter-utils.js b/app/mixins/pouch-adapter-utils.js
deleted file mode 100644
index 371d0d4f4b..0000000000
--- a/app/mixins/pouch-adapter-utils.js
+++ /dev/null
@@ -1,20 +0,0 @@
-import Ember from 'ember';
-export default Ember.Mixin.create({
- session: Ember.inject.service(),
- _pouchError(reject) {
- return function(err) {
- if (err.status === 401) {
- // User is unauthorized; reload to force login.
- let session = this.get('session');
- if (!Ember.isEmpty(session) && session.get('isAuthenticated')) {
- session.invalidate();
- }
- }
- let errmsg = [err.status,
- `${(err.name || err.error)}:`,
- (err.message || err.reason)
- ].join(' ');
- Ember.run(null, reject, errmsg);
- }.bind(this);
- }
-});
diff --git a/app/mixins/user-session.js b/app/mixins/user-session.js
index 78ae206084..fc9162a307 100644
--- a/app/mixins/user-session.js
+++ b/app/mixins/user-session.js
@@ -6,6 +6,14 @@ export default Ember.Mixin.create({
'User Administrator',
'System Administrator'
],
+ add_allergy: [
+ 'Data Entry',
+ 'Doctor',
+ 'Hospital Administrator',
+ 'Medical Records Officer',
+ 'Patient Administration',
+ 'System Administrator'
+ ],
appointments: [
'Data Entry',
'Finance',
@@ -52,6 +60,22 @@ export default Ember.Mixin.create({
'Pharmacist',
'System Administrator'
],
+ add_operative_plan: [
+ 'Data Entry',
+ 'Doctor',
+ 'Hospital Administrator',
+ 'Medical Records Officer',
+ 'Patient Administration',
+ 'System Administrator'
+ ],
+ add_operation_report: [
+ 'Data Entry',
+ 'Doctor',
+ 'Hospital Administrator',
+ 'Medical Records Officer',
+ 'Patient Administration',
+ 'System Administrator'
+ ],
add_photo: [
'Data Entry',
'Hospital Administrator',
diff --git a/app/models/allergy.js b/app/models/allergy.js
index 3d1a215b0e..92b2e2e928 100644
--- a/app/models/allergy.js
+++ b/app/models/allergy.js
@@ -2,8 +2,10 @@ import AbstractModel from 'hospitalrun/models/abstract';
import DS from 'ember-data';
export default AbstractModel.extend({
- patient: DS.belongsTo('patient'),
+ // Attributes
name: DS.attr('string'),
icd9CMCode: DS.attr('string'),
- icd10Code: DS.attr('string')
+ icd10Code: DS.attr('string'),
+ // Associations
+ patient: DS.belongsTo('patient')
});
diff --git a/app/models/appointment.js b/app/models/appointment.js
index 74e88eed97..a429a59414 100644
--- a/app/models/appointment.js
+++ b/app/models/appointment.js
@@ -1,14 +1,12 @@
import AbstractModel from 'hospitalrun/models/abstract';
import DS from 'ember-data';
import Ember from 'ember';
+import moment from 'moment';
import PatientValidation from 'hospitalrun/utils/patient-validation';
export default AbstractModel.extend({
+ // Attributes
allDay: DS.attr(),
- patient: DS.belongsTo('patient', {
- async: false
- }),
- visits: DS.hasMany('visit'),
provider: DS.attr('string'),
location: DS.attr('string'),
appointmentType: DS.attr('string'),
@@ -17,6 +15,11 @@ export default AbstractModel.extend({
notes: DS.attr('string'),
status: DS.attr('string', { defaultValue: 'Scheduled' }),
+ // Associations
+ patient: DS.belongsTo('patient', { async: false }),
+ visits: DS.hasMany('visit'),
+
+ // Formats
longDateFormat: 'l h:mm A',
shortDateFormat: 'l',
timeFormat: 'h:mm A',
@@ -82,9 +85,6 @@ export default AbstractModel.extend({
appointmentType: {
presence: true
},
- location: {
- presence: true
- },
startDate: {
presence: true
},
diff --git a/app/models/billing-line-item.js b/app/models/billing-line-item.js
index 1b7317d0cc..3989d38c3f 100644
--- a/app/models/billing-line-item.js
+++ b/app/models/billing-line-item.js
@@ -4,16 +4,17 @@ import Ember from 'ember';
import NumberFormat from 'hospitalrun/mixins/number-format';
export default AbstractModel.extend(NumberFormat, {
+ // Attributes
amountOwed: DS.attr('number'),
category: DS.attr('string'),
description: DS.attr('string'),
- details: DS.hasMany('line-item-detail', {
- async: false
- }), /* The individual objects that make up this line item. */
discount: DS.attr('number'),
name: DS.attr('string'),
nationalInsurance: DS.attr('number'),
privateInsurance: DS.attr('number'),
+ // Associations
+ /* The individual objects that make up this line item. */
+ details: DS.hasMany('line-item-detail', { async: false }),
amountOwedChanged: function() {
Ember.run.debounce(this, function() {
diff --git a/app/models/diagnosis.js b/app/models/diagnosis.js
index fe92846930..f4c325fb25 100644
--- a/app/models/diagnosis.js
+++ b/app/models/diagnosis.js
@@ -2,6 +2,7 @@ import AbstractModel from 'hospitalrun/models/abstract';
import DS from 'ember-data';
export default AbstractModel.extend({
+ // Attributes
active: DS.attr('boolean', { defaultValue: true }),
date: DS.attr('date'),
diagnosis: DS.attr('string'),
diff --git a/app/models/imaging.js b/app/models/imaging.js
index f7c41736ca..80fc21a803 100644
--- a/app/models/imaging.js
+++ b/app/models/imaging.js
@@ -2,37 +2,35 @@ import AbstractModel from 'hospitalrun/models/abstract';
import CanEditRequested from 'hospitalrun/mixins/can-edit-requested';
import DateFormat from 'hospitalrun/mixins/date-format';
import DS from 'ember-data';
+import Ember from 'ember';
import PatientValidation from 'hospitalrun/utils/patient-validation';
import ResultValidation from 'hospitalrun/mixins/result-validation';
+const { computed } = Ember;
+
export default AbstractModel.extend(CanEditRequested, DateFormat, ResultValidation, {
- charges: DS.hasMany('proc-charge', {
- async: false
- }),
+ // Attributes
imagingDate: DS.attr('date'),
- imagingType: DS.belongsTo('pricing', {
- async: false
- }),
notes: DS.attr('string'),
- patient: DS.belongsTo('patient', {
- async: false
- }),
radiologist: DS.attr('string'),
requestedBy: DS.attr('string'),
requestedDate: DS.attr('date'),
result: DS.attr('string'),
status: DS.attr('string'),
- visit: DS.belongsTo('visit', {
- async: false
- }),
- imagingDateAsTime: function() {
+ // Associations
+ charges: DS.hasMany('proc-charge', { async: false }),
+ imagingType: DS.belongsTo('pricing', { async: false }),
+ patient: DS.belongsTo('patient', { async: false }),
+ visit: DS.belongsTo('visit', { async: false }),
+
+ imagingDateAsTime: computed('imagingDate', function() {
return this.dateToTime(this.get('imagingDate'));
- }.property('imagingDate'),
+ }),
- requestedDateAsTime: function() {
+ requestedDateAsTime: computed('requestedDate', function() {
return this.dateToTime(this.get('requestedDate'));
- }.property('requestedDate'),
+ }),
validations: {
imagingTypeName: {
diff --git a/app/models/inventory.js b/app/models/inventory.js
index f550d5962d..3c8a5d8799 100644
--- a/app/models/inventory.js
+++ b/app/models/inventory.js
@@ -5,49 +5,50 @@ import computed from 'ember-computed';
import LocationName from 'hospitalrun/mixins/location-name';
import { rankToMultiplier, getCondition } from 'hospitalrun/utils/item-condition';
+const { get, set } = Ember;
+
let validateIfNewItem = {
if: function validateNewItem(object) {
- let skipSavePurchase = object.get('skipSavePurchase');
+ let skipSavePurchase = get(object, 'skipSavePurchase');
// Only validate on new items and only if we are saving a purchase.
- return (!skipSavePurchase && object.get('isNew'));
+ return (!skipSavePurchase && get(object, 'isNew'));
}
};
export default AbstractModel.extend(LocationName, {
- purchases: DS.hasMany('inv-purchase', {
- async: false
- }),
- locations: DS.hasMany('inv-location', {
- async: false
- }),
+ // Attributes
+ crossReference: DS.attr('string'),
description: DS.attr('string'),
+ distributionUnit: DS.attr('string'),
friendlyId: DS.attr('string'),
+ inventoryType: DS.attr('string'),
keywords: DS.attr(),
name: DS.attr('string'),
- quantity: DS.attr('number'),
- crossReference: DS.attr('string'),
- inventoryType: DS.attr('string'),
price: DS.attr('number'),
- reorderPoint: DS.attr('number'),
- distributionUnit: DS.attr('string'),
+ quantity: DS.attr('number'),
rank: DS.attr('string'),
+ reorderPoint: DS.attr('number'),
+
+ // Associations
+ locations: DS.hasMany('inv-location', { async: false }),
+ purchases: DS.hasMany('inv-purchase', { async: false }),
// TODO: this value should be server calcuated property on model!
estimatedDaysOfStock: 14,
availableLocations: computed('locations.@each.quantity', function() {
- let locations = this.get('locations').filter((location) => {
- return location.get('quantity') > 0;
+ let locations = get(this, 'locations').filter((location) => {
+ return get(location, 'quantity') > 0;
});
return locations;
}),
displayLocations: computed('availableLocations', function() {
- let locations = this.get('availableLocations');
+ let locations = get(this, 'availableLocations');
let returnLocations = [];
locations.forEach((currentLocation) => {
- let aisleLocationName = currentLocation.get('aisleLocation');
- let locationName = currentLocation.get('location');
+ let aisleLocationName = get(currentLocation, 'aisleLocation');
+ let locationName = get(currentLocation, 'location');
let displayLocationName = this.formatLocationName(locationName, aisleLocationName);
if (!Ember.isEmpty(displayLocationName)) {
returnLocations.push(displayLocationName);
@@ -57,8 +58,8 @@ export default AbstractModel.extend(LocationName, {
}),
condition: computed('rank', 'estimatedDaysOfStock', function() {
- let estimatedDaysOfStock = this.get('estimatedDaysOfStock');
- let multiplier = rankToMultiplier(this.get('rank'));
+ let estimatedDaysOfStock = get(this, 'estimatedDaysOfStock');
+ let multiplier = rankToMultiplier(get(this, 'rank'));
return getCondition(estimatedDaysOfStock, multiplier);
}),
@@ -101,7 +102,7 @@ export default AbstractModel.extend(LocationName, {
},
updateQuantity() {
- let purchases = this.get('purchases');
+ let purchases = get(this, 'purchases');
let newQuantity = purchases.reduce((previousItem, currentItem) => {
let currentQuantity = 0;
if (!currentItem.get('expired')) {
@@ -109,6 +110,6 @@ export default AbstractModel.extend(LocationName, {
}
return previousItem + currentQuantity;
}, 0);
- this.set('quantity', newQuantity);
+ set(this, 'quantity', newQuantity);
}
});
diff --git a/app/models/invoice.js b/app/models/invoice.js
index 48802b09f4..92c8d92bb6 100644
--- a/app/models/invoice.js
+++ b/app/models/invoice.js
@@ -5,40 +5,35 @@ import Ember from 'ember';
import NumberFormat from 'hospitalrun/mixins/number-format';
import PatientValidation from 'hospitalrun/utils/patient-validation';
+const { computed, get, set } = Ember;
+
export default AbstractModel.extend(DateFormat, NumberFormat, {
+ // Attributes
+ billDate: DS.attr('date'),
externalInvoiceNumber: DS.attr('string'),
- patient: DS.belongsTo('patient', {
- async: false
- }),
+ paidTotal: DS.attr('number'),
patientInfo: DS.attr('string'), // Needed for searching
- visit: DS.belongsTo('visit', {
- async: false
- }),
- status: DS.attr('string'),
remarks: DS.attr('string'),
- billDate: DS.attr('date'),
- paidTotal: DS.attr('number'),
- paymentProfile: DS.belongsTo('price-profile', {
- async: false
- }),
- // payments track the number of payment events attached to an invoice.
- payments: DS.hasMany('payment', {
- async: false
- }),
- // the individual line items of the invoice
- lineItems: DS.hasMany('billing-line-item', {
- async: false
- }),
+ status: DS.attr('string'),
+
+ // Associations
+ /* the individual line items of the invoice */
+ lineItems: DS.hasMany('billing-line-item', { async: false }),
+ patient: DS.belongsTo('patient', { async: false }),
+ paymentProfile: DS.belongsTo('price-profile', { async: false }),
+ /* payments track the number of payment events attached to an invoice. */
+ payments: DS.hasMany('payment', { async: false }),
+ visit: DS.belongsTo('visit', { async: false }),
addPayment(payment) {
- let payments = this.get('payments');
+ let payments = get(this, 'payments');
payments.addObject(payment);
this.paymentAmountChanged();
},
- billDateAsTime: function() {
- return this.dateToTime(this.get('billDate'));
- }.property('billDate'),
+ billDateAsTime: computed('billDate', function() {
+ return this.dateToTime(get(this, 'billDate'));
+ }),
discountTotals: Ember.computed.mapBy('lineItemsByCategory', 'discount'),
discount: Ember.computed.sum('discountTotals'),
@@ -46,15 +41,15 @@ export default AbstractModel.extend(DateFormat, NumberFormat, {
nationalInsuranceTotals: Ember.computed.mapBy('lineItemsByCategory', 'nationalInsurance'),
nationalInsurance: Ember.computed.sum('nationalInsuranceTotals'),
- paidFlag: function() {
- return (this.get('status') === 'Paid');
- }.property('status'),
+ paidFlag: computed('status', function() {
+ return get(this, 'status') === 'Paid';
+ }),
- remainingBalance: function() {
- let patientResponsibility = this.get('patientResponsibility');
- let paidTotal = this.get('paidTotal');
+ remainingBalance: computed('patientResponsibility', 'paidTotal', function() {
+ let patientResponsibility = get(this, 'patientResponsibility');
+ let paidTotal = get(this, 'paidTotal');
return this._numberFormat((patientResponsibility - paidTotal), true);
- }.property('patientResponsibility', 'paidTotal'),
+ }),
privateInsuranceTotals: Ember.computed.mapBy('lineItemsByCategory', 'privateInsurance'),
privateInsurance: Ember.computed.sum('privateInsuranceTotals'),
@@ -62,21 +57,17 @@ export default AbstractModel.extend(DateFormat, NumberFormat, {
lineTotals: Ember.computed.mapBy('lineItems', 'total'),
total: Ember.computed.sum('lineTotals'),
- displayInvoiceNumber: function() {
- let externalInvoiceNumber = this.get('externalInvoiceNumber');
- let id = this.get('id');
- if (Ember.isEmpty(externalInvoiceNumber)) {
- return id;
- } else {
- return externalInvoiceNumber;
- }
- }.property('externalInvoiceNumber', 'id'),
+ displayInvoiceNumber: computed('externalInvoiceNumber', 'id', function() {
+ let externalInvoiceNumber = get(this, 'externalInvoiceNumber');
+ let id = get(this, 'id');
+ return Ember.isEmpty(externalInvoiceNumber) ? id : externalInvoiceNumber;
+ }),
- lineItemsByCategory: function() {
- let lineItems = this.get('lineItems');
+ lineItemsByCategory: computed('lineItems.@each.amountOwed', function() {
+ let lineItems = get(this, 'lineItems');
let byCategory = [];
lineItems.forEach(function(lineItem) {
- let category = lineItem.get('category');
+ let category = get(lineItem, 'category');
let categoryList = byCategory.findBy('category', category);
if (Ember.isEmpty(categoryList)) {
categoryList = {
@@ -95,12 +86,13 @@ export default AbstractModel.extend(DateFormat, NumberFormat, {
categoryList.total = this._calculateTotal(categoryList.items, 'total');
}.bind(this));
return byCategory;
- }.property('lineItems.@each.amountOwed'),
+ }),
+
patientIdChanged: function() {
- if (!Ember.isEmpty(this.get('patient'))) {
- let patientDisplayName = this.get('patient.displayName');
- let patientDisplayId = this.get('patient.displayPatientId');
- this.set('patientInfo', `${patientDisplayName} - ${patientDisplayId}`);
+ if (!Ember.isEmpty(get(this, 'patient'))) {
+ let patientDisplayName = get(this, 'patient.displayName');
+ let patientDisplayId = get(this, 'patient.displayPatientId');
+ set(this, 'patientInfo', `${patientDisplayName} - ${patientDisplayId}`);
}
}.observes('patient.displayName', 'patient.id', 'patient.displayPatientId'),
@@ -108,8 +100,8 @@ export default AbstractModel.extend(DateFormat, NumberFormat, {
patientResponsibility: Ember.computed.sum('patientResponsibilityTotals'),
paymentAmountChanged: function() {
- let payments = this.get('payments').filter(function(payment) {
- return !payment.get('isNew');
+ let payments = get(this, 'payments').filter(function(payment) {
+ return !get(payment, 'isNew');
});
if (payments.length === 0) {
return;
@@ -117,20 +109,18 @@ export default AbstractModel.extend(DateFormat, NumberFormat, {
let paidTotal = payments.reduce(function(previousValue, payment) {
return previousValue += this._getValidNumber(payment.get('amount'));
}.bind(this), 0);
- this.set('paidTotal', this._numberFormat(paidTotal, true));
- let remainingBalance = this.get('remainingBalance');
+ set(this, 'paidTotal', this._numberFormat(paidTotal, true));
+ let remainingBalance = get(this, 'remainingBalance');
if (remainingBalance <= 0) {
- this.set('status', 'Paid');
+ set(this, 'status', 'Paid');
}
}.observes('payments.[]', 'payments.@each.amount'),
validations: {
patientTypeAhead: PatientValidation.patientTypeAhead,
-
patient: {
presence: true
},
-
visit: {
presence: true
}
diff --git a/app/models/lab.js b/app/models/lab.js
index 41567f12e9..cfaae72498 100644
--- a/app/models/lab.js
+++ b/app/models/lab.js
@@ -2,36 +2,34 @@ import AbstractModel from 'hospitalrun/models/abstract';
import CanEditRequested from 'hospitalrun/mixins/can-edit-requested';
import DateFormat from 'hospitalrun/mixins/date-format';
import DS from 'ember-data';
+import Ember from 'ember';
import PatientValidation from 'hospitalrun/utils/patient-validation';
import ResultValidation from 'hospitalrun/mixins/result-validation';
+const { computed, get } = Ember;
+
export default AbstractModel.extend(CanEditRequested, DateFormat, ResultValidation, {
- charges: DS.hasMany('proc-charge', {
- async: false
- }),
+ // Attributes
labDate: DS.attr('date'),
- labType: DS.belongsTo('pricing', {
- async: false
- }),
notes: DS.attr('string'),
- patient: DS.belongsTo('patient', {
- async: false
- }),
requestedBy: DS.attr('string'),
requestedDate: DS.attr('date'),
result: DS.attr('string'),
status: DS.attr('string'),
- visit: DS.belongsTo('visit', {
- async: false
- }),
- labDateAsTime: function() {
- return this.dateToTime(this.get('labDate'));
- }.property('labDate'),
+ // Associations
+ charges: DS.hasMany('proc-charge', { async: false }),
+ labType: DS.belongsTo('pricing', { async: false }),
+ patient: DS.belongsTo('patient', { async: false }),
+ visit: DS.belongsTo('visit', { async: false }),
+
+ labDateAsTime: computed('labDate', function() {
+ return this.dateToTime(get(this, 'labDate'));
+ }),
- requestedDateAsTime: function() {
- return this.dateToTime(this.get('requestedDate'));
- }.property('requestedDate'),
+ requestedDateAsTime: computed('requestedDate', function() {
+ return this.dateToTime(get(this, 'requestedDate'));
+ }),
validations: {
labTypeName: {
diff --git a/app/models/line-item-detail.js b/app/models/line-item-detail.js
index ddeda766b4..b0d91577b9 100644
--- a/app/models/line-item-detail.js
+++ b/app/models/line-item-detail.js
@@ -1,26 +1,29 @@
import AbstractModel from 'hospitalrun/models/abstract';
import DS from 'ember-data';
+import Ember from 'ember';
import NumberFormat from 'hospitalrun/mixins/number-format';
+const { computed, get } = Ember;
+
export default AbstractModel.extend(NumberFormat, {
+ // Attributes
department: DS.attr('string'),
expenseAccount: DS.attr('string'),
name: DS.attr('string'),
price: DS.attr('number'),
- pricingItem: DS.belongsTo('pricing', {
- async: false
- }),
quantity: DS.attr('number'),
total: DS.attr('number'),
- amountOwed: function() {
- let price = this.get('price');
- let quantity = this.get('quantity');
+ // Associations
+ pricingItem: DS.belongsTo('pricing', { async: false }),
+
+ amountOwed: computed('price', 'quantity', function() {
+ let price = get(this, 'price');
+ let quantity = get(this, 'quantity');
let total = 0;
if (this._validNumber(price) && this._validNumber(quantity)) {
total = this._numberFormat((price * quantity), true);
}
return total;
- }.property('price', 'quantity')
-
+ })
});
diff --git a/app/models/operation-report.js b/app/models/operation-report.js
new file mode 100644
index 0000000000..7068cea320
--- /dev/null
+++ b/app/models/operation-report.js
@@ -0,0 +1,45 @@
+import AbstractModel from 'hospitalrun/models/abstract';
+import DS from 'ember-data';
+import Ember from 'ember';
+
+const {
+ get,
+ isEmpty
+} = Ember;
+
+function defaultProcedures() {
+ return [];
+}
+
+export default AbstractModel.extend({
+ // Attributes
+ additionalNotes: DS.attr('string'),
+ caseComplexity: DS.attr('number'),
+ customForms: DS.attr('custom-forms'),
+ procedures: DS.attr('operative-procedures', { defaultValue: defaultProcedures }),
+ operationDescription: DS.attr('string'),
+ surgeon: DS.attr('string'),
+ surgeryDate: DS.attr('date'),
+
+ // Associations
+ preOpDiagnoses: DS.hasMany('diagnosis'),
+ diagnoses: DS.hasMany('diagnosis'), // Post op diagnosis
+ operativePlan: DS.belongsTo('operative-plan', { async: true }),
+ patient: DS.belongsTo('patient', { async: false }),
+
+ validations: {
+ caseComplexity: {
+ numericality: {
+ allowBlank: true,
+ onlyInteger: true
+ }
+ },
+ procedureDescription: {
+ presence: {
+ if(object) {
+ return isEmpty(get(object, 'procedures'));
+ }
+ }
+ }
+ }
+});
diff --git a/app/models/operative-plan.js b/app/models/operative-plan.js
new file mode 100644
index 0000000000..8e456ed357
--- /dev/null
+++ b/app/models/operative-plan.js
@@ -0,0 +1,54 @@
+import AbstractModel from 'hospitalrun/models/abstract';
+import DS from 'ember-data';
+import Ember from 'ember';
+import { PLANNED_STATUS } from 'hospitalrun/mixins/operative-plan-statuses';
+
+const {
+ computed,
+ get,
+ isEmpty
+} = Ember;
+
+function defaultProcedures() {
+ return [];
+}
+
+export default AbstractModel.extend({
+ // Attributes
+ additionalNotes: DS.attr('string'),
+ admissionInstructions: DS.attr('string'),
+ caseComplexity: DS.attr('number'),
+ customForms: DS.attr('custom-forms'),
+ operationDescription: DS.attr('string'),
+ procedures: DS.attr('operative-procedures', { defaultValue: defaultProcedures }),
+ status: DS.attr('string', { defaultValue: PLANNED_STATUS }),
+ surgeon: DS.attr('string'),
+
+ // Associations
+ diagnoses: DS.hasMany('diagnosis'),
+ patient: DS.belongsTo('patient', { async: false }),
+
+ isPlanned: computed('status', {
+ get() {
+ let status = get(this, 'status');
+ return status === PLANNED_STATUS;
+ }
+ }),
+
+ validations: {
+ caseComplexity: {
+ numericality: {
+ allowBlank: true,
+ onlyInteger: true
+ }
+ },
+
+ procedureDescription: {
+ presence: {
+ if(object) {
+ return isEmpty(get(object, 'procedures'));
+ }
+ }
+ }
+ }
+});
diff --git a/app/models/option.js b/app/models/option.js
index bf571c14f3..204528d83e 100644
--- a/app/models/option.js
+++ b/app/models/option.js
@@ -1,5 +1,6 @@
import { Model } from 'ember-pouch';
import DS from 'ember-data';
+
export default Model.extend({
value: DS.attr('')
-});
+});
\ No newline at end of file
diff --git a/app/models/override-price.js b/app/models/override-price.js
index e95e7e77cf..bc4f49ea5a 100644
--- a/app/models/override-price.js
+++ b/app/models/override-price.js
@@ -2,10 +2,12 @@ import AbstractModel from 'hospitalrun/models/abstract';
import DS from 'ember-data';
export default AbstractModel.extend({
- profile: DS.belongsTo('price-profile', {
- async: false
- }),
+ // Attributes
price: DS.attr('number'),
+
+ // Associations
+ profile: DS.belongsTo('price-profile', { async: false }),
+
validations: {
profile: {
presence: true
diff --git a/app/models/patient-note.js b/app/models/patient-note.js
index e90330a386..773f21340b 100644
--- a/app/models/patient-note.js
+++ b/app/models/patient-note.js
@@ -1,30 +1,36 @@
import AbstractModel from 'hospitalrun/models/abstract';
import Ember from 'ember';
import DS from 'ember-data';
+
+const { computed } = Ember;
+
export default AbstractModel.extend({
- authoredBy: function() {
+ // Attributes
+ /*
+ * if the note was written by one person but dictated or
+ * given on behalf of another, otherwise, this and createdBy are the same.
+ */
+ attribution: DS.attr('string'),
+
+ content: DS.attr('string'),
+ createdBy: DS.attr('string'),
+ date: DS.attr('date'),
+ /* custom list of noteTypes of mixins/patient-note-types */
+ noteType: DS.attr(),
+ /* who is this note about? */
+ patient: DS.belongsTo('patient', { async: false }),
+ /* if this note is related to a visit, make sure it's noted. */
+ visit: DS.belongsTo('visit', { async: false }),
+
+ authoredBy: computed('attribution', 'createdBy', function() {
if (!Ember.isEmpty(this.get('attribution'))) {
let i18n = this.get('i18n');
return `${this.get('createdBy')} ${i18n.t('patients.notes.onBehalfOfCopy')} ${this.get('attribution')}`;
} else {
return this.get('createdBy');
}
- }.property('attribution', 'createdBy'),
- // if the note was written by one person but dictated / given on behalf of another, otherwise, this and createdBy are the same
- attribution: DS.attr('string'),
- content: DS.attr('string'),
- createdBy: DS.attr('string'),
- date: DS.attr('date'),
- // custom list of noteTypes of mixins/patient-note-types
- noteType: DS.attr(),
- // who is this note about?
- patient: DS.belongsTo('patient', {
- async: false
- }),
- // if this note is related to a visit, make sure it's noted.
- visit: DS.belongsTo('visit', {
- async: false
}),
+
validations: {
patient: {
presence: true
diff --git a/app/models/patient.js b/app/models/patient.js
index 3fabfcd95a..bb1be13707 100644
--- a/app/models/patient.js
+++ b/app/models/patient.js
@@ -5,27 +5,22 @@ import Ember from 'ember';
import DS from 'ember-data';
import PatientName from 'hospitalrun/mixins/patient-name';
-const { computed } = Ember;
+const { computed, get } = Ember;
export default AbstractModel.extend(DOBDays, PatientName, {
+ // Attributes
admitted: DS.attr('boolean', { defaultValue: false }),
additionalContacts: DS.attr(),
address: DS.attr('string'),
address2: DS.attr('string'),
address3: DS.attr('string'),
address4: DS.attr('string'),
- allergies: DS.hasMany('allergy', {
- async: true
- }),
bloodType: DS.attr('string'),
clinic: DS.attr('string'),
country: DS.attr('string'),
checkedIn: DS.attr('boolean', { defaultValue: false }),
customForms: DS.attr('custom-forms'),
dateOfBirth: DS.attr('date'),
- diagnoses: DS.hasMany('diagnosis', {
- async: false
- }),
economicClassification: DS.attr('string'),
email: DS.attr('string'),
expenses: DS.attr(),
@@ -47,14 +42,8 @@ export default AbstractModel.extend(DOBDays, PatientName, {
middleName: DS.attr('string'),
notes: DS.attr('string'),
otherIncome: DS.attr('string'),
- payments: DS.hasMany('payment', {
- async: true
- }),
patientType: DS.attr('string'),
parent: DS.attr('string'),
- paymentProfile: DS.belongsTo('price-profile', {
- async: false
- }),
phone: DS.attr('string'),
placeOfBirth: DS.attr('string'),
referredDate: DS.attr('date'),
@@ -63,13 +52,20 @@ export default AbstractModel.extend(DOBDays, PatientName, {
socialActionTaken: DS.attr('string'),
socialRecommendation: DS.attr('string'),
status: DS.attr('string'),
+ // Associations
+ allergies: DS.hasMany('allergy', { async: true }),
+ diagnoses: DS.hasMany('diagnosis', { async: false }),
+ operationReports: DS.hasMany('operation-report', { async: true }),
+ operativePlans: DS.hasMany('operative-plan', { async: true }),
+ payments: DS.hasMany('payment', { async: true }),
+ paymentProfile: DS.belongsTo('price-profile', { async: false }),
- age: function() {
- let dob = this.get('dateOfBirth');
+ age: computed('dateOfBirth', function() {
+ let dob = get(this, 'dateOfBirth');
return this.convertDOBToText(dob);
- }.property('dateOfBirth'),
+ }),
- displayAddress: function() {
+ displayAddress: computed('address', 'address2', 'address3', 'address4', function() {
let addressFields = this.getProperties('address', 'address2', 'address3', 'address4');
let displayAddress = '';
for (let prop in addressFields) {
@@ -81,20 +77,20 @@ export default AbstractModel.extend(DOBDays, PatientName, {
}
}
return displayAddress;
- }.property('address', 'address2', 'address3', 'address4'),
+ }),
- displayName: function() {
+ displayName: computed('firstName', 'lastName', 'middleName', function() {
return this.getPatientDisplayName(this);
- }.property('firstName', 'lastName', 'middleName'),
+ }),
- displayPatientId: function() {
+ displayPatientId: computed('id', 'externalPatientId', 'friendlyId', function() {
return this.getPatientDisplayId(this);
- }.property('id', 'externalPatientId', 'friendlyId'),
+ }),
- shortAge: function() {
- let dob = this.get('dateOfBirth');
+ shortAge: computed('dateOfBirth', function() {
+ let dob = get(this, 'dateOfBirth');
return this.convertDOBToText(dob, true);
- }.property('dateOfBirth'),
+ }),
shortDisplayName: computed('firstName', 'lastName', function() {
return this.getPatientDisplayName(this, true);
@@ -118,5 +114,4 @@ export default AbstractModel.extend(DOBDays, PatientName, {
presence: true
}
}
-
});
diff --git a/app/models/payment.js b/app/models/payment.js
index 649be4c3c9..5b8d8bccce 100644
--- a/app/models/payment.js
+++ b/app/models/payment.js
@@ -1,20 +1,25 @@
import AbstractModel from 'hospitalrun/models/abstract';
import DS from 'ember-data';
+import Ember from 'ember';
+
+const { computed, get } = Ember;
export default AbstractModel.extend({
+ // Attributes
amount: DS.attr('number'),
- charityPatient: DS.attr('boolean'), // Is patient a charity case
- expenseAccount: DS.attr('string'),
- invoice: DS.belongsTo('invoice', {
- async: false
- }),
+ /* Is patient a charity case */
+ charityPatient: DS.attr('boolean'),
datePaid: DS.attr('date'),
- paymentType: DS.attr('string'),
+ expenseAccount: DS.attr('string'),
notes: DS.attr('string'),
+ paymentType: DS.attr('string'),
- canRemovePayment: function() {
- return (this.get('paymentType') === 'Deposit');
- }.property('paymentType'),
+ // Associations
+ invoice: DS.belongsTo('invoice', { async: false }),
+
+ canRemovePayment: computed('paymentType', function() {
+ return get(this, 'paymentType') === 'Deposit';
+ }),
validations: {
amount: {
diff --git a/app/models/photo.js b/app/models/photo.js
index b281e27352..43c41eba9e 100644
--- a/app/models/photo.js
+++ b/app/models/photo.js
@@ -2,13 +2,15 @@ import AbstractModel from 'hospitalrun/models/abstract';
import DS from 'ember-data';
export default AbstractModel.extend({
- _attachments: DS.attr(), // Temporarily store file as attachment until it gets uploaded to the server
+ // Attributes
+ /* Temporarily store file as attachment until it gets uploaded to the server */
+ _attachments: DS.attr(),
+ caption: DS.attr('string'),
coverImage: DS.attr('boolean'),
fileName: DS.attr('string'),
localFile: DS.attr('boolean'),
- patient: DS.belongsTo('patient', {
- async: false
- }),
- caption: DS.attr('string'),
- url: DS.attr('string')
+ url: DS.attr('string'),
+
+ // Associations
+ patient: DS.belongsTo('patient', { async: false })
});
diff --git a/app/models/pricing.js b/app/models/pricing.js
index ab675f6457..11301697da 100644
--- a/app/models/pricing.js
+++ b/app/models/pricing.js
@@ -2,14 +2,15 @@ import AbstractModel from 'hospitalrun/models/abstract';
import DS from 'ember-data';
export default AbstractModel.extend({
+ // Attributes
category: DS.attr('string'),
expenseAccount: DS.attr('string'),
name: DS.attr('string'),
price: DS.attr('number'),
pricingType: DS.attr('string'),
- pricingOverrides: DS.hasMany('override-price', {
- async: false
- }),
+
+ // Associations
+ pricingOverrides: DS.hasMany('override-price', { async: false }),
validations: {
category: {
diff --git a/app/models/proc-charge.js b/app/models/proc-charge.js
index a3b58e09e3..83f92bac9f 100644
--- a/app/models/proc-charge.js
+++ b/app/models/proc-charge.js
@@ -3,32 +3,33 @@ import DS from 'ember-data';
import Ember from 'ember';
import MedicationDetails from 'hospitalrun/mixins/medication-details';
+const { computed, get } = Ember;
+
/**
* Procedure charges
*/
export default AbstractModel.extend(MedicationDetails, {
- medication: DS.belongsTo('inventory', {
- async: false
- }),
- pricingItem: DS.belongsTo('pricing', {
- async: false
- }),
+ // Attributes
quantity: DS.attr('number'),
dateCharged: DS.attr('date'),
- medicationCharge: function() {
- let medication = this.get('medication');
- let newMedicationCharge = this.get('newMedicationCharge');
- return (!Ember.isEmpty(medication) || !Ember.isEmpty(newMedicationCharge));
- }.property('medication', 'newMedicationCharge'),
+ // Associations
+ medication: DS.belongsTo('inventory', { async: false }),
+ pricingItem: DS.belongsTo('pricing', { async: false }),
- medicationName: function() {
+ medicationCharge: computed('medication', 'newMedicationCharge', function() {
+ let medication = get(this, 'medication');
+ let newMedicationCharge = get(this, 'newMedicationCharge');
+ return !Ember.isEmpty(medication) || !Ember.isEmpty(newMedicationCharge);
+ }),
+
+ medicationName: computed('medication', function() {
return this.get('medication.name');
- }.property('medication'),
+ }),
- medicationPrice: function() {
+ medicationPrice: computed('medication', function() {
return this.get('medication.price');
- }.property('medication'),
+ }),
validations: {
itemName: {
@@ -36,12 +37,12 @@ export default AbstractModel.extend(MedicationDetails, {
acceptance: {
accept: true,
if(object) {
- let medicationCharge = object.get('medicationCharge');
- if (!medicationCharge || !object.get('hasDirtyAttributes')) {
+ let medicationCharge = get(object, 'medicationCharge');
+ if (!medicationCharge || !get(object, 'hasDirtyAttributes')) {
return false;
}
- let itemName = object.get('inventoryItem.name');
- let itemTypeAhead = object.get('itemName');
+ let itemName = get(object, 'inventoryItem.name');
+ let itemTypeAhead = get(object, 'itemName');
if (Ember.isEmpty(itemName) || Ember.isEmpty(itemTypeAhead)) {
// force validation to fail
return true;
diff --git a/app/models/procedure.js b/app/models/procedure.js
index 6a1ad0b1e1..7f0317da9f 100644
--- a/app/models/procedure.js
+++ b/app/models/procedure.js
@@ -2,13 +2,11 @@ import AbstractModel from 'hospitalrun/models/abstract';
import DS from 'ember-data';
export default AbstractModel.extend({
+ // Attributes
anesthesiaType: DS.attr('string'),
anesthesiologist: DS.attr('string'),
assistant: DS.attr('string'),
description: DS.attr('string'),
- charges: DS.hasMany('proc-charge', {
- async: false
- }),
cptCode: DS.attr('string'),
location: DS.attr('string'),
notes: DS.attr('string'),
@@ -16,9 +14,10 @@ export default AbstractModel.extend({
procedureDate: DS.attr('date'),
timeStarted: DS.attr('string'),
timeEnded: DS.attr('string'),
- visit: DS.belongsTo('visit', {
- async: false
- }),
+
+ // Associations
+ charges: DS.hasMany('proc-charge', { async: false }),
+ visit: DS.belongsTo('visit', { async: false }),
validations: {
description: {
diff --git a/app/models/sequence.js b/app/models/sequence.js
index ffa5e29fb4..370b02759b 100644
--- a/app/models/sequence.js
+++ b/app/models/sequence.js
@@ -1,6 +1,8 @@
import { Model } from 'ember-pouch';
import DS from 'ember-data';
+
export default Model.extend({
+ // Attributes
prefix: DS.attr('string'),
value: DS.attr('number')
});
diff --git a/app/models/social-expense.js b/app/models/social-expense.js
index 64f281bc28..e535d9e18a 100644
--- a/app/models/social-expense.js
+++ b/app/models/social-expense.js
@@ -4,10 +4,13 @@
import DS from 'ember-data';
import EmberValidations from 'ember-validations';
import { Model } from 'ember-pouch';
+
export default Model.extend(EmberValidations, {
+ // Attributes
category: DS.attr('string'),
sources: DS.attr('string'),
cost: DS.attr(),
+
validations: {
category: {
presence: true
diff --git a/app/models/user-role.js b/app/models/user-role.js
index f8cb0b9556..4c48927047 100644
--- a/app/models/user-role.js
+++ b/app/models/user-role.js
@@ -1,6 +1,8 @@
import AbstractModel from 'hospitalrun/models/abstract';
import DS from 'ember-data';
+
export default AbstractModel.extend({
+ // Attributes
name: DS.attr('string'),
capabilities: DS.attr()
-});
+});
\ No newline at end of file
diff --git a/app/models/user.js b/app/models/user.js
index 854b3e3642..db1c71affe 100644
--- a/app/models/user.js
+++ b/app/models/user.js
@@ -2,7 +2,11 @@ import DS from 'ember-data';
import EmailValidation from 'hospitalrun/utils/email-validation';
import Ember from 'ember';
import EmberValidations from 'ember-validations';
+
+const { computed } = Ember;
+
let User = DS.Model.extend(EmberValidations, {
+ // Attributes
derived_key: DS.attr('string'),
deleted: DS.attr('boolean'),
displayName: DS.attr('string'),
@@ -17,18 +21,18 @@ let User = DS.Model.extend(EmberValidations, {
salt: DS.attr('string'),
userPrefix: DS.attr('string'),
- displayRole: function() {
+ displayRole: computed('roles', function() {
let roles = this.get('roles');
if (!Ember.isEmpty(roles)) {
return roles[0];
}
- }.property('roles'),
+ }),
validations: {
email: {
format: {
with: EmailValidation.emailRegex,
- message: 'please enter a valid email address'
+ message: 'Please, enter a valid email address'
}
}
}
diff --git a/app/models/visit.js b/app/models/visit.js
index 4fc207c9dd..e400cb4136 100644
--- a/app/models/visit.js
+++ b/app/models/visit.js
@@ -1,6 +1,7 @@
import AbstractModel from 'hospitalrun/models/abstract';
import DS from 'ember-data';
import Ember from 'ember';
+import moment from 'moment';
function dateAcceptance(object) {
if (!object.get('hasDirtyAttributes')) {
diff --git a/app/models/vital.js b/app/models/vital.js
index 7fffa09d8d..d775d41cab 100644
--- a/app/models/vital.js
+++ b/app/models/vital.js
@@ -2,14 +2,16 @@ import AbstractModel from 'hospitalrun/models/abstract';
import DS from 'ember-data';
export default AbstractModel.extend({
+ // Attributes
dateRecorded: DS.attr('date'),
- temperature: DS.attr('number'),
- weight: DS.attr('string'),
- height: DS.attr('string'),
- sbp: DS.attr('number'),
dbp: DS.attr('number'),
heartRate: DS.attr('number'),
+ height: DS.attr('string'),
respiratoryRate: DS.attr('number'),
+ sbp: DS.attr('number'),
+ temperature: DS.attr('number'),
+ weight: DS.attr('string'),
+
validations: {
temperature: {
numericality: true
diff --git a/app/patients/edit/controller.js b/app/patients/edit/controller.js
index 801c302490..93560580ae 100644
--- a/app/patients/edit/controller.js
+++ b/app/patients/edit/controller.js
@@ -9,6 +9,11 @@ import SelectValues from 'hospitalrun/utils/select-values';
import UserSession from 'hospitalrun/mixins/user-session';
import VisitStatus from 'hospitalrun/utils/visit-statuses';
+const {
+ get,
+ isEmpty
+} = Ember;
+
export default AbstractEditController.extend(BloodTypes, DiagnosisActions, ReturnTo, UserSession, PatientId, PatientNotes, {
canAddAppointment: function() {
@@ -145,8 +150,21 @@ export default AbstractEditController.extend(BloodTypes, DiagnosisActions, Retur
}.property('model.visits.[].medication'),
patientProcedures: function() {
- return this._getVisitCollection('procedures');
- }.property('model.visits.[].procedures'),
+ let patientProcedures = this._getVisitCollection('procedures');
+ let operationReports = get(this, 'model.operationReports');
+ operationReports.forEach((report) => {
+ let reportedProcedures = get(report, 'procedures');
+ let surgeryDate = get(report, 'surgeryDate');
+ reportedProcedures.forEach((procedure) => {
+ patientProcedures.addObject({
+ description: get(procedure, 'description'),
+ procedureDate: surgeryDate,
+ report
+ });
+ });
+ });
+ return patientProcedures;
+ }.property('model.visits.[].procedures', 'model.operationReports.[].procedures'),
showExpenseTotal: function() {
let expenses = this.get('model.expenses');
@@ -307,6 +325,24 @@ export default AbstractEditController.extend(BloodTypes, DiagnosisActions, Retur
}
},
+ editOperativePlan(operativePlan) {
+ let model = operativePlan;
+ if (isEmpty(model)) {
+ this._addChildObject('patients.operative-plan', (route) =>{
+ route.controller.getPatientDiagnoses(this.get('model'), route.currentModel);
+ });
+ } else {
+ model.set('returnToVisit');
+ model.set('returnToPatient', this.get('model.id'));
+ this.transitionToRoute('patients.operative-plan', model);
+ }
+ },
+
+ editOperationReport(operationReport) {
+ operationReport.set('returnToPatient', this.get('model.id'));
+ this.transitionToRoute('patients.operation-report', operationReport);
+ },
+
editPhoto(photo) {
this.send('openModal', 'patients.photo', photo);
},
@@ -343,6 +379,16 @@ export default AbstractEditController.extend(BloodTypes, DiagnosisActions, Retur
this._addChildObject('medication.edit');
},
+ newSurgicalAppointment() {
+ this.transitionToRoute('appointments.edit', 'newsurgery').then((newRoute) => {
+ newRoute.currentModel.setProperties({
+ patient: this.get('model'),
+ returnToPatient: this.get('model.id'),
+ selectPatient: false
+ });
+ });
+ },
+
newVisit() {
let patient = this.get('model');
this.send('createNewVisit', patient, true);
@@ -487,13 +533,16 @@ export default AbstractEditController.extend(BloodTypes, DiagnosisActions, Retur
},
- _addChildObject(route) {
+ _addChildObject(route, afterTransition) {
this.transitionToRoute(route, 'new').then(function(newRoute) {
newRoute.currentModel.setProperties({
patient: this.get('model'),
returnToPatient: this.get('model.id'),
selectPatient: false
});
+ if (afterTransition) {
+ afterTransition(newRoute);
+ }
}.bind(this));
},
@@ -522,9 +571,6 @@ export default AbstractEditController.extend(BloodTypes, DiagnosisActions, Retur
visits.forEach(function(visit) {
visit.get(name).then(function(items) {
returnList.addObjects(items);
- if (returnList.length > 0) {
- returnList[0].set('first', true);
- }
});
});
}
diff --git a/app/patients/edit/template.hbs b/app/patients/edit/template.hbs
index 89b1c5c7da..501e638d3a 100644
--- a/app/patients/edit/template.hbs
+++ b/app/patients/edit/template.hbs
@@ -6,7 +6,9 @@
patientProcedures=patientProcedures
disablePatientLink=true
store=store
- canAddDiagnosis=canAddDiagnosis
+ allowAddAllergy=true
+ allowAddDiagnosis=true
+ allowAddOperativePlan=true
diagnosisList=diagnosisList
}}