ecom_core 1.2.34 → 1.3.2
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.
- checksums.yaml +4 -4
- data/app/controllers/ecom/core/{project_crews_controller.rb → site_crews_controller.rb} +5 -4
- data/app/controllers/ecom/core/unit_costs_controller.rb +29 -0
- data/app/models/ecom/core/attendance_sheet.rb +19 -19
- data/app/models/ecom/core/available_unit_of_measurement.rb +10 -0
- data/app/models/ecom/core/crew.rb +4 -2
- data/app/models/ecom/core/crew_contract.rb +41 -1
- data/app/models/ecom/core/crew_contract_transaction.rb +29 -0
- data/app/models/ecom/core/crew_id_card.rb +36 -0
- data/app/models/ecom/core/inspection_checklist.rb +6 -0
- data/app/models/ecom/core/lookahead_plan.rb +41 -0
- data/app/models/ecom/core/lookahead_plan_history.rb +16 -0
- data/app/models/ecom/core/lookahead_plan_review_time.rb +29 -0
- data/app/models/ecom/core/lookahead_plan_task_progress.rb +22 -0
- data/app/models/ecom/core/material.rb +6 -0
- data/app/models/ecom/core/material_identity.rb +21 -0
- data/app/models/ecom/core/material_item.rb +18 -0
- data/app/models/ecom/core/material_sub_type.rb +20 -0
- data/app/models/ecom/core/measurement_unit.rb +4 -14
- data/app/models/ecom/core/overtime_sheet.rb +13 -15
- data/app/models/ecom/core/payroll.rb +3 -3
- data/app/models/ecom/core/project.rb +0 -3
- data/app/models/ecom/core/project_template.rb +13 -0
- data/app/models/ecom/core/project_work_item_template.rb +9 -0
- data/app/models/ecom/core/resource_requisition.rb +21 -0
- data/app/models/ecom/core/resource_requisition_item.rb +45 -0
- data/app/models/ecom/core/{project_crew.rb → site.rb} +8 -4
- data/app/models/ecom/core/site_crew.rb +27 -0
- data/app/models/ecom/core/stakeholder.rb +1 -1
- data/app/models/ecom/core/task.rb +22 -9
- data/app/models/ecom/core/task_attachment.rb +11 -0
- data/app/models/ecom/core/task_inspection_checklist.rb +18 -0
- data/app/models/ecom/core/task_template.rb +20 -90
- data/app/models/ecom/core/task_template_inspection_checklist.rb +8 -0
- data/app/models/ecom/core/unit_cost.rb +27 -0
- data/app/models/ecom/core/unit_of_measure.rb +8 -0
- data/app/models/ecom/core/work_item_resource_requirement_template.rb +18 -0
- data/app/models/ecom/core/work_package.rb +3 -0
- data/app/models/ecom/core/work_product.rb +2 -18
- data/app/models/ecom/core/work_product_template.rb +2 -2
- data/app/serializers/ecom/core/unit_cost_serializer.rb +21 -0
- data/app/services/ecom/core/crew_contract_transaction_service.rb +89 -0
- data/app/services/ecom/core/menu_service.rb +2 -2
- data/app/services/ecom/core/site_crew_service.rb +44 -0
- data/app/uploaders/ecom/core/photo_uploader.rb +5 -1
- data/app/uploaders/ecom/core/task_attachment_uploader.rb +11 -0
- data/config/initializers/carrierwave.rb +8 -0
- data/config/routes.rb +4 -2
- data/db/migrate/20191118052213_create_ecom_core_unit_of_measures.rb +11 -0
- data/db/migrate/20191119012030_create_ecom_core_task_templates.rb +10 -8
- data/db/migrate/20191119013236_create_ecom_core_work_product_templates.rb +0 -15
- data/db/migrate/20191119021405_create_ecom_core_project_templates.rb +15 -0
- data/db/migrate/20191119034319_create_ecom_core_project_work_item_templates.rb +20 -0
- data/db/migrate/20191201145849_create_ecom_core_sites.rb +16 -0
- data/db/migrate/20191202222210_create_ecom_core_work_packages.rb +12 -0
- data/db/migrate/20191202235434_create_ecom_core_work_products.rb +2 -17
- data/db/migrate/20191207103730_create_ecom_core_lookahead_plans.rb +19 -0
- data/db/migrate/20191207103735_create_ecom_core_tasks.rb +15 -10
- data/db/migrate/20191225140433_create_ecom_core_attendance_sheets.rb +4 -4
- data/db/migrate/20200126081005_create_ecom_core_payrolls.rb +3 -3
- data/db/migrate/20200410090701_create_ecom_core_overtime_sheets.rb +4 -4
- data/db/migrate/20200616044231_create_ecom_core_material_sub_types.rb +14 -0
- data/db/migrate/20200616051902_create_ecom_core_material_identities.rb +17 -0
- data/db/migrate/20200618105233_create_ecom_core_material_items.rb +16 -0
- data/db/migrate/20200813165555_create_ecom_core_available_unit_of_measurements.rb +16 -0
- data/db/migrate/20200901085227_create_ecom_core_crew_contracts.rb +7 -1
- data/db/migrate/20201013072924_create_ecom_core_crew_contract_transactions.rb +16 -0
- data/db/migrate/20201013090609_create_ecom_core_site_crews.rb.rb +22 -0
- data/db/migrate/20201013094100_create_ecom_core_crew_id_cards.rb +16 -0
- data/db/migrate/20201113050953_create_ecom_core_task_inspection_checklists.rb +22 -0
- data/db/migrate/20201113094302_create_ecom_core_task_template_inspection_checklists.rb +17 -0
- data/db/migrate/20201121064916_create_ecom_core_unit_costs.rb +30 -0
- data/db/migrate/20201122123227_create_ecom_core_lookahead_plan_backlogs.rb +18 -0
- data/db/migrate/20201122170645_create_ecom_core_lookahead_plan_histories.rb +21 -0
- data/db/migrate/20201122170724_create_ecom_core_lookahead_plan_task_progresses.rb +21 -0
- data/db/migrate/20201123134917_create_ecom_core_task_attachments.rb +15 -0
- data/db/migrate/20201124171642_create_ecom_core_lookahead_plan_review_times.rb +17 -0
- data/db/migrate/20201125191158_create_ecom_core_work_item_resource_requirement_templates.rb +31 -0
- data/db/migrate/20201126191334_create_ecom_core_resource_requisitions.rb +23 -0
- data/db/migrate/20201126191349_create_ecom_core_resource_requisition_items.rb +33 -0
- data/lib/ecom/core/version.rb +1 -1
- data/spec/factories/ecom/core/attendance_sheets.rb +1 -1
- data/spec/factories/ecom/core/available_unit_of_measurements.rb +6 -0
- data/spec/factories/ecom/core/crew_contract_transactions.rb +8 -0
- data/spec/factories/ecom/core/crew_contracts.rb +12 -0
- data/spec/factories/ecom/core/crew_id_cards.rb +8 -0
- data/spec/factories/{dimension_elements.rb → ecom/core/dimension_elements.rb} +0 -0
- data/spec/factories/ecom/core/inspection_checklists.rb +5 -0
- data/spec/factories/ecom/core/lookahead_plan_histories.rb +9 -0
- data/spec/factories/ecom/core/lookahead_plan_review_times.rb +8 -0
- data/spec/factories/ecom/core/lookahead_plan_task_progresses.rb +9 -0
- data/spec/factories/ecom/core/lookahead_plans.rb +10 -0
- data/spec/factories/ecom/core/material_identities.rb +6 -0
- data/spec/factories/ecom/core/material_items.rb +6 -0
- data/spec/factories/ecom/core/material_sub_types.rb +6 -0
- data/spec/factories/ecom/core/materials.rb +5 -0
- data/spec/factories/{measurement_units.rb → ecom/core/measurement_units.rb} +6 -0
- data/spec/factories/ecom/core/overtime_sheets.rb +1 -1
- data/spec/factories/ecom/core/payrolls.rb +1 -1
- data/spec/factories/ecom/core/project_templates.rb +8 -0
- data/spec/factories/ecom/core/project_work_item_templates.rb +7 -0
- data/spec/factories/ecom/core/resource_requisition_items.rb +12 -0
- data/spec/factories/ecom/core/resource_requisitions.rb +9 -0
- data/spec/factories/ecom/core/site_crews.rb +10 -0
- data/spec/factories/ecom/core/sites.rb +8 -0
- data/spec/factories/ecom/core/task_attachments.rb +8 -0
- data/spec/factories/ecom/core/task_inspection_checklists.rb +11 -0
- data/spec/factories/ecom/core/task_template_inspection_checklists.rb +7 -0
- data/spec/factories/ecom/core/task_templates.rb +11 -6
- data/spec/factories/ecom/core/tasks.rb +9 -3
- data/spec/factories/ecom/core/unit_costs.rb +13 -0
- data/spec/factories/ecom/core/unit_of_measures.rb +7 -0
- data/spec/factories/ecom/core/work_item_resource_requirement_templates.rb +10 -0
- data/spec/factories/ecom/core/work_packages.rb +6 -0
- data/spec/factories/ecom/core/work_product_templates.rb +0 -1
- data/spec/factories/ecom/core/work_products.rb +1 -7
- metadata +97 -23
- data/app/controllers/concerns/ecom/core/filterable.rb +0 -14
- data/app/models/ecom/core/plan.rb +0 -18
- data/app/models/ecom/core/takeoff_calculator.rb +0 -115
- data/app/models/ecom/core/task_step.rb +0 -85
- data/app/models/ecom/core/task_step_dependency.rb +0 -10
- data/app/services/ecom/core/project_crew_service.rb +0 -39
- data/db/migrate/20191119012027_create_ecom_core_takeoff_calculators.rb +0 -11
- data/db/migrate/20191207103730_create_ecom_core_plans.rb +0 -12
- data/db/migrate/20191225121850_create_ecom_core_project_crews.rb +0 -19
- data/db/migrate/20200820123719_create_ecom_core_task_steps.rb +0 -17
- data/db/migrate/20200821130934_create_ecom_core_task_step_dependencies.rb +0 -16
- data/spec/factories/ecom/core/plans.rb +0 -8
- data/spec/factories/ecom/core/project_crews.rb +0 -9
- data/spec/factories/ecom/core/takeoff_calculators.rb +0 -18
- data/spec/factories/ecom/core/task_step_dependencies.rb +0 -6
- data/spec/factories/ecom/core/task_steps.rb +0 -8
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module Ecom
|
|
2
|
+
module Core
|
|
3
|
+
class MaterialItem < ApplicationRecord
|
|
4
|
+
before_save :assign_serial_number
|
|
5
|
+
|
|
6
|
+
belongs_to :material_identity
|
|
7
|
+
|
|
8
|
+
validates :serial_number, presence: true, uniqueness: true
|
|
9
|
+
validates :material_identity_id, :material_identity, presence: true
|
|
10
|
+
validates :serial_number, format: { with: /^SN_\d+$/, message: 'Invalid serial number format', multiline: true }
|
|
11
|
+
validates :price, numericality: { greater_than: 0 }, allow_nil: true
|
|
12
|
+
|
|
13
|
+
def assign_serial_number
|
|
14
|
+
self.serial_number = "SN_#{(Time.now.to_f * 1000).to_i}"
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module Ecom
|
|
2
|
+
module Core
|
|
3
|
+
class MaterialSubType < ApplicationRecord
|
|
4
|
+
after_save :create_material_identity
|
|
5
|
+
|
|
6
|
+
belongs_to :material_type
|
|
7
|
+
has_many :material_identity
|
|
8
|
+
|
|
9
|
+
validates :name, presence: true, uniqueness: { case_sensitive: false, scope: :material_type_id }
|
|
10
|
+
validates :material_type_id, :material_type, presence: true
|
|
11
|
+
|
|
12
|
+
def create_material_identity
|
|
13
|
+
Ecom::Core::MaterialIdentity.create(
|
|
14
|
+
material_type_id: material_type_id,
|
|
15
|
+
material_sub_type_id: id
|
|
16
|
+
)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -28,7 +28,10 @@ module Ecom
|
|
|
28
28
|
validates :physical_quantity, inclusion: PHYSICAL_QUANTITIES
|
|
29
29
|
|
|
30
30
|
validate :si_unit_with_conversion_factor
|
|
31
|
-
|
|
31
|
+
validates_uniqueness_of :is_si_unit, scope: %i[physical_quantity system_of_measurement],
|
|
32
|
+
if: -> { is_si_unit == true },
|
|
33
|
+
message: 'There exist an si unit of measurement for the '\
|
|
34
|
+
'given physical quantity and system of measurement'
|
|
32
35
|
|
|
33
36
|
def si_unit_with_conversion_factor
|
|
34
37
|
if is_si_unit && conversion_factor != 1
|
|
@@ -37,19 +40,6 @@ module Ecom
|
|
|
37
40
|
errors.add(:base, 'Only SI units can have a conversion factor 1')
|
|
38
41
|
end
|
|
39
42
|
end
|
|
40
|
-
|
|
41
|
-
# scope si unit with system of measurement and physical quantity
|
|
42
|
-
def si_unit_system_of_measurement_and_physical_quantity
|
|
43
|
-
return if system_of_measurement.nil? || physical_quantity.nil?
|
|
44
|
-
|
|
45
|
-
existing_record = MeasurementUnit
|
|
46
|
-
.where(system_of_measurement: system_of_measurement,
|
|
47
|
-
physical_quantity: physical_quantity, is_si_unit: true).first
|
|
48
|
-
return unless (new_record? && existing_record.present?) || (persisted? && existing_record != self)
|
|
49
|
-
|
|
50
|
-
errors.add(:is_si_unit,
|
|
51
|
-
'There exist an si unit of measurement for the given physical quantity and system of measurement')
|
|
52
|
-
end
|
|
53
43
|
end
|
|
54
44
|
end
|
|
55
45
|
end
|
|
@@ -1,39 +1,37 @@
|
|
|
1
1
|
module Ecom
|
|
2
2
|
module Core
|
|
3
3
|
class OvertimeSheet < ApplicationRecord
|
|
4
|
-
validates :date, :opened_at, presence: true, uniqueness: { scope: :
|
|
4
|
+
validates :date, :opened_at, presence: true, uniqueness: { scope: :site_id }
|
|
5
5
|
validates :status, inclusion: StatusConstants::STATUSES
|
|
6
6
|
|
|
7
|
-
belongs_to :
|
|
7
|
+
belongs_to :site
|
|
8
8
|
|
|
9
9
|
has_many :overtime_sheet_entries
|
|
10
10
|
has_many :crew_overtimes, through: :overtime_sheet_entries
|
|
11
11
|
|
|
12
|
-
scope :
|
|
12
|
+
scope :by_site, ->(id) { where(site_id: id) }
|
|
13
13
|
scope :by_date, ->(date) { where(date: date) }
|
|
14
14
|
scope :by_status, ->(status) { where(status: status) }
|
|
15
15
|
scope :by_date_between, ->(from, to) { where('date BETWEEN ? AND ?', from, to) }
|
|
16
|
-
# scope :open, ->(id) { where(status: StatusConstants::OPEN, project_id: id) }
|
|
17
|
-
# scope :submitted, ->(id) { where(status: StatusConstants::SUBMITTED, project_id: id) }
|
|
18
16
|
|
|
19
|
-
def self.open_exists?(
|
|
17
|
+
def self.open_exists?(site_id)
|
|
20
18
|
OvertimeSheet
|
|
21
|
-
.
|
|
19
|
+
.by_site(site_id)
|
|
22
20
|
.by_status(StatusConstants::OPEN)
|
|
23
21
|
.exists?
|
|
24
22
|
end
|
|
25
23
|
|
|
26
|
-
def self.open_for_date_exists?(date,
|
|
24
|
+
def self.open_for_date_exists?(date, site_id)
|
|
27
25
|
OvertimeSheet
|
|
28
|
-
.
|
|
26
|
+
.by_site(site_id)
|
|
29
27
|
.by_status(StatusConstants::OPEN)
|
|
30
28
|
.by_date(date)
|
|
31
29
|
.exists?
|
|
32
30
|
end
|
|
33
31
|
|
|
34
|
-
def self.exists_for_date?(date,
|
|
32
|
+
def self.exists_for_date?(date, site_id)
|
|
35
33
|
OvertimeSheet
|
|
36
|
-
.
|
|
34
|
+
.by_site(site_id)
|
|
37
35
|
.by_date(date)
|
|
38
36
|
.exists?
|
|
39
37
|
end
|
|
@@ -43,18 +41,18 @@ module Ecom
|
|
|
43
41
|
# check if there is an open overtime already,
|
|
44
42
|
# and also that we have only one open overtime
|
|
45
43
|
# sheet at a time.
|
|
46
|
-
def self.create_new(date,
|
|
47
|
-
if OvertimeSheet.exists_for_date?(date,
|
|
44
|
+
def self.create_new(date, site_id)
|
|
45
|
+
if OvertimeSheet.exists_for_date?(date, site_id)
|
|
48
46
|
raise 'There is already an overtime sheet for the selected date.'
|
|
49
47
|
end
|
|
50
48
|
|
|
51
|
-
if OvertimeSheet.open_exists?(
|
|
49
|
+
if OvertimeSheet.open_exists?(site_id)
|
|
52
50
|
open_overtime_sheet = OvertimeSheet.find_by(status: 'Open')
|
|
53
51
|
raise "There is already an open overtime sheet for #{open_overtime_sheet.date}.
|
|
54
52
|
It has to be submitted before creating a new one."
|
|
55
53
|
end
|
|
56
54
|
|
|
57
|
-
OvertimeSheet.create(date: date, opened_at: Time.now, status: StatusConstants::OPEN,
|
|
55
|
+
OvertimeSheet.create(date: date, opened_at: Time.now, status: StatusConstants::OPEN, site_id: site_id)
|
|
58
56
|
end
|
|
59
57
|
|
|
60
58
|
def submit
|
|
@@ -4,9 +4,9 @@ module Ecom
|
|
|
4
4
|
validates :month, :year, presence: true
|
|
5
5
|
|
|
6
6
|
has_many :payments, class_name: 'Ecom::Core::Payment'
|
|
7
|
-
belongs_to :
|
|
7
|
+
belongs_to :site
|
|
8
8
|
|
|
9
|
-
scope :
|
|
9
|
+
scope :by_site, ->(id) { where(site_id: id) }
|
|
10
10
|
scope :by_month, ->(month) { where(month: month) }
|
|
11
11
|
scope :by_year, ->(year) { where(year: year) }
|
|
12
12
|
|
|
@@ -17,7 +17,7 @@ module Ecom
|
|
|
17
17
|
m = 1
|
|
18
18
|
y += 1
|
|
19
19
|
end
|
|
20
|
-
Payroll.create(month: m, year: y,
|
|
20
|
+
Payroll.create(month: m, year: y, site_id: site_id)
|
|
21
21
|
end
|
|
22
22
|
end
|
|
23
23
|
end
|
|
@@ -9,9 +9,6 @@ module Ecom
|
|
|
9
9
|
belongs_to :currency
|
|
10
10
|
belongs_to :company
|
|
11
11
|
|
|
12
|
-
has_many :project_crews
|
|
13
|
-
has_many :crews, through: :project_crews
|
|
14
|
-
|
|
15
12
|
validates :name, :location, :contract_number, :date_contract_signed, :commencement_date, :completion_date,
|
|
16
13
|
:contract_amount, :advance_payment, :retention, presence: true
|
|
17
14
|
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
module Ecom
|
|
2
|
+
module Core
|
|
3
|
+
class ProjectTemplate < ApplicationRecord
|
|
4
|
+
belongs_to :task_template_type
|
|
5
|
+
has_many :project_work_item_templates
|
|
6
|
+
|
|
7
|
+
validates :code, :name, presence: true
|
|
8
|
+
validates_uniqueness_of :code
|
|
9
|
+
|
|
10
|
+
delegate(:name, to: :task_template_type, prefix: true)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
module Ecom
|
|
2
|
+
module Core
|
|
3
|
+
class ResourceRequisition < ApplicationRecord
|
|
4
|
+
DRAFT = 'Draft'.freeze
|
|
5
|
+
SUBMITTED = 'Submitted'.freeze
|
|
6
|
+
APPROVED = 'Approved'.freeze
|
|
7
|
+
REJECTED = 'Rejected'.freeze
|
|
8
|
+
|
|
9
|
+
STATUSES = [DRAFT, SUBMITTED, APPROVED, REJECTED].freeze
|
|
10
|
+
|
|
11
|
+
belongs_to :lookahead_plan
|
|
12
|
+
belongs_to :reviewed_by, class_name: 'Ecom::Core::User', optional: true
|
|
13
|
+
belongs_to :approved_by, class_name: 'Ecom::Core::User', optional: true
|
|
14
|
+
has_many :resource_requisition_items
|
|
15
|
+
|
|
16
|
+
validates :delivery_point, presence: true
|
|
17
|
+
|
|
18
|
+
validates :status, presence: true, inclusion: STATUSES
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
module Ecom
|
|
2
|
+
module Core
|
|
3
|
+
class ResourceRequisitionItem < ApplicationRecord
|
|
4
|
+
PENDING = 'Pending'.freeze
|
|
5
|
+
APPROVED = 'Approved'.freeze
|
|
6
|
+
REJECTED = 'Rejected'.freeze
|
|
7
|
+
|
|
8
|
+
STATUSES = [PENDING, APPROVED, REJECTED].freeze
|
|
9
|
+
|
|
10
|
+
belongs_to :resource_requisition
|
|
11
|
+
belongs_to :resource_type
|
|
12
|
+
belongs_to :requested_quantity_measurement_unit, class_name: 'Ecom::Core::MeasurementUnit'
|
|
13
|
+
belongs_to :awaiting_quantity_measurement_unit, class_name: 'Ecom::Core::MeasurementUnit'
|
|
14
|
+
|
|
15
|
+
validates :due_date, presence: true
|
|
16
|
+
|
|
17
|
+
validates :requested_quantity, presence: true, numericality: { greater_than: 0 }
|
|
18
|
+
validates :awaiting_quantity, presence: true, numericality: { greater_than: 0 }
|
|
19
|
+
|
|
20
|
+
validates :status, presence: true, inclusion: STATUSES
|
|
21
|
+
|
|
22
|
+
validate :quantity_validator
|
|
23
|
+
|
|
24
|
+
def quantity_validator
|
|
25
|
+
if requested_quantity.nil? || awaiting_quantity.nil? ||
|
|
26
|
+
requested_quantity_measurement_unit_id.nil? ||
|
|
27
|
+
awaiting_quantity_measurement_unit_id.nil?
|
|
28
|
+
return
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
requested_quantity_measurement_unit =
|
|
32
|
+
Ecom::Core::MeasurementUnit.find_by(id: requested_quantity_measurement_unit_id)
|
|
33
|
+
awaiting_quantity_measurement_unit =
|
|
34
|
+
Ecom::Core::MeasurementUnit.find_by(id: awaiting_quantity_measurement_unit_id)
|
|
35
|
+
|
|
36
|
+
requested_quantity_in_si_unit = requested_quantity / requested_quantity_measurement_unit.conversion_factor
|
|
37
|
+
awaiting_quantity_in_si_unit = awaiting_quantity / awaiting_quantity_measurement_unit.conversion_factor
|
|
38
|
+
|
|
39
|
+
return unless awaiting_quantity_in_si_unit > requested_quantity_in_si_unit
|
|
40
|
+
|
|
41
|
+
errors.add(:awaiting_quantity, 'awaiting quantity can not be greater than requested quantity')
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
module Ecom
|
|
2
2
|
module Core
|
|
3
|
-
class
|
|
3
|
+
class Site < ApplicationRecord
|
|
4
4
|
ACTIVE = 'Active'.freeze
|
|
5
5
|
INACTIVE = 'Inactive'.freeze
|
|
6
|
+
|
|
6
7
|
STATUSES = [ACTIVE, INACTIVE].freeze
|
|
7
8
|
|
|
8
|
-
|
|
9
|
-
belongs_to :crew
|
|
9
|
+
validates :name, :project_id, :project, :address, :status, presence: true
|
|
10
10
|
|
|
11
|
-
validates :start_date, :status, presence: true
|
|
12
11
|
validates :status, inclusion: STATUSES
|
|
12
|
+
|
|
13
|
+
belongs_to :project
|
|
14
|
+
|
|
15
|
+
has_many :site_crews
|
|
16
|
+
has_many :crews, through: :site_crews
|
|
13
17
|
end
|
|
14
18
|
end
|
|
15
19
|
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
module Ecom
|
|
2
|
+
module Core
|
|
3
|
+
class SiteCrew < ApplicationRecord
|
|
4
|
+
TEMPORARY_SITE_CREW = 'Temporary site crew'.freeze
|
|
5
|
+
PERMANENT_SITE_CREW = 'Permanent site crew'.freeze
|
|
6
|
+
|
|
7
|
+
SITE_CREW_TYPES = [TEMPORARY_SITE_CREW, PERMANENT_SITE_CREW].freeze
|
|
8
|
+
|
|
9
|
+
ACTIVE = 'Active'.freeze
|
|
10
|
+
INACTIVE = 'Inactive'.freeze
|
|
11
|
+
STATUSES = [ACTIVE, INACTIVE].freeze
|
|
12
|
+
|
|
13
|
+
validates :crew_id, :crew, :site_id, :site, :start_date, :site_crew_type, :status, presence: true
|
|
14
|
+
|
|
15
|
+
validates_uniqueness_of :site_id,
|
|
16
|
+
scope: :crew_id,
|
|
17
|
+
if: -> { status == 'Active' },
|
|
18
|
+
message: 'There can only be one record with status `Active` for a given site and crew'
|
|
19
|
+
|
|
20
|
+
validates :site_crew_type, inclusion: SITE_CREW_TYPES
|
|
21
|
+
validates :status, inclusion: STATUSES
|
|
22
|
+
|
|
23
|
+
belongs_to :crew
|
|
24
|
+
belongs_to :site
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -5,34 +5,47 @@ module Ecom
|
|
|
5
5
|
|
|
6
6
|
has_ancestry
|
|
7
7
|
|
|
8
|
+
NOT_INSPECTED = 'Not Inspected'.freeze
|
|
9
|
+
IN_PROGRESS = 'In Progress'.freeze
|
|
10
|
+
PASS = 'Pass'.freeze
|
|
11
|
+
FAIL = 'Fail'.freeze
|
|
12
|
+
|
|
13
|
+
INSPECTION_STATUSES = [NOT_INSPECTED, IN_PROGRESS, PASS, FAIL].freeze
|
|
14
|
+
|
|
8
15
|
belongs_to :work_product
|
|
9
16
|
belongs_to :task_template
|
|
10
17
|
belongs_to :work_package, optional: true
|
|
11
18
|
belongs_to :work_order, optional: true
|
|
12
|
-
belongs_to :plan, optional: true
|
|
13
19
|
belongs_to :performer, class_name: 'Ecom::Core::User', optional: true
|
|
14
|
-
belongs_to :
|
|
15
|
-
belongs_to :
|
|
16
|
-
belongs_to :
|
|
20
|
+
belongs_to :client_consultant, class_name: 'Ecom::Core::User', optional: true
|
|
21
|
+
belongs_to :foreman, class_name: 'Ecom::Core::User', optional: true
|
|
22
|
+
belongs_to :inspector, class_name: 'Ecom::Core::User', optional: true
|
|
23
|
+
belongs_to :change_order_for, class_name: 'Ecom::Core::User', optional: true
|
|
17
24
|
|
|
18
|
-
has_many :task_steps
|
|
19
25
|
has_many :task_resources
|
|
20
26
|
has_one :takeoff
|
|
27
|
+
has_one :change_order, foreign_key: :change_order_for_id, class_name: 'Ecom::Core::Task'
|
|
21
28
|
|
|
22
29
|
validates_with DateRangeValidator
|
|
23
|
-
validates :code, :name, :status, :percent_completed, presence: true
|
|
30
|
+
validates :code, :name, :status, :inspection_status, :percent_completed, presence: true
|
|
24
31
|
validates_numericality_of :percent_completed,
|
|
25
32
|
only_integer: true,
|
|
26
33
|
greater_than_or_equal_to: 0,
|
|
27
34
|
less_than_or_equal_to: 100
|
|
35
|
+
validates :percentage_contribution,
|
|
36
|
+
numericality: {
|
|
37
|
+
greater_than_or_equal_to: 0,
|
|
38
|
+
less_than_or_equal_to: 100,
|
|
39
|
+
only_integer: true
|
|
40
|
+
},
|
|
41
|
+
allow_nil: true
|
|
42
|
+
|
|
43
|
+
validates_inclusion_of :inspection_status, in: INSPECTION_STATUSES
|
|
28
44
|
|
|
29
45
|
scope :by_status, ->(status) { where(status: status) }
|
|
30
46
|
|
|
31
|
-
# State: planned -> The task has be planned for execution
|
|
32
|
-
# State: ready_to_start -> All resources for the task has been set and is ready to start
|
|
33
47
|
aasm column: 'status' do
|
|
34
48
|
state :new, initial: true
|
|
35
|
-
state :planned
|
|
36
49
|
state :ready_to_start
|
|
37
50
|
state :in_progress
|
|
38
51
|
state :submitted
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module Ecom
|
|
2
|
+
module Core
|
|
3
|
+
class TaskInspectionChecklist < ApplicationRecord
|
|
4
|
+
NOT_INSPECTED = 'Not Inspected'.freeze
|
|
5
|
+
IN_PROGRESS = 'In Progress'.freeze
|
|
6
|
+
PASS = 'Pass'.freeze
|
|
7
|
+
FAIL = 'Fail'.freeze
|
|
8
|
+
|
|
9
|
+
INSPECTION_STATUSES = [NOT_INSPECTED, IN_PROGRESS, PASS, FAIL].freeze
|
|
10
|
+
|
|
11
|
+
belongs_to :inspected_by, class_name: 'Ecom::Core::User'
|
|
12
|
+
belongs_to :task
|
|
13
|
+
|
|
14
|
+
validates :name, :status, presence: true
|
|
15
|
+
validates :status, inclusion: INSPECTION_STATUSES
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -1,57 +1,30 @@
|
|
|
1
|
-
require 'json-schema'
|
|
2
1
|
module Ecom
|
|
3
2
|
module Core
|
|
4
3
|
class TaskTemplate < ApplicationRecord
|
|
5
|
-
TASK_STEP_SCHEMA = {
|
|
6
|
-
'type' => 'object',
|
|
7
|
-
'required' => %w[name total_contribution_percentage_to_task],
|
|
8
|
-
'additionalProperties' => false,
|
|
9
|
-
'properties' => {
|
|
10
|
-
'name' => { 'type' => 'string' },
|
|
11
|
-
'total_contribution_percentage_to_task' => {
|
|
12
|
-
'type' => 'integer',
|
|
13
|
-
'minimum' => 1,
|
|
14
|
-
'maximum' => 100
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
}.freeze
|
|
18
|
-
|
|
19
|
-
# here the json schema has a bug ( including all properties as required)
|
|
20
|
-
# and because task_step_name is required on a condition ( only if the
|
|
21
|
-
# milestone is after a task step ), we can solve this with a workaround
|
|
22
|
-
# by specifying task_step_name in patternProperties.
|
|
23
|
-
MILESTONE_SCHEMA = {
|
|
24
|
-
'type' => 'object',
|
|
25
|
-
'required' => %w[name is_after_task_step],
|
|
26
|
-
'additionalProperties' => false,
|
|
27
|
-
'properties' => {
|
|
28
|
-
'name' => { 'type' => 'string' },
|
|
29
|
-
'is_after_task_step' => {
|
|
30
|
-
'type' => 'boolean'
|
|
31
|
-
}
|
|
32
|
-
},
|
|
33
|
-
"patternProperties": {
|
|
34
|
-
"task_step_name": {
|
|
35
|
-
'type' => 'string'
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
}.freeze
|
|
39
|
-
|
|
40
4
|
has_ancestry
|
|
41
5
|
|
|
42
6
|
belongs_to :task_template_type
|
|
43
|
-
|
|
7
|
+
belongs_to :unit_of_measure
|
|
8
|
+
|
|
9
|
+
has_many :task_template_inspection_checklists
|
|
10
|
+
has_many :inspection_checklists, through: :task_template_inspection_checklists
|
|
11
|
+
has_many :project_work_item_templates
|
|
12
|
+
has_many :work_product_templates, through: :project_work_item_templates
|
|
44
13
|
has_and_belongs_to_many :resource_types, join_table: 'ecom_core_task_templates_resource_types'
|
|
45
|
-
belongs_to :takeoff_calculator, optional: true
|
|
46
14
|
|
|
47
|
-
validates :name, :code, presence: true
|
|
15
|
+
validates :name, :code, :takeoff_fields, :task_completion_detail, presence: true
|
|
48
16
|
validates :code, uniqueness: true
|
|
17
|
+
validates :percentage_contribution,
|
|
18
|
+
numericality: {
|
|
19
|
+
greater_than_or_equal_to: 0,
|
|
20
|
+
less_than_or_equal_to: 100,
|
|
21
|
+
only_integer: true
|
|
22
|
+
},
|
|
23
|
+
allow_nil: true
|
|
24
|
+
|
|
49
25
|
delegate(:name, to: :task_template_type, prefix: true)
|
|
50
26
|
|
|
51
|
-
validate :
|
|
52
|
-
validate :milestones_schema_validator
|
|
53
|
-
validate :validate_sum_of_task_step_contribution
|
|
54
|
-
validate :validate_milestone_task_step_association
|
|
27
|
+
validate :percentage_contribution_sum_validator
|
|
55
28
|
|
|
56
29
|
def full_name
|
|
57
30
|
parent_name = parent&.name
|
|
@@ -72,54 +45,11 @@ module Ecom
|
|
|
72
45
|
resource_types.where(type: 'Ecom::Core::EquipmentType')
|
|
73
46
|
end
|
|
74
47
|
|
|
75
|
-
def
|
|
76
|
-
return if
|
|
77
|
-
|
|
78
|
-
validation_errors = JSON::Validator.fully_validate(TASK_STEP_SCHEMA,
|
|
79
|
-
task_steps, strict: true,
|
|
80
|
-
list: true, clear_cache: true)
|
|
81
|
-
|
|
82
|
-
errors.add(:task_steps, validation_errors) unless validation_errors.empty?
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
def milestones_schema_validator
|
|
86
|
-
return if milestones.nil?
|
|
87
|
-
|
|
88
|
-
validation_errors = JSON::Validator.fully_validate(MILESTONE_SCHEMA,
|
|
89
|
-
milestones, strict: true,
|
|
90
|
-
list: true, clear_cache: true)
|
|
91
|
-
|
|
92
|
-
errors.add(:milestones, validation_errors) unless validation_errors.empty?
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
def validate_sum_of_task_step_contribution
|
|
96
|
-
return if task_steps.nil?
|
|
97
|
-
|
|
98
|
-
filtered_task_steps = task_steps.select { |task_step| task_step['total_contribution_percentage_to_task'] }
|
|
99
|
-
|
|
100
|
-
sum_of_task_step_contribution =
|
|
101
|
-
filtered_task_steps.sum { |task_step| task_step['total_contribution_percentage_to_task'] }
|
|
102
|
-
|
|
103
|
-
errors.add(:task_steps, 'Sum of task step contributions has to be 100') if sum_of_task_step_contribution != 100
|
|
104
|
-
end
|
|
105
|
-
|
|
106
|
-
def validate_milestone_task_step_association
|
|
107
|
-
return if milestones.nil?
|
|
108
|
-
|
|
109
|
-
task_step_names = task_steps&.map { |task_step| task_step['name'] }
|
|
110
|
-
|
|
111
|
-
milestones_associated_with_task_step = milestones.select { |milestone| milestone['is_after_task_step'] }
|
|
112
|
-
|
|
113
|
-
milestones_associated_with_task_step.each do |milestone|
|
|
114
|
-
if milestone['task_step_name'].nil?
|
|
115
|
-
errors.add(:milestones, 'if the milestone is after a task step, please specify the task step name')
|
|
116
|
-
next
|
|
117
|
-
end
|
|
48
|
+
def percentage_contribution_sum_validator
|
|
49
|
+
return if percentage_contribution.nil?
|
|
118
50
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
end
|
|
122
|
-
end
|
|
51
|
+
sum = siblings.sum(:percentage_contribution)
|
|
52
|
+
errors.add(:task, 'Sum of percentage contributions has to be 100') if sum > 100
|
|
123
53
|
end
|
|
124
54
|
end
|
|
125
55
|
end
|