{% extends "base.html" %} {% block title %}Listing run · foilstack{% endblock %} {% block status %}{{ card_count }} cards · {{ line_count }} listings · {{ rule_obj.name }} · {{ run_value|money }} at list{% endblock %} {% block screen %}

Listing run

{{ card_count }} card{{ '' if card_count == 1 else 's' }} {% if line_count != card_count %}· {{ line_count }} listings{% endif %} {# A run chosen by filter says so in its own terms. The seller never saw most of these lines — that is the point of selecting by filter — so a bare "selected" would be the run declining to say what it is over, which is the shape of the bug that made this screen price the whole inventory under a heading reading `Not listed 75`. #} {% if described %}· {{ described }} {% elif selected_ids %}· selected{% else %}· nothing selected{% endif %}
Back to inventory {# Both buttons count what they would change, not what is on screen, and both name the channels they would change it on. The count alone is ambiguous the moment a second channel is ticked: "Mark 6" against six rows already reading "listed · tcgplayer" looks like a bug until you notice the eBay box, and the number moves when you tick it. "Mark 6 on TCGplayer" rather than "Mark 6 as listed on TCGplayer", which is what this said first: the bar is captured at 1000px for the README animation and the landing hero, and the longer pair wrapped it onto two rows there. The verb it loses is in the title and in the pills the button produces, and the shorter form reads as the exact undo of the button beside it — which the longer one did not. #} {# Shown only when there is something on a picked channel to take off it. No disabled twin, unlike the button beside it: "nothing here is listed" is already what a live Mark button and an empty status column say. #} {% if unmark_ids %} {% endif %} {% if mark_ids %} {% elif card_count %} {# ...and nothing at all when there is no run. This twin says "everything here is already listed", which over an empty selection read "All 0 listed on TCGplayer" — a sentence about nothing, in the place the screen puts its most consequential button. #} {% endif %}
Channels
{% for c in channels %}
{{ c.name }}
{{ c.note }}
{% if c.exporter %}
{{ c.exporter.columns|length }} columns · {{ c.exporter.filename }}
{% endif %}
{% endfor %}
A channel here is a CSV format, not a connection. Nothing is sent to a marketplace on your behalf. You download the file and upload it yourself.
Pricing rule
{% for r in rules %}
{{ r.name }}
{{ r.formula }}
{% endfor %}
Applied on top of the condition discount. “Low + $0.01” is an approximation: the catalogue gives a market price, not the current lowest listing.
{# The floor is a control and not a caption. It used to print `inventory.FLOOR`, which was one number for every seller on the install — right for a bulk dealer clearing commons at pennies and wrong for a shop that will not put a card in an envelope under a dollar. A GET back to this same run, so applying one re-prices what is on screen rather than starting a new selection. #}
{% for k, v in floor_form %} {% endfor %}
{# Which floor is in force, and whether it is the saved one. A run priced under a number the seller never saved must never be able to pass for their settings — and the same rule backwards, a saved floor must not look like a one-off. #}
{% if floor_override %} This run only. Your floor is {{ account_floor|money }}. {% else %} Your floor, on every screen. Nothing lists below it. {% endif %}
{# A real button, and present in both states rather than appearing only once the floor has been changed. It was a `linkish` span that showed up after Apply, which read as a sentence rather than an action — the first person to use this concluded the control could not save at all and that a floor was per-export. The disabled twin is the same answer the bar above gives with "All 21 listed on TCGplayer": saying what the button would do, greyed, is what makes it findable before there is anything to press it for. #} {% if floor_override %} {% else %} {% endif %} {# "at list", not "listed value": on this screen "listed" now means a row marked as being on a marketplace, and the same word for the run's total at list price made the summary read as the value of the marked half. #} {# Only when there is a run. These are its two figures, and over an empty selection they read `$0.00` and `+$0.00` — true, and a summary of nothing, next to a floor control that is still worth using. #} {% if rows %}
at list   {{ run_value|money }}
vs market   {{ '+' if delta >= 0 }}{{ delta|money }}
{% endif %}
{# Offered only when there is a run to download. With nothing selected both of these lead into the 400 the export answers an empty selection with — a button that cannot work, styled like one that can, which is what got the TCGplayer CSV removed from the inventory bar. #} {% if rows %}
Download
{% for c in channels %} {% if c.on and c.exporter %} {% if c.match_href %}
{# A pricing export is large and the upload is the whole wait, so this form is the one on the site that needs to say it is working. No `display` is set on it in CSS, so `[hidden]` is left to the user agent rather than being overridden by a class of equal specificity. #}
Needs your own Export Filtered CSV from TCGplayer’s pricing screen: their ids name a card and a condition, so only their file has them. The quantities in it are read for one thing — the file adds what you own beyond what you already have listed there, and takes any surplus back down.
{% if run_sets %} {# Named so the export can be filtered before it is downloaded. An unfiltered Magic product line is ~800,000 rows and over 100 MB, sent to match a few dozen cards, and that transfer is the whole wait. #}
Filter that export before you download it — this run only needs: {% for g in run_sets %}
{{ g.line }} {% for name in g.sets %}{{ name }}{% endfor %} {% if g.more %}+{{ g.more }} more{% endif %}
{% endfor %} {% if run_sets|length > 1 %}
One upload is one product line, so this run needs an export and a run per line. Filter inventory by game first.
{% endif %}
{% endif %}
{% else %} {{ c.exporter.label }} CSV {% endif %} {% endif %} {% endfor %} {% endif %}
{% if rows %} {% endif %} {% for r in rows %} {% endfor %}
CARD SKU CND QTY MARKET LIST PRICE STATUS
{{ r.name }} {{ r.sku }} {{ r.condition }} {{ r.quantity }} {{ r.market|money if r.market is not none else '—' }} {{ r.list_price|money if r.list_price is not none else '—' }} {% if r.listed_partly %}{{ r.listed_count }} of {{ r.quantity }} listed · {{ r.listed_channels }} {% elif r.listed %}listed · {{ r.listed_channels }} {% else %}ready{% endif %}
{% if rows_hidden %} {# The run is not truncated and the file is not short: this is the table declining to paint fifty thousand rows. Said in those words because a seller who reads it as a truncated export has no obvious way to check, and would be right not to trust the CSV. #}
showing the first {{ shown_label }} of {{ line_label }} lines · the run and its file cover all {{ line_label }}
{% endif %} {% if not rows %} {# Arriving here with no selection used to price the seller's whole inventory and offer to mark all of it. It says what it has instead, and offers the widest useful run as a *click* — a stated `?sel=all&listed=unlisted` that reads back in its own terms — rather than as the thing that happens to you for using the nav bar. #}

nothing selected

Pick rows on the inventory screen and press List selected →.

{% if unlisted_count %} {# No count on this button, deliberately. `listed=unlisted` matches inventory *lines* with an unlisted copy and takes those lines whole, so a line half on TCGplayer arrives with both copies — the run is reliably larger than a count of unlisted copies, and the first version of this promised 19,746 and delivered 28,160. The run states its own terms on arrival, which is where they can be computed correctly; the count survives only as the test for whether there is anything to offer. #}

List everything not yet listed →

{% endif %}
{% endif %}
Job log
{% for l in log %}
{{ l.t }}  {{ l.msg }}
{% else %}
nothing yet this session
{% endfor %}
{% endblock %} {% block scripts %} {% endblock %}