| @@ -0,0 +1,69 @@ | |||||
| package com.ffii.lioner.modules.lioner.pdf.entity; | |||||
| import java.time.LocalDate; | |||||
| import java.time.LocalDateTime; | |||||
| import com.ffii.core.entity.BaseEntity; | |||||
| import jakarta.persistence.Column; | |||||
| import jakarta.persistence.Entity; | |||||
| import jakarta.persistence.Inheritance; | |||||
| import jakarta.persistence.InheritanceType; | |||||
| import jakarta.persistence.Table; | |||||
| import jakarta.validation.constraints.NotBlank; | |||||
| import jakarta.validation.constraints.NotNull; | |||||
| @Entity | |||||
| @Table(name = "filled_form") | |||||
| @Inheritance(strategy=InheritanceType.TABLE_PER_CLASS) | |||||
| public class Pdf extends BaseEntity<Long>{ | |||||
| @NotNull | |||||
| @Column | |||||
| private Long templateId; | |||||
| @Column | |||||
| private Long clientId; | |||||
| @NotNull | |||||
| @Column | |||||
| private Long fileId; | |||||
| @Column | |||||
| private String remarks; | |||||
| public Long getTemplateId() { | |||||
| return templateId; | |||||
| } | |||||
| public void setTemplateId(Long templateId) { | |||||
| this.templateId = templateId; | |||||
| } | |||||
| public Long getClientId() { | |||||
| return clientId; | |||||
| } | |||||
| public void setClientId(Long clientId) { | |||||
| this.clientId = clientId; | |||||
| } | |||||
| public Long getFileId() { | |||||
| return fileId; | |||||
| } | |||||
| public void setFileId(Long fileId) { | |||||
| this.fileId = fileId; | |||||
| } | |||||
| public String getRemarks() { | |||||
| return remarks; | |||||
| } | |||||
| public void setRemarks(String remarks) { | |||||
| this.remarks = remarks; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,10 @@ | |||||
| package com.ffii.lioner.modules.lioner.pdf.entity; | |||||
| import java.util.List; | |||||
| // import java.util.Map; | |||||
| import com.ffii.core.support.AbstractRepository; | |||||
| public interface PdfRepository extends AbstractRepository<Pdf, Long> { | |||||
| List<Pdf> findAllByClientId(Long clientId); | |||||
| } | |||||
| @@ -0,0 +1,47 @@ | |||||
| package com.ffii.lioner.modules.lioner.pdf.req; | |||||
| public class UpdatePdfReq { | |||||
| private Long id; | |||||
| private Long templateId; | |||||
| private Long clientId; | |||||
| private String remarks; | |||||
| public Long getId() { | |||||
| return id; | |||||
| } | |||||
| public void setId(Long id) { | |||||
| this.id = id; | |||||
| } | |||||
| public Long getTemplateId() { | |||||
| return templateId; | |||||
| } | |||||
| public void setTemplateId(Long templateId) { | |||||
| this.templateId = templateId; | |||||
| } | |||||
| public Long getClientId() { | |||||
| return clientId; | |||||
| } | |||||
| public void setClientId(Long clientId) { | |||||
| this.clientId = clientId; | |||||
| } | |||||
| public String getRemarks() { | |||||
| return remarks; | |||||
| } | |||||
| public void setRemarks(String remarks) { | |||||
| this.remarks = remarks; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,237 @@ | |||||
| package com.ffii.lioner.modules.lioner.pdf.service; | |||||
| import java.io.IOException; | |||||
| import java.io.InputStream; | |||||
| import java.time.LocalDate; | |||||
| import java.util.ArrayList; | |||||
| import java.util.Arrays; | |||||
| import java.util.Date; | |||||
| import java.util.HashMap; | |||||
| import java.util.List; | |||||
| import java.util.Map; | |||||
| import java.util.stream.Collectors; | |||||
| import org.springframework.stereotype.Service; | |||||
| import org.springframework.web.multipart.MultipartFile; | |||||
| import org.springframework.core.io.ByteArrayResource; | |||||
| import org.springframework.core.io.ClassPathResource; | |||||
| import com.ffii.lioner.modules.lioner.pdf.entity.Pdf; | |||||
| import com.ffii.lioner.modules.lioner.pdf.entity.PdfRepository; | |||||
| import com.ffii.lioner.modules.lioner.entity.ImpEvent; | |||||
| import com.ffii.lioner.modules.lioner.pdf.req.UpdatePdfReq; | |||||
| import com.ffii.lioner.modules.lioner.service.FileService; | |||||
| import com.ffii.lioner.modules.common.SecurityUtils; | |||||
| import com.ffii.lioner.modules.common.service.AuditLogService; | |||||
| import com.ffii.lioner.modules.master.entity.SubDivision; | |||||
| import com.fasterxml.jackson.databind.ObjectMapper; | |||||
| import com.ffii.core.exception.NotFoundException; | |||||
| import com.ffii.core.exception.UnprocessableEntityException; | |||||
| import com.ffii.core.support.AbstractBaseEntityService; | |||||
| import com.ffii.core.support.JdbcDao; | |||||
| import com.ffii.core.utils.BeanUtils; | |||||
| import com.ffii.core.utils.JsonUtils; | |||||
| import com.ffii.core.utils.Params; | |||||
| import jakarta.persistence.Table; | |||||
| @Service | |||||
| public class PdfService extends AbstractBaseEntityService<Pdf, Long, PdfRepository> { | |||||
| private String pdf_path = "templates/pdf/"; | |||||
| private AuditLogService auditLogService; | |||||
| private FileService fileService; | |||||
| public PdfService(JdbcDao jdbcDao, PdfRepository repository, AuditLogService auditLogService, FileService fileService) { | |||||
| super(jdbcDao, repository); | |||||
| this.auditLogService = auditLogService; | |||||
| this.fileService = fileService; | |||||
| } | |||||
| // public Map<String,Object> getAuditLogObject(Map<String,Object> req){ | |||||
| // StringBuilder sql = new StringBuilder("SELECT" | |||||
| // + " e.id, " | |||||
| // + " e.created, " | |||||
| // + " e.createdBy AS createdById, " | |||||
| // + " u1.name AS createdBy, " | |||||
| // + " e.version, " | |||||
| // + " e.modified, " | |||||
| // + " e.modifiedBy AS modifiedById, " | |||||
| // + " e.deleted, " | |||||
| // + " u2.name AS modifiedBy, " | |||||
| // + " e.name, " | |||||
| // + " e.nameCht, " | |||||
| // + " e.description, " | |||||
| // + " e.region, " | |||||
| // + " e.organization, " | |||||
| // + " e.eventType, " | |||||
| // + " e.frequency, " | |||||
| // + " e.series, " | |||||
| // + " e.startDate, " | |||||
| // + " e.eventFrom, " | |||||
| // + " e.eventTo, " | |||||
| // + " e.applicationDeadline, " | |||||
| // + " e.nextApplicationDate, " | |||||
| // + " e.announcementDate, " | |||||
| // + " e.awardDate, " | |||||
| // + " e.reminderFlag, " | |||||
| // + " e.reminderThreshold, " | |||||
| // + " e.reminderInterval, " | |||||
| // + " e.reminderLimit " | |||||
| // + " FROM event e " | |||||
| // + " LEFT JOIN `user` u1 ON u1.id = e.createdBy " | |||||
| // + " LEFT JOIN `user` u2 ON u2.id = e.modifiedBy " | |||||
| // + " WHERE e.id = :id " | |||||
| // ); | |||||
| // return jdbcDao.queryForMap(sql.toString(), req).get(); | |||||
| // } | |||||
| public Map<String, Object> saveOrUpdate(String recordJson, MultipartFile file) { | |||||
| ObjectMapper objectMapper = new ObjectMapper(); | |||||
| UpdatePdfReq req; | |||||
| try { | |||||
| req = objectMapper.readValue(recordJson, UpdatePdfReq.class); | |||||
| } catch (Exception e) { | |||||
| throw new UnprocessableEntityException("Invalid JSON format"); | |||||
| } | |||||
| Pdf instance; | |||||
| // List<SubDivision> onUsingIdList = new ArrayList<SubDivision>(); | |||||
| if(req.getId()>0){ | |||||
| instance = find(req.getId()).get(); | |||||
| fileService.deleteFile(instance.getFileId()); // Delete previous record - WIP | |||||
| // onUsingIdList = this.getSelectedSubDivisionList(req.getId()); | |||||
| } | |||||
| else{ | |||||
| instance = new Pdf(); | |||||
| } | |||||
| System.out.println(req.getTemplateId()); | |||||
| BeanUtils.copyProperties(req, instance); | |||||
| Map<String, Object> pdf = new HashMap<>(); | |||||
| Map<String, Object> response = new HashMap<>(); | |||||
| if (file.isEmpty()) { | |||||
| throw new UnprocessableEntityException("No file uploaded."); | |||||
| // return ResponseEntity.badRequest().body(Map.of("message", "No file uploaded.")); | |||||
| } | |||||
| try { | |||||
| // Convert the MultipartFile to a byte array | |||||
| byte[] pdfData = file.getBytes(); | |||||
| MultipartFile[] files = new MultipartFile[1]; | |||||
| files[0] = file; | |||||
| try { | |||||
| pdf = fileService.saveOrUpdate(files, (long) 0, "pdf"); | |||||
| } catch (Exception e) { | |||||
| System.out.println(e); | |||||
| } | |||||
| // Save the PDF data to the database | |||||
| // File pdfForm = new PdfForm(); | |||||
| // pdfForm.setPdfData(pdfData); | |||||
| // pdfFormRepository.save(pdfForm); // Assuming you have autowired this repository | |||||
| response.put("message", "PDF saved successfully."); | |||||
| // response.put("id", pdfForm.getId().toString()); // Return the ID of the saved PDF | |||||
| } catch (IOException e) { | |||||
| throw new UnprocessableEntityException( | |||||
| "Failed to save PDF: " | |||||
| + e | |||||
| ); | |||||
| // e.printStackTrace(); | |||||
| // return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) | |||||
| // .body(Map.of("message", "Failed to save PDF: " + e.getMessage())); | |||||
| } | |||||
| Object fileIdList = pdf.get("fileIdList"); | |||||
| List<?> list = (List<?>) fileIdList; | |||||
| Long fileId = (long) list.get(0); | |||||
| instance.setFileId(fileId); | |||||
| instance = save(instance); | |||||
| response = Map.of( | |||||
| "id", instance.getId() | |||||
| ); | |||||
| return response; | |||||
| } | |||||
| public byte[] getTemplateForm() { | |||||
| // Ensure the template PDF is in src/main/resources/template/pdf | |||||
| ClassPathResource pdfFile = new ClassPathResource(pdf_path + "HSBC B24102883_fillable_Financial Needs Analysis for Individual Nov2024.pdf"); | |||||
| if (!pdfFile.exists()) { | |||||
| throw new UnprocessableEntityException("PDF template not found."); | |||||
| } | |||||
| try (InputStream is = pdfFile.getInputStream()) { | |||||
| return is.readAllBytes(); | |||||
| } catch (Exception e) { | |||||
| throw new UnprocessableEntityException("Fail to load PDF: " + e); | |||||
| } | |||||
| // return fileService.getfileBlob((long) 2); | |||||
| } | |||||
| public List<Map<String,Object>> list(Map<String, Object> args){ | |||||
| StringBuilder sql = new StringBuilder("SELECT" | |||||
| + " id, " | |||||
| + " templateId, " | |||||
| + " fileId, " | |||||
| + " created, " | |||||
| + " modified " | |||||
| + " FROM filled_form " | |||||
| + " WHERE deleted = FALSE " | |||||
| ); | |||||
| if (args != null) { | |||||
| if (args.containsKey("clientId")) | |||||
| sql.append(" AND clientId = :clientId "); | |||||
| if (args.containsKey("templateId")) | |||||
| sql.append(" AND templateId = :templateId "); | |||||
| if (args.containsKey("remarks")) | |||||
| sql.append(" AND remarks LIKE :remarks "); | |||||
| if (args.containsKey("createDateFrom")) | |||||
| sql.append(" AND created >= :createDateFrom "); | |||||
| if (args.containsKey("createDateTo")) | |||||
| sql.append(" AND created <= :createDateTo "); | |||||
| } | |||||
| // sql.append(" ORDER BY id desc "); | |||||
| return jdbcDao.queryForList(sql.toString(), args); | |||||
| } | |||||
| public Map<String, Object> loadPDF(Long id) { | |||||
| // Pdf pdfInstance = find(id).orElseThrow(NotFoundException::new); | |||||
| // byte[] blobBytes = fileService.getfileBlob(pdfInstance.getFileId()); | |||||
| StringBuilder sql = new StringBuilder("SELECT" | |||||
| + " ff.*, " | |||||
| + " fb.bytes AS blobValue" | |||||
| + " FROM filled_form ff " | |||||
| + " LEFT JOIN file_blob fb ON ff.fileId = fb.fileId " | |||||
| + " WHERE ff.deleted = FALSE" | |||||
| + " AND ff.id = :id " | |||||
| ); | |||||
| // Map<String, Object> result = jdbcDao.queryForMap(sql.toString(), Map.of("id", id)).orElseThrow(NotFoundException::new); | |||||
| // result.put("blobValue", new ByteArrayResource(blobBytes)); | |||||
| // return result; | |||||
| return jdbcDao.queryForMap(sql.toString(), Map.of("id", id)).orElseThrow(NotFoundException::new); | |||||
| } | |||||
| public Integer getIdByName(String name) { | |||||
| StringBuilder sql = new StringBuilder("SELECT" | |||||
| + " e.id " | |||||
| + " FROM event e " | |||||
| + " WHERE e.deleted = FALSE" | |||||
| + " AND e.name = :name " | |||||
| ); | |||||
| return jdbcDao.queryForInt(sql.toString(), Map.of("name", name)); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,112 @@ | |||||
| package com.ffii.lioner.modules.lioner.pdf.web; | |||||
| import java.io.IOException; | |||||
| import java.nio.file.Files; | |||||
| import java.nio.file.Path; | |||||
| import java.nio.file.Paths; | |||||
| import java.util.HashMap; | |||||
| import java.util.List; | |||||
| import java.util.Map; | |||||
| import java.util.UUID; | |||||
| import org.springframework.http.HttpHeaders; | |||||
| import org.springframework.http.HttpStatus; | |||||
| import org.springframework.http.MediaType; | |||||
| import org.springframework.http.ResponseEntity; | |||||
| import org.springframework.web.bind.ServletRequestBindingException; | |||||
| import org.springframework.web.bind.annotation.CrossOrigin; | |||||
| import org.springframework.web.bind.annotation.GetMapping; | |||||
| import org.springframework.web.bind.annotation.PathVariable; | |||||
| import org.springframework.web.bind.annotation.PostMapping; | |||||
| import org.springframework.web.bind.annotation.RequestBody; | |||||
| import org.springframework.web.bind.annotation.RequestMapping; | |||||
| import org.springframework.web.bind.annotation.RequestParam; | |||||
| import org.springframework.web.bind.annotation.RestController; | |||||
| import org.springframework.transaction.annotation.Isolation; | |||||
| import org.springframework.transaction.annotation.Transactional; | |||||
| import org.springframework.web.multipart.MultipartFile; | |||||
| import com.ffii.core.response.DataRes; | |||||
| import com.ffii.core.response.RecordsRes; | |||||
| import com.ffii.core.utils.CriteriaArgsBuilder; | |||||
| import jakarta.servlet.http.HttpServletRequest; | |||||
| import jakarta.validation.Valid; | |||||
| import com.ffii.core.exception.NotFoundException; | |||||
| import com.ffii.core.utils.Params; | |||||
| import com.ffii.lioner.modules.lioner.pdf.req.UpdatePdfReq; | |||||
| import com.ffii.lioner.modules.lioner.pdf.service.PdfService; | |||||
| @RestController | |||||
| @RequestMapping("/pdf") | |||||
| @CrossOrigin(origins = "", allowedHeaders = "") | |||||
| public class PdfController { | |||||
| private PdfService pdfService; | |||||
| public PdfController(PdfService pdfService) { | |||||
| this.pdfService = pdfService; | |||||
| } | |||||
| // @GetMapping("/{id}") | |||||
| // public List<Map<String, Object>> get(@PathVariable Long id) { | |||||
| // return Map.of( | |||||
| // Params.DATA, pdfService.findByClientId(id).orElseThrow(NotFoundException::new) | |||||
| // ); | |||||
| // } | |||||
| @GetMapping | |||||
| public RecordsRes<Map<String, Object>> list(HttpServletRequest request) throws ServletRequestBindingException { | |||||
| return new RecordsRes<>(pdfService.list( | |||||
| CriteriaArgsBuilder.withRequest(request) | |||||
| .addInteger("clientId") | |||||
| .addInteger("templateId") | |||||
| .addDate("createDateFrom") | |||||
| .addDate("createDateTo") | |||||
| .addStringLike("remarks") | |||||
| .build())); | |||||
| } | |||||
| @GetMapping("/{id}") | |||||
| public Map<String, Object> get(@PathVariable Long id) { | |||||
| return pdfService.loadPDF(id); | |||||
| // return Map.of( | |||||
| // Params.DATA, pdfService.loadPDF(id) | |||||
| // ); | |||||
| } | |||||
| // Endpoint to serve the initial template PDF | |||||
| @GetMapping(value = "/template", produces = MediaType.APPLICATION_PDF_VALUE) | |||||
| public ResponseEntity<byte[]> getPdfTemplate() throws IOException { | |||||
| byte[] pdfBytes = pdfService.getTemplateForm(); | |||||
| HttpHeaders headers = new HttpHeaders(); | |||||
| headers.setContentDispositionFormData("inline", "template_form.pdf"); | |||||
| headers.setContentType(MediaType.APPLICATION_PDF); | |||||
| return new ResponseEntity<>(pdfBytes, headers, HttpStatus.OK); | |||||
| } | |||||
| // Endpoint to receive the filled PDF from the frontend | |||||
| @Transactional(isolation = Isolation.SERIALIZABLE, rollbackFor = Exception.class, readOnly = false) | |||||
| @PostMapping(value = "/save", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) | |||||
| // public Map<String, Object> saveFilledPdf(@RequestParam("pdf") @Valid UpdatePdfReq req, @RequestParam("file") MultipartFile file) { | |||||
| // public Map<String, Object> saveFilledPdf(@RequestParam("record") UpdatePdfReq req, @RequestParam("file") MultipartFile file) { | |||||
| public Map<String, Object> saveFilledPdf(@RequestParam("record") String recordJson, @RequestParam("file") MultipartFile file) { | |||||
| return Map.of( | |||||
| Params.DATA,pdfService.saveOrUpdate(recordJson, file) | |||||
| ); | |||||
| } | |||||
| // Optional: Endpoint to receive just the form data (e.g., JSON) | |||||
| @PostMapping("/saveFormData") | |||||
| public ResponseEntity<Map<String, String>> saveFormData(@RequestBody Map<String, Object> formData) { | |||||
| System.out.println("Received form data: " + formData); | |||||
| Map<String, String> response = new HashMap<>(); | |||||
| response.put("message", "Form data received and processed successfully."); | |||||
| return ResponseEntity.ok(response); | |||||
| } | |||||
| } | |||||
| @@ -1,86 +0,0 @@ | |||||
| package com.ffii.lioner.modules.lioner.web; | |||||
| import java.io.IOException; | |||||
| import java.io.InputStream; | |||||
| import java.nio.file.Files; | |||||
| import java.nio.file.Path; | |||||
| import java.nio.file.Paths; | |||||
| import java.util.HashMap; | |||||
| import java.util.Map; | |||||
| import java.util.UUID; | |||||
| import org.springframework.core.io.ClassPathResource; | |||||
| import org.springframework.http.HttpHeaders; | |||||
| import org.springframework.http.HttpStatus; | |||||
| import org.springframework.http.MediaType; | |||||
| import org.springframework.http.ResponseEntity; | |||||
| import org.springframework.web.bind.annotation.CrossOrigin; | |||||
| import org.springframework.web.bind.annotation.GetMapping; | |||||
| import org.springframework.web.bind.annotation.PostMapping; | |||||
| import org.springframework.web.bind.annotation.RequestBody; | |||||
| import org.springframework.web.bind.annotation.RequestMapping; | |||||
| import org.springframework.web.bind.annotation.RequestParam; | |||||
| import org.springframework.web.bind.annotation.RestController; | |||||
| import org.springframework.web.multipart.MultipartFile; | |||||
| @RestController | |||||
| @RequestMapping("/pdf") | |||||
| @CrossOrigin(origins = "", allowedHeaders = "") | |||||
| public class PdfController { | |||||
| private String pdf_path = "templates/pdf/"; | |||||
| // Endpoint to serve the initial template PDF | |||||
| @GetMapping(value = "/template", produces = MediaType.APPLICATION_PDF_VALUE) | |||||
| public ResponseEntity<byte[]> getPdfTemplate() throws IOException { | |||||
| // Ensure your template PDF is in src/main/resources/static/ | |||||
| ClassPathResource pdfFile = new ClassPathResource(pdf_path + "HSBC B24102883_fillable_Financial Needs Analysis for Individual Nov2024.pdf"); | |||||
| if (!pdfFile.exists()) { | |||||
| return ResponseEntity.status(HttpStatus.NOT_FOUND).body("PDF template not found.".getBytes()); | |||||
| } | |||||
| byte[] pdfBytes; | |||||
| try (InputStream is = pdfFile.getInputStream()) { | |||||
| pdfBytes = is.readAllBytes(); | |||||
| } | |||||
| HttpHeaders headers = new HttpHeaders(); | |||||
| headers.setContentDispositionFormData("inline", "template_form.pdf"); | |||||
| headers.setContentType(MediaType.APPLICATION_PDF); | |||||
| return new ResponseEntity<>(pdfBytes, headers, HttpStatus.OK); | |||||
| } | |||||
| // Endpoint to receive the filled PDF from the frontend | |||||
| @PostMapping(value = "/save", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) | |||||
| public ResponseEntity<Map<String, String>> saveFilledPdf(@RequestParam("file") MultipartFile file) { | |||||
| if (file.isEmpty()) { | |||||
| return ResponseEntity.badRequest().body(Map.of("message", "No file uploaded.")); | |||||
| } | |||||
| try { | |||||
| // Generate a unique filename and save to an 'uploads' directory | |||||
| String fileName = "filled_form_" + UUID.randomUUID().toString() + ".pdf"; | |||||
| Path filePath = Paths.get("uploads", fileName); | |||||
| Files.createDirectories(filePath.getParent()); // Ensure directory exists | |||||
| Files.copy(file.getInputStream(), filePath); | |||||
| Map<String, String> response = new HashMap<>(); | |||||
| response.put("message", "PDF saved successfully: " + fileName); | |||||
| response.put("filePath", filePath.toString()); | |||||
| return ResponseEntity.ok(response); | |||||
| } catch (IOException e) { | |||||
| e.printStackTrace(); | |||||
| return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) | |||||
| .body(Map.of("message", "Failed to save PDF: " + e.getMessage())); | |||||
| } | |||||
| } | |||||
| // Optional: Endpoint to receive just the form data (e.g., JSON) | |||||
| @PostMapping("/saveFormData") | |||||
| public ResponseEntity<Map<String, String>> saveFormData(@RequestBody Map<String, Object> formData) { | |||||
| System.out.println("Received form data: " + formData); | |||||
| Map<String, String> response = new HashMap<>(); | |||||
| response.put("message", "Form data received and processed successfully."); | |||||
| return ResponseEntity.ok(response); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,20 @@ | |||||
| --liquibase formatted sql | |||||
| --changeset kelvin:add filled form table | |||||
| CREATE TABLE `filled_form` ( | |||||
| `id` int NOT NULL AUTO_INCREMENT, | |||||
| `created` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, | |||||
| `createdBy` int DEFAULT NULL, | |||||
| `version` int NOT NULL DEFAULT '0', | |||||
| `modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, | |||||
| `modifiedBy` int DEFAULT NULL, | |||||
| `deleted` tinyint(1) NOT NULL DEFAULT '0', | |||||
| `templateId` int(11) NOT NULL, | |||||
| `clientId` int(11), | |||||
| `fileId` int(11) NOT NULL, | |||||
| `remarks` VARCHAR(600), | |||||
| PRIMARY KEY (`id`) | |||||
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8; | |||||
| @@ -0,0 +1,7 @@ | |||||
| --liquibase formatted sql | |||||
| --changeset kelvin:update client table | |||||
| ALTER TABLE `lionerdb`.`client` | |||||
| CHANGE COLUMN `createdBy` `createdBy` INT NULL DEFAULT NULL , | |||||
| CHANGE COLUMN `modifiedBy` `modifiedBy` INT NULL DEFAULT NULL ; | |||||