jobshop 0.0.163 → 0.0.167

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +3 -3
  3. data/Rakefile +8 -17
  4. data/app/controllers/jobshop/application_controller.rb +5 -4
  5. data/app/controllers/jobshop/places_controller.rb +0 -4
  6. data/app/controllers/jobshop/users_controller.rb +0 -3
  7. data/app/mailers/jobshop/application_mailer.rb +0 -2
  8. data/app/mailers/jobshop/rfq_responder_mailer.rb +18 -0
  9. data/app/models/jobshop/ability.rb +1 -1
  10. data/app/models/jobshop/customer.rb +30 -0
  11. data/app/models/jobshop/customer/category.rb +19 -0
  12. data/app/models/jobshop/customer/contact.rb +28 -0
  13. data/app/models/jobshop/employee.rb +46 -0
  14. data/app/models/jobshop/employment.rb +25 -0
  15. data/app/models/jobshop/employment_version.rb +10 -0
  16. data/app/models/jobshop/inspection/boolean_criterion.rb +2 -2
  17. data/app/models/jobshop/inspection/deviation_criterion.rb +4 -4
  18. data/app/models/jobshop/inspection/limit_criterion.rb +6 -4
  19. data/app/models/jobshop/inspection/report.rb +2 -0
  20. data/app/models/jobshop/inspection/result.rb +2 -2
  21. data/app/models/jobshop/mailman.rb +22 -0
  22. data/app/models/jobshop/order.rb +2 -6
  23. data/app/models/jobshop/order_line.rb +2 -3
  24. data/app/models/jobshop/organization.rb +15 -6
  25. data/app/models/jobshop/place.rb +2 -0
  26. data/app/models/jobshop/product.rb +0 -3
  27. data/app/models/jobshop/rfq.rb +12 -6
  28. data/app/models/jobshop/user.rb +2 -17
  29. data/app/views/jobshop/rfq_responder_mailer/verified_contact.html.erb +5 -0
  30. data/app/views/jobshop/rfq_responder_mailer/verified_contact.text.erb +3 -0
  31. data/app/views/layouts/jobshop/application.html.haml +15 -0
  32. data/app/views/layouts/jobshop/mailer.html.erb +13 -0
  33. data/config/initializers/devise.rb +290 -0
  34. data/config/locales/devise.en.yml +64 -0
  35. data/config/routes.rb +1 -2
  36. data/db/migrate/20170311194758_initialize_jobshop.rb +42 -2
  37. data/db/migrate/20171216021339_create_organizations.rb +1 -4
  38. data/db/migrate/20171216021400_create_employees.rb +47 -0
  39. data/db/migrate/20171216021554_create_people.rb +13 -18
  40. data/db/migrate/20171216021853_create_customers.rb +57 -0
  41. data/db/migrate/20171216022020_create_places.rb +8 -9
  42. data/db/migrate/20171216022135_create_products.rb +6 -13
  43. data/db/migrate/20171216022605_create_orders.rb +19 -36
  44. data/db/migrate/20171216023018_create_roles.rb +5 -3
  45. data/db/migrate/20171216035357_create_things.rb +4 -4
  46. data/db/migrate/20171219022118_create_routing_processes.rb +15 -15
  47. data/db/migrate/20180107203241_create_inspections.rb +15 -14
  48. data/db/migrate/20181117023949_create_rfqs.rb +27 -19
  49. data/db/migrate/20181118014603_create_mailmen.rb +6 -4
  50. data/db/seeds.rb +126 -0
  51. data/lib/generators/jobshop/app/app_generator.rb +1 -1
  52. data/lib/generators/jobshop/app/templates/Procfile.tt +1 -0
  53. data/lib/generators/jobshop/app/templates/config/database.yml.tt +5 -5
  54. data/lib/generators/jobshop/{dummy/dummy_generator.rb → canary/canary_generator.rb} +13 -14
  55. data/lib/generators/jobshop/{dummy → canary}/templates/config/boot.rb.tt +0 -0
  56. data/lib/jobshop.rb +41 -12
  57. data/lib/jobshop/cli.rb +16 -82
  58. data/lib/jobshop/cli/app_generator.rb +38 -0
  59. data/lib/jobshop/cli/application.rb +14 -0
  60. data/lib/jobshop/cli/canary.rb +52 -0
  61. data/lib/jobshop/configuration.rb +16 -11
  62. data/lib/jobshop/engine.rb +39 -28
  63. data/lib/jobshop/helpers/migration.rb +78 -2
  64. data/lib/jobshop/mailroom/base_handler.rb +33 -0
  65. data/lib/jobshop/mailroom/null_handler.rb +10 -0
  66. data/lib/jobshop/mailroom/postmaster.rb +77 -0
  67. data/lib/jobshop/mailroom/rfq_handler.rb +39 -0
  68. data/lib/jobshop/version.rb +3 -1
  69. data/lib/tasks/jobshop_tasks.rake +7 -6
  70. metadata +98 -69
  71. data/app/controllers/concerns/email_token_validation.rb +0 -59
  72. data/app/controllers/concerns/jobshop/authentication_handler.rb +0 -15
  73. data/app/controllers/concerns/jobshop/authorization_handler.rb +0 -29
  74. data/app/controllers/jobshop/session_activations_controller.rb +0 -13
  75. data/app/controllers/jobshop/sessions_controller.rb +0 -20
  76. data/app/email_handlers/jobshop/rfq_handler.rb +0 -43
  77. data/app/models/jobshop/company.rb +0 -35
  78. data/app/models/jobshop/company/type.rb +0 -17
  79. data/app/models/jobshop/company_person.rb +0 -15
  80. data/app/models/jobshop/person.rb +0 -30
  81. data/app/models/jobshop/session_activation.rb +0 -30
  82. data/app/serializers/jobshop/test_user_serializer.rb +0 -10
  83. data/app/services/jobshop/authentication_service.rb +0 -20
  84. data/app/services/jobshop/authorization_service.rb +0 -30
  85. data/app/services/jobshop/jwt_service.rb +0 -17
  86. data/db/migrate/20171216021853_create_companies.rb +0 -64
  87. data/db/migrate/20171216023022_create_sessions.rb +0 -23
  88. data/lib/jobshop/cli/spinner.rb +0 -21
  89. data/lib/jobshop/dummy_app.rb +0 -190
  90. data/lib/jobshop/postmaster.rb +0 -89
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 72d9c251b2bcc65848a33510d25bdee8d14ca55b
4
- data.tar.gz: b0e53706a8d59d0824affb1a416fb519786a520b
2
+ SHA256:
3
+ metadata.gz: 6c48065969cc31f4dbc0155fb650a57b8759fe983b7e4d2daa5d459216296d8b
4
+ data.tar.gz: 25a97a07fdbefc8d1e60d7af5099c8d9d2d2918a8114e0f69303b79687d35e43
5
5
  SHA512:
6
- metadata.gz: 3a442988c2fcc8dc15e7bca171754a7d1ef608cf55a1021354b0be3c189ec1eadac472ffbb33c69371a8a9caceff0513dde3d7624aadf69f07fa5c6cbfe15c53
7
- data.tar.gz: 1aff3bac63832e1f71be8cb40ae5949b8f45966d9752a78f0c2e7a89e8f1e3b01c70b5c58c02ab2b4d034ee419a49fe72f7f562da98bd863046d728e0886fc2b
6
+ metadata.gz: ebabad19298eeb8bcadf77fe19cce8f71dccc97eaf3ecc1b83244a832b10f4c60f0286ae03436808ff641d7aa04a18de5cd741487ee2a26d51b654ac4c374c90
7
+ data.tar.gz: 5953bb253466f946f598b52b500a8be51cb124d9968e725c2c87663b3eae920a4da6f84d6cc76b37842fbf6a685447df84f1e129dca5aac65826488f5f4199bf
data/README.md CHANGED
@@ -19,9 +19,9 @@ manufacturing execution system and put it within reach of the average job shop.
19
19
 
20
20
  Jobshop only requires a few things:
21
21
 
22
- - Ruby >= 2.4
23
- - Rails >= 5.0
24
- - PostgreSQL >= 9.5
22
+ - Ruby >= 2.6
23
+ - Rails >= 5.2
24
+ - PostgreSQL >= 11.0
25
25
 
26
26
  ## Quick Installation
27
27
 
data/Rakefile CHANGED
@@ -1,5 +1,6 @@
1
1
  begin
2
2
  require "bundler/setup"
3
+ require "bundler/gem_tasks"
3
4
  rescue LoadError
4
5
  puts "You must `gem install bundler` and `bundle install` to run rake tasks"
5
6
  end
@@ -14,28 +15,18 @@ RDoc::Task.new(:rdoc) do |rdoc|
14
15
  rdoc.rdoc_files.include("lib/**/*.rb")
15
16
  end
16
17
 
17
- require "jobshop/dummy_app"
18
+ APP_RAKEFILE = File.expand_path("spec/canary/Rakefile", __dir__)
19
+ load "rails/tasks/engine.rake"
18
20
  load "rails/tasks/statistics.rake"
