gillbus 0.17.6 → 0.22.9

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 (56) hide show
  1. checksums.yaml +5 -5
  2. data/.ruby-version +1 -1
  3. data/Gemfile +0 -4
  4. data/gillbus.gemspec +1 -1
  5. data/lib/gillbus/base_request.rb +2 -0
  6. data/lib/gillbus/base_response.rb +8 -4
  7. data/lib/gillbus/get_carriers.rb +13 -0
  8. data/lib/gillbus/get_required_fields.rb +1 -0
  9. data/lib/gillbus/get_trip_seats.rb +7 -0
  10. data/lib/gillbus/helpers/parser.rb +45 -11
  11. data/lib/gillbus/return_position.rb +2 -0
  12. data/lib/gillbus/return_position_forced.rb +16 -0
  13. data/lib/gillbus/search_nearby_trips.rb +39 -0
  14. data/lib/gillbus/search_trips.rb +20 -13
  15. data/lib/gillbus/structs/carrier.rb +11 -0
  16. data/lib/gillbus/structs/luggage.rb +19 -0
  17. data/lib/gillbus/structs/nearby_cities_trip.rb +61 -0
  18. data/lib/gillbus/structs/point.rb +2 -0
  19. data/lib/gillbus/structs/return_cause.rb +1 -1
  20. data/lib/gillbus/structs/seat.rb +1 -0
  21. data/lib/gillbus/structs/segment.rb +27 -0
  22. data/lib/gillbus/structs/tariff/return_cause.rb +8 -3
  23. data/lib/gillbus/structs/ticket.rb +29 -12
  24. data/lib/gillbus/structs/tickets_option.rb +29 -0
  25. data/lib/gillbus/structs/trip.rb +35 -0
  26. data/lib/gillbus/structs/trip_options.rb +82 -24
  27. data/lib/gillbus/structs/trip_service.rb +16 -1
  28. data/lib/gillbus/tickets_booking.rb +34 -0
  29. data/lib/gillbus/version.rb +1 -1
  30. data/lib/gillbus.rb +31 -3
  31. data/test/error_test.rb +1 -1
  32. data/test/find_order_test.rb +16 -0
  33. data/test/get_required_fields_test.rb +77 -0
  34. data/test/get_trip_seats_test.rb +36 -0
  35. data/test/get_trip_segments_test.rb +1 -0
  36. data/test/parse_trip_options_test.rb +92 -0
  37. data/test/parse_trip_test.rb +25 -0
  38. data/test/responses/findOrder.xml +8 -0
  39. data/test/responses/getRequiredFieldsWithOneLuggage.xml +28 -0
  40. data/test/responses/getRequiredFieldsWithTwoLuggageSegments.xml +40 -0
  41. data/test/responses/getRequiredFieldsWithoutLuggage.xml +23 -0
  42. data/test/responses/getTripSeats-back-seats.xml +1192 -0
  43. data/test/responses/getTripSeats-two-floors.xml +1122 -0
  44. data/test/responses/getTripSeats.xml +70 -0
  45. data/test/responses/legacy_trip.yml +120 -0
  46. data/test/responses/legacy_trip_2.yml +217 -0
  47. data/test/responses/searchTrips-full-carriers-info.xml +231 -0
  48. data/test/responses/searchTrips-new-options-format.xml +244 -0
  49. data/test/responses/searchTrips-prod.xml +5 -0
  50. data/test/responses/searchTrips-round-trip-offers.xml +2016 -0
  51. data/test/responses/searchTripsNearby.xml +707 -0
  52. data/test/responses/ticketsBooking.xml +1 -0
  53. data/test/search_nearby_trips_test.rb +18 -0
  54. data/test/search_trips_test.rb +93 -0
  55. data/test/tickets_booking_test.rb +63 -0
  56. metadata +49 -13
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 39981156aa20418b3109add8e3d94c63077bd44c
4
- data.tar.gz: 50e5710aa809acc6203119011b706034fbdd100f
2
+ SHA256:
3
+ metadata.gz: b85dbfeb542cb41597bcaff503e35298c94742adcf937f536f41d26849c41f0b
4
+ data.tar.gz: fe22b0ac687bf787630356475e001b40f8ecbeccb1f6a3560816b8663666a75d
5
5
  SHA512:
