cats_core 1.0.4 → 1.0.5

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2d2e957d3c24b295e163776c3ecd67c21e16877687a0c2f4682be641ea2278a5
4
- data.tar.gz: 1230cf3469e3a2943cad4e91d229e5aefb110f84e459b741022e28d91b099c62
3
+ metadata.gz: b6ff0706b8636cf94fea0714f73ed8fead005d08a2647f5365f43ac7ba6a53b6
4
+ data.tar.gz: ab055e9fc942f99eed1e28ab7a755e0c5f54098a854705cf46c6c9bc880d0cff
5
5
  SHA512:
6
- metadata.gz: f0b8e1139d6a14e4afc0c49914b2d1cc1f9fe4e6e180410cb15368160f7705ab76665bb8805f37d538207f14d92126a20a70cc7ccbce1b6c4380025a15f06a30
7
- data.tar.gz: 9e1dc4a4ecfd31ce032e64111a5d0d21f4c89a70e0732cfcba688e1e90804e2a9c8cea50ec8a602b7d73fed7d968117ea83c44a0538e436bc4584513823e0b61
6
+ metadata.gz: 82950facfa04e42a6aa4e934bfe9f950c158db65dbf55e61c6aff04ad2c9041354e2560a61222817864c5cd8288649282e099f362e7014f7abf65d3ba628a441
7
+ data.tar.gz: 8e951eebc249a57a1868dbc9155c1818bfc791ef6a0c987aaccf203c34e2d9fab7a3598b138c70de6e6c5f910cd8d2970e838c9719198f9ccd1d6380b9989143
@@ -1,4 +1,30 @@
1
- module CatsCore
2
- class ApplicationController < ActionController::Base
1
+ module Cats
2
+ module Core
3
+ class ApplicationController < ActionController::Base
4
+ before_action :authenticate
5
+
6
+ def current_user
7
+ return if token.nil?
8
+
9
+ user = Cats::Core::User.find(auth['id'])
10
+ @current_user ||= user
11
+ end
12
+
13
+ def authenticate
14
+ render json: { error: 'Unauthorized' }, status: 401 if current_user.nil?
15
+ end
16
+
17
+ private
18
+
19
+ def token
20
+ return nil if request.env['HTTP_AUTHORIZATION'].nil?
21
+
22
+ request.env['HTTP_AUTHORIZATION'].scan(/Bearer (.*)$/).flatten.last
23
+ end
24
+
25
+ def auth
26
+ Cats::Core::TokenAuthService.decode(token)
27
+ end
28
+ end
3
29
  end
4
30
  end
@@ -0,0 +1,15 @@
1
+ module Cats
2
+ module Core
3
+ class NotificationsController < ApplicationController
4
+ def index
5
+ data = { success: true, data: current_user.notifications.newest_first }
6
+ render json: data
7
+ end
8
+
9
+ def unread
10
+ data = { success: true, data: current_user.notifications.unread.newest_first }
11
+ render json: data
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,6 @@
1
+ module Cats
2
+ module Core
3
+ class ApplicationJob < ActiveJob::Base
4
+ end
5
+ end
6
+ end
@@ -1,6 +1,8 @@
1
1
  module Cats
2
2
  module Core
3
3
  class Notification < ApplicationRecord
4
+ include Noticed::Model
5
+
4
6
  belongs_to :recipient, polymorphic: true
5
7
  end
6
8
  end
@@ -0,0 +1,24 @@
1
+ module Cats
2
+ module Core
3
+ class ReceiptPlan < ApplicationRecord
4
+ # receipt plan status
5
+ DRAFT = 'Draft'.freeze
6
+ ACCEPTED = 'Accepted'.freeze
7
+ DECLINED = 'Declined'.freeze
8
+ RECEIPT_PLAN_STATUSES = [DRAFT, ACCEPTED, DECLINED].freeze
9
+
10
+ validates :quantity, :status, presence: true
11
+ belongs_to :commodity
12
+ belongs_to :plan_recipient, polymorphic: true
13
+ validates :quantity, numericality: { greater_than: 0 }
14
+ validates :status, inclusion: { in: RECEIPT_PLAN_STATUSES }
15
+ validate :validate_reason_for_decline
16
+
17
+ def validate_reason_for_decline
18
+ return unless reason_for_decline.nil? || reason_for_decline == 'Accepted'
19
+
20
+ errors.add(:reason_for_decline, 'must be specified')
21
+ end
22
+ end
23
+ end
24
+ end
@@ -19,7 +19,8 @@ module Cats
19
19
  validates :quantity, numericality: { greater_than_or_equal_to: 0 }
