spree_packeta 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/.github/workflows/release.yml +196 -0
- data/.github/workflows/test.yml +61 -0
- data/.gitignore +63 -0
- data/CHANGELOG.md +43 -0
- data/COMMANDS.md +322 -0
- data/Gemfile +13 -0
- data/LICENSE +21 -0
- data/README.md +307 -0
- data/app/decorators/spree/order_decorator.rb +44 -0
- data/app/decorators/spree/shipment_decorator.rb +65 -0
- data/db/migrate/20241206000001_add_packeta_tracking_to_shipments.rb +14 -0
- data/docs/RELEASING.md +421 -0
- data/lib/generators/spree_packeta/install_generator.rb +68 -0
- data/lib/generators/spree_packeta/templates/initializer.rb +39 -0
- data/lib/spree_packeta/configuration.rb +55 -0
- data/lib/spree_packeta/engine.rb +48 -0
- data/lib/spree_packeta/models/shipping_calculator.rb +54 -0
- data/lib/spree_packeta/models/shipping_method.rb +59 -0
- data/lib/spree_packeta/services/packet_creator.rb +98 -0
- data/lib/spree_packeta/services/tracker.rb +96 -0
- data/lib/spree_packeta/soap/client.rb +117 -0
- data/lib/spree_packeta/soap/operations.rb +140 -0
- data/lib/spree_packeta/soap/packeta.wsdl +1819 -0
- data/lib/spree_packeta/version.rb +5 -0
- data/lib/spree_packeta.rb +18 -0
- data/lib/tasks/spree_packeta.rake +293 -0
- data/spree_packeta.gemspec +41 -0
- metadata +228 -0
data/docs/RELEASING.md
ADDED
|
@@ -0,0 +1,421 @@
|
|
|
1
|
+
# Release Guide for spree_packeta
|
|
2
|
+
|
|
3
|
+
This guide explains how to create a new release of the spree_packeta gem.
|
|
4
|
+
|
|
5
|
+
## Prerequisites
|
|
6
|
+
|
|
7
|
+
1. **Maintainer access**: You must have push access to the repository
|
|
8
|
+
2. **RubyGems account**: Configured as owner of the spree_packeta gem
|
|
9
|
+
3. **GitHub secrets**: `RUBYGEMS_API_KEY` must be configured (maintainers only)
|
|
10
|
+
|
|
11
|
+
## Dual Publishing
|
|
12
|
+
|
|
13
|
+
This gem is published to **two registries**:
|
|
14
|
+
- **RubyGems.org**: Public gem registry (primary)
|
|
15
|
+
- **GitHub Packages**: GitHub's gem registry (backup/alternative)
|
|
16
|
+
|
|
17
|
+
Benefits:
|
|
18
|
+
- **Redundancy**: If RubyGems.org is down, users can install from GitHub Packages
|
|
19
|
+
- **Private gems**: Can be extended for private versions
|
|
20
|
+
- **GitHub integration**: Better integration with GitHub ecosystem
|
|
21
|
+
- **No extra setup required**: `GITHUB_TOKEN` is automatically provided by GitHub Actions
|
|
22
|
+
|
|
23
|
+
## Release Process
|
|
24
|
+
|
|
25
|
+
### 1. Prepare the Release
|
|
26
|
+
|
|
27
|
+
#### Update Version Number
|
|
28
|
+
|
|
29
|
+
Edit `lib/spree_packeta/version.rb`:
|
|
30
|
+
|
|
31
|
+
```ruby
|
|
32
|
+
module SpreePacketa
|
|
33
|
+
VERSION = '1.0.0' # Change to your new version
|
|
34
|
+
end
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Follow [Semantic Versioning](https://semver.org/):
|
|
38
|
+
- **MAJOR** (1.0.0): Breaking changes
|
|
39
|
+
- **MINOR** (0.2.0): New features, backward compatible
|
|
40
|
+
- **PATCH** (0.1.1): Bug fixes, backward compatible
|
|
41
|
+
|
|
42
|
+
#### Update CHANGELOG.md
|
|
43
|
+
|
|
44
|
+
Move items from `[Unreleased]` to a new version section:
|
|
45
|
+
|
|
46
|
+
```markdown
|
|
47
|
+
## [Unreleased]
|
|
48
|
+
|
|
49
|
+
### Added
|
|
50
|
+
- (empty after release)
|
|
51
|
+
|
|
52
|
+
## [1.0.0] - 2024-12-21
|
|
53
|
+
|
|
54
|
+
### Added
|
|
55
|
+
- New feature X
|
|
56
|
+
- New feature Y
|
|
57
|
+
|
|
58
|
+
### Fixed
|
|
59
|
+
- Bug fix Z
|
|
60
|
+
|
|
61
|
+
[Unreleased]: https://github.com/yourusername/spree_packeta/compare/v1.0.0...HEAD
|
|
62
|
+
[1.0.0]: https://github.com/yourusername/spree_packeta/compare/v0.1.0...v1.0.0
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
#### Update Documentation
|
|
66
|
+
|
|
67
|
+
If needed, update:
|
|
68
|
+
- `README.md` - Installation version numbers
|
|
69
|
+
- Code examples with new features
|
|
70
|
+
- Roadmap section
|
|
71
|
+
|
|
72
|
+
### 2. Pre-Release Checks
|
|
73
|
+
|
|
74
|
+
Run these commands locally:
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
# Install dependencies
|
|
78
|
+
bundle install
|
|
79
|
+
|
|
80
|
+
# Run tests
|
|
81
|
+
bundle exec rspec
|
|
82
|
+
|
|
83
|
+
# Run linter (if configured)
|
|
84
|
+
bundle exec rubocop
|
|
85
|
+
|
|
86
|
+
# Build gem locally to verify
|
|
87
|
+
gem build spree_packeta.gemspec
|
|
88
|
+
# Should output: Successfully built RubyGem
|
|
89
|
+
# Should create: spree_packeta-1.0.0.gem
|
|
90
|
+
|
|
91
|
+
# Clean up test gem
|
|
92
|
+
rm spree_packeta-*.gem
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
All checks must pass before proceeding.
|
|
96
|
+
|
|
97
|
+
### 3. Commit and Tag
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
# Stage changes
|
|
101
|
+
git add lib/spree_packeta/version.rb CHANGELOG.md README.md
|
|
102
|
+
|
|
103
|
+
# Commit with descriptive message
|
|
104
|
+
git commit -m "Prepare v1.0.0 release
|
|
105
|
+
|
|
106
|
+
- Update version to 1.0.0
|
|
107
|
+
- Update CHANGELOG with new features and fixes
|
|
108
|
+
- Update README documentation
|
|
109
|
+
"
|
|
110
|
+
|
|
111
|
+
# Push to main
|
|
112
|
+
git push origin main
|
|
113
|
+
|
|
114
|
+
# Create annotated tag
|
|
115
|
+
git tag -a v1.0.0 -m "Release v1.0.0"
|
|
116
|
+
|
|
117
|
+
# Push tag (this triggers the release workflow)
|
|
118
|
+
git push origin v1.0.0
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### 4. Monitor Release Workflow
|
|
122
|
+
|
|
123
|
+
1. Go to GitHub Actions: https://github.com/yourusername/spree_packeta/actions
|
|
124
|
+
2. Find the "Release Gem to RubyGems and GitHub Packages" workflow
|
|
125
|
+
3. Watch the progress through three stages:
|
|
126
|
+
- ✅ Validate Release (version check)
|
|
127
|
+
- ✅ Run Tests (RSpec)
|
|
128
|
+
- ✅ Build and Publish (RubyGems.org + GitHub Packages + GitHub Release)
|
|
129
|
+
|
|
130
|
+
Expected duration: 3-5 minutes
|
|
131
|
+
|
|
132
|
+
### 5. Verify Release
|
|
133
|
+
|
|
134
|
+
After workflow completes:
|
|
135
|
+
|
|
136
|
+
#### Check RubyGems.org
|
|
137
|
+
```bash
|
|
138
|
+
# Search for new version
|
|
139
|
+
gem search spree_packeta
|
|
140
|
+
|
|
141
|
+
# Install and verify
|
|
142
|
+
gem install spree_packeta -v 1.0.0
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Or visit: https://rubygems.org/gems/spree_packeta
|
|
146
|
+
|
|
147
|
+
#### Check GitHub Packages
|
|
148
|
+
|
|
149
|
+
Visit: https://github.com/yourusername/spree_packeta/packages
|
|
150
|
+
|
|
151
|
+
Should see:
|
|
152
|
+
- Package: spree_packeta
|
|
153
|
+
- Latest version: 1.0.0
|
|
154
|
+
- Published timestamp
|
|
155
|
+
|
|
156
|
+
Or verify via command line (requires GitHub authentication):
|
|
157
|
+
```bash
|
|
158
|
+
# Configure bundler to use GitHub Packages
|
|
159
|
+
bundle config set --local https://rubygems.pkg.github.com/yourusername <YOUR_GITHUB_TOKEN>
|
|
160
|
+
|
|
161
|
+
# Then install
|
|
162
|
+
gem install spree_packeta --source https://rubygems.pkg.github.com/yourusername
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
#### Check GitHub Release
|
|
166
|
+
|
|
167
|
+
Visit: https://github.com/yourusername/spree_packeta/releases
|
|
168
|
+
|
|
169
|
+
Should see:
|
|
170
|
+
- Release title: "Release v1.0.0"
|
|
171
|
+
- Auto-generated release notes with installation instructions for both registries
|
|
172
|
+
- Attached gem file: `spree_packeta-1.0.0.gem`
|
|
173
|
+
|
|
174
|
+
#### Test Installation
|
|
175
|
+
|
|
176
|
+
In a test Rails app:
|
|
177
|
+
|
|
178
|
+
```ruby
|
|
179
|
+
# Gemfile
|
|
180
|
+
gem 'spree_packeta', '~> 1.0.0'
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
```bash
|
|
184
|
+
bundle install
|
|
185
|
+
bundle exec rails g spree_packeta:install
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### 6. Announce Release (Optional)
|
|
189
|
+
|
|
190
|
+
Consider announcing:
|
|
191
|
+
- Twitter/X post
|
|
192
|
+
- Company blog post
|
|
193
|
+
- Spree Community forums
|
|
194
|
+
- Email to users/clients
|
|
195
|
+
|
|
196
|
+
## Troubleshooting
|
|
197
|
+
|
|
198
|
+
### Version Mismatch Error
|
|
199
|
+
|
|
200
|
+
```
|
|
201
|
+
❌ ERROR: Version mismatch!
|
|
202
|
+
Git tag: v1.0.0
|
|
203
|
+
version.rb: 0.9.0
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
**Solution**:
|
|
207
|
+
```bash
|
|
208
|
+
# Delete the tag
|
|
209
|
+
git tag -d v1.0.0
|
|
210
|
+
git push --delete origin v1.0.0
|
|
211
|
+
|
|
212
|
+
# Update version.rb to 1.0.0
|
|
213
|
+
# Commit and re-tag
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### Test Failures
|
|
217
|
+
|
|
218
|
+
```
|
|
219
|
+
❌ Run Tests failed
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
**Solution**:
|
|
223
|
+
```bash
|
|
224
|
+
# Run tests locally to debug
|
|
225
|
+
bundle exec rspec --format documentation
|
|
226
|
+
|
|
227
|
+
# Fix failing tests
|
|
228
|
+
# Commit fixes
|
|
229
|
+
# Delete and recreate tag
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### RubyGems Publish Failed
|
|
233
|
+
|
|
234
|
+
```
|
|
235
|
+
❌ ERROR: There was a problem saving your gem: Name already exists
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
**Cause**: Version already published
|
|
239
|
+
|
|
240
|
+
**Solution**:
|
|
241
|
+
```bash
|
|
242
|
+
# Increment patch version
|
|
243
|
+
# Update version.rb to 1.0.1
|
|
244
|
+
# Commit and create new tag v1.0.1
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
### GitHub Release Failed
|
|
248
|
+
|
|
249
|
+
The workflow continues even if GitHub Release creation fails.
|
|
250
|
+
|
|
251
|
+
**Solution**: Create release manually:
|
|
252
|
+
```bash
|
|
253
|
+
gh release create v1.0.0 \
|
|
254
|
+
--title "Release v1.0.0" \
|
|
255
|
+
--notes "See CHANGELOG.md for details" \
|
|
256
|
+
spree_packeta-1.0.0.gem
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
### Missing RubyGems API Key
|
|
260
|
+
|
|
261
|
+
```
|
|
262
|
+
❌ ERROR: Please sign up for an account at http://rubygems.org
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
**Cause**: `RUBYGEMS_API_KEY` secret not configured or invalid
|
|
266
|
+
|
|
267
|
+
**Solution**:
|
|
268
|
+
1. Login to rubygems.org
|
|
269
|
+
2. Go to Edit Profile > API Keys
|
|
270
|
+
3. Create new API key with "Push rubygems" scope
|
|
271
|
+
4. Copy the token (shown once)
|
|
272
|
+
5. Add to GitHub: Settings > Secrets and variables > Actions > New repository secret
|
|
273
|
+
- Name: `RUBYGEMS_API_KEY`
|
|
274
|
+
- Value: [paste token]
|
|
275
|
+
|
|
276
|
+
## Rollback Procedures
|
|
277
|
+
|
|
278
|
+
### Yank a Published Gem
|
|
279
|
+
|
|
280
|
+
If you need to remove a published version:
|
|
281
|
+
|
|
282
|
+
```bash
|
|
283
|
+
# Mark version as yanked (users can't install, but existing installs work)
|
|
284
|
+
gem yank spree_packeta -v 1.0.0
|
|
285
|
+
|
|
286
|
+
# To undo yank
|
|
287
|
+
gem yank spree_packeta -v 1.0.0 --undo
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
**Note**: Yanking should be rare and only for critical security issues.
|
|
291
|
+
|
|
292
|
+
### Delete a GitHub Release
|
|
293
|
+
|
|
294
|
+
```bash
|
|
295
|
+
# Delete release (keeps tag)
|
|
296
|
+
gh release delete v1.0.0 --yes
|
|
297
|
+
|
|
298
|
+
# Delete tag
|
|
299
|
+
git push --delete origin v1.0.0
|
|
300
|
+
git tag -d v1.0.0
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
## Setting up RubyGems API Key
|
|
304
|
+
|
|
305
|
+
For first-time setup or rotation:
|
|
306
|
+
|
|
307
|
+
### 1. Generate API Key on RubyGems
|
|
308
|
+
|
|
309
|
+
1. Login to https://rubygems.org
|
|
310
|
+
2. Click on your profile > Edit Profile
|
|
311
|
+
3. Navigate to "API Keys" section
|
|
312
|
+
4. Click "New API Key"
|
|
313
|
+
5. Configure the key:
|
|
314
|
+
- **Name**: "GitHub Actions - spree_packeta"
|
|
315
|
+
- **Scopes**: Check "Push rubygems" only
|
|
316
|
+
- **Gem**: Select "spree_packeta" (or leave blank for all)
|
|
317
|
+
- **Expiration**: Set appropriate expiration (or leave blank)
|
|
318
|
+
6. Click "Create"
|
|
319
|
+
7. **COPY THE KEY NOW** - it's shown only once
|
|
320
|
+
|
|
321
|
+
### 2. Add to GitHub Secrets
|
|
322
|
+
|
|
323
|
+
1. Go to repository on GitHub
|
|
324
|
+
2. Settings > Secrets and variables > Actions
|
|
325
|
+
3. Click "New repository secret"
|
|
326
|
+
4. Name: `RUBYGEMS_API_KEY`
|
|
327
|
+
5. Value: Paste the API key from step 1
|
|
328
|
+
6. Click "Add secret"
|
|
329
|
+
|
|
330
|
+
### 3. Verify Setup
|
|
331
|
+
|
|
332
|
+
Test with a patch release:
|
|
333
|
+
|
|
334
|
+
```bash
|
|
335
|
+
# Update version to 0.1.1
|
|
336
|
+
# Update CHANGELOG
|
|
337
|
+
# Commit and tag
|
|
338
|
+
git tag v0.1.1
|
|
339
|
+
git push origin v0.1.1
|
|
340
|
+
|
|
341
|
+
# Watch workflow to ensure it completes successfully
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
## Security Notes
|
|
345
|
+
|
|
346
|
+
- Never commit API keys or credentials
|
|
347
|
+
- Rotate `RUBYGEMS_API_KEY` periodically (every 6-12 months)
|
|
348
|
+
- Use 2FA on RubyGems account
|
|
349
|
+
- Review dependency updates before releases
|
|
350
|
+
- Run `bundle audit` to check for vulnerabilities
|
|
351
|
+
- Limit API key scope to push-only permissions
|
|
352
|
+
- Set expiration dates on API keys
|
|
353
|
+
|
|
354
|
+
## Installing from GitHub Packages (for users)
|
|
355
|
+
|
|
356
|
+
If users want to install your gem from GitHub Packages instead of RubyGems.org:
|
|
357
|
+
|
|
358
|
+
### Option 1: Using Gemfile source block
|
|
359
|
+
|
|
360
|
+
```ruby
|
|
361
|
+
# Gemfile
|
|
362
|
+
source 'https://rubygems.pkg.github.com/yourusername' do
|
|
363
|
+
gem 'spree_packeta', '~> 1.0.0'
|
|
364
|
+
end
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
Then authenticate:
|
|
368
|
+
```bash
|
|
369
|
+
bundle config set --local https://rubygems.pkg.github.com/yourusername <GITHUB_TOKEN>
|
|
370
|
+
bundle install
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
### Option 2: Using gem command
|
|
374
|
+
|
|
375
|
+
```bash
|
|
376
|
+
# Configure credentials
|
|
377
|
+
gem sources --add https://rubygems.pkg.github.com/yourusername
|
|
378
|
+
|
|
379
|
+
# Install
|
|
380
|
+
gem install spree_packeta --source https://rubygems.pkg.github.com/yourusername
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
**Note**: GitHub Packages requires authentication. Users need a GitHub Personal Access Token with `read:packages` scope.
|
|
384
|
+
|
|
385
|
+
## FAQ
|
|
386
|
+
|
|
387
|
+
**Q: Can I release from a branch other than main?**
|
|
388
|
+
A: The workflow triggers on any tag push, regardless of branch. However, it's recommended to always release from main after merging all changes.
|
|
389
|
+
|
|
390
|
+
**Q: What if I need to release a hotfix?**
|
|
391
|
+
A: Create a hotfix branch, make changes, update version to a patch increment (e.g., 1.0.1), merge to main, then tag and push.
|
|
392
|
+
|
|
393
|
+
**Q: How do I handle pre-releases (beta, rc)?**
|
|
394
|
+
A: Currently, the workflow only supports stable releases (v1.0.0). For pre-releases, you'd need to manually publish or extend the tag regex pattern.
|
|
395
|
+
|
|
396
|
+
**Q: What happens if the workflow fails midway?**
|
|
397
|
+
A: The workflow is designed to fail-fast:
|
|
398
|
+
- If validation fails: Nothing is published
|
|
399
|
+
- If tests fail: Nothing is published
|
|
400
|
+
- If RubyGems.org publish fails: GitHub Packages is not published
|
|
401
|
+
- If GitHub Packages publish fails: Workflow continues (RubyGems.org is primary)
|
|
402
|
+
- If GitHub Release fails: Gems are already published (manual release creation needed)
|
|
403
|
+
|
|
404
|
+
**Q: What if GitHub Packages publishing fails?**
|
|
405
|
+
A: GitHub Packages publishing is considered non-critical. If it fails, the workflow continues and the gem is still available on RubyGems.org. You can manually publish to GitHub Packages later if needed.
|
|
406
|
+
|
|
407
|
+
**Q: How do I test the workflow without publishing?**
|
|
408
|
+
A: You can test validation and build steps by:
|
|
409
|
+
1. Running `gem build` locally
|
|
410
|
+
2. Checking the workflow logs on a test tag
|
|
411
|
+
3. Using a separate test gem name for initial setup
|
|
412
|
+
|
|
413
|
+
**Q: Can I skip the tests?**
|
|
414
|
+
A: Not recommended. Tests are a quality gate. If you absolutely must, you can modify the workflow to remove the test job dependency.
|
|
415
|
+
|
|
416
|
+
**Q: Do users need special setup to use my gem from GitHub Packages?**
|
|
417
|
+
A: Yes, they need a GitHub Personal Access Token with `read:packages` scope. For most users, installing from RubyGems.org is simpler and recommended.
|
|
418
|
+
|
|
419
|
+
## Questions?
|
|
420
|
+
|
|
421
|
+
Contact the maintainers or open an issue on GitHub.
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SpreePacketa
|
|
4
|
+
module Generators
|
|
5
|
+
class InstallGenerator < Rails::Generators::Base
|
|
6
|
+
source_root File.expand_path('templates', __dir__)
|
|
7
|
+
|
|
8
|
+
desc 'Installs Spree Packeta and generates necessary files'
|
|
9
|
+
|
|
10
|
+
def copy_initializer
|
|
11
|
+
template 'initializer.rb', 'config/initializers/spree_packeta.rb'
|
|
12
|
+
say 'Initializer created at config/initializers/spree_packeta.rb', :green
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def copy_migrations
|
|
16
|
+
rake 'railties:install:migrations FROM=spree_packeta'
|
|
17
|
+
say 'Migrations copied', :green
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def run_migrations
|
|
21
|
+
if options[:auto_run_migrations] || yes?('Run migrations now? (yes/no)')
|
|
22
|
+
rake 'db:migrate'
|
|
23
|
+
say 'Migrations completed', :green
|
|
24
|
+
else
|
|
25
|
+
say 'Skipping migrations. Run `rails db:migrate` manually', :yellow
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def install_shipping_method
|
|
30
|
+
if options[:skip_shipping_method]
|
|
31
|
+
say 'Skipping shipping method installation', :yellow
|
|
32
|
+
elsif yes?('Install Packeta shipping method now? (yes/no)')
|
|
33
|
+
rake 'spree_packeta:install'
|
|
34
|
+
else
|
|
35
|
+
say 'You can install the shipping method later with: rake spree_packeta:install', :yellow
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def show_readme
|
|
40
|
+
say ''
|
|
41
|
+
say '=' * 80, :green
|
|
42
|
+
say 'Spree Packeta Installation Complete!', :green
|
|
43
|
+
say '=' * 80, :green
|
|
44
|
+
say ''
|
|
45
|
+
say 'Next steps:', :yellow
|
|
46
|
+
say ''
|
|
47
|
+
say ' 1. Add your Packeta credentials to .env:', :cyan
|
|
48
|
+
say ' PACKETA_API_PASSWORD=your_api_password'
|
|
49
|
+
say ' PACKETA_ESHOP=your_eshop_id'
|
|
50
|
+
say ' PACKETA_WSDL_PATH=file:///path/to/soap.wsdl'
|
|
51
|
+
say ' PACKETA_SENDER_EMAIL=shipping@yourstore.com'
|
|
52
|
+
say ''
|
|
53
|
+
say ' 2. Restart your Rails server', :cyan
|
|
54
|
+
say ''
|
|
55
|
+
say ' 3. Configure shipping method in Spree admin', :cyan
|
|
56
|
+
say ' or run: rake spree_packeta:install (if you skipped it)'
|
|
57
|
+
say ''
|
|
58
|
+
say ' 4. Frontend integration:', :cyan
|
|
59
|
+
say ' See FRONTEND_INTEGRATION.md for React/frontend setup'
|
|
60
|
+
say ''
|
|
61
|
+
say 'Documentation:', :yellow
|
|
62
|
+
say ' - README.md - General usage'
|
|
63
|
+
say ' - FRONTEND_INTEGRATION.md - Frontend setup guide'
|
|
64
|
+
say ''
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
SpreePacketa.configure do |config|
|
|
4
|
+
# API credentials
|
|
5
|
+
# Get your API password from Packeta dashboard
|
|
6
|
+
config.api_password = ENV['PACKETA_API_PASSWORD']
|
|
7
|
+
|
|
8
|
+
# SOAP endpoint (production vs sandbox)
|
|
9
|
+
# Default: http://www.zasilkovna.cz/api/soap
|
|
10
|
+
# Sandbox: http://www.zasilkovna.cz/api/soap-php-bugfix (if available)
|
|
11
|
+
config.soap_endpoint = ENV.fetch('PACKETA_SOAP_ENDPOINT',
|
|
12
|
+
'http://www.zasilkovna.cz/api/soap')
|
|
13
|
+
|
|
14
|
+
# WSDL path (can be local file or remote URL)
|
|
15
|
+
# Use local file for better performance: file:///path/to/soap.wsdl
|
|
16
|
+
# Or use remote: http://www.zasilkovna.cz/api/soap.wsdl
|
|
17
|
+
config.wsdl_path = ENV.fetch('PACKETA_WSDL_PATH',
|
|
18
|
+
'http://www.zasilkovna.cz/api/soap.wsdl')
|
|
19
|
+
|
|
20
|
+
# Your Eshop identifier from Packeta
|
|
21
|
+
config.eshop = ENV['PACKETA_ESHOP']
|
|
22
|
+
|
|
23
|
+
# Sender information (for return labels and contact)
|
|
24
|
+
config.sender_name = ENV.fetch('PACKETA_SENDER_NAME', 'Your Store Name')
|
|
25
|
+
config.sender_email = ENV.fetch('PACKETA_SENDER_EMAIL', 'shipping@yourstore.com')
|
|
26
|
+
config.sender_phone = ENV.fetch('PACKETA_SENDER_PHONE', '+420123456789')
|
|
27
|
+
|
|
28
|
+
# Rate caching duration (in seconds)
|
|
29
|
+
# How long to cache shipping rate calculations
|
|
30
|
+
config.rate_cache_duration = 3600 # 1 hour
|
|
31
|
+
|
|
32
|
+
# Auto-create packets on shipment
|
|
33
|
+
# Set to true to automatically create Packeta packets when order is shipped
|
|
34
|
+
config.auto_create_packets = true
|
|
35
|
+
|
|
36
|
+
# Tracking sync interval (in seconds)
|
|
37
|
+
# How often to sync tracking status from Packeta
|
|
38
|
+
config.tracking_sync_interval = 3600 # 1 hour
|
|
39
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SpreePacketa
|
|
4
|
+
class Configuration
|
|
5
|
+
# API credentials
|
|
6
|
+
attr_accessor :api_password
|
|
7
|
+
|
|
8
|
+
# SOAP endpoint (production vs sandbox)
|
|
9
|
+
attr_accessor :soap_endpoint
|
|
10
|
+
|
|
11
|
+
# Default eshop identifier
|
|
12
|
+
attr_accessor :eshop
|
|
13
|
+
|
|
14
|
+
# Sender information for return labels
|
|
15
|
+
attr_accessor :sender_name
|
|
16
|
+
attr_accessor :sender_email
|
|
17
|
+
attr_accessor :sender_phone
|
|
18
|
+
|
|
19
|
+
# Rate caching duration (in seconds)
|
|
20
|
+
attr_accessor :rate_cache_duration
|
|
21
|
+
|
|
22
|
+
# Auto-create packets on shipment
|
|
23
|
+
attr_accessor :auto_create_packets
|
|
24
|
+
|
|
25
|
+
# Sync tracking status interval
|
|
26
|
+
attr_accessor :tracking_sync_interval
|
|
27
|
+
|
|
28
|
+
# WSDL file path (can be local or remote)
|
|
29
|
+
attr_accessor :wsdl_path
|
|
30
|
+
|
|
31
|
+
def initialize
|
|
32
|
+
@soap_endpoint = 'http://www.zasilkovna.cz/api/soap'
|
|
33
|
+
@rate_cache_duration = 3600 # 1 hour
|
|
34
|
+
@auto_create_packets = true
|
|
35
|
+
@tracking_sync_interval = 3600 # 1 hour in seconds
|
|
36
|
+
@wsdl_path = 'http://www.zasilkovna.cz/api/soap.wsdl'
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
class << self
|
|
41
|
+
attr_writer :configuration
|
|
42
|
+
|
|
43
|
+
def configuration
|
|
44
|
+
@configuration ||= Configuration.new
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def configure
|
|
48
|
+
yield(configuration)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def reset_configuration!
|
|
52
|
+
@configuration = Configuration.new
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spree_core'
|
|
4
|
+
|
|
5
|
+
module SpreePacketa
|
|
6
|
+
class Engine < Rails::Engine
|
|
7
|
+
require 'spree/core'
|
|
8
|
+
isolate_namespace Spree
|
|
9
|
+
engine_name 'spree_packeta'
|
|
10
|
+
|
|
11
|
+
config.autoload_paths += %W[#{config.root}/lib]
|
|
12
|
+
|
|
13
|
+
# use rspec for tests
|
|
14
|
+
config.generators do |g|
|
|
15
|
+
g.test_framework :rspec
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def self.activate
|
|
19
|
+
# Load decorators
|
|
20
|
+
Dir.glob(File.join(File.dirname(__FILE__), '../../app/**/*_decorator*.rb')) do |c|
|
|
21
|
+
Rails.configuration.cache_classes ? require(c) : load(c)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Load gem components after Spree has been initialized
|
|
25
|
+
require 'spree_packeta/soap/client'
|
|
26
|
+
require 'spree_packeta/soap/operations'
|
|
27
|
+
require 'spree_packeta/models/shipping_method'
|
|
28
|
+
require 'spree_packeta/models/shipping_calculator'
|
|
29
|
+
require 'spree_packeta/services/packet_creator'
|
|
30
|
+
require 'spree_packeta/services/tracker'
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
config.to_prepare(&method(:activate).to_proc)
|
|
34
|
+
|
|
35
|
+
initializer 'spree_packeta.environment', before: :load_config_initializers do |_app|
|
|
36
|
+
SpreePacketa.configure do |config|
|
|
37
|
+
# Load configuration from environment variables
|
|
38
|
+
config.api_password = ENV['PACKETA_API_PASSWORD'] if ENV['PACKETA_API_PASSWORD']
|
|
39
|
+
config.soap_endpoint = ENV['PACKETA_SOAP_ENDPOINT'] if ENV['PACKETA_SOAP_ENDPOINT']
|
|
40
|
+
config.eshop = ENV['PACKETA_ESHOP'] if ENV['PACKETA_ESHOP']
|
|
41
|
+
config.sender_name = ENV['PACKETA_SENDER_NAME'] if ENV['PACKETA_SENDER_NAME']
|
|
42
|
+
config.sender_email = ENV['PACKETA_SENDER_EMAIL'] if ENV['PACKETA_SENDER_EMAIL']
|
|
43
|
+
config.sender_phone = ENV['PACKETA_SENDER_PHONE'] if ENV['PACKETA_SENDER_PHONE']
|
|
44
|
+
config.wsdl_path = ENV['PACKETA_WSDL_PATH'] if ENV['PACKETA_WSDL_PATH']
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SpreePacketa
|
|
4
|
+
module Models
|
|
5
|
+
class ShippingCalculator < Spree::ShippingCalculator
|
|
6
|
+
# Preference for base shipping rate
|
|
7
|
+
preference :amount, :decimal, default: 99.0
|
|
8
|
+
preference :currency, :string, default: 'CZK'
|
|
9
|
+
|
|
10
|
+
# Calculate shipping rate for a package
|
|
11
|
+
#
|
|
12
|
+
# @param package [Spree::Stock::Package] The package to calculate for
|
|
13
|
+
# @return [BigDecimal] The shipping cost
|
|
14
|
+
def compute_package(package)
|
|
15
|
+
return 0 if package.contents.empty?
|
|
16
|
+
|
|
17
|
+
# For Phase 1, use fixed rate from preferences
|
|
18
|
+
# Phase 2 will implement dynamic rate calculation via Packeta API
|
|
19
|
+
base_rate = BigDecimal(preferred_amount.to_s)
|
|
20
|
+
|
|
21
|
+
# Apply weight-based multiplier if needed
|
|
22
|
+
total_weight = calculate_total_weight(package)
|
|
23
|
+
weight_multiplier = calculate_weight_multiplier(total_weight)
|
|
24
|
+
|
|
25
|
+
(base_rate * weight_multiplier).round(2)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
private
|
|
29
|
+
|
|
30
|
+
def calculate_total_weight(package)
|
|
31
|
+
package.contents.sum do |item|
|
|
32
|
+
weight = item.variant.weight.to_f
|
|
33
|
+
quantity = item.quantity
|
|
34
|
+
weight * quantity
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def calculate_weight_multiplier(weight)
|
|
39
|
+
# Simple weight-based pricing tiers
|
|
40
|
+
# Adjust these based on your business needs
|
|
41
|
+
case weight
|
|
42
|
+
when 0..5
|
|
43
|
+
1.0
|
|
44
|
+
when 5..10
|
|
45
|
+
1.2
|
|
46
|
+
when 10..20
|
|
47
|
+
1.5
|
|
48
|
+
else
|
|
49
|
+
2.0
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|