| @@ -1,28 +1,41 @@ | |||
| package com.ffii.tsms.modules.claim.service | |||
| import com.ffii.core.support.AbstractBaseEntityService | |||
| import com.ffii.core.support.JdbcDao | |||
| import com.ffii.tsms.modules.claim.entity.Claim | |||
| import com.ffii.tsms.modules.claim.entity.ClaimDetail | |||
| import com.ffii.tsms.modules.claim.entity.ClaimDetailRepository | |||
| import com.ffii.tsms.modules.claim.entity.ClaimRepository | |||
| import com.ffii.tsms.modules.claim.web.models.SaveClaimDetailRequest | |||
| import com.ffii.tsms.modules.claim.web.models.SaveClaimRequest | |||
| import com.ffii.tsms.modules.claim.web.models.SaveClaimResponse | |||
| import com.ffii.tsms.modules.file.entity.FileBlob | |||
| import com.ffii.tsms.modules.data.entity.StaffRepository | |||
| import com.ffii.tsms.modules.data.service.StaffsService | |||
| import com.ffii.tsms.modules.file.entity.FileRepository | |||
| import com.ffii.tsms.modules.file.service.FileService | |||
| import com.ffii.tsms.modules.project.entity.ProjectRepository | |||
| import org.springframework.beans.BeanUtils | |||
| import com.ffii.tsms.modules.user.entity.User | |||
| import com.ffii.tsms.modules.user.entity.UserRepository | |||
| import com.ffii.tsms.modules.user.service.UserService | |||
| import org.springframework.security.core.Authentication | |||
| import org.springframework.security.core.context.SecurityContextHolder | |||
| import org.springframework.stereotype.Service | |||
| import org.springframework.transaction.annotation.Transactional | |||
| import java.text.NumberFormat | |||
| import org.springframework.web.multipart.MultipartFile | |||
| import java.math.BigDecimal | |||
| import java.time.LocalDate | |||
| import java.time.format.DateTimeFormatter | |||
| import java.util.HashMap | |||
| import java.util.* | |||
| @Service | |||
| open class ClaimService( | |||
| private val claimRepository: ClaimRepository, | |||
| private val fileService: FileService, private val claimDetailRepository: ClaimDetailRepository, private val projectRepository: ProjectRepository | |||
| ) { | |||
| private val fileService: FileService, | |||
| private val claimDetailRepository: ClaimDetailRepository, | |||
| private val projectRepository: ProjectRepository, | |||
| private val jdbcDao: JdbcDao, | |||
| private val fileRepository: FileRepository, | |||
| private val userRepository: UserRepository, | |||
| private val staffsService: StaffsService, | |||
| ) : AbstractBaseEntityService<Claim, Long, ClaimRepository>(jdbcDao, claimRepository) { | |||
| open fun allClaims(): List<Claim> { | |||
| return claimRepository.findAllByDeletedFalse() | |||
| } | |||
| @@ -41,52 +54,99 @@ open class ClaimService( | |||
| } | |||
| @Transactional(rollbackFor = [Exception::class]) | |||
| open fun saveClaimDetail(claimDetail: SaveClaimDetailRequest, claim: Claim) { | |||
| val oldSupportingDocumentId = claimDetail.oldSupportingDocument?.id // fileId | |||
| val newSupportingDocument = claimDetail.newSupportingDocument | |||
| val claimDetailId = claimDetail.id | |||
| val projectId = claimDetail.project.id | |||
| open fun saveClaimDetail( | |||
| claimDetailId: Long, | |||
| claimDetailInvoiceDate: LocalDate, | |||
| claimDetailProjectId: Long, | |||
| claimDetailDescription: String, | |||
| claimDetailAmount: BigDecimal, | |||
| claimDetailNewSupportingDocument: MultipartFile?, | |||
| claimDetailOldSupportingDocumentId: Long?, | |||
| claim: Claim, | |||
| ) { | |||
| var result: MutableMap<String, Any> = HashMap<String, Any>() | |||
| if (oldSupportingDocumentId != null && oldSupportingDocumentId > 0 && newSupportingDocument != null) { | |||
| result = fileService.updateFile(multipartFile = newSupportingDocument, refId = claim.id, refType = "claimDetail", refCode = claim.code, maxSize = 50, fileId = oldSupportingDocumentId) | |||
| } else if ((oldSupportingDocumentId == null || oldSupportingDocumentId <= 0) && newSupportingDocument != null) { | |||
| result = fileService.uploadFile(multipartFile = newSupportingDocument, refId = claim.id, refType = "claimDetail", refCode = claim.code, maxSize = 50) | |||
| if (claimDetailOldSupportingDocumentId != null && claimDetailOldSupportingDocumentId > 0 && claimDetailNewSupportingDocument != null) { | |||
| result = fileService.updateFile( | |||
| multipartFile = claimDetailNewSupportingDocument, | |||
| refId = claim.id, | |||
| refType = "claimDetail", | |||
| refCode = claim.code, | |||
| maxSize = 50, | |||
| fileId = claimDetailOldSupportingDocumentId | |||
| ) | |||
| } else if ((claimDetailOldSupportingDocumentId == null || claimDetailOldSupportingDocumentId <= 0) && claimDetailNewSupportingDocument != null) { | |||
| result = fileService.uploadFile( | |||
| multipartFile = claimDetailNewSupportingDocument, | |||
| refId = claim.id, | |||
| refType = "claimDetail", | |||
| refCode = claim.code, | |||
| maxSize = 50 | |||
| ) | |||
| } | |||
| val instance = claimDetailRepository.findById(claimDetailId).orElse(ClaimDetail()) | |||
| BeanUtils.copyProperties(claimDetail, instance) | |||
| if (result["fileId"] != null && result["fileId"] as Long > 0) { | |||
| val instance = claimDetailRepository.findById(claimDetailId).orElse(ClaimDetail()) | |||
| val project = projectRepository.findById(claimDetailProjectId).orElseThrow() | |||
| val file = fileRepository.findById(result["fileId"] as Long).orElseThrow() | |||
| instance.apply { | |||
| this.claim = claim | |||
| invoiceDate = claimDetailInvoiceDate | |||
| this.project = project | |||
| description = claimDetailDescription | |||
| amount = claimDetailAmount | |||
| this.file = file | |||
| } | |||
| val project = projectRepository.findById(projectId!!).orElseThrow() | |||
| instance.apply { | |||
| this.project = project | |||
| claimDetailRepository.save(instance) | |||
| } else { | |||
| logger.info("error") | |||
| } | |||
| claimDetailRepository.save(instance) | |||
| } | |||
| @Transactional(rollbackFor = [Exception::class]) | |||
| open fun saveClaim(saveClaimRequest: SaveClaimRequest): SaveClaimResponse { | |||
| val claimId = saveClaimRequest.id | |||
| val addClaimDetails = saveClaimRequest.addClaimDetails | |||
| open fun saveClaim( | |||
| id: Long?, | |||
| expenseType: String, | |||
| status: String, | |||
| addClaimDetailIds: List<Long>, | |||
| addClaimDetailInvoiceDates: List<LocalDate>, | |||
| addClaimDetailProjectIds: List<Long>, | |||
| addClaimDetailDescriptions: List<String>, | |||
| addClaimDetailAmounts: List<BigDecimal>, | |||
| addClaimDetailNewSupportingDocuments: List<MultipartFile>, | |||
| addClaimDetailOldSupportingDocumentIds: List<Long> | |||
| ): SaveClaimResponse { | |||
| // Save to claim | |||
| val instance = if (claimId != null && claimId > 0) claimRepository.findById(claimId).orElseThrow() else Claim(); | |||
| val instance = if (id != null && id > 0) claimRepository.findById(id).orElseThrow() else Claim(); | |||
| val user = SecurityContextHolder.getContext().authentication.principal as User | |||
| logger.info(user.id) | |||
| val staff = staffsService.findByUserId(user.id!!).orElseThrow() | |||
| instance.apply { | |||
| type = saveClaimRequest.expenseType | |||
| code = if(instance.code.isNullOrEmpty()) generateCode() else instance.code | |||
| type = expenseType | |||
| code = if (instance.code.isNullOrEmpty()) generateCode() else instance.code | |||
| this.staff = staff | |||
| this.status = status | |||
| } | |||
| claimRepository.save(instance) | |||
| // Save to claim detail | |||
| if (addClaimDetails.isNotEmpty()) { | |||
| for(addClaimDetail in addClaimDetails) { | |||
| saveClaimDetail(addClaimDetail, instance) | |||
| if (addClaimDetailIds.isNotEmpty()) { | |||
| for (i in addClaimDetailIds.indices) { | |||
| saveClaimDetail( | |||
| addClaimDetailIds[i], | |||
| addClaimDetailInvoiceDates[i], | |||
| addClaimDetailProjectIds[i], | |||
| addClaimDetailDescriptions[i], | |||
| addClaimDetailAmounts[i], | |||
| addClaimDetailNewSupportingDocuments[i], | |||
| addClaimDetailOldSupportingDocumentIds[i], | |||
| instance | |||
| ) | |||
| } | |||
| } | |||
| return SaveClaimResponse(claim = instance, message = "Success"); | |||
| return SaveClaimResponse(claim = Claim(), message = "Success"); | |||
| } | |||
| } | |||
| @@ -1,17 +1,28 @@ | |||
| package com.ffii.tsms.modules.claim.web | |||
| import com.ffii.tsms.modules.claim.entity.Claim | |||
| import com.ffii.tsms.modules.claim.entity.ClaimDetail | |||
| import com.ffii.tsms.modules.claim.service.ClaimService | |||
| import com.ffii.tsms.modules.claim.web.models.SaveClaimDetailRequest | |||
| import com.ffii.tsms.modules.claim.web.models.SaveClaimRequest | |||
| import com.ffii.tsms.modules.claim.web.models.SaveClaimResponse | |||
| import com.ffii.tsms.modules.data.web.models.SaveCustomerResponse | |||
| import com.ffii.tsms.modules.project.web.models.SaveCustomerRequest | |||
| import jakarta.validation.Valid | |||
| import org.apache.logging.log4j.core.config.plugins.validation.constraints.Required | |||
| import org.springframework.web.bind.ServletRequestBindingException | |||
| import org.springframework.web.bind.annotation.GetMapping | |||
| import org.springframework.web.bind.annotation.ModelAttribute | |||
| 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.RequestPart | |||
| import org.springframework.web.bind.annotation.RestController | |||
| import org.springframework.web.multipart.MultipartFile | |||
| import java.io.IOException | |||
| import java.math.BigDecimal | |||
| import java.time.LocalDate | |||
| @RestController | |||
| @RequestMapping("/claim") | |||
| @@ -22,8 +33,40 @@ class ClaimController(private val claimService: ClaimService) { | |||
| return claimService.allClaims() | |||
| } | |||
| @PostMapping("/test") | |||
| fun forTest(@RequestBody testFiles: List<MultipartFile>) { | |||
| System.out.println(testFiles.size) | |||
| } | |||
| @PostMapping("/save") | |||
| fun saveClaim(@Valid @RequestBody saveClaimRequest: SaveClaimRequest): SaveClaimResponse { | |||
| return claimService.saveClaim(saveClaimRequest) | |||
| fun saveClaim( | |||
| @RequestParam(required = false) id: Long?, | |||
| @RequestParam expenseType: String, | |||
| @RequestParam status: String, | |||
| @RequestParam addClaimDetailIds: List<Long>, | |||
| @RequestParam addClaimDetailInvoiceDates: List<LocalDate>, | |||
| @RequestParam addClaimDetailProjectIds: List<Long>, | |||
| @RequestParam addClaimDetailDescriptions: List<String>, | |||
| @RequestParam addClaimDetailAmounts: List<BigDecimal>, | |||
| @RequestParam addClaimDetailNewSupportingDocuments: List<MultipartFile>, | |||
| @RequestParam addClaimDetailOldSupportingDocumentIds: List<Long>, | |||
| ): SaveClaimResponse { | |||
| System.out.println("yo") | |||
| return claimService.saveClaim(id, expenseType, status, addClaimDetailIds, addClaimDetailInvoiceDates, addClaimDetailProjectIds, addClaimDetailDescriptions, addClaimDetailAmounts, addClaimDetailNewSupportingDocuments, addClaimDetailOldSupportingDocumentIds) | |||
| } | |||
| @PostMapping("/save2") | |||
| fun saveClaim2( | |||
| @RequestParam id: Long, | |||
| @RequestParam expenseType: String, | |||
| @RequestParam status: String, | |||
| @RequestParam addClaimDetailIds: List<Long>, | |||
| @RequestParam addClaimDetailInvoiceDates: List<LocalDate>, | |||
| @RequestParam addClaimDetailDescriptions: List<String>, | |||
| @RequestParam addClaimDetailProjectIds: List<Long>, | |||
| @RequestParam addClaimDetailNewSupportingDocuments: List<MultipartFile>, | |||
| @RequestParam addClaimDetailOldSupportingDocumentIds: List<Long>, | |||
| ) { | |||
| System.out.println("yo") | |||
| } | |||
| } | |||
| @@ -16,9 +16,9 @@ data class Project ( | |||
| val id: Long, | |||
| ) | |||
| data class SaveClaimDetailRequest ( | |||
| val id: Long, | |||
| val id: String?, | |||
| val invoiceDate: LocalDate, | |||
| val description: String, | |||
| val description: String?, | |||
| val project: Project, | |||
| val amount: BigDecimal, | |||
| val newSupportingDocument: MultipartFile?, | |||
| @@ -30,6 +30,7 @@ data class SaveClaimRequest ( | |||
| val expenseType: String, | |||
| val addClaimDetails: List<SaveClaimDetailRequest>, | |||
| val addClaimDetailsFiles: List<MultipartFile>, | |||
| val status: String, | |||
| val id: Long?, | |||
| @@ -15,4 +15,6 @@ public interface StaffRepository extends AbstractRepository<Staff, Long> { | |||
| List<StaffSearchInfo> findAllStaffSearchInfoByIdIn(List<Long> ids); | |||
| Optional<Staff> findByStaffId(@Param("staffId") String staffId); | |||
| Optional<Staff> findByUserId(@Param("userId") Long userId); | |||
| } | |||
| @@ -70,6 +70,10 @@ open class StaffsService( | |||
| return staffRepository.findByStaffId(id); | |||
| } | |||
| open fun findByUserId(userId: Long): Optional<Staff> { | |||
| return staffRepository.findByUserId(userId); | |||
| } | |||
| @Transactional(rollbackFor = [Exception::class]) | |||
| open fun saveStaff(req: NewStaffRequest): Staff { | |||
| val user = userRepository.saveAndFlush( | |||
| @@ -1,19 +1,15 @@ | |||
| package com.ffii.tsms.modules.file.entity | |||
| import com.ffii.core.entity.BaseEntity | |||
| import com.ffii.core.entity.IdEntity | |||
| import jakarta.persistence.Column | |||
| import jakarta.persistence.Entity | |||
| import jakarta.persistence.Table | |||
| import jakarta.validation.constraints.NotNull | |||
| import java.math.BigInteger | |||
| @Entity | |||
| @Table(name = "file") | |||
| open class File : BaseEntity<Long>() { | |||
| open val DEFAULT_UPLOAD_MAX_FILE_SIZE_MB: Int = 50 | |||
| @NotNull | |||
| @Column(name = "skey", length = 32) | |||
| open var skey: String? = null | |||
| @@ -24,7 +20,7 @@ open class File : BaseEntity<Long>() { | |||
| @NotNull | |||
| @Column(name = "extension", length = 10) | |||
| open var description: String? = null | |||
| open var extension: String? = null | |||
| @NotNull | |||
| @Column(name = "mimetype", length = 255) | |||
| @@ -1,6 +1,5 @@ | |||
| package com.ffii.tsms.modules.file.entity | |||
| import com.ffii.core.entity.BaseEntity | |||
| import com.ffii.core.entity.IdEntity | |||
| import jakarta.persistence.Column | |||
| import jakarta.persistence.Entity | |||
| @@ -11,7 +10,7 @@ import jakarta.validation.constraints.NotNull | |||
| @Entity | |||
| @Table(name = "file_blob") | |||
| open class FileBlob : BaseEntity<Long>() { | |||
| open class FileBlob : IdEntity<Long>() { | |||
| @NotNull | |||
| @OneToOne | |||
| @@ -1,6 +1,5 @@ | |||
| package com.ffii.tsms.modules.file.entity | |||
| import com.ffii.core.entity.BaseEntity | |||
| import com.ffii.core.entity.IdEntity | |||
| import jakarta.persistence.Column | |||
| import jakarta.persistence.Entity | |||
| @@ -11,7 +10,7 @@ import jakarta.validation.constraints.NotNull | |||
| @Entity | |||
| @Table(name = "file_ref") | |||
| open class FileRef : BaseEntity<Long>() { | |||
| open class FileRef : IdEntity<Long>() { | |||
| @NotNull | |||
| @Column(name = "refType", length = 20) | |||
| @@ -5,6 +5,7 @@ import com.ffii.core.support.JdbcDao | |||
| import com.ffii.core.utils.FileUtils | |||
| import com.ffii.core.utils.NumberUtils | |||
| import com.ffii.core.utils.Params | |||
| import com.ffii.core.utils.StringUtils | |||
| import com.ffii.tsms.modules.file.entity.* | |||
| import org.apache.commons.lang3.RandomStringUtils | |||
| import org.springframework.stereotype.Service | |||
| @@ -13,8 +14,8 @@ import org.springframework.transaction.annotation.Transactional | |||
| import org.springframework.web.multipart.MultipartFile | |||
| import java.io.ByteArrayInputStream | |||
| import java.io.IOException | |||
| import java.util.* | |||
| import java.util.Map | |||
| import java.util.Optional | |||
| import javax.imageio.ImageIO | |||
| @@ -99,7 +100,7 @@ open class FileService( | |||
| + " fr.refType," | |||
| + " f.created," | |||
| + " u.name AS createdByName," | |||
| + " f.description" | |||
| + " f.extension" | |||
| + " FROM file f" | |||
| + " LEFT JOIN file_ref fr ON f.id = fr.fileId" | |||
| + " LEFT JOIN user u ON f.createdBy = u.id" | |||
| @@ -155,7 +156,7 @@ open class FileService( | |||
| @Transactional(isolation = Isolation.SERIALIZABLE, rollbackFor = [Exception::class], readOnly = false) | |||
| open fun saveFile( | |||
| filename: String, | |||
| description: String, | |||
| // extension: String, | |||
| refType: String, | |||
| refId: Long, | |||
| refCode: String, | |||
| @@ -165,7 +166,7 @@ open class FileService( | |||
| file.apply { | |||
| this.filename = filename | |||
| this.description = description | |||
| this.extension = StringUtils.substringAfterLast(filename, "."); | |||
| mimetype = FileUtils.guessMimetype(filename) | |||
| filesize = NumberUtils.toLong(bytes.size, 0L) | |||
| skey = RandomStringUtils.randomAlphanumeric(32) | |||
| @@ -207,7 +208,7 @@ open class FileService( | |||
| @Throws(IOException::class) | |||
| open fun uploadFile( | |||
| multipartFile: MultipartFile, refId: Long?, refType: String?, refCode: String?, | |||
| maxSize: Int | |||
| maxSize: Int = 50 | |||
| ): MutableMap<String, Any> { | |||
| val result: MutableMap<String, Any> = HashMap<String, Any>() | |||
| @@ -221,6 +222,7 @@ open class FileService( | |||
| file.apply { | |||
| filename = multipartFile.originalFilename | |||
| extension = StringUtils.substringAfterLast(multipartFile.originalFilename, "."); | |||
| mimetype = FileUtils.guessMimetype(multipartFile.originalFilename) | |||
| filesize = multipartFile.size | |||
| skey = RandomStringUtils.randomAlphanumeric(32) | |||
| @@ -287,6 +289,7 @@ open class FileService( | |||
| file.apply { | |||
| filename = multipartFile.originalFilename | |||
| extension = StringUtils.substringAfterLast(multipartFile.originalFilename, "."); | |||
| mimetype = FileUtils.guessMimetype(multipartFile.originalFilename) | |||
| filesize = multipartFile.size | |||
| skey = RandomStringUtils.randomAlphanumeric(32) | |||
| @@ -49,7 +49,7 @@ open class FileController (private val fileService: FileService) { | |||
| if (file != null) { | |||
| file.apply { | |||
| filename = req.filename | |||
| description = req.description | |||
| extension = req.extension | |||
| } | |||
| fileService.saveFile(file) | |||
| @@ -35,7 +35,7 @@ class UploadFileController(private val settingsService: SettingsService, private | |||
| if (multipartFileList != null) { | |||
| for (multipartFile in multipartFileList) { | |||
| result = fileService.uploadFile(multipartFile, refId, refType, refCode, File().DEFAULT_UPLOAD_MAX_FILE_SIZE_MB) | |||
| result = fileService.uploadFile(multipartFile, refId, refType, refCode, 50) | |||
| } | |||
| } | |||
| @@ -4,5 +4,5 @@ data class UpdateFileReq ( | |||
| val fileId: Long, | |||
| val filename: String, | |||
| val skey: String, | |||
| val description: String, | |||
| val extension: String, | |||
| ) | |||