epos_now_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.
Files changed (52) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +10 -0
  3. data/LICENSE +21 -0
  4. data/README.md +380 -0
  5. data/bin/simulate +309 -0
  6. data/lib/epos_now_sandbox_simulator/configuration.rb +173 -0
  7. data/lib/epos_now_sandbox_simulator/data/bar_nightclub/categories.json +9 -0
  8. data/lib/epos_now_sandbox_simulator/data/bar_nightclub/items.json +26 -0
  9. data/lib/epos_now_sandbox_simulator/data/bar_nightclub/tenders.json +8 -0
  10. data/lib/epos_now_sandbox_simulator/data/cafe_bakery/categories.json +9 -0
  11. data/lib/epos_now_sandbox_simulator/data/cafe_bakery/items.json +28 -0
  12. data/lib/epos_now_sandbox_simulator/data/cafe_bakery/tenders.json +8 -0
  13. data/lib/epos_now_sandbox_simulator/data/restaurant/categories.json +9 -0
  14. data/lib/epos_now_sandbox_simulator/data/restaurant/items.json +29 -0
  15. data/lib/epos_now_sandbox_simulator/data/restaurant/tenders.json +9 -0
  16. data/lib/epos_now_sandbox_simulator/data/retail_general/categories.json +9 -0
  17. data/lib/epos_now_sandbox_simulator/data/retail_general/items.json +17 -0
  18. data/lib/epos_now_sandbox_simulator/data/retail_general/tenders.json +8 -0
  19. data/lib/epos_now_sandbox_simulator/database.rb +136 -0
  20. data/lib/epos_now_sandbox_simulator/db/factories/api_requests.rb +13 -0
  21. data/lib/epos_now_sandbox_simulator/db/factories/business_types.rb +34 -0
  22. data/lib/epos_now_sandbox_simulator/db/factories/categories.rb +10 -0
  23. data/lib/epos_now_sandbox_simulator/db/factories/items.rb +12 -0
  24. data/lib/epos_now_sandbox_simulator/db/factories/simulated_orders.rb +25 -0
  25. data/lib/epos_now_sandbox_simulator/db/factories/simulated_payments.rb +14 -0
  26. data/lib/epos_now_sandbox_simulator/db/migrate/20260312000001_enable_pgcrypto.rb +7 -0
  27. data/lib/epos_now_sandbox_simulator/db/migrate/20260312000002_create_business_types.rb +16 -0
  28. data/lib/epos_now_sandbox_simulator/db/migrate/20260312000003_create_categories.rb +16 -0
  29. data/lib/epos_now_sandbox_simulator/db/migrate/20260312000004_create_items.rb +19 -0
  30. data/lib/epos_now_sandbox_simulator/db/migrate/20260312000005_create_simulated_orders.rb +27 -0
  31. data/lib/epos_now_sandbox_simulator/db/migrate/20260312000006_create_simulated_payments.rb +22 -0
  32. data/lib/epos_now_sandbox_simulator/db/migrate/20260312000007_create_api_requests.rb +22 -0
  33. data/lib/epos_now_sandbox_simulator/db/migrate/20260312000008_create_daily_summaries.rb +21 -0
  34. data/lib/epos_now_sandbox_simulator/generators/data_loader.rb +100 -0
  35. data/lib/epos_now_sandbox_simulator/generators/entity_generator.rb +103 -0
  36. data/lib/epos_now_sandbox_simulator/generators/order_generator.rb +336 -0
  37. data/lib/epos_now_sandbox_simulator/models/api_request.rb +16 -0
  38. data/lib/epos_now_sandbox_simulator/models/business_type.rb +16 -0
  39. data/lib/epos_now_sandbox_simulator/models/category.rb +18 -0
  40. data/lib/epos_now_sandbox_simulator/models/daily_summary.rb +43 -0
  41. data/lib/epos_now_sandbox_simulator/models/item.rb +20 -0
  42. data/lib/epos_now_sandbox_simulator/models/simulated_order.rb +21 -0
  43. data/lib/epos_now_sandbox_simulator/models/simulated_payment.rb +17 -0
  44. data/lib/epos_now_sandbox_simulator/seeder.rb +119 -0
  45. data/lib/epos_now_sandbox_simulator/services/base_service.rb +248 -0
  46. data/lib/epos_now_sandbox_simulator/services/epos_now/inventory_service.rb +178 -0
  47. data/lib/epos_now_sandbox_simulator/services/epos_now/services_manager.rb +56 -0
  48. data/lib/epos_now_sandbox_simulator/services/epos_now/tax_service.rb +45 -0
  49. data/lib/epos_now_sandbox_simulator/services/epos_now/tender_service.rb +90 -0
  50. data/lib/epos_now_sandbox_simulator/services/epos_now/transaction_service.rb +171 -0
  51. data/lib/epos_now_sandbox_simulator.rb +49 -0
  52. metadata +334 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 9c002c6a16bcabbcb0990831de0d1e8d15552a3e80566fe6292c6d8527bae7d2
