add unpaid14 to the premium unlock api

This commit is contained in:
Jonas Lochmann
2026-06-15 02:00:00 +02:00
parent b2bcc3715f
commit 235115168f
4 changed files with 42 additions and 11 deletions
+1
View File
@@ -101,6 +101,7 @@ request properties: ``purchaseToken``, ``purchaseId`` and ``dryRun``
- ``purchasetoken`` is a string which the client shows at the purchase screen
- ``purchaseId`` is the ID that is used at the bill
- ``dryRun`` is a boolean; setting true will skip the actual unlocking
- ``type`` is a string and must be ``year``, ``month`` or ``unpaid14``
### response
+8 -2
View File
@@ -141,7 +141,8 @@ export const createAdminRouter = ({ database, websocket, eventHandler }: {
typeof req.body !== 'object' ||
typeof req.body.purchaseToken !== 'string' ||
typeof req.body.purchaseId !== 'string' ||
typeof req.body.dryRun !== 'boolean'
typeof req.body.dryRun !== 'boolean' ||
typeof req.body.type !== 'string'
) {
throw new BadRequest()
}
@@ -149,6 +150,11 @@ export const createAdminRouter = ({ database, websocket, eventHandler }: {
const purchaseToken: string = req.body.purchaseToken
const purchaseId: string = req.body.purchaseId
const dryRun: boolean = req.body.dryRun
const type: string = req.body.type
if (type !== 'month' && type !== 'year' && type !== 'unpaid14') {
throw new BadRequest()
}
const tokenContent = await verifyIdentitifyToken(purchaseToken)
@@ -259,7 +265,7 @@ export const createAdminRouter = ({ database, websocket, eventHandler }: {
await addPurchase({
database,
familyId: tokenContent.familyId,
type: 'year',
type,
service: 'directpurchase',
transactionId: purchaseId,
websocket,
+3 -3
View File
@@ -1,6 +1,6 @@
/*
* server component for the TimeLimit App
* Copyright (C) 2019 - 2022 Jonas Lochmann
* Copyright (C) 2019 - 2026 Jonas Lochmann
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
@@ -23,7 +23,7 @@ export interface PurchaseAttributes {
familyId: string
service: 'googleplay' | 'directpurchase'
transactionId: string
type: 'month' | 'year'
type: 'month' | 'year' | 'unpaid14'
loggedAt: string
previousFullVersionEndTime: string
newFullVersionEndTime: string
@@ -44,7 +44,7 @@ export const attributes: SequelizeAttributes<PurchaseAttributes> = {
type: Sequelize.STRING,
primaryKey: true
},
type: createEnumColumn(['month', 'year']),
type: createEnumColumn(['month', 'year', 'unpaid14']),
loggedAt: { ...timestampColumn },
previousFullVersionEndTime: { ...timestampColumn },
newFullVersionEndTime: { ...timestampColumn }
+30 -6
View File
@@ -21,13 +21,14 @@ import { notifyClientsAboutChangesDelayed } from '../../function/websocket'
import { WebsocketApi } from '../../websocket'
const day = 1000 * 60 * 60 * 24
const week = day * 7
const month = day * 31
const year = day * 366
export const addPurchase = async ({ database, familyId, type, service, transactionId, websocket, transaction }: {
database: Database
familyId: string
type: 'month' | 'year'
type: 'month' | 'year' | 'unpaid14'
service: 'googleplay' | 'directpurchase'
transactionId: string
websocket: WebsocketApi
@@ -59,16 +60,39 @@ export const addPurchase = async ({ database, familyId, type, service, transacti
const previousFullVersionEndTime = familyEntry.fullVersionUntil
const previousFullVersionDebts = parseInt(familyEntry.fullVersionDebts, 10)
const typeDuration = type === 'year' ? year : month
if (type === 'month' || type === 'year') {
const typeDuration = type === 'year' ? year : month
if (typeDuration > previousFullVersionDebts) {
const newFullVersionUntil = Math.max(parseInt(familyEntry.fullVersionUntil, 10), Date.now()) + typeDuration - previousFullVersionDebts
if (typeDuration > previousFullVersionDebts) {
const newFullVersionUntil = Math.max(parseInt(familyEntry.fullVersionUntil, 10), Date.now()) + typeDuration - previousFullVersionDebts
familyEntry.fullVersionUntil = newFullVersionUntil.toString(10)
familyEntry.fullVersionDebts = '0'
familyEntry.hasFullVersion = true
} else {
familyEntry.fullVersionDebts = (previousFullVersionDebts - typeDuration).toString(10)
}
} else if (type === 'unpaid14') {
const debtsAdd = 2 * week
const debtsMax = 3 * week
const newDebts = Math.min(debtsMax, previousFullVersionDebts + debtsAdd)
if (newDebts <= previousFullVersionDebts) {
// do not save anything
return
}
const durationToAdd = newDebts - previousFullVersionDebts
const newFullVersionUntil = Math.max(parseInt(familyEntry.fullVersionUntil, 10), Date.now()) + durationToAdd
familyEntry.fullVersionUntil = newFullVersionUntil.toString(10)
familyEntry.fullVersionDebts = '0'
familyEntry.fullVersionDebts = newDebts.toString(10)
familyEntry.hasFullVersion = true
} else {
familyEntry.fullVersionDebts = (previousFullVersionDebts - typeDuration).toString(10)
throw new Error()
}
await familyEntry.save({ transaction })