Order viewer

This commit is contained in:
Jiang Yio 2022-10-01 00:38:59 -04:00
parent a01fa834ac
commit c1ca4ea414
6 changed files with 199 additions and 4 deletions

View File

@ -0,0 +1,28 @@
<template>
<select class="form-select form-select-sm" style="width: auto;" v-model="x_value">
<option v-for="item in options" :value="item.ien">{{item.name}}</option>
</select>
</template>
<script>
export default {
props: {
client: Object,
modelValue: { default: 2 }
},
data() {
return {
options: [],
x_value: this.modelValue
};
},
watch: {
client: {
async handler(value) { if(value) this.options = await value.ORWORDG_REVSTS(); },
immediate: true
},
modelValue(value) { this.x_value = value; },
x_value(value) { this.$emit('update:modelValue', value); }
}
};
</script>

View File

@ -21,6 +21,14 @@
<ViewVitalsLabs :client="client" :dfn="dfn" :date_begin="report_date_begin" :date_end="report_date" /> <ViewVitalsLabs :client="client" :dfn="dfn" :date_begin="report_date_begin" :date_end="report_date" />
</div> </div>
</div> </div>
<div class="card mb-3 shadow">
<div class="card-header d-flex justify-content-between align-items-center">
<span>Orders</span>
<OrderFilterPicker :client="client" v-model="orders_filter" />
<DateRangePicker range="6M" direction="-1" v-model:date="orders_date" v-model:date_end="orders_date_begin" />
</div>
<div class="card-body"><ViewOrders :client="client" :dfn="dfn" :filter="orders_filter" :date_begin="orders_date_begin" :date_end="orders_date" /></div>
</div>
</div> </div>
</template> </template>
@ -29,12 +37,14 @@
import DateRangePicker from './DateRangePicker.vue'; import DateRangePicker from './DateRangePicker.vue';
import ViewVitalsLabs from './ViewVitalsLabs.vue'; import ViewVitalsLabs from './ViewVitalsLabs.vue';
import OrderFilterPicker from './OrderFilterPicker.vue';
import ViewOrders from './ViewOrders.vue';
var now = new Date(); var now = new Date();
export default { export default {
components: { components: {
DateRangePicker, ViewVitalsLabs DateRangePicker, ViewVitalsLabs, OrderFilterPicker, ViewOrders
}, },
props: { props: {
client: Object client: Object
@ -44,7 +54,10 @@
dfn: null, dfn: null,
info: null, info: null,
report_date: now, report_date: now,
report_date_begin: now report_date_begin: now,
orders_filter: 2,
orders_date: now,
orders_date_begin: now
}; };
}, },
watch: { watch: {

104
htdocs/ViewOrders.vue Normal file
View File

@ -0,0 +1,104 @@
<template>
<table v-if="details.length > 0" class="table table-striped">
<template v-for="group in details">
<thead>
<tr>
<th>{{map_groups[group.key].name}}</th>
<th>Practitioner</th>
<th style="text-align: right;">Status</th>
</tr>
</thead>
<tbody>
<tr v-for="item in group.values">
<td><div v-for="line in item.text">{{line}}</div></td>
<td>
<div v-if="item.PrvNam" :title="item.PrvID">{{item.PrvNam}}</div>
<div v-if="item.Nrs">Nurse: {{item.Nrs}}</div>
<div v-if="item.Clk">Clerk: {{item.Clk}}</div>
<div v-if="item.ChartRev">Chart: {{item.ChartRev}}</div>
<div v-if="item.LOC">{{item.LOC.split(':')[0]}}</div>
</td>
<td style="text-align: right;">
<div v-if="item.Sts">{{name_of_status[item.Sts]}}</div>
<div v-if="item.OrdTm">Ordered: {{strptime_vista(item.OrdTm).toLocaleDateString('en-CA')}}</div>
<div v-if="item.StrtTm">Start: {{strptime_vista(item.StrtTm).toLocaleDateString('en-CA')}}</div>
<div v-if="item.StopTm">Stop: {{strptime_vista(item.StopTm).toLocaleDateString('en-CA')}}</div>
</td>
</tr>
</tbody>
</template>
</table>
</template>
<style scoped>
th {
text-transform: lowercase;
}
th::first-letter {
text-transform: uppercase;
}
</style>
<script>
import { groupByArray, strftime_vista, strptime_vista } from './util.mjs';
const name_of_status = {
0: 'Error',
1: 'Discontinued',
2: 'Complete',
3: 'Hold',
4: 'Flagged',
5: 'Pending',
6: 'Active',
7: 'Expired',
8: 'Scheduled',
9: 'Partial results',
10: 'Delayed',
11: 'Unreleased',
12: 'DC/edit',
13: 'Cancelled',
14: 'Lapsed',
15: 'Renewed',
97: '',
98: 'New',
99: 'No status'
};
export default {
props: {
client: Object,
dfn: String,
filter: { default: 2 },
group: { default: 1 },
date_begin: Date,
date_end: Date
},
data() {
return {
orders: [],
details: [],
map_groups: {},
name_of_status
};
},
computed: {
params() {
return { dfn: this.dfn, filter: this.filter, group: this.group, date_begin: strftime_vista(this.date_begin), date_end: strftime_vista(this.date_end) };
}
},
watch: {
async params(value) {
this.orders = await this.client.ORWORR_AGET(value.dfn, value.filter, value.group, value.date_begin, value.date_end);
},
async orders(value) {
this.details = this.orders.length > 0 ? groupByArray(await this.client.ORWORR_GET4LST(0, 0, value.map(x => x.ifn)), x => x.Grp) : [];
}
},
methods: {
strptime_vista
},
async mounted() {
this.map_groups = (await this.client.ORWORDG_ALLTREE()).reduce((acc, x) => (acc[x.ien] = x, acc), {});
}
};
</script>

View File

@ -179,3 +179,36 @@ export function measurement_parse(data) {
res.push(...extras); res.push(...extras);
return res; return res;
} }
export function order_parse(data) {
var res = [], item, line;
for(var i = 0; i < data.length; ++i) {
if((line = data[i]).startsWith('~')) {
res.push(item = line.slice(1).split('^'));
item.IFN = item[0];
item.Grp = item[1];
item.OrdTm = item[2];
item.StrtTm = item[3];
item.StopTm = item[4];
item.Sts = item[5];
item.Sig = item[6];
item.Nrs = item[7];
item.Clk = item[8];
item.PrvID = item[9];
item.PrvNam = item[10];
item.Act = item[11];
item.Flagged = item[12];
item.DCType = item[13];
item.ChartRev = item[14];
item.DEA = item[15];
item.DigSig = item[17];
item.LOC = item[18];
item.DCORIGINAL = item[19];
item.IsPendingDCorder = item[20];
item.IsDelayOrder = item[21];
item.text = [];
} else if((item) && (line.startsWith('t'))) item.text.push(line.slice(1));
else console.log('INVALID:', line);
}
return res;
}

View File

@ -2,7 +2,7 @@ import { reactive, watch } from 'vue';
import vista from './vista.mjs'; import vista from './vista.mjs';
import cookie from './cookie.mjs'; import cookie from './cookie.mjs';
import { lab_parse, lab_reparse_results, measurement_parse } from './reportparser.mjs'; import { lab_parse, lab_reparse_results, measurement_parse, order_parse } from './reportparser.mjs';
export const state = reactive(cookie.get('state') ? JSON.parse(cookie.get('state')) : {}); export const state = reactive(cookie.get('state') ? JSON.parse(cookie.get('state')) : {});
if((!state.secret) && (cookie.get('secret'))) state.resources = cookie.get('secret'); if((!state.secret) && (cookie.get('secret'))) state.resources = cookie.get('secret');
@ -67,12 +67,24 @@ export function caretseparated1(fn, columns=null) {
} }
} }
export function sliced(fn, start, end) {
return async function(...args) {
return (await fn(...args)).slice(start, end);
}
}
export function labreportparsed(fn) { export function labreportparsed(fn) {
return async function(...args) { return async function(...args) {
return lab_parse(await fn(...args)); return lab_parse(await fn(...args));
} }
} }
export function orderparsed(fn) {
return async function(...args) {
return order_parse(await fn(...args));
}
}
export function tabulated(fn, mapping) { export function tabulated(fn, mapping) {
return async function(...args) { return async function(...args) {
var res = (await fn(...args)).map(function(row) { return row.slice(); }), nrow = res.length; var res = (await fn(...args)).map(function(row) { return row.slice(); }), nrow = res.length;
@ -141,6 +153,11 @@ export function Client(cid, secret) {
this.ORWLRR_INTERIM = memoized(labreportparsed(unwrapped(logged((...args) => this.callctx(['OR CPRS GUI CHART'], 'ORWLRR_INTERIM', ...args), 'ORWLRR_INTERIM')))); this.ORWLRR_INTERIM = memoized(labreportparsed(unwrapped(logged((...args) => this.callctx(['OR CPRS GUI CHART'], 'ORWLRR_INTERIM', ...args), 'ORWLRR_INTERIM'))));
this.ORWLRR_INTERIM_RESULTS = memoized(async (...args) => lab_reparse_results(await this.ORWLRR_INTERIM(...args))); this.ORWLRR_INTERIM_RESULTS = memoized(async (...args) => lab_reparse_results(await this.ORWLRR_INTERIM(...args)));
this.ORWORDG_ALLTREE = memoized(caretseparated(unwrapped(logged(() => this.callctx(['OR CPRS GUI CHART'], 'ORWORDG_ALLTREE'), 'ORWORDG_ALLTREE')), ['ien', 'name', 'parent', 'has_children']));
this.ORWORDG_REVSTS = memoized(caretseparated(unwrapped(logged(() => this.callctx(['OR CPRS GUI CHART'], 'ORWORDG_REVSTS'), 'ORWORDG_REVSTS')), ['ien', 'name', 'parent', 'has_children']));
this.ORWORR_AGET = memoized(caretseparated(sliced(unwrapped(logged((...args) => this.callctx(['OR CPRS GUI CHART'], 'ORWORR_AGET', ...args), 'ORWORR_AGET')), 1), ['ifn', 'dgrp', 'time']));
this.ORWORR_GET4LST = memoized(orderparsed(unwrapped(logged((...args) => this.callctx(['OR CPRS GUI CHART'], 'ORWORR_GET4LST', ...args), 'ORWORR_GET4LST'))));
return this; return this;
} }
Client._registry = {}; Client._registry = {};

View File

@ -31,7 +31,7 @@ class CacheProxyRPC(util.CacheProxy):
if volatile is None: if volatile is None:
volatile = util.Store().memo volatile = util.Store().memo
self._cache(('__call__', 'close', 'authenticate', 'keepalive', 'XWB_CREATE_CONTEXT', 'XWB_IM_HERE'), None) self._cache(('__call__', 'close', 'authenticate', 'keepalive', 'XWB_CREATE_CONTEXT', 'XWB_IM_HERE'), None)
self._cache(('SDEC_RESOURCE', 'ORWLRR_ALLTESTS_ALL'), persistent, prefix=prefix, ttl=float('inf')) self._cache(('SDEC_RESOURCE', 'ORWLRR_ALLTESTS_ALL', 'ORWORDG_ALLTREE', 'ORWORDG_REVSTS'), persistent, prefix=prefix, ttl=float('inf'))
self._cache(('XWB_GET_BROKER_INFO', 'XUS_INTRO_MSG'), volatile, prefix=prefix, ttl=float('inf')) self._cache(('XWB_GET_BROKER_INFO', 'XUS_INTRO_MSG'), volatile, prefix=prefix, ttl=float('inf'))
self._cache(None, volatile, prefix=prefix, ttl=float('-inf')) self._cache(None, volatile, prefix=prefix, ttl=float('-inf'))
def _cache_persistent(self, persistent=None, prefix=''): def _cache_persistent(self, persistent=None, prefix=''):