1 """GNUmed to MSVA (Canada) connector classes.
2
3 Jim's notes:
4
5 - source directory will reside on a Windows NTFS file system volume.
6 - end-of-Record will be designated by Carriage Return and Line Feed
7 - character set is "plain Western" (ISO Latin 1)
8 - record mockup:
9
10 FIRSTNAME XXLASTNAME 912345677300BC 196012251234512345M6 ADDRESS_LINE_1_XXXXXXXXXXADDRESS_LINE_2_XXXXXXXXXXCITY_XXXXXXXXXXXXXXXXXXXXBCA2A 2A2 604124456760489012340000000002009071307801
11
12 - "PHN" + "Dependent #" + "Carrier ID" (in the above example "9123456773", "00", BC") work together as an identifier
13
14 - format specification:
15
16 *-- MSVAEX30.TXT format
17 *--
18 *--------------------------------------------------------------------
19 *-- First Name X(20) No punctuations ( e.g. John Allen)
20 *-- MSP Initials X(02) e.g. JA
21 *-- Last Name X(25)
22 *-- PHN 9(10)
23 *-- Dependent # 9(02) 66 for newborn, otherwise zeros
24 *-- Carrier ID X(02) Province providing coverage:
25 *-- BC, AB, SA, MB, ON, PQ, OI, NB, NS, NL, YT, NT, NU
26 *-- Exempt X(01) "X" for exempt, otherwise blank
27 *-- Opted-out X(01) "H" for Hard (Send payment to patient address)
28 *-- "S" for Soft (Send paymant to office address)
29 *-- Blank for Opted-in
30 *-- Visits Used 9(02) # of MSP visits used this calendar year, form zero up
31 *-- to 12 0r 15 depending on age.
32 *-- Birthdate 9(08) ccyymmdd
33 *-- Payee # 9(05)
34 *-- Practitioner # 9(05)
35 *-- Sex X(01) M, F
36 *-- Chart # X(08)
37 *-- Street 1 X(25)
38 *-- Street 2 X(25)
39 *-- City X(25)
40 *-- Province X(02)
41 *-- Postal Code X(09) A0A'b'0A0 or US Zip Code
42 *-- Home Phone 9(10) If no area code use 3 leading zeros
43 *-- Work Phone 9(10) If no area code use 3 leading zeros
44 *-- SIN 9(09)
45 *-- Last Service Date 9(08) ccyymmdd
46 *-- Referral Doctor 9(05)
47 *--
48 *-- Record size = 220 + <CR><LF> = 222 End-of-Record designated by Carriage Return and Line Feed.
49 *-- File is ASCII text - Named "MSVAEX30.TXT"
50 *-- X(n) = Aplhanumeric, left justified, padded with blanks
51 *-- 9(n) = Numeric, leading zeros
52
53 A0A'b'0A0:
54
55 - standard Canadian postal code format which is 3 characters:
56 - (upper case letter + single digit number + upper case letter)
57 - followed by a breaking space
58 - followed by (number+letter number)
59
60 US Zip code:
61
62 - 12345 or 12345-1234
63
64 Dependant # / Carrier ID
65
66 I did some checking, and it seems in BC a corner case about
67 the "00" being instead "66". The provision to designate
68 newborns (as dependent "66" and, in the case of multiple
69 births, "64" ... "63") seems now obsoleted by the ability of
70 the hospital to log into the provincial system and generate
71 a new Personal Health Number. Any such legacy values in
72 Medical Manager would not be to drive the slave.
73
74 The PHN can therefore be taken as unique *within* carrier
75 ID. While the following may be far fetched, there is no
76 agreement between Canada's provinces to avoid collisions, so
77 it could be possible to exist
78
79 BC.CA MOH | Personal Health Number | 90123456780
80 ON.CA MOH | Personal Health Number | 90123456780
81
82 """
83
84 __license__ = "GPL"
85 __version__ = "$Revision: 1.2 $"
86 __author__ = "K.Hilbert <Karsten.Hilbert@gmx.net>"
87
88
89
90 import sys, codecs, time, datetime as pyDT
91
92
93
94 if __name__ == '__main__':
95 sys.path.insert(0, '../../')
96 from Gnumed.pycommon import gmTools, gmDateTime
97 from Gnumed.business import gmPerson
98
99 MSVA_line_len = 220
100 MSVA_dob_format = '%Y%m%d'
101 MSVA_encoding = 'latin1'
102
103
105
106 if encoding is None:
107 encoding = MSVA_encoding
108
109 pats_file = codecs.open(filename = filename, mode = 'rU', encoding = encoding)
110
111 dtos = []
112
113 for line in pats_file:
114 if len(line) < MSVA_line_len:
115 continue
116
117 dto = gmPerson.cDTO_person()
118 dto.source = u'Med.Manager/CA'
119 dto.external_ids = []
120
121 dto.firstnames = u'%s %s' % (
122 gmTools.capitalize(line[:20].strip(), gmTools.CAPS_FIRST_ONLY),
123 gmTools.capitalize(line[20:22].strip(), gmTools.CAPS_FIRST_ONLY)
124 )
125 dto.lastnames = gmTools.capitalize(line[22:47].strip(), gmTools.CAPS_FIRST_ONLY)
126
127 province = line[59:61]
128 value = line[47:57].strip()
129 if value != u'':
130 dto.external_ids.append({'name': u'PHN (%s.CA)' % province, 'value': value, 'issuer': 'MOH (%s.CA)' % province})
131
132 dob = time.strptime(line[65:73].strip(), MSVA_dob_format)
133 dto.dob = pyDT.datetime(dob.tm_year, dob.tm_mon, dob.tm_mday, tzinfo = gmDateTime.gmCurrentLocalTimezone)
134 dto.gender = line[83].lower()
135
136 value = line[84:92].strip()
137 if value != u'':
138 dto.external_ids.append({'name': u'MM (CA) Chart #', 'value': value, 'issuer': 'Medical Manager (CA) application'})
139
140
141 dto.street = u'%s // %s' % (
142 gmTools.capitalize(line[92:117].strip(), gmTools.CAPS_FIRST),
143 gmTools.capitalize(line[117:142].strip(), gmTools.CAPS_FIRST)
144 )
145 dto.urb = line[142:167].strip()
146 dto.region = line[167:169].strip()
147 dto.zip = line[169:178].strip()
148
149 dto.comms = [
150 {'homephone': line[178:188]},
151 {'workphone': line[188:198]}
152 ]
153
154 value = line[198:207].strip()
155 if value != u'':
156 dto.external_ids.append({'name': u'Social Insurance Number', 'value': value, 'issuer': 'Canada'})
157
158 dtos.append(dto)
159
160 pats_file.close()
161
162 return dtos
163
164
165
166 if __name__ == "__main__":
167 from Gnumed.pycommon import gmI18N
168 gmI18N.activate_locale()
169 gmI18N.install_domain()
170 gmDateTime.init()
171
172 patfile = sys.argv[1]
173 print "reading patient data from MSVA file [%s]" % patfile
174
175 dtos = read_persons_from_msva_file(patfile)
176 for dto in dtos:
177 print "DTO:", dto
178 print "dto.dob:", dto.dob, type(dto.dob)
179 print "dto.dob.tz:", dto.dob.tzinfo
180 print "dto.zip / urb / region: %s / %s / %s" % (dto.zip, dto.urb, dto.region)
181 print "dto.street:", dto.street
182 for ext_id in dto.external_ids:
183 print ext_id
184 for comm in dto.comms:
185 print comm
186
187
188
189
190
191