comee_core 0.1.45.pre3 → 0.1.46

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cdf4d95f06116fc407191db6b1571999c236053b5c9805315cf4858b55c26452
4
- data.tar.gz: 6629ed11e8508b32d5b04b5c441caee0437b8ba590307d940442bb92e3dfd599
3
+ metadata.gz: b627b9c57084edd4b480f661502a765f0988cfca86b25c42691b19d650d5dc5b
4
+ data.tar.gz: 9f3f4164affa01dc56b3d2f13b8ec9ac2efca5e0a99d58d935bc33360baacfa5
5
5
  SHA512:
6
- metadata.gz: d7640b1d8e0fb87d7fe92759527ac31e6d9beb8116a49102d3949f8d55820b89d103f8075b46da1d923a2f1f635524d1c0147187a6c48aecdfba3a05079e8044
7
- data.tar.gz: 55e1a668a581b7db5c644029626fc67976f341e07054251adb0fe89a952653c04e9af86c0ae938af23fdd454388595566f8b95bde01032948f6149f93a8bc115
6
+ metadata.gz: 43c210add4f2c3d2f87535b251ba52e22d0b477439dde17116b95e2c5f12133e800c09cd628967497b5d42a20970ffc753ebb0826ff6361838d15406df601e82
7
+ data.tar.gz: d1a70bed42a7c03cf4473cda58ad8776566c696713ded246742e044ce8b2aeb27f76b37d7a23e509628bcb9b4d0e522bcc5828d18ad4ad1e22c32148fe40af13
@@ -20,7 +20,7 @@ module Comee
20
20
  private
21
21
 
22
22
  def model_params
23
- params.required(:payload).permit(:code, :name, :description, :parent_id, :thumbnail_image, images: [])
23
+ params.required(:payload).permit(:code, :name, :description, :parent_id, :thumbnail_image, :preferred_units, images: [])
24
24
  end
25
25
  end
26
26
  end
@@ -9,6 +9,12 @@ module Comee
9
9
  end
10
10
  end
11
11
 
12
+ def suggest_values
13
+ service = CustomerOrderService.new
14
+ result = service.suggest_values(params[:id], params[:unit_id])
15
+ render json: {success: true, data: result}
16
+ end
17
+
12
18
  def destroy
13
19
  Comee::Core::SalesOrderItem.destroy(params[:id])
14
20
  render json: {success: true}
@@ -0,0 +1,19 @@
1
+ module Comee
2
+ module Core
3
+ class UnitConversionsController < ApplicationController
4
+ include Common
5
+
6
+ def index
7
+ super do
8
+ Comee::Core::UnitConversion.includes(:from, :to).all
9
+ end
10
+ end
11
+
12
+ private
13
+
14
+ def model_params
15
+ params.require(:payload).permit(:from_id, :to_id, :factor)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -25,13 +25,8 @@ module Comee
25
25
  return unless product && primary
26
26
 
27
27
  price = MasterPrice.find_by(product: product, primary: true, status: Price.statuses[:current])
28
- Rails.logger.info("Existing price: ")
29
- Rails.logger.info(price)
30
- Rails.logger.info("Current price:")
31
- Rails.logger.info(self)
32
28
  return unless price && price.id != id && status == price.status
33
29
 
34
- Rails.logger.info("RAISING ERROR ...")
35
30
  errors.add(:base, "There is already a primary price entry for item '#{product.code}'")
36
31
  end
37
32
 
@@ -25,6 +25,10 @@ module Comee
25
25
  def images_url
26
26
  images.attached? ? images.map { |image| Rails.application.routes.url_helpers.rails_blob_url(image, only_path: false) } : []
27
27
  end
28
+
29
+ def default_unit
30
+ preferred_units.find { |unit| unit["default"] }
31
+ end
28
32
  end
29
33
  end
30
34
  end
@@ -0,0 +1,10 @@
1
+ module Comee
2
+ module Core
3
+ class UnitConversion < ApplicationRecord
4
+ belongs_to :from, class_name: "Comee::Core::Unit"
5
+ belongs_to :to, class_name: "Comee::Core::Unit"
6
+
7
+ validates :factor, presence: true, numericality: {greater_than: 0}
8
+ end
9
+ end
10
+ end
@@ -1,7 +1,7 @@
1
1
  module Comee
