tiny_builder 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: e052508ea63349c2f46abe6399a5c8bc1300601f832f03dc1494b515935e5449
4
+ data.tar.gz: 1e2393239ba81d30bd1051db3da032579f4aec616b6fa4df50020f368ddafbed
5
+ SHA512:
6
+ metadata.gz: 5894b6bc636d5e63db1233e5035bd10154ca97ec5b9b933a480c7e50a8d77b7a1fd9a5c2a6c53d809aca3f0ffdfb6608c97b3617bf5ec131cd85fee6cd1c4448
7
+ data.tar.gz: 83e9a103b7e32e27e0987444df03407fc766cb7aa200abc9c3c1232bc846db48c7fd55e84b265b327aed5bcb6f6fafa3f8e629d5c0b967f920bc39635fcad134
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ class MasterProduct
4
+ include Mongoid::Document
5
+ include Mongoid::Attributes::Dynamic
6
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ class MongoItemListing
4
+ include Mongoid::Document
5
+ include Mongoid::Attributes::Dynamic
6
+
7
+ store_in collection: 'listings'
8
+
9
+ def master_product
10
+ @master_product ||= MasterProduct.where(product_id: master_product_id).first
11
+ end
12
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ class MongoVariantListing
4
+ include Mongoid::Document
5
+ include Mongoid::Attributes::Dynamic
6
+
7
+ store_in collection: 'listings'
8
+
9
+ def local_item_id
10
+ item_listing.local_id
11
+ end
12
+
13
+ def item_listing
14
+ @item_listing ||= MongoItemListing.where(variants: id).first
15
+ end
16
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'tiny_builder/base_builder'
4
+
5
+ class TinyBuilder
6
+ class ActiveBuilder < BaseBuilder
7
+ def to_h(listing)
8
+ {
9
+ active: listing.active,
10
+ active_variant: active_variant
11
+ }
12
+ end
13
+
14
+ private
15
+
16
+ def active_variant
17
+ listing.item_listing.variants.map do |v_id|
18
+ MongoVariantListing.find(v_id)
19
+ end.select { |mvl| mvl.active }.size
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ class TinyBuilder
4
+ module AllocatedStock
5
+ def allocated_stock_active?
6
+ stock_alloc.present? &&
7
+ stock_alloc.start_at <= Time.now &&
8
+ stock_alloc.end_at >= Time.now
9
+ end
10
+
11
+ def count_allocated_stock
12
+ stock_alloc.quantity.to_i - one_alloc_rsvd_stock(stock_alloc).to_i
13
+ end
14
+
15
+ def host
16
+ url = ENV['ORDERS_URL'] || 'orders.forstok.com'
17
+ url + '/api/v2/item_line/count_one_allocated_reserved_stock'
18
+ end
19
+
20
+ def params(allocated_stock)
21
+ {
22
+ channel_id: allocated_stock.variant_listing.channel_id,
23
+ item_variant_id: allocated_stock.variant_listing.variant_id,
24
+ start_at: allocated_stock.start_at,
25
+ end_at: allocated_stock.end_at
26
+ }.to_query
27
+ end
28
+
29
+ # one_alloc_rsvd_stock fungsi untuk mendapatkan satu
30
+ # allocated reserved stock
31
+ def one_alloc_rsvd_stock(allocated_stock)
32
+ RestClient.get("#{host}?#{params(allocated_stock)}")
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'tiny_builder/data_loader'
4
+
5
+ class TinyBuilder
6
+ class BaseBuilder
7
+ DataLoader
8
+
9
+ attr_reader :listings
10
+ attr_reader :mwh
11
+
12
+ def initialize(args)
13
+ @listings = args[:listings]
14
+ @mwh = args[:mwh]
15
+ end
16
+
17
+ def perform
18
+ listings.map do |listing|
19
+ {
20
+ id: listing.icava_id,
21
+ local_id: listing.local_id,
22
+ local_item_id: listing.local_item_id,
23
+ sku: listing.sku,
24
+ variant_id: listing.master_variant_id
25
+ }.merge(to_h(listing))
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,101 @@
1
+ # frozen_string_literal: true
2
+
3
+ class TinyBuilder
4
+ module DataLoader
5
+ def variants
6
+ @variants ||= Variant.where(
7
+ id: listings.map(&:master_variant_id)
8
+ )
9
+ end
10
+
11
+ def collect_variants_data
12
+ data = Variant.where(
13
+ id: listings.map(&:master_variant_id)
14
+ )
15
+ listings.map do |listing|
16
+ [listing.icava_id, data.find{ |v| v.id == listing.master_variant_id }]
17
+ end
18
+ end
19
+
20
+ def variant_ids
21
+ @variant_ids ||= variants.map(&:id)
22
+ end
23
+
24
+ def account_id
25
+ listings[0]&.account_id
26
+ end
27
+
28
+ def warehouse_mappings
29
+ @warehouse_mappings ||= WarehouseMapping.joins(:warehouse).where(
30
+ profile_channel_association_id: account_id
31
+ ).where(warehouses: {consignment: false})
32
+ end
33
+
34
+ def warehouse_mapping
35
+ warehouse_mapping ||= warehouse_mappings.first
36
+ end
37
+
38
+ def mapped_wh_mappings
39
+ @mapped_wh_mappings ||= warehouse_mappings.select(:warehouse_id, :channel_warehouse_id).to_h
40
+ end
41
+
42
+ def associated_listings
43
+ @associated_listings ||= collect_associated_listings
44
+ end
45
+
46
+ def collect_associated_listings
47
+ data = []
48
+ MongoVariantListing.in(master_variant_id: variant_ids).each do |listing|
49
+ data << listing
50
+ end
51
+ data
52
+ end
53
+
54
+ def stock_allocations
55
+ @stock_allocations ||= VariantListingStockAllocation.where(
56
+ variant_association_id: listing_ids
57
+ ).where('end_at >= NOW()')
58
+ end
59
+
60
+ def associated_stock_allocations
61
+ @associated_stock_allocations ||= VariantListingStockAllocation.where(
62
+ variant_association_id: associated_listings.map(&:icava_id)
63
+ ).where('end_at >= NOW()')
64
+ end
65
+
66
+ def warehouse_spaces
67
+ @warehouse_spaces ||= WarehouseSpace.where(item_variant_id: variant_ids).where.not(warehouse_id: nil)
68
+ end
69
+
70
+ def listing_warehouse_spaces(listing)
71
+ warehouse_spaces.select{ |wh_space| wh_space.item_variant_id == listing.master_variant_id }
72
+ end
73
+
74
+ def mapped_data
75
+ @mapped_data ||= listings.map do |listing|
76
+ [
77
+ listing.icava_id,
78
+ {
79
+ variant: variants.find{ |v| v.id == listing.master_variant_id },
80
+ warehouse_spaces: listing_warehouse_spaces(listing),
81
+ stock_alloc: stock_alloc(listing),
82
+ associated_stock_allocs: associated_stock_allocs(listing)
83
+ }
84
+ ]
85
+ end.to_h
86
+ end
87
+
88
+ def stock_alloc(listing)
89
+ stock_allocations.find{ |sa| sa.variant_association_id == listing.icava_id }
90
+ end
91
+
92
+ def associated_stock_allocs(listing)
93
+ ids = associated_listings.select{ |l| l.master_variant_id == listing.maaster_variant_id }.map(&:icava_id)
94
+ associated_stock_allocations.map do |asa|
95
+ if ids.include?(asa)
96
+ asa
97
+ end
98
+ end.compact
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ class TinyBuilder
4
+ module ModeExecutor
5
+ def build_quantity
6
+ TinyBuilder::QuantityBuilder.new(
7
+ listings: listings,
8
+ mwh: mwh
9
+ ).perform
10
+ end
11
+
12
+ def build_price
13
+ []
14
+ end
15
+
16
+ def build_active
17
+ []
18
+ end
19
+
20
+ def quantity_params(listing)
21
+ end
22
+
23
+ def listings
24
+ @listings ||= collect_listings
25
+ end
26
+
27
+ def collect_listings
28
+ data = []
29
+ MongoVariantListing.in(icava_id: listing_ids).each do |listing|
30
+ data << listing
31
+ end
32
+ data
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'tiny_builder/base_builder'
4
+
5
+ class TinyBuilder
6
+ class PriceBuilder < BaseBuilder
7
+ def to_h(listing)
8
+ {
9
+ price: listing.price,
10
+ sale_price: listing.sale_price,
11
+ sale_start_at: listing.sale_start_at,
12
+ sale_end_at: listing.sale_end_at
13
+ }
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'tiny_builder/base_builder'
4
+ require 'tiny_builder/quantity_counter'
5
+
6
+ class TinyBuilder
7
+ class QuantityBuilder < BaseBuilder
8
+ def to_h(listing)
9
+ if mwh
10
+ { warehouse: warehouse_quantities(listing) }
11
+ else
12
+ { quantity: quantity(listing) }
13
+ end
14
+ end
15
+
16
+ def warehouse_quantities(listing)
17
+ results = multi_warehouse_spaces(listing).map do |wh_space|
18
+ {
19
+ id: wh_space&.warehouse_id,
20
+ quantity: quantity(listing, wh_space),
21
+ warehouse_id: mapped_wh_mappings[wh_space.warehouse_id]
22
+ }
23
+ end
24
+ end
25
+
26
+ def quantity(listing, wh_space = nil)
27
+ QuantityCounter.new(
28
+ counter_params(listing, wh_space)
29
+ ).perform
30
+ end
31
+
32
+ def counter_params(listing, wh_space = nil)
33
+ params = mapped_data[listing.icava_id].slice(:variant, :stock_alloc, :associated_stock_allocs)
34
+ wh_space ||= single_warehouse_space(mapped_data[listing.icava_id][:warehouse_spaces])
35
+ params.merge(warehouse_space: wh_space)
36
+ end
37
+
38
+ def single_warehouse_space
39
+ if warehouse_id
40
+ warehuse_spaces.find{ |wh_space| wh_space.warehouse_id == wh_id }
41
+ else
42
+ warehuse_spaces.last
43
+ end
44
+ end
45
+
46
+ def multi_warehouse_spaces(listing)
47
+ mapped_data[listing.icava_id][:warehouse_spaces].select do |wh_space|
48
+ warehouse_mappings.map(&:warehouse_id).include?(wh_space.warehouse_id)
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'tiny_builder/allocated_stock'
4
+
5
+ class TinyBuilder
6
+ class QuantityCounter
7
+ include AllocatedStock
8
+
9
+ attr_reader :variant
10
+ attr_reader :stock_alloc
11
+ attr_reader :associated_stock_allocs
12
+ attr_reader :warehouse_space
13
+ def initialize(args)
14
+ @variant = args[:variant]
15
+ @stock_alloc = args[:stock_alloc]
16
+ @associated_stock_allocs = args[:associated_stock_allocs]
17
+ @warehouse_space = args[:warehouse_space]
18
+ end
19
+
20
+ def perform
21
+ if allocated_stock_active?
22
+ # yang masuk di kondisi ini,
23
+ # artinya akun tersebut ada allocated stock yang aktif
24
+ count_allocated_stock
25
+ elsif associated_stock_allocs.present?
26
+ # yang masuk di kondisi ini,
27
+ # artinya akun tersebut tidak ada allocated stock yang aktif,
28
+ # namun ada allocated stock yg aktif dari channel lain
29
+ warehouse_stock - count_existing_alloc_stock + count_alloc_rsvd_stock
30
+ else
31
+ # yang masuk di kondisi ini,
32
+ # artinya tidak ada allocated stock di item tersebut
33
+ warehouse_stock
34
+ end
35
+ end
36
+
37
+ def warehouse_stock
38
+ case variant.config.downcase
39
+ when 'default'
40
+ qty_default
41
+ when 'free gift', 'combo'
42
+ qty_bundle
43
+ else
44
+ raise "config not recognize => #{variant.config}"
45
+ end
46
+ end
47
+
48
+ def qty_default
49
+ [(warehouse_space&.quantity || 0), 0].max
50
+ end
51
+
52
+ def qty_bundle
53
+ if bundle_product
54
+ qty_list = []
55
+ bundle_variants.each do |bv|
56
+ wh_space = WarehouseSpace.find_by(
57
+ item_variant_id: bv[:master_variant_id],
58
+ warehouse_id: wh_space.warehouse_id
59
+ )
60
+ qty = wh_space.quantity if wh_space.present?
61
+ qty ||= 0
62
+ qty = qty / bv[:bundle_attribute][:quantity]
63
+ qty_list.push(qty)
64
+ end
65
+ [qty_list.min, 0].sort[1]
66
+ else
67
+ qty_default
68
+ end
69
+ end
70
+
71
+ def bundle_variants
72
+ bundle = MasterProduct.where("bundle_variants.master_variant_id": variant.id).last
73
+ bundle.bundle_variants.select { |bv| !bv[:main] }
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ class TinyBuilder
4
+ VERSION = '0.0.1'
5
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'tiny_builder/version'
4
+ require 'tiny_builder/mode_executor'
5
+ require 'models/mongo_item_listing'
6
+ require 'models/mongo_variant_listing'
7
+
8
+ class TinyBuilder
9
+ include ModeExecutor
10
+
11
+ attr_reader :listing_ids, :mode, :multiwarehouse
12
+
13
+ def self.build(listing_ids, mode, multiwarehouse)
14
+ new(listing_ids, mode, mwh).perform
15
+ end
16
+
17
+ def initialize(listing_ids, mode, mwh)
18
+ @listing_ids = listing_ids
19
+ @mode = mode
20
+ @multiwarehouse = multiwarehouse
21
+ end
22
+
23
+ def perform
24
+ send("build_#{mode}")
25
+ end
26
+ end
metadata ADDED
@@ -0,0 +1,167 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tiny_builder
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - hayakaza
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2023-09-25 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 1.17.2
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 1.17.2
27
+ - !ruby/object:Gem::Dependency
28
+ name: byebug
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 11.1.0
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 11.1.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '10.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '10.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '3.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '3.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rubocop
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 0.79.0
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 0.79.0
83
+ - !ruby/object:Gem::Dependency
84
+ name: item_models_2
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 0.0.21
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 0.0.21
97
+ - !ruby/object:Gem::Dependency
98
+ name: warehouse_models
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: 0.1.2
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: 0.1.2
111
+ - !ruby/object:Gem::Dependency
112
+ name: mongoid
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: 7.0.5
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: 7.0.5
125
+ description: Forstok Gem to build simple export listing
126
+ email:
127
+ - hayhay2301@gmail.com
128
+ executables: []
129
+ extensions: []
130
+ extra_rdoc_files: []
131
+ files:
132
+ - lib/models/master_product.rb
133
+ - lib/models/mongo_item_listing.rb
134
+ - lib/models/mongo_variant_listing.rb
135
+ - lib/tiny_builder.rb
136
+ - lib/tiny_builder/active_builder.rb
137
+ - lib/tiny_builder/allocated_stock.rb
138
+ - lib/tiny_builder/base_builder.rb
139
+ - lib/tiny_builder/data_loader.rb
140
+ - lib/tiny_builder/mode_executor.rb
141
+ - lib/tiny_builder/price_builder.rb
142
+ - lib/tiny_builder/quantity_builder.rb
143
+ - lib/tiny_builder/quantity_counter.rb
144
+ - lib/tiny_builder/version.rb
145
+ homepage:
146
+ licenses: []
147
+ metadata: {}
148
+ post_install_message:
149
+ rdoc_options: []
150
+ require_paths:
151
+ - lib
152
+ required_ruby_version: !ruby/object:Gem::Requirement
153
+ requirements:
154
+ - - ">="
155
+ - !ruby/object:Gem::Version
156
+ version: 2.3.0
157
+ required_rubygems_version: !ruby/object:Gem::Requirement
158
+ requirements:
159
+ - - ">="
160
+ - !ruby/object:Gem::Version
161
+ version: '0'
162
+ requirements: []
163
+ rubygems_version: 3.0.3
164
+ signing_key:
165
+ specification_version: 4
166
+ summary: Simple item builder for Forstok
167
+ test_files: []