19
-
20
- APP_RAKEFILE = Jobshop::DummyApp.rakefile
21
- require "bundler/gem_tasks"
22
-
23
- load "rails/tasks/engine.rake" if File.exist?(APP_RAKEFILE)
24
-
25
- Bundler::GemHelper.install_tasks
26
-
27
- require "rspec/core"
28
- require "rspec/core/rake_task"
21
+ load "rspec/rails/tasks/rspec.rake"
29
22
 
30
23
  desc "Verify that all FactoryBot factories are valid"
31
24
  task lint: :environment do
25
+ FACTORY_PATH = File.expand_path("spec/factories", __dir__)
26
+ FactoryBot.definition_file_paths = [ FACTORY_PATH ]
27
+ FactoryBot.find_definitions
28
+
32
29
  DatabaseCleaner.cleaning do
33
- FactoryBot.definition_file_paths = Jobshop::DummyApp.factory_paths
34
- FactoryBot.find_definitions
35
30
  FactoryBot.lint traits: true
36
31
  end
37
32
  end
38
-
39
- desc "Run all specs"
40
- RSpec::Core::RakeTask.new(:spec)
41
- task default: :spec
@@ -1,10 +1,11 @@
1
1
  module Jobshop
2
- class ApplicationController < ActionController::API
3
- include Jobshop::AuthorizationHandler
4
- include Jobshop::AuthenticationHandler
2
+ class ApplicationController < ActionController::Base
3
+ protect_from_forgery with: :exception
4
+
5
+ layout "jobshop/application"
5
6
 
6
7
  def current_organization
7
- @current_organization ||= current_user && current_user.organization
8
+ @current_organization ||= current_user&.organization
8
9
  end
9
10
  end
10
11
  end
@@ -4,9 +4,5 @@ module Jobshop
4
4
  class PlacesController < ApplicationController
5
5
  def show
6
6
  end
7
-
8
- private def session_activations
9
- current_user.session_activations
10
- end
11
7
  end
12
8
  end
@@ -2,8 +2,5 @@ require_dependency "jobshop/application_controller"
2
2
 
3
3
  module Jobshop
4
4
  class UsersController < ApplicationController
5
- def current
6
- render(json: Jobshop::TestUserSerializer.new(current_user))
7
- end
8
5
  end
9
6
  end
@@ -1,7 +1,5 @@
1
1
  module Jobshop
2
2
  class ApplicationMailer < ActionMailer::Base
3
- default from: "jobshop-lookup@example.com"
4
-
5
3
  layout "mailer"
6
4
  end
7
5
  end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literals: true
2
+
3
+ module Jobshop
4
+ class RFQResponderMailer < ApplicationMailer
5
+
6
+ # Subject can be set in your I18n file at config/locales/en.yml
7
+ # with the following lookup:
8
+ #
9
+ # en.rfq_responder_mailer.verified_contact.subject
10
+ #
11
+ def verified_contact
12
+ @to = params[:customer_contact]
13
+ @greeting = "RFQ Received"
14
+
15
+ mail(to: @to.email)
16
+ end
17
+ end
18
+ end
@@ -1,6 +1,6 @@
1
1
  module Jobshop
2
2
  class Ability < ApplicationRecord
3
- belongs_to :organization, class_name: "Jobshop::Organization"
3
+ belongs_to :organization, -> { readonly }
4
4
  has_many :role_abilities, -> (object) { where(organization_id: object.organization_id) }
5
5
  has_many :roles, through: :role_abilities
6
6
  end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literals: true