2
2
  module Core
3
3
  class ProductSerializer < ActiveModel::Serializer
4
- attributes :id, :code, :name, :description, :thumbnail_image_url, :images_url
4
+ attributes :id, :code, :name, :description, :thumbnail_image_url, :images_url, :preferred_units
5
5
  end
6
6
  end
7
7
  end
@@ -0,0 +1,9 @@
1
+ module Comee
2
+ module Core
3
+ class UnitConversionSerializer < ActiveModel::Serializer
4
+ attributes :id, :factor
5
+ belongs_to :from
6
+ belongs_to :to
7
+ end
8
+ end
9
+ end
@@ -1,6 +1,76 @@
1
1
  module Comee
2
2
  module Core
3
3
  class CustomerOrderService
4
+ ##
5
+ # This method converts a price value per a unit of measure to a price value per another
6
+ # unit of measure.
7
+ #
8
+ # @param price [Numeric] the price value
9
+ # @param unit [Numeric] the unit id of measure for the price
10
+ # @param new_unit [Numeric] the new unit id of measure
11
+ #
12
+ # @return [Numeric] the converted price for the new unit
13
+ #
14
+ def convert_price(price, unit_id, new_unit_id)
15
+ return price if unit_id == new_unit_id
16
+
17
+ conversions = UnitConversion.where("from_id = ? AND to_id = ?", unit_id, new_unit_id)
18
+ .or(UnitConversion.where("from_id = ? AND to_id = ?", new_unit_id, unit_id))
19
+ unless conversions.count.positive?
20
+ units = Unit.where(id: [unit_id, new_unit_id]).select(:code)
21
+ raise(StandardError, "There is no conversion factor between #{units[0].code} and #{units[1].code}.")
22
+ end
23
+
24
+ conversion = conversions.first
25
+ return (price / conversion.factor).round(2) if unit_id == conversion.from_id && new_unit_id == conversion.to_id
26
+
27
+ (price * conversion.factor).round(2)
28
+ end
29
+
30
+ ##
31
+ # This method converts a price value per a unit of measure to a price value per another
32
+ # unit of measure.
33
+ #
34
+ # @param quantity [Numeric] the price value
35
+ # @param unit_id [Numeric] the unit id of measure for the price
36
+ # @param new_unit_id [Numeric] the new unit id of measure
37
+ #
38
+ # @return [Numeric] the converted price for the new unit
39
+ #
40
+ def convert_quantity(quantity, unit_id, new_unit_id)
41
+ return quantity if unit_id == new_unit_id
42
+
43
+ conversions = UnitConversion.where("from_id = ? AND to_id = ?", unit_id, new_unit_id)
44
+ .or(UnitConversion.where("from_id = ? AND to_id = ?", new_unit_id, unit_id))
45
+
46
+ unless conversions.count.positive?
47
+ units = Unit.where(id: [unit_id, new_unit_id]).select(:code)
48
+ raise(StandardError, "There is no conversion factor between #{units[0].code} and #{units[1].code}.")
49
+ end
50
+
51
+ conversion = conversions.first
52
+ return (quantity * conversion.factor).round if unit_id == conversion.from_id && new_unit_id == conversion.to_id
53
+
54
+ (quantity / conversion.factor).round
55
+ end
56
+
57
+ def suggest_values(item_id, new_unit_id)
58
+ item = CustomerOrderItem.includes(:customer_order).find_by(id: item_id)
59
+ raise(StandardError, "Order item with id `#{item_id}` not found.") unless item
60
+
61
+ quantity = convert_quantity(item.quantity, item.unit_id, new_unit_id)
62
+ client_price = ClientPrice.find_by(product_id: item.product_id, client_id: item.customer_order.client_id)
63
+ if client_price
64
+ price = convert_price(client_price.price, client_price.unit_id, new_unit_id)
65
+ else
66
+ master_price = MasterPrice.find_by(product_id: item.product_id, primary: true)
67
+ raise(StandardError, "No price entry could be found for product `#{item.product.code}`.") unless master_price
68
+
69
+ price = convert_price(master_price.selling_price, master_price.unit_id, new_unit_id)
70
+ end
71
+ {quantity: quantity, price: price}
72
+ end
73
+
4
74
  def submit(id)