6
- metadata.gz: 512923d49ef42592d7f3d1d2fbd4a6e97b888d15980cd1b1ebeee82ded1908cda2fa820e07d8a2769ebf797f2557e7d8beb1395e34dee02f54298705d2c2f4ab
7
- data.tar.gz: 15d286724cead0805000c7d4d29c9abea2f7b59ca11561bc8cc6515a2e037cf616df9cbfa6284d9f90c418723de581c00ef6b3ad7d95add3171a6cb0a11c261d
6
+ metadata.gz: 5bdc19f44370f737270f8220415b9c6ef927a7821e08d072bf2f778c6adbfe9b847a212b53a036b7ab226772bc1459cbab5d5be29337fb16bd5de11d89d61cd0
7
+ data.tar.gz: 24b1d2cf5459a9f61bafa62adf9f2cdfd27c18562ca3bdb5f15afcdf306ed60e98f29e19444682f955d26380b5162adfd3b1d4d8e97c8cba11907b5d907952d0
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 2.3.2
1
+ 2.6.3
data/Gemfile CHANGED
@@ -2,7 +2,3 @@ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in gillbus.gemspec
4
4
  gemspec
5
-
6
- group :development do
7
- gem 'ox'
8
- end
data/gillbus.gemspec CHANGED
@@ -22,7 +22,7 @@ Gem::Specification.new do |spec|
22
22
  spec.add_dependency 'faraday'
23
23
  spec.add_dependency 'monetize'
24
24
  spec.add_dependency 'money'
25
- spec.add_dependency 'multi_xml'
25
+ spec.add_dependency 'ox', '~> 2.9'
26
26
 
27
27
  spec.add_development_dependency 'bundler', '~> 1.6'
28
28
  spec.add_development_dependency 'minitest'
@@ -45,6 +45,8 @@ class Gillbus
45
45
  'uk' => 'ukr',
46
46
  'th' => 'tai',
47
47
  'pl' => 'pol',
48
+ 'cs' => 'ces',
49
+ 'bg' => 'bul',
48
50
 
49
51
  # temporary, until changed in busfor
50
52
  'ua' => 'ukr',
@@ -1,4 +1,4 @@
1
- require 'multi_xml'
1
+ require 'ox'
2
2
 
3
3
  class Gillbus
4
4
  class BaseResponse
@@ -13,11 +13,15 @@ class Gillbus
13
13
  attr_accessor :external_error_message
14
14
  attr_accessor :request_time
15
15
 
16
+ attr_accessor :raw_xml # make accessible for logging and debuging
17
+
16
18
  def error?
17
19
  !error_code.nil?
18
20
  end
19
21
 
20
22
  def self.parse(data, instance: new, options: {})
23
+ instance.raw_xml = options[:raw_xml] if options[:raw_xml]
24
+
21
25
  # ugly
22
26
  if data['MESSAGE']
23
27
  instance.error_code = data['MESSAGE']['CODE'].to_i
@@ -32,12 +36,12 @@ class Gillbus
32
36
  end
33
37
 
34
38
  def self.parse_string(xml_string, **options)
35
- xml = MultiXml.parse(xml_string)
39
+ xml = Ox.load(xml_string, mode: :hash, symbolize_keys: false)
36
40
  # <DATA/> is a valid response
37
41
  return ParseError.new(xml_string, 'DATA attribute missing') unless xml.key?('DATA')
38
42
  data = xml['DATA'] || {}
39
- parse(data, instance: new, options: options)
40
- rescue MultiXml::ParseError, ArgumentError => e
43
+ parse(data, instance: new, options: options.merge(raw_xml: xml_string))
44
+ rescue Ox::ParseError, ArgumentError => e
41
45
  ParseError.new(xml_string, e.message)
42
46
  end
43
47
  end
@@ -0,0 +1,13 @@
1
+ class Gillbus
2
+ module GetCarriers
3
+ Gillbus.register self, :get_carriers
4
+
5
+ class Request < BaseRequest
6
+ def path; '/online2/getCarriers' end
7
+ end
8
+
9
+ class Response < BaseResponse
10
+ field :carriers, [Carrier], key: 'CARRIER'
11
+ end
12
+ end
13
+ end
@@ -16,6 +16,7 @@ class Gillbus
16
16
 
17
17
  class Response < BaseResponse
