count overpay as debts when fronted + add debt writeoff
This commit is contained in:
1 parent
2939415f76
commit
7ec95ee24a
8 files changed
+194
-5
No files matched your search
@@ -12,6 +12,7 @@ The idea is pretty simple: public pages for stats and session history, plus a sm
|
|||||||
- admin login for recording events
|
- admin login for recording events
|
||||||
- open / closed session tracking
|
- open / closed session tracking
|
||||||
- payout tracking with `paid` events
|
- payout tracking with `paid` events
|
||||||
|
- front debt write-offs with `front_writeoff` events
|
||||||
- session and player charts
|
- session and player charts
|
||||||
- CSV import / export from the admin page
|
- CSV import / export from the admin page
|
||||||
- append-only `entries.csv` ledger instead of overwriting old rows
|
- append-only `entries.csv` ledger instead of overwriting old rows
|
||||||
@@ -36,8 +37,12 @@ Each row is an event, not a final snapshot. Instead of editing an old row, I app
|
|||||||
Current event types:
|
Current event types:
|
||||||
|
|
||||||
- `buyin`
|
- `buyin`
|
||||||
|
- `front`
|
||||||
|
- `front_writeoff`
|
||||||
- `cashout`
|
- `cashout`
|
||||||
- `paid`
|
- `paid`
|
||||||
|
- `rollover_in`
|
||||||
|
- `rollover_out`
|
||||||
- `note`
|
- `note`
|
||||||
- `session_open`
|
- `session_open`
|
||||||
- `session_close`
|
- `session_close`
|
||||||
@@ -47,6 +52,7 @@ A few examples:
|
|||||||
- another `buyin` for a rebuy
|
- another `buyin` for a rebuy
|
||||||
- another `cashout` if chip counts are corrected later
|
- another `cashout` if chip counts are corrected later
|
||||||
- a `paid` event when someone is actually settled up
|
- a `paid` event when someone is actually settled up
|
||||||
|
- a `front_writeoff` event when a front will not be collected
|
||||||
- a `note` event for bookkeeping context
|
- a `note` event for bookkeeping context
|
||||||
- `session_open` / `session_close` to mark whether a game night is still live
|
- `session_open` / `session_close` to mark whether a game night is still live
|
||||||
|
|
||||||
@@ -61,7 +67,7 @@ Main file:
|
|||||||
Header:
|
Header:
|
||||||
|
|
||||||
```csv
|
```csv
|
||||||
id,created_at,session_date,player_name,event_type,amount_cents,note,actor
|
id,created_at,session_id,session_date,player_name,event_type,amount_cents,note,actor
|
||||||
```
|
```
|
||||||
|
|
||||||
Amounts are stored in cents to avoid floating-point issues.
|
Amounts are stored in cents to avoid floating-point issues.
|
||||||
|
|||||||
@@ -370,6 +370,74 @@ def admin_import_csv():
|
|||||||
return redirect(url_for("admin_dashboard"))
|
return redirect(url_for("admin_dashboard"))
|
||||||
|
|
||||||
|
|
||||||
|
@app.post("/admin/write-off-front")
|
||||||
|
def admin_write_off_front() -> str:
|
||||||
|
if not is_admin():
|
||||||
|
flash("Admin login required.", "error")
|
||||||
|
return redirect(url_for("admin_login"))
|
||||||
|
|
||||||
|
debt_key = request.form.get("debt_key", "").strip()
|
||||||
|
note = request.form.get("note", "").strip()
|
||||||
|
amount_raw = request.form.get("amount", "0").strip()
|
||||||
|
|
||||||
|
try:
|
||||||
|
amount_cents = int(round(float(amount_raw) * 100))
|
||||||
|
except ValueError:
|
||||||
|
flash("Amount must be a number.", "error")
|
||||||
|
return redirect(url_for("admin_dashboard"))
|
||||||
|
|
||||||
|
if amount_cents <= 0:
|
||||||
|
flash("Write-off amount must be greater than zero.", "error")
|
||||||
|
return redirect(url_for("admin_dashboard"))
|
||||||
|
|
||||||
|
try:
|
||||||
|
session_id, player_name = debt_key.split("||", 1)
|
||||||
|
except ValueError:
|
||||||
|
flash("Select a valid player debt.", "error")
|
||||||
|
return redirect(url_for("admin_dashboard"))
|
||||||
|
|
||||||
|
events = load_events(DATA_PATH)
|
||||||
|
sessions = build_session_summaries(events)
|
||||||
|
target = next(
|
||||||
|
(session for session in sessions if session.session_id == session_id),
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
|
||||||
|
if target is None:
|
||||||
|
flash("Session not found.", "error")
|
||||||
|
return redirect(url_for("admin_dashboard"))
|
||||||
|
|
||||||
|
entry = next(
|
||||||
|
(entry for entry in target.entries if entry.player_name == player_name),
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
|
||||||
|
if entry is None or entry.player_owes_cents <= 0:
|
||||||
|
flash("That player does not have an outstanding front debt.", "error")
|
||||||
|
return redirect(url_for("admin_dashboard"))
|
||||||
|
|
||||||
|
if amount_cents > entry.player_owes_cents:
|
||||||
|
flash(
|
||||||
|
f"Write-off cannot exceed {cents_to_dollars(entry.player_owes_cents)}.",
|
||||||
|
"error",
|
||||||
|
)
|
||||||
|
return redirect(url_for("admin_dashboard"))
|
||||||
|
|
||||||
|
append_event(
|
||||||
|
DATA_PATH,
|
||||||
|
session_id=target.session_id,
|
||||||
|
session_date=target.session_date,
|
||||||
|
player_name=entry.player_name,
|
||||||
|
event_type="front_writeoff",
|
||||||
|
amount_cents=amount_cents,
|
||||||
|
note=note or "Front debt written off.",
|
||||||
|
actor=app.config["ADMIN_USERNAME"],
|
||||||
|
)
|
||||||
|
|
||||||
|
flash("Front debt written off.", "success")
|
||||||
|
return redirect(url_for("admin_dashboard"))
|
||||||
|
|
||||||
|
|
||||||
@app.post("/admin/open-session")
|
@app.post("/admin/open-session")
|
||||||
def admin_open_session() -> str:
|
def admin_open_session() -> str:
|
||||||
if not is_admin():
|
if not is_admin():
|
||||||
@@ -453,6 +521,12 @@ def admin_dashboard():
|
|||||||
open_sessions = [session for session in sessions if session.status == "open"]
|
open_sessions = [session for session in sessions if session.status == "open"]
|
||||||
recent_sessions = sessions[:8]
|
recent_sessions = sessions[:8]
|
||||||
recent_events = list(reversed(events[-20:]))
|
recent_events = list(reversed(events[-20:]))
|
||||||
|
debt_entries = [
|
||||||
|
{"session": session, "entry": entry}
|
||||||
|
for session in sessions
|
||||||
|
for entry in session.entries
|
||||||
|
if entry.player_owes_cents > 0
|
||||||
|
]
|
||||||
|
|
||||||
admin_totals = {
|
admin_totals = {
|
||||||
"cash_in_cents": sum(session.total_cash_in_cents for session in sessions),
|
"cash_in_cents": sum(session.total_cash_in_cents for session in sessions),
|
||||||
@@ -463,6 +537,9 @@ def admin_dashboard():
|
|||||||
"players_owe_cents": sum(
|
"players_owe_cents": sum(
|
||||||
session.total_player_owes_cents for session in sessions
|
session.total_player_owes_cents for session in sessions
|
||||||
),
|
),
|
||||||
|
"written_off_cents": sum(
|
||||||
|
session.total_front_writeoff_cents for session in sessions
|
||||||
|
),
|
||||||
"open_balance_cents": sum(
|
"open_balance_cents": sum(
|
||||||
session.total_open_balance_cents for session in sessions
|
session.total_open_balance_cents for session in sessions
|
||||||
),
|
),
|
||||||
@@ -473,6 +550,7 @@ def admin_dashboard():
|
|||||||
open_sessions=open_sessions,
|
open_sessions=open_sessions,
|
||||||
recent_sessions=recent_sessions,
|
recent_sessions=recent_sessions,
|
||||||
recent_events=recent_events,
|
recent_events=recent_events,
|
||||||
|
debt_entries=debt_entries,
|
||||||
player_names=unique_player_names(events),
|
player_names=unique_player_names(events),
|
||||||
session_label=session_label,
|
session_label=session_label,
|
||||||
admin_totals=admin_totals,
|
admin_totals=admin_totals,
|
||||||
|
|||||||
@@ -958,6 +958,12 @@ td a:hover {
|
|||||||
border: 1px solid rgba(251, 146, 60, 0.22);
|
border: 1px solid rgba(251, 146, 60, 0.22);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.pill-front_writeoff {
|
||||||
|
color: #f87171;
|
||||||
|
background: rgba(248, 113, 113, 0.12);
|
||||||
|
border: 1px solid rgba(248, 113, 113, 0.22);
|
||||||
|
}
|
||||||
|
|
||||||
.pill-note {
|
.pill-note {
|
||||||
color: #cbd5e1;
|
color: #cbd5e1;
|
||||||
background: rgba(203, 213, 225, 0.08);
|
background: rgba(203, 213, 225, 0.08);
|
||||||
@@ -983,6 +989,12 @@ td a:hover {
|
|||||||
border: 1px solid rgba(239, 68, 68, 0.24);
|
border: 1px solid rgba(239, 68, 68, 0.24);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.status-written_off {
|
||||||
|
color: #f87171;
|
||||||
|
background: rgba(248, 113, 113, 0.12);
|
||||||
|
border: 1px solid rgba(248, 113, 113, 0.24);
|
||||||
|
}
|
||||||
|
|
||||||
.inline-action-form {
|
.inline-action-form {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ class SessionEntry:
|
|||||||
player_name: str
|
player_name: str
|
||||||
buy_in_cents: int = 0
|
buy_in_cents: int = 0
|
||||||
front_cents: int = 0
|
front_cents: int = 0
|
||||||
|
front_writeoff_cents: int = 0
|
||||||
cash_out_cents: int = 0
|
cash_out_cents: int = 0
|
||||||
paid_cents: int = 0
|
paid_cents: int = 0
|
||||||
rollover_in_cents: int = 0
|
rollover_in_cents: int = 0
|
||||||
@@ -67,12 +68,30 @@ class SessionEntry:
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def player_owes_cents(self) -> int:
|
def player_owes_cents(self) -> int:
|
||||||
|
return max(self.raw_player_owes_cents - self.front_writeoff_applied_cents, 0)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def raw_player_owes_cents(self) -> int:
|
||||||
|
return self.front_shortfall_cents + self.overpaid_front_cents
|
||||||
|
|
||||||
|
@property
|
||||||
|
def front_shortfall_cents(self) -> int:
|
||||||
return max(self.front_cents - self.cash_out_cents, 0)
|
return max(self.front_cents - self.cash_out_cents, 0)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def overpaid_front_cents(self) -> int:
|
||||||
|
return max(self.settled_cents - self.gross_payout_cents, 0)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def front_writeoff_applied_cents(self) -> int:
|
||||||
|
return min(self.front_writeoff_cents, self.raw_player_owes_cents)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def payout_status(self) -> str:
|
def payout_status(self) -> str:
|
||||||
if self.player_owes_cents > 0:
|
if self.player_owes_cents > 0:
|
||||||
return "owes"
|
return "owes"
|
||||||
|
if self.front_writeoff_applied_cents > 0:
|
||||||
|
return "written_off"
|
||||||
if self.gross_payout_cents <= 0:
|
if self.gross_payout_cents <= 0:
|
||||||
return "none"
|
return "none"
|
||||||
if self.current_due_cents <= 0:
|
if self.current_due_cents <= 0:
|
||||||
@@ -146,6 +165,10 @@ class SessionSummary:
|
|||||||
def total_player_owes_cents(self) -> int:
|
def total_player_owes_cents(self) -> int:
|
||||||
return sum(entry.player_owes_cents for entry in self.entries)
|
return sum(entry.player_owes_cents for entry in self.entries)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def total_front_writeoff_cents(self) -> int:
|
||||||
|
return sum(entry.front_writeoff_applied_cents for entry in self.entries)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def total_cash_in_cents(self) -> int:
|
def total_cash_in_cents(self) -> int:
|
||||||
return sum(entry.buy_in_cents for entry in self.entries)
|
return sum(entry.buy_in_cents for entry in self.entries)
|
||||||
@@ -173,6 +196,8 @@ class PlayerStats:
|
|||||||
biggest_loss_cents: int
|
biggest_loss_cents: int
|
||||||
total_buy_in_cents: int
|
total_buy_in_cents: int
|
||||||
total_front_cents: int
|
total_front_cents: int
|
||||||
|
total_front_writeoff_cents: int
|
||||||
|
current_player_owes_cents: int
|
||||||
total_rollover_in_cents: int
|
total_rollover_in_cents: int
|
||||||
total_invested_cents: int
|
total_invested_cents: int
|
||||||
total_cash_out_cents: int
|
total_cash_out_cents: int
|
||||||
@@ -322,6 +347,8 @@ def build_session_summaries(events: list[EventRow]) -> list[SessionSummary]:
|
|||||||
entry.buy_in_cents += event["amount_cents"]
|
entry.buy_in_cents += event["amount_cents"]
|
||||||
elif event_type == "front":
|
elif event_type == "front":
|
||||||
entry.front_cents += event["amount_cents"]
|
entry.front_cents += event["amount_cents"]
|
||||||
|
elif event_type == "front_writeoff":
|
||||||
|
entry.front_writeoff_cents += event["amount_cents"]
|
||||||
elif event_type == "rollover_in":
|
elif event_type == "rollover_in":
|
||||||
entry.rollover_in_cents += event["amount_cents"]
|
entry.rollover_in_cents += event["amount_cents"]
|
||||||
elif event_type == "cashout":
|
elif event_type == "cashout":
|
||||||
@@ -454,6 +481,10 @@ def build_leaderboard(sessions: list[SessionSummary]) -> list[PlayerStats]:
|
|||||||
|
|
||||||
total_buy_in = sum(entry.buy_in_cents for entry in entries)
|
total_buy_in = sum(entry.buy_in_cents for entry in entries)
|
||||||
total_front = sum(entry.front_cents for entry in entries)
|
total_front = sum(entry.front_cents for entry in entries)
|
||||||
|
total_front_writeoff = sum(
|
||||||
|
entry.front_writeoff_applied_cents for entry in entries
|
||||||
|
)
|
||||||
|
current_player_owes = sum(entry.player_owes_cents for entry in entries)
|
||||||
total_rollover_in = sum(entry.rollover_in_cents for entry in entries)
|
total_rollover_in = sum(entry.rollover_in_cents for entry in entries)
|
||||||
total_invested = sum(entry.invested_cents for entry in entries)
|
total_invested = sum(entry.invested_cents for entry in entries)
|
||||||
total_cash_out = sum(entry.cash_out_cents for entry in entries)
|
total_cash_out = sum(entry.cash_out_cents for entry in entries)
|
||||||
@@ -476,6 +507,8 @@ def build_leaderboard(sessions: list[SessionSummary]) -> list[PlayerStats]:
|
|||||||
biggest_loss_cents=biggest_loss,
|
biggest_loss_cents=biggest_loss,
|
||||||
total_buy_in_cents=total_buy_in,
|
total_buy_in_cents=total_buy_in,
|
||||||
total_front_cents=total_front,
|
total_front_cents=total_front,
|
||||||
|
total_front_writeoff_cents=total_front_writeoff,
|
||||||
|
current_player_owes_cents=current_player_owes,
|
||||||
total_rollover_in_cents=total_rollover_in,
|
total_rollover_in_cents=total_rollover_in,
|
||||||
total_invested_cents=total_invested,
|
total_invested_cents=total_invested,
|
||||||
total_cash_out_cents=total_cash_out,
|
total_cash_out_cents=total_cash_out,
|
||||||
|
|||||||
+2
-1
@@ -35,6 +35,7 @@ class EventRow(TypedDict):
|
|||||||
VALID_EVENT_TYPES = {
|
VALID_EVENT_TYPES = {
|
||||||
"buyin",
|
"buyin",
|
||||||
"front",
|
"front",
|
||||||
|
"front_writeoff",
|
||||||
"cashout",
|
"cashout",
|
||||||
"paid",
|
"paid",
|
||||||
"rollover_in",
|
"rollover_in",
|
||||||
@@ -98,7 +99,7 @@ def append_event(
|
|||||||
if normalized_type not in VALID_EVENT_TYPES:
|
if normalized_type not in VALID_EVENT_TYPES:
|
||||||
raise ValueError(f"Unsupported event type: {event_type}")
|
raise ValueError(f"Unsupported event type: {event_type}")
|
||||||
|
|
||||||
if normalized_type == {"note", "session_open", "session_close"}:
|
if normalized_type in {"note", "session_open", "session_close"}:
|
||||||
amount_cents = 0
|
amount_cents = 0
|
||||||
|
|
||||||
event = EventRow(
|
event = EventRow(
|
||||||
|
|||||||
@@ -112,6 +112,39 @@
|
|||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
<form class="panel form-card" method="post" action="{{ url_for('admin_write_off_front') }}">
|
||||||
|
<p class="eyebrow">Front debt</p>
|
||||||
|
<h2>Write off debt</h2>
|
||||||
|
|
||||||
|
<label>
|
||||||
|
<span>Outstanding debt</span>
|
||||||
|
<select name="debt_key" required>
|
||||||
|
<option value="">Select debt</option>
|
||||||
|
{% for item in debt_entries %}
|
||||||
|
{% set session = item.session %}
|
||||||
|
{% set entry = item.entry %}
|
||||||
|
<option value="{{ session.session_id }}||{{ entry.player_name }}">
|
||||||
|
{{ entry.player_name }} · {{ session_label(session) }} · owes {{ entry.player_owes_cents | money }}
|
||||||
|
</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<label>
|
||||||
|
<span>Amount to write off</span>
|
||||||
|
<input type="number" step="0.01" name="amount" placeholder="5.00" required>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<label>
|
||||||
|
<span>Note</span>
|
||||||
|
<textarea name="note" rows="3" placeholder="Won't be collected."></textarea>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<div class="button-row">
|
||||||
|
<button class="secondary-button" type="submit">Write off front</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
</section>
|
</section>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
@@ -140,6 +173,13 @@
|
|||||||
</strong>
|
</strong>
|
||||||
</article>
|
</article>
|
||||||
|
|
||||||
|
<article class="panel stat-card">
|
||||||
|
<span>Written off</span>
|
||||||
|
<strong class="{{ 'negative' if admin_totals.written_off_cents > 0 else '' }}">
|
||||||
|
{{ admin_totals.written_off_cents | money }}
|
||||||
|
</strong>
|
||||||
|
</article>
|
||||||
|
|
||||||
<article class="panel stat-card">
|
<article class="panel stat-card">
|
||||||
<span>Open balance</span>
|
<span>Open balance</span>
|
||||||
<strong class="{% if admin_totals.open_balance_cents > 0 %}negative{% elif admin_totals.open_balance_cents < 0 %}positive{% endif %}">
|
<strong class="{% if admin_totals.open_balance_cents > 0 %}negative{% elif admin_totals.open_balance_cents < 0 %}positive{% endif %}">
|
||||||
@@ -165,6 +205,7 @@
|
|||||||
<th>Paid out</th>
|
<th>Paid out</th>
|
||||||
<th>Still owed</th>
|
<th>Still owed</th>
|
||||||
<th>Players owe</th>
|
<th>Players owe</th>
|
||||||
|
<th>Written off</th>
|
||||||
<th>Open balance</th>
|
<th>Open balance</th>
|
||||||
<th>Status</th>
|
<th>Status</th>
|
||||||
<th>Action</th>
|
<th>Action</th>
|
||||||
@@ -187,6 +228,9 @@
|
|||||||
<td class="{{ 'negative' if session.total_player_owes_cents > 0 else '' }}">
|
<td class="{{ 'negative' if session.total_player_owes_cents > 0 else '' }}">
|
||||||
{{ session.total_player_owes_cents | money }}
|
{{ session.total_player_owes_cents | money }}
|
||||||
</td>
|
</td>
|
||||||
|
<td class="{{ 'negative' if session.total_front_writeoff_cents > 0 else '' }}">
|
||||||
|
{{ session.total_front_writeoff_cents | money }}
|
||||||
|
</td>
|
||||||
<td class="{% if session.total_open_balance_cents > 0 %}negative{% elif session.total_open_balance_cents < 0 %}positive{% endif %}">
|
<td class="{% if session.total_open_balance_cents > 0 %}negative{% elif session.total_open_balance_cents < 0 %}positive{% endif %}">
|
||||||
{{ session.total_open_balance_cents | money }}
|
{{ session.total_open_balance_cents | money }}
|
||||||
</td>
|
</td>
|
||||||
@@ -208,7 +252,7 @@
|
|||||||
</tr>
|
</tr>
|
||||||
{% else %}
|
{% else %}
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="4">No sessions yet.</td>
|
<td colspan="10">No sessions yet.</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|||||||
@@ -16,6 +16,8 @@
|
|||||||
<article class="panel stat-card"><span>Total invested</span><strong>{{ player.total_invested_cents | money }}</strong></article>
|
<article class="panel stat-card"><span>Total invested</span><strong>{{ player.total_invested_cents | money }}</strong></article>
|
||||||
<article class="panel stat-card"><span>Paid Buy-in</span><strong>{{ player.total_buy_in_cents | money }}</strong></article>
|
<article class="panel stat-card"><span>Paid Buy-in</span><strong>{{ player.total_buy_in_cents | money }}</strong></article>
|
||||||
<article class="panel stat-card"><span>Fronted</span><strong>{{ player.total_front_cents | money }}</strong></article>
|
<article class="panel stat-card"><span>Fronted</span><strong>{{ player.total_front_cents | money }}</strong></article>
|
||||||
|
<article class="panel stat-card"><span>Current debt</span><strong class="{{ 'negative' if player.current_player_owes_cents > 0 else '' }}">{{ player.current_player_owes_cents | money }}</strong></article>
|
||||||
|
<article class="panel stat-card"><span>Written off</span><strong class="{{ 'negative' if player.total_front_writeoff_cents > 0 else '' }}">{{ player.total_front_writeoff_cents | money }}</strong></article>
|
||||||
<!--<article class="panel stat-card"><span>Rolled in</span><strong>{{ player.total_rollover_in_cents | money }}</strong></article>-->
|
<!--<article class="panel stat-card"><span>Rolled in</span><strong>{{ player.total_rollover_in_cents | money }}</strong></article>-->
|
||||||
<article class="panel stat-card"><span>Cash-outs</span><strong>{{ player.total_cash_out_cents | money }}</strong></article>
|
<article class="panel stat-card"><span>Cash-outs</span><strong>{{ player.total_cash_out_cents | money }}</strong></article>
|
||||||
<article class="panel stat-card"><span>Sessions</span><strong>{{ player.sessions_played }}</strong></article>
|
<article class="panel stat-card"><span>Sessions</span><strong>{{ player.sessions_played }}</strong></article>
|
||||||
@@ -87,6 +89,8 @@
|
|||||||
<tbody>
|
<tbody>
|
||||||
<tr><th>Paid Buy-ins</th><td>{{ player.total_buy_in_cents | money }}</td></tr>
|
<tr><th>Paid Buy-ins</th><td>{{ player.total_buy_in_cents | money }}</td></tr>
|
||||||
<tr><th>Fronted</th><td>{{ player.total_front_cents | money }}</td></tr>
|
<tr><th>Fronted</th><td>{{ player.total_front_cents | money }}</td></tr>
|
||||||
|
<tr><th>Current Debt</th><td>{{ player.current_player_owes_cents | money }}</td></tr>
|
||||||
|
<tr><th>Written Off</th><td>{{ player.total_front_writeoff_cents | money }}</td></tr>
|
||||||
<tr><th>Rolled In</th><td>{{ player.total_rollover_in_cents | money }}</td></tr>
|
<tr><th>Rolled In</th><td>{{ player.total_rollover_in_cents | money }}</td></tr>
|
||||||
<tr><th>Total Invested</th><td>{{ player.total_invested_cents | money }}</td></tr>
|
<tr><th>Total Invested</th><td>{{ player.total_invested_cents | money }}</td></tr>
|
||||||
<tr><th>Rolled Out</th><td>{{ player.total_rollover_out_cents | money }}</td></tr>
|
<tr><th>Rolled Out</th><td>{{ player.total_rollover_out_cents | money }}</td></tr>
|
||||||
|
|||||||
@@ -54,6 +54,13 @@
|
|||||||
{{ session.total_player_owes_cents | money }}
|
{{ session.total_player_owes_cents | money }}
|
||||||
</strong>
|
</strong>
|
||||||
</article>
|
</article>
|
||||||
|
|
||||||
|
<article class="panel stat-card">
|
||||||
|
<span>Written off</span>
|
||||||
|
<strong class="{{ 'negative' if session.total_front_writeoff_cents > 0 else '' }}">
|
||||||
|
{{ session.total_front_writeoff_cents | money }}
|
||||||
|
</strong>
|
||||||
|
</article>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
|
||||||
@@ -87,6 +94,7 @@
|
|||||||
<th class="detail-col">Gross due</th>
|
<th class="detail-col">Gross due</th>
|
||||||
<th class="detail-col">Paid</th>
|
<th class="detail-col">Paid</th>
|
||||||
<th class="detail-col">Rolled out</th>
|
<th class="detail-col">Rolled out</th>
|
||||||
|
<th class="detail-col">Written off</th>
|
||||||
<th>Still owed</th>
|
<th>Still owed</th>
|
||||||
<th>Status</th>
|
<th>Status</th>
|
||||||
<th>Notes</th>
|
<th>Notes</th>
|
||||||
@@ -111,7 +119,7 @@
|
|||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td class="detail-col">
|
<td class="detail-col">
|
||||||
{% if entry.player_owes_cents > 0 %}
|
{% if entry.raw_player_owes_cents > 0 %}
|
||||||
—
|
—
|
||||||
{% else %}
|
{% else %}
|
||||||
{{ entry.gross_payout_cents | money }}
|
{{ entry.gross_payout_cents | money }}
|
||||||
@@ -120,10 +128,13 @@
|
|||||||
|
|
||||||
<td class="detail-col">{{ entry.paid_cents | money }}</td>
|
<td class="detail-col">{{ entry.paid_cents | money }}</td>
|
||||||
<td class="detail-col">{{ entry.rollover_out_cents | money }}</td>
|
<td class="detail-col">{{ entry.rollover_out_cents | money }}</td>
|
||||||
|
<td class="detail-col">{{ entry.front_writeoff_applied_cents | money }}</td>
|
||||||
|
|
||||||
<td class="{% if entry.player_owes_cents > 0 %}negative{% elif entry.current_due_cents > 0 %}negative{% else %}positive{% endif %}">
|
<td class="{% if entry.player_owes_cents > 0 %}negative{% elif entry.front_writeoff_applied_cents > 0 %}negative{% elif entry.current_due_cents > 0 %}negative{% else %}positive{% endif %}">
|
||||||
{% if entry.player_owes_cents > 0 %}
|
{% if entry.player_owes_cents > 0 %}
|
||||||
Owes {{ entry.player_owes_cents | money }}
|
Owes {{ entry.player_owes_cents | money }}
|
||||||
|
{% elif entry.front_writeoff_applied_cents > 0 %}
|
||||||
|
Written off {{ entry.front_writeoff_applied_cents | money }}
|
||||||
{% else %}
|
{% else %}
|
||||||
{{ entry.current_due_cents | money }}
|
{{ entry.current_due_cents | money }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|||||||
Reference in new issue
Block a user