Order viewer
This commit is contained in:
		
							
								
								
									
										28
									
								
								htdocs/OrderFilterPicker.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								htdocs/OrderFilterPicker.vue
									
									
									
									
									
										Normal 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>
 | 
			
		||||
@@ -21,6 +21,14 @@
 | 
			
		||||
				<ViewVitalsLabs :client="client" :dfn="dfn" :date_begin="report_date_begin" :date_end="report_date" />
 | 
			
		||||
			</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>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
@@ -29,12 +37,14 @@
 | 
			
		||||
 | 
			
		||||
	import DateRangePicker from './DateRangePicker.vue';
 | 
			
		||||
	import ViewVitalsLabs from './ViewVitalsLabs.vue';
 | 
			
		||||
	import OrderFilterPicker from './OrderFilterPicker.vue';
 | 
			
		||||
	import ViewOrders from './ViewOrders.vue';
 | 
			
		||||
 | 
			
		||||
	var now = new Date();
 | 
			
		||||
 | 
			
		||||
	export default {
 | 
			
		||||
		components: {
 | 
			
		||||
			DateRangePicker, ViewVitalsLabs
 | 
			
		||||
			DateRangePicker, ViewVitalsLabs, OrderFilterPicker, ViewOrders
 | 
			
		||||
		},
 | 
			
		||||
		props: {
 | 
			
		||||
			client: Object
 | 
			
		||||
@@ -44,7 +54,10 @@
 | 
			
		||||
				dfn: null,
 | 
			
		||||
				info: null,
 | 
			
		||||
				report_date: now,
 | 
			
		||||
				report_date_begin: now
 | 
			
		||||
				report_date_begin: now,
 | 
			
		||||
				orders_filter: 2,
 | 
			
		||||
				orders_date: now,
 | 
			
		||||
				orders_date_begin: now
 | 
			
		||||
			};
 | 
			
		||||
		},
 | 
			
		||||
		watch: {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										104
									
								
								htdocs/ViewOrders.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								htdocs/ViewOrders.vue
									
									
									
									
									
										Normal 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>
 | 
			
		||||
@@ -179,3 +179,36 @@ export function measurement_parse(data) {
 | 
			
		||||
	res.push(...extras);
 | 
			
		||||
	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;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,7 @@ import { reactive, watch } from 'vue';
 | 
			
		||||
 | 
			
		||||
import vista from './vista.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')) : {});
 | 
			
		||||
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) {
 | 
			
		||||
	return async function(...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) {
 | 
			
		||||
	return async function(...args) {
 | 
			
		||||
		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_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;
 | 
			
		||||
}
 | 
			
		||||
Client._registry = {};
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								main.py
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								main.py
									
									
									
									
									
								
							@@ -31,7 +31,7 @@ class CacheProxyRPC(util.CacheProxy):
 | 
			
		||||
		if volatile is None:
 | 
			
		||||
			volatile = util.Store().memo
 | 
			
		||||
		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(None, volatile, prefix=prefix, ttl=float('-inf'))
 | 
			
		||||
	def _cache_persistent(self, persistent=None, prefix=''):
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user