2
+
3
+ module Jobshop # :nodoc:
4
+ class Customer < ApplicationRecord
5
+ self.primary_keys = %i[ organization_id customer_id ]
6
+
7
+ after_initialize { self.customer_id ||= SecureRandom.uuid if new_record? }
8
+ after_create { reload }
9
+
10
+ belongs_to :organization, -> { readonly }, inverse_of: :customers
11
+
12
+ belongs_to :category, inverse_of: :customers,
13
+ foreign_key: %i[ organization_id category_id ]
14
+
15
+ has_many :contacts, inverse_of: :customer,
16
+ foreign_key: %i[ organization_id customer_id ]
17
+
18
+ has_many :orders, inverse_of: :customer,
19
+ foreign_key: %i[ organization_id customer_id ]
20
+
21
+ has_many :rfqs, inverse_of: :customer,
22
+ foreign_key: %i[ organization_id customer_id ]
23
+
24
+ validates :name, presence: true
25
+ end
26
+ end
27
+
28
+ # TODO: CreatedBy Implementation
29
+ # belongs_to :created_by, polymorphic: true,
30
+ # foreign_key: %i[ organization_id created_by_id ]
@@ -0,0 +1,19 @@
1
+ # frozen_string_literals: true
2
+
3
+ module Jobshop
4
+ class Customer::Category < ApplicationRecord
5
+ self.primary_keys = %i[ organization_id category_id ]
6
+
7
+ after_initialize { self.category_id ||= SecureRandom.uuid if new_record? }
8
+ after_create { reload }
9
+
10
+ belongs_to :organization, -> { readonly }, inverse_of: :customer_categories
11
+
12
+ has_many :customers, inverse_of: :category,
13
+ foreign_key: %i[ organization_id category_id ]
14
+
15
+ validates :name, uniqueness: {
16
+ case_insensitive: true, scope: :organization_id
17
+ }
18
+ end
19
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literals: true
2
+
3
+ module Jobshop # :nodoc:
4
+ class Customer::Contact < ApplicationRecord
5
+ self.primary_keys = %i[ organization_id customer_id contact_id ]
6
+
7
+ after_initialize { self.contact_id ||= SecureRandom.uuid if new_record? }
8
+ after_create { reload }
9
+
10
+ belongs_to :organization, inverse_of: :customer_contacts
11
+ belongs_to :customer, inverse_of: :contacts,
12
+ foreign_key: %i[ organization_id customer_id ]
13
+
14
+ validates :email,
15
+ presence: { if: :email_required? },
16
+ format: { if: :email_required?, with: /\A[^@\s]+@[^@\s]+\z/ },
17
+ uniqueness: { if: :email_changed?, scope: :organization_id,
18
+ case_sensitive: false }
19
+
20
+ def full_name
21
+ @name = [ forename, surname ].join(" ")
22
+ end
23
+
24
+ private def email_required?
25
+ true
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literals: true
2
+
3
+ module Jobshop # :nodoc:
4
+ class Employee < ApplicationRecord
5
+ self.primary_keys = %i[ organization_id employee_id ]
6
+
7
+ after_initialize { self.employee_id ||= SecureRandom.uuid if new_record? }
8
+ after_create { reload }
9
+
10
+ belongs_to :organization, -> { readonly }, inverse_of: :employees
11
+
12
+ has_many :employments, inverse_of: :employee,
13
+ foreign_key: %i[ organization_id employee_id ],
14
+ dependent: :restrict_with_exception
15
+
16
+ validates :email,
17
+ presence: { if: :email_required? },
18
+ format: { if: :email_required?, with: /\A[^@\s]+@[^@\s]+\z/ },
19
+ uniqueness: { if: :email_changed?, scope: :organization_id,
20
+ case_sensitive: false }
21
+
22
+ scope :active, -> {
23
+ joins(:employments).merge(Jobshop::Employment.active)
24
+ }
25
+
26
+ scope :inactive, -> {
27
+ joins(:employments).merge(Jobshop::Employment.inactive)
28
+ }
29
+
30
+ def active?
31
+ !!employments.active.first
32
+ end
33
+
34
+ def inactive?
35
+ !employments.active.first
36
+ end
37
+
38
+ def name
39
+ @name = [ forename, surname ].join(" ")
40
+ end
41
+
42
+ private def email_required?
43
+ true
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literals: true
2
+
3
+ module Jobshop
4
+ class Employment < ApplicationRecord
5
+ self.primary_keys = %i[ organization_id employment_id ]
6
+
7
+ after_initialize { self.employment_id ||= SecureRandom.uuid if new_record? }
8
+ after_create { reload }
9
+
10
+ belongs_to :organization, inverse_of: :employments
11
+
12
+ belongs_to :employee, inverse_of: :employments,
13
+ foreign_key: %i[ organization_id employee_id ]
14
+
15
+ default_scope { order(ended_on: :desc, started_on: :desc) }
16
+
17
+ scope :active, -> {
18
+ where(ended_on: nil)
19
+ }
20
+
21
+ scope :inactive, -> {
22
+ where.not(ended_on: nil)
23
+ }
24
+ end
25
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literals: true
2
+
3
+ module Jobshop
4
+ class EmploymentVersion < ApplicationRecord
5
+ private_class_method :new, :create
6
+
7
+ self.table_name = :jobshop_employment_auditing
8
+ self.primary_key = :auditing_id
9
+ end
10
+ end
@@ -21,11 +21,11 @@ module Jobshop
21
21
  end
