Skip to content

Instantly share code, notes, and snippets.

@jasoet
Created September 9, 2016 02:37
Show Gist options
  • Save jasoet/f1a8fc2a2e95d7fb1a31cbab13b87cf7 to your computer and use it in GitHub Desktop.
Save jasoet/f1a8fc2a2e95d7fb1a31cbab13b87cf7 to your computer and use it in GitHub Desktop.
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional
import org.jasoet.util.lang.orNotFound
import org.jasoet.db.entity.FinancialData
import org.jasoet.db.entity.Grant
import org.jasoet.db.repository.FinancialDataRepository
import org.jasoet.repository.GrantRepository
import org.jasoet.db.repository.master.InstitutionRepository
import java.time.LocalDate
import java.time.Month
import java.time.Year
/**
* [Documentation Here]
*
* @author Deny Prasetyo.
*/
@Service
open class GrantService {
@Autowired
open lateinit var grantRepository: GrantRepository
@Autowired
open lateinit var financialDataRepository: FinancialDataRepository
@Autowired
open lateinit var institutionRepository: InstitutionRepository
private val monthDueDate: Int = 14
@Transactional
@Throws(Exception::class)
open fun save(grant: Grant): Grant {
val savedGrant: Grant = grantRepository.save(grant)
val grantId = savedGrant.id
val student = savedGrant.student orNotFound "Student not Found for Grant $grantId "
val schoolPeriod = savedGrant.schoolPeriod orNotFound "SchoolPeriod not Found for Grant $grantId "
val schoolStartYear = schoolPeriod.startYear.value orNotFound "School Period StartYear not Found for SchoolPeriod ${schoolPeriod.id} in Grant $grantId "
val devianStartMonth: Month? = savedGrant.devianStartMonth
val institution = institutionRepository.findOne(student.institutionCode) orNotFound "Institution not Found [$grantId - ${student.username}]"
val institutionMonthStart = institution.monthStart
val schoolPeriodDetail = schoolPeriod.getDetailByLevelId(student.level?.id) orNotFound "SchoolPeriodDetail not Found [$grantId - ${student.username}]"
val yearMonthMap = Month.values().toMapBy(institutionMonthStart, schoolStartYear, devianStartMonth)
yearMonthMap.forEach {
val (yearMonth, active) = it
val (year, month) = yearMonth
val financialData = FinancialData()
financialData.grant = savedGrant
financialData.month = month
if (active) {
financialData.dateDue = LocalDate.of(year.value, month, monthDueDate)
financialData.rpDue = schoolPeriodDetail.monthlyGrant.toFloat()
}
financialDataRepository.save(financialData)
}
return savedGrant
}
/** Update Grant
* Currently ONLY School Year can be Updated!
* */
@Transactional
@Throws(Exception::class)
open fun update(grantId: Long, grant: Grant): Grant {
val updatedGrant = grantRepository.findOne(grantId) ?: throw NullPointerException("Grant with id $grantId not found!")
updatedGrant.schoolYear = grant.schoolYear orNotFound "Grant schoolYear cannot null"
return grantRepository.save(updatedGrant)
}
/** Delete Grant
* Will delete All Related FinancialData
* */
@Transactional
@Throws(Exception::class)
open fun delete(grantId: Long): Grant? {
val updatedGrant = grantRepository.findOne(grantId) ?: throw NullPointerException("Grant with id $grantId not found!")
val financialDatas = financialDataRepository.findByGrant(updatedGrant)
financialDataRepository.delete(financialDatas)
return updatedGrant
}
}
/** Class to Store Year and Month Combination */
private data class YearMonth(val year: Year, val month: Month)
private fun Array<Month>.toMapBy(order: Month, startYear: Int, devianMonth: Month?): Map<YearMonth, Boolean> {
val yearMonths = this.reorderBy(order, startYear)
return if (devianMonth == null) {
yearMonths.map { it to true }.toMap()
} else {
val indexDevian = yearMonths.indexOfFirst { it.month == devianMonth }
yearMonths.mapIndexed { i, yearMonth ->
yearMonth to (i >= indexDevian)
}.toMap()
}
}
private fun Array<Month>.reorderBy(month: Month, startYear: Int): List<YearMonth> {
val months = this.reorderBy(month)
val januaryIndex = months.indexOf(Month.JANUARY)
return months.mapIndexed { i, month ->
if (i < januaryIndex) {
YearMonth(year = Year.of(startYear), month = month)
} else {
YearMonth(year = Year.of(startYear + 1), month = month)
}
}
}
private fun Array<Month>.reorderBy(month: Month): List<Month> {
val months = this.toList()
val startIndex = months.indexOf(month)
val startList = months.subList(startIndex, months.size)
val endList = months.subList(0, startIndex)
return startList + endList
}
@jasoet
Copy link
Author

jasoet commented Sep 9, 2016

@hiraq basically sama tanda ?: (elvis operator) itu dia melakukan Check apakan variable sebelah kanan Null atau tidak. kemudian menjalankan kode sebelah kanan.

Itu hal yang sama yang dilakukan oleh orNotFound, harusnya kode baris 88 bisa diganti dengan orNotFound

NullObjectException ini custom Exception, agar ketika handle di controller @ExceptionHandler lebih sepesifik

@jasoet
Copy link
Author

jasoet commented Sep 9, 2016

Baris https://gist.github.com/jasoet/f1a8fc2a2e95d7fb1a31cbab13b87cf7#file-grantservice-kt-L37:L40

Sebenarnya kompensasi dari Bawaan Library Java yang nullable jadi setiap step nya lbh baik "Diamankan", walau beberapa kode itu sebenarnya Not Null dan aman kalau mau dipaksa pakai (!!) tapi saya lebih nyaman di check satu satu.

@hiraq
Copy link

hiraq commented Sep 9, 2016

i see .. paham2 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment