cats_core 1.0.0

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.
Files changed (67) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +28 -0
  4. data/Rakefile +10 -0
  5. data/app/controllers/cats/core/application_controller.rb +4 -0
  6. data/app/models/cats/core/application_module.rb +8 -0
  7. data/app/models/cats/core/application_record.rb +7 -0
  8. data/app/models/cats/core/commodity.rb +17 -0
  9. data/app/models/cats/core/commodity_category.rb +8 -0
  10. data/app/models/cats/core/commodity_transaction.rb +55 -0
  11. data/app/models/cats/core/donor.rb +8 -0
  12. data/app/models/cats/core/location.rb +48 -0
  13. data/app/models/cats/core/menu.rb +9 -0
  14. data/app/models/cats/core/menu_item.rb +9 -0
  15. data/app/models/cats/core/program.rb +8 -0
  16. data/app/models/cats/core/role.rb +9 -0
  17. data/app/models/cats/core/role_menu.rb +19 -0
  18. data/app/models/cats/core/stack.rb +39 -0
  19. data/app/models/cats/core/store.rb +24 -0
  20. data/app/models/cats/core/transporter.rb +8 -0
  21. data/app/models/cats/core/unit_of_measure.rb +13 -0
  22. data/app/models/cats/core/user.rb +14 -0
  23. data/app/models/cats/core/way_bill.rb +12 -0
  24. data/app/models/cats/core/way_bill_item.rb +15 -0
  25. data/config/routes.rb +2 -0
  26. data/db/migrate/20210715114238_create_cats_core_application_modules.rb +10 -0
  27. data/db/migrate/20210715114910_create_cats_core_users.rb +18 -0
  28. data/db/migrate/20210715120018_create_cats_core_roles.rb +28 -0
  29. data/db/migrate/20210715121244_create_cats_core_menus.rb +14 -0
  30. data/db/migrate/20210715122141_create_cats_core_menu_items.rb +15 -0
  31. data/db/migrate/20210715122423_create_cats_core_role_menus.rb +28 -0
  32. data/db/migrate/20210716124953_create_cats_core_commodity_categories.rb +12 -0
  33. data/db/migrate/20210716145125_create_cats_core_unit_of_measures.rb +11 -0
  34. data/db/migrate/20210716151230_create_cats_core_programs.rb +11 -0
  35. data/db/migrate/20210717031108_create_cats_core_donors.rb +10 -0
  36. data/db/migrate/20210717033223_create_cats_core_commodities.rb +28 -0
  37. data/db/migrate/20210717043620_create_cats_core_locations.rb +13 -0
  38. data/db/migrate/20210717140855_create_cats_core_stores.rb +23 -0
  39. data/db/migrate/20210717171101_create_cats_core_stacks.rb +25 -0
  40. data/db/migrate/20210718042749_create_cats_core_transporters.rb +12 -0
  41. data/db/migrate/20210718045516_create_cats_core_way_bills.rb +25 -0
  42. data/db/migrate/20210718050751_create_cats_core_way_bill_items.rb +18 -0
  43. data/db/migrate/20210718202957_create_cats_core_commodity_transactions.rb +14 -0
  44. data/lib/cats/core.rb +4 -0
  45. data/lib/cats/core/engine.rb +24 -0
  46. data/lib/cats/core/version.rb +5 -0
  47. data/lib/cats_core.rb +4 -0
  48. data/lib/tasks/cats_core_tasks.rake +4 -0
  49. data/spec/factories/cats/core/application_modules.rb +6 -0
  50. data/spec/factories/cats/core/commodities.rb +12 -0
  51. data/spec/factories/cats/core/commodity_categories.rb +8 -0
  52. data/spec/factories/cats/core/commodity_transactions.rb +10 -0
  53. data/spec/factories/cats/core/donors.rb +6 -0
  54. data/spec/factories/cats/core/locations.rb +12 -0
  55. data/spec/factories/cats/core/menu_items.rb +8 -0
  56. data/spec/factories/cats/core/menus.rb +7 -0
  57. data/spec/factories/cats/core/programs.rb +7 -0
  58. data/spec/factories/cats/core/role_menus.rb +12 -0
  59. data/spec/factories/cats/core/roles.rb +6 -0
  60. data/spec/factories/cats/core/stacks.rb +15 -0
  61. data/spec/factories/cats/core/stores.rb +16 -0
  62. data/spec/factories/cats/core/transporters.rb +8 -0
  63. data/spec/factories/cats/core/unit_of_measures.rb +7 -0
  64. data/spec/factories/cats/core/users.rb +11 -0
  65. data/spec/factories/cats/core/way_bill_items.rb +8 -0
  66. data/spec/factories/cats/core/way_bills.rb +12 -0
  67. metadata +280 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 604365a363f0851bc10ec03d4e364de15b081685afbd076e3fef22d66c045b6f
