feat🔫: 部署完成

This commit is contained in:
车厘子 2022-11-26 01:18:20 +08:00
parent 545edb747b
commit dc3acb18ce
13 changed files with 85 additions and 43 deletions

View File

@ -1,4 +1,13 @@
services: services:
back:
container_name: bill-ktor
image: registry.cn-hangzhou.aliyuncs.com/fadinglight/bill-ktor:dev
restart: always
environment:
JDBC_URL: mariadb://db/bill
ports:
- 80:4000
db: db:
container_name: bill-test-db container_name: bill-test-db
image: mariadb image: mariadb

View File

@ -4,18 +4,21 @@ import asyncio
mongo_url = 'http://www.fadinglight.cn:8088/list' mongo_url = 'http://www.fadinglight.cn:8088/list'
mysql_url = 'http://localhost:8080/api/v1/bill/' mysql_url = 'http://localhost:8080/api/v1/bill/'
async def getMongoBills(): async def getMongoBills():
async with aiohttp.ClientSession() as session: async with aiohttp.ClientSession() as session:
async with session.get(mongo_url) as response: async with session.get(mongo_url) as response:
data = await response.json() data = await response.json()
return data return data
async def postBillsToMysql(bills): async def postBillsToMysql(bills):
async with aiohttp.ClientSession() as session: async with aiohttp.ClientSession() as session:
async with session.post(mysql_url, json=bills) as response: async with session.post(mysql_url, json=bills) as response:
data = await response.json() data = await response.json()
return data return data
def dealOneBill(bill): def dealOneBill(bill):
bill.setdefault('type', 0) bill.setdefault('type', 0)
return dict( return dict(
@ -27,11 +30,19 @@ def dealOneBill(bill):
type="consume" if bill['type'] == 0 else "income", type="consume" if bill['type'] == 0 else "income",
) )
def transType(bill):
bill['type'] = 0 if bill['type'].lower() == 'income' else 1
return bill
async def main(): async def main():
data = await getMongoBills() data = await getMongoBills()
bills = data['data'] bills = data['data']
bills = list(map(dealOneBill, bills)) bills = list(map(dealOneBill, bills))
bills = list(map(transType, bills))
respData = await postBillsToMysql(bills) respData = await postBillsToMysql(bills)
print(respData) print(respData)
asyncio.run(main())
asyncio.run(main())

View File

@ -5,43 +5,50 @@ mongo_url = 'http://www.fadinglight.cn:8088/class'
mysql_url = 'http://localhost:8080/api/v1/label/' mysql_url = 'http://localhost:8080/api/v1/label/'
async def getMongoBills(): async def getMongoLabels():
async with aiohttp.ClientSession() as session: async with aiohttp.ClientSession() as session:
async with session.get(mongo_url) as response: async with session.get(mongo_url) as response:
data = await response.json() data = await response.json()
return data return data
async def postBillsToMysql(bills): async def postLabelsToMysql(label):
async with aiohttp.ClientSession() as session: async with aiohttp.ClientSession() as session:
async with session.post(mysql_url, json=bills) as response: async with session.post(mysql_url, json=label) as response:
data = await response.json() data = await response.json()
return data return data
def dealOneBill(bill): def newLabel(name, type=0, relativeId=None):
bill.setdefault('type', 0)
return dict( return dict(
money=bill['money'], name=name,
cls=bill['cls'], type=type,
label=bill['label'], relativeId=relativeId,
date=bill['date'],
options=bill['options'],
type="consume" if bill['type'] == 0 else "income",
) )
async def main(): async def main():
data = await getMongoBills() data = await getMongoLabels()
labels = data['data'] labels = data['data']
consumeLabels = labels['consume'] consumeLabels = labels['consume']
incomeLabels = labels['income'] incomeLabels = labels['income']
# for i in consumeLabels: print(consumeLabels)
for i in incomeLabels:
label = newLabel(i, type=2)
# print(label)
await postLabelsToMysql(label)
for i in consumeLabels:
subLabels = consumeLabels[i]
label = newLabel(i, type=0)
resp = await postLabelsToMysql(label)
id = resp['data']
print(id)
for j in subLabels:
sub_label = newLabel(j, type=1, relativeId=id)
await postLabelsToMysql(sub_label)
# bills = list(map(dealOneBill, bills))
# respData = await postBillsToMysql(bills)
# print(respData)
asyncio.run(main()) asyncio.run(main())

