gillbus 0.17.6 → 0.22.9

Sign up to get free protection for your applications and to get access to all the features.
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