feat🔫: 账单的基本操作

This commit is contained in:
车厘子 2022-10-28 05:02:55 +08:00
parent 371359430f
commit 76e1f5d9ec
16 changed files with 345 additions and 125 deletions

75
.gitignore vendored
View File

@ -1,36 +1,39 @@
.gradle .gradle
build/ build/
!gradle/wrapper/gradle-wrapper.jar !gradle/wrapper/gradle-wrapper.jar
!**/src/main/**/build/ !**/src/main/**/build/
!**/src/test/**/build/ !**/src/test/**/build/
### STS ### ### STS ###
.apt_generated .apt_generated
.classpath .classpath
.factorypath .factorypath
.project .project
.settings .settings
.springBeans .springBeans
.sts4-cache .sts4-cache
bin/ bin/
!**/src/main/**/bin/ !**/src/main/**/bin/
!**/src/test/**/bin/ !**/src/test/**/bin/
### IntelliJ IDEA ### ### IntelliJ IDEA ###
.idea .idea
*.iws *.iws
*.iml *.iml
*.ipr *.ipr
out/ out/
!**/src/main/**/out/ !**/src/main/**/out/
!**/src/test/**/out/ !**/src/test/**/out/
### NetBeans ### ### NetBeans ###
/nbproject/private/ /nbproject/private/
/nbbuild/ /nbbuild/
/dist/ /dist/
/nbdist/ /nbdist/
/.nb-gradle/ /.nb-gradle/
### VS Code ### ### VS Code ###
.vscode/ .vscode/
### Fleet ###
.fleet

View File

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

View File

@ -1,19 +1,21 @@
services: services:
db: db:
image: mariadb container_name: bill-test-db
restart: always image: mariadb
environment: restart: always
MARIADB_ROOT_PASSWORD: 123456 environment:
ports: MARIADB_ROOT_PASSWORD: 123456
- 3306:3306 ports:
volumes: - 3306:3306
- db-data:/var/lib/mysql volumes:
- db-data:/var/lib/mysql
adminer:
image: adminer adminer:
restart: always container_name: bill-test-adminer
ports: image: adminer
- 8081:8080 restart: always
ports:
volumes: - 8081:8080
volumes:
db-data: db-data:

View File

@ -14,5 +14,5 @@ fun Application.module() {
configureRouting() configureRouting()
configureSession() configureSession()
configureWebSocket() configureWebSocket()
// configureDatabase() configureDatabase()
} }

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

View File

@ -0,0 +1,7 @@
package cn.fadinglight.dao
data class LabelDao(
val name: String,
val count: Int,
val labels: List<LabelDao>?
)

View 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)
}
}

View File

@ -1,19 +1,19 @@
package cn.fadinglight.mapers 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 name = varchar("name", 15) val type = varchar("type", 15)
val type = integer("type") val name = varchar("name", 15)
val relativeId = integer("relative_id") val relativeId = integer("relative_id")
val nums = integer("nums") val nums = integer("nums")
} }

View File

@ -1,15 +1,19 @@
package cn.fadinglight.models package cn.fadinglight.models
enum class BillType { import kotlinx.serialization.Serializable
Consume,
Income,
} enum class BillType {
Consume,
data class Bill( Income,
var id: Int?, }
var type: BillType, @Serializable
val money: Int, data class Bill(
val cls: String, var id: Int?,
val label: String, val type: BillType,
val options: String?, val date: String,
) val money: Int,
val cls: String,
val label: String,
val options: String?,
)

View File

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

View File

@ -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())
}
} }
} }

View File

@ -1,15 +1,18 @@
package cn.fadinglight.services 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
class BillServiceImpl : BillService { suspend fun addOneBill(bill: Bill): Int
override fun getMonthBills(year: String, month: String): List<Bill> { suspend fun updateManyBills(bills: List<Bill>): Int
TODO("Not yet implemented") suspend fun updateOneBill(bill: Bill): Int
} suspend fun deleteManyBills(bills: List<Bill>): Int
} suspend fun deleteOneBill(billId: Int): Int
}

View 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 }
}
}

View 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
}

View File

@ -1,4 +1,4 @@
driverClassName=org.mariadb.jdbc.Driver driverClassName=org.mariadb.jdbc.Driver
jdbcUrl=jdbc:mariadb://localhost:3306/bill jdbcUrl=jdbc:mariadb://localhost:3306/bill
dataSource.user=root dataSource.user=root
dataSource.password=123456 dataSource.password=123456

View File

@ -1,12 +1,12 @@
<configuration> <configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder> <encoder>
<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"/>
<logger name="com.zaxxer.hikari" level="ERROR"/> <logger name="com.zaxxer.hikari" level="ERROR"/>
</configuration> </configuration>