cats_core 1.0.4 → 1.0.5

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