@@ -89,53 +89,60 @@ def self.import_from_csv(file)
8989 errors = [ ]
9090 ignored = [ ]
9191 data = FileHelper . read_file_to_str ( file ) . gsub ( '\\n' , "\n " )
92- CSV . parse ( data ,
93- headers : true ,
94- header_converters : [ -> ( i ) { i . nil? ? '' : i } , :downcase , -> ( hdr ) { hdr . strip unless hdr . nil? } ] ,
95- converters : [ -> ( body ) { body . encode! ( 'UTF-8' , 'binary' , invalid : :replace , undef : :replace , replace : '' ) unless body . nil? } ] ) . each do |row |
96- missing = missing_headers ( row , csv_columns )
97- if missing . count > 0
98- errors << { row : row , message : "Missing headers: #{ missing . join ( ', ' ) } " }
99- next
100- end
10192
102- tutorial_code = row [ 'code' ] . strip unless row [ 'code' ] . nil?
103- abbreviation = row [ 'abbreviation' ] . strip unless row [ 'abbreviation' ] . nil?
104- unit_id = row [ 'unit_id' ] . strip unless row [ 'unit_id' ] . nil?
105- user_id = row [ 'tutor_id' ] . strip unless row [ 'tutor_id' ] . nil?
106- tutorial_stream_name = row [ 'tutorial_stream' ] . strip unless row [ 'tutorial_stream' ] . nil?
93+ ActiveRecord ::Base . transaction do
94+ CSV . parse ( data ,
95+ headers : true ,
96+ header_converters : [ -> ( i ) { i . nil? ? '' : i } , :downcase , -> ( hdr ) { hdr . strip unless hdr . nil? } ] ,
97+ converters : [ -> ( body ) { body . encode! ( 'UTF-8' , 'binary' , invalid : :replace , undef : :replace , replace : '' ) unless body . nil? } ] ) . each do |row |
98+ missing = missing_headers ( row , csv_columns )
99+ if missing . count > 0
100+ errors << { row : row , message : "Missing headers: #{ missing . join ( ', ' ) } " }
101+ raise StandardError , "Critical import error: missing headers"
102+ end
107103
108- # find unit role using tutor's user_id and unit_id
109- unit_role = UnitRole . find_by ( user_id : user_id , unit_id : unit_id )
104+ tutorial_code = row [ 'code' ] . strip unless row [ 'code' ] . nil?
105+ abbreviation = row [ 'abbreviation' ] . strip unless row [ 'abbreviation' ] . nil?
106+ unit_id = row [ 'unit_id' ] . strip unless row [ 'unit_id' ] . nil?
107+ user_id = row [ 'tutor_id' ] . strip unless row [ 'tutor_id' ] . nil?
108+ tutorial_stream_name = row [ 'tutorial_stream' ] . strip unless row [ 'tutorial_stream' ] . nil?
110109
111- if unit_role . nil?
112- errors << { row : row , message : "Tutor with user_id (#{ user_id } ) not found in unit roles" }
113- next
114- end
110+ # find unit role using tutor's user_id and unit_id
111+ unit_role = UnitRole . find_by ( user_id : user_id , unit_id : unit_id )
112+
113+ if unit_role . nil?
114+ errors << { row : row , message : "Tutor with user_id (#{ user_id } ) not found in unit roles" }
115+ raise StandardError , 'Critical import error: missing unit role'
116+ end
117+
118+ # if tutorial is found set it, otherwise leave it blank
119+ tutorial_stream = TutorialStream . find_by ( name : tutorial_stream_name ) if tutorial_stream_name . present?
115120
116- # if tutorial is found set it, otherwise leave it blank
117- tutorial_stream = TutorialStream . find_by ( name : tutorial_stream_name ) if tutorial_stream_name . present?
118-
119- # handle missing tutorial stream
120- tutorial_stream = nil if tutorial_stream_name . blank?
121-
122- # create a new tutorial
123- tutorial = Tutorial . new (
124- unit_id : unit_id ,
125- code : tutorial_code ,
126- abbreviation : abbreviation ,
127- unit_role_id : unit_role . id ,
128- tutorial_stream_id : tutorial_stream &.id
129- )
130-
131- if tutorial . save
132- success << { row : row , message : "Created tutorial #{ abbreviation } #{ unit_id } " }
133- else
134- errors << { row : row , message : "Failed to create tutorial #{ abbreviation } #{ unit_id } " }
121+ # handle missing tutorial stream
122+ tutorial_stream = nil if tutorial_stream_name . blank?
123+
124+ # create a new tutorial
125+ tutorial = Tutorial . new (
126+ unit_id : unit_id ,
127+ code : tutorial_code ,
128+ abbreviation : abbreviation ,
129+ unit_role_id : unit_role . id ,
130+ tutorial_stream_id : tutorial_stream &.id
131+ )
132+
133+ if tutorial . save
134+ success << { row : row , message : "Created tutorial #{ abbreviation } #{ unit_id } " }
135+ else
136+ errors << { row : row , message : "Failed to create tutorial #{ abbreviation } #{ unit_id } " }
137+ raise StandardError , 'Critical import error: failed to save tutorial'
138+ end
139+ rescue StandardError => e
140+ raise ActiveRecord ::Rollback
135141 end
136- rescue StandardError => e
137- errors << { row : row , message : e . message }
142+
143+ raise ActiveRecord :: Rollback unless errors . empty?
138144 end
145+
139146 {
140147 success : success ,
141148 ignored : ignored ,
0 commit comments