22
22
 
23
23
  delegate :name, :name=, :position, :position=, to: :criterion
24
-
24
+ =begin
25
25
  def specification
26
26
  @specification ||= "#{condition}\nPASS/FAIL"
27
27
  end
28
-
28
+ =end
29
29
  def tolerance
30
30
  @tolerance ||= condition
31
31
  end
@@ -66,7 +66,7 @@ module Jobshop
66
66
  errors[:base] << "minimum must be less than maximum"
67
67
  end
68
68
  end
69
-
69
+ =begin
70
70
  def specification
71
71
  @specfication ||= if symmetric?
72
72
  "#{nominal}±#{abs(upper)}"
@@ -74,7 +74,7 @@ module Jobshop
74
74
  "#{nominal}\n#{lower}/#{upper}"
75
75
  end
76
76
  end
77
-
77
+ =end
78
78
  def symmetric?
79
79
  @symmetrical ||= lower == upper * -1
80
80
  end
@@ -92,7 +92,7 @@ module Jobshop
92
92
  Unitwise(value.truncate(4), self[:unit])
93
93
  end
94
94
 
95
- private def oversize?(value)
95
+ def oversize?(value)
96
96
  value = if value.respond_to?(:unit)
97
97
  value.convert_to(self[:unit])
98
98
  else
@@ -102,7 +102,7 @@ module Jobshop
102
102
  value > upper || false
103
103
  end
104
104
 
105
- private def undersize?(value)
105
+ def undersize?(value)
106
106
  value = if value.respond_to?(:unit)
107
107
  value.convert_to(self[:unit])
108
108
  else
@@ -48,13 +48,13 @@ module Jobshop
48
48
  self[:maximum] = value
49
49
  end
50
50
  end
51
-
51
+ =begin
52
52
  def specification
53
53
  @specification ||= [
54
54
  qualifier, [ minimum, maximum ].compact.join("/")
55
55
  ].compact.join("\n")
56
56
  end
57
-
57
+ =end
58
58
  def qualifier
59
59
  @qualifier ||= if minimum && !maximum
60
60
  "Minimum"
@@ -77,18 +77,19 @@ module Jobshop
77
77
  !undersize?(value) && !oversize?(value)
78
78
  end
79
79
 
80
- private def oversize?(value)
80
+ def oversize?(value)
81
81
  value = Unitwise(value, self[:unit]) unless value.respond_to?(:unit)
82
82
  maximum && value > maximum || false
83
83
  end
84
84
 
85
- private def undersize?(value)
85
+ def undersize?(value)
86
86
  value = Unitwise(value, self[:unit]) unless value.respond_to?(:unit)
87
87
  minimum && value < minimum || false
88
88
  end
89
89
 
90
90
  # Generate a random value that has a 90% chance of being in spec.
91
91
  # TODO: This needs to go in the tests somewhere, not really in the model.
92
+ # :nocov:
92
93
  def random
93
94
  value = if bound?
94
95
  rand(self[:minimum].to_f..self[:maximum].to_f) * 1.1
@@ -100,6 +101,7 @@ module Jobshop
100
101
 
101
102
  Unitwise(value, self[:unit])
102
103
  end
104
+ # :nocov:
103
105
 
104
106
  private def minimum_or_maximum_or_both
105
107
  unless minimum || maximum
@@ -17,6 +17,7 @@ module Jobshop
17
17
  has_many :tuples, -> { order(:position) }, inverse_of: :report,
18
18
  foreign_key: %i[ organization_id report_id ]
19
19
 
20
+ =begin
20
21
  def ascii
21
22
  require "terminal-table"
22
23
  table = Terminal::Table.new do |t|
@@ -33,5 +34,6 @@ module Jobshop
33
34
 
34
35
  puts table
35
36
  end
37
+ =end
36
38
  end
37
39
  end
@@ -19,7 +19,7 @@ module Jobshop
19
19
 
20
20
  def value
21
21
  if self[:unit] == "boolean"
22
- !!self[:value]
22
+ FALSE_VALUES.exclude?(self[:value])
23
23
  else
24
24
  self[:value] && Unitwise(self[:value].truncate(4), self[:unit])
25
25
  end
@@ -27,7 +27,7 @@ module Jobshop
27
27
 
28
28
  def value=(value)
29
29
  if criterion.unit == "boolean"
30
- self[:value] = value
30
+ self[:value] = FALSE_VALUES.exclude?(value)
31
31
  self[:unit] = "boolean"
32
32
  else
33
33
  if value.respond_to?(:unit)