show how many tokens a user has been gifted

This commit is contained in:
Spine
2025-09-08 12:21:58 +00:00
parent d9b4588a1d
commit d3ca5ce981
4 changed files with 76 additions and 21 deletions

View File

@@ -144,7 +144,7 @@ class BonusItem extends \Gazelle\BaseObject {
AND ub.user_id = ?
', $this->amount(), $price, $price, $user->id
);
if (self::$db->affected_rows() != 2) {
if (self::$db->affected_rows() != 1 + ($price === 0 ? 0 : 1)) {
return Enum\BonusItemPurchaseStatus::insufficientFunds;
}
} elseif (str_starts_with($this->label(), 'other-')) {
@@ -178,13 +178,14 @@ class BonusItem extends \Gazelle\BaseObject {
other_uf.tokens = other_uf.tokens + ?,
ub.points = ub.points - ?
WHERE noFL.UserID IS NULL
AND ub.points >= ?
AND other.Enabled = '1'
AND other.Enabled = ?
AND other.ID = ?
AND self.ID = ?
", $this->amount(), $price, $price, $receiver->id, $user->id
AND ub.points >= ?
", $this->amount(), $price,
Enum\UserStatus::enabled->value, $receiver->id, $user->id, $price
);
if (self::$db->affected_rows() != 2) {
if (self::$db->affected_rows() != 1 + ($price === 0 ? 0 : 1)) {
return Enum\BonusItemPurchaseStatus::insufficientFunds;
}
$amount = $this->amount();
@@ -213,8 +214,7 @@ class BonusItem extends \Gazelle\BaseObject {
AND ub.user_id = ?
', $price, $price, $user->id
);
$rows = self::$db->affected_rows();
if (($price > 0 && $rows !== 2) || ($price === 0 && $rows !== 1)) {
if (self::$db->affected_rows() != 1 + ($price === 0 ? 0 : 1)) {
self::$db->rollback();
return Enum\BonusItemPurchaseStatus::insufficientFunds;
}
@@ -238,7 +238,7 @@ class BonusItem extends \Gazelle\BaseObject {
AND ub.user_id = ?
', $price, $price, $user->id
);
if (self::$db->affected_rows() != 1) {
if ($price > 0 && self::$db->affected_rows() != 1) {
self::$db->rollback();
return Enum\BonusItemPurchaseStatus::insufficientFunds;
}
@@ -270,7 +270,7 @@ class BonusItem extends \Gazelle\BaseObject {
AND ub.user_id = ?
', $price, $price, $user->id
);
if (self::$db->affected_rows() != 2) {
if (self::$db->affected_rows() != 1 + ($price === 0 ? 0 : 1)) {
return Enum\BonusItemPurchaseStatus::insufficientFunds;
}
break;
@@ -284,7 +284,7 @@ class BonusItem extends \Gazelle\BaseObject {
AND ub.user_id = ?
', $price, $price, $user->id
);
if (self::$db->affected_rows() != 1) {
if ($price > 0 && self::$db->affected_rows() != 1) {
self::$db->rollback();
return Enum\BonusItemPurchaseStatus::insufficientFunds;
}

View File

@@ -40,6 +40,35 @@ class Bonus extends \Gazelle\BaseUser {
);
}
/**
* @return array<int>
*/
public function tokenExchange(): array {
return array_map(
'intval',
self::$db->rowAssoc("
WITH sent(n) AS (
SELECT sum(bi.Amount)
FROM bonus_history bh
INNER JOIN bonus_item bi ON (bi.ID = bh.ItemID)
WHERE bh.OtherUserID IS NOT NULL
AND bh.UserID = ?
),
recv(n) AS (
SELECT sum(bi.Amount)
FROM bonus_history bh
INNER JOIN bonus_item bi ON (bi.ID = bh.ItemID)
WHERE OtherUserID = ?
)
SELECT coalesce(recv.n, 0) AS received,
coalesce(sent.n, 0) AS sent
FROM sent
CROSS JOIN recv
", $this->user->id, $this->user->id
)
);
}
public function otherLatest(\Gazelle\User $other): array {
return self::$db->rowAssoc("
SELECT bi.Title AS title,

View File

@@ -89,19 +89,29 @@
<form class="fl_form" name="user" id="fl_form" action="user.php?id={{ user_id }}" method="post">
<ul class="stats nobullet">
{% for item in freeleech.offer %}
<li><input type="radio" name="fltype" id="{{ item.label }}" value="{{ item.label }}" />
<label title="This costs {{ item.price|number_format }} BP, which will leave you with {{
(viewer.bonusPointsTotal - item.price)|number_format}} afterwards" for="{{
item.label }}"> {{ item.title }}</label></li>
<li>
<label class="tooltip" title="This costs {{ item.price|number_format
}} BP, which will leave you with {{
(viewer.bonusPointsTotal - item.price)|number_format }} afterwards">
<input type="radio" name="fltype" value="{{ item.label }}" />
{{ item.title }}
</label>
</li>
{% endfor %}
<li><input type="text" id="message" name="message" placeholder="Message"/> <br /></li>
<li><input type="submit" name="flsubmit" value="Send" /></li>
{% if freeleech.latest %}
{% set when = freeleech.latest.purchase_date|time_diff %}
<li>
You gave them {{ freeleech.latest.title|trim(' to Other') }} {{ when|raw }}
{%- if 'Just now' in when %}. Your generosity is most appreciated!{% endif -%}
<li>You gave them {{ freeleech.latest.title|trim(' to Other') }} {{
when|raw }}{% if 'Just now' in when %}. Your generosity is most appreciated!{% endif -%}
</li>
{% endif %}
{% set exchange = bonus.tokenExchange %}
{% if exchange.received > exchange.sent %}
{% set net = exchange.received - exchange.sent %}
<li title="{{ exchange.received|number_format}} received, {{
exchange.sent|number_format }} given">Total benefits: {{
net | number_format }} token{{ net|plural }}</li>
{% endif %}
</ul>
<input type="hidden" name="action" value="fltoken" />

View File

@@ -194,6 +194,23 @@ class BonusTest extends TestCase {
'bonus-points-spent',
);
$this->assertEquals(
BonusItemPurchaseStatus::success,
$other1->purchase(
$this->userList['receiver'],
0,
['receiver' => $user],
),
'bonus-item-receiver-give'
);
$this->assertEquals(
[
"received" => 50,
"sent" => 1,
],
(new User\Bonus($this->userList['receiver'])->tokenExchange()),
'bonus-token-exchange',
);
$latest = $giver->otherLatest($this->userList['receiver']);
$this->assertEquals('50 Freeleech Tokens to Other', $latest['title'], 'bonus-item-given');
@@ -287,16 +304,15 @@ class BonusTest extends TestCase {
'bonus-item-free-title-yes-bb',
);
$userBonus = new User\Bonus($user);
$history = $userBonus->purchaseHistory();
$history = $giver->purchaseHistory();
$this->assertCount(8, $history, 'bonus-history-count');
$this->assertEquals(
['id', 'title', 'total', 'cost'],
array_keys(current($history)),
'bonus-history-shape',
);
$this->assertCount(0, $userBonus->seedList(5, 0), 'bonus-history-seedlist');
$this->assertCount(0, $userBonus->poolHistory(), 'bonus-history-pool');
$this->assertCount(0, $giver->seedList(5, 0), 'bonus-history-seedlist');
$this->assertCount(0, $giver->poolHistory(), 'bonus-history-pool');
// Here is as good a place as any
$this->assertEquals(0, $manager->discount(), 'bonus-discount');