18
18
  field :dictionary, :bool_dict
19
+ field :luggage, Luggage, key: 'BAGGAGE'
19
20
 
20
21
  parser do
21
22
  def bool_dict(val)
@@ -21,6 +21,11 @@ class Gillbus
21
21
  # Только для железнодорожных рейсов.
22
22
  attr_accessor :back_carriage_id
23
23
 
24
+ # floorNumber
25
+ # Номер этажа автобуса, если указан, то возвращается карта мест указанного этажа.
26
+ # Если задан неверно или не указан, то возвращается вся карта мест.
27
+ attr_accessor :floor_number
28
+
24
29
  # segment0carriageId...segmentNcarriageId (не обязательный)
25
30
  # ИД вагона сегмента рейса с порядковым нормеом 0...N, для которого нужно получить карту мест.
26
31
  # По-умолчанию первый попавшийся. Только для железнодорожных рейсов.
@@ -30,6 +35,7 @@ class Gillbus
30
35
  tripId: trip_id,
31
36
  carriageId: carriage_id,
32
37
  backCarriageId: back_carriage_id,
38
+ floorNumber: floor_number,
33
39
  )
34
40
  end
35
41
  end
@@ -38,6 +44,7 @@ class Gillbus
38
44
  SEGMENT_REGEX = /SEGMENT_(?<number>\d+)_SEAT/
39
45
 
40
46
  field :seats, [Seat], key: 'SEAT'
47
+ field :back_seats, [Seat], key: 'BACK_SEAT' # для round_trip offers
41
48
 
42
49
  field :segments, :segments, key: SEGMENT_REGEX
43
50
 
@@ -3,6 +3,13 @@ require 'active_support/time'
3
3
 
4
4
  class Gillbus
5
5
  class Parser
6
+ NULL_CONST = 'null'.freeze
7
+ TRUE_CONST = 'true'.freeze
8
+ YES_CONST = 'Y'.freeze
9
+ DATE_FORMAT_CONST = '%d.%m.%Y'.freeze
10
+ TIME_FORMAT_REGEXP = /^ ( \d\d:\d\d ) (?: :\d\d )? $/x.freeze
11
+ DEFAULT_TIMEZONE = 'Europe/Kiev'.freeze
12
+
6
13
  attr_accessor :doc
7
14
  attr_accessor :instance
8
15
  attr_accessor :fields
@@ -33,18 +40,43 @@ class Gillbus
33
40
  private
34
41
 
35
42
  def fetch_value(key:, root:)
43
+ target_doc = root ? doc[root] : doc
44
+ return unless target_doc
45
+
36
46
  if key.is_a?(Regexp)
37
- doc.select { |k| k =~ key }
38
- elsif root
39
- doc[root] && doc[root][key]
47
+ target_doc.select { |k| k =~ key }
48
+ elsif key.is_a?(Array)
49
+ key.map { |k| ensure_array(target_doc[k]) }.inject(&:+)
50
+ else
51
+ target_doc[key]
52
+ end
53
+ end
54
+
55
+ # Нужно удостовериться, что элемент завёрнут в массив,
56
+ # чтобы дальше эти массивы сложить в методе fetch_value.
57
+ # Есть нюанс, что при сложении ['Item'] + [{'ID'=>'1'}, 'Subitem'] получается
58
+ # ['Item', {'ID'=>'1'}, 'Subitem'], а нам надо ['Item', [{'ID'=>'1'}, 'Subitem']]
59
+ # Поэтому item_with_id заворачиваем во внешний массив
60
+ def ensure_array(val)
61
+ if is_item_with_id?(val)
62
+ [val]
40
63
  else
41
- doc[key]
64
+ Array(val)
42
65
  end
43
66
  end
44
67
 
68
+ # Детектит элементы вида <CRITICAL_INF ID="1">Text</CRITICAL_INF>,
69
+ # которые парсятся как [{'ID'=>'1'}, 'Text']
70
+ def is_item_with_id?(val)
71
+ val.is_a?(Array) && val.size == 2 && val.first.is_a?(Hash) && val.first.keys == ['ID']
72
+ end
73
+
45
74
  def make_one_or_many(type, val)
46
75
  # [:type]
47
76
  if type.is_a? Array