20
20
  validates :commodity_status, inclusion: { in: Cats::Core::Commodity::COMMODITY_STATUSES }
21
21
  validates :stack_status, inclusion: { in: STACK_STATUSES }
22
- validate :validate_coordinates, :validate_dimensions
22
+ validate :validate_coordinates, :validate_dimensions, :validate_distance_from_wall, :validate_overlap,
23
+ :validate_space_between_stack
23
24
 
24
25
  def validate_coordinates
25
26
  return unless store.present? && length.present? && width.present? && start_x.present? && start_y.present?
@@ -34,6 +35,59 @@ module Cats
34
35
  errors.add(:length, 'cannot exceed store length') if start_x + length > store.length
35
36
  errors.add(:width, 'cannot exceed store width') if start_y + width > store.width
36
37
  end
38
+
39
+ def stacking_rules
40
+ rule ||= Cats::Core::StackingRule.first
41
+ rule
42
+ end
43
+
44
+ def validate_distance_from_wall
45
+ return unless store.present? && length.present? && width.present? && start_x.present? && start_y.present?
46
+
47
+ rule = stacking_rules
48
+ if start_x < rule.distance_from_wall || store.length - (start_y + length) < rule.distance_from_wall ||
49
+ store.width - (start_x + width) < rule.distance_from_wall || start_y < rule.distance_from_wall
50
+ errors.add(:base,
51
+ message: "The stack must be placed #{rule.distance_from_wall} meter away from a store wall")
52
+ end
53
+ end
54
+
55
+ def validate_overlap
56
+ return unless store.present? && length.present? && width.present? && start_x.present? && start_y.present?
57
+
58
+ stacks = store.stacks.where(stack_status: [RESERVED, ALLOCATED]).where.not(id: id)
59
+ stacks.each do |s|
60
+ errors.add(:base, message: "#{code} overlaps with #{s.code}") if overlaps?(self, s)
61
+ end
62
+ end
63
+
64
+ def validate_space_between_stack
65
+ return unless store.present? && length.present? && width.present? && start_x.present? && start_y.present?
66
+
67
+ stacks = store.stacks.where(stack_status: [RESERVED, ALLOCATED]).where.not(id: id)
68
+ rule = stacking_rules
69
+ new_stack = dup
70
+ new_stack.assign_attributes(start_x: start_x - rule.space_between_stack,
71
+ start_y: start_y - rule.space_between_stack,
72
+ length: length + (2 * rule.space_between_stack),
73
+ width: width + (2 * rule.space_between_stack))
74
+ stacks.each do |s|
75
+ errors.add(:base, message: "#{code} overlaps with #{s.code}") if overlaps?(new_stack, s)
76
+ end
77
+ end
78
+
79
+ # A method that checks if an overlap exists b/n two stacks.
80
+ # An overlap b/n stacks does not occur if one of the stacks is completely above the other stack or
81
+ # if one of the stacks is on the left side of the other stack.
82
+ # If both conditions fail, it means an overlap exists b/n the two stacks
83
+
84
+ def overlaps?(st1, st2)
85
+ return false if st1.start_x > (st2.start_x + st2.width) || st2.start_x > (st1.start_x + st1.width)
86
+
87
+ return false if st1.start_y > (st2.start_y + st2.length) || st2.start_y > (st1.start_y + st1.length)
88
+
89
+ true
90
+ end
37
91
  end
38
92
  end
39
93
  end
@@ -0,0 +1,16 @@
1
+ module Cats
2
+ module Core
3
+ class StackingRule < ApplicationRecord
4
+ validates :distance_from_wall, :space_between_stack, :distance_from_ceiling, :maximum_height, :maximum_length,
5
+ :maximum_width, :distance_from_gangway, presence: true, numericality: { greater_than: 0 }
6
+ validate :validate_only_a_record_exist
7
+
8
+ def validate_only_a_record_exist
9
+ return unless StackingRule.count > 1
10
+
11
+ errors.add(:base,
12
+ 'There is already a stacking rule entry. A new rule can not be added')
13
+ end
14
+ end
15
+ end
16
+ end
@@ -3,6 +3,7 @@ module Cats
3
3
  class Store < ApplicationRecord