5
75
  order = CustomerOrder.find_by(id: id)
6
76
  raise(StandardError, "Customer order with id `#{id}` not found.") unless order
@@ -51,16 +121,31 @@ module Comee
51
121
  customer_order: order,
52
122
  status: SalesOrder.statuses[:draft]
53
123
  )
54
- items = order.customer_order_items.each_with_object([]) do |item, res|
124
+ order_items = order.customer_order_items.includes(:product, :unit)
125
+ prices = ClientPrice.where(client: order.client, product_id: order_items.map(&:product_id))
126
+ items = order_items.each_with_object([]) do |item, res|
55
127
  next if item.canceled?
56
128
 
129
+ default_unit = item.product.default_unit
130
+ unit_id = default_unit ? default_unit["id"] : item.unit_id
131
+ quantity = convert_quantity(item.quantity, item.unit_id, unit_id)
132
+ client_price = prices.find { |price| price.product_id == item.product_id }
133
+ if client_price
134
+ price = convert_price(client_price.price, client_price.unit_id, unit_id)
135
+ else
136
+ master_price = MasterPrice.find_by(product: item.product, primary: true)
137
+ raise(StandardError, "No price entry could be found for product `#{item.product.code}`.") unless master_price
138
+
139
+ price = convert_price(master_price.selling_price, master_price.unit_id, unit_id)
140
+ end
141
+
57
142
  res << {
58
143
  sales_order_id: sales_order.id,
59
144
  customer_order_item_id: item.id,
60
145
  product_id: item.product_id,
61
- unit_id: item.unit_id,
62
- quantity: item.quantity,
63
- price: item.price,
146
+ unit_id: unit_id,
147
+ quantity: quantity,
148
+ price: price,
64
149
  delivery_date: item.delivery_date
65
150
  }
66
151
  end
data/config/routes.rb CHANGED
@@ -45,6 +45,7 @@ Comee::Core::Engine.routes.draw do
45
45
  end
46
46
  resources :currencies
47
47
  resources :units
48
+ resources :unit_conversions
48
49
  resources :users
49
50
  post "/purchase_orders/filter", controller: :purchase_orders, action: :filter
50
51
  resources :purchase_orders
@@ -66,7 +67,11 @@ Comee::Core::Engine.routes.draw do
66
67
  post "submit"
67
68
  end
68
69
  end
69
- resources :sales_order_items, except: [:index]
70
+ resources :sales_order_items, except: [:index] do
71
+ member do
72
+ get "suggest", controller: :sales_order_items, action: :suggest_values
73
+ end
74
+ end
70
75
  post "/sales_orders/filter", controller: :sales_orders, action: :filter
71
76
  resources :sales_orders do
72
77
  collection do
@@ -6,6 +6,7 @@ class CreateComeeCoreProducts < ActiveRecord::Migration[7.0]
6
6
  t.string :description
7
7
  t.boolean :leaf, null: false, default: true
8
8
  t.string :ancestry
9
+ t.jsonb :preferred_units, null: false, default: []
9
10
 
10
11
  t.timestamps
11
12
  end
@@ -0,0 +1,19 @@
1
+ class CreateComeeCoreUnitConversions < ActiveRecord::Migration[7.1]
2
+ def change
3
+ create_table :comee_core_unit_conversions do |t|
4
+ t.references :from,
5
+ null: false,
6
+ index: {name: "from_on_uc_indx"},
7
+ foreign_key: {to_table: :comee_core_units}
8
+ t.references :to,
9
+ null: false,
10
+ index: {name: "to_on_uc_indx"},
11
+ foreign_key: {to_table: :comee_core_units}
12
+ t.float :factor, null: false
13
+
14
+ t.timestamps
15
+ end
16
+
17
+ add_index(:comee_core_unit_conversions, %i[from_id to_id], unique: true)
18
+ end
19
+ end
@@ -1,5 +1,5 @@
1
1
  module Comee