77
+ if val.is_a?(Array) && val[0].is_a?(Hash) && !val[0].has_key?('__content__')
78
+ val = [val] if val[1].is_a?(String) # hack to handle attribute parsing by Ox
79
+ end
48
80
  array(val).map { |v| make_one type.first, v }
49
81
  # :type
50
82
  else
@@ -70,16 +102,18 @@ class Gillbus
70
102
  end
71
103
 
72
104
  def string(val)
73
- return if val == 'null'
105
+ return if val == NULL_CONST
106
+ # если это тег с атрибутами - возвращаем только содержимое тега
107
+ return val.last if val.is_a?(Array) && val.size == 2
74
108
  val
75
109
  end
76
110
 
77
111
  def bool(val)
78
- val == 'true'
112
+ val == TRUE_CONST
79
113
  end
80
114
 
81
115
  def yesno_bool(val)
82
- val == 'Y'
116
+ val == YES_CONST
83
117
  end
84
118
 
85
119
  def int(val)
@@ -87,12 +121,12 @@ class Gillbus
87
121
  end
88
122
 
89
123
  def date(val)
90
- Date.strptime(val, '%d.%m.%Y')
124
+ Date.strptime(val, DATE_FORMAT_CONST)
91
125
  end
92
126
 
93
127
  # rubocop:disable Style/GuardClause, Style/IfUnlessModifier
94
128
  def time(val)
95
- if val =~ /^ ( \d\d:\d\d ) (?: :\d\d )? $/x
129
+ if val =~ TIME_FORMAT_REGEXP
96
130
  $1
97
131
  end
98
132
  end
@@ -109,11 +143,11 @@ class Gillbus
109
143
  end
110
144
 
111
145
  def default_timezone
112
- @options[:timezone] || 'Europe/Kiev'
146
+ @options[:timezone] || DEFAULT_TIMEZONE
113
147
  end
114
148
 
115
149
  def decimal(val)
116
- BigDecimal.new(val)
150
+ BigDecimal(val)
117
151
  end
118
152
  end
119
153
  end
@@ -33,6 +33,8 @@ class Gillbus
33
33
  field :reason_id
34
34
  field :date
35
35
  field :failures
36
+ field :returned_amount
37
+ field :detained_amount
36
38
  end
37
39
 
38
40
  field :return_positions, [ReturnPosition], key: 'RETURN_POSITION'
@@ -0,0 +1,16 @@
1
+ class Gillbus
2
+ module ReturnPositionForced
3
+ Gillbus.register self, :return_position_forced
4
+
5
+ class Request < ::Gillbus::ReturnPosition::Request
6
+ def path; '/online2/ReturnPositionForced'; end
7
+ end
8
+
9
+ class Response < ::Gillbus::ReturnPosition::Response
10
+ class ReturnPositionForced < ::Gillbus::ReturnPosition::Response::ReturnPosition
11
+ end
12
+
13
+ field :return_positions, [::Gillbus::ReturnPosition::Response::ReturnPosition], key: 'RETURN_POSITION'
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,39 @@
1
+ class Gillbus
2
+ module SearchTripNearbyCities
3
+ Gillbus.register self, :search_nearby_cities_trips
4
+
5
+ class Request < BaseRequest
6
+ def path; '/online2/searchTripNearbyCities' end
7
+
8
+ # startCityId
9
+ # ИД пункта отправления
10
+ attr_accessor :start_city_id
11
+
12
+ # endCityId
13
+ # ИД пункта прибытия
14
+ attr_accessor :end_city_id
15
+
16
+ # startDateSearch
17
+ # Дата отправления, на которую будет произведен поиск рейсов.
18
+ attr_accessor :start_date_search
19
+
20
+ # ticketCount
21
+ # Количество оформляемых билетов. От 1 до k.
22
+ attr_accessor :ticket_count
23
+
24
+ def params
25
+ compact(
26
+ startCityId: start_city_id,
27
+ endCityId: end_city_id,
28
+ startDateSearch: date(start_date_search),
29
+ ticketCount: ticket_count,
30
+ )
31
+ end
32
+ end
33
+
34
+ class Response < BaseResponse
35
+ field :completed, :bool
36
+ field :trips, [NearbyCitiesTrip], key: 'TRIP', root: 'NEARBY_CITIES'
37
+ end
38
+ end
39
+ end
@@ -44,6 +44,11 @@ class Gillbus
44
44
  # Если false, то будут искаться рейсы только в одну сторону.