4
4
  belongs_to :warehouse, class_name: 'Cats::Core::Location'
5
5
  has_many :stacks
6
+ has_many :receipt_plans, as: :receivable
6
7
 
7
8
  validates :name, :store_keeper_name, :length, :width, :height, presence: true
8
9
  validates :length, :width, :height, numericality: { greater_than: 0 }
@@ -2,7 +2,7 @@ module Cats
2
2
  module Core
3
3
  class User < ApplicationRecord
4
4
  has_secure_password
5
- rolify
5
+ rolify role_cname: 'Cats::Core::Role'
6
6
 
7
7
  belongs_to :application_module
8
8
  has_and_belongs_to_many :roles, join_table: :cats_core_users_cats_core_roles
@@ -0,0 +1,9 @@
1
+ # This is a simple notification class which delivers a
2
+ # message via database delivery method. It requires a
3
+ # +msg+ parameter to instantiate, which represents the
4
+ # text message to deliver.
5
+ class SimpleNotification < Noticed::Base
6
+ deliver_by :database
7
+
8
+ param :msg
9
+ end
@@ -0,0 +1,41 @@
1
+ module Cats
2
+ module Core
3
+ class NotificationService
4
+ NOTIFICATION_RULES = {
5
+ dispatch_plan: {
6
+ application: 'CATS-WH',
7
+ notification: 'DispatchPlanNotification',
8
+ params: [:way_bill],
9
+ recipients: [:warehouse_manager]
10
+ },
11
+ receipt_plan: {
12
+ application: 'CATS-WH',
13
+ notification: 'ReceiptPlanNotification',
14
+ params: [:receipt_plan],
15
+ recipients: [:store_keeper]
16
+ }
17
+ }.freeze
18
+
19
+ def initialize(code, params)
20
+ @code = code
21
+ @params = params
22
+ end
23
+
24
+ def notification_rules
25
+ NOTIFICATION_RULES
26
+ end
27
+
28
+ def notify
29
+ rules = notification_rules
30
+ clazz = rules[@code][:notification].constantize
31
+ app_code = rules[@code][:application]
32
+ roles = rules[@code][:recipients]
33
+
34
+ notification = clazz.with(**@params)
35
+ users = Cats::Core::User.joins(:application_module)
36
+ .where(application_module: { prefix: app_code }).with_all_roles(*roles)
37
+ notification.deliver(users)
38
+ end
39
+ end
40
+ end
41
+ end
data/config/routes.rb CHANGED
@@ -1,2 +1,5 @@
1
1
  Cats::Core::Engine.routes.draw do
2
+ get '/notifications/unread', controller: :notifications, action: :unread
3
+
4
+ resources :notifications, only: [:index]
2
5
  end
@@ -0,0 +1,15 @@
1
+ class CreateCatsCoreStackingRules < ActiveRecord::Migration[6.1]
2
+ def change
3
+ create_table :cats_core_stacking_rules do |t|
4
+ t.float :distance_from_wall, null: false
5
+ t.float :space_between_stack, null: false
6
+ t.float :distance_from_ceiling, null: false
7
+ t.float :maximum_height, null: false
8
+ t.float :maximum_length, null: false
9
+ t.float :maximum_width, null: false
10
+ t.float :distance_from_gangway, null: false
11
+
12
+ t.timestamps
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,16 @@
1
+ class CreateCatsCoreReceiptPlans < ActiveRecord::Migration[6.1]
2
+ def change
3
+ create_table :cats_core_receipt_plans do |t|
4
+ t.float :quantity, null: false
5
+ t.string :status, default: 'Draft'
6
+ t.references :commodity,
7
+ null: false,
8
+ index: { name: 'commodity_on_receipt_plan_indx' },
9
+ foreign_key: { to_table: :cats_core_commodities }
10
+ t.string :reason_for_decline
11
+ t.references :plan_recipient, polymorphic: true
12
+
13
+ t.timestamps
14
+ end
15
+ end
16
+ end
@@ -1,5 +1,5 @@
1
1
  module Cats
2
2
  module Core
