jobshop 0.0.167 → 0.0.179

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 (120) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -2
  3. data/Rakefile +2 -1
  4. data/app/assets/javascripts/application.js +1 -0
  5. data/app/controllers/jobshop/application_controller.rb +3 -1
  6. data/app/controllers/jobshop/dashboards_controller.rb +11 -0
  7. data/app/controllers/jobshop/departments_controller.rb +52 -0
  8. data/app/controllers/jobshop/employees_controller.rb +77 -0
  9. data/app/controllers/jobshop/organizations_controller.rb +29 -0
  10. data/app/controllers/jobshop/rfqs_controller.rb +49 -0
  11. data/app/controllers/jobshop/roles_controller.rb +52 -0
  12. data/app/helpers/jobshop/application_helper.rb +10 -0
  13. data/app/listeners/jobshop/assignment_listener.rb +13 -0
  14. data/app/mailers/jobshop/rfq_responder_mailer.rb +1 -1
  15. data/app/models/jobshop/auditing.rb +20 -0
  16. data/app/models/jobshop/collection.rb +2 -7
  17. data/app/models/jobshop/customer.rb +6 -17
  18. data/app/models/jobshop/customer/category.rb +2 -8
  19. data/app/models/jobshop/customer/contact.rb +3 -8
  20. data/app/models/jobshop/department.rb +10 -0
  21. data/app/models/jobshop/department/assignment.rb +15 -0
  22. data/app/models/jobshop/employee.rb +13 -6
  23. data/app/models/jobshop/employment.rb +8 -8
  24. data/app/models/jobshop/inspection.rb +1 -1
  25. data/app/models/jobshop/inspection/boolean_criterion.rb +13 -17
  26. data/app/models/jobshop/inspection/criterion.rb +9 -10
  27. data/app/models/jobshop/inspection/deviation_criterion.rb +10 -12
  28. data/app/models/jobshop/inspection/limit_criterion.rb +12 -10
  29. data/app/models/jobshop/inspection/report.rb +22 -34
  30. data/app/models/jobshop/mailman.rb +2 -4
  31. data/app/models/jobshop/order.rb +3 -27
  32. data/app/models/jobshop/order_line.rb +4 -10
  33. data/app/models/jobshop/organization.rb +8 -15
  34. data/app/models/jobshop/organization_state.rb +10 -0
  35. data/app/models/jobshop/place.rb +3 -8
  36. data/app/models/jobshop/product.rb +4 -7
  37. data/app/models/jobshop/rfq.rb +32 -14
  38. data/app/models/jobshop/rfq/line.rb +28 -0
  39. data/app/models/jobshop/rfq/line/assignment.rb +25 -0
  40. data/app/models/jobshop/rfq/line/quantity.rb +23 -0
  41. data/app/models/jobshop/role.rb +3 -9
  42. data/app/models/jobshop/role_assignment.rb +10 -4
  43. data/app/models/jobshop/routing_process.rb +4 -10
  44. data/app/models/jobshop/routing_step.rb +3 -5
  45. data/app/models/jobshop/thing.rb +3 -8
  46. data/app/models/jobshop/user.rb +24 -11
  47. data/app/views/jobshop/dashboards/show.html.haml +35 -0
  48. data/app/views/jobshop/departments/_form.html.haml +12 -0
  49. data/app/views/jobshop/departments/edit.html.haml +7 -0
  50. data/app/views/jobshop/departments/index.html.haml +17 -0
  51. data/app/views/jobshop/departments/new.html.haml +5 -0
  52. data/app/views/jobshop/departments/show.html.haml +15 -0
  53. data/app/views/jobshop/employees/_form.html.haml +46 -0
  54. data/app/views/jobshop/employees/edit.html.haml +1 -0
  55. data/app/views/jobshop/employees/index.html.haml +12 -0
  56. data/app/views/jobshop/employees/new.html.haml +1 -0
  57. data/app/views/jobshop/employees/show.html.haml +16 -0
  58. data/app/views/jobshop/organizations/_form.html.haml +10 -0
  59. data/app/views/jobshop/organizations/edit.html.haml +7 -0
  60. data/app/views/jobshop/organizations/index.html.haml +19 -0
  61. data/app/views/jobshop/organizations/new.html.haml +5 -0
  62. data/app/views/jobshop/organizations/show.html.haml +16 -0
  63. data/app/views/jobshop/rfqs/_form.html.haml +60 -0
  64. data/app/views/jobshop/rfqs/edit.html.haml +4 -0
  65. data/app/views/jobshop/rfqs/index.html.haml +2 -0
  66. data/app/views/jobshop/roles/_form.html.haml +11 -0
  67. data/app/views/jobshop/roles/edit.html.haml +7 -0
  68. data/app/views/jobshop/roles/index.html.haml +21 -0
  69. data/app/views/jobshop/roles/new.html.haml +5 -0
  70. data/app/views/jobshop/roles/show.html.haml +3 -0
  71. data/app/views/layouts/jobshop/application.html.haml +50 -2
  72. data/config/initializers/devise.rb +2 -2
  73. data/config/routes.rb +18 -0
  74. data/db/migrate/20170311194758_initialize_jobshop.rb +4 -39
  75. data/db/migrate/20171216021339_create_organizations.rb +3 -8
  76. data/db/migrate/20171216021350_create_users.rb +28 -0
  77. data/db/migrate/20171216021400_create_employees.rb +27 -9
  78. data/db/migrate/20171216021853_create_customers.rb +29 -14
  79. data/db/migrate/20171216022020_create_places.rb +3 -4
  80. data/db/migrate/20171216022135_create_products.rb +4 -4
  81. data/db/migrate/20171216022605_create_orders.rb +27 -13
  82. data/db/migrate/20171216023018_create_roles.rb +30 -27
  83. data/db/migrate/20171216035357_create_things.rb +26 -23
  84. data/db/migrate/20171219022118_create_routing_processes.rb +28 -33
  85. data/db/migrate/20180107203241_create_inspections.rb +48 -115
  86. data/db/migrate/20181117023949_create_rfqs.rb +74 -15
  87. data/db/migrate/20181118014603_create_mailmen.rb +5 -6
  88. data/db/migrate/20190309163306_create_departments.rb +38 -0
  89. data/db/migrate/support/temporal_tables.sql +210 -0
  90. data/db/seeds.rb +92 -64
  91. data/exe/jobshop +1 -0
  92. data/lib/generators/jobshop/app/app_generator.rb +13 -3
  93. data/lib/generators/jobshop/app/templates/Procfile.tt +1 -1
  94. data/lib/generators/jobshop/app/templates/config/databases/postgresql.yml.tt +24 -0
  95. data/lib/generators/jobshop/app/templates/config/puma.rb.tt +44 -0
  96. data/lib/generators/jobshop/canary/canary_generator.rb +21 -9
  97. data/lib/generators/jobshop/dev_cert/dev_cert_generator.rb +124 -0
  98. data/lib/jobshop.rb +1 -1
  99. data/lib/jobshop/cli.rb +3 -3
  100. data/lib/jobshop/cli/app_generator.rb +15 -10
  101. data/lib/jobshop/cli/application.rb +7 -7
  102. data/lib/jobshop/cli/base.rb +65 -0
  103. data/lib/jobshop/cli/canary.rb +120 -22
  104. data/lib/jobshop/configuration.rb +1 -1
  105. data/lib/jobshop/engine.rb +8 -4
  106. data/lib/jobshop/helpers/migration.rb +27 -66
  107. data/lib/jobshop/mailroom/base_handler.rb +1 -1
  108. data/lib/jobshop/mailroom/null_handler.rb +1 -1
  109. data/lib/jobshop/mailroom/postmaster.rb +1 -1
  110. data/lib/jobshop/mailroom/rfq_handler.rb +1 -1
  111. data/lib/jobshop/version.rb +2 -2
  112. data/lib/tasks/jobshop_tasks.rake +15 -1
  113. metadata +114 -61
  114. data/app/controllers/jobshop/organizations/lookups_controller.rb +0 -18
  115. data/app/models/jobshop/employment_version.rb +0 -10
  116. data/app/models/jobshop/inspection/result.rb +0 -46
  117. data/app/models/jobshop/inspection/tuple.rb +0 -17
  118. data/app/models/jobshop/rfq_line.rb +0 -12
  119. data/db/migrate/20171216021554_create_people.rb +0 -43
  120. data/lib/generators/jobshop/app/templates/config/database.yml.tt +0 -19
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6c48065969cc31f4dbc0155fb650a57b8759fe983b7e4d2daa5d459216296d8b
4
- data.tar.gz: 25a97a07fdbefc8d1e60d7af5099c8d9d2d2918a8114e0f69303b79687d35e43
3
+ metadata.gz: 922b038f72e025abe054d5e4f78c5624483d59ace4082a48e763dc1d4502b1f6
4
+ data.tar.gz: 4f7b0db7c9742386ac470349e0fd80c103f1b49754d0ffb778f00594b9deef48
5
5
  SHA512:
6
- metadata.gz: ebabad19298eeb8bcadf77fe19cce8f71dccc97eaf3ecc1b83244a832b10f4c60f0286ae03436808ff641d7aa04a18de5cd741487ee2a26d51b654ac4c374c90
7
- data.tar.gz: 5953bb253466f946f598b52b500a8be51cb124d9968e725c2c87663b3eae920a4da6f84d6cc76b37842fbf6a685447df84f1e129dca5aac65826488f5f4199bf
6
+ metadata.gz: 5a0116eca2be332fdcd5ef9cc059e1ab3a8cf38603ef35b3fef4fbdef388249322dc5976cb8e6da658f93592c7fcb20e9fc2d459f116891bcae844f138826b96
7
+ data.tar.gz: 0c5c64510e4dc1bdb24cd3ccab712d449f21619f1a5af8cd7a130dc19de04e81daf0b596fa05b47c56e65aae4a9c0c45241d3d249af4850a357ccc3fb92025c5
data/README.md CHANGED
@@ -4,7 +4,6 @@ Real-time production tracking and process evaluation, under your own roof.
4
4
 
5
5
  [![Gem Version](https://badge.fury.io/rb/jobshop.svg)](https://badge.fury.io/rb/jobshop)
6
6
  [![Code Climate](https://codeclimate.com/github/jobshop/jobshop/badges/gpa.svg)](https://codeclimate.com/github/jobshop/jobshop)
7
- [![Build Status](https://semaphoreci.com/api/v1/frankjmattia/jobshop/branches/master/shields_badge.svg)](https://semaphoreci.com/frankjmattia/jobshop)
8
7
  [![Test Coverage](https://codeclimate.com/github/jobshop/jobshop/badges/coverage.svg)](https://codeclimate.com/github/jobshop/jobshop/coverage)
9
8
 
10
9
  ## TL;DR
@@ -78,7 +77,7 @@ tracker. Send an email to
78
77
  ## License
79
78
  Jobshop
80
79
 
81
- Copyright © 2016 Frank J. Mattia
80
+ Copyright © Frank J. Mattia
82
81
 
83
82
  This program is free software: you can redistribute it and/or modify
84
83
  it under the terms of the GNU Affero General Public License as
data/Rakefile CHANGED
@@ -26,7 +26,8 @@ task lint: :environment do
26
26
  FactoryBot.definition_file_paths = [ FACTORY_PATH ]
27
27
  FactoryBot.find_definitions
28
28
 
29
- DatabaseCleaner.cleaning do
29
+ ActiveRecord::Base.connection.transaction do
30
30
  FactoryBot.lint traits: true
31
+ raise ActiveRecord::Rollback
31
32
  end
32
33
  end
@@ -0,0 +1 @@
1
+ console.log("Hello from application.js!");
@@ -4,8 +4,10 @@ module Jobshop
4
4
 
5
5
  layout "jobshop/application"
6
6
 
7
+ before_action :authenticate_user!
8
+
7
9
  def current_organization
8
10
  @current_organization ||= current_user&.organization
9
- end
11
+ end; helper_method :current_organization
10
12
  end
11
13
  end
@@ -2,5 +2,16 @@ require_dependency "jobshop/application_controller"
2
2
 
3
3
  module Jobshop
4
4
  class DashboardsController < ApplicationController
5
+ def show
6
+ @rfqs = current_organization.rfqs.verified
7
+ .or(current_organization.rfqs.verifiable).order(created_at: :asc)
8
+ .includes(:customer, :requested_by).references(:customer)
9
+ .undelegated
10
+
11
+ @low_priority_rfqs = current_organization.rfqs.unverifiable
12
+ .order(created_at: :asc).undelegated
13
+
14
+ @assigned_rfq_lines = current_user.rfq_line_assignments || []
15
+ end
5
16
  end
6
17
  end
@@ -0,0 +1,52 @@
1
+ require_dependency "jobshop/application_controller"
2
+
3
+ module Jobshop
4
+ class DepartmentsController < ApplicationController
5
+ before_action :set_department, only: [:show, :edit, :update, :destroy]
6
+
7
+ def index
8
+ @departments = current_organization.departments.all
9
+ end
10
+
11
+ def show
12
+ end
13
+
14
+ def new
15
+ @department = current_organization.departments.new
16
+ end
17
+
18
+ def edit
19
+ end
20
+
21
+ def create
22
+ @department = current_organization.departments.new(department_params)
23
+
24
+ if @department.save
25
+ redirect_to @department, notice: "Created Department"
26
+ else
27
+ render :new
28
+ end
29
+ end
30
+
31
+ def update
32
+ if @department.update(department_params)
33
+ redirect_to @department, notice: "Updated Department"
34
+ else
35
+ render :edit
36
+ end
37
+ end
38
+
39
+ def destroy
40
+ @department.destroy
41
+ redirect_to departments_url, notice: "Destroyed Department"
42
+ end
43
+
44
+ private def set_department
45
+ @department = current_organization.departments.find(params[:id])
46
+ end
47
+
48
+ private def department_params
49
+ params.require(:department).permit(:name)
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,77 @@
1
+ require_dependency "jobshop/application_controller"
2
+
3
+ module Jobshop
4
+ class EmployeesController < ApplicationController
5
+ def index
6
+ @active_employees = current_organization.employees
7
+ .merge(Jobshop::Employee.active).eager_load(:departments)
8
+ end
9
+
10
+ def new
11
+ build_employee do |employee|
12
+ render :new, locals: { employee: employee }
13
+ end
14
+ end
15
+
16
+ def create
17
+ respond_to do |format|
18
+ build_employee(employee_params) do |employee|
19
+ if employee.save
20
+ format.html {
21
+ redirect_to(employees_path, flash: { notice: "Created Employee" })
22
+ }
23
+ else
24
+ format.html { render :new, locals: { employee: employee } }
25
+ end
26
+ end
27
+ end
28
+ end
29
+
30
+ def edit
31
+ find_employee do |employee|
32
+ render :edit, locals: { employee: employee }
33
+ end
34
+ end
35
+
36
+ def update
37
+ respond_to do |format|
38
+ Wisper.subscribe(Jobshop::AssignmentListener.new(current_user)) do
39
+ find_employee do |employee|
40
+ if employee.update(employee_params)
41
+ format.html {
42
+ redirect_to(employee_path(employee),
43
+ flash: { notice: "Updated Employee" })
44
+ }
45
+ else
46
+ format.html { render :edit, locals: { employee: employee } }
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+
53
+ def show
54
+ find_employee do |employee|
55
+ render :show, locals: { employee: employee }
56
+ end
57
+ end
58
+
59
+ private def build_employee(attrs = {})
60
+ employee = current_organization.employees.build(attrs)
61
+
62
+ yield employee
63
+ end
64
+
65
+ private def find_employee
66
+ employee = current_organization.employees.where(id: params[:id]).first
67
+
68
+ yield employee
69
+ end
70
+
71
+ private def employee_params
72
+ params.require(:employee)
73
+ .permit(:forename, :surname, :email, department_ids: [ ],
74
+ employments_attributes: [ :id, :started_on, :ended_on ])
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,29 @@
1
+ require_dependency "jobshop/application_controller"
2
+
3
+ module Jobshop
4
+ class OrganizationsController < ApplicationController
5
+ before_action :set_organization, only: %i[ show edit update ]
6
+
7
+ def show
8
+ end
9
+
10
+ def edit
11
+ end
12
+
13
+ def update
14
+ if @organization.update(organization_params)
15
+ redirect_to organization_path, notice: "Updated Organization"
16
+ else
17
+ render :edit
18
+ end
19
+ end
20
+
21
+ private def set_organization
22
+ @organization = Organization.find(current_organization.id)
23
+ end
24
+
25
+ private def organization_params
26
+ params.fetch(:organization, {})
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,49 @@
1
+ require_dependency "jobshop/application_controller"
2
+
3
+ module Jobshop
4
+ class RFQsController < ApplicationController
5
+ def edit
6
+ find_rfq do |rfq|
7
+ render :edit, locals: { rfq: rfq }
8
+ end
9
+ end
10
+
11
+ def update
12
+ respond_to do |format|
13
+ Wisper.subscribe(Jobshop::AssignmentListener.new(current_user)) do
14
+ find_rfq do |rfq|
15
+ if rfq.update(rfq_params)
16
+ format.html {
17
+ redirect_to(edit_rfq_path(rfq),
18
+ flash: { notice: "RFQ Saved Successfully" })
19
+ }
20
+ else
21
+ format.html { render :edit, locals: { rfq: rfq } }
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+ private def find_rfq
29
+ rfq = current_organization.rfqs.includes(lines: :quantities)
30
+ .where(id: params[:id])
31
+ .references(:rfqs)
32
+ .merge(Jobshop::RFQ::Line.order(identifier: :asc))
33
+ .merge(Jobshop::RFQ::Line::Quantity.order(quantity: :asc))
34
+ .first
35
+
36
+ yield rfq
37
+ end
38
+
39
+ private def rfq_params
40
+ params.require(:rfq)
41
+ .permit(lines_attributes: [
42
+ :id, :identifier, :description, :_destroy, assignee_ids: [ ],
43
+ quantities_attributes: [
44
+ :id, :organization_id, :rfq_id, :rfq_line_id, :quantity_id, :quantity
45
+ ]
46
+ ])
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,52 @@
1
+ require_dependency "jobshop/application_controller"
2
+
3
+ module Jobshop
4
+ class RolesController < ApplicationController
5
+ before_action :set_role, only: [:show, :edit, :update, :destroy]
6
+
7
+ def index
8
+ @roles = current_organization.roles.all
9
+ end
10
+
11
+ def show
12
+ end
13
+
14
+ def new
15
+ @role = current_organization.roles.new
16
+ end
17
+
18
+ def edit
19
+ end
20
+
21
+ def create
22
+ @role = current_organization.roles.new(role_params)
23
+
24
+ if @role.save
25
+ redirect_to @role, notice: "Created Role"
26
+ else
27
+ render :new
28
+ end
29
+ end
30
+
31
+ def update
32
+ if @role.update(role_params)
33
+ redirect_to @role, notice: "Updated Role"
34
+ else
35
+ render :edit
36
+ end
37
+ end
38
+
39
+ def destroy
40
+ @role.destroy
41
+ redirect_to roles_url, notice: "Destroyed Role"
42
+ end
43
+
44
+ private def set_role
45
+ @role = current_organization.roles.find(params[:id])
46
+ end
47
+
48
+ private def role_params
49
+ params.require(:role).permit(:name)
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jobshop
4
+ module ApplicationHelper
5
+ def webpack_asset_url(name)
6
+ Rails.env.production? ? "/assets/#{name}" \
7
+ : "http://localhost:8080/#{name}"
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jobshop
4
+ class AssignmentListener
5
+ def initialize(assigner)
6
+ @assigner = assigner
7
+ end
8
+
9
+ def set_assigned_by(assignment)
10
+ assignment.assigned_by = @assigner
11
+ end
12
+ end
13
+ end
@@ -1,4 +1,4 @@
1
- # frozen_string_literals: true
1
+ # frozen_string_literal: true
2
2
 
3
3
  module Jobshop
4
4
  class RFQResponderMailer < ApplicationMailer
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/concern"
4
+
5
+ module Jobshop
6
+ module Auditing
7
+ extend ActiveSupport::Concern
8
+
9
+ included do
10
+ audited_class = self
11
+
12
+ self::History = Class.new(ApplicationRecord) do
13
+ private_class_method :new, :create
14
+
15
+ self.table_name = "#{audited_class.table_name}_history"
16
+ self.primary_key = audited_class.primary_key
17
+ end
18
+ end
19
+ end
20
+ end
@@ -1,15 +1,10 @@
1
- # frozen_string_literals
1
+ # frozen_string_literal: true
2
2
 
3
3
  module Jobshop
4
4
  class Collection < ApplicationRecord
5
- self.primary_keys = %i[ organization_id collection_id ]
6
-
7
- after_initialize { self.collection_id ||= SecureRandom.uuid if new_record? }
8
-
9
5
  belongs_to :organization, inverse_of: :collections
10
6
 
11
- has_many :things, inverse_of: :collection,
12
- foreign_key: %i[ organization_id collection_id ]
7
+ has_many :things, inverse_of: :collection
13
8
 
14
9
  validates :name, presence: true,
15
10
  uniqueness: { scope: :organization_id, case_sensitive: false }
@@ -1,30 +1,19 @@
1
- # frozen_string_literals: true
1
+ # frozen_string_literal: true
2
2
 
3
3
  module Jobshop # :nodoc:
4
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 }
5
+ include Auditing
9
6
 
10
7
  belongs_to :organization, -> { readonly }, inverse_of: :customers
11
8
 
12
- belongs_to :category, inverse_of: :customers,
13
- foreign_key: %i[ organization_id category_id ]
9
+ belongs_to :category, inverse_of: :customers
14
10
 
15
- has_many :contacts, inverse_of: :customer,
16
- foreign_key: %i[ organization_id customer_id ]
11
+ has_many :contacts, inverse_of: :customer
17
12
 
18
- has_many :orders, inverse_of: :customer,
19
- foreign_key: %i[ organization_id customer_id ]
13
+ has_many :orders, inverse_of: :customer
20
14
 
21
- has_many :rfqs, inverse_of: :customer,
22
- foreign_key: %i[ organization_id customer_id ]
15
+ has_many :rfqs, inverse_of: :customer
23
16
 
24
17
  validates :name, presence: true
25
18
  end
26
19
  end
27
-
28
- # TODO: CreatedBy Implementation
29
- # belongs_to :created_by, polymorphic: true,
30
- # foreign_key: %i[ organization_id created_by_id ]