eddy 0.1.0 → 0.3.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.
- checksums.yaml +4 -4
- data/.rubocop.yml +103 -37
- data/.solargraph.yml +4 -0
- data/.vscode/settings.json +17 -0
- data/.yardopts +2 -2
- data/CHANGELOG.md +50 -0
- data/Gemfile.lock +21 -7
- data/README.md +32 -3
- data/Rakefile +1 -10
- data/data/004010/code-lists/100.tsv +164 -0
- data/data/004010/code-lists/156.tsv +52 -0
- data/data/004010/code-lists/26.tsv +499 -0
- data/data/004010/code-lists/etc/100-fancy-definitions.tsv +164 -0
- data/data/004010/code-lists/etc/100-with-funds-codes.tsv +180 -0
- data/data/004010/code-lists/etc/26-alpha2.tsv +250 -0
- data/data/004010/code-lists/etc/26-alpha3.tsv +250 -0
- data/data/004010/elements-short.tsv +1405 -0
- data/data/004010/elements.tsv +3 -3
- data/data/004010/segments.tsv +1009 -1003
- data/data/004010/segments/ack.segment.yml +15 -0
- data/data/004010/segments/bak.segment.yml +9 -0
- data/data/004010/segments/beg.segment.yml +17 -0
- data/data/004010/segments/big.segment.yml +10 -0
- data/data/004010/segments/bsn.segment.yml +10 -0
- data/data/004010/segments/cad.segment.yml +14 -0
- data/data/004010/segments/ctp.segment.yml +19 -0
- data/data/004010/segments/ctt.segment.yml +13 -0
- data/data/004010/segments/dtm.segment.yml +7 -0
- data/data/004010/segments/envelope/ge.segment.yml +7 -0
- data/data/004010/segments/envelope/gs.segment.yml +13 -0
- data/data/004010/segments/envelope/iea.segment.yml +8 -0
- data/data/004010/segments/envelope/isa.segment.yml +22 -0
- data/data/004010/segments/envelope/se.segment.yml +7 -0
- data/data/004010/segments/envelope/st.segment.yml +12 -0
- data/data/004010/segments/hl.segment.yml +9 -0
- data/data/004010/segments/it1.segment.yml +20 -0
- data/data/004010/segments/lin.segment.yml +10 -0
- data/data/004010/segments/loop/hl.segment.yml +8 -0
- data/data/004010/segments/man.segment.yml +7 -0
- data/data/004010/segments/n1.segment.yml +9 -0
- data/data/004010/segments/n2.segment.yml +7 -0
- data/data/004010/segments/n3.segment.yml +6 -0
- data/data/004010/segments/n4.segment.yml +9 -0
- data/data/004010/segments/pid.segment.yml +10 -0
- data/data/004010/segments/po1.segment.yml +14 -0
- data/data/004010/segments/prf.segment.yml +9 -0
- data/data/004010/segments/ref.segment.yml +7 -0
- data/data/004010/segments/sac.segment.yml +20 -0
- data/data/004010/segments/sln.segment.yml +12 -0
- data/data/004010/segments/sn1.segment.yml +11 -0
- data/data/004010/segments/td1.segment.yml +13 -0
- data/data/004010/segments/td5.segment.yml +11 -0
- data/data/004010/segments/tds.segment.yml +10 -0
- data/data/schema/element_summary.json +60 -0
- data/data/schema/loop_summary.json +49 -0
- data/data/schema/segment_summary.json +66 -0
- data/data/schema/src/element_summary.schema.yml +73 -0
- data/data/schema/src/loop_summary.schema.yml +50 -0
- data/data/schema/src/segment_summary.schema.yml +59 -0
- data/data/schema/src/transaction_set_summary.schema.yml +27 -0
- data/data/schema/transaction_set_summary.json +33 -0
- data/data/sources.md +114 -145
- data/eddy.gemspec +6 -3
- data/exe/eddy +14 -0
- data/lib/definitions/elements/generated/1005.hierarchical_structure_code.rb +98 -0
- data/lib/definitions/elements/generated/1019.invoice_type_code.rb +40 -0
- data/lib/definitions/elements/generated/103.packaging_code.rb +29 -0
- data/lib/definitions/elements/generated/1166.contract_type_code.rb +87 -0
- data/lib/definitions/elements/generated/1232.purchase_category.rb +53 -0
- data/lib/definitions/elements/generated/127.reference_identification.rb +29 -0
- data/lib/definitions/elements/generated/128.reference_identification_qualifier.rb +1540 -0
- data/lib/definitions/elements/generated/1300.service_promotion_allowance_or_charge_code.rb +1090 -0
- data/lib/definitions/elements/generated/1301.agency_service_promotion_allowance_or_charge_code.rb +29 -0
- data/lib/definitions/elements/generated/133.routing_sequence_code.rb +60 -0
- data/lib/definitions/elements/generated/166.address_information.rb +29 -0
- data/lib/definitions/elements/generated/183.volume.rb +29 -0
- data/lib/definitions/elements/generated/187.weight_qualifier.rb +88 -0
- data/lib/definitions/elements/generated/19.city_name.rb +29 -0
- data/lib/definitions/elements/generated/206.equipment_initial.rb +29 -0
- data/lib/definitions/elements/generated/207.equipment_number.rb +29 -0
- data/lib/definitions/elements/generated/212.unit_price.rb +29 -0
- data/lib/definitions/elements/generated/22.commodity_code.rb +29 -0
- data/lib/definitions/elements/generated/23.commodity_code_qualifier.rb +60 -0
- data/lib/definitions/elements/generated/234.product_service_id.rb +29 -0
- data/lib/definitions/elements/generated/235.product_service_id_qualifier.rb +514 -0
- data/lib/definitions/elements/generated/236.price_identifier_code.rb +201 -0
- data/lib/definitions/elements/generated/248.allowance_or_charge_indicator.rb +44 -0
- data/lib/definitions/elements/generated/26.country_code.rb +535 -0
- data/lib/definitions/elements/generated/284.service_level_code.rb +103 -0
- data/lib/definitions/elements/generated/324.purchase_order_number.rb +29 -0
- data/lib/definitions/elements/generated/326.request_reference_number.rb +29 -0
- data/lib/definitions/elements/generated/327.change_order_sequence_number.rb +29 -0
- data/lib/definitions/elements/generated/328.release_number.rb +29 -0
- data/lib/definitions/elements/generated/330.quantity_ordered.rb +29 -0
- data/lib/definitions/elements/generated/347.hash_total.rb +29 -0
- data/lib/definitions/elements/generated/349.item_description_type.rb +40 -0
- data/lib/definitions/elements/generated/352.description.rb +29 -0
- data/lib/definitions/elements/generated/353.transaction_set_purpose_code.rb +102 -0
- data/lib/definitions/elements/generated/354.number_of_line_items.rb +30 -0
- data/lib/definitions/elements/generated/355.unit_or_basis_for_measurement_code.rb +831 -0
- data/lib/definitions/elements/generated/358.quantity_invoiced.rb +29 -0
- data/lib/definitions/elements/generated/367.contract_number.rb +29 -0
- data/lib/definitions/elements/generated/368.shipment_order_status_code.rb +139 -0
- data/lib/definitions/elements/generated/374.date_time_qualifier.rb +1149 -0
- data/lib/definitions/elements/generated/380.quantity.rb +29 -0
- data/lib/definitions/elements/generated/382.number_of_units_shipped.rb +29 -0
- data/lib/definitions/elements/generated/387.routing.rb +29 -0
- data/lib/definitions/elements/generated/396.shipment_identification.rb +29 -0
- data/lib/definitions/elements/generated/559.agency_qualifier_code.rb +213 -0
- data/lib/definitions/elements/generated/587.acknowledgment_type.rb +52 -0
- data/lib/definitions/elements/generated/610.amount.rb +30 -0
- data/lib/definitions/elements/generated/639.basis_of_unit_price_code.rb +128 -0
- data/lib/definitions/elements/generated/640.transaction_type_code.rb +483 -0
- data/lib/definitions/elements/generated/646.quantity_shipped_to_date.rb +29 -0
- data/lib/definitions/elements/generated/648.price_multiplier_qualifier.rb +43 -0
- data/lib/definitions/elements/generated/649.multiplier.rb +29 -0
- data/lib/definitions/elements/generated/66.identification_code_qualifier.rb +252 -0
- data/lib/definitions/elements/generated/662.relationship_code.rb +42 -0
- data/lib/definitions/elements/generated/668.line_item_status_code.rb +63 -0
- data/lib/definitions/elements/generated/67.identification_code.rb +29 -0
- data/lib/definitions/elements/generated/687.class_of_trade_code.rb +89 -0
- data/lib/definitions/elements/generated/750.product_process_characteristic_code.rb +254 -0
- data/lib/definitions/elements/generated/751.product_description_code.rb +29 -0
- data/lib/definitions/elements/generated/76.invoice_number.rb +29 -0
- data/lib/definitions/elements/generated/782.monetary_amount.rb +29 -0
- data/lib/definitions/elements/generated/786.security_level_code.rb +54 -0
- data/lib/definitions/elements/generated/79.lading_description.rb +29 -0
- data/lib/definitions/elements/generated/80.lading_quantity.rb +30 -0
- data/lib/definitions/elements/generated/87.marks_and_numbers.rb +29 -0
- data/lib/definitions/elements/generated/88.marks_and_numbers_qualifier.rb +57 -0
- data/lib/definitions/elements/generated/91.transportation_method_type_code.rb +108 -0
- data/lib/definitions/elements/generated/92.purchase_order_type_code.rb +106 -0
- data/lib/definitions/elements/generated/98.entity_identifier_code.rb +1349 -0
- data/lib/definitions/elements/manual/116.postal_code.rb +44 -0
- data/lib/definitions/elements/manual/124.application_receivers_code.rb +29 -0
- data/lib/definitions/elements/manual/140.standard_carrier_alpha_code.rb +211 -0
- data/lib/definitions/elements/manual/142.application_senders_code.rb +29 -0
- data/lib/definitions/elements/manual/143.transaction_set_identifier_code.rb +335 -0
- data/lib/definitions/elements/manual/156.state_or_province_code.rb +92 -0
- data/lib/definitions/elements/manual/28.group_control_number.rb +34 -0
- data/lib/definitions/elements/manual/329.transactional_set_control_number.rb +35 -0
- data/lib/definitions/elements/manual/337.time.rb +30 -0
- data/lib/definitions/elements/manual/350.assigned_identification.rb +33 -0
- data/lib/definitions/elements/manual/373.date.rb +30 -0
- data/lib/definitions/elements/manual/455.responsible_agency_code.rb +43 -0
- data/lib/definitions/elements/manual/479.functional_identifier_code.rb +271 -0
- data/lib/definitions/elements/manual/480.version_release_industry_identifier_code.rb +145 -0
- data/lib/definitions/elements/manual/784.length_of_binary_data.rb +30 -0
- data/lib/definitions/elements/manual/785.binary_data.rb +30 -0
- data/lib/definitions/elements/manual/96.number_of_included_segments.rb +30 -0
- data/lib/definitions/elements/manual/97.number_of_transaction_sets_included.rb +30 -0
- data/lib/definitions/elements/manual/hl/628.hierarchical_id_number.rb +29 -0
- data/lib/definitions/elements/manual/hl/734.hierarchical_parent_id_number.rb +29 -0
- data/lib/definitions/elements/manual/hl/735.hierarchical_level_code.rb +207 -0
- data/lib/definitions/elements/manual/hl/736.hierarchical_child_code.rb +39 -0
- data/lib/definitions/elements/manual/i/I01.authorization_information_qualifier.rb +48 -0
- data/lib/definitions/elements/manual/i/I02.authorization_information.rb +33 -0
- data/lib/definitions/elements/manual/i/I03.security_information_qualifier.rb +43 -0
- data/lib/definitions/elements/manual/i/I04.security_information.rb +33 -0
- data/lib/definitions/elements/manual/i/I05.interchange_id_qualifier.rb +75 -0
- data/lib/definitions/elements/manual/i/I06.interchange_sender_id.rb +29 -0
- data/lib/definitions/elements/manual/i/I07.interchange_receiver_id.rb +29 -0
- data/lib/definitions/elements/manual/i/I08.interchange_date.rb +35 -0
- data/lib/definitions/elements/manual/i/I09.interchange_time.rb +36 -0
- data/lib/definitions/elements/manual/i/I10.interchange_control_standards_identifier.rb +42 -0
- data/lib/definitions/elements/manual/i/I11.interchange_control_version_number.rb +55 -0
- data/lib/definitions/elements/manual/i/I12.interchange_control_number.rb +34 -0
- data/lib/definitions/elements/manual/i/I13.acknowledgment_requested.rb +43 -0
- data/lib/definitions/elements/manual/i/I14.usage_indicator.rb +40 -0
- data/lib/definitions/elements/manual/i/I15.component_element_separator.rb +36 -0
- data/lib/definitions/elements/manual/i/I16.number_of_included_functional_groups.rb +30 -0
- data/lib/definitions/elements/manual/misc/81.weight.rb +29 -0
- data/lib/definitions/elements/manual/misc/93.name.rb +29 -0
- data/lib/definitions/segments/generated/ack.rb +192 -0
- data/lib/definitions/segments/generated/bak.rb +90 -0
- data/lib/definitions/segments/generated/beg.rb +226 -0
- data/lib/definitions/segments/generated/big.rb +107 -0
- data/lib/definitions/segments/generated/bsn.rb +107 -0
- data/lib/definitions/segments/generated/cad.rb +175 -0
- data/lib/definitions/segments/generated/ctp.rb +158 -0
- data/lib/definitions/segments/generated/ctt.rb +141 -0
- data/lib/definitions/segments/generated/dtm.rb +56 -0
- data/lib/definitions/segments/generated/it1.rb +277 -0
- data/lib/definitions/segments/generated/lin.rb +107 -0
- data/lib/definitions/segments/generated/man.rb +56 -0
- data/lib/definitions/segments/generated/n1.rb +90 -0
- data/lib/definitions/segments/generated/n3.rb +39 -0
- data/lib/definitions/segments/generated/n4.rb +90 -0
- data/lib/definitions/segments/generated/pid.rb +107 -0
- data/lib/definitions/segments/generated/po1.rb +175 -0
- data/lib/definitions/segments/generated/prf.rb +90 -0
- data/lib/definitions/segments/generated/ref.rb +56 -0
- data/lib/definitions/segments/generated/sac.rb +107 -0
- data/lib/definitions/segments/generated/sln.rb +141 -0
- data/lib/definitions/segments/generated/sn1.rb +124 -0
- data/lib/definitions/segments/generated/td1.rb +158 -0
- data/lib/definitions/segments/generated/td5.rb +107 -0
- data/lib/definitions/segments/generated/tds.rb +39 -0
- data/lib/definitions/segments/manual/envelopes/ge.rb +53 -0
- data/lib/definitions/segments/manual/envelopes/gs.rb +163 -0
- data/lib/definitions/segments/manual/envelopes/iea.rb +53 -0
- data/lib/definitions/segments/manual/envelopes/isa.rb +295 -0
- data/lib/definitions/segments/manual/envelopes/se.rb +52 -0
- data/lib/definitions/segments/manual/envelopes/st.rb +52 -0
- data/lib/definitions/segments/manual/hl.rb +96 -0
- data/lib/definitions/segments/manual/n2.rb +52 -0
- data/lib/definitions/transaction_sets/manual/810/810.rb +143 -0
- data/lib/definitions/transaction_sets/manual/810/loops.rb +109 -0
- data/lib/definitions/transaction_sets/manual/850/850.rb +92 -0
- data/lib/definitions/transaction_sets/manual/850/loops.rb +58 -0
- data/lib/definitions/transaction_sets/manual/855/855.rb +83 -0
- data/lib/definitions/transaction_sets/manual/855/loops.rb +104 -0
- data/lib/definitions/transaction_sets/manual/856/856.rb +83 -0
- data/lib/definitions/transaction_sets/manual/856/loops.rb +155 -0
- data/lib/eddy.rb +29 -7
- data/lib/eddy/build/build.rb +47 -0
- data/lib/eddy/build/elements/element.rb +67 -0
- data/lib/eddy/build/elements/elements.rb +46 -0
- data/lib/eddy/build/elements/id.rb +55 -0
- data/lib/eddy/build/elements/n.rb +48 -0
- data/lib/eddy/build/loop_builder.rb +93 -0
- data/lib/eddy/build/segment_builder.rb +169 -0
- data/lib/eddy/build/transaction_set_builder.rb +218 -0
- data/lib/eddy/cli/cli.rb +39 -0
- data/lib/eddy/config.rb +51 -0
- data/lib/eddy/data.rb +50 -0
- data/lib/eddy/data/persistence/active_record.rb +10 -0
- data/lib/eddy/data/persistence/base.rb +47 -0
- data/lib/eddy/data/persistence/file.rb +50 -0
- data/lib/eddy/data/persistence/memory.rb +65 -0
- data/lib/eddy/data/store.rb +108 -0
- data/lib/eddy/errors.rb +112 -0
- data/lib/eddy/models/element.rb +14 -0
- data/lib/eddy/models/element/an.rb +55 -0
- data/lib/eddy/models/element/b.rb +53 -0
- data/lib/eddy/models/element/base.rb +116 -0
- data/lib/eddy/models/element/composite.rb +6 -0
- data/lib/eddy/models/element/dt.rb +100 -0
- data/lib/eddy/models/element/id.rb +58 -0
- data/lib/eddy/models/element/n.rb +94 -0
- data/lib/eddy/models/element/r.rb +84 -0
- data/lib/eddy/models/element/tm.rb +113 -0
- data/lib/eddy/models/loop.rb +74 -0
- data/lib/eddy/models/segment.rb +35 -0
- data/lib/eddy/models/transaction_set.rb +101 -0
- data/lib/eddy/parse.rb +58 -0
- data/lib/eddy/schema/element_summary.rb +123 -0
- data/lib/eddy/schema/loop_summary.rb +101 -0
- data/lib/eddy/schema/segment_summary.rb +116 -0
- data/lib/eddy/schema/transaction_set_summary.rb +96 -0
- data/lib/eddy/schema/validate.rb +41 -0
- data/lib/eddy/util.rb +16 -0
- data/lib/eddy/util/clean_folder.rb +14 -0
- data/lib/eddy/util/edi_data.rb +153 -0
- data/lib/eddy/util/new_number.rb +24 -0
- data/lib/eddy/util/normalize.rb +51 -0
- data/lib/eddy/util/paths.rb +19 -0
- data/lib/eddy/util/read.rb +38 -0
- data/lib/eddy/util/time.rb +56 -0
- data/lib/eddy/util/timestamp.rb +12 -0
- data/lib/eddy/util/trim.rb +29 -0
- data/lib/eddy/version.rb +1 -1
- data/lib/eddy/write/functional_group.rb +33 -0
- data/lib/eddy/write/interchange.rb +28 -0
- data/lib/eddy/write/simple_interchange.rb +57 -0
- data/lib/generators/eddy/initializer/initializer_generator.rb +17 -0
- data/lib/generators/eddy/initializer/templates/eddy.rb.erb +6 -0
- data/lib/generators/eddy/migration/migration_generator.rb +53 -0
- data/lib/generators/eddy/migration/templates/migration.rb.erb +35 -0
- data/tasks/build.rake +15 -0
- data/tasks/misc/gemspec.rake +12 -0
- data/tasks/misc/missing_lists.rake +240 -0
- data/tasks/misc/yaml2json.rake +20 -0
- data/todo.txt +16 -0
- metadata +297 -42
- data/data/004010/segments/ISA.tsv +0 -17
- data/data/schema.jsonc +0 -67
- data/lib/eddy/build/build_an.rb +0 -31
- data/lib/eddy/build/build_dt.rb +0 -46
- data/lib/eddy/build/build_elements.rb +0 -181
- data/lib/eddy/build/build_id.rb +0 -56
- data/lib/eddy/build/build_r_and_n.rb +0 -69
- data/lib/eddy/build/build_tm.rb +0 -52
- data/lib/eddy/build/segments.rb +0 -25
- data/lib/eddy/definitions/manual/elements/109.dt.pickup_date.rb +0 -20
- data/lib/eddy/definitions/manual/elements/111.tm.pickup_time.rb +0 -20
- data/lib/eddy/definitions/manual/elements/112.an.pier_name.rb +0 -19
- data/lib/eddy/definitions/manual/elements/785.b.binary_data.rb +0 -19
- data/lib/eddy/definitions/manual/elements/81.r.weight.rb +0 -19
- data/lib/eddy/definitions/manual/elements/86.n0.total_equipment.rb +0 -20
- data/lib/eddy/definitions/manual/elements/I02.authorization_information.rb +0 -20
- data/lib/eddy/definitions/manual/elements/I04.security_information.rb +0 -20
- data/lib/eddy/definitions/manual/elements/I08.interchange_date.rb +0 -20
- data/lib/eddy/definitions/manual/elements/I09.interchange_time.rb +0 -20
- data/lib/eddy/definitions/manual/elements/I15.component_element_separator.rb +0 -32
- data/lib/eddy/definitions/manual/segments/n1.rb +0 -14
- data/lib/eddy/element.rb +0 -14
- data/lib/eddy/element/an.rb +0 -36
- data/lib/eddy/element/b.rb +0 -9
- data/lib/eddy/element/base.rb +0 -37
- data/lib/eddy/element/dt.rb +0 -89
- data/lib/eddy/element/id.rb +0 -40
- data/lib/eddy/element/n.rb +0 -43
- data/lib/eddy/element/r.rb +0 -47
- data/lib/eddy/element/tm.rb +0 -108
- data/lib/eddy/error.rb +0 -14
- data/lib/eddy/helpers.rb +0 -31
- data/lib/eddy/segment.rb +0 -12
- data/lib/eddy/transaction_set.rb +0 -35
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
module Eddy
|
|
2
|
+
module Loop
|
|
3
|
+
# A repeated collection of Segments and/or other Loops.
|
|
4
|
+
#
|
|
5
|
+
# See:
|
|
6
|
+
#
|
|
7
|
+
# - [HL Loop Structure in TS 837 - X12 RFI](http://www.x12.org/rfis/HL%20Loop%20Structure%20in%20TS%20837.pdf)
|
|
8
|
+
# - [HL Segment Content - X12 RFI](http://www.x12.org/rfis/HL%20Segment%20Content.pdf)
|
|
9
|
+
class Base
|
|
10
|
+
|
|
11
|
+
# (Name) A unique string used to identify the Loop within its Transaction Set.
|
|
12
|
+
# @return [String]
|
|
13
|
+
attr_reader :loop_id
|
|
14
|
+
# Number of times a particular Loop may be repeated.
|
|
15
|
+
# @return [Integer]
|
|
16
|
+
attr_reader :repeat
|
|
17
|
+
# Defines if/how the Loop is required.
|
|
18
|
+
# @return [String]
|
|
19
|
+
attr_reader :req
|
|
20
|
+
# An array of Segments and/or other Loops.
|
|
21
|
+
# This is used as a template to populate `content`.
|
|
22
|
+
# @return [Array<Eddy::Segment, Eddy::Loop::Base>]
|
|
23
|
+
attr_reader :components
|
|
24
|
+
# @return [Eddy::Data::Store] Data passed down from a Transaction Set.
|
|
25
|
+
attr_reader :store
|
|
26
|
+
# An array of loop iterations.
|
|
27
|
+
# @return [Array<Array>]
|
|
28
|
+
attr_accessor :content
|
|
29
|
+
|
|
30
|
+
# All of a Loop's elements need to be declared in its constructor.
|
|
31
|
+
#
|
|
32
|
+
# @param store [Eddy::Data::Store]
|
|
33
|
+
# @param components [Array<Eddy::Loop, Eddy::Segment>]
|
|
34
|
+
# @return [void]
|
|
35
|
+
def initialize(store, *components)
|
|
36
|
+
@store = store
|
|
37
|
+
components.flatten!
|
|
38
|
+
@components = components || []
|
|
39
|
+
@content = []
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Return all contained Segments in a single, flattened array.
|
|
43
|
+
#
|
|
44
|
+
# @return [Array<Eddy::Segment>]
|
|
45
|
+
def all_contents()
|
|
46
|
+
contents = self.content.flatten.map do |c|
|
|
47
|
+
if c.is_a?(Eddy::Loop::Base)
|
|
48
|
+
c.all_contents()
|
|
49
|
+
elsif c.is_a?(Eddy::Segment)
|
|
50
|
+
# elsif c < Eddy::Segment
|
|
51
|
+
c
|
|
52
|
+
else
|
|
53
|
+
raise Eddy::Errors::RenderError
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
return contents.flatten
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# @param block [Block]
|
|
60
|
+
# @return [void]
|
|
61
|
+
def add_iteration(&block)
|
|
62
|
+
iteration = self.components.map { |c| c.new(self.store) }
|
|
63
|
+
if block_given?
|
|
64
|
+
yield(*iteration)
|
|
65
|
+
else
|
|
66
|
+
raise Eddy::Errors::Error, "No block given in loop iteration"
|
|
67
|
+
end
|
|
68
|
+
self.content << iteration
|
|
69
|
+
return nil
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
module Eddy
|
|
2
|
+
# Base class for EDI Segments.
|
|
3
|
+
class Segment
|
|
4
|
+
|
|
5
|
+
# An alphanumeric code unique to each Segment type.
|
|
6
|
+
# @return [String]
|
|
7
|
+
attr_reader :id
|
|
8
|
+
# Short name of the Segment.
|
|
9
|
+
# @return [String]
|
|
10
|
+
attr_reader :name
|
|
11
|
+
# @return [Array<Element>]
|
|
12
|
+
attr_accessor :elements
|
|
13
|
+
# @return [Eddy::Data::Store] Data passed down from a Transaction Set.
|
|
14
|
+
attr_accessor :store
|
|
15
|
+
|
|
16
|
+
# All of a Segment's elements need to be declared in its constructor.
|
|
17
|
+
#
|
|
18
|
+
# @param store [Eddy::Data::Store]
|
|
19
|
+
# @param elements [Eddy::Element::Base]
|
|
20
|
+
# @return [void]
|
|
21
|
+
def initialize(store, *elements)
|
|
22
|
+
self.store = store
|
|
23
|
+
elements.flatten!
|
|
24
|
+
self.elements = elements || []
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# @param separator [String] (self.store.element_separator) String used to delimit elements within a segment.
|
|
28
|
+
# @return [String]
|
|
29
|
+
def render(separator = self.store.element_separator)
|
|
30
|
+
segment = [self.id, self.elements.map(&:value)].join(separator)
|
|
31
|
+
return Eddy::Util.trim_delims_from_segment(segment, separator: separator)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
module Eddy
|
|
2
|
+
# Base class for EDI Transaction Sets.
|
|
3
|
+
class TransactionSet
|
|
4
|
+
|
|
5
|
+
# @return [Integer]
|
|
6
|
+
ID = nil
|
|
7
|
+
# @return [String]
|
|
8
|
+
NAME = nil
|
|
9
|
+
# @return [String]
|
|
10
|
+
FUNCTIONAL_GROUP = nil
|
|
11
|
+
|
|
12
|
+
# @return [Array<Segment, Loop>]
|
|
13
|
+
attr_accessor :components
|
|
14
|
+
# @return [Eddy::Data::Store] Container used to distribute state throughout an Interchange.
|
|
15
|
+
attr_accessor :store
|
|
16
|
+
|
|
17
|
+
# @param store [Eddy::Data::Store]
|
|
18
|
+
# @param components [Array<Segment, Loop>]
|
|
19
|
+
# @return [void]
|
|
20
|
+
def initialize(store, *components)
|
|
21
|
+
self.store = store
|
|
22
|
+
components.flatten!
|
|
23
|
+
self.components = components || []
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# @return [String]
|
|
27
|
+
def id
|
|
28
|
+
return self.class::ID
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# @return [String]
|
|
32
|
+
def self.id
|
|
33
|
+
return self::ID
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# @return [String]
|
|
37
|
+
def functional_group
|
|
38
|
+
return self.class::FUNCTIONAL_GROUP
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# @return [String]
|
|
42
|
+
def self.functional_group
|
|
43
|
+
return self::FUNCTIONAL_GROUP
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# @return [String]
|
|
47
|
+
def name
|
|
48
|
+
return self.class::NAME
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# @return [String]
|
|
52
|
+
def self.name
|
|
53
|
+
return self::NAME
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Add `ST` and `SE` segments to the `components` array.
|
|
57
|
+
#
|
|
58
|
+
# @param t_set_control_number [Integer] (Eddy::Data::Store#transaction_set_control_number)
|
|
59
|
+
# @return [void]
|
|
60
|
+
def add_envelope(t_set_control_number = self.store.transaction_set_control_number)
|
|
61
|
+
st = Eddy::Segments::ST.new(self.store)
|
|
62
|
+
st.TransactionSetIdentifierCode = self.id
|
|
63
|
+
st.TransactionSetControlNumber = t_set_control_number
|
|
64
|
+
|
|
65
|
+
se = Eddy::Segments::SE.new(self.store)
|
|
66
|
+
se.NumberOfIncludedSegments = self.all_components.length + 2
|
|
67
|
+
se.TransactionSetControlNumber = t_set_control_number
|
|
68
|
+
|
|
69
|
+
self.components.unshift(st)
|
|
70
|
+
self.components.push(se)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# This shouldn't be used.
|
|
74
|
+
# An Interchange or FunctionalGroup should call `all_components` and render those itself.
|
|
75
|
+
#
|
|
76
|
+
# @param s_sep [String] (self.store.segment_separator)
|
|
77
|
+
# @return [String]
|
|
78
|
+
def render(s_sep = self.store.segment_separator)
|
|
79
|
+
add_envelope()
|
|
80
|
+
e_sep = self.store.element_separator
|
|
81
|
+
return self.all_components.map { |s| s.render(e_sep) }.join(s_sep) + s_sep
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Return all contained Segments in a single, flattened array.
|
|
85
|
+
#
|
|
86
|
+
# @return [Array<Eddy::Segment>]
|
|
87
|
+
def all_components()
|
|
88
|
+
comps = self.components.map do |c|
|
|
89
|
+
if c.is_a?(Eddy::Loop::Base)
|
|
90
|
+
c.all_contents()
|
|
91
|
+
elsif c.is_a?(Eddy::Segment)
|
|
92
|
+
c
|
|
93
|
+
else
|
|
94
|
+
raise Eddy::Errors::RenderError
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
return comps.flatten
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
end
|
|
101
|
+
end
|
data/lib/eddy/parse.rb
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
module Eddy
|
|
2
|
+
module Parse
|
|
3
|
+
# Wrapper around an interchange file or string.
|
|
4
|
+
class Interchange
|
|
5
|
+
|
|
6
|
+
# Raw content of the interchange.
|
|
7
|
+
# @return [String]
|
|
8
|
+
attr_accessor :document
|
|
9
|
+
# Component Element Separator
|
|
10
|
+
# @return [String] (">")
|
|
11
|
+
attr_accessor :component_separator
|
|
12
|
+
# @return [String] ("~")
|
|
13
|
+
attr_accessor :segment_separator
|
|
14
|
+
# Data Element Separator
|
|
15
|
+
# @return [String] ("*")
|
|
16
|
+
attr_accessor :element_separator
|
|
17
|
+
|
|
18
|
+
# @param doc [String] EDI document.
|
|
19
|
+
# @param component_separator [String] (">")
|
|
20
|
+
# @param segment_separator [String] ("~")
|
|
21
|
+
# @param element_separator [String] ("*")
|
|
22
|
+
# @return [void]
|
|
23
|
+
def initialize(doc, component_separator: ">", segment_separator: "~", element_separator: "*")
|
|
24
|
+
self.document = doc
|
|
25
|
+
self.component_separator = component_separator
|
|
26
|
+
self.segment_separator = segment_separator
|
|
27
|
+
self.element_separator = element_separator
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# @param path [String]
|
|
31
|
+
# @return [self]
|
|
32
|
+
def self.from_file(path, **kwargs)
|
|
33
|
+
return self.new(File.read(path), **kwargs)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# @return [Array<Hash>]
|
|
37
|
+
def parse()
|
|
38
|
+
doc = self.document.gsub(/\n/, "")
|
|
39
|
+
segments = doc.split(self.segment_separator)
|
|
40
|
+
segments.map { |seg| self.parse_segment(seg) }
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# @param seg [String]
|
|
44
|
+
# @return [Hash]
|
|
45
|
+
def parse_segment(seg)
|
|
46
|
+
name, *elements = seg.split(self.element_separator)
|
|
47
|
+
res = { name: name, elements: {} }
|
|
48
|
+
elements.each_with_index do |value, index|
|
|
49
|
+
next if value == ""
|
|
50
|
+
key = sprintf("%s%02d", name, index + 1)
|
|
51
|
+
res[:elements][key] = value
|
|
52
|
+
end
|
|
53
|
+
return res
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
module Eddy
|
|
2
|
+
module Schema
|
|
3
|
+
# An individual EDI Data Element. Used in Companion Guides to define requirements for a Segment.
|
|
4
|
+
class ElementSummary
|
|
5
|
+
|
|
6
|
+
# Indicates the order in which Elements should appear in their Segment.
|
|
7
|
+
# @return [String]
|
|
8
|
+
attr_accessor :ref
|
|
9
|
+
# Short string used to identify the Element.
|
|
10
|
+
# @return [String]
|
|
11
|
+
attr_accessor :id
|
|
12
|
+
# Full name of the Element.
|
|
13
|
+
# @return [String]
|
|
14
|
+
attr_accessor :name
|
|
15
|
+
# Minimum length for a valid Element value. Used for validation.
|
|
16
|
+
# @return [Integer]
|
|
17
|
+
attr_accessor :min
|
|
18
|
+
# Maximum length for a valid Element value. Used for validation.
|
|
19
|
+
# @return [Integer]
|
|
20
|
+
attr_accessor :max
|
|
21
|
+
# Description of the Element.
|
|
22
|
+
# @return [String]
|
|
23
|
+
attr_accessor :description
|
|
24
|
+
# Defines if/how the Element is required.
|
|
25
|
+
# @return [String]
|
|
26
|
+
attr_accessor :req
|
|
27
|
+
# Default value for the Element
|
|
28
|
+
# @return [String]
|
|
29
|
+
attr_accessor :default
|
|
30
|
+
# A list of valid values for the Element.
|
|
31
|
+
# @return [Array]
|
|
32
|
+
attr_accessor :valid_values
|
|
33
|
+
# The kind of value the Element will contain.
|
|
34
|
+
# @return [String]
|
|
35
|
+
attr_accessor :type
|
|
36
|
+
|
|
37
|
+
# @param params [Hash] ({})
|
|
38
|
+
# @return [self]
|
|
39
|
+
def self.create(params = {})
|
|
40
|
+
summary = new()
|
|
41
|
+
summary.ref = params[:ref]&.strip
|
|
42
|
+
summary.id = params[:id]&.strip
|
|
43
|
+
summary.name = params[:name]&.strip
|
|
44
|
+
summary.min = params[:min]&.to_i
|
|
45
|
+
summary.max = params[:max]&.to_i
|
|
46
|
+
summary.description = params[:description]&.strip
|
|
47
|
+
summary.req = params[:req]&.strip
|
|
48
|
+
summary.default = params[:default]&.strip
|
|
49
|
+
summary.valid_values = params[:valid_values]
|
|
50
|
+
summary.type = params[:type]&.strip
|
|
51
|
+
return summary
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# @param id [String]
|
|
55
|
+
# @return [self]
|
|
56
|
+
def self.default_for_id(id)
|
|
57
|
+
data = Eddy::Util.raw_element_data()
|
|
58
|
+
id.upcase!
|
|
59
|
+
result = data.find { |el| el[:id] == id }
|
|
60
|
+
raise Eddy::Errors::Error, "No element found with id #{id}" if result.nil?
|
|
61
|
+
return self.create(result)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# @return [String]
|
|
65
|
+
def normalized_name
|
|
66
|
+
return Eddy::Util.normalize_name(self.name)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Generate a description to use as a doc comment for an element.
|
|
70
|
+
#
|
|
71
|
+
# @param header [Hash<:none, :ref, :see, :summary>] (:summary)
|
|
72
|
+
# @return [String]
|
|
73
|
+
def doc_comment(header: :summary)
|
|
74
|
+
parts = []
|
|
75
|
+
case header
|
|
76
|
+
when :none, nil, false
|
|
77
|
+
# Nothing to do
|
|
78
|
+
when :see then return "(see Eddy::Elements::#{Eddy::Util.normalize_id(self.id)})"
|
|
79
|
+
when :ref then parts << "### #{self.ref.upcase}\n"
|
|
80
|
+
when :summary then parts << "### Element Summary:\n"
|
|
81
|
+
else raise ArgumentError, "header must be a valid symbol"
|
|
82
|
+
end
|
|
83
|
+
parts << <<~YARD.strip
|
|
84
|
+
- Id: #{self.id}
|
|
85
|
+
- Name: #{self.name}
|
|
86
|
+
- Type: #{self.type}
|
|
87
|
+
- Min/Max: #{self.min}/#{self.max}
|
|
88
|
+
- Description: #{self.description}
|
|
89
|
+
YARD
|
|
90
|
+
return parts.compact.join("\n")
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# @return [String]
|
|
94
|
+
def yard_type()
|
|
95
|
+
return case self.type
|
|
96
|
+
when "AN" then "String"
|
|
97
|
+
when "B" then "String"
|
|
98
|
+
when "DT" then "Time"
|
|
99
|
+
when "ID" then "String"
|
|
100
|
+
when /N\d*/ then "Integer"
|
|
101
|
+
when /R\d*/ then "Float"
|
|
102
|
+
when "TM" then "Time"
|
|
103
|
+
else raise Eddy::Errors::Error, "unable to determine element type"
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# @return [String]
|
|
108
|
+
def edi_type()
|
|
109
|
+
return case self.type
|
|
110
|
+
when "AN" then "AN"
|
|
111
|
+
when "B" then "B"
|
|
112
|
+
when "DT" then "DT"
|
|
113
|
+
when "ID" then "ID"
|
|
114
|
+
when /N\d*/ then "N"
|
|
115
|
+
when /R\d*/ then "R"
|
|
116
|
+
when "TM" then "TM"
|
|
117
|
+
else raise Eddy::Errors::Error, "unable to determine element type"
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
module Eddy
|
|
2
|
+
module Schema
|
|
3
|
+
# A repeated collection of Segments and/or other Loops. Used in Companion Guides.
|
|
4
|
+
class LoopSummary
|
|
5
|
+
|
|
6
|
+
# A unique string used to identify the Loop within its Transaction Set.
|
|
7
|
+
# @return [String]
|
|
8
|
+
attr_accessor :loop_id
|
|
9
|
+
# Number of times a particular Loop may be repeated.
|
|
10
|
+
# @return [Integer]
|
|
11
|
+
attr_accessor :repeat
|
|
12
|
+
# *Syntax*, *Semantic*, or *Comment* notes on a Loop.
|
|
13
|
+
# @return [String]
|
|
14
|
+
attr_accessor :notes
|
|
15
|
+
# Indicates where the Loop is located in the Transaction Set.
|
|
16
|
+
# @return [String]
|
|
17
|
+
attr_accessor :level
|
|
18
|
+
# Defines if/how the Loop is required.
|
|
19
|
+
# @return [String]
|
|
20
|
+
attr_accessor :req
|
|
21
|
+
# The components that make up the Loop.
|
|
22
|
+
# @return [Array<Eddy::Schema::SegmentSummary, Eddy::Schema::LoopSummary>]
|
|
23
|
+
attr_accessor :components
|
|
24
|
+
|
|
25
|
+
# @return [void]
|
|
26
|
+
def initialize()
|
|
27
|
+
self.components = []
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# @param params [Hash]
|
|
31
|
+
# @return [self]
|
|
32
|
+
def self.create(params = {})
|
|
33
|
+
l = LoopSummary.new
|
|
34
|
+
l.loop_id = params[:loop_id]
|
|
35
|
+
l.repeat = params[:repeat]
|
|
36
|
+
l.notes = params[:notes]
|
|
37
|
+
l.level = params[:level]
|
|
38
|
+
l.req = params[:req]
|
|
39
|
+
l.process_components(params[:components])
|
|
40
|
+
return l
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# @param path [String] Path to a JSON or YAML file containing a valid Loop definition.
|
|
44
|
+
# @return [self]
|
|
45
|
+
def self.from_file(path)
|
|
46
|
+
raise Eddy::Errors::Error, "Invalid segment definition" unless Eddy::Schema.valid_loop_data?(path)
|
|
47
|
+
data = Eddy::Util.read_json_or_yaml(path)
|
|
48
|
+
return Eddy::Schema::LoopSummary.create(data)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# @param components [Array<Hash>]
|
|
52
|
+
# @return [void]
|
|
53
|
+
def process_components(components)
|
|
54
|
+
return if components.nil?
|
|
55
|
+
components.each do |comp|
|
|
56
|
+
if comp.key?(:loop_id)
|
|
57
|
+
self.components << Eddy::Schema::LoopSummary.create(comp)
|
|
58
|
+
else
|
|
59
|
+
self.components << Eddy::Schema::SegmentSummary.create(comp)
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Generate a description to use as a doc comment for a Loop.
|
|
65
|
+
#
|
|
66
|
+
# @param header [Boolean] (true)
|
|
67
|
+
# @return [String]
|
|
68
|
+
def doc_comment(header: true)
|
|
69
|
+
comps = ""
|
|
70
|
+
self.components.each do |comp|
|
|
71
|
+
case comp
|
|
72
|
+
when Eddy::Schema::SegmentSummary then comps << " - #{comp.id.upcase}\n"
|
|
73
|
+
when Eddy::Schema::LoopSummary then comps << " - #{comp.loop_id.upcase} (loop)\n"
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
parts = []
|
|
77
|
+
parts << "### Loop Summary:\n" if header
|
|
78
|
+
parts << <<~YARD.strip
|
|
79
|
+
- Repeat: #{self.repeat}
|
|
80
|
+
- Components:
|
|
81
|
+
#{comps}
|
|
82
|
+
YARD
|
|
83
|
+
return parts.compact.join("\n")
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Return all components in a single, flattened array.
|
|
87
|
+
#
|
|
88
|
+
# @return [Array<Eddy::Schema::SegmentSummary, Eddy::Schema::LoopSummary>]
|
|
89
|
+
def all_components()
|
|
90
|
+
return self.components.map do |comp|
|
|
91
|
+
case comp
|
|
92
|
+
when Eddy::Schema::LoopSummary then [comp, comp.all_components()]
|
|
93
|
+
when Eddy::Schema::SegmentSummary then comp
|
|
94
|
+
else raise Eddy::Errors::Error
|
|
95
|
+
end
|
|
96
|
+
end.flatten
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|