skytab_sandbox_simulator 0.1.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 +7 -0
- data/Gemfile +10 -0
- data/bin/simulate +433 -0
- data/lib/skytab_sandbox_simulator/configuration.rb +205 -0
- data/lib/skytab_sandbox_simulator/data/bar_nightclub/categories.json +9 -0
- data/lib/skytab_sandbox_simulator/data/bar_nightclub/items.json +28 -0
- data/lib/skytab_sandbox_simulator/data/bar_nightclub/tenders.json +19 -0
- data/lib/skytab_sandbox_simulator/data/cafe_bakery/categories.json +9 -0
- data/lib/skytab_sandbox_simulator/data/cafe_bakery/items.json +30 -0
- data/lib/skytab_sandbox_simulator/data/cafe_bakery/tenders.json +17 -0
- data/lib/skytab_sandbox_simulator/data/fine_dining/categories.json +9 -0
- data/lib/skytab_sandbox_simulator/data/fine_dining/items.json +30 -0
- data/lib/skytab_sandbox_simulator/data/fine_dining/tenders.json +18 -0
- data/lib/skytab_sandbox_simulator/data/pizzeria/categories.json +9 -0
- data/lib/skytab_sandbox_simulator/data/pizzeria/items.json +28 -0
- data/lib/skytab_sandbox_simulator/data/pizzeria/tenders.json +18 -0
- data/lib/skytab_sandbox_simulator/data/restaurant/categories.json +44 -0
- data/lib/skytab_sandbox_simulator/data/restaurant/items.json +59 -0
- data/lib/skytab_sandbox_simulator/data/restaurant/tenders.json +22 -0
- data/lib/skytab_sandbox_simulator/database.rb +192 -0
- data/lib/skytab_sandbox_simulator/db/factories/business_types.rb +102 -0
- data/lib/skytab_sandbox_simulator/db/factories/categories.rb +243 -0
- data/lib/skytab_sandbox_simulator/db/factories/items.rb +976 -0
- data/lib/skytab_sandbox_simulator/db/factories/simulated_orders.rb +120 -0
- data/lib/skytab_sandbox_simulator/db/factories/simulated_payments.rb +75 -0
- data/lib/skytab_sandbox_simulator/db/migrate/20260316000000_enable_pgcrypto.rb +7 -0
- data/lib/skytab_sandbox_simulator/db/migrate/20260316000001_create_business_types.rb +18 -0
- data/lib/skytab_sandbox_simulator/db/migrate/20260316000002_create_categories.rb +18 -0
- data/lib/skytab_sandbox_simulator/db/migrate/20260316000003_create_items.rb +23 -0
- data/lib/skytab_sandbox_simulator/db/migrate/20260316000004_create_simulated_orders.rb +35 -0
- data/lib/skytab_sandbox_simulator/db/migrate/20260316000005_create_simulated_payments.rb +26 -0
- data/lib/skytab_sandbox_simulator/db/migrate/20260316000006_create_api_requests.rb +27 -0
- data/lib/skytab_sandbox_simulator/db/migrate/20260316000007_create_daily_summaries.rb +24 -0
- data/lib/skytab_sandbox_simulator/generators/data_loader.rb +125 -0
- data/lib/skytab_sandbox_simulator/generators/entity_generator.rb +107 -0
- data/lib/skytab_sandbox_simulator/generators/order_generator.rb +390 -0
- data/lib/skytab_sandbox_simulator/models/api_request.rb +43 -0
- data/lib/skytab_sandbox_simulator/models/business_type.rb +25 -0
- data/lib/skytab_sandbox_simulator/models/category.rb +17 -0
- data/lib/skytab_sandbox_simulator/models/daily_summary.rb +67 -0
- data/lib/skytab_sandbox_simulator/models/item.rb +32 -0
- data/lib/skytab_sandbox_simulator/models/record.rb +14 -0
- data/lib/skytab_sandbox_simulator/models/simulated_order.rb +40 -0
- data/lib/skytab_sandbox_simulator/models/simulated_payment.rb +28 -0
- data/lib/skytab_sandbox_simulator/seeder.rb +167 -0
- data/lib/skytab_sandbox_simulator/services/base_service.rb +227 -0
- data/lib/skytab_sandbox_simulator/services/skytab/catalog_service.rb +130 -0
- data/lib/skytab_sandbox_simulator/services/skytab/location_service.rb +54 -0
- data/lib/skytab_sandbox_simulator/services/skytab/order_service.rb +139 -0
- data/lib/skytab_sandbox_simulator/services/skytab/payment_service.rb +94 -0
- data/lib/skytab_sandbox_simulator/services/skytab/service_manager.rb +62 -0
- data/lib/skytab_sandbox_simulator/version.rb +5 -0
- data/lib/skytab_sandbox_simulator.rb +45 -0
- metadata +305 -0
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SkytabSandboxSimulator
|
|
4
|
+
module Services
|
|
5
|
+
module Skytab
|
|
6
|
+
# Manages SkyTab tickets (orders/checks) via POS API.
|
|
7
|
+
# GET /pos/v2/{locationId}/tickets
|
|
8
|
+
class OrderService < BaseService
|
|
9
|
+
REVENUE_CLASSES = %w[DINE_IN TAKEOUT DELIVERY BAR CATERING].freeze
|
|
10
|
+
|
|
11
|
+
# Fetch all tickets for the current location
|
|
12
|
+
#
|
|
13
|
+
# @param limit [Integer] Maximum number of tickets to return
|
|
14
|
+
# @param status [String, nil] Filter by status (open, closed)
|
|
15
|
+
# @return [Array<Hash>] Array of ticket objects
|
|
16
|
+
def get_tickets(limit: 50, status: nil)
|
|
17
|
+
logger.info "Fetching tickets..."
|
|
18
|
+
params = { limit: limit }
|
|
19
|
+
params[:status] = status if status
|
|
20
|
+
|
|
21
|
+
response = request(:get, pos_endpoint("tickets"), params: params,
|
|
22
|
+
resource_type: "Ticket")
|
|
23
|
+
tickets = extract_elements(response)
|
|
24
|
+
logger.info "Found #{tickets.size} tickets"
|
|
25
|
+
tickets
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Get a single ticket by ID
|
|
29
|
+
#
|
|
30
|
+
# @param ticket_id [String] Ticket ID
|
|
31
|
+
# @return [Hash, nil] Ticket data
|
|
32
|
+
def get_ticket(ticket_id)
|
|
33
|
+
logger.info "Fetching ticket: #{ticket_id}"
|
|
34
|
+
request(:get, pos_endpoint("tickets/#{ticket_id}"),
|
|
35
|
+
resource_type: "Ticket", resource_id: ticket_id)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Create a new ticket (check/order)
|
|
39
|
+
#
|
|
40
|
+
# @param pos_ref [String, nil] POS reference number
|
|
41
|
+
# @param employee_pos_ref [String, nil] Employee POS reference
|
|
42
|
+
# @param revenue_class [String] Revenue class (DINE_IN, TAKEOUT, etc.)
|
|
43
|
+
# @return [Hash, nil] Created ticket
|
|
44
|
+
def create_ticket(pos_ref: nil, employee_pos_ref: nil, revenue_class: "DINE_IN")
|
|
45
|
+
logger.info "Creating ticket..."
|
|
46
|
+
|
|
47
|
+
payload = {
|
|
48
|
+
"status" => "open",
|
|
49
|
+
"revenueClassPosRef" => revenue_class
|
|
50
|
+
}
|
|
51
|
+
payload["posRef"] = pos_ref if pos_ref
|
|
52
|
+
payload["employeePosRef"] = employee_pos_ref if employee_pos_ref
|
|
53
|
+
|
|
54
|
+
request(:post, pos_endpoint("tickets"), payload: payload,
|
|
55
|
+
resource_type: "Ticket")
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Add an item to a ticket
|
|
59
|
+
#
|
|
60
|
+
# @param ticket_id [String] Ticket ID
|
|
61
|
+
# @param pos_ref [String] Item POS reference
|
|
62
|
+
# @param name [String] Item name
|
|
63
|
+
# @param quantity [Integer] Quantity
|
|
64
|
+
# @param price [Integer] Unit price in cents
|
|
65
|
+
# @return [Hash, nil] Updated ticket
|
|
66
|
+
def add_item_to_ticket(ticket_id, pos_ref:, name:, quantity: 1, price:)
|
|
67
|
+
logger.debug "Adding item #{name} to ticket #{ticket_id}"
|
|
68
|
+
|
|
69
|
+
payload = {
|
|
70
|
+
"items" => [
|
|
71
|
+
{
|
|
72
|
+
"posRef" => pos_ref,
|
|
73
|
+
"name" => name,
|
|
74
|
+
"quantity" => quantity,
|
|
75
|
+
"price" => price,
|
|
76
|
+
"total" => price * quantity
|
|
77
|
+
}
|
|
78
|
+
]
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
request(:put, pos_endpoint("tickets/#{ticket_id}/items"), payload: payload,
|
|
82
|
+
resource_type: "Ticket", resource_id: ticket_id)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Close a ticket (mark as completed)
|
|
86
|
+
#
|
|
87
|
+
# @param ticket_id [String] Ticket ID
|
|
88
|
+
# @param subtotal [Integer] Subtotal in cents
|
|
89
|
+
# @param tax [Integer] Tax amount in cents
|
|
90
|
+
# @param total [Integer] Total in cents
|
|
91
|
+
# @param tip [Integer] Tip amount in cents
|
|
92
|
+
# @return [Hash, nil] Updated ticket
|
|
93
|
+
def close_ticket(ticket_id, subtotal:, tax:, total:, tip: 0)
|
|
94
|
+
logger.info "Closing ticket: #{ticket_id}"
|
|
95
|
+
|
|
96
|
+
payload = {
|
|
97
|
+
"status" => "closed",
|
|
98
|
+
"subtotal" => subtotal,
|
|
99
|
+
"tax" => tax,
|
|
100
|
+
"total" => total,
|
|
101
|
+
"tip" => tip,
|
|
102
|
+
"closedAt" => Time.now.utc.iso8601
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
request(:put, pos_endpoint("tickets/#{ticket_id}"), payload: payload,
|
|
106
|
+
resource_type: "Ticket", resource_id: ticket_id)
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# Delete all tickets (use with caution)
|
|
110
|
+
#
|
|
111
|
+
# @return [Integer] Number of deleted tickets
|
|
112
|
+
def delete_all_tickets
|
|
113
|
+
tickets = get_tickets(limit: 100)
|
|
114
|
+
tickets.each do |ticket|
|
|
115
|
+
request(:delete, pos_endpoint("tickets/#{ticket['id']}"),
|
|
116
|
+
resource_type: "Ticket", resource_id: ticket["id"])
|
|
117
|
+
rescue StandardError => e
|
|
118
|
+
logger.warn "Failed to delete ticket #{ticket['id']}: #{e.message}"
|
|
119
|
+
end
|
|
120
|
+
tickets.size
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
private
|
|
124
|
+
|
|
125
|
+
def extract_elements(response)
|
|
126
|
+
return [] if response.nil?
|
|
127
|
+
|
|
128
|
+
if response.is_a?(Array)
|
|
129
|
+
response
|
|
130
|
+
elsif response.is_a?(Hash)
|
|
131
|
+
response["tickets"] || response["elements"] || []
|
|
132
|
+
else
|
|
133
|
+
[]
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
end
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SkytabSandboxSimulator
|
|
4
|
+
module Services
|
|
5
|
+
module Skytab
|
|
6
|
+
# Manages SkyTab payments on tickets via POS API.
|
|
7
|
+
class PaymentService < BaseService
|
|
8
|
+
# Add a payment to a ticket
|
|
9
|
+
#
|
|
10
|
+
# @param ticket_id [String] Ticket ID
|
|
11
|
+
# @param tender_pos_ref [String] Tender POS reference (CASH, VISA, etc.)
|
|
12
|
+
# @param amount [Integer] Payment amount in cents
|
|
13
|
+
# @param tip [Integer] Tip amount in cents
|
|
14
|
+
# @return [Hash, nil] Payment result
|
|
15
|
+
def add_payment(ticket_id, tender_pos_ref:, amount:, tip: 0)
|
|
16
|
+
logger.info "Adding payment of $#{amount / 100.0} to ticket #{ticket_id}"
|
|
17
|
+
|
|
18
|
+
payload = {
|
|
19
|
+
"payments" => [
|
|
20
|
+
{
|
|
21
|
+
"tenderPosRef" => tender_pos_ref,
|
|
22
|
+
"amount" => amount,
|
|
23
|
+
"tip" => tip,
|
|
24
|
+
"status" => "completed"
|
|
25
|
+
}
|
|
26
|
+
]
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
request(:put, pos_endpoint("tickets/#{ticket_id}/payments"), payload: payload,
|
|
30
|
+
resource_type: "Payment")
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Add a split payment to a ticket (multiple tenders)
|
|
34
|
+
#
|
|
35
|
+
# @param ticket_id [String] Ticket ID
|
|
36
|
+
# @param payments [Array<Hash>] Array of payment hashes with :tender_pos_ref, :amount, :tip
|
|
37
|
+
# @return [Hash, nil] Payment result
|
|
38
|
+
def add_split_payment(ticket_id, payments:)
|
|
39
|
+
logger.info "Adding #{payments.size} split payments to ticket #{ticket_id}"
|
|
40
|
+
|
|
41
|
+
payment_data = payments.map do |p|
|
|
42
|
+
{
|
|
43
|
+
"tenderPosRef" => p[:tender_pos_ref],
|
|
44
|
+
"amount" => p[:amount],
|
|
45
|
+
"tip" => p[:tip] || 0,
|
|
46
|
+
"status" => "completed"
|
|
47
|
+
}
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
payload = { "payments" => payment_data }
|
|
51
|
+
|
|
52
|
+
request(:put, pos_endpoint("tickets/#{ticket_id}/payments"), payload: payload,
|
|
53
|
+
resource_type: "Payment")
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Fetch payments for a ticket
|
|
57
|
+
#
|
|
58
|
+
# @param ticket_id [String] Ticket ID
|
|
59
|
+
# @return [Array<Hash>] Array of payment objects
|
|
60
|
+
def get_payments(ticket_id)
|
|
61
|
+
logger.info "Fetching payments for ticket: #{ticket_id}"
|
|
62
|
+
response = request(:get, pos_endpoint("tickets/#{ticket_id}/payments"),
|
|
63
|
+
resource_type: "Payment")
|
|
64
|
+
|
|
65
|
+
return [] if response.nil?
|
|
66
|
+
|
|
67
|
+
if response.is_a?(Array)
|
|
68
|
+
response
|
|
69
|
+
elsif response.is_a?(Hash)
|
|
70
|
+
response["payments"] || response["elements"] || []
|
|
71
|
+
else
|
|
72
|
+
[]
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Refund a payment
|
|
77
|
+
#
|
|
78
|
+
# @param ticket_id [String] Ticket ID
|
|
79
|
+
# @param payment_id [String] Payment ID to refund
|
|
80
|
+
# @param amount [Integer, nil] Refund amount in cents (nil for full refund)
|
|
81
|
+
# @return [Hash, nil] Refund result
|
|
82
|
+
def refund_payment(ticket_id, payment_id:, amount: nil)
|
|
83
|
+
logger.info "Refunding payment #{payment_id} on ticket #{ticket_id}"
|
|
84
|
+
|
|
85
|
+
payload = { "paymentId" => payment_id }
|
|
86
|
+
payload["amount"] = amount if amount
|
|
87
|
+
|
|
88
|
+
request(:post, pos_endpoint("tickets/#{ticket_id}/refunds"), payload: payload,
|
|
89
|
+
resource_type: "Refund")
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SkytabSandboxSimulator
|
|
4
|
+
module Services
|
|
5
|
+
module Skytab
|
|
6
|
+
# Central manager for all SkyTab services.
|
|
7
|
+
# Provides thread-safe, lazy-loaded access to all service classes.
|
|
8
|
+
class ServiceManager
|
|
9
|
+
attr_reader :config
|
|
10
|
+
|
|
11
|
+
def initialize(config: nil)
|
|
12
|
+
@config = config || SkytabSandboxSimulator.configuration
|
|
13
|
+
@mutex = Mutex.new
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def location
|
|
17
|
+
thread_safe_memoize(:@location) { LocationService.new(config: config) }
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def catalog
|
|
21
|
+
thread_safe_memoize(:@catalog) { CatalogService.new(config: config) }
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def order
|
|
25
|
+
thread_safe_memoize(:@order) { OrderService.new(config: config) }
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def payment
|
|
29
|
+
thread_safe_memoize(:@payment) { PaymentService.new(config: config) }
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Clear all cached service instances
|
|
33
|
+
def clear_services
|
|
34
|
+
@mutex.synchronize do
|
|
35
|
+
instance_variables.each do |var|
|
|
36
|
+
next if var == :@config || var == :@mutex
|
|
37
|
+
|
|
38
|
+
instance_variable_set(var, nil)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
private
|
|
44
|
+
|
|
45
|
+
# Thread-safe memoization pattern
|
|
46
|
+
def thread_safe_memoize(ivar_name)
|
|
47
|
+
value = instance_variable_get(ivar_name)
|
|
48
|
+
return value if value
|
|
49
|
+
|
|
50
|
+
@mutex.synchronize do
|
|
51
|
+
value = instance_variable_get(ivar_name)
|
|
52
|
+
return value if value
|
|
53
|
+
|
|
54
|
+
value = yield
|
|
55
|
+
instance_variable_set(ivar_name, value)
|
|
56
|
+
value
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "zeitwerk"
|
|
4
|
+
require "logger"
|
|
5
|
+
require "json"
|
|
6
|
+
require "rest-client"
|
|
7
|
+
require "dotenv"
|
|
8
|
+
|
|
9
|
+
# Load environment variables
|
|
10
|
+
Dotenv.load
|
|
11
|
+
|
|
12
|
+
module SkytabSandboxSimulator
|
|
13
|
+
class Error < StandardError; end
|
|
14
|
+
class ConfigurationError < Error; end
|
|
15
|
+
class ApiError < Error; end
|
|
16
|
+
|
|
17
|
+
class << self
|
|
18
|
+
attr_writer :configuration
|
|
19
|
+
|
|
20
|
+
def configuration
|
|
21
|
+
@configuration ||= Configuration.new
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def configure
|
|
25
|
+
yield(configuration)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def logger
|
|
29
|
+
configuration.logger
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def root
|
|
33
|
+
File.expand_path("..", __dir__)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Set up Zeitwerk autoloader
|
|
39
|
+
loader = Zeitwerk::Loader.for_gem
|
|
40
|
+
# Migrations and factories follow ActiveRecord conventions, not Zeitwerk naming
|
|
41
|
+
loader.ignore(File.expand_path("skytab_sandbox_simulator/db", __dir__))
|
|
42
|
+
loader.setup
|
|
43
|
+
|
|
44
|
+
# Eager load in production
|
|
45
|
+
loader.eager_load if ENV["RACK_ENV"] == "production"
|
metadata
ADDED
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: skytab_sandbox_simulator
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- TheOwnerStack
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: activerecord
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - "~>"
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '8.0'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - "~>"
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '8.0'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: concurrent-ruby
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - "~>"
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '1.2'
|
|
33
|
+
type: :runtime
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - "~>"
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '1.2'
|
|
40
|
+
- !ruby/object:Gem::Dependency
|
|
41
|
+
name: dotenv
|
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
|
43
|
+
requirements:
|
|
44
|
+
- - "~>"
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: '3.0'
|
|
47
|
+
type: :runtime
|
|
48
|
+
prerelease: false
|
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - "~>"
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: '3.0'
|
|
54
|
+
- !ruby/object:Gem::Dependency
|
|
55
|
+
name: factory_bot
|
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
|
57
|
+
requirements:
|
|
58
|
+
- - "~>"
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: '6.4'
|
|
61
|
+
type: :runtime
|
|
62
|
+
prerelease: false
|
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
65
|
+
- - "~>"
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
version: '6.4'
|
|
68
|
+
- !ruby/object:Gem::Dependency
|
|
69
|
+
name: faker
|
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
|
71
|
+
requirements:
|
|
72
|
+
- - "~>"
|
|
73
|
+
- !ruby/object:Gem::Version
|
|
74
|
+
version: '3.2'
|
|
75
|
+
type: :runtime
|
|
76
|
+
prerelease: false
|
|
77
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
78
|
+
requirements:
|
|
79
|
+
- - "~>"
|
|
80
|
+
- !ruby/object:Gem::Version
|
|
81
|
+
version: '3.2'
|
|
82
|
+
- !ruby/object:Gem::Dependency
|
|
83
|
+
name: pg
|
|
84
|
+
requirement: !ruby/object:Gem::Requirement
|
|
85
|
+
requirements:
|
|
86
|
+
- - "~>"
|
|
87
|
+
- !ruby/object:Gem::Version
|
|
88
|
+
version: '1.5'
|
|
89
|
+
type: :runtime
|
|
90
|
+
prerelease: false
|
|
91
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
92
|
+
requirements:
|
|
93
|
+
- - "~>"
|
|
94
|
+
- !ruby/object:Gem::Version
|
|
95
|
+
version: '1.5'
|
|
96
|
+
- !ruby/object:Gem::Dependency
|
|
97
|
+
name: rest-client
|
|
98
|
+
requirement: !ruby/object:Gem::Requirement
|
|
99
|
+
requirements:
|
|
100
|
+
- - "~>"
|
|
101
|
+
- !ruby/object:Gem::Version
|
|
102
|
+
version: '2.1'
|
|
103
|
+
type: :runtime
|
|
104
|
+
prerelease: false
|
|
105
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
106
|
+
requirements:
|
|
107
|
+
- - "~>"
|
|
108
|
+
- !ruby/object:Gem::Version
|
|
109
|
+
version: '2.1'
|
|
110
|
+
- !ruby/object:Gem::Dependency
|
|
111
|
+
name: thor
|
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
|
113
|
+
requirements:
|
|
114
|
+
- - "~>"
|
|
115
|
+
- !ruby/object:Gem::Version
|
|
116
|
+
version: '1.3'
|
|
117
|
+
type: :runtime
|
|
118
|
+
prerelease: false
|
|
119
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
120
|
+
requirements:
|
|
121
|
+
- - "~>"
|
|
122
|
+
- !ruby/object:Gem::Version
|
|
123
|
+
version: '1.3'
|
|
124
|
+
- !ruby/object:Gem::Dependency
|
|
125
|
+
name: tzinfo
|
|
126
|
+
requirement: !ruby/object:Gem::Requirement
|
|
127
|
+
requirements:
|
|
128
|
+
- - "~>"
|
|
129
|
+
- !ruby/object:Gem::Version
|
|
130
|
+
version: '2.0'
|
|
131
|
+
type: :runtime
|
|
132
|
+
prerelease: false
|
|
133
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
134
|
+
requirements:
|
|
135
|
+
- - "~>"
|
|
136
|
+
- !ruby/object:Gem::Version
|
|
137
|
+
version: '2.0'
|
|
138
|
+
- !ruby/object:Gem::Dependency
|
|
139
|
+
name: zeitwerk
|
|
140
|
+
requirement: !ruby/object:Gem::Requirement
|
|
141
|
+
requirements:
|
|
142
|
+
- - "~>"
|
|
143
|
+
- !ruby/object:Gem::Version
|
|
144
|
+
version: '2.6'
|
|
145
|
+
type: :runtime
|
|
146
|
+
prerelease: false
|
|
147
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
148
|
+
requirements:
|
|
149
|
+
- - "~>"
|
|
150
|
+
- !ruby/object:Gem::Version
|
|
151
|
+
version: '2.6'
|
|
152
|
+
- !ruby/object:Gem::Dependency
|
|
153
|
+
name: database_cleaner-active_record
|
|
154
|
+
requirement: !ruby/object:Gem::Requirement
|
|
155
|
+
requirements:
|
|
156
|
+
- - "~>"
|
|
157
|
+
- !ruby/object:Gem::Version
|
|
158
|
+
version: '2.1'
|
|
159
|
+
type: :development
|
|
160
|
+
prerelease: false
|
|
161
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
162
|
+
requirements:
|
|
163
|
+
- - "~>"
|
|
164
|
+
- !ruby/object:Gem::Version
|
|
165
|
+
version: '2.1'
|
|
166
|
+
- !ruby/object:Gem::Dependency
|
|
167
|
+
name: rspec
|
|
168
|
+
requirement: !ruby/object:Gem::Requirement
|
|
169
|
+
requirements:
|
|
170
|
+
- - "~>"
|
|
171
|
+
- !ruby/object:Gem::Version
|
|
172
|
+
version: '3.12'
|
|
173
|
+
type: :development
|
|
174
|
+
prerelease: false
|
|
175
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
176
|
+
requirements:
|
|
177
|
+
- - "~>"
|
|
178
|
+
- !ruby/object:Gem::Version
|
|
179
|
+
version: '3.12'
|
|
180
|
+
- !ruby/object:Gem::Dependency
|
|
181
|
+
name: rubocop
|
|
182
|
+
requirement: !ruby/object:Gem::Requirement
|
|
183
|
+
requirements:
|
|
184
|
+
- - "~>"
|
|
185
|
+
- !ruby/object:Gem::Version
|
|
186
|
+
version: '1.50'
|
|
187
|
+
type: :development
|
|
188
|
+
prerelease: false
|
|
189
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
190
|
+
requirements:
|
|
191
|
+
- - "~>"
|
|
192
|
+
- !ruby/object:Gem::Version
|
|
193
|
+
version: '1.50'
|
|
194
|
+
- !ruby/object:Gem::Dependency
|
|
195
|
+
name: vcr
|
|
196
|
+
requirement: !ruby/object:Gem::Requirement
|
|
197
|
+
requirements:
|
|
198
|
+
- - "~>"
|
|
199
|
+
- !ruby/object:Gem::Version
|
|
200
|
+
version: '6.1'
|
|
201
|
+
type: :development
|
|
202
|
+
prerelease: false
|
|
203
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
204
|
+
requirements:
|
|
205
|
+
- - "~>"
|
|
206
|
+
- !ruby/object:Gem::Version
|
|
207
|
+
version: '6.1'
|
|
208
|
+
- !ruby/object:Gem::Dependency
|
|
209
|
+
name: webmock
|
|
210
|
+
requirement: !ruby/object:Gem::Requirement
|
|
211
|
+
requirements:
|
|
212
|
+
- - "~>"
|
|
213
|
+
- !ruby/object:Gem::Version
|
|
214
|
+
version: '3.18'
|
|
215
|
+
type: :development
|
|
216
|
+
prerelease: false
|
|
217
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
218
|
+
requirements:
|
|
219
|
+
- - "~>"
|
|
220
|
+
- !ruby/object:Gem::Version
|
|
221
|
+
version: '3.18'
|
|
222
|
+
description: A Ruby gem for simulating Point of Sale operations in SkyTab (Shift4)
|
|
223
|
+
sandbox environments. Generates realistic restaurant orders, payments, and transaction
|
|
224
|
+
data for testing integrations with the Shift4 Marketplace API.
|
|
225
|
+
email:
|
|
226
|
+
- support@salestobooks.com
|
|
227
|
+
executables:
|
|
228
|
+
- simulate
|
|
229
|
+
extensions: []
|
|
230
|
+
extra_rdoc_files: []
|
|
231
|
+
files:
|
|
232
|
+
- Gemfile
|
|
233
|
+
- bin/simulate
|
|
234
|
+
- lib/skytab_sandbox_simulator.rb
|
|
235
|
+
- lib/skytab_sandbox_simulator/configuration.rb
|
|
236
|
+
- lib/skytab_sandbox_simulator/data/bar_nightclub/categories.json
|
|
237
|
+
- lib/skytab_sandbox_simulator/data/bar_nightclub/items.json
|
|
238
|
+
- lib/skytab_sandbox_simulator/data/bar_nightclub/tenders.json
|
|
239
|
+
- lib/skytab_sandbox_simulator/data/cafe_bakery/categories.json
|
|
240
|
+
- lib/skytab_sandbox_simulator/data/cafe_bakery/items.json
|
|
241
|
+
- lib/skytab_sandbox_simulator/data/cafe_bakery/tenders.json
|
|
242
|
+
- lib/skytab_sandbox_simulator/data/fine_dining/categories.json
|
|
243
|
+
- lib/skytab_sandbox_simulator/data/fine_dining/items.json
|
|
244
|
+
- lib/skytab_sandbox_simulator/data/fine_dining/tenders.json
|
|
245
|
+
- lib/skytab_sandbox_simulator/data/pizzeria/categories.json
|
|
246
|
+
- lib/skytab_sandbox_simulator/data/pizzeria/items.json
|
|
247
|
+
- lib/skytab_sandbox_simulator/data/pizzeria/tenders.json
|
|
248
|
+
- lib/skytab_sandbox_simulator/data/restaurant/categories.json
|
|
249
|
+
- lib/skytab_sandbox_simulator/data/restaurant/items.json
|
|
250
|
+
- lib/skytab_sandbox_simulator/data/restaurant/tenders.json
|
|
251
|
+
- lib/skytab_sandbox_simulator/database.rb
|
|
252
|
+
- lib/skytab_sandbox_simulator/db/factories/business_types.rb
|
|
253
|
+
- lib/skytab_sandbox_simulator/db/factories/categories.rb
|
|
254
|
+
- lib/skytab_sandbox_simulator/db/factories/items.rb
|
|
255
|
+
- lib/skytab_sandbox_simulator/db/factories/simulated_orders.rb
|
|
256
|
+
- lib/skytab_sandbox_simulator/db/factories/simulated_payments.rb
|
|
257
|
+
- lib/skytab_sandbox_simulator/db/migrate/20260316000000_enable_pgcrypto.rb
|
|
258
|
+
- lib/skytab_sandbox_simulator/db/migrate/20260316000001_create_business_types.rb
|
|
259
|
+
- lib/skytab_sandbox_simulator/db/migrate/20260316000002_create_categories.rb
|
|
260
|
+
- lib/skytab_sandbox_simulator/db/migrate/20260316000003_create_items.rb
|
|
261
|
+
- lib/skytab_sandbox_simulator/db/migrate/20260316000004_create_simulated_orders.rb
|
|
262
|
+
- lib/skytab_sandbox_simulator/db/migrate/20260316000005_create_simulated_payments.rb
|
|
263
|
+
- lib/skytab_sandbox_simulator/db/migrate/20260316000006_create_api_requests.rb
|
|
264
|
+
- lib/skytab_sandbox_simulator/db/migrate/20260316000007_create_daily_summaries.rb
|
|
265
|
+
- lib/skytab_sandbox_simulator/generators/data_loader.rb
|
|
266
|
+
- lib/skytab_sandbox_simulator/generators/entity_generator.rb
|
|
267
|
+
- lib/skytab_sandbox_simulator/generators/order_generator.rb
|
|
268
|
+
- lib/skytab_sandbox_simulator/models/api_request.rb
|
|
269
|
+
- lib/skytab_sandbox_simulator/models/business_type.rb
|
|
270
|
+
- lib/skytab_sandbox_simulator/models/category.rb
|
|
271
|
+
- lib/skytab_sandbox_simulator/models/daily_summary.rb
|
|
272
|
+
- lib/skytab_sandbox_simulator/models/item.rb
|
|
273
|
+
- lib/skytab_sandbox_simulator/models/record.rb
|
|
274
|
+
- lib/skytab_sandbox_simulator/models/simulated_order.rb
|
|
275
|
+
- lib/skytab_sandbox_simulator/models/simulated_payment.rb
|
|
276
|
+
- lib/skytab_sandbox_simulator/seeder.rb
|
|
277
|
+
- lib/skytab_sandbox_simulator/services/base_service.rb
|
|
278
|
+
- lib/skytab_sandbox_simulator/services/skytab/catalog_service.rb
|
|
279
|
+
- lib/skytab_sandbox_simulator/services/skytab/location_service.rb
|
|
280
|
+
- lib/skytab_sandbox_simulator/services/skytab/order_service.rb
|
|
281
|
+
- lib/skytab_sandbox_simulator/services/skytab/payment_service.rb
|
|
282
|
+
- lib/skytab_sandbox_simulator/services/skytab/service_manager.rb
|
|
283
|
+
- lib/skytab_sandbox_simulator/version.rb
|
|
284
|
+
homepage: https://github.com/dan1d/skytab_sandbox_simulator
|
|
285
|
+
licenses:
|
|
286
|
+
- MIT
|
|
287
|
+
metadata: {}
|
|
288
|
+
rdoc_options: []
|
|
289
|
+
require_paths:
|
|
290
|
+
- lib
|
|
291
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
292
|
+
requirements:
|
|
293
|
+
- - ">="
|
|
294
|
+
- !ruby/object:Gem::Version
|
|
295
|
+
version: 3.0.0
|
|
296
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
297
|
+
requirements:
|
|
298
|
+
- - ">="
|
|
299
|
+
- !ruby/object:Gem::Version
|
|
300
|
+
version: '0'
|
|
301
|
+
requirements: []
|
|
302
|
+
rubygems_version: 3.6.9
|
|
303
|
+
specification_version: 4
|
|
304
|
+
summary: SkyTab (Shift4) POS sandbox simulator for SalesToBooks integration testing
|
|
305
|
+
test_files: []
|