cats_core 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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