45
45
  attr_accessor :round_trip
46
46
 
47
+ # limitSegmentTripShow (опциональный параметр)
48
+ # Ограничение максимального количества сегментных рейсов.
49
+ # Если ничего не передано или передано число -1, то выдача не ограничена.
50
+ attr_accessor :limit_segment_trip_show
51
+
47
52
  # backStartDateSearch (обязательный если roundTrip=true)
48
53
  # Дата отправления, на которую будет произведен поиск обратных рейсов.
49
54
  attr_accessor :back_start_date_search
@@ -93,20 +98,21 @@ class Gillbus
93
98
 
94
99
  def params
95
100
  compact(
96
- selectedModes: modes(selected_modes),
97
- connectionIds: list(connection_ids),
98
- tripFullSale: bool(trip_full_sale),
99
- fullSearch: bool(full_search),
100
- startCityId: start_city_id,
101
- endCityId: end_city_id,
102
- startDateSearch: date(start_date_search),
103
- roundTrip: bool(round_trip),
101
+ selectedModes: modes(selected_modes),
102
+ connectionIds: list(connection_ids),
103
+ tripFullSale: bool(trip_full_sale),
104
+ fullSearch: bool(full_search),
105
+ startCityId: start_city_id,
106
+ endCityId: end_city_id,
107
+ startDateSearch: date(start_date_search),
108
+ roundTrip: bool(round_trip),
109
+ limitSegmentTripShow: limit_segment_trip_show,
104
110
  backStartDateSearch: date(back_start_date_search),
105
- ticketCount: ticket_count,
106
- waitTimeout: wait_timeout,
107
- onlyBranded: bool(only_branded),
108
- tripOptions: bool(trip_options),
109
- insuranceId: insurance_id,
111
+ ticketCount: ticket_count,
112
+ waitTimeout: wait_timeout,
113
+ onlyBranded: bool(only_branded),
114
+ tripOptions: bool(trip_options),
115
+ insuranceId: insurance_id,
110
116
  **passengers_data,
111
117
  )
112
118
  end
@@ -132,6 +138,7 @@ class Gillbus
132
138
  class Response < BaseResponse
133
139
  field :completed, :bool
134
140
  field :trips, [Trip], key: 'TRIP'
141
+ field :back_trips, [Trip], key: 'BACK_TRIP'
135
142
  end
136
143
  end
137
144
  end
@@ -0,0 +1,11 @@
1
+ class Gillbus
2
+ class Carrier
3
+ extend Fields
4
+ include UpdateAttrs
5
+
6
+ field :id, key: 'CARRIER_ID'
7
+ field :name, key: 'CARRIER_NAME'
8
+ field :legal_name, key: 'CARRIER_LEGAL_NAME'
9
+ field :inn
10
+ end
11
+ end
@@ -0,0 +1,19 @@
1
+ class Gillbus
2
+ class Luggage
3
+ extend Fields
4
+
5
+ # => "0"
6
+ field :segment_number, :int
7
+
8
+ # => "true"
9
+ field :is_buy, :bool
10
+
11
+ # => "50.5"
12
+ field :luggage_tariff, :decimal, key: 'BAGGAGE_TARIFF'
13
+
14
+ # => "2"
15
+ field :luggage_limit, :int, key: 'BAGGAGE_LIMIT'
16
+
17
+ field :segments, [Luggage], key: 'SEGMENT'
18
+ end
19
+ end
@@ -0,0 +1,61 @@
1
+ # результаты поиска по соседним городам, берется из кеша и содержит меньше данных, чем поездка из выдачи
2
+ class Gillbus
3
+ class NearbyCitiesTrip
4
+ extend Fields
5
+ include UpdateAttrs
6
+
7
+ # => "Москва"
8
+ field :start_city_name
9
+
10
+ # => "A7CD147C07E7CD1BE040A8C0630328EC"
11
+ field :start_city_guid
12
+
13
+ # => "Europe/Moscow"
14
+ field :start_timezone
15
+
16
+ # => 20
17
+ field :distance_to_start
18
+
19
+ # => "Смоленск"
20
+ field :end_city_name
21
+
22
+ # => "DD253CDEE7D1555EE040B8596052093F"
23
+ field :end_city_guid
24
+
25
+ # => "Europe/Moscow"
26
+ field :end_timezone
27
+
28
+ # => 0
29
+ field :distance_to_end
30
+
31
+ # => "22:50"
32
+ field :start_time, :time # XXX
33
+
34
+ # => "08:00"
35
+ field :end_time, :time # XXX
36
+
37
+ # => ""Автофлот Автоколонна-1601" ООО"
38
+ field :carrier_name # XXX
39
+
40
+ # => "RU "Автофлот Автоколонна-1601" ООО"
41
+ field :carrier_legal_name # XXX
42
+
43
+ # => "390"
44
+ field :time_in_road
45
+
46
+ # => "1100"
47
+ field :total_cost, :money
48
+
49
+ # => "RUB"
50
+ field :currency
51
+
52
+ parser do
53
+ def money(val)
54
+ Monetize.parse(val, doc['CURRENCY'])
55
+ end
56
+ end
57
+
58
+ # to hold unserialized data
59
+ attr_accessor :data
60
+ end
61
+ end
@@ -33,5 +33,7 @@ class Gillbus
33
33
  # Признак наличия пересадки в пункте
