@cosyte/x12 0.0.13 → 0.0.15
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/CHANGELOG.md +369 -2
- package/KNOWN-LIMITATIONS.md +325 -8
- package/dist/index.cjs +131 -26
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +277 -25
- package/dist/index.d.ts +277 -25
- package/dist/index.mjs +130 -27
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -136,6 +136,7 @@ var WARNING_CODES = {
|
|
|
136
136
|
X12_UNKNOWN_HI_QUALIFIER: "X12_UNKNOWN_HI_QUALIFIER",
|
|
137
137
|
X12_MISSING_REQUIRED_LOOP: "X12_MISSING_REQUIRED_LOOP",
|
|
138
138
|
X12_837_UNKNOWN_VARIANT: "X12_837_UNKNOWN_VARIANT",
|
|
139
|
+
X12_837_AMBIGUOUS_VARIANT: "X12_837_AMBIGUOUS_VARIANT",
|
|
139
140
|
X12_UNKNOWN_CLAIM_STATUS_CATEGORY: "X12_UNKNOWN_CLAIM_STATUS_CATEGORY",
|
|
140
141
|
X12_UNKNOWN_CLAIM_STATUS: "X12_UNKNOWN_CLAIM_STATUS",
|
|
141
142
|
X12_834_UNKNOWN_MAINTENANCE_TYPE: "X12_834_UNKNOWN_MAINTENANCE_TYPE",
|
|
@@ -143,6 +144,7 @@ var WARNING_CODES = {
|
|
|
143
144
|
X12_837_SERVICE_LINE_NOT_DECODED: "X12_837_SERVICE_LINE_NOT_DECODED",
|
|
144
145
|
X12_837_SERVICE_LINE_DROPPED: "X12_837_SERVICE_LINE_DROPPED",
|
|
145
146
|
X12_837_SERVICE_SEGMENT_WITHOUT_LX: "X12_837_SERVICE_SEGMENT_WITHOUT_LX",
|
|
147
|
+
X12_837_SERVICE_SEGMENT_REPEATED: "X12_837_SERVICE_SEGMENT_REPEATED",
|
|
146
148
|
X12_837_ENTITY_SEGMENT_DISCARDED_AFTER_LX: "X12_837_ENTITY_SEGMENT_DISCARDED_AFTER_LX",
|
|
147
149
|
X12_837_PAY_TO_ADDRESS_REPEATED: "X12_837_PAY_TO_ADDRESS_REPEATED",
|
|
148
150
|
X12_835_BALANCE_NOT_EVALUABLE: "X12_835_BALANCE_NOT_EVALUABLE",
|
|
@@ -220,7 +222,8 @@ var WARNING_MESSAGES = {
|
|
|
220
222
|
X12_MISSING_REQUIRED_LOOP_2000B: 'Missing required loop "2000B" (Subscriber HL): no Subscriber HL precedes the CLM.',
|
|
221
223
|
X12_MISSING_REQUIRED_LOOP_2010BA: 'Missing required loop "2010BA" (Subscriber Name): no Subscriber Name follows the Subscriber HL.',
|
|
222
224
|
X12_MISSING_REQUIRED_LOOP_2010BB: 'Missing required loop "2010BB" (Payer Name): no Payer Name follows the Subscriber HL.',
|
|
223
|
-
X12_837_UNKNOWN_VARIANT:
|
|
225
|
+
X12_837_UNKNOWN_VARIANT: "837 variant could not be resolved: ST-03's implementation convention reference is absent, empty, or not an 837 Technical Report Type 3 identifier this reader recognises, and no SVx service-line segment was present to fall back on. The set of references it recognises covers the professional, institutional and dental 837 guides HIPAA adopts at 45 CFR 162.1102 together with their published errata; it is NOT claimed to be exhaustive, and this message deliberately does not enumerate it, because a list here goes stale the moment a guide is added. A reference outside that set is not asserted to be invalid - all this code reports is that this reader could not turn it into a variant and had nothing to fall back on. The verbatim reference is preserved on the model; read it there rather than inferring what the sender meant.",
|
|
226
|
+
X12_837_AMBIGUOUS_VARIANT: "837 variant resolved from a service segment while the transaction body carries service segments of more than one variant: no caller `type` option was supplied and ST-03's implementation convention reference is absent, empty, or not an 837 Technical Report Type 3 identifier this reader recognises, so this reader fell back to the FIRST SV1 / SV2 / SV3 in the body, and a later one names a different variant. `submission.variant` is therefore a guess between contradictory evidence, and every claim and service line in the submission was read against it. Which service segment is the stray one is NOT decided here and is not derivable from the TR3s: this reader cannot tell a stray service segment from a conformant one, and the fallback takes the first regardless of whether any Loop 2400 was open at it, so an orphan segment decides the variant like any other. Read the bound literally, as a property of the RESOLUTION rather than of the document: this reports the fallback's own ambiguity, so a caller-supplied `type`, or an ST-03 this reader does turn into a variant, means no guess was made and this code is NOT raised however mixed the body is. Whatever else this reader raised on a document that reaches this code, it still raises, at the same position, and this one is added beside them. It is NOT a list of what else you will see, and it does not promise that any particular loss on such a document is reported at all. Re-read with the `type` option to decode the document against a variant you trust. The verbatim segments are preserved on the transaction set; read them there before acting on the submission's type.",
|
|
224
227
|
X12_UNKNOWN_CLAIM_STATUS_CATEGORY: "Unknown claim status category (CSCC): the STC composite's first component is outside the bundled snapshot. The verbatim code is preserved on the status; only its description is unavailable.",
|
|
225
228
|
X12_UNKNOWN_CLAIM_STATUS: "Unknown claim status code (CSC): the STC composite's second component is outside the bundled snapshot. The verbatim code is preserved on the status; only its description is unavailable.",
|
|
226
229
|
X12_834_UNKNOWN_MAINTENANCE_TYPE: "Unknown 834 maintenance type: the INS-03/HD-01 code is outside the bundled snapshot. The verbatim code is preserved on the enrollment and the action is NEVER inferred.",
|
|
@@ -228,6 +231,7 @@ var WARNING_MESSAGES = {
|
|
|
228
231
|
X12_837_SERVICE_LINE_NOT_DECODED: "837 service line with no decoded service segment: the Loop 2400 line opened at `position.segmentIndex` is followed by no SV1 / SV2 / SV3 matching the variant this submission resolved to, so NOTHING carried by the service segment was read. The line's `charge` and `units` are `undefined`, which is what this library puts on a decimal slot it decoded no value into; its procedure code, modifiers, unit of measure and place of service are equally undecoded. Two common causes: the line carries no SVx at all, or it carries one for a different 837 variant than ST-03 (or the caller's `type` option) named. Which side is wrong is NOT decided here, because a caller-supplied `type` can disagree with a perfectly conformant document. The verbatim segments are preserved on the transaction set; read them there before acting on the charge or the quantity.",
|
|
229
232
|
X12_837_SERVICE_LINE_DROPPED: "837 service line dropped from the typed model: the LX at `position.segmentIndex` opened no Loop 2400, so no line appears on any claim's `serviceLines` for it and the SV1 / SV2 / SV3 that followed - its charge, units, procedure code and modifiers - was read into nothing. Compare `X12_837_SERVICE_LINE_NOT_DECODED`, where the line IS on the model and only its service segment went unread. Two causes: no Loop 2300 (CLM) is open at this LX, so there is no claim to attach a line to; or the submission's variant is not one of P / I / D, so no variant-specific line shape could be built. Read `submission.variant` and `submission.claims` to tell them apart; do NOT expect `X12_837_UNKNOWN_VARIANT` alongside this code, because a caller-supplied `type` outside P / I / D reaches the second cause without it. Nothing is fabricated to stand in for the missing line and no claim is synthesized. What becomes of a DTP / AMT / NTE / REF that follows the dropped LX depends on the route and this message does not say; see KNOWN-LIMITATIONS.md. The verbatim segments are preserved on the transaction set; read them there before concluding the claim had no service lines.",
|
|
230
233
|
X12_837_SERVICE_SEGMENT_WITHOUT_LX: "837 service segment with no Loop 2400 to read it into: no service line was open at the SV1 / SV2 / SV3 at `position.segmentIndex`, so NOTHING it carries - its charge, units, procedure code, modifiers, unit of measure and place of service - was read. Read that literally: an LX may well appear earlier in the transaction, and what this reports is that none of them had opened a Loop 2400 still current at this segment. No line appears on any claim's `serviceLines` for it and nothing is fabricated to stand in. Compare the two codes anchored at an LX: `X12_837_SERVICE_LINE_DROPPED`, where an LX IS present and opened no line, and `X12_837_SERVICE_LINE_NOT_DECODED`, where the line is on the model and only its service segment went unread. Neither of those can report the SAME service segment as this code, because both are raised at an LX and this one only where no Loop 2400 is open; a document with several claims can still carry all three. This says NOTHING about how the submission's variant resolved: absent a caller-supplied `type` option, and where ST-03 names no known implementation convention, the reader falls back to the first SV1 / SV2 / SV3 in the transaction, and a segment reported here is eligible for that fallback like any other, so a stray one can decide the variant every line is read against. Read `submission.variant`. The verbatim segments are preserved on the transaction set; read them there before concluding the claim had no service lines.",
|
|
234
|
+
X12_837_SERVICE_SEGMENT_REPEATED: "837 service segment repeated inside one Loop 2400: the SV1 / SV2 / SV3 at `position.segmentIndex` is not the first service segment to arrive in the service line the LX before it opened. This reader's line carries ONE service segment's worth of slots, so it cannot hold both, and this code is the only thing that tells you the document sent more than one. It asserts nothing about what usage the TR3s give the segment; what it reports is that this reader has one set of those slots per line. What the line carries is what the LAST service segment MATCHING the submission's resolved variant wrote onto it, and only that. Such a segment writes every slot its kind writes - the charge, the units and the procedure code among them - so a matching one arriving second leaves NOTHING an earlier matching one wrote, including where the later one's charge or units element is ABSENT: there the line is left with undefined, which is what this library puts on a decimal slot it decoded no value into, over an amount the earlier one stated. A service segment of a kind that does NOT match the resolved variant is read into nothing at all - it overwrites no slot, and what it carries reaches no part of the typed model. Which of them the sender meant is NOT decided here and is not derivable from the TR3s: this reader cannot tell a stray service segment from a conformant one, and picking a winner would be inventing. Nothing is fabricated to stand in, no second line is synthesized - an LX is what opens a line and there is none here - and no earlier value is kept in a second slot. Read the bound literally, as a property of the READ: this reports a second service segment arriving while a Loop 2400 IS open, whether or not it decoded. It is disjoint from `X12_837_SERVICE_SEGMENT_WITHOUT_LX`, which requires that NO Loop 2400 be open where this one requires that one is, so the two can never name the same segment; read that as disjointness and NOT as a promise that a service segment outside an open Loop 2400 is always named by that code, because a service segment FOLLOWING an LX that opened no line at all is named by neither of them, the loss having already been reported at that LX by `X12_837_SERVICE_LINE_DROPPED`. `X12_837_SERVICE_LINE_NOT_DECODED`, anchored at the LX, reports that no service segment matching the variant decoded onto the line at all, so a document can carry both codes on different segments. It fires once per repeat, so three service segments in one Loop 2400 are two warnings, and the count resets with the line: a first service segment under a later LX is a first and never a repeat. It says nothing about how the submission's variant resolved; where the fallback decided that and the body names more than one, `X12_837_AMBIGUOUS_VARIANT` reports it separately. The verbatim segments are preserved on the transaction set; read them there before acting on the charge, the quantity or the procedure code.",
|
|
231
235
|
X12_837_ENTITY_SEGMENT_DISCARDED_AFTER_LX: "837 entity segment read into nothing after a dropped LX: the N3 / N4 / PER / REF at `position.segmentIndex` arrived while no entity loop was open, because an earlier LX in this transaction opened no Loop 2400 (no CLM was open at it) and closed the entity loop that was current there. NOTHING this segment carries reached the model: no party's `address`, `contacts` or `references` was written from it, and no party, claim or line was synthesized to hold it. This is the code that names THAT loss; `X12_837_SERVICE_LINE_DROPPED` is raised at the LX itself and names the SERVICE LINE's loss, never an entity segment, so the two report different things about the same stretch of the document. Read the bound literally, because this code does NOT report every unattached entity segment: it reports one discarded after such an LX and only while nothing since has opened a new loop, so an N3 / N4 / PER / REF that reaches no party by any other route is still silent, and one arriving after a later NM1 is outside this code's scope, whether or not this reader surfaces that segment kind on that party. It reports that the segment reached NO party; it does not claim it would have reached one had the LX been absent, because this reader does not surface every one of these segment kinds on every party (a PER on a patient or a pay-to address, for one). Which party a segment following a stray LX belongs to is not derivable from the TR3s in either direction, so it is discarded rather than attributed: see KNOWN-LIMITATIONS.md. The verbatim segments are preserved on the transaction set; read them there before concluding a party had no address, no secondary identifier or no contact.",
|
|
232
236
|
X12_837_PAY_TO_ADDRESS_REPEATED: "837 pay-to address named more than once in one Loop 2000A: the NM1*87 at `position.segmentIndex` is not the first in this Loop 2000A, and the TR3s allow Loop 2010AB at most once there. The model has ONE pay-to address slot, so it cannot carry both, and this code is the only thing that tells you the document named more than one. The reader NEVER merges them: an N3 or N4 after this segment can no longer add a street line to, or fill a blank in, the address an earlier NM1*87 named, which is what this library did through 0.0.12 - it returned a fused address no sender sent, silently. What the slot carries instead is the LAST occurrence that stated an address of its own; an occurrence that states none - one carrying no N3 or N4 at all, or only a valueless N3 or N4 whose elements are empty - does NOT replace one that did, so nothing an earlier occurrence stated is blanked either. Where no occurrence states an address, the slot holds what the FIRST N3 or N4 to arrive under any of them produced, which may be an address with no elements at all, and which is not necessarily the first occurrence's: an occurrence that carries no N3 or N4 writes nothing, so a later one's valueless N3 is the first write and takes a slot still empty. Read that as the corner it is, and never restate it as the first OCCURRENCE winning. Which occurrence the sender meant is NOT decided here and is not derivable from the TR3s, and the losing occurrence's address is NOT on the model in any form. Read the bound literally: this reports repetition within one Loop 2000A, which is where the pay-to route lives, and an NM1*87 arriving while a CLM is open never reaches that route. The verbatim segments are preserved on the transaction set; read them there before acting on where a payment is to be sent.",
|
|
233
237
|
X12_AMOUNT_ROW_DROPPED: "Amount row dropped from the typed model: the AMT or ADX at `position.segmentIndex` carried no decodable amount (AMT-02, ADX-01), so NO row was built for it and the rest of the segment went with it - its qualifier or adjustment reason code, and any reference qualifier and id. Nothing is fabricated to stand in: a row is not built around a zero this library did not read, which is why the loss is reported rather than papered over. Two routes reach it and this code does not say which: the amount element was ABSENT, or it was present and held bytes that do not decode as a decimal. On this segment only the second route also raises `X12_UNPARSEABLE_DECIMAL`, carrying the failing element in its own `position.elementIndex`, so whether one is present at this `position.segmentIndex` is what separates them - and that code is unchanged by this one, which is raised alongside it rather than in place of it. Read the bound literally: this reports a row whose AMOUNT was read and decoded no value, and it is NOT a general report that an amount segment reached no model. A segment a reader discards before reading its amount is not on this channel, and neither is one whose amount decoded and then found no claim, service line, coverage or remittance open to attach the row to. An 820 RMR is not on it either, for its own reason: that row is dropped on open-item IDENTITY, RMR-01 and RMR-02 both empty, before the amount is read at all, so an RMR that states an open item and no amount keeps its row with amountPaid undefined while one that states an amount and no open item is dropped whole. That second case is a separate loss, and so is an 837 AMT that decoded while a Loop 2430 adjudication was open; `X12_STATED_AMOUNT_DISCARDED` reports both, and this code reports neither. The two can never name the same segment, because this one requires an amount element that decoded no value and that one requires the opposite. The verbatim segments are preserved on the transaction set; read them there before concluding the document stated no such amount.",
|
|
@@ -404,6 +408,13 @@ function unknown837Variant(position) {
|
|
|
404
408
|
position
|
|
405
409
|
};
|
|
406
410
|
}
|
|
411
|
+
function ambiguous837Variant(position) {
|
|
412
|
+
return {
|
|
413
|
+
code: WARNING_CODES.X12_837_AMBIGUOUS_VARIANT,
|
|
414
|
+
message: WARNING_MESSAGES.X12_837_AMBIGUOUS_VARIANT,
|
|
415
|
+
position
|
|
416
|
+
};
|
|
417
|
+
}
|
|
407
418
|
function serviceLineNotDecoded(position) {
|
|
408
419
|
return {
|
|
409
420
|
code: WARNING_CODES.X12_837_SERVICE_LINE_NOT_DECODED,
|
|
@@ -425,6 +436,13 @@ function serviceSegmentWithoutLx(position) {
|
|
|
425
436
|
position
|
|
426
437
|
};
|
|
427
438
|
}
|
|
439
|
+
function serviceSegmentRepeated(position) {
|
|
440
|
+
return {
|
|
441
|
+
code: WARNING_CODES.X12_837_SERVICE_SEGMENT_REPEATED,
|
|
442
|
+
message: WARNING_MESSAGES.X12_837_SERVICE_SEGMENT_REPEATED,
|
|
443
|
+
position
|
|
444
|
+
};
|
|
445
|
+
}
|
|
428
446
|
function entitySegmentDiscardedAfterLx(position) {
|
|
429
447
|
return {
|
|
430
448
|
code: WARNING_CODES.X12_837_ENTITY_SEGMENT_DISCARDED_AFTER_LX,
|
|
@@ -1077,7 +1095,10 @@ function splitSegments(text, start, delimiters) {
|
|
|
1077
1095
|
return { segments, endIndex: lastEnd };
|
|
1078
1096
|
}
|
|
1079
1097
|
function splitElements(segment, delimiters) {
|
|
1080
|
-
|
|
1098
|
+
if (delimiters.element === RELEASE_CHAR) {
|
|
1099
|
+
return Object.freeze(segment.split(delimiters.element));
|
|
1100
|
+
}
|
|
1101
|
+
return Object.freeze(splitWithRelease(segment, delimiters.element));
|
|
1081
1102
|
}
|
|
1082
1103
|
function el(elements, index) {
|
|
1083
1104
|
return elements[index] ?? "";
|
|
@@ -3321,9 +3342,20 @@ function statesAnAddress(address) {
|
|
|
3321
3342
|
|
|
3322
3343
|
// src/transactions/claim/get-837.ts
|
|
3323
3344
|
var VARIANT_BY_ICR = wireLookup({
|
|
3345
|
+
// Health Care Claim: Professional (837).
|
|
3346
|
+
"005010X222": "P",
|
|
3347
|
+
"005010X222A1": "P",
|
|
3324
3348
|
"005010X222A2": "P",
|
|
3349
|
+
// Health Care Claim: Institutional (837).
|
|
3350
|
+
"005010X223": "I",
|
|
3351
|
+
"005010X223A1": "I",
|
|
3352
|
+
"005010X223A2": "I",
|
|
3325
3353
|
"005010X223A3": "I",
|
|
3326
|
-
|
|
3354
|
+
// Health Care Claim: Dental (837).
|
|
3355
|
+
"005010X224": "D",
|
|
3356
|
+
"005010X224A1": "D",
|
|
3357
|
+
"005010X224A2": "D",
|
|
3358
|
+
"005010X224A3": "D"
|
|
3327
3359
|
});
|
|
3328
3360
|
var VARIANT_BY_SV_SEGMENT = wireLookup({
|
|
3329
3361
|
SV1: "P",
|
|
@@ -3359,16 +3391,24 @@ function get837Claims(delimiters, tx, opts) {
|
|
|
3359
3391
|
const explicitType = opts?.type;
|
|
3360
3392
|
const variantFromIcr = implementationConventionReference !== void 0 && implementationConventionReference !== "" ? VARIANT_BY_ICR[implementationConventionReference] : void 0;
|
|
3361
3393
|
let variantFromSegment;
|
|
3362
|
-
|
|
3363
|
-
|
|
3364
|
-
|
|
3365
|
-
|
|
3366
|
-
|
|
3394
|
+
let serviceSegmentVariantsConflict = false;
|
|
3395
|
+
if (explicitType === void 0 && variantFromIcr === void 0) {
|
|
3396
|
+
for (const seg of body) {
|
|
3397
|
+
const fromSv = VARIANT_BY_SV_SEGMENT[seg.id];
|
|
3398
|
+
if (fromSv === void 0) continue;
|
|
3399
|
+
if (variantFromSegment === void 0) {
|
|
3400
|
+
variantFromSegment = fromSv;
|
|
3401
|
+
} else if (fromSv !== variantFromSegment) {
|
|
3402
|
+
serviceSegmentVariantsConflict = true;
|
|
3403
|
+
break;
|
|
3404
|
+
}
|
|
3367
3405
|
}
|
|
3368
3406
|
}
|
|
3369
3407
|
const variant = explicitType ?? variantFromIcr ?? variantFromSegment ?? "unknown";
|
|
3370
3408
|
if (variant === "unknown") {
|
|
3371
3409
|
warnings.push(unknown837Variant({ segmentIndex: 0, transactionIndex: 0 }));
|
|
3410
|
+
} else if (serviceSegmentVariantsConflict) {
|
|
3411
|
+
warnings.push(ambiguous837Variant({ segmentIndex: 0, transactionIndex: 0 }));
|
|
3372
3412
|
}
|
|
3373
3413
|
const hierarchies = [];
|
|
3374
3414
|
const hlIndex = /* @__PURE__ */ new Map();
|
|
@@ -3417,6 +3457,10 @@ function get837Claims(delimiters, tx, opts) {
|
|
|
3417
3457
|
if (droppedLineReported) return;
|
|
3418
3458
|
warnings.push(serviceSegmentWithoutLx(position));
|
|
3419
3459
|
};
|
|
3460
|
+
const noteServiceSegment = (acc, position) => {
|
|
3461
|
+
if (acc.serviceSegmentSeen) warnings.push(serviceSegmentRepeated(position));
|
|
3462
|
+
acc.serviceSegmentSeen = true;
|
|
3463
|
+
};
|
|
3420
3464
|
const reportDiscardedEntitySegment = (position) => {
|
|
3421
3465
|
if (!entityLoopClosedByStrayLx) return;
|
|
3422
3466
|
warnings.push(entitySegmentDiscardedAfterLx(position));
|
|
@@ -3759,19 +3803,41 @@ function get837Claims(delimiters, tx, opts) {
|
|
|
3759
3803
|
// before the walk and scans every SVx in the body: an orphan segment
|
|
3760
3804
|
// is eligible for that fallback like any other, which is pre-existing
|
|
3761
3805
|
// and disclosed in KNOWN-LIMITATIONS.md rather than changed here.
|
|
3806
|
+
//
|
|
3807
|
+
// A SECOND service segment inside an already-open Loop 2400 is the
|
|
3808
|
+
// other silence on this segment, and it is a worse one: the line IS
|
|
3809
|
+
// open, so the repeat decodes, and every decoder writes all of the
|
|
3810
|
+
// slots its kind writes. `SV1*HC:99213*8500*…` followed by
|
|
3811
|
+
// `SV1*HC:99999*12*…` left ONE line reading `charge` 12 and
|
|
3812
|
+
// `procedureCode` 99999 through `0.0.13`, with `warnings: []` - money
|
|
3813
|
+
// and a CPT code replaced on the model, on no channel at all.
|
|
3814
|
+
// `noteServiceSegment` reports that, at the repeat itself, and changes
|
|
3815
|
+
// NOTHING about which segment wins.
|
|
3762
3816
|
case "SV1": {
|
|
3763
|
-
if (currentServiceLine
|
|
3764
|
-
|
|
3817
|
+
if (currentServiceLine === void 0) {
|
|
3818
|
+
reportOrphanServiceSegment(position);
|
|
3819
|
+
break;
|
|
3820
|
+
}
|
|
3821
|
+
noteServiceSegment(currentServiceLine, position);
|
|
3822
|
+
decodeSv1(currentServiceLine, seg, delimiters, sink);
|
|
3765
3823
|
break;
|
|
3766
3824
|
}
|
|
3767
3825
|
case "SV2": {
|
|
3768
|
-
if (currentServiceLine
|
|
3769
|
-
|
|
3826
|
+
if (currentServiceLine === void 0) {
|
|
3827
|
+
reportOrphanServiceSegment(position);
|
|
3828
|
+
break;
|
|
3829
|
+
}
|
|
3830
|
+
noteServiceSegment(currentServiceLine, position);
|
|
3831
|
+
decodeSv2(currentServiceLine, seg, delimiters, sink);
|
|
3770
3832
|
break;
|
|
3771
3833
|
}
|
|
3772
3834
|
case "SV3": {
|
|
3773
|
-
if (currentServiceLine
|
|
3774
|
-
|
|
3835
|
+
if (currentServiceLine === void 0) {
|
|
3836
|
+
reportOrphanServiceSegment(position);
|
|
3837
|
+
break;
|
|
3838
|
+
}
|
|
3839
|
+
noteServiceSegment(currentServiceLine, position);
|
|
3840
|
+
decodeSv3(currentServiceLine, seg, delimiters, sink);
|
|
3775
3841
|
break;
|
|
3776
3842
|
}
|
|
3777
3843
|
case "TOO": {
|
|
@@ -4078,6 +4144,7 @@ function openServiceLine2(seg, delimiters, variant, position) {
|
|
|
4078
4144
|
lineNumber,
|
|
4079
4145
|
position,
|
|
4080
4146
|
serviceSegmentDecoded: false,
|
|
4147
|
+
serviceSegmentSeen: false,
|
|
4081
4148
|
charge: void 0,
|
|
4082
4149
|
units: void 0,
|
|
4083
4150
|
unitOfMeasure: void 0,
|
|
@@ -4503,6 +4570,29 @@ var VERSION_BY_VARIANT = {
|
|
|
4503
4570
|
I: "005010X223A3",
|
|
4504
4571
|
D: "005010X224A2"
|
|
4505
4572
|
};
|
|
4573
|
+
function resolveVersionRelease(variant, reference, esc) {
|
|
4574
|
+
if (reference === void 0) return VERSION_BY_VARIANT[variant];
|
|
4575
|
+
if (reference === "") {
|
|
4576
|
+
throw new Claim837BuildError(
|
|
4577
|
+
CLAIM_837_BUILD_ERROR_CODES.X12_837_BUILD_INVALID_SPEC,
|
|
4578
|
+
"build837: envelope.implementationConventionReference is empty. ST-03 and GS-08 are required elements and a trailing empty element is not emitted, so an empty reference would remove them rather than send them empty. Omit the field to take the builder's default."
|
|
4579
|
+
);
|
|
4580
|
+
}
|
|
4581
|
+
if (esc(reference) !== reference) {
|
|
4582
|
+
throw new Claim837BuildError(
|
|
4583
|
+
CLAIM_837_BUILD_ERROR_CODES.X12_837_BUILD_INVALID_SPEC,
|
|
4584
|
+
"build837: envelope.implementationConventionReference carries an active delimiter or the release character. Escaping does not make it safe here: the ST and GS segments are read by a splitter that is not release-aware, so a released delimiter still splits the segment and the declaration silently becomes two elements. State a reference that carries neither, or choose different delimiters."
|
|
4585
|
+
);
|
|
4586
|
+
}
|
|
4587
|
+
const named = Object.hasOwn(VARIANT_BY_ICR, reference) ? VARIANT_BY_ICR[reference] : void 0;
|
|
4588
|
+
if (named !== void 0 && named !== variant) {
|
|
4589
|
+
throw new Claim837BuildError(
|
|
4590
|
+
CLAIM_837_BUILD_ERROR_CODES.X12_837_BUILD_INVALID_SPEC,
|
|
4591
|
+
`build837: envelope.implementationConventionReference names an implementation guide this library reads as a DIFFERENT 837 variant, but this is build837${variant}. The emitted file would declare one variant and carry another's service segments, and this library's own reader would then decode none of its service lines. State a reference for the ${variant} 837, or build with the entry point that matches the reference.`
|
|
4592
|
+
);
|
|
4593
|
+
}
|
|
4594
|
+
return reference;
|
|
4595
|
+
}
|
|
4506
4596
|
var X12_837_FUNCTIONAL_ID = "HC";
|
|
4507
4597
|
var X12_AGENCY_CODE2 = "X";
|
|
4508
4598
|
var HL_LEVEL = { BILLING: "20", SUBSCRIBER: "22", PATIENT: "23" };
|
|
@@ -4517,7 +4607,6 @@ function build837D(spec) {
|
|
|
4517
4607
|
}
|
|
4518
4608
|
function buildClaim837(variant, spec) {
|
|
4519
4609
|
const { envelope } = spec;
|
|
4520
|
-
const versionRelease = VERSION_BY_VARIANT[variant];
|
|
4521
4610
|
enforceStructuralSpec2(variant, spec);
|
|
4522
4611
|
const elementSeparator = envelope.elementSeparator ?? "*";
|
|
4523
4612
|
const repetitionSeparator = envelope.repetitionSeparator ?? "^";
|
|
@@ -4543,6 +4632,11 @@ function buildClaim837(variant, spec) {
|
|
|
4543
4632
|
return escaped.slice(0, end).join(componentSeparator);
|
|
4544
4633
|
};
|
|
4545
4634
|
const ctx = { seg, esc, comp };
|
|
4635
|
+
const versionRelease = resolveVersionRelease(
|
|
4636
|
+
variant,
|
|
4637
|
+
envelope.implementationConventionReference,
|
|
4638
|
+
esc
|
|
4639
|
+
);
|
|
4546
4640
|
const senderQualifier = envelope.senderQualifier ?? "ZZ";
|
|
4547
4641
|
const receiverQualifier = envelope.receiverQualifier ?? "ZZ";
|
|
4548
4642
|
const usageIndicator = envelope.usageIndicator ?? "P";
|
|
@@ -9667,18 +9761,27 @@ function expandYY8(yymmdd) {
|
|
|
9667
9761
|
// src/transactions/ack/build-ta1.ts
|
|
9668
9762
|
function buildTA1(spec, options = {}) {
|
|
9669
9763
|
enforceAcceptIsClean2(spec);
|
|
9670
|
-
const
|
|
9764
|
+
const delimiters = {
|
|
9765
|
+
element: options.elementSeparator ?? "*",
|
|
9766
|
+
repetition: options.repetitionSeparator ?? "^",
|
|
9767
|
+
component: options.componentSeparator ?? ":",
|
|
9768
|
+
segment: options.segmentTerminator ?? "~"
|
|
9769
|
+
};
|
|
9770
|
+
const esc = makeCallerEscaper(delimiters, "buildTA1", refuseSpec9);
|
|
9671
9771
|
const elements = Object.freeze([
|
|
9672
9772
|
"TA1",
|
|
9673
|
-
spec.interchangeControlNumber,
|
|
9674
|
-
spec.interchangeDate,
|
|
9675
|
-
spec.interchangeTime,
|
|
9676
|
-
spec.ackCode,
|
|
9677
|
-
spec.noteCode
|
|
9773
|
+
esc(spec.interchangeControlNumber),
|
|
9774
|
+
esc(spec.interchangeDate),
|
|
9775
|
+
esc(spec.interchangeTime),
|
|
9776
|
+
esc(spec.ackCode),
|
|
9777
|
+
esc(spec.noteCode)
|
|
9678
9778
|
]);
|
|
9679
|
-
const raw = elements.join(
|
|
9779
|
+
const raw = elements.join(delimiters.element);
|
|
9680
9780
|
return Object.freeze({ raw, elements });
|
|
9681
9781
|
}
|
|
9782
|
+
function refuseSpec9(message) {
|
|
9783
|
+
throw new AckBuildError(ACK_BUILD_ERROR_CODES.X12_ACK_INVALID_SPEC, message);
|
|
9784
|
+
}
|
|
9682
9785
|
function enforceAcceptIsClean2(spec) {
|
|
9683
9786
|
if (spec.ackCode === TA1_ACK_CODES.A && spec.noteCode !== "000") {
|
|
9684
9787
|
throw new AckBuildError(
|
|
@@ -9867,7 +9970,7 @@ var X12BuildError = class extends Error {
|
|
|
9867
9970
|
};
|
|
9868
9971
|
|
|
9869
9972
|
// src/builder/build-interchange.ts
|
|
9870
|
-
function
|
|
9973
|
+
function refuseSpec10(message) {
|
|
9871
9974
|
throw new X12BuildError(X12_BUILD_ERROR_CODES.X12_BUILD_INVALID_SPEC, message);
|
|
9872
9975
|
}
|
|
9873
9976
|
function buildInterchange(spec) {
|
|
@@ -9881,7 +9984,7 @@ function buildInterchange(spec) {
|
|
|
9881
9984
|
component: componentSeparator,
|
|
9882
9985
|
segment: segmentTerminator
|
|
9883
9986
|
};
|
|
9884
|
-
const esc = makeCallerEscaper(delimiters, "buildInterchange",
|
|
9987
|
+
const esc = makeCallerEscaper(delimiters, "buildInterchange", refuseSpec10);
|
|
9885
9988
|
const senderQualifier = spec.senderQualifier ?? "ZZ";
|
|
9886
9989
|
const receiverQualifier = spec.receiverQualifier ?? "ZZ";
|
|
9887
9990
|
const usageIndicator = spec.usageIndicator ?? "P";
|
|
@@ -9995,7 +10098,7 @@ function buildTransaction(tx, esc, elementSeparator, segmentTerminator) {
|
|
|
9995
10098
|
return st + bodySegments + se;
|
|
9996
10099
|
}
|
|
9997
10100
|
function joinSeg2(parts, elementSeparator, segmentTerminator) {
|
|
9998
|
-
requireCallerSegment(parts, "buildInterchange",
|
|
10101
|
+
requireCallerSegment(parts, "buildInterchange", refuseSpec10);
|
|
9999
10102
|
return parts.join(elementSeparator) + segmentTerminator;
|
|
10000
10103
|
}
|
|
10001
10104
|
function pad9(value, width) {
|
|
@@ -10304,8 +10407,8 @@ var profiles = Object.freeze({
|
|
|
10304
10407
|
});
|
|
10305
10408
|
|
|
10306
10409
|
// src/index.ts
|
|
10307
|
-
var VERSION = "0.0.
|
|
10410
|
+
var VERSION = "0.0.15";
|
|
10308
10411
|
|
|
10309
|
-
export { ACK_BUILD_ERROR_CODES, ALL_WARNING_MESSAGES, AUTH_278_BUILD_ERROR_CODES, AUTH_278_LOOP_2000A, AUTH_278_LOOP_2000B, AUTH_278_LOOP_2000C, AUTH_278_LOOP_2000D, AUTH_278_LOOP_2000E, AUTH_278_LOOP_2000F, AckBuildError, BALANCE_INVARIANTS, BUILD_REFUSAL_VALUE_MAX_LENGTH, BUILD_REFUSAL_VALUE_MAX_RENDERED, CARC, CLAIM_837D_LOOP_2000A, CLAIM_837D_LOOP_2300, CLAIM_837D_LOOP_2400, CLAIM_837I_LOOP_2000A, CLAIM_837I_LOOP_2300, CLAIM_837I_LOOP_2400, CLAIM_837P_LOOP_2000A, CLAIM_837P_LOOP_2300, CLAIM_837P_LOOP_2400, CLAIM_837P_LOOP_2410, CLAIM_837_BUILD_ERROR_CODES, CLAIM_837_LOOP_1000A, CLAIM_837_LOOP_1000B, CLAIM_837_LOOP_2010AA, CLAIM_837_LOOP_2010BA, CLAIM_837_LOOP_2010BB, CLAIM_837_LOOP_2010CA, CLAIM_837_LOOP_2430, CLAIM_ADJUSTMENT_GROUP_CODES, CLAIM_STATUS_277_BUILD_ERROR_CODES, CLAIM_STATUS_CATEGORY_CODES, CLAIM_STATUS_CODES, CLP_STATUS, CONTROL_NUMBER_PAIRS, Claim837BuildError, ClaimStatus277BuildError, DELIMITER_POSITIONS, ELIGIBILITY_271_BUILD_ERROR_CODES, ELIGIBILITY_271_LOOP_2000A, ELIGIBILITY_271_LOOP_2000B, ELIGIBILITY_271_LOOP_2000C, ELIGIBILITY_271_LOOP_2000D, ELIGIBILITY_271_LOOP_2100C, ELIGIBILITY_271_LOOP_2100D, ELIGIBILITY_271_LOOP_2110, ENROLLMENT_834_BUILD_ERROR_CODES, ENROLLMENT_834_LOOP_1000A, ENROLLMENT_834_LOOP_1000B, ENROLLMENT_834_LOOP_2000, ENROLLMENT_834_LOOP_2100A, ENROLLMENT_834_LOOP_2300, ENROLLMENT_834_LOOP_2320, Eligibility271BuildError, Enrollment834BuildError, FATAL_CODES, HI_QUALIFIERS, HL_LEVEL_CODES, IK3_SYNTAX_ERROR_CODES, IK4_SYNTAX_ERROR_CODES, ISA_MIN_LENGTH, LoopSpecDefinitionError, MAINTENANCE_TYPE_CODES, NM1_QUALIFIERS, NON_SPEC_SEGMENT_ID, PREMIUM_820_BUILD_ERROR_CODES, PREMIUM_820_LOOP_1000A, PREMIUM_820_LOOP_1000B, PREMIUM_820_LOOP_2000A, PREMIUM_820_LOOP_2100A, PREMIUM_820_LOOP_2300A, PREMIUM_820_LOOP_2310A, Premium820BuildError, RARC, RELEASE_CHAR, REMIT_835_BUILD_ERROR_CODES, REMIT_835_LOOP_1000A, REMIT_835_LOOP_1000B, REMIT_835_LOOP_2000, REMIT_835_LOOP_2100, REMIT_835_LOOP_2110, REQUIRED_LOOPS, Remit835BuildError, SERVICE_TYPE_CODES, STATUS_277_LOOP_2000A, STATUS_277_LOOP_2000B, STATUS_277_LOOP_2000C, STATUS_277_LOOP_2000D, STATUS_277_LOOP_2000E, STATUS_277_LOOP_2200, STATUS_277_LOOP_2220, ServicesReview278BuildError, TA1_ACK_CODES, TA1_NOTE_CODES, UNEXPECTED_SEGMENT_CONTEXTS, VERSION, WARNING_CODES, X12BuildError, X12Decimal, X12ParseError, X12ProfileError, X12_ACK_DISPOSITION_CODES, X12_BUILD_ERROR_CODES, amountRowDropped, balanceNotEvaluable, build271, build277, build277CA, build278Request, build278Response, build820, build834, build835, build837D, build837I, build837P, build999, buildInterchange, buildTA1, checkClaimBalance, checkRemitTotalBalance, checkServiceLineBalance, collectElementValues, componentOptional, controlNumberMismatch, danglingReleaseChar, decodeSegment, defineLoopSpec, defineProfile, detectDelimiters, elementDecimal, elementDecimalOrZero, elementOptional, elementValue, entitySegmentDiscardedAfterLx, escapeRelease, get271Eligibility, get277CADisposition, get277Status, get278Request, get278Response, get820Payments, get834Enrollments, get834Header, get835, get837Claims, getAllSegmentValues, getDefaultProfile, getSegmentValue, groupCountMismatch, hlParentLevelInvalid, hlParentMismatch, isAcceptDisposition, isClaimAdjustmentGroupCode, isDiagnosisQualifier, isProcedureQualifier, lookupCarc, lookupClaimStatus, lookupClaimStatusCategory, lookupClpStatus, lookupMaintenanceType, lookupRarc, lookupServiceType, missingGe, missingIea, missingRequiredLoop, missingSe, parse999, parseTA1, parseX12, partitionWarnings, payToAddressRepeated, pre005010, profiles, readElementDecimal, remitBalanceMismatch, renderCallerValue, resolveHiQualifier, segmentCountMismatch, serializeX12, serviceLineDropped, serviceLineNotDecoded, serviceSegmentWithoutLx, setDefaultProfile, statedAmountDiscarded, trailingGarbage, transactionCountMismatch, unescapeRelease, unexpectedSegment, unknown837Variant, unknownCarc, unknownClaimStatus, unknownClaimStatusCategory, unknownHiQualifier, unknownMaintenanceType, unknownRarc, unparseableDecimal };
|
|
10412
|
+
export { ACK_BUILD_ERROR_CODES, ALL_WARNING_MESSAGES, AUTH_278_BUILD_ERROR_CODES, AUTH_278_LOOP_2000A, AUTH_278_LOOP_2000B, AUTH_278_LOOP_2000C, AUTH_278_LOOP_2000D, AUTH_278_LOOP_2000E, AUTH_278_LOOP_2000F, AckBuildError, BALANCE_INVARIANTS, BUILD_REFUSAL_VALUE_MAX_LENGTH, BUILD_REFUSAL_VALUE_MAX_RENDERED, CARC, CLAIM_837D_LOOP_2000A, CLAIM_837D_LOOP_2300, CLAIM_837D_LOOP_2400, CLAIM_837I_LOOP_2000A, CLAIM_837I_LOOP_2300, CLAIM_837I_LOOP_2400, CLAIM_837P_LOOP_2000A, CLAIM_837P_LOOP_2300, CLAIM_837P_LOOP_2400, CLAIM_837P_LOOP_2410, CLAIM_837_BUILD_ERROR_CODES, CLAIM_837_LOOP_1000A, CLAIM_837_LOOP_1000B, CLAIM_837_LOOP_2010AA, CLAIM_837_LOOP_2010BA, CLAIM_837_LOOP_2010BB, CLAIM_837_LOOP_2010CA, CLAIM_837_LOOP_2430, CLAIM_ADJUSTMENT_GROUP_CODES, CLAIM_STATUS_277_BUILD_ERROR_CODES, CLAIM_STATUS_CATEGORY_CODES, CLAIM_STATUS_CODES, CLP_STATUS, CONTROL_NUMBER_PAIRS, Claim837BuildError, ClaimStatus277BuildError, DELIMITER_POSITIONS, ELIGIBILITY_271_BUILD_ERROR_CODES, ELIGIBILITY_271_LOOP_2000A, ELIGIBILITY_271_LOOP_2000B, ELIGIBILITY_271_LOOP_2000C, ELIGIBILITY_271_LOOP_2000D, ELIGIBILITY_271_LOOP_2100C, ELIGIBILITY_271_LOOP_2100D, ELIGIBILITY_271_LOOP_2110, ENROLLMENT_834_BUILD_ERROR_CODES, ENROLLMENT_834_LOOP_1000A, ENROLLMENT_834_LOOP_1000B, ENROLLMENT_834_LOOP_2000, ENROLLMENT_834_LOOP_2100A, ENROLLMENT_834_LOOP_2300, ENROLLMENT_834_LOOP_2320, Eligibility271BuildError, Enrollment834BuildError, FATAL_CODES, HI_QUALIFIERS, HL_LEVEL_CODES, IK3_SYNTAX_ERROR_CODES, IK4_SYNTAX_ERROR_CODES, ISA_MIN_LENGTH, LoopSpecDefinitionError, MAINTENANCE_TYPE_CODES, NM1_QUALIFIERS, NON_SPEC_SEGMENT_ID, PREMIUM_820_BUILD_ERROR_CODES, PREMIUM_820_LOOP_1000A, PREMIUM_820_LOOP_1000B, PREMIUM_820_LOOP_2000A, PREMIUM_820_LOOP_2100A, PREMIUM_820_LOOP_2300A, PREMIUM_820_LOOP_2310A, Premium820BuildError, RARC, RELEASE_CHAR, REMIT_835_BUILD_ERROR_CODES, REMIT_835_LOOP_1000A, REMIT_835_LOOP_1000B, REMIT_835_LOOP_2000, REMIT_835_LOOP_2100, REMIT_835_LOOP_2110, REQUIRED_LOOPS, Remit835BuildError, SERVICE_TYPE_CODES, STATUS_277_LOOP_2000A, STATUS_277_LOOP_2000B, STATUS_277_LOOP_2000C, STATUS_277_LOOP_2000D, STATUS_277_LOOP_2000E, STATUS_277_LOOP_2200, STATUS_277_LOOP_2220, ServicesReview278BuildError, TA1_ACK_CODES, TA1_NOTE_CODES, UNEXPECTED_SEGMENT_CONTEXTS, VERSION, WARNING_CODES, X12BuildError, X12Decimal, X12ParseError, X12ProfileError, X12_ACK_DISPOSITION_CODES, X12_BUILD_ERROR_CODES, ambiguous837Variant, amountRowDropped, balanceNotEvaluable, build271, build277, build277CA, build278Request, build278Response, build820, build834, build835, build837D, build837I, build837P, build999, buildInterchange, buildTA1, checkClaimBalance, checkRemitTotalBalance, checkServiceLineBalance, collectElementValues, componentOptional, controlNumberMismatch, danglingReleaseChar, decodeSegment, defineLoopSpec, defineProfile, detectDelimiters, elementDecimal, elementDecimalOrZero, elementOptional, elementValue, entitySegmentDiscardedAfterLx, escapeRelease, get271Eligibility, get277CADisposition, get277Status, get278Request, get278Response, get820Payments, get834Enrollments, get834Header, get835, get837Claims, getAllSegmentValues, getDefaultProfile, getSegmentValue, groupCountMismatch, hlParentLevelInvalid, hlParentMismatch, isAcceptDisposition, isClaimAdjustmentGroupCode, isDiagnosisQualifier, isProcedureQualifier, lookupCarc, lookupClaimStatus, lookupClaimStatusCategory, lookupClpStatus, lookupMaintenanceType, lookupRarc, lookupServiceType, missingGe, missingIea, missingRequiredLoop, missingSe, parse999, parseTA1, parseX12, partitionWarnings, payToAddressRepeated, pre005010, profiles, readElementDecimal, remitBalanceMismatch, renderCallerValue, resolveHiQualifier, segmentCountMismatch, serializeX12, serviceLineDropped, serviceLineNotDecoded, serviceSegmentRepeated, serviceSegmentWithoutLx, setDefaultProfile, statedAmountDiscarded, trailingGarbage, transactionCountMismatch, unescapeRelease, unexpectedSegment, unknown837Variant, unknownCarc, unknownClaimStatus, unknownClaimStatusCategory, unknownHiQualifier, unknownMaintenanceType, unknownRarc, unparseableDecimal };
|
|
10310
10413
|
//# sourceMappingURL=index.mjs.map
|
|
10311
10414
|
//# sourceMappingURL=index.mjs.map
|