4
+ data.tar.gz: d1ff473020652f3fbb66bef23955cff2e57270e419507540195ef9d8a5702b8f
5
+ SHA512:
6
+ metadata.gz: 9476576fe0f712e1001cd6148b365ef2e94ec65c8287b1eeb4304baec8bef1f37cbcff62a499145bd9f78f0878bef775225a2cd2cf5795ffe6a3efcfbb44506d
7
+ data.tar.gz: db89e8070c9b8f82a242c811435af2a0bf85876b6d1c86ed64fe5da3fdcd85c9a6f08d8b907a9f8f922140417ce5baa639e78ecbec0be7c233b450564a92e5d2
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2021 Henock L.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,28 @@
1
+ # CatsCore
2
+ Short description and motivation.
3
+
4
+ ## Usage
5
+ How to use my plugin.
6
+
7
+ ## Installation
8
+ Add this line to your application's Gemfile:
9
+
10
+ ```ruby
11
+ gem 'cats_core'
12
+ ```
13
+
14
+ And then execute:
15
+ ```bash
16
+ $ bundle
17
+ ```
18
+
19
+ Or install it yourself as:
20
+ ```bash
21
+ $ gem install cats_core
22
+ ```
23
+
24
+ ## Contributing
25
+ Contribution directions go here.
26
+
27
+ ## License
28
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require 'bundler/setup'
2
+
3
+ APP_RAKEFILE = File.expand_path('spec/dummy/Rakefile', __dir__)
4
+ load 'rails/tasks/engine.rake'
5
+
6
+ load 'rails/tasks/statistics.rake'
7
+
8
+ require 'bundler/gem_tasks'
9
+ require 'rspec/core/rake_task'
10
+ RSpec::Core::RakeTask.new(spec: 'app:db:test:prepare')
@@ -0,0 +1,4 @@
1
+ module CatsCore
2
+ class ApplicationController < ActionController::Base
3
+ end
4
+ end
@@ -0,0 +1,8 @@
1
+ module Cats
2
+ module Core
3
+ class ApplicationModule < ApplicationRecord
4
+ validates :prefix, :name, presence: true
5
+ validates :prefix, uniqueness: true
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,7 @@
1
+ module Cats
2
+ module Core
3
+ class ApplicationRecord < ActiveRecord::Base
4
+ self.abstract_class = true
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,17 @@
1
+ module Cats
2
+ module Core
3
+ class Commodity < ApplicationRecord
4
+ # Commodity statuses
5
+ GOOD = 'Good'.freeze
6
+ DAMAGED = 'Damaged'.freeze
7
+ COMMODITY_STATUSES = [GOOD, DAMAGED].freeze
8
+
9
+ belongs_to :commodity_category
10
+ belongs_to :donor
11
+ belongs_to :program
12
+ belongs_to :unit_of_measure
13
+
14
+ validates :quantity, presence: true, numericality: { greater_than: 0 }
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,8 @@
1
+ module Cats
2
+ module Core
3
+ class CommodityCategory < ApplicationRecord
4
+ validates :code, presence: true, uniqueness: true
5
+ validates :name, presence: true
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,55 @@
1
+ module Cats
2
+ module Core
3
+ class CommodityTransaction < ApplicationRecord
4
+ # Transaction statuses
5
+ DRAFT = 'Draft'.freeze
6
+ COMMITTED = 'Committed'.freeze
7
+ STATUSES = [DRAFT, COMMITTED].freeze
8
+
9
+ # Transaction types
10
+ STACK_TO_STACK = 'Stack to Stack'.freeze
11
+ STACK_TO_WAY_BILL = 'Stack to Way Bill'.freeze
12
+ WAY_BILL_TO_STACK = 'Way Bill to Stack'.freeze
13
+ TRANSACTION_TYPES = [STACK_TO_STACK, STACK_TO_WAY_BILL, WAY_BILL_TO_STACK].freeze
14
+
15
+ belongs_to :source, polymorphic: true
16
+ belongs_to :destination, polymorphic: true
17
+
18
+ validates :transaction_date, :quantity, :status, presence: true
19
+ validates :quantity, numericality: { greater_than: 0 }
20
+ validates :status, inclusion: { in: STATUSES }
21
+ validate :validate_quantity
22
+
23
+ before_validation :set_transaction_type
24
+
25
+ def validate_quantity
26
+ return unless quantity.present? && source.present?
27
+
28
+ errors.add(:quantity, 'cannot be more than source quantity') if quantity > source.quantity
29
+ end
30
+
31
+ def commit
32
+ CommodityTransaction.transaction do
33
+ source.quantity -= quantity
34
+ destination.quantity += quantity
35
+ source.save
36
+ destination.save
37
+ end
38
+ end
39
+
40
+ private
41
+
42
+ def set_transaction_type
43
+ return unless transaction_type.nil? && source.present? && destination.present?
44
+
45
+ if source.instance_of?(Cats::Core::Stack) && destination.instance_of?(Cats::Core::Stack)
46
+ self.transaction_type = STACK_TO_STACK
47
+ elsif source.instance_of?(Cats::Core::Stack) && destination.instance_of?(Cats::Core::WayBillItem)
48
+ self.transaction_type = STACK_TO_WAY_BILL
49
+ else
50
+ self.transaction_type = WAY_BILL_TO_STACK
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,8 @@
1
+ module Cats
2
+ module Core
3
+ class Donor < ApplicationRecord
4
+ validates :code, :name, presence: true
5
+ validates :code, uniqueness: true
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,48 @@
1
+ module Cats
2
+ module Core
3
+ class Location < ApplicationRecord
4
+ REGION = 'Region'.freeze
5
+ ZONE = 'Zone'.freeze
6
+ WOREDA = 'Woreda'.freeze
7
+ KEBELE = 'Kebele'.freeze
8
+ HUB = 'Hub'.freeze
9
+ WAREHOUSE = 'Warehouse'.freeze
10
+
11
+ LOCATION_TYPES = [REGION, ZONE, WOREDA, KEBELE, HUB, WAREHOUSE].freeze
12
+
13
+ has_ancestry
14
+
15
+ validates :name, :location_type, presence: true
16
+ validates :location_type, inclusion: { in: LOCATION_TYPES }
17
+ validate :validate_location_parent
18
+
19
+ def validate_location_parent
20
+ parents = {
21
+ REGION => [],
22
+ ZONE => [REGION],
23
+ WOREDA => [REGION, ZONE],
24
+ KEBELE => [REGION, ZONE, WOREDA],
25
+ HUB => [REGION, ZONE, WOREDA, KEBELE],
26
+ WAREHOUSE => [REGION, ZONE, WOREDA, KEBELE, HUB]
27
+ }
28
+
29
+ return if location_type.nil? || location_type.empty?
30
+
31
+ return if location_type == REGION && parent.nil?
32
+
33
+ # Check that parent is not nil for locations other than region
34
+ errors.add(:location, 'parent cannot be empty') if location_type != REGION && parent.nil?
35
+
36
+ # At this point, we may return if parent.nil? is true
37
+ # because the above statement already took care of that.
38
+ return unless parent
39
+
40
+ return if parents[location_type].include?(parent.location_type)
41
+
42
+ # If we reach this far then it means that we have assigned a
43
+ # wrong type of parent to our location.
44
+ errors.add(:location, "cannot have #{parent.location_type} as parent")
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,9 @@
1
+ module Cats
2
+ module Core
3
+ class Menu < ApplicationRecord
4
+ belongs_to :application_module
5
+
6
+ validates :label, presence: true
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module Cats
2
+ module Core
3
+ class MenuItem < ApplicationRecord
4
+ belongs_to :menu
5
+
6
+ validates :label, :route, presence: true
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,8 @@
1
+ module Cats
2
+ module Core
3
+ class Program < ApplicationRecord
4
+ validates :code, :name, presence: true
5
+ validates :code, uniqueness: true
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,9 @@
1
+ module Cats
2
+ module Core
3
+ class Role < ApplicationRecord
4
+ belongs_to :application_module
5
+
6
+ validates :name, presence: true
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,19 @@
1
+ module Cats
2
+ module Core
3
+ class RoleMenu < ApplicationRecord
4
+ belongs_to :role
5
+ belongs_to :menu
6
+ has_and_belongs_to_many :menu_items, join_table: :cats_core_role_menus_menu_items
7
+
8
+ validate :validate_role_and_menu
9
+
10
+ def validate_role_and_menu
11
+ return unless role.present? && menu.present?
12
+
13
+ return if role.application_module_id == menu.application_module.id
14
+
15
+ errors.add(:base, 'Application module does not match for role and menu')
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,39 @@
1
+ module Cats
2
+ module Core
3
+ class Stack < ApplicationRecord
4
+ # Stack statuses
5
+ RESERVED = 'Reserved'.freeze
6
+ ALLOCATED = 'Allocated'.freeze
7
+ DESTROYED = 'Destroyed'.freeze
8
+ STACK_STATUSES = [RESERVED, ALLOCATED, DESTROYED].freeze
9
+
10
+ belongs_to :commodity
11
+ belongs_to :store
12
+ has_many :source_transactions, class_name: 'Cats::Core::CommodityTransaction', as: :source
13
+ has_many :destination_transactions, class_name: 'Cats::Core::CommodityTransaction', as: :destination
14
+
15
+ validates :code, :length, :width, :height, :start_x, :start_y, :commodity_status, :stack_status,
16
+ :quantity, presence: true
17
+ validates :code, uniqueness: true
18
+ validates :length, :width, :height, :start_x, :start_y, numericality: { greater_than: 0 }
19
+ validates :quantity, numericality: { greater_than_or_equal_to: 0 }
20
+ validates :commodity_status, inclusion: { in: Cats::Core::Commodity::COMMODITY_STATUSES }
21
+ validates :stack_status, inclusion: { in: STACK_STATUSES }
22
+ validate :validate_coordinates, :validate_dimensions
23
+
24
+ def validate_coordinates
25
+ return unless store.present? && length.present? && width.present? && start_x.present? && start_y.present?
26
+
27
+ errors.add(:start_x, 'cannot exceed length') if start_x.present? && start_x > store.length
28
+ errors.add(:start_y, 'cannot exceed width') if start_y.present? && start_y > store.width
29
+ end
30
+
31
+ def validate_dimensions
32
+ return unless store.present? && length.present? && width.present? && start_x.present? && start_y.present?
33
+
34
+ errors.add(:length, 'cannot exceed store length') if start_x + length > store.length
35
+ errors.add(:width, 'cannot exceed store width') if start_y + width > store.width
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,24 @@
1
+ module Cats
2
+ module Core
3
+ class Store < ApplicationRecord
4
+ belongs_to :warehouse, class_name: 'Cats::Core::Location'
5
+ has_many :stacks
6
+
7
+ validates :name, :store_keeper_name, :length, :width, :height, presence: true
8
+ validates :length, :width, :height, numericality: { greater_than: 0 }
9
+ validates :gangway_length, :gangway_width, :gangway_corner_dist, presence: true, if: :has_gangway?
10
+ validates :gangway_length,
11
+ :gangway_width,
12
+ :gangway_corner_dist,
13
+ numericality: { greater_than: 0 },
14
+ allow_nil: true
15
+ validate :validate_location
16
+
17
+ def validate_location
18
+ return if warehouse.nil?
19
+
20
+ errors.add(:warehouse, 'must be a valid warehouse') unless warehouse.location_type == Location::WAREHOUSE
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,8 @@
1
+ module Cats
2
+ module Core
3
+ class Transporter < ApplicationRecord
4
+ validates :code, :name, :address, :contact_phone, presence: true
5
+ validates :code, uniqueness: true
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,13 @@
1
+ module Cats
2
+ module Core
3
+ class UnitOfMeasure < ApplicationRecord
4
+ WEIGHT = 'Weight'.freeze
5
+ VOLUME = 'Volume'.freeze
6
+ ITEM = 'Item'.freeze
7
+ UNIT_TYPES = [WEIGHT, VOLUME, ITEM].freeze
8
+
9
+ validates :name, :abbreviation, presence: true, uniqueness: true
10
+ validates :unit_type, presence: true, inclusion: { in: UNIT_TYPES }
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,14 @@
1
+ module Cats
2
+ module Core
3
+ class User < ApplicationRecord
4
+ has_secure_password
5
+ rolify
6
+
7
+ belongs_to :application_module
8
+
9
+ validates :first_name, :last_name, :email, presence: true
10
+ validates :password, length: { minimum: 6 }
11
+ validates :email, uniqueness: true, format: { with: URI::MailTo::EMAIL_REGEXP }
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,12 @@
1
+ module Cats
2
+ module Core
3
+ class WayBill < ApplicationRecord
4
+ belongs_to :source, class_name: 'Cats::Core::Location'
5
+ belongs_to :destination, class_name: 'Cats::Core::Location'
6
+ belongs_to :transporter
7
+
8
+ validates :ref_no, :plate_no, :driver_name, :driver_phone, :date_prepared, presence: true
9
+ validates :ref_no, uniqueness: true
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,15 @@
1
+ module Cats
2
+ module Core
3
+ class WayBillItem < ApplicationRecord
4
+ belongs_to :way_bill
5
+ belongs_to :commodity
6
+
7
+ has_many :source_transactions, class_name: 'Cats::Core::CommodityTransaction', as: :source
8
+ has_many :destination_transactions, class_name: 'Cats::Core::CommodityTransaction', as: :destination
9
+
10
+ validates :quantity, :commodity_status, presence: true
11
+ validates :quantity, numericality: { greater_than: 0 }
12
+ validates :commodity_status, inclusion: { in: Cats::Core::Commodity::COMMODITY_STATUSES }
13
+ end
14
+ end
15
+ end