34
34
  # => "false"
35
35
  field :transfer_point, :bool
36
+
37
+ field :distance, :int
36
38
  end
37
39
  end
@@ -14,7 +14,7 @@ class Gillbus
14
14
 
15
15
  parser do
16
16
  def money(val)
17
- Monetize.parse(val, doc[:_currency])
17
+ Monetize.parse(val, parent.sale_cur_code)
18
18
  end
19
19
  end
20
20
  end
@@ -24,6 +24,7 @@ class Gillbus
24
24
 
25
25
  field :x, :int
26
26
  field :y, :int
27
+ field :z, :int
27
28
 
28
29
  def free?
29
30
  type == 3 || type == 9
@@ -67,6 +67,24 @@ class Gillbus
67
67
  # => "RU \"ПЕТРОКОМ - АВТО ПЛЮС\" ООО"
68
68
  field :carrier_name
69
69
 
70
+ # => "RU \"Еременчук Е.А.\" ИП"
71
+ field :carrier_legal_name
72
+
73
+ # => "260802027265"
74
+ field :carrier_inn
75
+
76
+ # => "г СНТ Лилия, Московская, Наро-фоминский"
77
+ field :carrier_address_fact
78
+
79
+ # => "г СНТ Лилия, Московская, Наро-фоминский"
80
+ field :carrier_address_leg
81
+
82
+ # => "316265100057314"
83
+ field :carrier_egrul_egis
84
+
85
+ # => "2514411332"
86
+ field :carrier_ogrn
87
+
70
88
  # => "09:10"
71
89
  field :time_in_road, :time
72
90
 
@@ -130,6 +148,15 @@ class Gillbus
130
148
  # => "1100"
131
149
  field :total_cost, :money
132
150
 
151
+ # => "1300"
152
+ field :original_amount, :money
153
+
154
+ # => "200"
155
+ field :discount_value, :money
156
+
157
+ # => "13.57"
158
+ field :discount_percentage
159
+
133
160
  # => "RUB"
134
161
  field :currency
135
162
 
@@ -1,6 +1,8 @@
1
1
  class Gillbus
2
2
  class Tariff
3
3
  class ReturnCause
4
+ LOSSLESS = 'lossless'.freeze
5
+
4
6
  extend Fields
5
7
  include UpdateAttrs
6
8
 
@@ -10,10 +12,13 @@ class Gillbus
10
12
 
11
13
  # rubocop:disable Lint/UnusedMethodArgument
12
14
  def self.parse(doc, instance: nil, parent: nil, options: {})
13
- instance = super
14
- if doc.is_a? Hash
15
+ instance = new
16
+ if doc.is_a?(Array) && doc.size == 2 && doc.first.is_a?(Hash) && doc.last.is_a?(String)
17
+ instance.lossless = doc.first[LOSSLESS] == Parser::TRUE_CONST
18
+ instance.cause = doc.last
19
+ elsif doc.is_a?(Hash) && doc.has_key?('__content__')
20
+ instance.lossless = (doc['lossless'] == 'true')
15
21
  instance.cause = doc['__content__']
16
- instance.lossless = doc['lossless'] == 'true'
17
22
  else
