@@ -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, | |||
) |