Class: SpreeCmCommissioner::Integrations::VireakBuntham::Polling::SyncItemAvailability

Inherits:
Object
  • Object
show all
Includes:
InventorySyncCachable
Defined in:
app/services/spree_cm_commissioner/integrations/vireak_buntham/polling/sync_item_availability.rb

Overview

SyncItemAvailability — refresh price + reserved seats for a trip on a date.

Wired end-to-end so the integration’s ‘sync_item_availability!` contract is callable. Steps:

  1. Look up the trip + inventory items for the date.

  2. POST /schedule/list — resolve effective local + foreigner prices via Resources::Schedule#effective_local_price / #effective_foreigner_price.

  3. Update each inventory_item’s USD price to the effective local price.

  4. Delegate the foreigner delta to SyncNationalityPricing

  5. POST /seat/unavailable — upsert ReservedBlock records to mirror VET’s occupied seats, removing stale ones.

  6. Touch the inventory mapping’s last_synced_at.

Idempotent: every step is a find-or-update; no destructive writes other than removing reserved blocks that VET no longer reports as occupied.

Instance Method Summary collapse

Methods included from InventorySyncCachable

#sync_cache_ttl

Constructor Details

#initialize(integration:, sync_result: nil) ⇒ SyncItemAvailability

Returns a new instance of SyncItemAvailability.



21
22
23
24
# File 'app/services/spree_cm_commissioner/integrations/vireak_buntham/polling/sync_item_availability.rb', line 21

def initialize(integration:, sync_result: nil)
  @integration = integration
  @sync_result = sync_result || SpreeCmCommissioner::Integrations::Base::SyncResult.new
end

Instance Method Details

#call(trip_id:, on_date:) ⇒ Object

Entry point: fetch trip and inventory items for a date, then sync prices and reserved seats. Returns SyncResult with tracking of all changes and API calls.



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'app/services/spree_cm_commissioner/integrations/vireak_buntham/polling/sync_item_availability.rb', line 28

def call(trip_id:, on_date:) # rubocop:disable Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
  trip_mapping = find_trip_mapping(trip_id)
  trip = trip_mapping&.internal || SpreeCmCommissioner::Trip.find_by(id: trip_id)
  return @sync_result unless trip

  inventory_items = inventory_items_for(trip, on_date)
  return @sync_result if inventory_items.empty?

  schedule = fetch_schedule(trip, trip_mapping&.external_payload&.dig('id'))

  inventory_items.each do |inventory_item|
    sync_item(trip, on_date, inventory_item, schedule, trip_mapping&.external_payload&.dig('id'))
  end

  @sync_result.last_synced_at =
    inventory_items.last
                   &.integration_mappings
                   &.maximum(:last_synced_at)
  @sync_result
rescue StandardError => e
  @sync_result.record_error(e)
  CmAppLogger.error(label: '[VireakBuntham::SyncItemAvailability] sync failed', data: { error: e.message })
  @sync_result
end

#sync_item(trip, on_date, inventory_item, schedule, trip_external_id) ⇒ Object

Sync single inventory item: update USD price from VET schedule and sync reserved seats from API. Wrapped in transaction to ensure atomic updates; errors are logged but do not halt processing.



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'app/services/spree_cm_commissioner/integrations/vireak_buntham/polling/sync_item_availability.rb', line 55

def sync_item(trip, on_date, inventory_item, schedule, trip_external_id)
  inventory_item_mapping = find_or_initialize_item_mapping(inventory_item)

  return unless should_sync_item?(inventory_item_mapping)

  ActiveRecord::Base.transaction do
    sync_price(trip, on_date, inventory_item, inventory_item_mapping, schedule) if schedule
    sync_reserved_blocks(trip, on_date, inventory_item, trip_external_id) if trip.allow_seat_selection?
    update_last_sync_at(inventory_item_mapping)
  end
rescue StandardError => e
  @sync_result.record_error(e)
  CmAppLogger.error(label: '[VireakBuntham::SyncItemAvailability] error syncing item',
                    data: { inventory_item_id: inventory_item.id, error: e.message }
                   )
end