View File

@ -9,10 +9,10 @@ sealed class Resp<T> {
abstract fun json(): RespData<T> abstract fun json(): RespData<T>
class Ok<T>(private val data: T) : Resp<T>() { class Ok<T>(private val data: T) : Resp<T>() {
override fun json() = RespData(code = 0, data = data, message = null) override fun json() = RespData(code = 0, data = data, message = "")
} }
class Error(private val message: String?, val code: Int=-1) : Resp<Unit>() { class Error(private val message: String? = "", val code: Int = -1) : Resp<Unit>() {
override fun json(): RespData<Unit> = RespData(code = code, data = null, message = message) override fun json(): RespData<Unit> = RespData(code = code, data = null, message = message)
} }

View File

@ -2,15 +2,15 @@ package cn.fadinglight.models
enum class LabelType { enum class LabelType {
CLASS, CONSUME_CLASS,
LABEL, CONSUME_LABEL,
INCOME_CLASS; INCOME_CLASS;
companion object { companion object {
fun of(n: Int) = when (n) { fun of(n: Int) = when (n) {
0 -> LabelType.CLASS 0 -> CONSUME_CLASS
1 -> LabelType.LABEL 1 -> CONSUME_LABEL
2 -> LabelType.INCOME_CLASS 2 -> INCOME_CLASS
else -> throw IllegalArgumentException("error code $n") else -> throw IllegalArgumentException("error code $n")
} }
} }

View File

@ -14,6 +14,10 @@ const val HIKARI_CONFIG_KEY = "ktor.hikariConfig"
fun Application.configureDatabase() { fun Application.configureDatabase() {
val configPath = environment.config.property(HIKARI_CONFIG_KEY).getString() val configPath = environment.config.property(HIKARI_CONFIG_KEY).getString()
val dbConfig = HikariConfig(configPath) val dbConfig = HikariConfig(configPath)
val envs = System.getenv()
if (envs.containsKey("JDBC_URL")) {
dbConfig.jdbcUrl = envs["JDBC_URL"]
}
val dataSource = HikariDataSource(dbConfig) val dataSource = HikariDataSource(dbConfig)
Database.connect(dataSource) Database.connect(dataSource)
createTables() createTables()

View File

@ -11,7 +11,7 @@ fun Application.configureRouting() {
routing { routing {
route("/") { route("/") {
get { get {
call.respond(LabelType.LABEL) call.respond("Hello world")
} }
} }
route("/api/v1") { route("/api/v1") {

View File

@ -37,6 +37,7 @@ fun Route.billRoute() {
}.onSuccess { }.onSuccess {
call.respond(Resp.Ok(it).json()) call.respond(Resp.Ok(it).json())
}.onFailure { }.onFailure {
it.printStackTrace()
call.respond(Resp.Error(it.message, code = -1).json()) call.respond(Resp.Error(it.message, code = -1).json())
} }
} }

View File

@ -4,12 +4,15 @@ import cn.fadinglight.mapers.Bills
import cn.fadinglight.mapers.Labels import cn.fadinglight.mapers.Labels
import cn.fadinglight.models.Bill import cn.fadinglight.models.Bill
import cn.fadinglight.models.BillType import cn.fadinglight.models.BillType
import cn.fadinglight.models.LabelType
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.awaitAll import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.coroutineScope
import org.jetbrains.exposed.sql.* import org.jetbrains.exposed.sql.*
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
import org.jetbrains.exposed.sql.SqlExpressionBuilder.inList
import org.jetbrains.exposed.sql.SqlExpressionBuilder.like import org.jetbrains.exposed.sql.SqlExpressionBuilder.like
import org.jetbrains.exposed.sql.SqlExpressionBuilder.neq
import org.jetbrains.exposed.sql.transactions.experimental.suspendedTransactionAsync import org.jetbrains.exposed.sql.transactions.experimental.suspendedTransactionAsync
import org.jetbrains.exposed.sql.transactions.transaction import org.jetbrains.exposed.sql.transactions.transaction
@ -78,7 +81,6 @@ class BillServiceImpl : BillService {
} }
override suspend fun addManyBills(bills: List<Bill>): Int = transaction { override suspend fun addManyBills(bills: List<Bill>): Int = transaction {
val newBills = Bills val newBills = Bills
.batchInsert(bills) { .batchInsert(bills) {
this[Bills.type] = it.type.name this[Bills.type] = it.type.name
@ -91,13 +93,19 @@ class BillServiceImpl : BillService {
.map(::resultRowToBill) .map(::resultRowToBill)
newBills.forEach { newBills.forEach {
val classId = Labels val classId = Labels
.select(Labels.name eq it.cls) .select(
(Labels.name eq it.cls) and (Labels.type inList listOf(
LabelType.CONSUME_CLASS,
LabelType.INCOME_CLASS
).map(LabelType::toString))
)
.map { it2 -> it2[Labels.id].value } .map { it2 -> it2[Labels.id].value }
.single() .singleOrNull()
val labelId = Labels val labelId = if (it.type == BillType.CONSUME) Labels
.select(Labels.name eq it.label) .select((Labels.name eq it.label) and (Labels.type eq LabelType.CONSUME_LABEL.toString()))
.map { it2 -> it2[Labels.id].value } .map { it2 -> it2[Labels.id].value }
.single() .singleOrNull()
else null
Labels.update({ (Labels.id eq labelId) or (Labels.id eq classId) }) { Labels.update({ (Labels.id eq labelId) or (Labels.id eq classId) }) {
with(SqlExpressionBuilder) { with(SqlExpressionBuilder) {
it[count] = count + 1 it[count] = count + 1

View File

@ -24,17 +24,21 @@ class LabelServiceImpl : LabelService {
.map(::resultRowToLabel) .map(::resultRowToLabel)
.groupBy { it.type } .groupBy { it.type }
} }
val consumeLabels = labelGroups[LabelType.CLASS] val consumeLabels = labelGroups[LabelType.CONSUME_CLASS]
?.sortedByDescending { it.count }
?.map { ?.map {
it.vo().apply { it.vo().apply {
this.labels = labelGroups[LabelType.LABEL] this.labels = labelGroups[LabelType.CONSUME_LABEL]
?.filter { it2 -> it2.relativeId == it.id } ?.filter { it2 -> it2.relativeId == it.id }
?.map(Label::vo) ?.sortedByDescending { it2 -> it2.count }
?: emptyList() ?.map { it2 -> it2.name }
} }
} ?: emptyList() }
?: emptyList()
val incomeLabels = labelGroups[LabelType.INCOME_CLASS] val incomeLabels = labelGroups[LabelType.INCOME_CLASS]
?.map(Label::vo) ?: emptyList() ?.sortedByDescending { it.count }
?.map(Label::vo)
?: emptyList()
return LabelGroup(income = incomeLabels, consume = consumeLabels) return LabelGroup(income = incomeLabels, consume = consumeLabels)
} }

View File

@ -23,8 +23,7 @@ fun LabelPost.label() = Label(
@Serializable @Serializable
data class LabelVO( data class LabelVO(
val name: String, val name: String,
val count: Int, var labels: List<String>?,
var labels: List<LabelVO>?,
) )
@Serializable @Serializable
@ -36,6 +35,5 @@ data class LabelGroup(
fun Label.vo() = LabelVO( fun Label.vo() = LabelVO(
name = name, name = name,
count = count, labels = null,
labels = emptyList(),
) )

View File

@ -2,7 +2,7 @@ ktor {
development = true development = true
deployment { deployment {
port = 8080 port = 4000
port = ${?PORT} port = ${?PORT}
watch = [ bill-ktor ] watch = [ bill-ktor ]
} }

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://www.fadinglight.cn:3306/bill
dataSource.user=root dataSource.user=root
dataSource.password=123456 dataSource.password=123456