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.
Files changed (309) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +103 -37
  3. data/.solargraph.yml +4 -0
  4. data/.vscode/settings.json +17 -0
  5. data/.yardopts +2 -2
  6. data/CHANGELOG.md +50 -0
  7. data/Gemfile.lock +21 -7
  8. data/README.md +32 -3
  9. data/Rakefile +1 -10
  10. data/data/004010/code-lists/100.tsv +164 -0
  11. data/data/004010/code-lists/156.tsv +52 -0
  12. data/data/004010/code-lists/26.tsv +499 -0
  13. data/data/004010/code-lists/etc/100-fancy-definitions.tsv +164 -0
  14. data/data/004010/code-lists/etc/100-with-funds-codes.tsv +180 -0
  15. data/data/004010/code-lists/etc/26-alpha2.tsv +250 -0
  16. data/data/004010/code-lists/etc/26-alpha3.tsv +250 -0
  17. data/data/004010/elements-short.tsv +1405 -0
  18. data/data/004010/elements.tsv +3 -3
  19. data/data/004010/segments.tsv +1009 -1003
  20. data/data/004010/segments/ack.segment.yml +15 -0
  21. data/data/004010/segments/bak.segment.yml +9 -0
  22. data/data/004010/segments/beg.segment.yml +17 -0
  23. data/data/004010/segments/big.segment.yml +10 -0
  24. data/data/004010/segments/bsn.segment.yml +10 -0
  25. data/data/004010/segments/cad.segment.yml +14 -0
  26. data/data/004010/segments/ctp.segment.yml +19 -0
  27. data/data/004010/segments/ctt.segment.yml +13 -0
  28. data/data/004010/segments/dtm.segment.yml +7 -0
  29. data/data/004010/segments/envelope/ge.segment.yml +7 -0
  30. data/data/004010/segments/envelope/gs.segment.yml +13 -0
  31. data/data/004010/segments/envelope/iea.segment.yml +8 -0
  32. data/data/004010/segments/envelope/isa.segment.yml +22 -0
  33. data/data/004010/segments/envelope/se.segment.yml +7 -0
  34. data/data/004010/segments/envelope/st.segment.yml +12 -0
  35. data/data/004010/segments/hl.segment.yml +9 -0
  36. data/data/004010/segments/it1.segment.yml +20 -0
  37. data/data/004010/segments/lin.segment.yml +10 -0
  38. data/data/004010/segments/loop/hl.segment.yml +8 -0
  39. data/data/004010/segments/man.segment.yml +7 -0
  40. data/data/004010/segments/n1.segment.yml +9 -0
  41. data/data/004010/segments/n2.segment.yml +7 -0
  42. data/data/004010/segments/n3.segment.yml +6 -0
  43. data/data/004010/segments/n4.segment.yml +9 -0
  44. data/data/004010/segments/pid.segment.yml +10 -0
  45. data/data/004010/segments/po1.segment.yml +14 -0
  46. data/data/004010/segments/prf.segment.yml +9 -0
  47. data/data/004010/segments/ref.segment.yml +7 -0
  48. data/data/004010/segments/sac.segment.yml +20 -0
  49. data/data/004010/segments/sln.segment.yml +12 -0
  50. data/data/004010/segments/sn1.segment.yml +11 -0
  51. data/data/004010/segments/td1.segment.yml +13 -0
  52. data/data/004010/segments/td5.segment.yml +11 -0
  53. data/data/004010/segments/tds.segment.yml +10 -0
  54. data/data/schema/element_summary.json +60 -0
  55. data/data/schema/loop_summary.json +49 -0
  56. data/data/schema/segment_summary.json +66 -0
  57. data/data/schema/src/element_summary.schema.yml +73 -0
  58. data/data/schema/src/loop_summary.schema.yml +50 -0
  59. data/data/schema/src/segment_summary.schema.yml +59 -0
  60. data/data/schema/src/transaction_set_summary.schema.yml +27 -0
  61. data/data/schema/transaction_set_summary.json +33 -0
  62. data/data/sources.md +114 -145
  63. data/eddy.gemspec +6 -3
  64. data/exe/eddy +14 -0
  65. data/lib/definitions/elements/generated/1005.hierarchical_structure_code.rb +98 -0
  66. data/lib/definitions/elements/generated/1019.invoice_type_code.rb +40 -0
  67. data/lib/definitions/elements/generated/103.packaging_code.rb +29 -0
  68. data/lib/definitions/elements/generated/1166.contract_type_code.rb +87 -0
  69. data/lib/definitions/elements/generated/1232.purchase_category.rb +53 -0
  70. data/lib/definitions/elements/generated/127.reference_identification.rb +29 -0
  71. data/lib/definitions/elements/generated/128.reference_identification_qualifier.rb +1540 -0
  72. data/lib/definitions/elements/generated/1300.service_promotion_allowance_or_charge_code.rb +1090 -0
  73. data/lib/definitions/elements/generated/1301.agency_service_promotion_allowance_or_charge_code.rb +29 -0
  74. data/lib/definitions/elements/generated/133.routing_sequence_code.rb +60 -0
  75. data/lib/definitions/elements/generated/166.address_information.rb +29 -0
  76. data/lib/definitions/elements/generated/183.volume.rb +29 -0
  77. data/lib/definitions/elements/generated/187.weight_qualifier.rb +88 -0
  78. data/lib/definitions/elements/generated/19.city_name.rb +29 -0
  79. data/lib/definitions/elements/generated/206.equipment_initial.rb +29 -0
  80. data/lib/definitions/elements/generated/207.equipment_number.rb +29 -0
  81. data/lib/definitions/elements/generated/212.unit_price.rb +29 -0
  82. data/lib/definitions/elements/generated/22.commodity_code.rb +29 -0
  83. data/lib/definitions/elements/generated/23.commodity_code_qualifier.rb +60 -0
  84. data/lib/definitions/elements/generated/234.product_service_id.rb +29 -0
  85. data/lib/definitions/elements/generated/235.product_service_id_qualifier.rb +514 -0
  86. data/lib/definitions/elements/generated/236.price_identifier_code.rb +201 -0
  87. data/lib/definitions/elements/generated/248.allowance_or_charge_indicator.rb +44 -0
  88. data/lib/definitions/elements/generated/26.country_code.rb +535 -0
  89. data/lib/definitions/elements/generated/284.service_level_code.rb +103 -0
  90. data/lib/definitions/elements/generated/324.purchase_order_number.rb +29 -0
  91. data/lib/definitions/elements/generated/326.request_reference_number.rb +29 -0
  92. data/lib/definitions/elements/generated/327.change_order_sequence_number.rb +29 -0
  93. data/lib/definitions/elements/generated/328.release_number.rb +29 -0
  94. data/lib/definitions/elements/generated/330.quantity_ordered.rb +29 -0
  95. data/lib/definitions/elements/generated/347.hash_total.rb +29 -0
  96. data/lib/definitions/elements/generated/349.item_description_type.rb +40 -0
  97. data/lib/definitions/elements/generated/352.description.rb +29 -0
  98. data/lib/definitions/elements/generated/353.transaction_set_purpose_code.rb +102 -0
  99. data/lib/definitions/elements/generated/354.number_of_line_items.rb +30 -0
  100. data/lib/definitions/elements/generated/355.unit_or_basis_for_measurement_code.rb +831 -0
  101. data/lib/definitions/elements/generated/358.quantity_invoiced.rb +29 -0
  102. data/lib/definitions/elements/generated/367.contract_number.rb +29 -0
  103. data/lib/definitions/elements/generated/368.shipment_order_status_code.rb +139 -0
  104. data/lib/definitions/elements/generated/374.date_time_qualifier.rb +1149 -0
  105. data/lib/definitions/elements/generated/380.quantity.rb +29 -0
  106. data/lib/definitions/elements/generated/382.number_of_units_shipped.rb +29 -0
  107. data/lib/definitions/elements/generated/387.routing.rb +29 -0
  108. data/lib/definitions/elements/generated/396.shipment_identification.rb +29 -0
  109. data/lib/definitions/elements/generated/559.agency_qualifier_code.rb +213 -0
  110. data/lib/definitions/elements/generated/587.acknowledgment_type.rb +52 -0
  111. data/lib/definitions/elements/generated/610.amount.rb +30 -0
  112. data/lib/definitions/elements/generated/639.basis_of_unit_price_code.rb +128 -0
  113. data/lib/definitions/elements/generated/640.transaction_type_code.rb +483 -0
  114. data/lib/definitions/elements/generated/646.quantity_shipped_to_date.rb +29 -0
  115. data/lib/definitions/elements/generated/648.price_multiplier_qualifier.rb +43 -0
  116. data/lib/definitions/elements/generated/649.multiplier.rb +29 -0
  117. data/lib/definitions/elements/generated/66.identification_code_qualifier.rb +252 -0
  118. data/lib/definitions/elements/generated/662.relationship_code.rb +42 -0
  119. data/lib/definitions/elements/generated/668.line_item_status_code.rb +63 -0
  120. data/lib/definitions/elements/generated/67.identification_code.rb +29 -0
  121. data/lib/definitions/elements/generated/687.class_of_trade_code.rb +89 -0
  122. data/lib/definitions/elements/generated/750.product_process_characteristic_code.rb +254 -0
  123. data/lib/definitions/elements/generated/751.product_description_code.rb +29 -0
  124. data/lib/definitions/elements/generated/76.invoice_number.rb +29 -0
  125. data/lib/definitions/elements/generated/782.monetary_amount.rb +29 -0
  126. data/lib/definitions/elements/generated/786.security_level_code.rb +54 -0
  127. data/lib/definitions/elements/generated/79.lading_description.rb +29 -0
  128. data/lib/definitions/elements/generated/80.lading_quantity.rb +30 -0
  129. data/lib/definitions/elements/generated/87.marks_and_numbers.rb +29 -0
  130. data/lib/definitions/elements/generated/88.marks_and_numbers_qualifier.rb +57 -0
  131. data/lib/definitions/elements/generated/91.transportation_method_type_code.rb +108 -0
  132. data/lib/definitions/elements/generated/92.purchase_order_type_code.rb +106 -0
  133. data/lib/definitions/elements/generated/98.entity_identifier_code.rb +1349 -0
  134. data/lib/definitions/elements/manual/116.postal_code.rb +44 -0
  135. data/lib/definitions/elements/manual/124.application_receivers_code.rb +29 -0
  136. data/lib/definitions/elements/manual/140.standard_carrier_alpha_code.rb +211 -0
  137. data/lib/definitions/elements/manual/142.application_senders_code.rb +29 -0
  138. data/lib/definitions/elements/manual/143.transaction_set_identifier_code.rb +335 -0
  139. data/lib/definitions/elements/manual/156.state_or_province_code.rb +92 -0
  140. data/lib/definitions/elements/manual/28.group_control_number.rb +34 -0
  141. data/lib/definitions/elements/manual/329.transactional_set_control_number.rb +35 -0
  142. data/lib/definitions/elements/manual/337.time.rb +30 -0
  143. data/lib/definitions/elements/manual/350.assigned_identification.rb +33 -0
  144. data/lib/definitions/elements/manual/373.date.rb +30 -0
  145. data/lib/definitions/elements/manual/455.responsible_agency_code.rb +43 -0
  146. data/lib/definitions/elements/manual/479.functional_identifier_code.rb +271 -0
  147. data/lib/definitions/elements/manual/480.version_release_industry_identifier_code.rb +145 -0
  148. data/lib/definitions/elements/manual/784.length_of_binary_data.rb +30 -0
  149. data/lib/definitions/elements/manual/785.binary_data.rb +30 -0
  150. data/lib/definitions/elements/manual/96.number_of_included_segments.rb +30 -0
  151. data/lib/definitions/elements/manual/97.number_of_transaction_sets_included.rb +30 -0
  152. data/lib/definitions/elements/manual/hl/628.hierarchical_id_number.rb +29 -0
  153. data/lib/definitions/elements/manual/hl/734.hierarchical_parent_id_number.rb +29 -0
  154. data/lib/definitions/elements/manual/hl/735.hierarchical_level_code.rb +207 -0
  155. data/lib/definitions/elements/manual/hl/736.hierarchical_child_code.rb +39 -0
  156. data/lib/definitions/elements/manual/i/I01.authorization_information_qualifier.rb +48 -0
  157. data/lib/definitions/elements/manual/i/I02.authorization_information.rb +33 -0
  158. data/lib/definitions/elements/manual/i/I03.security_information_qualifier.rb +43 -0
  159. data/lib/definitions/elements/manual/i/I04.security_information.rb +33 -0
  160. data/lib/definitions/elements/manual/i/I05.interchange_id_qualifier.rb +75 -0
  161. data/lib/definitions/elements/manual/i/I06.interchange_sender_id.rb +29 -0
  162. data/lib/definitions/elements/manual/i/I07.interchange_receiver_id.rb +29 -0
  163. data/lib/definitions/elements/manual/i/I08.interchange_date.rb +35 -0
  164. data/lib/definitions/elements/manual/i/I09.interchange_time.rb +36 -0
  165. data/lib/definitions/elements/manual/i/I10.interchange_control_standards_identifier.rb +42 -0
  166. data/lib/definitions/elements/manual/i/I11.interchange_control_version_number.rb +55 -0
  167. data/lib/definitions/elements/manual/i/I12.interchange_control_number.rb +34 -0
  168. data/lib/definitions/elements/manual/i/I13.acknowledgment_requested.rb +43 -0
  169. data/lib/definitions/elements/manual/i/I14.usage_indicator.rb +40 -0
  170. data/lib/definitions/elements/manual/i/I15.component_element_separator.rb +36 -0
  171. data/lib/definitions/elements/manual/i/I16.number_of_included_functional_groups.rb +30 -0
  172. data/lib/definitions/elements/manual/misc/81.weight.rb +29 -0
  173. data/lib/definitions/elements/manual/misc/93.name.rb +29 -0
  174. data/lib/definitions/segments/generated/ack.rb +192 -0
  175. data/lib/definitions/segments/generated/bak.rb +90 -0
  176. data/lib/definitions/segments/generated/beg.rb +226 -0
  177. data/lib/definitions/segments/generated/big.rb +107 -0
  178. data/lib/definitions/segments/generated/bsn.rb +107 -0
  179. data/lib/definitions/segments/generated/cad.rb +175 -0
  180. data/lib/definitions/segments/generated/ctp.rb +158 -0
  181. data/lib/definitions/segments/generated/ctt.rb +141 -0
  182. data/lib/definitions/segments/generated/dtm.rb +56 -0
  183. data/lib/definitions/segments/generated/it1.rb +277 -0
  184. data/lib/definitions/segments/generated/lin.rb +107 -0
  185. data/lib/definitions/segments/generated/man.rb +56 -0
  186. data/lib/definitions/segments/generated/n1.rb +90 -0
  187. data/lib/definitions/segments/generated/n3.rb +39 -0
  188. data/lib/definitions/segments/generated/n4.rb +90 -0
  189. data/lib/definitions/segments/generated/pid.rb +107 -0
  190. data/lib/definitions/segments/generated/po1.rb +175 -0
  191. data/lib/definitions/segments/generated/prf.rb +90 -0
  192. data/lib/definitions/segments/generated/ref.rb +56 -0
  193. data/lib/definitions/segments/generated/sac.rb +107 -0
  194. data/lib/definitions/segments/generated/sln.rb +141 -0
  195. data/lib/definitions/segments/generated/sn1.rb +124 -0
  196. data/lib/definitions/segments/generated/td1.rb +158 -0
  197. data/lib/definitions/segments/generated/td5.rb +107 -0
  198. data/lib/definitions/segments/generated/tds.rb +39 -0
  199. data/lib/definitions/segments/manual/envelopes/ge.rb +53 -0
  200. data/lib/definitions/segments/manual/envelopes/gs.rb +163 -0
  201. data/lib/definitions/segments/manual/envelopes/iea.rb +53 -0
  202. data/lib/definitions/segments/manual/envelopes/isa.rb +295 -0
  203. data/lib/definitions/segments/manual/envelopes/se.rb +52 -0
  204. data/lib/definitions/segments/manual/envelopes/st.rb +52 -0
  205. data/lib/definitions/segments/manual/hl.rb +96 -0
  206. data/lib/definitions/segments/manual/n2.rb +52 -0
  207. data/lib/definitions/transaction_sets/manual/810/810.rb +143 -0
  208. data/lib/definitions/transaction_sets/manual/810/loops.rb +109 -0
  209. data/lib/definitions/transaction_sets/manual/850/850.rb +92 -0
  210. data/lib/definitions/transaction_sets/manual/850/loops.rb +58 -0
  211. data/lib/definitions/transaction_sets/manual/855/855.rb +83 -0
  212. data/lib/definitions/transaction_sets/manual/855/loops.rb +104 -0
  213. data/lib/definitions/transaction_sets/manual/856/856.rb +83 -0
  214. data/lib/definitions/transaction_sets/manual/856/loops.rb +155 -0
  215. data/lib/eddy.rb +29 -7
  216. data/lib/eddy/build/build.rb +47 -0
  217. data/lib/eddy/build/elements/element.rb +67 -0
  218. data/lib/eddy/build/elements/elements.rb +46 -0
  219. data/lib/eddy/build/elements/id.rb +55 -0
  220. data/lib/eddy/build/elements/n.rb +48 -0
  221. data/lib/eddy/build/loop_builder.rb +93 -0
  222. data/lib/eddy/build/segment_builder.rb +169 -0
  223. data/lib/eddy/build/transaction_set_builder.rb +218 -0
  224. data/lib/eddy/cli/cli.rb +39 -0
  225. data/lib/eddy/config.rb +51 -0
  226. data/lib/eddy/data.rb +50 -0
  227. data/lib/eddy/data/persistence/active_record.rb +10 -0
  228. data/lib/eddy/data/persistence/base.rb +47 -0
  229. data/lib/eddy/data/persistence/file.rb +50 -0
  230. data/lib/eddy/data/persistence/memory.rb +65 -0
  231. data/lib/eddy/data/store.rb +108 -0
  232. data/lib/eddy/errors.rb +112 -0
  233. data/lib/eddy/models/element.rb +14 -0
  234. data/lib/eddy/models/element/an.rb +55 -0
  235. data/lib/eddy/models/element/b.rb +53 -0
  236. data/lib/eddy/models/element/base.rb +116 -0
  237. data/lib/eddy/models/element/composite.rb +6 -0
  238. data/lib/eddy/models/element/dt.rb +100 -0
  239. data/lib/eddy/models/element/id.rb +58 -0
  240. data/lib/eddy/models/element/n.rb +94 -0
  241. data/lib/eddy/models/element/r.rb +84 -0
  242. data/lib/eddy/models/element/tm.rb +113 -0
  243. data/lib/eddy/models/loop.rb +74 -0
  244. data/lib/eddy/models/segment.rb +35 -0
  245. data/lib/eddy/models/transaction_set.rb +101 -0
  246. data/lib/eddy/parse.rb +58 -0
  247. data/lib/eddy/schema/element_summary.rb +123 -0
  248. data/lib/eddy/schema/loop_summary.rb +101 -0
  249. data/lib/eddy/schema/segment_summary.rb +116 -0
  250. data/lib/eddy/schema/transaction_set_summary.rb +96 -0
  251. data/lib/eddy/schema/validate.rb +41 -0
  252. data/lib/eddy/util.rb +16 -0
  253. data/lib/eddy/util/clean_folder.rb +14 -0
  254. data/lib/eddy/util/edi_data.rb +153 -0
  255. data/lib/eddy/util/new_number.rb +24 -0
  256. data/lib/eddy/util/normalize.rb +51 -0
  257. data/lib/eddy/util/paths.rb +19 -0
  258. data/lib/eddy/util/read.rb +38 -0
  259. data/lib/eddy/util/time.rb +56 -0
  260. data/lib/eddy/util/timestamp.rb +12 -0
  261. data/lib/eddy/util/trim.rb +29 -0
  262. data/lib/eddy/version.rb +1 -1
  263. data/lib/eddy/write/functional_group.rb +33 -0
  264. data/lib/eddy/write/interchange.rb +28 -0
  265. data/lib/eddy/write/simple_interchange.rb +57 -0
  266. data/lib/generators/eddy/initializer/initializer_generator.rb +17 -0
  267. data/lib/generators/eddy/initializer/templates/eddy.rb.erb +6 -0
  268. data/lib/generators/eddy/migration/migration_generator.rb +53 -0
  269. data/lib/generators/eddy/migration/templates/migration.rb.erb +35 -0
  270. data/tasks/build.rake +15 -0
  271. data/tasks/misc/gemspec.rake +12 -0
  272. data/tasks/misc/missing_lists.rake +240 -0
  273. data/tasks/misc/yaml2json.rake +20 -0
  274. data/todo.txt +16 -0
  275. metadata +297 -42
  276. data/data/004010/segments/ISA.tsv +0 -17
  277. data/data/schema.jsonc +0 -67
  278. data/lib/eddy/build/build_an.rb +0 -31
  279. data/lib/eddy/build/build_dt.rb +0 -46
  280. data/lib/eddy/build/build_elements.rb +0 -181
  281. data/lib/eddy/build/build_id.rb +0 -56
  282. data/lib/eddy/build/build_r_and_n.rb +0 -69
  283. data/lib/eddy/build/build_tm.rb +0 -52
  284. data/lib/eddy/build/segments.rb +0 -25
  285. data/lib/eddy/definitions/manual/elements/109.dt.pickup_date.rb +0 -20
  286. data/lib/eddy/definitions/manual/elements/111.tm.pickup_time.rb +0 -20
  287. data/lib/eddy/definitions/manual/elements/112.an.pier_name.rb +0 -19
  288. data/lib/eddy/definitions/manual/elements/785.b.binary_data.rb +0 -19
  289. data/lib/eddy/definitions/manual/elements/81.r.weight.rb +0 -19
  290. data/lib/eddy/definitions/manual/elements/86.n0.total_equipment.rb +0 -20
  291. data/lib/eddy/definitions/manual/elements/I02.authorization_information.rb +0 -20
  292. data/lib/eddy/definitions/manual/elements/I04.security_information.rb +0 -20
  293. data/lib/eddy/definitions/manual/elements/I08.interchange_date.rb +0 -20
  294. data/lib/eddy/definitions/manual/elements/I09.interchange_time.rb +0 -20
  295. data/lib/eddy/definitions/manual/elements/I15.component_element_separator.rb +0 -32
  296. data/lib/eddy/definitions/manual/segments/n1.rb +0 -14
  297. data/lib/eddy/element.rb +0 -14
  298. data/lib/eddy/element/an.rb +0 -36
  299. data/lib/eddy/element/b.rb +0 -9
  300. data/lib/eddy/element/base.rb +0 -37
  301. data/lib/eddy/element/dt.rb +0 -89
  302. data/lib/eddy/element/id.rb +0 -40
  303. data/lib/eddy/element/n.rb +0 -43
  304. data/lib/eddy/element/r.rb +0 -47
  305. data/lib/eddy/element/tm.rb +0 -108
  306. data/lib/eddy/error.rb +0 -14
  307. data/lib/eddy/helpers.rb +0 -31
  308. data/lib/eddy/segment.rb +0 -12
  309. 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
@@ -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