@@ -2,7 +2,7 @@ package au.org.ala.merit
2
2
3
3
import au.com.bytecode.opencsv.CSVWriter
4
4
import org.apache.commons.lang.WordUtils
5
- import org.apache.commons.validator.EmailValidator
5
+ import org.apache.commons.validator.routines. EmailValidator
6
6
7
7
import java.text.DecimalFormat
8
8
import java.text.SimpleDateFormat
@@ -95,6 +95,7 @@ class GmsMapper {
95
95
96
96
def geographicInfoMapping = [
97
97
NATIONWIDE :[name :' nationwide' , type :' boolean' , description :' If true, this project does not have a primary state' ],
98
+ STATEWIDE :[name :' statewide' , type :' boolean' , description :' If true, this project does not have a primary electorate' ],
98
99
PRIMARY_STATE :[name :' primaryState' , type :' string' , description :' The primary state to be manually assigned to this project' ],
99
100
PRIMARY_ELECTORATE :[name :' primaryElectorate' , type :' string' , description :' The primary electorate to be manually assigned to this project' ],
100
101
OTHER_ELECTORATES :[name :' otherElectorates' , type :' list' , description :' Other electorates to be manually assigned to this project. Enter as a comma separated list' ],
@@ -135,6 +136,8 @@ class GmsMapper {
135
136
]
136
137
137
138
private boolean includeProgress
139
+ /* * If the mapping is being done to update a project, mandatory fields aren't required as they won't be updated if absent */
140
+ private boolean mapForUpdate = false
138
141
139
142
public GmsMapper () {
140
143
this . activitiesModel = []
@@ -144,9 +147,10 @@ class GmsMapper {
144
147
this . programs = [:]
145
148
this . managementUnits = [:]
146
149
includeProgress = false
150
+ mapForUpdate = false
147
151
}
148
152
149
- GmsMapper (activitiesModel , programModel , organisations , abnLookup , List<Map > scores , Map programs = [:], Map managementUnits = [:], includeProgress = false ) {
153
+ GmsMapper (activitiesModel , programModel , organisations , abnLookup , List<Map > scores , Map programs = [:], Map managementUnits = [:], includeProgress = false , mapForUpdate = false ) {
150
154
this . activitiesModel = activitiesModel
151
155
this . programModel = programModel
152
156
this . includeProgress = includeProgress
@@ -155,6 +159,7 @@ class GmsMapper {
155
159
this . programs = programs
156
160
this . managementUnits = managementUnits
157
161
this . abnLookupService = abnLookup
162
+ this . mapForUpdate = mapForUpdate
158
163
}
159
164
160
165
/* * Creates a CSV file in the format required to import projects into MERIT with additional instructions */
@@ -222,29 +227,21 @@ class GmsMapper {
222
227
return errors
223
228
}
224
229
225
- def mapProject (projectRows ) {
230
+ def mapProject (projectRows , boolean update = false ) {
226
231
227
232
List errors = []
228
233
List messages = []
229
- Map result = gmsToMerit (projectRows[0 ], projectMapping) // All project rows have the project details.
234
+ Map result = csvToProjectProperties (projectRows[0 ], projectMapping, update ) // All project rows have the project details.
230
235
def project = result. mappedData
231
- project. projectType = ' works'
232
- project. isMERIT = true
236
+ if (! update) {
237
+ // Set some default project properties for the MERIT hub
238
+ project. projectType = ' works'
239
+ project. isMERIT = true
240
+ }
233
241
234
- mapGeographicInfo(projectRows[0 ], project, errors)
242
+ mapGeographicInfo(projectRows[0 ], project, update, errors)
235
243
236
-
237
- String programName = project. associatedSubProgram ?: project. associatedProgram
238
- Map program = programs[programName]
239
- String programId = program?. programId
240
- if (programId) {
241
- project. remove(' associatedProgram' )
242
- project. remove(' associatedSubProgram' )
243
- project. programId = programId
244
- }
245
- else {
246
- errors << " Program ${ programName} doesn't match an existing MERIT programme"
247
- }
244
+ mapProgram(project, update, errors)
248
245
249
246
if (project. managementUnitName) {
250
247
String managementUnitName = project. remove(' managementUnitName' )
@@ -254,10 +251,9 @@ class GmsMapper {
254
251
}
255
252
}
256
253
257
- Map organisation = mapOrganisation(project, program , errors, messages)
254
+ Map organisation = mapOrganisation(project, update , errors, messages)
258
255
259
256
errors. addAll(result. errors)
260
- project. planStatus = project. planStatus ?: ' not approved'
261
257
262
258
mapRisks(projectRows, project, errors)
263
259
@@ -270,18 +266,44 @@ class GmsMapper {
270
266
project. custom = [details :meriPlan]
271
267
}
272
268
269
+ if (update) {
270
+ Set propertiesToUpdate = new HashSet (project. keySet())
271
+ propertiesToUpdate. remove(' grantId' ) // This identifies the project and won't be updated.
272
+ messages << " Update: ${ propertiesToUpdate} "
273
+ }
274
+
273
275
[project :project, sites :sites, activities :activities, errors :errors, messages :messages, organisation :organisation]
274
276
275
277
}
276
278
279
+ private Map mapProgram (LinkedHashMap<Object , Object > project , boolean update , ArrayList errors ) {
280
+ String programName = project. associatedSubProgram ?: project. associatedProgram
281
+ if (! programName) {
282
+ if (! update) {
283
+ errors << " Please supply a program name (PROGRAM_NM) or sub-program name (ROUND_NM) for the project"
284
+ }
285
+ return
286
+ }
287
+ Map program = programs[programName]
288
+ String programId = program?. programId
289
+ if (programId) {
290
+ project. remove(' associatedProgram' )
291
+ project. remove(' associatedSubProgram' )
292
+ project. programId = programId
293
+ } else {
294
+ errors << " Program ${ programName} doesn't match an existing MERIT programme"
295
+ }
296
+ program
297
+ }
298
+
277
299
private Map findExistingOrganisation (String organisationId , String abn ) {
278
300
organisations. find{
279
301
(abn && (it. abn == abn)) ||
280
302
(organisationId && (it. organisationId == organisationId)) }
281
303
282
304
}
283
305
284
- private Map mapOrganisation (Map project , Map program , List errors , List messages ) {
306
+ private Map mapOrganisation (Map project , boolean update , List errors , List messages ) {
285
307
Map organisation
286
308
Map abnLookup
287
309
String error = null
@@ -339,7 +361,7 @@ class GmsMapper {
339
361
project. associatedOrgs = [
340
362
[organisationId :organisation. organisationId, name : contractName ?: organisation. name, description :description]]
341
363
}
342
- } else {
364
+ } else if ( ! update) {
343
365
error = " Please supply an organisationId (ORG_ID) or ABN (ABN) for the project"
344
366
}
345
367
if (error) {
@@ -395,7 +417,7 @@ class GmsMapper {
395
417
def count = siteRows. size()
396
418
siteRows. eachWithIndex {siteRow , i ->
397
419
398
- def siteResult = gmsToMerit (siteRow, siteMapping)
420
+ def siteResult = csvToProjectProperties (siteRow, siteMapping)
399
421
def site = siteResult. mappedData
400
422
errors. addAll(siteResult. errors)
401
423
@@ -432,7 +454,7 @@ class GmsMapper {
432
454
def activityRows = projectRows. findAll{it[DATA_TYPE_COLUMN ] == ACTIVITY_DATA_TYPE && it[DATA_SUB_TYPE_COLUMN ] == ACTIVITY_DATA_SUB_TYPE }
433
455
def activities = []
434
456
activityRows. eachWithIndex { activityRow , i ->
435
- def activityResult = gmsToMerit (activityRow, activityMapping)
457
+ def activityResult = csvToProjectProperties (activityRow, activityMapping)
436
458
def mappedActivity = activityResult. mappedData
437
459
errors. addAll(activityResult. errors)
438
460
@@ -526,7 +548,7 @@ class GmsMapper {
526
548
def risks = []
527
549
riskRows. eachWithIndex { riskRow , i ->
528
550
529
- def result = gmsToMerit (riskRow, riskMapping)
551
+ def result = csvToProjectProperties (riskRow, riskMapping)
530
552
errors. addAll(result. errors)
531
553
def risk = [
532
554
" threat" : " " ,
@@ -546,19 +568,19 @@ class GmsMapper {
546
568
}
547
569
}
548
570
549
- private void mapGeographicInfo (Map rowData , Map project , List errors ) {
571
+ private void mapGeographicInfo (Map rowData , Map project , boolean update , List errors ) {
550
572
551
- Map result = gmsToMerit (rowData, geographicInfoMapping)
573
+ Map result = csvToProjectProperties (rowData, geographicInfoMapping, update )
552
574
if (result. mappedData) {
553
575
project. geographicInfo = result. mappedData
554
576
}
555
- errors. addAll(errors)
577
+ errors. addAll(result . errors)
556
578
}
557
579
558
580
private def mapTarget (rowMap ) {
559
581
560
582
def errors = []
561
- def map = gmsToMerit (rowMap, outputTargetColumnMapping)
583
+ def map = csvToProjectProperties (rowMap, outputTargetColumnMapping)
562
584
def target = map. mappedData
563
585
errors. addAll(map. errors)
564
586
@@ -594,7 +616,7 @@ class GmsMapper {
594
616
[mappedData :result, errors : errors]
595
617
}
596
618
597
- private def gmsToMerit (Map rowMap , Map mapping ) {
619
+ private def csvToProjectProperties (Map rowMap , Map mapping , boolean update = false ) {
598
620
def result = [:]
599
621
def errors = []
600
622
mapping. each { Map.Entry e ->
@@ -605,16 +627,20 @@ class GmsMapper {
605
627
String propertyName = columnMapping. name
606
628
if (columnMapping. multipleColumnsSupported) {
607
629
List values = findMultiValue(mappingColumnName, rowMap)
608
- if (! result[propertyName]) {
630
+ if (! result[propertyName] && ! update ) {
609
631
result[propertyName] = []
610
632
}
611
633
values = values. findAll{it}
612
- result[propertyName]. addAll(values. collect{convertByType(it, columnMapping)}. findAll{it})
634
+ if (values || ! update) {
635
+ result[propertyName]. addAll(values. collect{convertByType(it, columnMapping, update)}. findAll{it})
636
+ }
613
637
}
614
638
else {
615
- result[propertyName] = convertByType(rowMap[mappingColumnName], columnMapping)
639
+ def value = rowMap[mappingColumnName]?. trim()
640
+ if (value || ! update) { // If we are doing an update, ignore empty values.
641
+ result[propertyName] = convertByType(rowMap[mappingColumnName], columnMapping, update)
642
+ }
616
643
}
617
-
618
644
}
619
645
catch (Exception ex) {
620
646
errors << " Error converting value: ${ rowMap[mappingColumnName]} from row ${ rowMap.index} column: ${ mappingColumnName} , ${ ex.getMessage()} "
@@ -627,22 +653,25 @@ class GmsMapper {
627
653
private List findMultiValue (String mappingColumnName , Map rowMap ) {
628
654
rowMap. findAll { String key , def value ->
629
655
key. startsWith(mappingColumnName)
630
- }. collect{it. value}
656
+ }. collect{it. value?. trim() }
631
657
}
632
658
633
- private def convertByType (String value , Map mapping ) {
659
+ private def convertByType (String value , Map mapping , boolean update ) {
634
660
String type = mapping. type
635
661
value = value? value. trim(): ' '
636
662
def result = null
637
663
switch (type) {
638
664
case ' date' :
639
- result = convertDate(value, mapping. mandatory)
665
+ result = convertDate(value, mapping. mandatory && ! update )
640
666
break
641
667
case ' decimal' :
642
668
result = convertDecimal(value)
643
669
break
644
670
case ' string' :
645
- result = value ?: (mapping[' default' ]?: value)
671
+ result = value
672
+ if (! result && ! update) {
673
+ result = mapping[' default' ]?: value
674
+ }
646
675
break
647
676
case ' url' :
648
677
URI . create(value) // validation purposes only
@@ -669,6 +698,9 @@ class GmsMapper {
669
698
case ' list' :
670
699
result = value?. split(' ,' ). collect{it. trim()}. findAll{it}
671
700
break
701
+ case ' boolean' :
702
+ result = value?. toBoolean() // accept "y"/"true"/"1" as true
703
+ break
672
704
default :
673
705
throw new IllegalArgumentException (" Unsupported type: ${ type} " )
674
706
}
0 commit comments