-
Notifications
You must be signed in to change notification settings - Fork 154
/
campaign.rb
150 lines (128 loc) · 5.15 KB
/
campaign.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# frozen_string_literal: true
# = Informations
#
# == License
#
# Ekylibre - Simple agricultural ERP
# Copyright (C) 2008-2009 Brice Texier, Thibaud Merigon
# Copyright (C) 2010-2012 Brice Texier
# Copyright (C) 2012-2014 Brice Texier, David Joulin
# Copyright (C) 2015-2023 Ekylibre SAS
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see http://www.gnu.org/licenses.
#
# == Table: campaigns
#
# closed :boolean default(FALSE), not null
# closed_at :datetime
# created_at :datetime not null
# creator_id :integer(4)
# description :text
# harvest_year :integer(4)
# id :integer(4) not null, primary key
# lock_version :integer(4) default(0), not null
# name :string not null
# updated_at :datetime not null
# updater_id :integer(4)
#
class Campaign < ApplicationRecord
has_many :cap_statements, dependent: :restrict_with_exception
has_many :activity_budgets, inverse_of: :campaign, dependent: :restrict_with_exception
has_one :selected_manure_management_plan, -> { selecteds }, class_name: 'ManureManagementPlan', foreign_key: :campaign_id, inverse_of: :campaign
has_many :tactics, class_name: 'ActivityTactic', inverse_of: :campaign
# [VALIDATORS[ Do not edit these lines directly. Use `rake clean:validations`.
validates :closed, inclusion: { in: [true, false] }
validates :closed_at, timeliness: { on_or_after: -> { Time.new(1, 1, 1).in_time_zone }, on_or_before: -> { Time.zone.now + 100.years } }, allow_blank: true
validates :description, length: { maximum: 500_000 }, allow_blank: true
validates :harvest_year, numericality: { only_integer: true, greater_than: -2_147_483_649, less_than: 2_147_483_648 }, allow_blank: true
validates :name, presence: true, length: { maximum: 500 }
# ]VALIDATORS]
validates :harvest_year, length: { is: 4 }, allow_nil: true
validates :harvest_year, uniqueness: true
has_and_belongs_to_many :activities
has_and_belongs_to_many :interventions
has_and_belongs_to_many :activity_productions
has_many :cvi_statements
scope :current, -> { where(closed: false).reorder(:harvest_year) }
scope :at, ->(searched_at = Time.zone.now) {
ActiveSupport::Deprecation.warn "Campaign#at is deprecated, use Campaign#on instead"
where(harvest_year: searched_at.year)
}
scope :with_interventions, -> { where(id: HABTM_Interventions.select(:campaign_id)) }
scope :with_activity, -> { where('id IN (SELECT DISTINCT campaign_id from activities_campaigns)') }
scope :with_plant_farming_interventions, -> { where(id: HABTM_Interventions.where(intervention_id: Intervention.of_activity_family(:plant_farming)).select(:campaign_id)) }
scope :on, ->(searched_on) { find_by(harvest_year: searched_on.year) }
scope :of_activity_production, lambda { |activity_production|
where('id IN (SELECT campaign_id FROM activity_productions_campaigns WHERE activity_production_id = ?)', activity_production.id)
}
scope :of_production, ->(production) { of_activity_production(production) }
protect(on: :destroy) do
interventions.any?
end
before_validation do
self.name = harvest_year.to_s
end
class << self
def of(year)
raise 'Invalid year: ' + year.inspect unless year.to_s =~ /\A\d+\z/
find_or_create_by!(harvest_year: year)
end
def first_of_all
Campaign.reorder(:harvest_year, :id).first
end
end
# Returns all CampaignProduction. These productions always last the campaign
# duration
def productions
CampaignProduction.of(self)
end
# Returns the cost of production for the given campaign. It's the sum of all
# "campaign production" production cost
def productions_cost_amount
productions.map(:cost_amount).sum
end
# FIXME: Not generic. Some activities have no shape
def net_surface_area
activity_productions.map(&:support_shape_area).sum
end
alias shape_area net_surface_area
def previous
self.class.where('harvest_year < ?', harvest_year)
end
# Return the previous campaign
def preceding
self.class.where('harvest_year < ?', harvest_year).order(harvest_year: :desc).first
end
def followings
self.class.where('harvest_year > ?', harvest_year).order(:harvest_year)
end
def current_and_followings
self.class.where('harvest_year >= ?', harvest_year).order(:harvest_year)
end
# Return the following campaign
def following
followings.first
end
def opened?
!closed
end
def close
update_column(closed: true)
Ekylibre::Hook.publish(:campaign_closing, campaign_id: id)
end
def reopen
update_column(closed: false)
Ekylibre::Hook.publish(:campaign_reopening, campaign_id: id)
end
end