jobshop 0.0.167 → 0.0.179

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