Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1257f0d644 |
30
app.py
30
app.py
@@ -12,15 +12,15 @@ from flask import Flask, render_template, g, send_file, request
|
|||||||
scripts_dir = Path(__file__).parent / "scripts"
|
scripts_dir = Path(__file__).parent / "scripts"
|
||||||
sys.path.append(str(scripts_dir))
|
sys.path.append(str(scripts_dir))
|
||||||
|
|
||||||
from attendance import get_members_with_fees, get_junior_members_with_fees, SHEET_ID as ATTENDANCE_SHEET_ID, JUNIOR_SHEET_GID, MERGED_MONTHS
|
from attendance import get_members_with_fees, get_junior_members_with_fees, SHEET_ID as ATTENDANCE_SHEET_ID, JUNIOR_SHEET_GID, ADULT_MERGED_MONTHS, JUNIOR_MERGED_MONTHS
|
||||||
from match_payments import reconcile, fetch_sheet_data, fetch_exceptions, normalize, DEFAULT_SPREADSHEET_ID as PAYMENTS_SHEET_ID
|
from match_payments import reconcile, fetch_sheet_data, fetch_exceptions, normalize, DEFAULT_SPREADSHEET_ID as PAYMENTS_SHEET_ID
|
||||||
|
|
||||||
def get_month_labels(sorted_months):
|
def get_month_labels(sorted_months, merged_months):
|
||||||
labels = {}
|
labels = {}
|
||||||
for m in sorted_months:
|
for m in sorted_months:
|
||||||
dt = datetime.strptime(m, "%Y-%m")
|
dt = datetime.strptime(m, "%Y-%m")
|
||||||
# Find which months were merged into m (e.g. 2026-01 is merged into 2026-02)
|
# Find which months were merged into m (e.g. 2026-01 is merged into 2026-02)
|
||||||
merged_in = sorted([k for k, v in MERGED_MONTHS.items() if v == m])
|
merged_in = sorted([k for k, v in merged_months.items() if v == m])
|
||||||
if merged_in:
|
if merged_in:
|
||||||
all_dts = [datetime.strptime(x, "%Y-%m") for x in sorted(merged_in + [m])]
|
all_dts = [datetime.strptime(x, "%Y-%m") for x in sorted(merged_in + [m])]
|
||||||
years = {d.year for d in all_dts}
|
years = {d.year for d in all_dts}
|
||||||
@@ -87,7 +87,7 @@ def fees():
|
|||||||
results = [(name, fees) for name, tier, fees in members if tier == "A"]
|
results = [(name, fees) for name, tier, fees in members if tier == "A"]
|
||||||
|
|
||||||
# Format month labels
|
# Format month labels
|
||||||
month_labels = get_month_labels(sorted_months)
|
month_labels = get_month_labels(sorted_months, ADULT_MERGED_MONTHS)
|
||||||
|
|
||||||
monthly_totals = {m: 0 for m in sorted_months}
|
monthly_totals = {m: 0 for m in sorted_months}
|
||||||
|
|
||||||
@@ -144,7 +144,7 @@ def fees_juniors():
|
|||||||
results = sorted([(name, fees) for name, tier, fees in members], key=lambda x: x[0])
|
results = sorted([(name, fees) for name, tier, fees in members], key=lambda x: x[0])
|
||||||
|
|
||||||
# Format month labels
|
# Format month labels
|
||||||
month_labels = get_month_labels(sorted_months)
|
month_labels = get_month_labels(sorted_months, JUNIOR_MERGED_MONTHS)
|
||||||
|
|
||||||
monthly_totals = {m: 0 for m in sorted_months}
|
monthly_totals = {m: 0 for m in sorted_months}
|
||||||
|
|
||||||
@@ -227,7 +227,7 @@ def reconcile_view():
|
|||||||
record_step("reconcile")
|
record_step("reconcile")
|
||||||
|
|
||||||
# Format month labels
|
# Format month labels
|
||||||
month_labels = get_month_labels(sorted_months)
|
month_labels = get_month_labels(sorted_months, ADULT_MERGED_MONTHS)
|
||||||
|
|
||||||
# Filter to adults for the main table
|
# Filter to adults for the main table
|
||||||
adult_names = sorted([name for name, tier, _ in members if tier == "A"])
|
adult_names = sorted([name for name, tier, _ in members if tier == "A"])
|
||||||
@@ -235,7 +235,8 @@ def reconcile_view():
|
|||||||
formatted_results = []
|
formatted_results = []
|
||||||
for name in adult_names:
|
for name in adult_names:
|
||||||
data = result["members"][name]
|
data = result["members"][name]
|
||||||
row = {"name": name, "months": [], "balance": data["total_balance"]}
|
row = {"name": name, "months": [], "balance": data["total_balance"], "unpaid_periods": ""}
|
||||||
|
unpaid_months = []
|
||||||
for m in sorted_months:
|
for m in sorted_months:
|
||||||
mdata = data["months"].get(m, {"expected": 0, "original_expected": 0, "paid": 0})
|
mdata = data["months"].get(m, {"expected": 0, "original_expected": 0, "paid": 0})
|
||||||
expected = mdata["expected"]
|
expected = mdata["expected"]
|
||||||
@@ -253,10 +254,12 @@ def reconcile_view():
|
|||||||
status = "partial"
|
status = "partial"
|
||||||
cell_text = f"{paid}/{expected}"
|
cell_text = f"{paid}/{expected}"
|
||||||
amount_to_pay = expected - paid
|
amount_to_pay = expected - paid
|
||||||
|
unpaid_months.append(month_labels[m])
|
||||||
else:
|
else:
|
||||||
status = "unpaid"
|
status = "unpaid"
|
||||||
cell_text = f"UNPAID {expected}"
|
cell_text = f"UNPAID {expected}"
|
||||||
amount_to_pay = expected
|
amount_to_pay = expected
|
||||||
|
unpaid_months.append(month_labels[m])
|
||||||
elif paid > 0:
|
elif paid > 0:
|
||||||
status = "surplus"
|
status = "surplus"
|
||||||
cell_text = f"PAID {paid}"
|
cell_text = f"PAID {paid}"
|
||||||
@@ -268,12 +271,13 @@ def reconcile_view():
|
|||||||
"month": month_labels[m]
|
"month": month_labels[m]
|
||||||
})
|
})
|
||||||
|
|
||||||
|
row["unpaid_periods"] = ", ".join(unpaid_months) if unpaid_months else ("Older debt" if data["total_balance"] < 0 else "")
|
||||||
row["balance"] = data["total_balance"] # Updated to use total_balance
|
row["balance"] = data["total_balance"] # Updated to use total_balance
|
||||||
formatted_results.append(row)
|
formatted_results.append(row)
|
||||||
|
|
||||||
# Format credits and debts
|
# Format credits and debts
|
||||||
credits = sorted([{"name": n, "amount": a["total_balance"]} for n, a in result["members"].items() if a["total_balance"] > 0], key=lambda x: x["name"])
|
credits = sorted([{"name": n, "amount": a["total_balance"]} for n, a in result["members"].items() if a["total_balance"] > 0 and n in adult_names], key=lambda x: x["name"])
|
||||||
debts = sorted([{"name": n, "amount": abs(a["total_balance"])} for n, a in result["members"].items() if a["total_balance"] < 0], key=lambda x: x["name"])
|
debts = sorted([{"name": n, "amount": abs(a["total_balance"])} for n, a in result["members"].items() if a["total_balance"] < 0 and n in adult_names], key=lambda x: x["name"])
|
||||||
# Format unmatched
|
# Format unmatched
|
||||||
unmatched = result["unmatched"]
|
unmatched = result["unmatched"]
|
||||||
import json
|
import json
|
||||||
@@ -330,7 +334,7 @@ def reconcile_juniors_view():
|
|||||||
record_step("reconcile")
|
record_step("reconcile")
|
||||||
|
|
||||||
# Format month labels
|
# Format month labels
|
||||||
month_labels = get_month_labels(sorted_months)
|
month_labels = get_month_labels(sorted_months, JUNIOR_MERGED_MONTHS)
|
||||||
|
|
||||||
# Filter to juniors for the main table
|
# Filter to juniors for the main table
|
||||||
junior_names = sorted([name for name, tier, _ in adapted_members])
|
junior_names = sorted([name for name, tier, _ in adapted_members])
|
||||||
@@ -338,7 +342,8 @@ def reconcile_juniors_view():
|
|||||||
formatted_results = []
|
formatted_results = []
|
||||||
for name in junior_names:
|
for name in junior_names:
|
||||||
data = result["members"][name]
|
data = result["members"][name]
|
||||||
row = {"name": name, "months": [], "balance": data["total_balance"]}
|
row = {"name": name, "months": [], "balance": data["total_balance"], "unpaid_periods": ""}
|
||||||
|
unpaid_months = []
|
||||||
for m in sorted_months:
|
for m in sorted_months:
|
||||||
mdata = data["months"].get(m, {"expected": 0, "original_expected": 0, "paid": 0})
|
mdata = data["months"].get(m, {"expected": 0, "original_expected": 0, "paid": 0})
|
||||||
expected = mdata["expected"]
|
expected = mdata["expected"]
|
||||||
@@ -359,10 +364,12 @@ def reconcile_juniors_view():
|
|||||||
status = "partial"
|
status = "partial"
|
||||||
cell_text = f"{paid}/{expected}"
|
cell_text = f"{paid}/{expected}"
|
||||||
amount_to_pay = expected - paid
|
amount_to_pay = expected - paid
|
||||||
|
unpaid_months.append(month_labels[m])
|
||||||
else:
|
else:
|
||||||
status = "unpaid"
|
status = "unpaid"
|
||||||
cell_text = f"UNPAID {expected}"
|
cell_text = f"UNPAID {expected}"
|
||||||
amount_to_pay = expected
|
amount_to_pay = expected
|
||||||
|
unpaid_months.append(month_labels[m])
|
||||||
elif paid > 0:
|
elif paid > 0:
|
||||||
status = "surplus"
|
status = "surplus"
|
||||||
cell_text = f"PAID {paid}"
|
cell_text = f"PAID {paid}"
|
||||||
@@ -374,6 +381,7 @@ def reconcile_juniors_view():
|
|||||||
"month": month_labels[m]
|
"month": month_labels[m]
|
||||||
})
|
})
|
||||||
|
|
||||||
|
row["unpaid_periods"] = ", ".join(unpaid_months) if unpaid_months else ("Older debt" if data["total_balance"] < 0 else "")
|
||||||
row["balance"] = data["total_balance"]
|
row["balance"] = data["total_balance"]
|
||||||
formatted_results.append(row)
|
formatted_results.append(row)
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,12 @@ JUNIOR_FEE_DEFAULT = 500 # CZK for 2+ practices
|
|||||||
JUNIOR_MONTHLY_RATE = {
|
JUNIOR_MONTHLY_RATE = {
|
||||||
"2025-09": 250
|
"2025-09": 250
|
||||||
}
|
}
|
||||||
MERGED_MONTHS = {
|
ADULT_MERGED_MONTHS = {
|
||||||
|
#"2025-12": "2026-01", # keys are merged into values
|
||||||
|
#"2025-09": "2025-10"
|
||||||
|
}
|
||||||
|
|
||||||
|
JUNIOR_MERGED_MONTHS = {
|
||||||
"2025-12": "2026-01", # keys are merged into values
|
"2025-12": "2026-01", # keys are merged into values
|
||||||
"2025-09": "2025-10"
|
"2025-09": "2025-10"
|
||||||
}
|
}
|
||||||
@@ -65,13 +70,13 @@ def parse_dates(header_row: list[str]) -> list[tuple[int, datetime]]:
|
|||||||
return dates
|
return dates
|
||||||
|
|
||||||
|
|
||||||
def group_by_month(dates: list[tuple[int, datetime]]) -> dict[str, list[int]]:
|
def group_by_month(dates: list[tuple[int, datetime]], merged_months: dict[str, str]) -> dict[str, list[int]]:
|
||||||
"""Group column indices by YYYY-MM, handling merged months."""
|
"""Group column indices by YYYY-MM, handling merged months."""
|
||||||
months: dict[str, list[int]] = {}
|
months: dict[str, list[int]] = {}
|
||||||
for col, dt in dates:
|
for col, dt in dates:
|
||||||
key = dt.strftime("%Y-%m")
|
key = dt.strftime("%Y-%m")
|
||||||
# Apply merged month mapping if configured
|
# Apply merged month mapping if configured
|
||||||
target_key = MERGED_MONTHS.get(key, key)
|
target_key = merged_months.get(key, key)
|
||||||
months.setdefault(target_key, []).append(col)
|
months.setdefault(target_key, []).append(col)
|
||||||
return months
|
return months
|
||||||
|
|
||||||
@@ -172,7 +177,7 @@ def get_members_with_fees() -> tuple[list[tuple[str, str, dict[str, int]]], list
|
|||||||
if not dates:
|
if not dates:
|
||||||
return [], []
|
return [], []
|
||||||
|
|
||||||
months = group_by_month(dates)
|
months = group_by_month(dates, ADULT_MERGED_MONTHS)
|
||||||
sorted_months = sorted(months.keys())
|
sorted_months = sorted(months.keys())
|
||||||
members_raw = get_members(rows)
|
members_raw = get_members(rows)
|
||||||
|
|
||||||
@@ -211,8 +216,8 @@ def get_junior_members_with_fees() -> tuple[list[tuple[str, str, dict[str, tuple
|
|||||||
main_dates = parse_dates(main_rows[0])
|
main_dates = parse_dates(main_rows[0])
|
||||||
junior_dates = parse_dates(junior_rows[0])
|
junior_dates = parse_dates(junior_rows[0])
|
||||||
|
|
||||||
main_months = group_by_month(main_dates)
|
main_months = group_by_month(main_dates, JUNIOR_MERGED_MONTHS)
|
||||||
junior_months = group_by_month(junior_dates)
|
junior_months = group_by_month(junior_dates, JUNIOR_MERGED_MONTHS)
|
||||||
|
|
||||||
# Collect all unique sorted months
|
# Collect all unique sorted months
|
||||||
all_months = set(main_months.keys()).union(set(junior_months.keys()))
|
all_months = set(main_months.keys()).union(set(junior_months.keys()))
|
||||||
|
|||||||
@@ -290,9 +290,11 @@ def reconcile(
|
|||||||
|
|
||||||
# Initialize ledger
|
# Initialize ledger
|
||||||
ledger: dict[str, dict[str, dict]] = {}
|
ledger: dict[str, dict[str, dict]] = {}
|
||||||
|
other_ledger: dict[str, list] = {}
|
||||||
exceptions = exceptions or {}
|
exceptions = exceptions or {}
|
||||||
for name in member_names:
|
for name in member_names:
|
||||||
ledger[name] = {}
|
ledger[name] = {}
|
||||||
|
other_ledger[name] = []
|
||||||
for m in sorted_months:
|
for m in sorted_months:
|
||||||
# Robust normalization for lookup
|
# Robust normalization for lookup
|
||||||
norm_name = normalize(name)
|
norm_name = normalize(name)
|
||||||
@@ -328,12 +330,13 @@ def reconcile(
|
|||||||
|
|
||||||
# Strip markers like [?]
|
# Strip markers like [?]
|
||||||
person_str = re.sub(r"\[\?\]\s*", "", person_str)
|
person_str = re.sub(r"\[\?\]\s*", "", person_str)
|
||||||
|
is_other = purpose_str.lower().startswith("other:")
|
||||||
|
|
||||||
if person_str and purpose_str:
|
if person_str and purpose_str:
|
||||||
# We have pre-matched data (either from script or manual)
|
# We have pre-matched data (either from script or manual)
|
||||||
# Support multiple people/months in the comma-separated string
|
# Support multiple people/months in the comma-separated string
|
||||||
matched_members = [(p.strip(), "auto") for p in person_str.split(",") if p.strip()]
|
matched_members = [(p.strip(), "auto") for p in person_str.split(",") if p.strip()]
|
||||||
matched_months = [m.strip() for m in purpose_str.split(",") if m.strip()]
|
matched_months = [purpose_str] if is_other else [m.strip() for m in purpose_str.split(",") if m.strip()]
|
||||||
|
|
||||||
# Use Inferred Amount if available, otherwise bank Amount
|
# Use Inferred Amount if available, otherwise bank Amount
|
||||||
amount = tx.get("inferred_amount")
|
amount = tx.get("inferred_amount")
|
||||||
@@ -359,6 +362,21 @@ def reconcile(
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
# Allocate payment across matched members and months
|
# Allocate payment across matched members and months
|
||||||
|
if is_other:
|
||||||
|
num_allocations = len(matched_members)
|
||||||
|
per_allocation = amount / num_allocations if num_allocations > 0 else 0
|
||||||
|
for member_name, confidence in matched_members:
|
||||||
|
if member_name in other_ledger:
|
||||||
|
other_ledger[member_name].append({
|
||||||
|
"amount": per_allocation,
|
||||||
|
"date": tx["date"],
|
||||||
|
"sender": tx["sender"],
|
||||||
|
"message": tx["message"],
|
||||||
|
"purpose": purpose_str,
|
||||||
|
"confidence": confidence,
|
||||||
|
})
|
||||||
|
continue
|
||||||
|
|
||||||
num_allocations = len(matched_members) * len(matched_months)
|
num_allocations = len(matched_members) * len(matched_months)
|
||||||
per_allocation = amount / num_allocations if num_allocations > 0 else 0
|
per_allocation = amount / num_allocations if num_allocations > 0 else 0
|
||||||
|
|
||||||
@@ -399,6 +417,7 @@ def reconcile(
|
|||||||
name: {
|
name: {
|
||||||
"tier": member_tiers[name],
|
"tier": member_tiers[name],
|
||||||
"months": ledger[name],
|
"months": ledger[name],
|
||||||
|
"other_transactions": other_ledger[name],
|
||||||
"total_balance": final_balances[name]
|
"total_balance": final_balances[name]
|
||||||
}
|
}
|
||||||
for name in member_names
|
for name in member_names
|
||||||
|
|||||||
@@ -471,8 +471,12 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
<td class="{% if row.balance > 0 %}balance-pos{% elif row.balance < 0 %}balance-neg{% endif %}">
|
<td class="{% if row.balance > 0 %}balance-pos{% elif row.balance < 0 %}balance-neg{% endif %}" style="position: relative;">
|
||||||
{{ "%+d"|format(row.balance) if row.balance != 0 else "0" }}
|
{{ "%+d"|format(row.balance) if row.balance != 0 else "0" }}
|
||||||
|
{% if row.balance < 0 %}
|
||||||
|
<button class="pay-btn"
|
||||||
|
onclick="showPayQR('{{ row.name|e }}', {{ -row.balance }}, '{{ row.unpaid_periods|e }}')">Pay All</button>
|
||||||
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
@@ -576,6 +580,13 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="modal-section" id="modalOtherSection" style="display: none;">
|
||||||
|
<div class="modal-section-title">Other Transactions</div>
|
||||||
|
<div id="modalOtherList" class="tx-list">
|
||||||
|
<!-- Filled by JS -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="modal-section">
|
<div class="modal-section">
|
||||||
<div class="modal-section-title">Payment History</div>
|
<div class="modal-section-title">Payment History</div>
|
||||||
<div id="modalTxList" class="tx-list">
|
<div id="modalTxList" class="tx-list">
|
||||||
@@ -684,6 +695,30 @@
|
|||||||
exSection.style.display = 'none';
|
exSection.style.display = 'none';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const otherList = document.getElementById('modalOtherList');
|
||||||
|
const otherSection = document.getElementById('modalOtherSection');
|
||||||
|
otherList.innerHTML = '';
|
||||||
|
|
||||||
|
if (data.other_transactions && data.other_transactions.length > 0) {
|
||||||
|
otherSection.style.display = 'block';
|
||||||
|
data.other_transactions.forEach(tx => {
|
||||||
|
const displayPurpose = tx.purpose || 'Other';
|
||||||
|
const item = document.createElement('div');
|
||||||
|
item.className = 'tx-item';
|
||||||
|
item.innerHTML = `
|
||||||
|
<div class="tx-meta">${tx.date} | ${displayPurpose}</div>
|
||||||
|
<div class="tx-main">
|
||||||
|
<span class="tx-amount" style="color: #66ccff;">${tx.amount} CZK</span>
|
||||||
|
<span class="tx-sender">${tx.sender}</span>
|
||||||
|
</div>
|
||||||
|
<div class="tx-msg">${tx.message || ''}</div>
|
||||||
|
`;
|
||||||
|
otherList.appendChild(item);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
otherSection.style.display = 'none';
|
||||||
|
}
|
||||||
|
|
||||||
const txList = document.getElementById('modalTxList');
|
const txList = document.getElementById('modalTxList');
|
||||||
txList.innerHTML = '';
|
txList.innerHTML = '';
|
||||||
|
|
||||||
|
|||||||
@@ -471,8 +471,12 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
<td class="{% if row.balance > 0 %}balance-pos{% elif row.balance < 0 %}balance-neg{% endif %}">
|
<td class="{% if row.balance > 0 %}balance-pos{% elif row.balance < 0 %}balance-neg{% endif %}" style="position: relative;">
|
||||||
{{ "%+d"|format(row.balance) if row.balance != 0 else "0" }}
|
{{ "%+d"|format(row.balance) if row.balance != 0 else "0" }}
|
||||||
|
{% if row.balance < 0 %}
|
||||||
|
<button class="pay-btn"
|
||||||
|
onclick="showPayQR('{{ row.name|e }}', {{ -row.balance }}, '{{ row.unpaid_periods|e }}')">Pay All</button>
|
||||||
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
@@ -576,6 +580,13 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="modal-section" id="modalOtherSection" style="display: none;">
|
||||||
|
<div class="modal-section-title">Other Transactions</div>
|
||||||
|
<div id="modalOtherList" class="tx-list">
|
||||||
|
<!-- Filled by JS -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="modal-section">
|
<div class="modal-section">
|
||||||
<div class="modal-section-title">Payment History</div>
|
<div class="modal-section-title">Payment History</div>
|
||||||
<div id="modalTxList" class="tx-list">
|
<div id="modalTxList" class="tx-list">
|
||||||
@@ -684,6 +695,30 @@
|
|||||||
exSection.style.display = 'none';
|
exSection.style.display = 'none';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const otherList = document.getElementById('modalOtherList');
|
||||||
|
const otherSection = document.getElementById('modalOtherSection');
|
||||||
|
otherList.innerHTML = '';
|
||||||
|
|
||||||
|
if (data.other_transactions && data.other_transactions.length > 0) {
|
||||||
|
otherSection.style.display = 'block';
|
||||||
|
data.other_transactions.forEach(tx => {
|
||||||
|
const displayPurpose = tx.purpose || 'Other';
|
||||||
|
const item = document.createElement('div');
|
||||||
|
item.className = 'tx-item';
|
||||||
|
item.innerHTML = `
|
||||||
|
<div class="tx-meta">${tx.date} | ${displayPurpose}</div>
|
||||||
|
<div class="tx-main">
|
||||||
|
<span class="tx-amount" style="color: #66ccff;">${tx.amount} CZK</span>
|
||||||
|
<span class="tx-sender">${tx.sender}</span>
|
||||||
|
</div>
|
||||||
|
<div class="tx-msg">${tx.message || ''}</div>
|
||||||
|
`;
|
||||||
|
otherList.appendChild(item);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
otherSection.style.display = 'none';
|
||||||
|
}
|
||||||
|
|
||||||
const txList = document.getElementById('modalTxList');
|
const txList = document.getElementById('modalTxList');
|
||||||
txList.innerHTML = '';
|
txList.innerHTML = '';
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user