Class: Comee::Core::SalesOrderService
- Inherits:
-
Object
- Object
- Comee::Core::SalesOrderService
- Defined in:
- app/services/comee/core/sales_order_service.rb
Instance Method Summary collapse
- #accept(id) ⇒ Object
-
#aggregate_back_order_item(items, supplier_id, back_order_id, delivery_date) ⇒ Object
This method returns items aggregated by product for a supplier.
-
#assign_price_to_items(items) ⇒ Object
This method assigns current purchase price for a product under a given supplier.
-
#bulk_create_back_order(params) ⇒ Object
This method returns { success: true} if all back orders in the
params
created successfully. - #cancel(id) ⇒ Object
-
#check_duplicate_order_number(params) ⇒ Object
This method returns false if there is no duplicate order number, otherwise it raises an error.
-
#check_product_prices(params) ⇒ Object
This method returns true if all products under each back order in
params
have active price in the master price table. -
#compose_error_messge(queries, master_prices) ⇒ Object
This method composes an error message when called from check_product_prices.
-
#confirm(id) ⇒ Object
order.update!(status: SalesOrder.statuses) order end.
-
#create_back_orders(params) ⇒ Object
This method returns { success: true} if all back orders in the
params
created successfully. - #revert(id) ⇒ Object
- #submit(id) ⇒ Object
Instance Method Details
#accept(id) ⇒ Object
182 183 184 185 186 187 188 189 190 191 192 193 194 |
# File 'app/services/comee/core/sales_order_service.rb', line 182 def accept(id) order = SalesOrder.find_by(id: id) raise(StandardError, "Sales order with id `#{id}` not found.") unless order raise(StandardError, "Sales order should be in confirmed state.") unless order.confirmed? raise(StandardError, "Sales order should have at least one item.") unless order.sales_order_items.count.positive? raise(StandardError, "All items are canceled for sales order.") if order.sales_order_items.all?(&:canceled?) order.update!(status: SalesOrder.statuses[:accepted]) order end |
#aggregate_back_order_item(items, supplier_id, back_order_id, delivery_date) ⇒ Object
This method returns items aggregated by product for a supplier. It recieves items
, supplier_id
and back_order_id
as a parameter
The +items+ is an array containing list of back order items
The +items+ param looks like [{product_id: '', requested_quantity: ''},...]
The +supplier_id+ is the id of the supplier under which the items belong to
The +back_order_id+ is the id of the backer order under which the items belong to
86 87 88 89 90 91 92 |
# File 'app/services/comee/core/sales_order_service.rb', line 86 def aggregate_back_order_item(items, supplier_id, back_order_id, delivery_date) items.group_by { |item| item[:product_id] }.map do |product_id, aggregated_items| total_quantity = aggregated_items.reduce(0) { |sum, agg_item| agg_item[:requested_quantity] + sum } {product_id: product_id, requested_quantity: total_quantity, supplier_quantity: total_quantity, supplier_id: supplier_id, back_order_id: back_order_id, delivery_date: delivery_date} end end |
#assign_price_to_items(items) ⇒ Object
This method assigns current purchase price for a product under a given supplier. It recieves items
containing array of products along with the corresponding suppliers The items
param looks like [
{product_id: '', requested_quantity: '', supplier_quantity: '', supplier_id: '', back_order_id: '' },
...
] It assigns price by first fetching the price of products in the items array and then iterate through the items array and find the corresponding price from the fetched price
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 |
# File 'app/services/comee/core/sales_order_service.rb', line 103 def assign_price_to_items(items) queries = [] items.map { |bo_item| queries << {supplier_id: bo_item[:supplier_id], product_id: bo_item[:product_id]} } master_prices = queries.inject(Comee::Core::MasterPrice.none) do |conditions, condition| conditions.or(Comee::Core::MasterPrice.where(condition)) end items.each do |item| mp = master_prices.find { |price| price.supplier_id == item[:supplier_id] && price.product_id == item[:product_id] } item[:requested_unit_price] = mp.purchase_price item[:supplier_unit_price] = mp.purchase_price item[:from] = mp.valid_from item[:to] = mp.valid_from item.delete(:supplier_id) end end |
#bulk_create_back_order(params) ⇒ Object
This method returns { success: true} if all back orders in the params
created successfully. The params
contain array of back orders with the corresponding products. The exact structure of params
looks like the following [”, order_number: ”, order_date: ”, delivery_date: ”, delivery_address: ”, invoice_address: ”,
back_order_items: [{product_id: '', requested_quantity: '',...] }...]
This method uses insert_all method to create back order and its items in bulk
126 127 128 129 130 131 132 133 134 135 136 137 138 |
# File 'app/services/comee/core/sales_order_service.rb', line 126 def bulk_create_back_order(params) back_orders = params.map { |p| {**p.except(:back_order_items), created_at: Time.now, updated_at: Time.now} } result = Comee::Core::BackOrder.insert_all!(back_orders, returning: %w[id supplier_id delivery_date]) aggregated_items = [] result.pluck("id", "supplier_id", "delivery_date").each do |r| supplier_detail = params.find { |p| p[:supplier_id].to_i == r[1] } aggregated_items << aggregate_back_order_item(supplier_detail[:back_order_items], r[1], r[0], r[2]) end Comee::Core::BackOrderItem.insert_all!(assign_price_to_items(aggregated_items.flatten)) {success: true} rescue StandardError => e {success: false, error: e.} end |
#cancel(id) ⇒ Object
196 197 198 199 200 201 202 203 204 |
# File 'app/services/comee/core/sales_order_service.rb', line 196 def cancel(id) order = SalesOrder.find_by(id: id) raise(StandardError, "Sales order with id `#{id}` not found.") unless order raise(StandardError, "Sales order is already canceled.") if order.canceled? order.update!(status: SalesOrder.statuses[:canceled]) order end |
#check_duplicate_order_number(params) ⇒ Object
This method returns false if there is no duplicate order number, otherwise it raises an error. The params
contain array of back orders with the corresponding products. The exact structure of params
looks like the following [”, order_number: ”, order_date: ”, delivery_date: ”, delivery_address: ”, invoice_address: ”,
back_order_items: [{product_id: '', requested_quantity: '',...] }...]
The method first checks if there is duplicate order number within in the params
array, and if not then it checks for duplicate order number from back order table.
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
# File 'app/services/comee/core/sales_order_service.rb', line 62 def check_duplicate_order_number(params) order_numbers = params.map { |param| param[:order_number] } unless order_numbers.uniq.count == order_numbers.count raise(StandardError, "Duplicate order number(s) #{order_numbers.select do |e| order_numbers.count(e) > 1 end.uniq.join(', ')} exist in the payload.") end duplicate_order_numbers = Comee::Core::BackOrder.where(order_number: order_numbers) unless duplicate_order_numbers.count.zero? raise(StandardError, "Duplicate order number(s) #{duplicate_order_numbers.map(&:order_number).join(', ')} exist in the back order table.") end false end |
#check_product_prices(params) ⇒ Object
This method returns true if all products under each back order in params
have active price in the master price table. The params
contain array of back orders with the corresponding products. The exact structure of params
looks like the following [”, order_number: ”, order_date: ”, delivery_date: ”, delivery_address: ”, invoice_address: ”,
back_order_items: [{product_id: '', requested_quantity: '',...] }...]
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
# File 'app/services/comee/core/sales_order_service.rb', line 22 def check_product_prices(params) queries = [] params.each do |param| param[:back_order_items].map do |bo_item| queries << {supplier_id: param[:supplier_id], product_id: bo_item[:product_id]} end end master_prices = queries.inject(Comee::Core::MasterPrice.none) do |conditions, condition| conditions.or(Comee::Core::MasterPrice.where(condition)) end raise(StandardError, compose_error_messge(queries, master_prices)) unless queries.count == master_prices.count true end |
#compose_error_messge(queries, master_prices) ⇒ Object
This method composes an error message when called from check_product_prices. It recieves queries
and master_prices
as a parameter
The +queries+ is an array containing list of conditions that will be joined using or connector
The +queries+ param looks like [{supplier_id: '', product_id: '', active: true},...]
The +master_prices+ param contains master prices fetched by the queries param given above
The message is composed by computing difference b/n the queries and master prices params
45 46 47 48 49 50 51 52 |
# File 'app/services/comee/core/sales_order_service.rb', line 45 def compose_error_messge(queries, master_prices) result = master_prices.map { |mp| {supplier_id: mp[:supplier_id], product_id: mp[:product_id]} } diff = queries - result product_names = Comee::Core::Product.where(id: diff.map { |dif| dif[:product_id] }).pluck("name").join(", ") supplier_names = Comee::Core::Supplier.where(id: diff.map { |dif| dif[:supplier_id] }).pluck("name").join(", ") "The following products #{product_names} do not have price entry for the following suppliers" \ " #{supplier_names} in the master price table or the prices are not valid." end |
#confirm(id) ⇒ Object
168 169 170 171 172 173 174 175 176 177 178 179 180 |
# File 'app/services/comee/core/sales_order_service.rb', line 168 def confirm(id) order = SalesOrder.find_by(id: id) raise(StandardError, "Sales order with id `#{id}` not found.") unless order raise(StandardError, "Sales order should be in submitted state.") unless order.submitted? raise(StandardError, "Sales order should have at least one item.") unless order.sales_order_items.count.positive? raise(StandardError, "All items are canceled for sales order.") if order.sales_order_items.all?(&:canceled?) order.update!(status: SalesOrder.statuses[:confirmed]) order end |
#create_back_orders(params) ⇒ Object
This method returns { success: true} if all back orders in the params
created successfully. The params
contain array of back orders with the corresponding products. The exact structure of params
looks like the following [”, order_number: ”, order_date: ”, delivery_date: ”, delivery_address: ”, invoice_address: ”,
back_order_items: [{product_id: '', requested_quantity: '',...] }...]
10 11 12 13 14 |
# File 'app/services/comee/core/sales_order_service.rb', line 10 def create_back_orders(params) check_product_prices(params) check_duplicate_order_number(params) bulk_create_back_order(params) end |
#revert(id) ⇒ Object
206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 |
# File 'app/services/comee/core/sales_order_service.rb', line 206 def revert(id) order = SalesOrder.find_by(id: id) raise(StandardError, "Sales order with id `#{id}` not found.") unless order raise(StandardError, "Sales order should be in draft state.") unless order.draft? customer_order = order.customer_order ActiveRecord::Base.transaction do Comee::Core::SalesOrderItem.where(sales_order: order).delete_all order.delete customer_order.status = Comee::Core::CustomerOrder.statuses[:draft] customer_order.save! end customer_order end |
#submit(id) ⇒ Object
140 141 142 143 144 145 146 147 148 149 150 151 152 |
# File 'app/services/comee/core/sales_order_service.rb', line 140 def submit(id) order = SalesOrder.find_by(id: id) raise(StandardError, "Sales order with id `#{id}` not found.") unless order raise(StandardError, "Sales order should be in draft state.") unless order.draft? raise(StandardError, "Sales order should have at least one item.") unless order.sales_order_items.count.positive? raise(StandardError, "All items are canceled for sales order.") if order.sales_order_items.all?(&:canceled?) order.update!(status: SalesOrder.statuses[:submitted]) order end |