feat🔫: 账单的基本操作
This commit is contained in:
parent
371359430f
commit
76e1f5d9ec
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -34,3 +34,6 @@ out/
|
||||||
|
|
||||||
### VS Code ###
|
### VS Code ###
|
||||||
.vscode/
|
.vscode/
|
||||||
|
|
||||||
|
### Fleet ###
|
||||||
|
.fleet
|
|
@ -50,6 +50,7 @@ dependencies {
|
||||||
|
|
||||||
// Session
|
// Session
|
||||||
implementation("io.ktor:ktor-server-sessions:$ktor_version")
|
implementation("io.ktor:ktor-server-sessions:$ktor_version")
|
||||||
|
implementation("io.ktor:ktor-server-auth:$ktor_version")
|
||||||
// Ktor
|
// Ktor
|
||||||
implementation("io.ktor:ktor-server-call-logging:$ktor_version")
|
implementation("io.ktor:ktor-server-call-logging:$ktor_version")
|
||||||
implementation("io.ktor:ktor-server-content-negotiation-jvm:$ktor_version")
|
implementation("io.ktor:ktor-server-content-negotiation-jvm:$ktor_version")
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
services:
|
services:
|
||||||
db:
|
db:
|
||||||
|
container_name: bill-test-db
|
||||||
image: mariadb
|
image: mariadb
|
||||||
restart: always
|
restart: always
|
||||||
environment:
|
environment:
|
||||||
|
@ -10,6 +11,7 @@ services:
|
||||||
- db-data:/var/lib/mysql
|
- db-data:/var/lib/mysql
|
||||||
|
|
||||||
adminer:
|
adminer:
|
||||||
|
container_name: bill-test-adminer
|
||||||
image: adminer
|
image: adminer
|
||||||
restart: always
|
restart: always
|
||||||
ports:
|
ports:
|
||||||
|
|
|
@ -14,5 +14,5 @@ fun Application.module() {
|
||||||
configureRouting()
|
configureRouting()
|
||||||
configureSession()
|
configureSession()
|
||||||
configureWebSocket()
|
configureWebSocket()
|
||||||
// configureDatabase()
|
configureDatabase()
|
||||||
}
|
}
|
36
src/main/kotlin/cn/fadinglight/dao/BillDao.kt
Normal file
36
src/main/kotlin/cn/fadinglight/dao/BillDao.kt
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
package cn.fadinglight.dao
|
||||||
|
|
||||||
|
import cn.fadinglight.models.Bill
|
||||||
|
import cn.fadinglight.models.BillType
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class BillDao(
|
||||||
|
val id: Int? = null,
|
||||||
|
val type: String,
|
||||||
|
val date: String,
|
||||||
|
val money: Int,
|
||||||
|
val cls: String,
|
||||||
|
val label: String,
|
||||||
|
val options: String? = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
fun BillDao.bill() = Bill(
|
||||||
|
id = id,
|
||||||
|
type = BillType.valueOf(type),
|
||||||
|
date = date,
|
||||||
|
money = money,
|
||||||
|
cls = cls,
|
||||||
|
label = label,
|
||||||
|
options = options ?: "",
|
||||||
|
)
|
||||||
|
|
||||||
|
fun Bill.dao() = BillDao(
|
||||||
|
id = id,
|
||||||
|
type = type.name,
|
||||||
|
date = date,
|
||||||
|
money = money,
|
||||||
|
cls = cls,
|
||||||
|
label = label,
|
||||||
|
options = options,
|
||||||
|
)
|
7
src/main/kotlin/cn/fadinglight/dao/LabelDao.kt
Normal file
7
src/main/kotlin/cn/fadinglight/dao/LabelDao.kt
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
package cn.fadinglight.dao
|
||||||
|
|
||||||
|
data class LabelDao(
|
||||||
|
val name: String,
|
||||||
|
val count: Int,
|
||||||
|
val labels: List<LabelDao>?
|
||||||
|
)
|
19
src/main/kotlin/cn/fadinglight/libs/Response.kt
Normal file
19
src/main/kotlin/cn/fadinglight/libs/Response.kt
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
package cn.fadinglight.libs
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class RespData<T>(val code: Int, val data: T?, val message: String?)
|
||||||
|
|
||||||
|
sealed class Resp<T> {
|
||||||
|
abstract fun json(): RespData<T>
|
||||||
|
|
||||||
|
class Ok<T>(val data: T) : Resp<T>() {
|
||||||
|
override fun json() = RespData<T>(code = 0, data = data, message = null)
|
||||||
|
}
|
||||||
|
|
||||||
|
class Error(val message: String?, val code: Int) : Resp<Unit>() {
|
||||||
|
override fun json(): RespData<Unit> = RespData(code = code, data = null, message = message)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -3,17 +3,17 @@ package cn.fadinglight.mapers
|
||||||
import org.jetbrains.exposed.dao.id.IntIdTable
|
import org.jetbrains.exposed.dao.id.IntIdTable
|
||||||
|
|
||||||
object Bills : IntIdTable() {
|
object Bills : IntIdTable() {
|
||||||
val type = integer("type")
|
val type = varchar("type", 15)
|
||||||
val date = varchar("date", 15)
|
val date = varchar("date", 15)
|
||||||
val money = integer("money")
|
val money = integer("money")
|
||||||
val cls = varchar("cls", 31)
|
val cls = varchar("cls", 31)
|
||||||
val label = varchar("label", 31)
|
val label = varchar("label", 31)
|
||||||
val options = varchar("options", 255)
|
val options = varchar("options", 255).nullable()
|
||||||
}
|
}
|
||||||
|
|
||||||
object Labels : IntIdTable() {
|
object Labels : IntIdTable() {
|
||||||
|
val type = varchar("type", 15)
|
||||||
val name = varchar("name", 15)
|
val name = varchar("name", 15)
|
||||||
val type = integer("type")
|
|
||||||
val relativeId = integer("relative_id")
|
val relativeId = integer("relative_id")
|
||||||
val nums = integer("nums")
|
val nums = integer("nums")
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,17 @@
|
||||||
package cn.fadinglight.models
|
package cn.fadinglight.models
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
|
||||||
enum class BillType {
|
enum class BillType {
|
||||||
Consume,
|
Consume,
|
||||||
Income,
|
Income,
|
||||||
}
|
}
|
||||||
|
@Serializable
|
||||||
data class Bill(
|
data class Bill(
|
||||||
var id: Int?,
|
var id: Int?,
|
||||||
var type: BillType,
|
val type: BillType,
|
||||||
|
val date: String,
|
||||||
val money: Int,
|
val money: Int,
|
||||||
val cls: String,
|
val cls: String,
|
||||||
val label: String,
|
val label: String,
|
||||||
|
|
|
@ -1,4 +1,15 @@
|
||||||
package cn.fadinglight.models
|
package cn.fadinglight.models
|
||||||
|
|
||||||
class Label {
|
|
||||||
|
enum class LabelType {
|
||||||
|
CLASS,
|
||||||
|
LABEL,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data class Label(
|
||||||
|
var id: Int?,
|
||||||
|
val type: LabelType,
|
||||||
|
val name: String,
|
||||||
|
var count: Int,
|
||||||
|
val relativedId: Int,
|
||||||
|
)
|
|
@ -1,12 +1,47 @@
|
||||||
package cn.fadinglight.routes
|
package cn.fadinglight.routes
|
||||||
|
|
||||||
|
import cn.fadinglight.dao.BillDao
|
||||||
|
import cn.fadinglight.dao.bill
|
||||||
|
import cn.fadinglight.libs.Resp
|
||||||
|
import cn.fadinglight.services.BillServiceImpl
|
||||||
|
import io.ktor.http.*
|
||||||
|
import io.ktor.server.application.*
|
||||||
|
import io.ktor.server.request.*
|
||||||
|
import io.ktor.server.response.*
|
||||||
import io.ktor.server.routing.*
|
import io.ktor.server.routing.*
|
||||||
|
import java.lang.Exception
|
||||||
|
|
||||||
fun Route.billRoute() {
|
fun Route.billRoute() {
|
||||||
|
val billService = BillServiceImpl()
|
||||||
route("/bill") {
|
route("/bill") {
|
||||||
get {}
|
get("/{year}/{month}") {
|
||||||
get("/{year}/{month}") {}
|
val year = call.parameters["year"]!!
|
||||||
post("/create") {}
|
val month = call.parameters["month"]!!
|
||||||
delete("/{year}/{month}/{day}") {}
|
call.respond(Resp.Ok(billService.getManyBills(year, month)).json())
|
||||||
|
}
|
||||||
|
|
||||||
|
get {
|
||||||
|
call.respond(status = HttpStatusCode.OK, Resp.Ok(billService.getManyBills()).json())
|
||||||
|
}
|
||||||
|
|
||||||
|
post {
|
||||||
|
try {
|
||||||
|
val bills = call.receive<List<BillDao>>().map(BillDao::bill)
|
||||||
|
val count = billService.addManyBills(bills)
|
||||||
|
call.respond(status = HttpStatusCode.Created, Resp.Ok(count).json())
|
||||||
|
} catch (e: Exception) {
|
||||||
|
call.respond(status = HttpStatusCode.Created, Resp.Error(e.message, code = -1).json())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete("{id}") {
|
||||||
|
val id = call.parameters["id"]!!.toInt()
|
||||||
|
val count = billService.deleteOneBill(id)
|
||||||
|
call.respond(status = HttpStatusCode.OK, Resp.Ok(count).json())
|
||||||
|
}
|
||||||
|
put {
|
||||||
|
val bill = call.receive<BillDao>().bill()
|
||||||
|
val count = billService.updateOneBill(bill)
|
||||||
|
call.respond(status = HttpStatusCode.OK, Resp.Ok(count).json())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -3,13 +3,16 @@ package cn.fadinglight.services
|
||||||
import cn.fadinglight.models.Bill
|
import cn.fadinglight.models.Bill
|
||||||
|
|
||||||
interface BillService {
|
interface BillService {
|
||||||
fun getMonthBills(year: String, month: String): List<Bill>
|
suspend fun getManyBills(year: String, month: String): List<Bill>
|
||||||
|
suspend fun getManyBills(year: String, month: String, day: String): List<Bill>
|
||||||
|
suspend fun getManyBills(): List<Bill>
|
||||||
|
suspend fun getOneBill(billId: Int): Bill
|
||||||
|
suspend fun addManyBills(bills: List<Bill>): Int
|
||||||
|
suspend fun addOneBill(bill: Bill): Int
|
||||||
|
suspend fun updateManyBills(bills: List<Bill>): Int
|
||||||
|
suspend fun updateOneBill(bill: Bill): Int
|
||||||
|
suspend fun deleteManyBills(bills: List<Bill>): Int
|
||||||
|
suspend fun deleteOneBill(billId: Int): Int
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class BillServiceImpl : BillService {
|
|
||||||
override fun getMonthBills(year: String, month: String): List<Bill> {
|
|
||||||
TODO("Not yet implemented")
|
|
||||||
}
|
|
||||||
}
|
|
87
src/main/kotlin/cn/fadinglight/services/BillServiceImpl.kt
Normal file
87
src/main/kotlin/cn/fadinglight/services/BillServiceImpl.kt
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
package cn.fadinglight.services
|
||||||
|
|
||||||
|
import cn.fadinglight.mapers.Bills
|
||||||
|
import cn.fadinglight.models.Bill
|
||||||
|
import cn.fadinglight.models.BillType
|
||||||
|
import org.jetbrains.exposed.sql.*
|
||||||
|
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
|
||||||
|
import org.jetbrains.exposed.sql.SqlExpressionBuilder.like
|
||||||
|
import org.jetbrains.exposed.sql.transactions.transaction
|
||||||
|
|
||||||
|
|
||||||
|
class BillServiceImpl : BillService {
|
||||||
|
private fun resultRowToBill(row: ResultRow) = Bill(
|
||||||
|
id = row[Bills.id].value,
|
||||||
|
type = BillType.valueOf(row[Bills.type]),
|
||||||
|
date = row[Bills.date],
|
||||||
|
money = row[Bills.money],
|
||||||
|
cls = row[Bills.cls],
|
||||||
|
label = row[Bills.label],
|
||||||
|
options = row[Bills.options]
|
||||||
|
)
|
||||||
|
|
||||||
|
override suspend fun getManyBills(year: String, month: String): List<Bill> = transaction {
|
||||||
|
Bills.select(Bills.date like "%${year}-${month}%").map(::resultRowToBill)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override suspend fun getManyBills(year: String, month: String, day: String): List<Bill> = transaction {
|
||||||
|
Bills.select(Bills.date eq "${year}-${month}-${day}").map(::resultRowToBill)
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun getManyBills(): List<Bill> = transaction {
|
||||||
|
Bills.selectAll().map(::resultRowToBill)
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun getOneBill(billId: Int): Bill = transaction {
|
||||||
|
Bills.select(Bills.id eq billId).single().let(::resultRowToBill)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override suspend fun addOneBill(bill: Bill): Int = transaction {
|
||||||
|
Bills.insertAndGetId {
|
||||||
|
it[type] = bill.type.name
|
||||||
|
it[date] = bill.date
|
||||||
|
it[cls] = bill.cls
|
||||||
|
it[label] = bill.label
|
||||||
|
it[money] = bill.money
|
||||||
|
it[options] = bill.options
|
||||||
|
}.value
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun addManyBills(bills: List<Bill>): Int = transaction {
|
||||||
|
Bills.batchInsert(bills) {
|
||||||
|
this[Bills.type] = it.type.name
|
||||||
|
this[Bills.date] = it.date
|
||||||
|
this[Bills.cls] = it.cls
|
||||||
|
this[Bills.label] = it.label
|
||||||
|
this[Bills.money] = it.money
|
||||||
|
this[Bills.options] = it.options
|
||||||
|
}.count()
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun updateManyBills(bills: List<Bill>): Int {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun updateOneBill(bill: Bill) = transaction {
|
||||||
|
Bills.update({ Bills.id eq bill.id }) {
|
||||||
|
it[type] = bill.type.name
|
||||||
|
it[date] = bill.date
|
||||||
|
it[money] = bill.money
|
||||||
|
it[cls] = bill.cls
|
||||||
|
it[label] = bill.label
|
||||||
|
it[options] = bill.options
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun deleteManyBills(bills: List<Bill>): Int {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun deleteOneBill(billId: Int): Int = transaction {
|
||||||
|
Bills.deleteWhere { Bills.id eq billId }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
12
src/main/kotlin/cn/fadinglight/services/LabelServe.kt
Normal file
12
src/main/kotlin/cn/fadinglight/services/LabelServe.kt
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
package cn.fadinglight.services
|
||||||
|
|
||||||
|
import cn.fadinglight.dao.LabelDao
|
||||||
|
import cn.fadinglight.models.Label
|
||||||
|
import cn.fadinglight.models.LabelType
|
||||||
|
|
||||||
|
interface LabelServe {
|
||||||
|
suspend fun getLabels(): List<LabelDao>
|
||||||
|
suspend fun addLabel(labelType: LabelType, label: Label): Boolean
|
||||||
|
suspend fun deleteLabel(labelId: Int): Boolean
|
||||||
|
suspend fun addCount(labelId: Int): Boolean
|
||||||
|
}
|
|
@ -4,7 +4,7 @@
|
||||||
<pattern>%d{YYYY-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
|
<pattern>%d{YYYY-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
|
||||||
</encoder>
|
</encoder>
|
||||||
</appender>
|
</appender>
|
||||||
<root level="trace">
|
<root level="INFO">
|
||||||
<appender-ref ref="STDOUT"/>
|
<appender-ref ref="STDOUT"/>
|
||||||
</root>
|
</root>
|
||||||
<logger name="io.netty" level="INFO"/>
|
<logger name="io.netty" level="INFO"/>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user