2
2
  module Core
3
- VERSION = "0.1.45.pre3".freeze
3
+ VERSION = "0.1.46".freeze
4
4
  end
5
5
  end
@@ -8,5 +8,6 @@ FactoryBot.define do
8
8
  description { Faker::Lorem.sentence }
9
9
  leaf { true }
10
10
  ancestry { root.id.to_s }
11
+ preferred_units { [] }
11
12
  end
12
13
  end
@@ -0,0 +1,7 @@
1
+ FactoryBot.define do
2
+ factory :unit_conversion, class: "Comee::Core::UnitConversion" do
3
+ from factory: :unit
4
+ to factory: :unit
5
+ factor { 1 }
6
+ end
7
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: comee_core
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.45.pre3
4
+ version: 0.1.46
5
5
  platform: ruby
6
6
  authors:
7
7
  - Henock L.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-12-05 00:00:00.000000000 Z
11
+ date: 2023-12-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: active_model_serializers
@@ -298,6 +298,7 @@ files:
298
298
  - app/controllers/comee/core/sales_order_items_controller.rb
299
299
  - app/controllers/comee/core/sales_orders_controller.rb
300
300
  - app/controllers/comee/core/suppliers_controller.rb
301
+ - app/controllers/comee/core/unit_conversions_controller.rb
301
302
  - app/controllers/comee/core/units_controller.rb
302
303
  - app/controllers/comee/core/users_controller.rb
303
304
  - app/controllers/concerns/comee/core/common.rb
@@ -336,6 +337,7 @@ files:
336
337
  - app/models/comee/core/sales_order_item.rb
337
338
  - app/models/comee/core/supplier.rb
338
339
  - app/models/comee/core/unit.rb
340
+ - app/models/comee/core/unit_conversion.rb
339
341
  - app/models/comee/core/user.rb
340
342
  - app/models/comee/core/warehouse_shipment.rb
341
343
  - app/models/comee/core/warehouse_shipment_item.rb
@@ -357,6 +359,7 @@ files:
357
359
  - app/serializers/comee/core/sales_order_item_serializer.rb
358
360
  - app/serializers/comee/core/sales_order_serializer.rb
359
361
  - app/serializers/comee/core/supplier_serializer.rb
362
+ - app/serializers/comee/core/unit_conversion_serializer.rb
360
363
  - app/serializers/comee/core/unit_serializer.rb
361
364
  - app/serializers/comee/core/user_serializer.rb
362
365
  - app/services/comee/core/customer_order_service.rb
@@ -404,6 +407,7 @@ files:
404
407
  - db/migrate/20231125115522_create_comee_core_customs_details.rb
405
408
  - db/migrate/20231125122723_create_comee_core_purchase_orders.rb
406
409
  - db/migrate/20231126082907_create_comee_core_purchase_order_items.rb
410
+ - db/migrate/20231206082503_create_comee_core_unit_conversions.rb
407
411
  - lib/comee/core.rb
408
412
  - lib/comee/core/engine.rb
409
413
  - lib/comee/core/version.rb
@@ -437,6 +441,7 @@ files:
437
441
  - spec/factories/comee/core/sales_order_items.rb
438
442
  - spec/factories/comee/core/sales_orders.rb
439
443
  - spec/factories/comee/core/suppliers.rb
444
+ - spec/factories/comee/core/unit_conversions.rb
440
445
  - spec/factories/comee/core/units.rb
441
446
  - spec/factories/comee/core/users.rb
442
447
  - spec/factories/comee/core/warehouse_shipment_items.rb
@@ -459,9 +464,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
459
464
  version: '3.0'
460
465
  required_rubygems_version: !ruby/object:Gem::Requirement
461
466
  requirements:
462
- - - ">"
467
+ - - ">="
463
468
  - !ruby/object:Gem::Version
464
- version: 1.3.1
469
+ version: '0'
465
470
  requirements: []
466
471
  rubygems_version: 3.4.10
467
472
  signing_key: