@@ -12,13 +12,15 @@ class Event::Tour::ReportForm
1212 EDITABLE_PARTICIPATION_STATES = %w[ assigned attended absent ] . freeze
1313
1414 attr_reader :report
15+ attr_writer :participations_attributes
1516
1617 delegate :event , to : :report
1718
1819 attribute :review , :string
1920 attribute :remarks , :string
2021
2122 validate :assert_participation_states_editable
23+ validate :assert_cost_records_valid
2224
2325 def initialize ( report , attrs = { } )
2426 @report = report
@@ -28,15 +30,15 @@ def initialize(report, attrs = {})
2830 def save
2931 return false unless valid?
3032
31- report . update ( review :, remarks :) && save_participations
33+ ActiveRecord ::Base . transaction do
34+ report . update! ( review :, remarks :) && save_participations && save_cost_records
35+ end
3236 end
3337
3438 def tour_completed?
3539 [ :ready , :closed ] . include? ( event . state . to_sym )
3640 end
3741
38- attr_writer :participations_attributes
39-
4042 def participations
4143 @participations ||= event
4244 . participations
@@ -45,6 +47,18 @@ def participations
4547 . order_by_role ( event )
4648 end
4749
50+ def revenues
51+ @revenues ||= report . costs . where ( income : true ) . to_a
52+ end
53+
54+ def expenditures
55+ @expenditures ||= report . costs . where ( income : false ) . to_a
56+ end
57+
58+ def receipts
59+ @receipts ||= report . cost_receipts . includes ( :file_attachment ) . to_a
60+ end
61+
4862 def editable_participation_state? ( participation )
4963 EDITABLE_PARTICIPATION_STATES . include? ( participation . state )
5064 end
@@ -56,6 +70,19 @@ def participation_state_labels(participation)
5670 . to_a
5771 end
5872
73+ def revenues_attributes = ( attrs )
74+ @revenues = build_records ( attrs , collection : report . costs , fixed_attributes : { income : true } )
75+ end
76+
77+ def expenditures_attributes = ( attrs )
78+ @expenditures = build_records ( attrs , collection : report . costs ,
79+ fixed_attributes : { income : false } )
80+ end
81+
82+ def receipts_attributes = ( attrs )
83+ @receipts = build_records ( attrs , collection : report . cost_receipts )
84+ end
85+
5986 private
6087
6188 def assert_participation_states_editable
@@ -70,6 +97,12 @@ def assert_participation_states_editable
7097 end
7198 end
7299
100+ def assert_cost_records_valid
101+ cost_records . flat_map { _1 . reject ( &:valid? ) } . each do |model |
102+ model . errors . full_messages . each { errors . add ( :base , _1 ) }
103+ end
104+ end
105+
73106 def save_participations
74107 return true unless @participations_attributes
75108
@@ -79,7 +112,34 @@ def save_participations
79112 end
80113 end
81114
115+ def save_cost_records
116+ cost_records . each do |collection |
117+ collection . each { _1 . marked_for_destruction? ? _1 . destroy! : _1 . save! }
118+ end
119+ end
120+
82121 def participation_by_id
83122 @participation_by_id ||= participations . index_by ( &:id )
84123 end
124+
125+ def cost_records
126+ [ @revenues , @expenditures , @receipts ] . compact
127+ end
128+
129+ def build_records ( attrs , collection :, fixed_attributes : { } )
130+ attrs . values . map do |values |
131+ record = if values [ :id ] . present?
132+ collection . index_by ( &:id ) . transform_keys ( &:to_s ) . fetch ( values [ :id ] . to_s )
133+ else
134+ collection . build
135+ end
136+
137+ if ActiveRecord ::Type ::Boolean . new . cast ( values [ :_destroy ] )
138+ record . mark_for_destruction
139+ else
140+ record . assign_attributes ( values . except ( :id , :_destroy ) . merge ( fixed_attributes ) )
141+ end
142+ record
143+ end
144+ end
85145end
0 commit comments