spree_cm_commissioner 1.9.2 → 1.10.0.pre.pre
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 +4 -4
- data/.github/workflows/test_and_build_gem.yml +86 -0
- data/.gitignore +2 -1
- data/Gemfile.lock +22 -1
- data/app/controllers/spree/admin/events_controller.rb +47 -0
- data/app/controllers/spree/admin/prototypes_controller_decorator.rb +20 -0
- data/app/controllers/spree/admin/stock_managements_controller.rb +17 -1
- data/app/controllers/spree/api/v2/storefront/accommodations/variants_controller.rb +42 -0
- data/app/controllers/spree/api/v2/storefront/accommodations_controller.rb +14 -31
- data/app/finders/spree_cm_commissioner/accommodations/find.rb +40 -0
- data/app/finders/spree_cm_commissioner/accommodations/find_variant.rb +35 -0
- data/app/interactors/spree_cm_commissioner/create_event.rb +65 -0
- data/app/interactors/spree_cm_commissioner/firebase_email_fetcher.rb +30 -4
- data/app/interactors/spree_cm_commissioner/firebase_email_fetcher_cron_executor.rb +23 -0
- data/app/interactors/spree_cm_commissioner/inventory_item_syncer.rb +25 -0
- data/app/interactors/spree_cm_commissioner/stock/permanent_inventory_items_generator.rb +71 -0
- data/app/interactors/spree_cm_commissioner/vattanac_bank_initiator.rb +25 -6
- data/app/jobs/spree_cm_commissioner/firebase_email_fetcher_job.rb +9 -0
- data/app/jobs/spree_cm_commissioner/inventory_item_syncer_job.rb +7 -0
- data/app/jobs/spree_cm_commissioner/stock/permanent_inventory_items_generator_job.rb +9 -0
- data/app/models/concerns/spree_cm_commissioner/order_state_machine.rb +26 -0
- data/app/models/concerns/spree_cm_commissioner/product_type.rb +10 -0
- data/app/models/spree_cm_commissioner/inventory.rb +11 -0
- data/app/models/spree_cm_commissioner/inventory_item.rb +37 -0
- data/app/models/spree_cm_commissioner/invite_user_taxon.rb +1 -0
- data/app/models/spree_cm_commissioner/line_item_decorator.rb +1 -0
- data/app/models/spree_cm_commissioner/order_decorator.rb +15 -0
- data/app/models/spree_cm_commissioner/product_decorator.rb +10 -0
- data/app/models/spree_cm_commissioner/prototype_decorator.rb +9 -0
- data/app/models/spree_cm_commissioner/redis_stock/cached_inventory_items_builder.rb +40 -0
- data/app/models/spree_cm_commissioner/redis_stock/inventory_updater.rb +114 -0
- data/app/models/spree_cm_commissioner/redis_stock/line_items_cached_inventory_items_builder.rb +42 -0
- data/app/models/spree_cm_commissioner/redis_stock/variant_cached_inventory_items_builder.rb +27 -0
- data/app/models/spree_cm_commissioner/stock/availability_checker.rb +27 -25
- data/app/models/spree_cm_commissioner/stock/availability_validator_decorator.rb +2 -1
- data/app/models/spree_cm_commissioner/stock/line_item_availability_checker.rb +3 -3
- data/app/models/spree_cm_commissioner/stock/order_availability_checker.rb +44 -0
- data/app/models/spree_cm_commissioner/stock_movement_decorator.rb +34 -0
- data/app/models/spree_cm_commissioner/taxon_decorator.rb +2 -1
- data/app/models/spree_cm_commissioner/user_decorator.rb +5 -1
- data/app/models/spree_cm_commissioner/variant_decorator.rb +24 -17
- data/app/overrides/spree/admin/prototypes/_form/description.html.erb.deface +6 -0
- data/app/overrides/spree/admin/prototypes/_form/icon.html.erb.deface +8 -0
- data/app/overrides/spree/admin/prototypes/_form/product_type.html.erb.deface +2 -2
- data/app/overrides/spree/admin/shared/sub_menu/_product/events_tab.html.erb.deface +3 -0
- data/app/request_schemas/spree_cm_commissioner/accommodation_request_schema.rb +3 -0
- data/app/request_schemas/spree_cm_commissioner/application_request_schema.rb +1 -1
- data/app/request_schemas/spree_cm_commissioner/variant_request_schema.rb +19 -0
- data/app/serializers/spree/v2/storefront/accommodation_serializer.rb +2 -0
- data/app/serializers/spree/v2/tenant/payment_method_serializer.rb +12 -0
- data/app/serializers/spree/v2/tenant/user_serializer.rb +1 -1
- data/app/views/spree/admin/events/_search_form.html.erb +61 -0
- data/app/views/spree/admin/events/_tab.html.erb +25 -0
- data/app/views/spree/admin/events/_table.html.erb +27 -0
- data/app/views/spree/admin/events/index.html.erb +15 -0
- data/app/views/spree/admin/stock_managements/_events_popover.html.erb +17 -0
- data/app/views/spree/admin/stock_managements/calendar.html.erb +32 -0
- data/app/views/spree/admin/stock_managements/index.html.erb +31 -5
- data/app/views/spree_cm_commissioner/crew_invite_mailer/_mailer_stylesheets.html.erb +2 -2
- data/app/views/spree_cm_commissioner/crew_invite_mailer/send_crew_invite_email.html.erb +1 -1
- data/config/initializers/user_manager_decorator.rb +26 -0
- data/config/routes.rb +12 -2
- data/db/migrate/20250304293518_create_cm_inventory_items.rb +21 -0
- data/db/migrate/20250425084929_add_description_to_spree_prototypes.rb +5 -0
- data/db/migrate/20250425085938_add_preferences_to_spree_prototypes.rb +5 -0
- data/db/migrate/20250428025645_add_slug_to_spree_prototypes.rb +6 -0
- data/db/migrate/20250429094228_add_lock_version_to_cm_inventory_items.rb +5 -0
- data/docker-compose.yml +1 -1
- data/lib/generators/spree_cm_commissioner/install/install_generator.rb +2 -2
- data/lib/generators/spree_cm_commissioner/install/templates/app/javascript/{spree_cm_commissioner → spree_dashboard/spree_cm_commissioner}/utilities.js +4 -0
- data/lib/spree_cm_commissioner/cached_inventory_item.rb +23 -0
- data/lib/spree_cm_commissioner/calendar_event.rb +11 -1
- data/lib/spree_cm_commissioner/test_helper/factories/inventory_item_factory.rb +9 -0
- data/lib/spree_cm_commissioner/test_helper/factories/variant_factory.rb +28 -6
- data/lib/spree_cm_commissioner/version.rb +1 -1
- data/lib/spree_cm_commissioner.rb +34 -0
- data/lib/tasks/create_default_non_permanent_inventory_items.rake +16 -0
- data/lib/tasks/fetch_email.rake +7 -0
- data/lib/tasks/generate_inventory_items.rake +7 -0
- data/spree_cm_commissioner.gemspec +5 -0
- metadata +88 -7
- data/app/queries/spree_cm_commissioner/variant_availability/non_permanent_stock_query.rb +0 -45
- data/app/queries/spree_cm_commissioner/variant_availability/permanent_stock_query.rb +0 -55
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f65a106e5b63ad907020c8170440edf6f39855bb166020954b51b9960aa8a052
|
4
|
+
data.tar.gz: f41887bf50e45ed36763177daeeaf433b88c8a41169ca3abcb67d59544f4faee
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5aa3d6bf790a31b5214d5e043c376288236283a0df96b8251574412530fd7a38b524592036303677bc141c44586ad58dbcb7e35b3f2a66218848036ecb78c82a
|
7
|
+
data.tar.gz: 8ba3abdb4a446e4493bf3369e5a375989e71c03643bfb9298169bf4335774a9189826fbc295c06cfcecf9f5edbb560c6ae9643d7a347cd619bdea7803d23c2c1
|
@@ -9,7 +9,91 @@ on:
|
|
9
9
|
tags:
|
10
10
|
- "*"
|
11
11
|
jobs:
|
12
|
+
validate-commits:
|
13
|
+
runs-on: ubuntu-latest
|
14
|
+
|
15
|
+
steps:
|
16
|
+
- name: Check PR title format
|
17
|
+
uses: actions/github-script@v7
|
18
|
+
if: github.event_name == 'pull_request'
|
19
|
+
with:
|
20
|
+
script: |
|
21
|
+
const title = context.payload.pull_request.title.trim();
|
22
|
+
|
23
|
+
console.log("PR title: ", title);
|
24
|
+
|
25
|
+
const pattern = /^Close\s+#\d+\s.+/;
|
26
|
+
|
27
|
+
if (!pattern.test(title)) {
|
28
|
+
core.setFailed(
|
29
|
+
`PR title must start with "Close #issue_number message". Example: Close #123 Add login form`
|
30
|
+
);
|
31
|
+
} else {
|
32
|
+
console.log("PR title format is correct.");
|
33
|
+
}
|
34
|
+
- name: Check commit messages format
|
35
|
+
uses: actions/github-script@v7
|
36
|
+
if: github.event_name == 'pull_request'
|
37
|
+
with:
|
38
|
+
script: |
|
39
|
+
const pr = context.payload.pull_request;
|
40
|
+
const commits_url = pr.commits_url;
|
41
|
+
|
42
|
+
const commits = await github.request(commits_url);
|
43
|
+
const pattern = /^Close\s+#\d+\s.+/;
|
44
|
+
|
45
|
+
let invalidCommits = [];
|
46
|
+
|
47
|
+
for (const commit of commits.data) {
|
48
|
+
const msg = commit.commit.message.trim();
|
49
|
+
|
50
|
+
console.log("commit message: ", msg);
|
51
|
+
|
52
|
+
if (!pattern.test(msg)) {
|
53
|
+
invalidCommits.push(`- ${msg}`);
|
54
|
+
}
|
55
|
+
}
|
56
|
+
|
57
|
+
if (invalidCommits.length > 0) {
|
58
|
+
core.setFailed(
|
59
|
+
`The following commit messages are not in the correct format:\n\n${invalidCommits.join(
|
60
|
+
'\n'
|
61
|
+
)}\n\nEach commit message must start with "Close #<issue_number> <message>"`
|
62
|
+
);
|
63
|
+
} else {
|
64
|
+
console.log("All commit messages are correctly formatted.");
|
65
|
+
}
|
66
|
+
- name: Check for unresolved review threads
|
67
|
+
uses: actions/github-script@v7
|
68
|
+
if: github.event_name == 'pull_request'
|
69
|
+
with:
|
70
|
+
script: |
|
71
|
+
const pr = context.payload.pull_request;
|
72
|
+
const owner = context.repo.owner;
|
73
|
+
const repo = context.repo.repo;
|
74
|
+
|
75
|
+
try {
|
76
|
+
const response = await github.rest.pulls.listReviewComments({
|
77
|
+
owner,
|
78
|
+
repo,
|
79
|
+
pull_number: pr.number,
|
80
|
+
per_page: 100
|
81
|
+
});
|
82
|
+
|
83
|
+
const unresolved = response.data.filter(comment => comment.in_reply_to_id && !comment.resolved);
|
84
|
+
|
85
|
+
if (unresolved.length > 0) {
|
86
|
+
core.setFailed(`There are ${unresolved.length} unresolved review comment(s). Please resolve all threads before merging.`);
|
87
|
+
} else {
|
88
|
+
console.log("All review comments are resolved.");
|
89
|
+
}
|
90
|
+
} catch (error) {
|
91
|
+
console.error("Error fetching review comments:", error.message);
|
92
|
+
core.setFailed("Failed to check for unresolved review threads.");
|
93
|
+
}
|
12
94
|
test_and_build_gem:
|
95
|
+
needs: [validate-commits]
|
96
|
+
# if: github.head_ref != '2572-enforce-pr-workflow' || github.base_ref != 'develop'
|
13
97
|
runs-on: ubuntu-latest
|
14
98
|
|
15
99
|
services:
|
@@ -49,12 +133,14 @@ jobs:
|
|
49
133
|
bundle install --jobs 4 --retry 3
|
50
134
|
|
51
135
|
- name: Quality
|
136
|
+
if: github.event_name == 'pull_request'
|
52
137
|
env:
|
53
138
|
DATABASE_URL: postgres://myuser:mypassword@localhost:5432/test_db
|
54
139
|
run: |
|
55
140
|
bundle exec rubocop
|
56
141
|
|
57
142
|
- name: Security
|
143
|
+
if: github.event_name == 'pull_request'
|
58
144
|
env:
|
59
145
|
DATABASE_URL: postgres://myuser:mypassword@localhost:5432/test_db
|
60
146
|
run: |
|
data/.gitignore
CHANGED
data/Gemfile.lock
CHANGED
@@ -34,7 +34,7 @@ GIT
|
|
34
34
|
PATH
|
35
35
|
remote: .
|
36
36
|
specs:
|
37
|
-
spree_cm_commissioner (1.
|
37
|
+
spree_cm_commissioner (1.10.0.pre.pre)
|
38
38
|
activerecord-multi-tenant
|
39
39
|
activerecord_json_validator (~> 2.1, >= 2.1.3)
|
40
40
|
aws-sdk-cloudfront
|
@@ -42,6 +42,7 @@ PATH
|
|
42
42
|
aws-sdk-s3
|
43
43
|
blazer (~> 3.0.4)
|
44
44
|
byebug
|
45
|
+
connection_pool
|
45
46
|
counter_culture (~> 3.2)
|
46
47
|
dry-validation (~> 1.10)
|
47
48
|
elasticsearch (~> 8.5)
|
@@ -57,6 +58,8 @@ PATH
|
|
57
58
|
phonelib
|
58
59
|
premailer-rails
|
59
60
|
rails (~> 7.0.4)
|
61
|
+
redis
|
62
|
+
redis-rails
|
60
63
|
rqrcode (~> 2.0)
|
61
64
|
searchkick (~> 5.1)
|
62
65
|
simple_calendar (~> 2.4)
|
@@ -617,6 +620,8 @@ GEM
|
|
617
620
|
activesupport (>= 2.3.14)
|
618
621
|
racc (1.7.1)
|
619
622
|
rack (2.2.8)
|
623
|
+
rack-session (1.0.2)
|
624
|
+
rack (< 3)
|
620
625
|
rack-test (2.1.0)
|
621
626
|
rack (>= 1.3)
|
622
627
|
rails (7.0.8)
|
@@ -660,8 +665,24 @@ GEM
|
|
660
665
|
rbtree (0.4.6)
|
661
666
|
redis (5.0.7)
|
662
667
|
redis-client (>= 0.9.0)
|
668
|
+
redis-actionpack (5.5.0)
|
669
|
+
actionpack (>= 5)
|
670
|
+
redis-rack (>= 2.1.0, < 4)
|
671
|
+
redis-store (>= 1.1.0, < 2)
|
672
|
+
redis-activesupport (5.3.0)
|
673
|
+
activesupport (>= 3, < 8)
|
674
|
+
redis-store (>= 1.3, < 2)
|
663
675
|
redis-client (0.17.0)
|
664
676
|
connection_pool
|
677
|
+
redis-rack (3.0.0)
|
678
|
+
rack-session (>= 0.2.0)
|
679
|
+
redis-store (>= 1.2, < 2)
|
680
|
+
redis-rails (5.0.2)
|
681
|
+
redis-actionpack (>= 5.0, < 6)
|
682
|
+
redis-activesupport (>= 5.0, < 6)
|
683
|
+
redis-store (>= 1.2, < 2)
|
684
|
+
redis-store (1.11.0)
|
685
|
+
redis (>= 4, < 6)
|
665
686
|
regexp_parser (2.8.2)
|
666
687
|
representable (3.2.0)
|
667
688
|
declarative (< 0.1.0)
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Spree
|
2
|
+
module Admin
|
3
|
+
class EventsController < Spree::Admin::ResourceController
|
4
|
+
before_action :load_taxonomy, only: [:index]
|
5
|
+
|
6
|
+
def index
|
7
|
+
params[:q] ||= {}
|
8
|
+
@search = taxon_scope.ransack(params[:q])
|
9
|
+
@taxons = fetch_taxons
|
10
|
+
@taxons_for_dropdown = @taxonomy.taxons if @taxonomy
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def fetch_taxons
|
16
|
+
scope = params[:taxon_id].present? ? filtered_taxons : searched_taxons
|
17
|
+
scope.includes(:taxonomy).page(params[:page]).per(15)
|
18
|
+
end
|
19
|
+
|
20
|
+
def model_class
|
21
|
+
Spree::Taxon
|
22
|
+
end
|
23
|
+
|
24
|
+
def load_taxonomy
|
25
|
+
@taxonomy = Spree::Taxonomy.find_by(name: 'Events')
|
26
|
+
return if @taxonomy
|
27
|
+
|
28
|
+
flash[:error] = Spree.t('admin.events.taxonomy_not_found')
|
29
|
+
redirect_to admin_events_path
|
30
|
+
end
|
31
|
+
|
32
|
+
def taxon_scope
|
33
|
+
@taxonomy ? Spree::Taxon.where(kind: 2, depth: 1) : Spree::Taxon.none
|
34
|
+
end
|
35
|
+
|
36
|
+
def filtered_taxons
|
37
|
+
taxon_scope.where(id: params[:taxon_id]).or(
|
38
|
+
taxon_scope.where(parent_id: params[:taxon_id])
|
39
|
+
).distinct
|
40
|
+
end
|
41
|
+
|
42
|
+
def searched_taxons
|
43
|
+
@search.result(distinct: true)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Spree
|
2
|
+
module Admin
|
3
|
+
module PrototypesControllerDecorator
|
4
|
+
def self.prepended(base)
|
5
|
+
base.before_action :load_icons
|
6
|
+
end
|
7
|
+
|
8
|
+
# overrided
|
9
|
+
def find_resource
|
10
|
+
Spree::Prototype.friendly.find(params[:id])
|
11
|
+
end
|
12
|
+
|
13
|
+
def load_icons
|
14
|
+
@icons = SpreeCmCommissioner::VectorIcon.all
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
Spree::Admin::PrototypesController.prepend(Spree::Admin::PrototypesControllerDecorator)
|
@@ -12,9 +12,25 @@ module Spree
|
|
12
12
|
def index
|
13
13
|
@variants = @product.variants.includes(:images, stock_items: :stock_location, option_values: :option_type)
|
14
14
|
@variants = [@product.master] if @variants.empty?
|
15
|
-
|
16
15
|
@stock_locations = (@variants.flat_map(&:stock_locations) + @product.vendor.stock_locations).uniq
|
17
16
|
|
17
|
+
load_inventories unless @product.permanent_stock?
|
18
|
+
end
|
19
|
+
|
20
|
+
def calendar
|
21
|
+
@year = params[:year].present? ? params[:year].to_i : Time.zone.today.year
|
22
|
+
|
23
|
+
from_date = Date.new(@year, 1, 1).beginning_of_year
|
24
|
+
to_date = Date.new(@year, 1, 1).end_of_year
|
25
|
+
|
26
|
+
@inventory_items = @product.inventory_items.includes(:variant).where(inventory_date: from_date..to_date).to_a
|
27
|
+
@events = SpreeCmCommissioner::CalendarEvent.from_inventory_items(@inventory_items)
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def load_inventories
|
33
|
+
@inventory_items = @product.inventory_items.group_by { |item| item.variant.id }
|
18
34
|
@reserved_stocks = Spree::LineItem
|
19
35
|
.complete
|
20
36
|
.where(variant_id: @variants.pluck(:id))
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Spree
|
2
|
+
module Api
|
3
|
+
module V2
|
4
|
+
module Storefront
|
5
|
+
class Accommodations::VariantsController < ::Spree::Api::V2::ResourceController
|
6
|
+
private
|
7
|
+
|
8
|
+
# override
|
9
|
+
def collection
|
10
|
+
@collection ||= SpreeCmCommissioner::Accommodations::FindVariant.new(
|
11
|
+
from_date: params[:from_date]&.to_date,
|
12
|
+
to_date: params[:to_date]&.to_date,
|
13
|
+
vendor_id: params[:accommodation_id],
|
14
|
+
number_of_adults: params[:number_of_adults].to_i,
|
15
|
+
number_of_kids: params[:number_of_kids].to_i
|
16
|
+
).execute
|
17
|
+
end
|
18
|
+
|
19
|
+
# override
|
20
|
+
def resource
|
21
|
+
@resource ||= collection.find(params[:id])
|
22
|
+
end
|
23
|
+
|
24
|
+
# override
|
25
|
+
def resource_serializer
|
26
|
+
Spree::V2::Storefront::VariantSerializer
|
27
|
+
end
|
28
|
+
|
29
|
+
# override
|
30
|
+
def collection_serializer
|
31
|
+
Spree::V2::Storefront::VariantSerializer
|
32
|
+
end
|
33
|
+
|
34
|
+
# override
|
35
|
+
def required_schema
|
36
|
+
SpreeCmCommissioner::VariantRequestSchema
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -5,55 +5,38 @@ module Spree
|
|
5
5
|
class AccommodationsController < ::Spree::Api::V2::ResourceController
|
6
6
|
private
|
7
7
|
|
8
|
+
# override
|
8
9
|
def collection
|
9
|
-
@collection ||=
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
@paginated_collection = apply_service_availability(@paginated_collection)
|
10
|
+
@collection ||= SpreeCmCommissioner::Accommodations::Find.new(
|
11
|
+
from_date: params[:from_date]&.to_date,
|
12
|
+
to_date: params[:to_date]&.to_date,
|
13
|
+
state_id: params[:state_id],
|
14
|
+
number_of_adults: params[:number_of_adults].to_i,
|
15
|
+
number_of_kids: params[:number_of_kids].to_i
|
16
|
+
).execute
|
17
17
|
end
|
18
18
|
|
19
|
+
# override
|
19
20
|
def resource
|
20
|
-
resource
|
21
|
-
raise ActiveRecord::RecordNotFound if resource.nil?
|
22
|
-
|
23
|
-
apply_service_availability(resource)
|
24
|
-
end
|
25
|
-
|
26
|
-
def apply_service_availability(resource)
|
27
|
-
SpreeCmCommissioner::ApplyServiceAvailability.call(calendarable: resource,
|
28
|
-
from_date: params[:from_date].to_date,
|
29
|
-
to_date: params[:to_date].to_date
|
30
|
-
).value
|
21
|
+
@resource ||= collection.find(params[:id])
|
31
22
|
end
|
32
23
|
|
24
|
+
# override
|
33
25
|
def allowed_sort_attributes
|
34
26
|
super << :min_price << :max_price
|
35
27
|
end
|
36
28
|
|
37
|
-
|
38
|
-
Spree::Vendor
|
39
|
-
end
|
40
|
-
|
29
|
+
# override
|
41
30
|
def resource_serializer
|
42
31
|
Spree::V2::Storefront::AccommodationSerializer
|
43
32
|
end
|
44
33
|
|
34
|
+
# override
|
45
35
|
def collection_serializer
|
46
36
|
Spree::V2::Storefront::AccommodationSerializer
|
47
37
|
end
|
48
38
|
|
49
|
-
|
50
|
-
SpreeCmCommissioner::AccommodationSearchDetail
|
51
|
-
end
|
52
|
-
|
53
|
-
def resource_finder
|
54
|
-
SpreeCmCommissioner::AccommodationSearchDetail
|
55
|
-
end
|
56
|
-
|
39
|
+
# override
|
57
40
|
def required_schema
|
58
41
|
SpreeCmCommissioner::AccommodationRequestSchema
|
59
42
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module SpreeCmCommissioner
|
2
|
+
module Accommodations
|
3
|
+
class Find
|
4
|
+
attr_reader :from_date, :to_date, :state_id, :number_of_guests
|
5
|
+
|
6
|
+
def initialize(from_date:, to_date:, state_id:, number_of_adults:, number_of_kids:)
|
7
|
+
@from_date = from_date
|
8
|
+
@to_date = to_date
|
9
|
+
@state_id = state_id
|
10
|
+
@number_of_guests = number_of_adults.to_i + number_of_kids.to_i
|
11
|
+
end
|
12
|
+
|
13
|
+
def execute
|
14
|
+
scope
|
15
|
+
.where(default_state_id: state_id)
|
16
|
+
.where(inventory_items: { inventory_date: date_range_excluding_checkout })
|
17
|
+
.where('CAST(spree_variants.public_metadata->\'cm_options\'->>\'number-of-adults\' AS INTEGER) +
|
18
|
+
CAST(spree_variants.public_metadata->\'cm_options\'->>\'number-of-kids\' AS INTEGER) >= ?', number_of_guests
|
19
|
+
)
|
20
|
+
.where('inventory_items.quantity_available > 0')
|
21
|
+
.distinct
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def scope
|
27
|
+
Spree::Vendor
|
28
|
+
.joins(variants: :inventory_items)
|
29
|
+
.where(primary_product_type: :accommodation, state: :active)
|
30
|
+
end
|
31
|
+
|
32
|
+
# Why? check_out date is not considered to be charged
|
33
|
+
# For example, if you check in on 2023-10-01 and check out on 2023-10-02,
|
34
|
+
# you will be charged for one night (2023-10-01).
|
35
|
+
def date_range_excluding_checkout
|
36
|
+
from_date..to_date.prev_day
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module SpreeCmCommissioner
|
2
|
+
module Accommodations
|
3
|
+
class FindVariant
|
4
|
+
attr_reader :vendor_id, :from_date, :to_date, :number_of_guests
|
5
|
+
|
6
|
+
def initialize(vendor_id:, from_date:, to_date:, number_of_adults:, number_of_kids:)
|
7
|
+
@vendor_id = vendor_id
|
8
|
+
@from_date = from_date
|
9
|
+
@to_date = to_date
|
10
|
+
@number_of_guests = number_of_adults.to_i + number_of_kids.to_i
|
11
|
+
end
|
12
|
+
|
13
|
+
def execute
|
14
|
+
Spree::Variant
|
15
|
+
.joins(:inventory_items)
|
16
|
+
.where(vendor_id: vendor_id)
|
17
|
+
.where(inventory_items: { inventory_date: date_range_excluding_checkout })
|
18
|
+
.where('CAST(public_metadata->\'cm_options\'->>\'number-of-adults\' AS INTEGER) +
|
19
|
+
CAST(public_metadata->\'cm_options\'->>\'number-of-kids\' AS INTEGER) >= ?', number_of_guests
|
20
|
+
)
|
21
|
+
.where('inventory_items.quantity_available > 0')
|
22
|
+
.distinct
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
# Why? check_out date is not considered to be charged
|
28
|
+
# For example, if you check in on 2023-10-01 and check out on 2023-10-02,
|
29
|
+
# you will be charged for one night (2023-10-01).
|
30
|
+
def date_range_excluding_checkout
|
31
|
+
from_date..to_date.prev_day
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module SpreeCmCommissioner
|
2
|
+
class CreateEvent
|
3
|
+
include Interactor
|
4
|
+
delegate :params, :current_vendor, to: :context
|
5
|
+
|
6
|
+
def call
|
7
|
+
ActiveRecord::Base.transaction do
|
8
|
+
build_parent_taxon
|
9
|
+
assign_vendor
|
10
|
+
assign_prototype
|
11
|
+
create_child_taxon
|
12
|
+
build_home_banner
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def build_parent_taxon
|
19
|
+
@parent_taxon = Spree::Taxon.new(
|
20
|
+
name: context.params[:name],
|
21
|
+
description: context.params[:description],
|
22
|
+
from_date: context.params[:from_date],
|
23
|
+
to_date: context.params[:to_date],
|
24
|
+
parent_id: context.params[:parent_id],
|
25
|
+
taxonomy_id: context.params[:taxonomy_id]
|
26
|
+
)
|
27
|
+
|
28
|
+
return if @parent_taxon.save
|
29
|
+
|
30
|
+
context.fail!(message: @parent_taxon.errors.full_messages.join(', '))
|
31
|
+
end
|
32
|
+
|
33
|
+
def assign_vendor
|
34
|
+
@parent_taxon.vendors << context.current_vendor
|
35
|
+
end
|
36
|
+
|
37
|
+
def assign_prototype
|
38
|
+
prototype = Spree::Prototype.find_by(slug: context.params[:prototype_id])
|
39
|
+
@parent_taxon.prototypes << prototype if prototype.present?
|
40
|
+
end
|
41
|
+
|
42
|
+
def create_child_taxon
|
43
|
+
child_taxon = Spree::Taxon.new(
|
44
|
+
name: 'Ticket Type',
|
45
|
+
parent_id: @parent_taxon.id,
|
46
|
+
taxonomy_id: context.params[:taxonomy_id]
|
47
|
+
)
|
48
|
+
|
49
|
+
return if child_taxon.save
|
50
|
+
|
51
|
+
context.fail!(message: child_taxon.errors.full_messages.join(', '))
|
52
|
+
end
|
53
|
+
|
54
|
+
def build_home_banner
|
55
|
+
return if context.params[:home_banner].nil?
|
56
|
+
|
57
|
+
banner = SpreeCmCommissioner::TaxonHomeBanner.create(
|
58
|
+
viewable: @parent_taxon,
|
59
|
+
attachment: context.params[:home_banner]
|
60
|
+
)
|
61
|
+
|
62
|
+
context.fail!(message: 'Home banner upload failed') unless banner.persisted?
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -2,11 +2,37 @@ require 'firebase-admin-sdk'
|
|
2
2
|
|
3
3
|
module SpreeCmCommissioner
|
4
4
|
class FirebaseEmailFetcher < BaseInteractor
|
5
|
-
delegate :user_id, to: :context
|
5
|
+
delegate :user_id, :sub, to: :context
|
6
|
+
|
7
|
+
# Firebase response
|
8
|
+
# {
|
9
|
+
# "localId" => "8AGwn0V88kP7vkticwuYZkNNoIJ2",
|
10
|
+
# "displayName" => "Sreyleak Deth",
|
11
|
+
# "photoUrl" => "https://lh3.googleusercontent.com/a/ACg8ocIkL62VaxNb7bOAXV30sZOGQ_Dw7ZYvlBH-Hk2jm3swNg=s96-c",
|
12
|
+
# "providerUserInfo" => [
|
13
|
+
# {
|
14
|
+
# "providerId" => "google.com",
|
15
|
+
# "displayName" => "Sreyleak Deth",
|
16
|
+
# "photoUrl" => "https://lh3.googleusercontent.com/a/ACg8ocK88Fm3GhVeCS98vLGE-vmShSi76xZwYYA1QwImuyck7zAqpR0=s96-c",
|
17
|
+
# "federatedId" => "109192493976909808585",
|
18
|
+
# "email" => "sreyleak.deth19@gmail.com",
|
19
|
+
# "rawId" => "109192493976909808585"
|
20
|
+
# }
|
21
|
+
# ],
|
22
|
+
# "validSince" => "1707378937",
|
23
|
+
# "lastLoginAt" => "1739440924021",
|
24
|
+
# "createdAt" => "1707378937388",
|
25
|
+
# "lastRefreshAt" => "2025-04-01T08:54:24.480031Z"
|
26
|
+
# }
|
6
27
|
|
7
28
|
def call
|
8
|
-
manager = initialize_firebase_manager
|
9
|
-
|
29
|
+
@manager = initialize_firebase_manager
|
30
|
+
|
31
|
+
if context.user_id.present?
|
32
|
+
user = @manager.get_user_by(uid: context.user_id)
|
33
|
+
elsif context.sub.present?
|
34
|
+
user = @manager.get_user_by_sub(sub: context.sub)
|
35
|
+
end
|
10
36
|
|
11
37
|
context.email = user.provider_data.first&.email
|
12
38
|
end
|
@@ -19,7 +45,7 @@ module SpreeCmCommissioner
|
|
19
45
|
|
20
46
|
def initialize_firebase_manager
|
21
47
|
@credentials ||= Firebase::Admin::Credentials.from_json(service_account.to_json)
|
22
|
-
|
48
|
+
Firebase::Admin::Auth::UserManager.new(service_account[:project_id], @credentials)
|
23
49
|
end
|
24
50
|
end
|
25
51
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module SpreeCmCommissioner
|
2
|
+
class FirebaseEmailFetcherCronExecutor < BaseInteractor
|
3
|
+
def call
|
4
|
+
users = Spree::User.includes(:google_user_identity_providers)
|
5
|
+
.joins(:google_user_identity_providers)
|
6
|
+
.where(email: nil)
|
7
|
+
|
8
|
+
users.find_each do |user|
|
9
|
+
google_identity = user.google_user_identity_providers.first
|
10
|
+
firebase_user = SpreeCmCommissioner::FirebaseEmailFetcher.call(sub: google_identity.sub)
|
11
|
+
next unless firebase_user.success?
|
12
|
+
|
13
|
+
email = firebase_user.email
|
14
|
+
|
15
|
+
next if email.blank?
|
16
|
+
next if Spree::User.exists?(email: email)
|
17
|
+
|
18
|
+
google_identity.update(email: email)
|
19
|
+
user.update(email: email)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module SpreeCmCommissioner
|
2
|
+
class InventoryItemSyncer < BaseInteractor
|
3
|
+
# inventory_id_and_quantities = [{ inventory_id: inventory_item1.id, quantity: 5 } ]
|
4
|
+
delegate :inventory_id_and_quantities, to: :context
|
5
|
+
|
6
|
+
def call
|
7
|
+
ActiveRecord::Base.transaction do
|
8
|
+
inventory_items.each do |inventory_item|
|
9
|
+
quantity = inventory_id_and_quantities.find { |item| item[:inventory_id] == inventory_item.id }&.dig(:quantity) || 0
|
10
|
+
adjust_quantity_available(inventory_item, quantity)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def adjust_quantity_available(inventory_item, quantity)
|
18
|
+
inventory_item.update!(quantity_available: inventory_item.quantity_available + quantity)
|
19
|
+
end
|
20
|
+
|
21
|
+
def inventory_items
|
22
|
+
@inventory_items ||= InventoryItem.where(id: inventory_id_and_quantities.pluck(:inventory_id))
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|