feat🔫: 部署完成
This commit is contained in:
parent
545edb747b
commit
dc3acb18ce
|
@ -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
|
||||||
|
|
|
@ -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())
|
|
@ -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())
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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") {
|
||||||
|
|
|
@ -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())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 }
|
||||||
|
?.sortedByDescending { it2 -> it2.count }
|
||||||
|
?.map { it2 -> it2.name }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?: emptyList()
|
||||||
|
val incomeLabels = labelGroups[LabelType.INCOME_CLASS]
|
||||||
|
?.sortedByDescending { it.count }
|
||||||
?.map(Label::vo)
|
?.map(Label::vo)
|
||||||
?: emptyList()
|
?: emptyList()
|
||||||
}
|
|
||||||
} ?: emptyList()
|
|
||||||
val incomeLabels = labelGroups[LabelType.INCOME_CLASS]
|
|
||||||
?.map(Label::vo) ?: emptyList()
|
|
||||||
|
|
||||||
return LabelGroup(income = incomeLabels, consume = consumeLabels)
|
return LabelGroup(income = incomeLabels, consume = consumeLabels)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(),
|
|
||||||
)
|
)
|
||||||
|
|
|
@ -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 ]
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
Loading…
Reference in New Issue
Block a user