3
- VERSION = '1.0.4'.freeze
3
+ VERSION = '1.0.5'.freeze
4
4
  end
5
5
  end
data/lib/cats_core.rb CHANGED
@@ -3,3 +3,4 @@ require 'cats/core/engine'
3
3
  require 'ancestry'
4
4
  require 'rolify'
5
5
  require 'jwt'
6
+ require 'noticed'
@@ -0,0 +1,9 @@
1
+ FactoryBot.define do
2
+ factory :receipt_plan, class: 'Cats::Core::ReceiptPlan' do
3
+ plan_recipient factory: :store
4
+ commodity
5
+ quantity { 1.5 }
6
+ status { 'Accepted' }
7
+ reason_for_decline { FFaker::Name.name }
8
+ end
9
+ end
@@ -0,0 +1,11 @@
1
+ FactoryBot.define do
2
+ factory :stacking_rule, class: 'Cats::Core::StackingRule' do
3
+ space_between_stack { 1 }
4
+ distance_from_gangway { 1.5 }
5
+ distance_from_ceiling { 1 }
6
+ maximum_height { 2.5 }
7
+ maximum_length { 6 }
8
+ maximum_width { 6 }
9
+ distance_from_wall { 1 }
10
+ end
11
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cats_core
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.4
4
+ version: 1.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Henock L.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-07-24 00:00:00.000000000 Z
11
+ date: 2021-07-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ancestry
@@ -203,6 +203,8 @@ files:
203
203
  - README.md
204
204
  - Rakefile
205
205
  - app/controllers/cats/core/application_controller.rb
206
+ - app/controllers/cats/core/notifications_controller.rb
207
+ - app/jobs/cats/core/application_job.rb
206
208
  - app/models/cats/core/application_module.rb
207
209
  - app/models/cats/core/application_record.rb
208
210
  - app/models/cats/core/commodity.rb
@@ -214,15 +216,19 @@ files:
214
216
  - app/models/cats/core/menu_item.rb
215
217
  - app/models/cats/core/notification.rb
216
218
  - app/models/cats/core/program.rb
219
+ - app/models/cats/core/receipt_plan.rb
217
220
  - app/models/cats/core/role.rb
218
221
  - app/models/cats/core/role_menu.rb
219
222
  - app/models/cats/core/stack.rb
223
+ - app/models/cats/core/stacking_rule.rb
220
224
  - app/models/cats/core/store.rb
221
225
  - app/models/cats/core/transporter.rb
222
226
  - app/models/cats/core/unit_of_measure.rb
223
227
  - app/models/cats/core/user.rb
224
228
  - app/models/cats/core/way_bill.rb
225
229
  - app/models/cats/core/way_bill_item.rb
230
+ - app/notifications/cats/core/simple_notification.rb
231
+ - app/services/cats/core/notification_service.rb
226
232
  - app/services/cats/core/token_auth_service.rb
227
233
  - config/routes.rb
228
234
  - db/migrate/20210715114238_create_cats_core_application_modules.rb
@@ -243,7 +249,9 @@ files:
243
249
  - db/migrate/20210718045516_create_cats_core_way_bills.rb
244
250
  - db/migrate/20210718050751_create_cats_core_way_bill_items.rb
245
251
  - db/migrate/20210718202957_create_cats_core_commodity_transactions.rb
252
+ - db/migrate/20210719133710_create_cats_core_stacking_rules.rb
246
253
  - db/migrate/20210724074657_create_cats_core_notifications.rb
254
+ - db/migrate/20210727074646_create_cats_core_receipt_plans.rb
247
255
  - lib/cats/core.rb
248
256
  - lib/cats/core/engine.rb
249
257
  - lib/cats/core/version.rb
@@ -259,8 +267,10 @@ files:
259
267
  - spec/factories/cats/core/menus.rb
260
268
  - spec/factories/cats/core/notifications.rb
261
269
  - spec/factories/cats/core/programs.rb
270
+ - spec/factories/cats/core/receipt_plans.rb
262
271
  - spec/factories/cats/core/role_menus.rb
263
272
  - spec/factories/cats/core/roles.rb
273
+ - spec/factories/cats/core/stacking_rules.rb
264
274
  - spec/factories/cats/core/stacks.rb
265
275
  - spec/factories/cats/core/stores.rb
266
276
  - spec/factories/cats/core/transporters.rb