tiny_builder 0.0.1

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 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: []