feat(admin): product catalog editor
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Successful in 11s
CI / integration (pull_request) Successful in 24s
CI / ui (pull_request) Has been skipped
CI / conformance (pull_request) Successful in 10s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m53s

The /_gm console gains a Catalog editor — the source of truth for products.
Create / edit / archive-unarchive products, their atom composition and per-rail
prices (RUB via direct / VOTE via vk / XTR via telegram / CHIP value), and
hard-delete only a never-transacted product (an order or ledger reference forces
archive-only, backed by the FK RESTRICT). The archived flag reuses the existing
product.active. Activation revalidates the sellable shape — a pack (the chips
atom ⇒ a money price per rail, chips-only) or a value (no chips ⇒ a CHIP price);
a tournament-bearing product is composable but never sellable yet.

Backed by payments AdminCatalog / CreateProduct / UpdateProduct /
SetProductActive / DeleteProduct + a pure validateProduct.

Tests: validateProduct (pack / value / tournament / duplicate / shape); the
console editor end to end (create, edit, archive, delete-if-clean, refuse a
transacted delete).
This commit is contained in:
Ilia Denisov
2026-07-10 05:18:54 +02:00
parent aabb32081e
commit 0036b55618
11 changed files with 867 additions and 1 deletions
+48
View File
@@ -653,3 +653,51 @@ type FeedbackDetailView struct {
UserTZ string
Banned bool
}
// CatalogView is the product-catalog list page.
type CatalogView struct {
Products []ProductRow
}
// ProductRow is one product in the catalog list: its composition, prices, the archived flag
// (Active) and the transacted flag (which forbids a hard delete).
type ProductRow struct {
ID string
Title string
Active bool
Atoms []AtomRow
Prices []PriceRow
Transacted bool
}
// AtomRow is one atom line of a product row.
type AtomRow struct {
Atom string
Quantity int
}
// PriceRow is one price of a product: the method ("" for a value's CHIP price), the currency, and
// the amount in that currency's minor units.
type PriceRow struct {
Method string
Currency string
Amount int64
}
// ProductFormView is the product edit form, pre-filled from the current composition. Atom quantities
// and prices are flattened to the fixed fields the form offers (0 = absent); Transacted disables the
// delete action.
type ProductFormView struct {
ID string
Title string
Active bool
Chips int
Hints int
NoAds int
Tournament int
PriceRUB int64
PriceVote int64
PriceStar int64
PriceChip int64
Transacted bool
}