package com.lemans.ds.studioorder import com.lemans.ds.flag.Flag import com.lemans.ds.flag.FlagValue import com.lemans.services.LemansManager import grails.transaction.Transactional import groovy.text.Template import groovy.text.markup.MarkupTemplateEngine import groovy.text.markup.TemplateConfiguration import javax.mail.internet.InternetAddress import javax.mail.internet.MimeMessage import java.sql.Timestamp @SuppressWarnings(['CyclomaticComplexity']) @Transactional class StudioOrderPartManagerService extends LemansManager { def mailSender StudioOrderPartService studioOrderPartService static final String NO_REPLY_FROM = 'HelpDesk' private static final String STUDIO_ORDER_PART_INSERT_SQL = ''' INSERT INTO dbo.StudioOrderPart(studioOrderId, partNumber, statusId, dateCreated, createdBy, lastUpdated, lastUpdatedBy) VALUES(:studioOrderId, :partNumber, 14200, :now, :username, :now, :username) ''' private static final String STUDIO_ORDER_PART_UPDATE_SQL = ''' UPDATE dbo.StudioOrderPart SET statusId = :statusId, lastUpdatedBy = :user, lastUpdated = :now, version = version + 1 WHERE studioOrderPartId = :studioOrderPartId AND dateDeleted IS NULL ''' private static final String STUDIO_ORDER_PART_DELETE_SQL = ''' UPDATE dbo.StudioOrderPart SET dateDeleted = :now, deletedBy = :username , version = version + 1 WHERE studioOrderId = :studioOrderId AND partNumber = :partNumber AND dateDeleted IS NULL ''' private static final String FLAG_VALUE_INSERT_SQL = ''' INSERT INTO dbo.FlagValue(entityId, flagId, dateCreated, createdBy, lastUpdated, lastUpdatedBy) VALUES(:entityId, :flagId, :now, :username, :now, :username) ''' private static final String FLAG_VALUE_DELETE_SQL = ''' UPDATE dbo.FlagValue SET dateDeleted = :now, deletedBy = :username, version = version + 1 WHERE entityId = :entityId AND flagId = :flagId AND dateDeleted IS NULL ''' private static final String FLAG_VALUE_UPDATE_SQL = ''' UPDATE dbo.FlagValue SET flagId = :flagId, lastUpdated = :now, lastUpdatedBy = :username, version = version + 1 WHERE entityId = :entityId AND flagId = :reshoot AND dateDeleted IS NULL ''' Map performActions(Map values, String username) { if (!(values.action.toString() in ['create', 'update', 'delete'])) { return [messages: [[type: 'error', text: 'Invalid action']]] } switch (values.action) { case 'create': addParts(values, username) break case 'update': updateParts(values, username) break case 'delete': deleteParts(values, username) break } } Map addParts(Map values, String username) { Timestamp now = new Timestamp(new Date().time) List partNumbers = findStudioOrderParts(values.studioOrderId, values.parts)*.partNumber sql().withBatch(50, STUDIO_ORDER_PART_INSERT_SQL) { stmt -> values.parts.each { String partNumber -> if (!(partNumber in partNumbers)) { stmt.addBatch([studioOrderId: values.studioOrderId, partNumber: partNumber, now: now, username: username]) } } } [results: [:]] } Map updateParts(Map values, String username) { List studioOrderParts = findStudioOrderParts(values.studioOrderId, values.parts) if (studioOrderParts) { if (values.statusId == 14201 && (StudioOrder.findById(studioOrderParts*.studioOrderId[0])?.note == null)) { return [messages: [type: 'error', text: 'Note is required for order to be submitted.']] } updateStudioOrderParts(values, studioOrderParts*.id, username) updateFlagValues(values.statusId, studioOrderParts, username) if (values.statusId == 14201) { sendEmail(values.studioOrderId) } [results: [:]] } else { [messages: [[type: 'error', text: 'Order does not have parts.']]] } } Map deleteParts(Map values, String username) { Timestamp now = new Timestamp(new Date().time) List studioOrderParts = findStudioOrderParts(values.studioOrderId, values.parts) String status = sql().firstRow("SELECT status FROM vwStudioOrder WHERE studioOrderId = ${values.studioOrderId}")?.status if (status.equalsIgnoreCase('open')) { sql().withBatch(50, STUDIO_ORDER_PART_DELETE_SQL) { stmt -> values.parts.each { String partNumber -> if (partNumber in studioOrderParts*.partNumber) { stmt.addBatch([studioOrderId: values.studioOrderId, partNumber: partNumber, now: now, username: username]) } } } [results: [:]] } else { [messages: [[type: 'error', text: 'Parts can not deleted after submitted.']]] } } private void updateStudioOrderParts(Map values, List studioOrderPartIds, String username) { Timestamp now = new Timestamp(new Date().time) sql().withBatch(50, STUDIO_ORDER_PART_UPDATE_SQL) { stmt -> studioOrderPartIds.each { studioOrderPartId -> stmt.addBatch([statusId: values.statusId, user: username, now: now, studioOrderPartId: studioOrderPartId]) } } } private void updateFlagValues(Integer statusId, List studioOrderParts, String username) { Timestamp now = new Timestamp(new Date().time) Integer submittedFlagId = findFlag('Submitted')?.id Integer reshootFlagId = findFlag('reshoot')?.id Integer reviewReshootFlagId = findFlag('reviewReshoot')?.id List partNumbers = findFlagValues(studioOrderParts*.partNumber, submittedFlagId)*.entityId List partsWithReshoot = findFlagValues(studioOrderParts*.partNumber, reshootFlagId)*.entityId switch (statusId) { case 14201: sql().withBatch(50, FLAG_VALUE_INSERT_SQL) { stmt -> studioOrderParts*.partNumber.each { String partNumber -> if (!(partNumber in partNumbers)) { stmt.addBatch([entityId: partNumber, flagId: submittedFlagId, username: username, now: now]) } } } break case 14203: sql().withBatch(50, FLAG_VALUE_DELETE_SQL) { stmt -> studioOrderParts*.partNumber.each { String partNumber -> if (partNumber in partNumbers) { stmt.addBatch([entityId: partNumber, flagId: submittedFlagId, username: username, now: now]) } } } if (partsWithReshoot) { sql().withBatch(50, FLAG_VALUE_UPDATE_SQL) { stmt -> studioOrderParts*.partNumber.each { String partNumber -> if (partNumber in partsWithReshoot) { stmt.addBatch([entityId: partNumber, flagId: reviewReshootFlagId, username: username, now: now, reshoot: reshootFlagId]) } } } } break } } private List findStudioOrderParts(Integer studioOrderId, List partNumbers) { StudioOrderPart.findAllByStudioOrderIdAndPartNumberInListAndDateDeletedIsNull(studioOrderId, partNumbers) } private Flag findFlag(String flagName) { Flag.findByFlagNameAndDateDeletedIsNull(flagName) } private List findFlagValues(List partNumbers, Integer flagId) { FlagValue.findAllByEntityIdInListAndFlagIdAndDateDeletedIsNull(partNumbers, flagId) } private void sendEmail(Integer studioOrderId) { StudioOrder studioOrder = StudioOrder.findByIdAndDateDeletedIsNull(studioOrderId) if(studioOrder == null) { return } String studioOrderName = studioOrder?.studioOrderName String note = studioOrder.note Map body = [ parts: studioOrderPartService.findParts([studioOrderId: studioOrderId])?.results, to: recipients(), subject: "Studio Order: ${studioOrderName}", bodyTitle: studioOrderName, orderNote: note, otherInfo: otherWarehouse(studioOrderId) ] MimeMessage mimeMessage = createHtmlEmailMessage('studioOrderReport', body) mailSender.send(mimeMessage) } MimeMessage createHtmlEmailMessage(String viewName, Map body) { Writer writer = new StringWriter() String tmpl = getEmailTemplate(viewName) TemplateConfiguration config = new TemplateConfiguration() MarkupTemplateEngine engine = new MarkupTemplateEngine(config) Template template = engine.createTemplate(tmpl) Writable output = template.make(body) output.writeTo(writer) MimeMessage mimeMessage = mailSender.createMimeMessage() body.to.each { mimeMessage.addRecipient(MimeMessage.RecipientType.TO, new InternetAddress(it)) } mimeMessage.from = new InternetAddress(NO_REPLY_FROM) mimeMessage.subject = body.subject mimeMessage.setContent writer.toString(), 'text/html' mimeMessage } private String getEmailTemplate(String viewName) { this.class.classLoader.getResource("emails/${viewName}.tmpl").text } private List recipients() { sql().firstRow(""" SELECT recipientEmailAddress FROM vwEmailConfiguration WITH(NOLOCK) WHERE applicationName = 'Digital Services' AND functionality = 'Studio Order' """)?.recipientEmailAddress?.split(',') } private boolean otherWarehouse(Integer studioOrderId) { StudioOrder.findByIdAndDateDeletedIsNull(studioOrderId)?.otherWarehouse } }