Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • main
1 result

Target

Select target project
  • justJanne/meteroid
1 result
Select Git revision
  • main
1 result
Show changes
{
"formatVersion": 1,
"database": {
"version": 3,
"identityHash": "f794acceadd9ed28da1b218972b5e530",
"entities": [
{
"tableName": "Drink",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`serverId` INTEGER NOT NULL, `drinkId` INTEGER NOT NULL, `active` INTEGER NOT NULL, `name` TEXT NOT NULL, `volume` TEXT NOT NULL, `caffeine` INTEGER, `price` TEXT NOT NULL, `logoUrl` TEXT NOT NULL, PRIMARY KEY(`serverId`, `drinkId`), FOREIGN KEY(`serverId`) REFERENCES `Server`(`serverId`) ON UPDATE NO ACTION ON DELETE NO ACTION )",
"fields": [
{
"fieldPath": "serverId",
"columnName": "serverId",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "drinkId",
"columnName": "drinkId",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "active",
"columnName": "active",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "name",
"columnName": "name",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "volume",
"columnName": "volume",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "caffeine",
"columnName": "caffeine",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "price",
"columnName": "price",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "logoUrl",
"columnName": "logoUrl",
"affinity": "TEXT",
"notNull": true
}
],
"primaryKey": {
"autoGenerate": false,
"columnNames": [
"serverId",
"drinkId"
]
},
"indices": [],
"foreignKeys": [
{
"table": "Server",
"onDelete": "NO ACTION",
"onUpdate": "NO ACTION",
"columns": [
"serverId"
],
"referencedColumns": [
"serverId"
]
}
]
},
{
"tableName": "Server",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`serverId` INTEGER NOT NULL, `name` TEXT, `url` TEXT NOT NULL, `logoUrl` TEXT, PRIMARY KEY(`serverId`))",
"fields": [
{
"fieldPath": "serverId",
"columnName": "serverId",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "name",
"columnName": "name",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "url",
"columnName": "url",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "logoUrl",
"columnName": "logoUrl",
"affinity": "TEXT",
"notNull": false
}
],
"primaryKey": {
"autoGenerate": false,
"columnNames": [
"serverId"
]
},
"indices": [],
"foreignKeys": []
},
{
"tableName": "User",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`serverId` INTEGER NOT NULL, `userId` INTEGER NOT NULL, `active` INTEGER NOT NULL, `name` TEXT NOT NULL, `email` TEXT NOT NULL, `balance` TEXT NOT NULL, `audit` INTEGER NOT NULL, `redirect` INTEGER NOT NULL, PRIMARY KEY(`serverId`, `userId`), FOREIGN KEY(`serverId`) REFERENCES `Server`(`serverId`) ON UPDATE NO ACTION ON DELETE NO ACTION )",
"fields": [
{
"fieldPath": "serverId",
"columnName": "serverId",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "userId",
"columnName": "userId",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "active",
"columnName": "active",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "name",
"columnName": "name",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "email",
"columnName": "email",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "balance",
"columnName": "balance",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "audit",
"columnName": "audit",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "redirect",
"columnName": "redirect",
"affinity": "INTEGER",
"notNull": true
}
],
"primaryKey": {
"autoGenerate": false,
"columnNames": [
"serverId",
"userId"
]
},
"indices": [],
"foreignKeys": [
{
"table": "Server",
"onDelete": "NO ACTION",
"onUpdate": "NO ACTION",
"columns": [
"serverId"
],
"referencedColumns": [
"serverId"
]
}
]
},
{
"tableName": "PinnedUser",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`serverId` INTEGER NOT NULL, `userId` INTEGER NOT NULL, PRIMARY KEY(`serverId`, `userId`), FOREIGN KEY(`serverId`) REFERENCES `Server`(`serverId`) ON UPDATE NO ACTION ON DELETE NO ACTION , FOREIGN KEY(`serverId`, `userId`) REFERENCES `User`(`serverId`, `userId`) ON UPDATE NO ACTION ON DELETE NO ACTION )",
"fields": [
{
"fieldPath": "serverId",
"columnName": "serverId",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "userId",
"columnName": "userId",
"affinity": "INTEGER",
"notNull": true
}
],
"primaryKey": {
"autoGenerate": false,
"columnNames": [
"serverId",
"userId"
]
},
"indices": [],
"foreignKeys": [
{
"table": "Server",
"onDelete": "NO ACTION",
"onUpdate": "NO ACTION",
"columns": [
"serverId"
],
"referencedColumns": [
"serverId"
]
},
{
"table": "User",
"onDelete": "NO ACTION",
"onUpdate": "NO ACTION",
"columns": [
"serverId",
"userId"
],
"referencedColumns": [
"serverId",
"userId"
]
}
]
},
{
"tableName": "Transaction",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`serverId` INTEGER NOT NULL, `transactionId` INTEGER NOT NULL, `userId` INTEGER NOT NULL, `drinkId` INTEGER, `difference` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, PRIMARY KEY(`serverId`, `transactionId`), FOREIGN KEY(`serverId`) REFERENCES `Server`(`serverId`) ON UPDATE NO ACTION ON DELETE NO ACTION , FOREIGN KEY(`serverId`, `userId`) REFERENCES `User`(`serverId`, `userId`) ON UPDATE NO ACTION ON DELETE NO ACTION , FOREIGN KEY(`serverId`, `drinkId`) REFERENCES `Drink`(`serverId`, `drinkId`) ON UPDATE NO ACTION ON DELETE NO ACTION )",
"fields": [
{
"fieldPath": "serverId",
"columnName": "serverId",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "transactionId",
"columnName": "transactionId",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "userId",
"columnName": "userId",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "drinkId",
"columnName": "drinkId",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "difference",
"columnName": "difference",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "timestamp",
"columnName": "timestamp",
"affinity": "INTEGER",
"notNull": true
}
],
"primaryKey": {
"autoGenerate": false,
"columnNames": [
"serverId",
"transactionId"
]
},
"indices": [
{
"name": "index_Transaction_serverId_userId",
"unique": false,
"columnNames": [
"serverId",
"userId"
],
"orders": [],
"createSql": "CREATE INDEX IF NOT EXISTS `index_Transaction_serverId_userId` ON `${TABLE_NAME}` (`serverId`, `userId`)"
},
{
"name": "index_Transaction_serverId_drinkId",
"unique": false,
"columnNames": [
"serverId",
"drinkId"
],
"orders": [],
"createSql": "CREATE INDEX IF NOT EXISTS `index_Transaction_serverId_drinkId` ON `${TABLE_NAME}` (`serverId`, `drinkId`)"
}
],
"foreignKeys": [
{
"table": "Server",
"onDelete": "NO ACTION",
"onUpdate": "NO ACTION",
"columns": [
"serverId"
],
"referencedColumns": [
"serverId"
]
},
{
"table": "User",
"onDelete": "NO ACTION",
"onUpdate": "NO ACTION",
"columns": [
"serverId",
"userId"
],
"referencedColumns": [
"serverId",
"userId"
]
},
{
"table": "Drink",
"onDelete": "NO ACTION",
"onUpdate": "NO ACTION",
"columns": [
"serverId",
"drinkId"
],
"referencedColumns": [
"serverId",
"drinkId"
]
}
]
}
],
"views": [],
"setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'f794acceadd9ed28da1b218972b5e530')"
]
}
}
\ No newline at end of file
......@@ -24,17 +24,21 @@
package de.chaosdorf.meteroid
import androidx.room.AutoMigration
import androidx.room.Database
import androidx.room.RoomDatabase
import androidx.room.TypeConverters
import de.chaosdorf.meteroid.model.Drink
import de.chaosdorf.meteroid.model.DrinkRepository
import de.chaosdorf.meteroid.model.Purchase
import de.chaosdorf.meteroid.model.PurchaseRepository
import de.chaosdorf.meteroid.model.PinnedUser
import de.chaosdorf.meteroid.model.PinnedUserRepository
import de.chaosdorf.meteroid.model.Server
import de.chaosdorf.meteroid.model.ServerRepository
import de.chaosdorf.meteroid.model.Transaction
import de.chaosdorf.meteroid.model.TransactionRepository
import de.chaosdorf.meteroid.model.User
import de.chaosdorf.meteroid.model.UserRepository
import de.chaosdorf.meteroid.util.BigDecimalTypeConverter
import de.chaosdorf.meteroid.util.KotlinDatetimeTypeConverter
@Database(
......@@ -43,14 +47,21 @@ import de.chaosdorf.meteroid.util.KotlinDatetimeTypeConverter
Drink::class,
Server::class,
User::class,
Purchase::class
PinnedUser::class,
Transaction::class
],
autoMigrations = [],
)
@TypeConverters(value = [KotlinDatetimeTypeConverter::class])
@TypeConverters(
value = [
KotlinDatetimeTypeConverter::class,
BigDecimalTypeConverter::class
]
)
abstract class MeteroidDatabase : RoomDatabase() {
abstract fun drinks(): DrinkRepository
abstract fun server(): ServerRepository
abstract fun users(): UserRepository
abstract fun purchases(): PurchaseRepository
abstract fun pinnedUsers(): PinnedUserRepository
abstract fun transactions(): TransactionRepository
}
/*
* The MIT License (MIT)
*
* Copyright (c) 2013-2023 Chaosdorf e.V.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package de.chaosdorf.meteroid.model
data class AccountInfo(
val server: Server,
val user: User?,
val pinned: Boolean
)
......@@ -30,16 +30,16 @@ import androidx.room.ForeignKey
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import de.chaosdorf.mete.DrinkId
import de.chaosdorf.mete.v1.DrinkModelV1
import de.chaosdorf.mete.model.DrinkId
import de.chaosdorf.mete.model.DrinkModel
import kotlinx.coroutines.flow.Flow
import kotlinx.datetime.Instant
import java.math.BigDecimal
import java.net.URI
@Entity(
primaryKeys = ["serverId", "drinkId"],
foreignKeys = [
ForeignKey(Server::class, ["serverId"], ["serverId"], onDelete = ForeignKey.CASCADE)
ForeignKey(Server::class, ["serverId"], ["serverId"])
]
)
data class Drink(
......@@ -47,33 +47,26 @@ data class Drink(
val drinkId: DrinkId,
val active: Boolean,
val name: String,
val volume: Double,
val volume: BigDecimal,
val caffeine: Int?,
val price: Double,
val createdAt: Instant,
val updatedAt: Instant,
val logoUrl: String,
val logoFileName: String,
val logoContentType: String,
val logoFileSize: Long,
val logoUpdatedAt: Instant
val price: BigDecimal,
val logoUrl: String?,
) {
val originalLogoUrl
get() = logoUrl?.replace("/thumb/", "/original/")
companion object {
fun fromModelV1(server: Server, value: DrinkModelV1) = Drink(
fun fromModel(server: Server, value: DrinkModel) = Drink(
server.serverId,
value.id,
value.drinkId,
value.active,
value.name,
value.bottleSize,
value.volume,
value.caffeine,
value.price,
value.createdAt,
value.updatedAt,
URI.create(server.url).resolve(value.logoUrl).toString(),
value.logoFileName,
value.logoContentType,
value.logoFileSize,
value.logoUpdatedAt
value.logoUrl?.let {
URI.create(server.url).resolve(it).toString()
}
)
}
}
......@@ -89,7 +82,7 @@ interface DrinkRepository {
@Query("SELECT * FROM Drink WHERE serverId = :serverId ORDER BY NAME ASC")
suspend fun getAll(serverId: ServerId): List<Drink>
@Query("SELECT * FROM Drink WHERE serverId = :serverId ORDER BY NAME ASC")
@Query("SELECT * FROM Drink WHERE serverId = :serverId ORDER BY ACTIVE DESC, NAME ASC")
fun getAllFlow(serverId: ServerId): Flow<List<Drink>>
@Insert(onConflict = OnConflictStrategy.REPLACE)
......
/*
* The MIT License (MIT)
*
* Copyright (c) 2013-2023 Chaosdorf e.V.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package de.chaosdorf.meteroid.model
import androidx.room.Dao
import androidx.room.Entity
import androidx.room.ForeignKey
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import de.chaosdorf.mete.model.UserId
import kotlinx.coroutines.flow.Flow
@Entity(
primaryKeys = ["serverId", "userId"],
foreignKeys = [
ForeignKey(Server::class, ["serverId"], ["serverId"]),
ForeignKey(User::class, ["serverId", "userId"], ["serverId", "userId"])
]
)
data class PinnedUser(
val serverId: ServerId,
val userId: UserId
)
@Dao
interface PinnedUserRepository {
@Query("SELECT 1 FROM PinnedUser WHERE serverId = :serverId AND userId = :userId LIMIT 1")
suspend fun isPinned(serverId: ServerId, userId: UserId): Boolean
@Query("SELECT 1 FROM PinnedUser WHERE serverId = :serverId AND userId = :userId LIMIT 1")
fun isPinnedFlow(serverId: ServerId, userId: UserId): Flow<Boolean>
@Query("SELECT userId FROM PinnedUser WHERE serverId = :serverId")
suspend fun getAll(serverId: ServerId): List<UserId>
@Query("SELECT userId FROM PinnedUser WHERE serverId = :serverId")
fun getAllFlow(serverId: ServerId): Flow<List<UserId>>
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun save(user: PinnedUser)
@Query("DELETE FROM PinnedUser WHERE serverId = :serverId AND userId = :userId")
suspend fun delete(serverId: ServerId, userId: UserId)
@Query("DELETE FROM PinnedUser WHERE serverId = :serverId")
suspend fun deleteAll(serverId: ServerId)
}
......@@ -31,62 +31,71 @@ import androidx.room.Index
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import de.chaosdorf.mete.AuditEntryId
import de.chaosdorf.mete.DrinkId
import de.chaosdorf.mete.UserId
import de.chaosdorf.mete.v1.AuditEntryModelV1
import de.chaosdorf.mete.model.DrinkId
import de.chaosdorf.mete.model.TransactionId
import de.chaosdorf.mete.model.TransactionModel
import de.chaosdorf.mete.model.UserId
import kotlinx.coroutines.flow.Flow
import kotlinx.datetime.Instant
import java.math.BigDecimal
@Entity(
primaryKeys = ["serverId", "purchaseId"],
primaryKeys = ["serverId", "transactionId"],
foreignKeys = [
ForeignKey(Server::class, ["serverId"], ["serverId"], onDelete = ForeignKey.CASCADE),
ForeignKey(User::class, ["serverId", "userId"], ["serverId", "userId"], onDelete = ForeignKey.CASCADE),
ForeignKey(Drink::class, ["serverId", "drinkId"], ["serverId", "drinkId"], onDelete = ForeignKey.NO_ACTION)
ForeignKey(Server::class, ["serverId"], ["serverId"]),
ForeignKey(
User::class,
["serverId", "userId"],
["serverId", "userId"]
),
ForeignKey(
Drink::class,
["serverId", "drinkId"],
["serverId", "drinkId"]
)
],
indices = [
Index("serverId", "userId"),
Index("serverId", "drinkId")
]
)
data class Purchase(
data class Transaction(
val serverId: ServerId,
val purchaseId: AuditEntryId,
val transactionId: TransactionId,
val userId: UserId,
val drinkId: DrinkId?,
val difference: Double,
val createdAt: Instant
val difference: BigDecimal,
val timestamp: Instant
) {
companion object {
fun fromModelV1(server: Server, userId: UserId, value: AuditEntryModelV1) = Purchase(
fun fromModel(server: Server, userId: UserId, value: TransactionModel) = Transaction(
server.serverId,
value.id,
value.transactionId,
userId,
value.drink,
value.drinkId,
value.difference,
value.createdAt
value.timestamp
)
}
}
@Dao
interface PurchaseRepository {
@Query("SELECT * FROM Purchase WHERE serverId = :serverId AND userId = :userId ORDER BY createdAt DESC")
suspend fun getAll(serverId: ServerId, userId: UserId): List<Purchase>
interface TransactionRepository {
@Query("SELECT * FROM `Transaction` WHERE serverId = :serverId AND userId = :userId ORDER BY timestamp DESC")
suspend fun getAll(serverId: ServerId, userId: UserId): List<Transaction>
@Query("SELECT * FROM Purchase WHERE serverId = :serverId AND userId = :userId ORDER BY createdAt DESC")
fun getAllFlow(serverId: ServerId, userId: UserId): Flow<List<Purchase>>
@Query("SELECT * FROM `Transaction` WHERE serverId = :serverId AND userId = :userId ORDER BY timestamp DESC")
fun getAllFlow(serverId: ServerId, userId: UserId): Flow<List<Transaction>>
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun save(purchase: Purchase)
suspend fun save(transaction: Transaction)
@Query("DELETE FROM Purchase WHERE serverId = :serverId AND purchaseId = :purchaseId")
suspend fun delete(serverId: ServerId, purchaseId: AuditEntryId)
@Query("DELETE FROM `Transaction` WHERE serverId = :serverId AND transactionId = :transactionId")
suspend fun delete(serverId: ServerId, transactionId: TransactionId)
@Query("DELETE FROM Purchase WHERE serverId = :serverId AND userId = :userId")
@Query("DELETE FROM `Transaction` WHERE serverId = :serverId AND userId = :userId")
suspend fun deleteAll(serverId: ServerId, userId: UserId)
@Query("DELETE FROM Purchase WHERE serverId = :serverId")
@Query("DELETE FROM `Transaction` WHERE serverId = :serverId")
suspend fun deleteAll(serverId: ServerId)
}