Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package eu.pretix.libpretixsync.models

import java.math.BigDecimal
import java.time.OffsetDateTime

data class Discount(
val id: Long,
val serverId: Long,
val eventSlug: String,
val active: Boolean,
val position: Long,
val allSalesChannels: Boolean,
val limitSalesChannels: List<String>,
val availableFrom: OffsetDateTime? = null,
val availableUntil: OffsetDateTime? = null,
val subeventMode: DiscountSubeventMode,
val subeventDateFrom: OffsetDateTime? = null,
val subeventDateUntil: OffsetDateTime? = null,
val conditionAllProducts: Boolean,
val conditionLimitProducts: List<Long>,
val conditionApplyToAddons: Boolean,
val conditionIgnoreVoucherDiscounted: Boolean,
val conditionMinCount: Int,
val conditionMinValue: BigDecimal,
val benefitSameProducts: Boolean,
val benefitLimitProducts: List<Long>,
val benefitDiscountMatchingPercent: BigDecimal,
val benefitOnlyApplyToCheapestNMatches: Int?,
val benefitApplyToAddons: Boolean,
val benefitIgnoreVoucherDiscounted: Boolean,
) {
enum class DiscountSubeventMode {
MIXED,
SAME,
DISTINCT
}

companion object {
/**
* only for use in test, not in production code, since the defaults might change server-side
* and we should not rely on them
*/
fun withDefaults(
id: Long = 1L,
serverId: Long = 1L,
eventSlug: String = "democon",
active: Boolean = true,
position: Long = 1L,
allSalesChannels: Boolean = true,
limitSalesChannels: List<String> = emptyList(),
availableFrom: OffsetDateTime? = null,
availableUntil: OffsetDateTime? = null,
subeventMode: DiscountSubeventMode = DiscountSubeventMode.MIXED,
subeventDateFrom: OffsetDateTime? = null,
subeventDateUntil: OffsetDateTime? = null,
conditionAllProducts: Boolean = true,
conditionLimitProducts: List<Long> = emptyList(),
conditionApplyToAddons: Boolean = true,
conditionIgnoreVoucherDiscounted: Boolean = false,
conditionMinCount: Int = 0,
conditionMinValue: BigDecimal = BigDecimal("0.00"),
benefitSameProducts: Boolean = true,
benefitLimitProducts: List<Long> = emptyList(),
benefitDiscountMatchingPercent: BigDecimal = BigDecimal("0.00"),
benefitOnlyApplyToCheapestNMatches: Int? = null,
benefitApplyToAddons: Boolean = true,
benefitIgnoreVoucherDiscounted: Boolean = false,
): Discount {
return Discount(
id = id,
serverId = serverId,
eventSlug = eventSlug,
active = active,
position = position,
allSalesChannels = allSalesChannels,
limitSalesChannels = limitSalesChannels,
availableFrom = availableFrom,
availableUntil = availableUntil,
subeventMode = subeventMode,
subeventDateFrom = subeventDateFrom,
subeventDateUntil = subeventDateUntil,
conditionAllProducts = conditionAllProducts,
conditionLimitProducts = conditionLimitProducts,
conditionApplyToAddons = conditionApplyToAddons,
conditionIgnoreVoucherDiscounted = conditionIgnoreVoucherDiscounted,
conditionMinCount = conditionMinCount,
conditionMinValue = conditionMinValue,
benefitSameProducts = benefitSameProducts,
benefitLimitProducts = benefitLimitProducts,
benefitDiscountMatchingPercent = benefitDiscountMatchingPercent,
benefitOnlyApplyToCheapestNMatches = benefitOnlyApplyToCheapestNMatches,
benefitApplyToAddons = benefitApplyToAddons,
benefitIgnoreVoucherDiscounted = benefitIgnoreVoucherDiscounted
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ data class ReceiptLine(
val giftCardId: Long? = null,
val giftCardSecret: String? = null,
val priceCalculatedFromNet: Boolean = false,
val linePriceGross: BigDecimal,
val discountId: Long? = null
) {
enum class Type(val value: String) {
PRODUCT_SALE("PRODUCT_SALE"),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package eu.pretix.libpretixsync.models.db

import eu.pretix.libpretixsync.models.Discount.DiscountSubeventMode
import eu.pretix.libpretixsync.sqldelight.Discount
import eu.pretix.libpretixsync.sqldelight.SafeOffsetDateTimeMapper
import org.json.JSONArray
import org.json.JSONObject
import java.math.BigDecimal
import eu.pretix.libpretixsync.models.Discount as DiscountModel

fun Discount.toModel(): DiscountModel {
val json = JSONObject(this.json_data)

return DiscountModel(
id = this.id,
serverId = this.server_id,
eventSlug = this.event_slug,
active = this.active,
position = this.position,
allSalesChannels = json.optBoolean("all_sales_channels", false),
limitSalesChannels = if (json.has("limit_sales_channels")) {
jsonArrayToStringList(json.getJSONArray("limit_sales_channels"))
} else if (json.has("sales_channels")) { // legacy pretix
jsonArrayToStringList(json.getJSONArray("sales_channels"))
} else {
emptyList()
},
availableFrom = SafeOffsetDateTimeMapper.decode(json, "available_from"),
availableUntil = SafeOffsetDateTimeMapper.decode(json, "available_until"),
subeventMode = when (json.getString("subevent_mode")) {
"mixed" -> DiscountSubeventMode.MIXED
"same" -> DiscountSubeventMode.SAME
"distinct" -> DiscountSubeventMode.DISTINCT
else -> DiscountSubeventMode.MIXED
},
subeventDateFrom = SafeOffsetDateTimeMapper.decode(json, "subevent_date_from"),
subeventDateUntil = SafeOffsetDateTimeMapper.decode(json, "subevent_date_until"),
conditionAllProducts = json.getBoolean("condition_all_products"),
conditionLimitProducts = jsonArrayToLongList(json.getJSONArray("condition_limit_products")),
conditionApplyToAddons = json.getBoolean("condition_apply_to_addons"),
conditionIgnoreVoucherDiscounted = json.getBoolean("condition_ignore_voucher_discounted"),
conditionMinCount = json.getInt("condition_min_count"),
conditionMinValue = BigDecimal(json.getString("condition_min_value")),
benefitSameProducts = json.optBoolean("benefit_same_products", true),
benefitLimitProducts = jsonArrayToLongList(json.optJSONArray("benefit_limit_products")),
benefitDiscountMatchingPercent = BigDecimal(json.getString("benefit_discount_matching_percent")),
benefitOnlyApplyToCheapestNMatches = if (json.isNull("benefit_only_apply_to_cheapest_n_matches"))
null
else
json.getInt("benefit_only_apply_to_cheapest_n_matches"),
benefitApplyToAddons = json.optBoolean("benefit_apply_to_addons", false),
benefitIgnoreVoucherDiscounted = json.optBoolean("benefit_ignore_voucher_discounted", true),
)
}

private fun jsonArrayToLongList(jsonArray: JSONArray?): List<Long> {
if (jsonArray == null) return emptyList()
return (0 until jsonArray.length()).map {
jsonArray.getLong(it)
}
}

private fun jsonArrayToStringList(jsonArray: JSONArray?): List<String> {
if (jsonArray == null) return emptyList()
return (0 until jsonArray.length()).map {
jsonArray.getString(it)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,6 @@ fun ReceiptLine.toModel() =
giftCardId = gift_card_id,
giftCardSecret = gift_card_secret,
priceCalculatedFromNet = price_calculated_from_net == true,
linePriceGross = line_price_gross ?: price,
discountId = discount_id,
)
Original file line number Diff line number Diff line change
Expand Up @@ -53,5 +53,7 @@ fun ReceiptLine.toJSON(): JSONObject {
jo.put("use_reusable_medium", use_reusable_medium)
jo.put("gift_card", gift_card_id)
jo.put("gift_card_secret", gift_card_secret)
jo.put("line_price_gross", line_price_gross ?: JSONObject.NULL)
jo.put("discount", discount_id ?: JSONObject.NULL)
return jo
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package eu.pretix.libpretixsync.sync

import app.cash.sqldelight.TransactionWithoutReturn
import app.cash.sqldelight.db.QueryResult
import eu.pretix.libpretixsync.api.PretixApi
import eu.pretix.libpretixsync.sqldelight.Discount
import eu.pretix.libpretixsync.sqldelight.SyncDatabase
import eu.pretix.libpretixsync.sync.SyncManager.ProgressFeedback
import org.joda.time.format.ISODateTimeFormat
import org.json.JSONObject

class DiscountSyncAdapter(
db: SyncDatabase,
fileStorage: FileStorage,
eventSlug: String,
api: PretixApi,
syncCycleId: String,
feedback: ProgressFeedback?,
) : BaseConditionalSyncAdapter<Discount, Long>(
db = db,
fileStorage = fileStorage,
eventSlug = eventSlug,
api = api,
syncCycleId = syncCycleId,
feedback = feedback,
) {

override fun getResourceName(): String = "discounts"

override fun getId(obj: Discount): Long = obj.server_id!!

override fun getId(obj: JSONObject): Long = obj.getLong("id")

override fun getJSON(obj: Discount): JSONObject = JSONObject(obj.json_data)

override fun queryKnownIDs(): MutableSet<Long> {
val res = mutableSetOf<Long>()
db.discountQueries.selectServerIdsByEventSlug(eventSlug)
.execute { cursor ->
while (cursor.next().value) {
val id = cursor.getLong(0)
?: throw RuntimeException("server_id column not available")

res.add(id)
}
QueryResult.Unit
}

return res
}

override fun insert(jsonobj: JSONObject) {
val availableFrom = if (!jsonobj.isNull("available_from")) {
ISODateTimeFormat.dateTimeParser().parseDateTime(jsonobj.getString("available_from")).toDate()
} else {
null
}
val availableUntil = if (!jsonobj.isNull("available_until")) {
ISODateTimeFormat.dateTimeParser().parseDateTime(jsonobj.getString("available_until")).toDate()
} else {
null
}
db.discountQueries.insert(
server_id = jsonobj.getLong("id"),
event_slug = eventSlug,
active = jsonobj.getBoolean("active"),
available_from = availableFrom,
available_until = availableUntil,
position = jsonobj.getLong("position"),
json_data = jsonobj.toString(),
)
}

override fun update(obj: Discount, jsonobj: JSONObject) {
val availableFrom = if (!jsonobj.isNull("available_from")) {
ISODateTimeFormat.dateTimeParser().parseDateTime(jsonobj.getString("available_from")).toDate()
} else {
null
}
val availableUntil = if (!jsonobj.isNull("available_until")) {
ISODateTimeFormat.dateTimeParser().parseDateTime(jsonobj.getString("available_until")).toDate()
} else {
null
}
db.discountQueries.updateFromJson(
event_slug = eventSlug,
active = jsonobj.getBoolean("active"),
available_from = availableFrom,
available_until = availableUntil,
position = jsonobj.getLong("position"),
json_data = jsonobj.toString(),
id = obj.id,
)
}

override fun delete(key: Long) {
db.discountQueries.deleteByServerId(key)
}

override fun runInTransaction(body: TransactionWithoutReturn.() -> Unit) {
db.discountQueries.transaction(false, body)
}

override fun runBatch(parameterBatch: List<Long>): List<Discount> =
db.discountQueries.selectByServerIdListAndEventSlug(
server_id = parameterBatch,
event_slug = eventSlug,
).executeAsList()
}
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,7 @@ protected void downloadData(ProgressFeedback feedback, Boolean skip_orders, Stri
download(new ItemSyncAdapter(db, fileStorage, eventSlug, api, configStore.getSyncCycleId(), feedback));
download(new QuestionSyncAdapter(db, fileStorage, eventSlug, api, configStore.getSyncCycleId(), feedback));
if (profile == Profile.PRETIXPOS) {
download(new DiscountSyncAdapter(db, fileStorage, eventSlug, api, configStore.getSyncCycleId(), feedback));
download(new QuotaSyncAdapter(db, fileStorage, eventSlug, api, configStore.getSyncCycleId(), feedback, subEvent));
download(new TaxRuleSyncAdapter(db, fileStorage, eventSlug, api, configStore.getSyncCycleId(), feedback));
download(new TicketLayoutSyncAdapter(db, fileStorage, eventSlug, api, configStore.getSyncCycleId(), feedback, salesChannel));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
selectById:
SELECT *
FROM Discount
WHERE id = ?;

selectByServerId:
SELECT *
FROM Discount
WHERE server_id = ?;

selectByEventSlug:
SELECT *
FROM Discount
WHERE event_slug = ?;

selectByServerIdListAndEventSlug:
SELECT *
FROM Discount
WHERE server_id IN ? AND event_slug = ?;

selectServerIdsByEventSlug:
SELECT server_id
FROM Discount
WHERE event_slug = ?;

deleteByServerId:
DELETE FROM Discount
WHERE server_id = ?;

insert:
INSERT INTO Discount
(
server_id,
event_slug,
active,
available_from,
available_until,
"position",
json_data
)
VALUES (
?,
?,
?,
?,
?,
?,
?
);

updateFromJson:
UPDATE Discount
SET
event_slug = ?,
active = ?,
available_from = ?,
available_until = ?,
"position" = ?,
json_data = ?
WHERE id = ?;
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,9 @@ INSERT INTO ReceiptLine (
type,
use_reusable_medium,
variation_id,
voucher_code
voucher_code,
line_price_gross,
discount_id
)
VALUES (
?,
Expand Down Expand Up @@ -104,5 +106,7 @@ VALUES (
?,
?,
?,
?,
?,
?
);
Original file line number Diff line number Diff line change
@@ -1 +1 @@
CREATE INDEX receipt_server_id ON Receipt(server_id);
CREATE INDEX receipt_server_id ON Receipt(server_id);
Original file line number Diff line number Diff line change
@@ -1 +1 @@
ALTER TABLE Cashier ADD COLUMN nfc_uid TEXT;
ALTER TABLE Cashier ADD COLUMN nfc_uid TEXT;
Loading
Loading