4
+ data.tar.gz: 84f4629f641c1866946d1d89e059d0f61dbc61b4786311947b12ef9aca70f8f2
5
+ SHA512:
6
+ metadata.gz: 30c77ce78d45989b8a83e103d90a7e4ebd935f550a67fb33c7fc6075761dec75a697f889f6bf6ffb2213979b590a2078d521d5e2f713d70923fa01fd4e2e274f
7
+ data.tar.gz: d69aa19872de25022289746b4df68ff4a48438c7f8fc1521a2b1fd5c87df1778e3d8c93df1a3ebfd954ab135a58057912f9655c05e1dec0ba96e04a41e531866
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gemspec
6
+
7
+ group :development, :test do
8
+ gem "pry", "~> 0.14"
9
+ gem "pry-byebug", "~> 3.10"
10
+ end
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 dan1d
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,380 @@
1
+ # Epos Now Sandbox Simulator
2
+
3
+ A Ruby gem for simulating Point of Sale operations against the **Epos Now V4 REST API**. Generates realistic restaurant, cafe, bar, and retail orders with payments and transaction data for testing integrations.
4
+
5
+ ## Features
6
+
7
+ - **4 Business Types**: Restaurant, Cafe/Bakery, Bar/Nightclub, Retail General — each with tailored categories and items
8
+ - **84 Menu/Product Items**: Spread across 20 categories with realistic pricing
9
+ - **V4 Transactions**: Single POST with embedded `TransactionItems[]` and `Tenders[]`
10
+ - **Basic Auth**: API Key + Secret authentication (no OAuth, no token refresh)
11
+ - **Meal Period Simulation**: Orders distributed across breakfast, lunch, happy hour, dinner, and late night
12
+ - **Order Types**: Eat-in (`ServiceType: 0`), Takeaway (`1`), and Delivery (`2`)
13
+ - **Dynamic Order Volume**: 40–120 orders/day based on day of week
14
+ - **Tips & Taxes**: Variable tip rates by dining option (15–25% eat-in, 0–15% takeaway, 10–20% delivery)
15
+ - **Discounts**: 10–20% applied probabilistically (8% chance per order)
16
+ - **Multiple Payment Methods**: Cash, Credit Card, Debit Card, Gift Card, Mobile Pay — weighted selection
17
+ - **PostgreSQL Audit Trail**: Track all simulated orders, payments, and API requests
18
+ - **Daily Summaries**: Automated aggregation of revenue, tax, tips, and discounts by meal period and tender
19
+ - **Multi-Device Support**: Configure multiple API devices via `.env.json`
20
+ - **Database Seeding**: Idempotent FactoryBot-based seeder for all 4 business types
21
+
22
+ ## Installation
23
+
24
+ Add to your Gemfile:
25
+
26
+ ```ruby
27
+ gem "epos_now_sandbox_simulator"
28
+ ```
29
+
30
+ Then:
31
+
32
+ ```bash
33
+ bundle install
34
+ ```
35
+
36
+ Or install directly:
37
+
38
+ ```bash
39
+ gem install epos_now_sandbox_simulator
40
+ ```
41
+
42
+ ## Configuration
43
+
44
+ ### Getting API Credentials
45
+
46
+ 1. Log in to your **Epos Now Backoffice** at https://eposnowhq.com
47
+ 2. Register an **API Device** under Settings
48
+ 3. Copy the **API Key** and **API Secret**
49
+ 4. The auth token is `Base64(api_key:api_secret)` — the simulator handles this automatically
50
+
51
+ ### Multi-Device Setup (Recommended)
52
+
53
+ Create a `.env.json` file:
54
+
55
+ ```json
56
+ {
57
+ "DATABASE_URL": "postgres://localhost:5432/epos_now_simulator_development",
58
+ "merchants": [
59
+ {
60
+ "EPOS_NOW_API_KEY": "your-api-key",
61
+ "EPOS_NOW_API_SECRET": "your-api-secret",
62
+ "EPOS_NOW_DEVICE_NAME": "Restaurant Device"
63
+ },
64
+ {
65
+ "EPOS_NOW_API_KEY": "second-device-key",
66
+ "EPOS_NOW_API_SECRET": "second-device-secret",
67
+ "EPOS_NOW_DEVICE_NAME": "Cafe Device"
68
+ }
69
+ ]
70
+ }
71
+ ```
72
+
73
+ ### Single Device Setup
74
+
75
+ Use a `.env` file:
76
+
77
+ ```env
78
+ EPOS_NOW_API_KEY=your-api-key
79
+ EPOS_NOW_API_SECRET=your-api-secret
80
+ EPOS_NOW_BASE_URL=https://api.eposnowhq.com
81
+ LOG_LEVEL=INFO
82
+ TAX_RATE=20.0
83
+ ```
84
+
85
+ ### Database Setup
86
+
87
+ The simulator uses PostgreSQL to persist audit data (simulated orders, payments, API requests, daily summaries):
88
+
89
+ ```bash
90
+ ./bin/simulate db create
91
+ ./bin/simulate db migrate
92
+ ./bin/simulate db seed
93
+ ```
94
+
95
+ ## Usage
96
+
97
+ ### Quick Start
98
+
99
+ ```bash
100
+ # Full setup + order generation in one command
101
+ ./bin/simulate full
102
+ ```
103
+
104
+ ### Commands
105
+
106
+ ```bash
107
+ # Show version
108
+ ./bin/simulate version
109
+
110
+ # List configured API devices
111
+ ./bin/simulate merchants
112
+
113
+ # Set up POS entities (categories, products, tender types)
114
+ ./bin/simulate setup
115
+
116
+ # Generate orders for today (random count based on day of week)
117
+ ./bin/simulate generate
118
+
119
+ # Generate a specific number of orders
120
+ ./bin/simulate generate -n 25
121
+
122
+ # Generate orders with refunds (5% of orders refunded)
123
+ ./bin/simulate generate -n 25 -r 10
124
+
125
+ # Generate a realistic full day of operations
126
+ ./bin/simulate day
127
+
128
+ # Busy day (2x normal volume)
129
+ ./bin/simulate day -x 2.0
130
+
131
+ # Slow day (half volume)
132
+ ./bin/simulate day -x 0.5
133
+
134
+ # Generate a lunch or dinner rush
135
+ ./bin/simulate rush -p lunch -n 20
136
+ ./bin/simulate rush -p dinner -n 30
137
+
138
+ # Check current entity counts
139
+ ./bin/simulate status
140
+
141
+ # Use a specific device by index
142
+ ./bin/simulate setup -i 0
143
+ ./bin/simulate generate -i 1 -n 20
144
+
145
+ # List available business types
146
+ ./bin/simulate business_types
147
+ ```
148
+
149
+ ### Database Management
150
+
151
+ ```bash
152
+ ./bin/simulate db create # Create PostgreSQL database
153
+ ./bin/simulate db migrate # Run pending migrations
154
+ ./bin/simulate db seed # Seed business types, categories, items
155
+ ./bin/simulate db reset # Drop, create, migrate, and seed
156
+
157
+ # Reporting
158
+ ./bin/simulate summary # Show daily summary
159
+ ./bin/simulate audit # Show recent API requests
160
+ ```
161
+
162
+ ## Business Types
163
+
164
+ | Type | Categories | Items | Description |
165
+ |------|-----------|-------|-------------|
166
+ | `restaurant` | 5 | 25 | Full-service casual dining |
167
+ | `cafe_bakery` | 5 | 24 | Coffee shop with pastries and light fare |
168
+ | `bar_nightclub` | 5 | 22 | Craft cocktails, draft beer, late-night bites |
169
+ | `retail_general` | 5 | 13 | Electronics, home goods, personal care |
170
+
171
+ ## Epos Now V4 API Endpoints
172
+
173
+ | Endpoint | Operations |
174
+ |----------|-----------|
175
+ | `/api/v4/Category` | CRUD for product categories |
176
+ | `/api/v4/Product` | CRUD for products/items |
177
+ | `/api/v4/TenderType` | CRUD for payment method types |
178
+ | `/api/v4/Transaction` | Create with embedded items + tenders |
179
+ | `/api/v4/Transaction/GetByDate` | Fetch transactions by date range |
180
+ | `/api/v4/Transaction/GetLatest` | Fetch most recent transactions |
181
+ | `/api/v4/Transaction/Validate` | Validate a transaction before commit |
182
+ | `/api/v4/TaxGroup` | Tax group and rate management |
183
+
184
+ ### Key Differences from Clover/Square
185
+
186
+ | Feature | Epos Now V4 | Clover | Square |
187
+ |---------|------------|--------|--------|
188
+ | Auth | Basic Auth (static) | OAuth2 Bearer | OAuth2 Bearer |
189
+ | Transactions | Single POST with embedded items + tenders | Separate order, line items, payment calls | Single order with line items |
190
+ | Order Types | `ServiceType`: 0=EatIn, 1=Takeaway, 2=Delivery | `OrderType` entities | Fulfillment types |
191
+ | Pagination | `?page=N` (200/page) | `?offset=N&limit=N` | Cursor-based |
192
+ | Delete | Request body `[{Id: int}]` | URL path `/v3/.../ID` | URL path |
193
+ | IDs | Integer | UUID-like string | UUID-like string |
194
+
195
+ ## Order Patterns
196
+
197
+ ### Daily Volume
198
+
199
+ | Day | Min Orders | Max Orders |
200
+ |-----|-----------|-----------|
201
+ | Weekday | 40 | 60 |
202
+ | Friday | 70 | 100 |
203
+ | Saturday | 80 | 120 |
204
+ | Sunday | 50 | 80 |
205
+
206
+ ### Meal Periods
207
+
208
+ | Period | Weight | Items | Typical Total |
209
+ |--------|--------|-------|--------------|
210
+ | Breakfast | 15% | 1–3 | $8–$20 |
211
+ | Lunch | 30% | 2–4 | $12–$35 |
212
+ | Happy Hour | 10% | 2–4 | $10–$25 |
213
+ | Dinner | 35% | 3–6 | $20–$60 |
214
+ | Late Night | 10% | 1–3 | $8–$25 |
215
+
216
+ ### Dining Options
217
+
218
+ | Period | Eat-In | Takeaway | Delivery |
219
+ |--------|--------|----------|----------|
220
+ | Breakfast | 40% | 50% | 10% |
221
+ | Lunch | 35% | 45% | 20% |
222
+ | Happy Hour | 80% | 15% | 5% |
223
+ | Dinner | 70% | 15% | 15% |
224
+ | Late Night | 50% | 30% | 20% |
225
+
226
+ ## Tips
227
+
228
+ | Dining Option | Tip Chance | Min Tip | Max Tip |
229
+ |---------------|-----------|---------|---------|
230
+ | Eat-In | 70% | 15% | 25% |
231
+ | Takeaway | 20% | 5% | 15% |
232
+ | Delivery | 50% | 10% | 20% |
233
+
234
+ ## Audit Trail & Persistence
235
+
236
+ ### Models
237
+
238
+ | Model | Purpose |
239
+ |-------|---------|
240
+ | `BusinessType` | 4 business types with category/item associations |
241
+ | `Category` | 20 categories linked to business types |
242
+ | `Item` | 84 items with SKUs, pricing, and category assignments |
243
+ | `SimulatedOrder` | Every generated order with meal period, dining option, amounts |
244
+ | `SimulatedPayment` | Payment records with tender type and transaction reference |
245
+ | `ApiRequest` | Full audit log of every HTTP call (method, URL, status, duration) |
246
+ | `DailySummary` | Daily aggregation of revenue, tax, tips, discounts by period/tender |
247
+
248
+ ## Architecture
249
+
250
+ ```
251
+ lib/epos_now_sandbox_simulator/
252
+ ├── configuration.rb # Multi-device config, Basic Auth token
253
+ ├── database.rb # Standalone ActiveRecord (no Rails)
254
+ ├── seeder.rb # Idempotent DB seeding via FactoryBot
255
+ ├── data/ # JSON data files per business type
256
+ │ ├── restaurant/
257
+ │ ├── cafe_bakery/
258
+ │ ├── bar_nightclub/
259
+ │ └── retail_general/
260
+ ├── generators/
261
+ │ ├── data_loader.rb # DB-first with JSON fallback
262
+ │ ├── entity_generator.rb # Setup categories/products/tenders
263
+ │ └── order_generator.rb # Realistic order generation
264
+ ├── models/ # ActiveRecord models (standalone)
265
+ │ ├── business_type.rb
266
+ │ ├── category.rb
267
+ │ ├── item.rb
268
+ │ ├── simulated_order.rb
269
+ │ ├── simulated_payment.rb
270
+ │ ├── api_request.rb
271
+ │ └── daily_summary.rb
272
+ ├── services/
273
+ │ ├── base_service.rb # HTTP client, auth, pagination, audit
274
+ │ └── epos_now/
275
+ │ ├── inventory_service.rb # Categories + Products
276
+ │ ├── tender_service.rb # Tender types
277
+ │ ├── transaction_service.rb # V4 transactions
278
+ │ ├── tax_service.rb # Tax groups + calculation
279
+ │ └── services_manager.rb # Thread-safe lazy loader
280
+ └── db/
281
+ ├── migrate/ # 8 migrations (UUID v7 PKs)
282
+ └── factories/ # FactoryBot for tests + seeding
283
+ ```
284
+
285
+ ## Development
286
+
287
+ ```bash
288
+ # Install dependencies
289
+ bundle install
290
+
291
+ # Run all tests (286 examples)
292
+ bundle exec rspec
293
+
294
+ # Run with coverage report (100% line + branch required)
295
+ COVERAGE=true bundle exec rspec
296
+
297
+ # Run linter (0 offenses required)
298
+ bundle exec rubocop
299
+
300
+ # Run specific test groups
301
+ bundle exec rspec spec/services/
302
+ bundle exec rspec spec/generators/
303
+ bundle exec rspec spec/models/
304
+
305
+ # Open console
306
+ bundle exec irb -r ./lib/epos_now_sandbox_simulator
307
+
308
+ # Build the gem
309
+ gem build epos_now_sandbox_simulator.gemspec
310
+ ```
311
+
312
+ ### Test Coverage
313
+
314
+ - **286 examples, 0 failures**
315
+ - **100% line coverage** (802/802 lines)
316
+ - **100% branch coverage** (223/223 branches)
317
+ - **Rubocop: 0 offenses** (52 files)
318
+
319
+ ## Ruby API
320
+
321
+ ```ruby
322
+ require "epos_now_sandbox_simulator"
323
+
324
+ # Configure
325
+ config = EposNowSandboxSimulator::Configuration.new
326
+ config.api_key = "your-api-key"
327
+ config.api_secret = "your-api-secret"
328
+
329
+ # Use services directly
330
+ manager = EposNowSandboxSimulator::Services::EposNow::ServicesManager.new(config: config)
331
+
332
+ # Inventory
333
+ categories = manager.inventory.list_categories
334
+ products = manager.inventory.list_products
335
+ manager.inventory.create_category(name: "Specials", sort_order: 99)
336
+ manager.inventory.create_product(name: "Daily Special", price: 14.99, category_id: 1)
337
+
338
+ # Transactions
339
+ result = manager.transactions.create_transaction(
340
+ service_type: 0, # EatIn
341
+ items: [
342
+ { product_id: 1, quantity: 2, unit_price: 9.99 },
343
+ { product_id: 3, quantity: 1 }
344
+ ],
345
+ tenders: [
346
+ { tender_type_id: 1, amount: 29.97 }
347
+ ]
348
+ )
349
+
350
+ # Fetch transactions by date
351
+ transactions = manager.transactions.fetch_by_date(
352
+ start_date: Date.today,
353
+ end_date: Date.today
354
+ )
355
+
356
+ # Tax groups
357
+ tax_groups = manager.tax.list_tax_groups
358
+
359
+ # Generate realistic orders
360
+ generator = EposNowSandboxSimulator::Generators::OrderGenerator.new(
361
+ config: config,
362
+ refund_percentage: 5
363
+ )
364
+ orders = generator.generate_today(count: 25)
365
+ ```
366
+
367
+ ## Sandbox Limitations
368
+
369
+ This gem is designed for **sandbox and development environments only** — not for production use. It generates test data against the Epos Now API to validate integrations before going live.
370
+
371
+ | Feature | Notes |
372
+ |---------|-------|
373
+ | Authentication | Basic Auth with sandbox API credentials |
374
+ | Transactions | Created in sandbox, visible in Epos Now Backoffice |
375
+ | Date | Epos Now may restrict orders to current date |
376
+ | Rate Limits | Sandbox may have different rate limits than production |
377
+
378
+ ## License
379
+
380
+ [MIT License](LICENSE)