datasus 0.4.5 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +7 -13
- package/src/bpa.js +159 -155
- package/src/utils.js +17 -17
- package/CHANGELOG.md +0 -16
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "datasus",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Library with helpers for datasus",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": "blikblum/datasus",
|
|
@@ -15,27 +15,21 @@
|
|
|
15
15
|
"src"
|
|
16
16
|
],
|
|
17
17
|
"devDependencies": {
|
|
18
|
-
"@babel/core": "^7.12.13",
|
|
19
|
-
"@babel/preset-env": "^7.12.13",
|
|
20
|
-
"@rollup/plugin-babel": "^5.2.3",
|
|
21
18
|
"chai": "^4.3.0",
|
|
22
|
-
"del": "^6.0.0",
|
|
23
19
|
"eslint": "^7.19.0",
|
|
24
20
|
"eslint-config-prettier": "^7.2.0",
|
|
21
|
+
"lodash-es": "^4.18.1",
|
|
25
22
|
"mocha": "^8.2.1",
|
|
26
23
|
"prettier": "^2.0.2",
|
|
27
|
-
"rollup": "^2.38.5",
|
|
28
24
|
"sinon": "^9.2.4"
|
|
29
25
|
},
|
|
30
26
|
"scripts": {
|
|
31
27
|
"lint": "eslint src test tools",
|
|
32
28
|
"test": "mocha test/*.spec.js",
|
|
33
|
-
"test:watch": "mocha --watch --parallel test/*.spec.js"
|
|
34
|
-
"build": "node tools/build.cjs",
|
|
35
|
-
"prepublishOnly": "npm run build"
|
|
29
|
+
"test:watch": "mocha --watch --parallel test/*.spec.js"
|
|
36
30
|
},
|
|
37
31
|
"dependencies": {
|
|
38
|
-
"date-fns": "^
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
}
|
|
32
|
+
"date-fns": "^4.4.0"
|
|
33
|
+
},
|
|
34
|
+
"packageManager": "yarn@4.18.0"
|
|
35
|
+
}
|
package/src/bpa.js
CHANGED
|
@@ -1,155 +1,159 @@
|
|
|
1
|
-
import { normalizeNumberText, padStartNumber, removeAccents } from './utils.js'
|
|
2
|
-
import { differenceInYears, format } from 'date-fns'
|
|
3
|
-
|
|
4
|
-
const ENTRIES_PER_SHEET = 20
|
|
5
|
-
const THREE_BLANKS = ' '
|
|
6
|
-
const EIGHT_BLANKS = ' '
|
|
7
|
-
const TEN_BLANKS = ' '
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
padStartNumber(
|
|
31
|
-
|
|
32
|
-
`${
|
|
33
|
-
`${origin.
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
.
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
const
|
|
48
|
-
const
|
|
49
|
-
const
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
padStartNumber(
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
padStartNumber(
|
|
60
|
-
(procedure.
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
const
|
|
69
|
-
const
|
|
70
|
-
const
|
|
71
|
-
const
|
|
72
|
-
const
|
|
73
|
-
const
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
`${procedure.
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
padStartNumber(
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
`${
|
|
87
|
-
|
|
88
|
-
padStartNumber(
|
|
89
|
-
padStartNumber(procedure.
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
THREE_BLANKS, //
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
' '.repeat(
|
|
102
|
-
|
|
103
|
-
`${patient.
|
|
104
|
-
`${
|
|
105
|
-
`${removeAccents(patient.
|
|
106
|
-
`${patient.
|
|
107
|
-
`${
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
1
|
+
import { normalizeNumberText, padStartNumber, removeAccents } from './utils.js'
|
|
2
|
+
import { differenceInYears, format } from 'date-fns'
|
|
3
|
+
|
|
4
|
+
const ENTRIES_PER_SHEET = 20
|
|
5
|
+
const THREE_BLANKS = ' '
|
|
6
|
+
const EIGHT_BLANKS = ' '
|
|
7
|
+
const TEN_BLANKS = ' '
|
|
8
|
+
const ELEVEN_BLANKS = ' '
|
|
9
|
+
const EMPTY_DATE = EIGHT_BLANKS
|
|
10
|
+
|
|
11
|
+
const LINE_SEPARATOR = '\r\n'
|
|
12
|
+
|
|
13
|
+
const formatCompetence = (competence) => {
|
|
14
|
+
const date = competence instanceof Date ? competence : new Date(competence.year, competence.month)
|
|
15
|
+
|
|
16
|
+
return format(date, 'yyyyMM')
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const getHeader = (
|
|
20
|
+
competence,
|
|
21
|
+
origin,
|
|
22
|
+
destination,
|
|
23
|
+
appInfo,
|
|
24
|
+
{ lineCount, sheetCount, controlAccumulator },
|
|
25
|
+
) => {
|
|
26
|
+
const controlCode = controlAccumulator % 1111
|
|
27
|
+
const header = [
|
|
28
|
+
'01#BPA#',
|
|
29
|
+
formatCompetence(competence),
|
|
30
|
+
padStartNumber(lineCount, 6, '0').slice(0, 6),
|
|
31
|
+
padStartNumber(sheetCount, 6, '0').slice(0, 6),
|
|
32
|
+
`${controlCode}`.padStart(4, '0').slice(0, 4),
|
|
33
|
+
`${removeAccents(origin.name)}`.padEnd(30, ' ').slice(0, 30),
|
|
34
|
+
`${origin.abbrev || ''}`.padEnd(6, ' ').slice(0, 6),
|
|
35
|
+
normalizeNumberText(origin.cnpj || origin.cpf)
|
|
36
|
+
.padStart(14, '0')
|
|
37
|
+
.slice(0, 14),
|
|
38
|
+
`${destination.name || ''}`.padEnd(40, ' ').slice(0, 40),
|
|
39
|
+
(destination.indicator || '').slice(0, 1),
|
|
40
|
+
appInfo.padEnd(10, ' ').slice(0, 10),
|
|
41
|
+
].join('')
|
|
42
|
+
|
|
43
|
+
return header
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const getConsolidatedEntry = (procedure, competence, origin, index) => {
|
|
47
|
+
const { patient = {} } = procedure
|
|
48
|
+
const sheetNumber = Math.trunc(index / ENTRIES_PER_SHEET) + 1
|
|
49
|
+
const sequentialNumber = (index % ENTRIES_PER_SHEET) + 1
|
|
50
|
+
const age = patient.birthDate ? differenceInYears(new Date(), patient.birthDate) : 0
|
|
51
|
+
const entry = [
|
|
52
|
+
'02',
|
|
53
|
+
padStartNumber(origin.cnes, 7, '0').slice(0, 7),
|
|
54
|
+
formatCompetence(competence),
|
|
55
|
+
`${procedure.cbo || ''}`.padStart(6, ' ').slice(0, 6),
|
|
56
|
+
padStartNumber(sheetNumber, 3, '0'),
|
|
57
|
+
padStartNumber(sequentialNumber, 2, '0'),
|
|
58
|
+
normalizeNumberText(procedure.code).padStart(10, '0').slice(0, 10),
|
|
59
|
+
padStartNumber(age, 3, '0').slice(0, 3),
|
|
60
|
+
padStartNumber(procedure.quantity, 6, '0').slice(0, 6),
|
|
61
|
+
(procedure.origin || 'BPA').padStart(3, ' ').slice(0, 3),
|
|
62
|
+
].join('')
|
|
63
|
+
|
|
64
|
+
return entry
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const getIndividualEntry = (procedure, competence, origin, index) => {
|
|
68
|
+
const { patient = {} } = procedure
|
|
69
|
+
const sheetNumber = Math.trunc(index / ENTRIES_PER_SHEET) + 1
|
|
70
|
+
const sequentialNumber = (index % ENTRIES_PER_SHEET) + 1
|
|
71
|
+
const age = patient.birthDate ? differenceInYears(new Date(), patient.birthDate) : 0
|
|
72
|
+
const birthDate = patient.birthDate ? format(patient.birthDate, 'yyyyMMdd') : EMPTY_DATE
|
|
73
|
+
const date = procedure.date ? format(procedure.date, 'yyyyMMdd') : EMPTY_DATE
|
|
74
|
+
const entry = [
|
|
75
|
+
'03',
|
|
76
|
+
padStartNumber(normalizeNumberText(origin.cnes), 7, '0').slice(0, 7),
|
|
77
|
+
formatCompetence(competence),
|
|
78
|
+
`${procedure.cns || ''}`.padStart(15, ' ').slice(0, 15),
|
|
79
|
+
`${procedure.cbo || ''}`.padStart(6, ' ').slice(0, 6),
|
|
80
|
+
date,
|
|
81
|
+
padStartNumber(sheetNumber, 3, '0').slice(0, 3),
|
|
82
|
+
padStartNumber(sequentialNumber, 2, '0').slice(0, 2),
|
|
83
|
+
normalizeNumberText(procedure.code).padStart(10, '0').slice(0, 10),
|
|
84
|
+
`${patient.cns || ''}`.padStart(15, ' ').slice(0, 15),
|
|
85
|
+
(patient.gender || ' ').slice(0, 1).slice(0, 1),
|
|
86
|
+
`${patient.ibge || ''}`.padEnd(6, ' ').slice(0, 6),
|
|
87
|
+
`${procedure.cid || ''}`.padEnd(4, ' ').slice(0, 4),
|
|
88
|
+
padStartNumber(age, 3, '0').slice(0, 3),
|
|
89
|
+
padStartNumber(procedure.quantity, 6, '0').slice(0, 6),
|
|
90
|
+
padStartNumber(procedure.character || 1, 2, '0').slice(0, 2),
|
|
91
|
+
`${procedure.authorization || ''}`.padEnd(13, ' ').slice(0, 13),
|
|
92
|
+
(procedure.origin || 'BPA').padStart(3, ' ').slice(0, 3),
|
|
93
|
+
`${removeAccents(patient.name)}`.padEnd(30, ' ').slice(0, 30),
|
|
94
|
+
birthDate,
|
|
95
|
+
padStartNumber(patient.race || 99, 2, '0').slice(0, 2),
|
|
96
|
+
`${patient.ethnicity || ''}`.padEnd(4, ' ').slice(0, 4),
|
|
97
|
+
padStartNumber(patient.nationality || 10, 3, '0').slice(0, 3),
|
|
98
|
+
THREE_BLANKS, // service code
|
|
99
|
+
THREE_BLANKS, // classification code
|
|
100
|
+
EIGHT_BLANKS, // sequence code
|
|
101
|
+
' '.repeat(4), // area code
|
|
102
|
+
' '.repeat(14), // maintainer cnpj
|
|
103
|
+
`${patient.cep || EIGHT_BLANKS}`.padStart(8, '0').slice(0, 8),
|
|
104
|
+
`${patient.placeCode || THREE_BLANKS}`.padStart(3, '0').slice(0, 3),
|
|
105
|
+
`${removeAccents(patient.address)}`.padEnd(30, ' ').slice(0, 30),
|
|
106
|
+
`${removeAccents(patient.addressComplement)}`.padEnd(10, ' ').slice(0, 10),
|
|
107
|
+
`${patient.addressNumber || ''}`.padEnd(5, ' ').slice(0, 5),
|
|
108
|
+
`${removeAccents(patient.addressDistrict)}`.padEnd(30, ' ').slice(0, 30),
|
|
109
|
+
normalizeNumberText(patient.phone).padEnd(11, ' ').slice(0, 11),
|
|
110
|
+
`${patient.email || ''}`.padEnd(40, ' ').slice(0, 40),
|
|
111
|
+
padStartNumber(procedure.nationalId || TEN_BLANKS, 10, '0').slice(0, 10),
|
|
112
|
+
procedure.cpf || ELEVEN_BLANKS,
|
|
113
|
+
' ', // situação de rua
|
|
114
|
+
procedure.cpf ? 'N' : 'S' // sem CPF
|
|
115
|
+
].join('')
|
|
116
|
+
|
|
117
|
+
return entry
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export const generateBPA = (
|
|
121
|
+
{ procedures = [], origin = {}, destination = {}, competence = {}, appInfo = '' } = {},
|
|
122
|
+
{ consolidated = true, individual = true } = {},
|
|
123
|
+
) => {
|
|
124
|
+
const stats = { lineCount: 0, sheetCount: 0, controlAccumulator: 0 }
|
|
125
|
+
|
|
126
|
+
const consolidatedEntries = consolidated
|
|
127
|
+
? procedures.map((procedure, index) => {
|
|
128
|
+
return getConsolidatedEntry(procedure, competence, origin, index)
|
|
129
|
+
})
|
|
130
|
+
: []
|
|
131
|
+
|
|
132
|
+
stats.lineCount += consolidatedEntries.length
|
|
133
|
+
stats.sheetCount += Math.ceil(consolidatedEntries.length / ENTRIES_PER_SHEET)
|
|
134
|
+
|
|
135
|
+
const individualEntries = individual
|
|
136
|
+
? procedures.map((procedure, index) => {
|
|
137
|
+
const codeText = normalizeNumberText(procedure.code)
|
|
138
|
+
const code = parseInt(codeText, 10)
|
|
139
|
+
const quantity = procedure.quantity || 1
|
|
140
|
+
stats.controlAccumulator += code + quantity
|
|
141
|
+
return getIndividualEntry(procedure, competence, origin, index)
|
|
142
|
+
})
|
|
143
|
+
: []
|
|
144
|
+
|
|
145
|
+
stats.lineCount += individualEntries.length
|
|
146
|
+
stats.sheetCount += Math.ceil(individualEntries.length / ENTRIES_PER_SHEET)
|
|
147
|
+
|
|
148
|
+
const header = getHeader(competence, origin, destination, appInfo, stats)
|
|
149
|
+
|
|
150
|
+
const content = [header]
|
|
151
|
+
if (consolidated) {
|
|
152
|
+
content.push(consolidatedEntries.join(LINE_SEPARATOR))
|
|
153
|
+
}
|
|
154
|
+
if (individual) {
|
|
155
|
+
content.push(individualEntries.join(LINE_SEPARATOR))
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
return content.join(LINE_SEPARATOR)
|
|
159
|
+
}
|
package/src/utils.js
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
const punctuationRegex = /\D/g
|
|
2
|
-
const diacriticsRegex = /[\u0300-\u036f]/g
|
|
3
|
-
|
|
4
|
-
export const padStartNumber = (number = '', maxLength, fillString) => {
|
|
5
|
-
return number.toString().padStart(maxLength, fillString)
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
export const normalizeNumberText = (number = '') => {
|
|
9
|
-
if (typeof number === 'string') {
|
|
10
|
-
return number.replace(punctuationRegex, '')
|
|
11
|
-
}
|
|
12
|
-
return `${number}`
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export const removeAccents = (text = '') => {
|
|
16
|
-
return text.normalize('NFD').replace(diacriticsRegex, '')
|
|
17
|
-
}
|
|
1
|
+
const punctuationRegex = /\D/g
|
|
2
|
+
const diacriticsRegex = /[\u0300-\u036f]/g
|
|
3
|
+
|
|
4
|
+
export const padStartNumber = (number = '', maxLength, fillString) => {
|
|
5
|
+
return number.toString().padStart(maxLength, fillString)
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export const normalizeNumberText = (number = '') => {
|
|
9
|
+
if (typeof number === 'string') {
|
|
10
|
+
return number.replace(punctuationRegex, '')
|
|
11
|
+
}
|
|
12
|
+
return `${number}`
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const removeAccents = (text = '') => {
|
|
16
|
+
return text.normalize('NFD').replace(diacriticsRegex, '')
|
|
17
|
+
}
|
package/CHANGELOG.md
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
## datasus Change Log
|
|
2
|
-
|
|
3
|
-
All notable changes to this project will be documented in this file.
|
|
4
|
-
|
|
5
|
-
### [Unreleased][unreleased]
|
|
6
|
-
|
|
7
|
-
- XXXXXXXX
|
|
8
|
-
|
|
9
|
-
### [v0.1.0] - 2018-01-01
|
|
10
|
-
|
|
11
|
-
- XXXXXXX
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
[unreleased]: https://github.com/blikblum/datasus/compare/v0.1.0...HEAD
|
|
16
|
-
[v0.1.0]: https://github.com/blikblum/datasus/compare/v0.0.1...v0.1.0
|