Index: trunk/grails-app/controllers/AssignedPersonDetailedController.groovy
===================================================================
--- trunk/grails-app/controllers/AssignedPersonDetailedController.groovy	(revision 181)
+++ trunk/grails-app/controllers/AssignedPersonDetailedController.groovy	(revision 182)
@@ -85,5 +85,5 @@
         if(!params.task?.id) {
             flash.message = "Please select a task and then 'Add Assigned Person'"
-            redirect(controller: "taskDetailed", action: list)
+            redirect(controller: "taskDetailed", action: search)
         }
         else {
Index: trunk/grails-app/controllers/PictureDetailedController.groovy
===================================================================
--- trunk/grails-app/controllers/PictureDetailedController.groovy	(revision 182)
+++ trunk/grails-app/controllers/PictureDetailedController.groovy	(revision 182)
@@ -0,0 +1,214 @@
+import org.codehaus.groovy.grails.plugins.springsecurity.Secured
+
+class PictureDetailedController extends BaseController {
+
+    def index = { redirect(action:list, params:params) }
+
+    // the delete, save and update actions only accept POST requests
+    static allowedMethods = [delete:'POST', save:'POST', update:'POST']
+
+    def list = {
+        prepareList()
+        [ list: Picture.list(params), paginateCount: Picture.count() ]
+    }
+
+    void prepareList() {
+        if (!params.max) {
+            params.max = 10
+        }
+        if (!params.order) {
+            params.order = "desc"
+        }
+        if (!params.sort) {
+            params.sort = "id"
+        }
+    }
+
+    def show = {
+        // In the case of an actionSubmit button, rewrite action name from 'index'.
+        if(params._action_Show)
+        { params.action='show' }
+
+        def picture = Picture.get( params.id )
+
+        if(!picture) {
+            flash.message = "Picture not found."
+            redirect(action:list)
+        }
+        else { [ picture : picture ] }
+    }
+
+    def delete = {
+        def picture = Picture.get(params.id)
+        def inventoryItem = InventoryItem.get(picture?.inventoryItem?.id)
+
+        if (inventoryItem && picture) {
+            Picture.withTransaction { status ->
+                inventoryItem.picture = null
+                inventoryItem.save()
+                picture.delete()
+            }
+            flash.message = "Picture ${params.id} deleted"
+            redirect(controller: "inventoryItemDetailed", action: show, id: inventoryItem.id)
+
+        }
+        else {
+            if(picture) {
+                flash.message = "Removing orphan picture ${picture.id}."
+                picture.delete(flush:true)
+                redirect(action: list)
+            }
+            else {
+                flash.message = "Picture not found"
+                redirect(action: list)
+            }
+        }
+    }
+
+    def edit = {
+        // In the case of an actionSubmit button, rewrite action name from 'index'.
+        if(params._action_Edit)
+        { params.action='edit' }
+
+        def picture = Picture.get(params.id)
+        if (!picture) {
+            flash.message = "Picture not found"
+            redirect(action: list)
+        }
+        else {
+            [ picture : picture ]
+        }
+    }
+
+    def update = {
+        def picture = Picture.get(params.id)
+        def inventoryItem = picture?.inventoryItem
+        if (inventoryItem && picture) {
+
+            if(params.version) {
+                def version = params.version.toLong()
+                if(picture.version > version) {
+                    picture.errors.rejectValue("version", "picture.optimistic.locking.failure", "Another user has updated this Picture while you were editing.")
+                    render(view:'edit',model:[picture:picture])
+                    return
+                }
+            }
+
+            picture.properties = params
+            if (!picture.hasErrors()) {
+                def imaging = new Imaging()
+                def images = imaging.updateAll(picture)
+                boolean result = false
+                Picture.withTransaction{ status ->
+                    result = picture.save()
+                }
+                if (result) {
+                    flash.message = "Picture ${params.id} updated"
+                    redirect(action: show, id: picture.id)
+                }
+                else {
+                    render(view: 'edit', model: [ picture: picture ])
+                }
+            }
+            else {
+                render(view: 'edit', model: [ picture: picture ])
+            }
+        }
+        else {
+            flash.message = "Picture not updated, picture or inventory item not found."
+            redirect(action: list)
+        }
+    }
+
+    def create = {
+        if(!params.inventoryItem?.id) {
+            flash.message = "Please select an inventory item and then 'Add Picture'."
+            redirect(controller: "inventoryItemDetailed", action: 'search')
+            return
+        }
+        def picture = new Picture()
+        picture.properties = params
+        [ picture: picture ]
+    }
+
+    def save = {
+        def inventoryItem = InventoryItem.get(params.inventoryItem.id)
+        if (inventoryItem) {
+            if(inventoryItem.picture) {
+                flash.message = "Inventory item already has a picture, please delete the old picture first."
+                redirect(controller: 'inventoryItemDetailed', action: 'show', id: inventoryItem.id)
+                return
+            }
+            def picture = new Picture(params)
+            def multiPartFile = request.getFile('file')
+            def imaging = new Imaging()
+            def images = null
+            if (multiPartFile && !multiPartFile.isEmpty()) {
+                if (multiPartFile.getSize() > Image.MAX_SIZE) {
+                    picture.errors.rejectValue('file', 'picture.file.maxSize.exceeded',
+                        [ 'file', 'Picture', Image.MAX_SIZE ] as Object[],
+                        'Property [{0}] of class [{1}] image file is too big (maximum [{2}] bytes)')
+                }
+                else {
+                    try {
+                        images = imaging.createAll(inventoryItem, picture, multiPartFile.inputStream)
+                    }
+                    catch(Exception ex) {
+                        log.error("picture save", ex)
+                        picture.errors.rejectValue('file', 'picture.file.unrecognised',
+                            [ 'file', 'Picture', multiPartFile.originalFilename ] as Object[],
+                            'Property [{0}] of class [{1}] image file [{2}]: type not recognised')
+                    }
+                }
+            }
+            else {
+                picture.errors.rejectValue('file', 'picture.file.missing',
+                    ['file', 'Picture', ''] as Object[],
+                    'Property [{0}] of class [{1}] no file specified')
+            }
+            if (images && !picture.hasErrors()) {
+                boolean result = false
+                Picture.withTransaction { status ->
+                    images.each { image ->
+                        picture.addToImages(image)
+                    }
+                    result = picture.save()
+                    inventoryItem.picture = picture
+                    inventoryItem.save()
+                }
+                if (result) {
+                    flash.message = "Picture ${picture.id} created"
+                    redirect(controller: 'inventoryItemDetailed', action: 'show', id: inventoryItem.id)
+                }
+                else {
+                    render(view: 'create', model: [ picture: picture ])
+                }
+            }
+            else {
+                render(view: 'create', model: [ picture: picture ])
+            }
+        }
+        else {
+            flash.message = "Picture not created, inventory item not found."
+            redirect(action: list)
+        }
+    }
+
+    def view = {
+        def picture = Picture.get(params.id)
+        def size = params.size ? Integer.parseInt(params.size) : Image.Small
+        def image = picture ? Image.findByPictureAndSize(picture, size) : null
+        if (picture && image) {
+            response.setContentType(image.contentType)
+            response.setContentLength(image.data.size())
+            response.setHeader('filename', image.filename())
+            OutputStream out = response.outputStream
+            out.write(image.data)
+            out.close()
+        }
+        else {
+            response.sendError(404)
+        }
+    }
+
+}