18
23
  instance.cause = doc
19
24
  instance.lossless = false
@@ -1,5 +1,17 @@
1
1
  class Gillbus
2
2
  class Ticket
3
+ STATUS_MAPPING = {
4
+ '0' => :voiding, # ticket in processing, interim status during refund;
5
+ '1' => :reserved, # ticket booked;
6
+ '2' => :ticketed, # ticket sold;
7
+ '3' => :ordered, # the booking, that waiting for the confirmation;
8
+ '4' => :returned, # ticket returned;
9
+ '5' => :canceled, # booking canceled;
10
+ '6' => :voided, # ticket canceled;
11
+ '8' => :booked, # the sale, that waiting for the confirmation;
12
+ 'e' => :ticketing_error, # resource failed to process this ticket;
13
+ }.freeze
14
+
3
15
  extend Fields
4
16
  include UpdateAttrs
5
17
 
@@ -22,8 +34,8 @@ class Gillbus
22
34
  # :ticketed 2 – ticket sold;
23
35
  # :ordered 3 – the booking, that waiting for the confirmation;
24
36
  # :returned 4 – ticket returned;
25
- # :canceled 5 – booking cancelled;
26
- # :voided 6 – ticket cancelled;
37
+ # :canceled 5 – booking canceled;
38
+ # :voided 6 – ticket canceled;
27
39
  # :booked 8 – the sale, that waiting for the confirmation
28
40
  field :ticket_status, :ticket_status
29
41
 
@@ -256,7 +268,7 @@ class Gillbus
256
268
  # Array of commissions only for us (with additional fields)
257
269
  field :all_commissions, [Commission], key: 'COMMISSION', root: 'ALL_COMMISSIONS'
258
270
 
259
- field :return_causes, [:return_cause], key: 'RETURN_CAUSE'
271
+ field :return_causes, [ReturnCause], key: 'RETURN_CAUSE'
260
272
 
261
273
  # Date to pay reserved ticket
262
274
  field :date_to_pay, :datetime
@@ -271,17 +283,22 @@ class Gillbus
271
283
 
272
284
  field :end_at, :datetime_combined, key: 'END'
273
285
 
286
+ field :is_online_refund, :bool
287
+
288
+ field :is_luggage, :bool, key: 'IS_BAGGAGE'
289
+
290
+ # => '3257025789'
291
+ field :supplier_inn
292
+
293
+ # => '"Клен 2" ООО'
294
+ field :supplier_name
295
+
296
+ # => "+79065002926"
297
+ field :supplier_phone
298
+
274
299
  parser do
275
300
  def ticket_status(value)
276
- {
277
- '1' => :reserved, # ticket booked;
278
- '2' => :ticketed, # ticket sold;
279
- '3' => :ordered, # the booking, that waiting for the confirmation;
280
- '4' => :returned, # ticket returned;
281
- '5' => :canceled, # booking cancelled;
282
- '6' => :voided, # ticket cancelled;
283
- '8' => :booked, # the sale, that waiting for the confirmation
284
- }[value]
301
+ ::Gillbus::Ticket::STATUS_MAPPING[value]
285
302
  end
286
303
 
287
304
  def money(val)
@@ -0,0 +1,29 @@
1
+ class Gillbus
2
+ class TicketsOption
3
+ extend Fields
4
+ include UpdateAttrs
5
+
6
+ # идентификатор опции
7
+ field :id, :int, key: 'ID'
8
+
9
+ # текст опции
10
+ field :text, :string, key: :__content__
11
+
12
+ def self.parse(doc, instance: nil, parent: nil, options: {})
13
+ instance = new
14
+ if doc.is_a?(String)
15
+ instance.text = doc
16
+ elsif doc.is_a?(Array)
17
+ raise ArgumentError, "Unable to parse TicketsOption: #{doc.inspect}" unless doc.size == 2
18
+ instance.id = doc.first.fetch('ID').to_i
19
+ instance.text = doc.last
20
+ elsif doc.is_a?(Hash) #legacy data made with MultiXML
21
+ instance.id = doc.fetch('ID')
22
+ instance.text = doc.fetch('__content__')
23
+ else
24
+ raise ArgumentError, "Unable to parse TicketsOption: #{doc.inspect}"
25
+ end
26
+ instance
27
+ end
28
+ end
29
+ end