From 1d77fbd8810059050897930a21c55f6804229611 Mon Sep 17 00:00:00 2001 From: HunterCustom Date: Sun, 30 Aug 2026 09:31:06 -0400 Subject: [PATCH 01/12] Fix inventory selected printing metadata --- src/services/inventoryService.js | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/services/inventoryService.js b/src/services/inventoryService.js index dc7795d..1e51268 100644 --- a/src/services/inventoryService.js +++ b/src/services/inventoryService.js @@ -17,7 +17,7 @@ export function getInventory(userId, filters = {}) { } = filters; const offset = (page - 1) * limit; - const params = [userId]; + const params = [userId, userId, userId]; const countParams = [userId]; // Base query - get all owned cards with their details @@ -30,7 +30,18 @@ export function getInventory(userId, filters = {}) { c.colors, c.type_line, c.oracle_text, - (SELECT p.image_url FROM printings p WHERE p.card_id = c.id AND p.image_url IS NOT NULL LIMIT 1) as image_url, + (SELECT p.image_url + FROM owned_printings op + JOIN printings p ON op.printing_id = p.id + WHERE op.user_id = ? AND p.card_id = c.id AND p.image_url IS NOT NULL + ORDER BY op.quantity DESC, op.id ASC + LIMIT 1) as image_url, + (SELECT p.id + FROM owned_printings op + JOIN printings p ON op.printing_id = p.id + WHERE op.user_id = ? AND p.card_id = c.id AND p.image_url IS NOT NULL + ORDER BY op.quantity DESC, op.id ASC + LIMIT 1) as selected_printing_id, ( SELECT COALESCE(SUM(op.quantity), 0) FROM owned_printings op From be538acf817e86d30f2cc14b183965c215a25e0d Mon Sep 17 00:00:00 2001 From: HunterCustom Date: Sun, 30 Aug 2026 09:32:11 -0400 Subject: [PATCH 02/12] Support explicit inventory printing replacements --- client/src/services/api.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/services/api.js b/client/src/services/api.js index 01c9324..aba9daa 100644 --- a/client/src/services/api.js +++ b/client/src/services/api.js @@ -135,10 +135,10 @@ class ApiClient { return this.request(`/cards/${cardId}/ownership-usage`); } - async setOwnedPrintingQuantity(printingId, quantity) { + async setOwnedPrintingQuantity(printingId, quantity, replacementPrintingId = null) { return this.request(`/cards/printings/${printingId}/quantity`, { method: 'POST', - body: JSON.stringify({ quantity }), + body: JSON.stringify({ quantity, replacementPrintingId }), }); } From 25183ba70ea6f56c46b68774d35e57cf4c0bc350 Mon Sep 17 00:00:00 2001 From: HunterCustom Date: Sun, 30 Aug 2026 09:32:14 -0400 Subject: [PATCH 03/12] Pass replacement printing through cards API --- src/routes/cards.js | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/routes/cards.js b/src/routes/cards.js index 4b82ba4..513a66f 100644 --- a/src/routes/cards.js +++ b/src/routes/cards.js @@ -250,13 +250,22 @@ router.post('/printings/:printingId/quantity', authenticate, (req, res, next) => try { const printingId = parseInt(req.params.printingId); const userId = req.user.id; - const { quantity } = req.body; + const { quantity, replacementPrintingId } = req.body; if (quantity === undefined || quantity === null) { return res.status(400).json({ error: 'Quantity is required' }); } - const result = setOwnedPrintingQuantity(userId, printingId, parseInt(quantity)); + const replacementId = replacementPrintingId === undefined || replacementPrintingId === null + ? null + : parseInt(replacementPrintingId); + + const result = setOwnedPrintingQuantity( + userId, + printingId, + parseInt(quantity), + replacementId + ); res.json(result); } catch (error) { next(error); From 0fb663cb16d16684cbb6be085105d03b75d538e5 Mon Sep 17 00:00:00 2001 From: HunterCustom Date: Sun, 30 Aug 2026 09:32:18 -0400 Subject: [PATCH 04/12] Keep deck printings aligned with inventory swaps --- src/services/cardService.js | 61 ++++++++++++++++++++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) diff --git a/src/services/cardService.js b/src/services/cardService.js index de92ff4..1b2b31c 100644 --- a/src/services/cardService.js +++ b/src/services/cardService.js @@ -649,7 +649,7 @@ export function getCardOwnedPrintings(userId, cardId) { * Add or update owned printing quantity * Also syncs with owned_cards table */ -export function setOwnedPrintingQuantity(userId, printingId, quantity) { +export function setOwnedPrintingQuantity(userId, printingId, quantity, replacementPrintingId = null) { // Get the card_id for this printing const printing = db.get( `SELECT card_id FROM printings WHERE id = ?`, @@ -663,6 +663,65 @@ export function setOwnedPrintingQuantity(userId, printingId, quantity) { const cardId = printing.card_id; if (quantity <= 0) { + if (replacementPrintingId) { + const replacement = db.get( + `SELECT card_id FROM printings WHERE id = ?`, + [replacementPrintingId] + ); + + if (!replacement || replacement.card_id !== cardId) { + throw new Error('Replacement printing must be for the same card'); + } + + const affectedDeckRows = db.all( + `SELECT dc.id, dc.deck_id, dc.quantity, dc.is_sideboard, dc.is_commander, + COALESCE(dc.board_type, CASE WHEN dc.is_sideboard = 1 THEN 'sideboard' ELSE 'mainboard' END) as board_type + FROM deck_cards dc + JOIN decks d ON d.id = dc.deck_id + WHERE dc.printing_id = ? AND d.user_id = ?`, + [printingId, userId] + ); + + for (const deckRow of affectedDeckRows) { + // The database uniqueness constraint is based on deck/is_sideboard/printing. + // If the replacement already exists in the same logical board, merge the rows. + // If it exists in a different logical board that shares the legacy is_sideboard + // value (for example mainboard vs maybeboard), leave this row unchanged instead + // of collapsing cards across boards. + const existingDeckRow = db.get( + `SELECT id, quantity, is_commander, + COALESCE(board_type, CASE WHEN is_sideboard = 1 THEN 'sideboard' ELSE 'mainboard' END) as board_type + FROM deck_cards + WHERE deck_id = ? AND printing_id = ? AND is_sideboard = ?`, + [deckRow.deck_id, replacementPrintingId, deckRow.is_sideboard] + ); + + if (existingDeckRow) { + if (existingDeckRow.board_type !== deckRow.board_type) { + continue; + } + + db.run( + `UPDATE deck_cards + SET quantity = ?, is_commander = ? + WHERE id = ?`, + [ + existingDeckRow.quantity + deckRow.quantity, + existingDeckRow.is_commander || deckRow.is_commander ? 1 : 0, + existingDeckRow.id + ] + ); + + db.run(`DELETE FROM deck_cards WHERE id = ?`, [deckRow.id]); + } else { + db.run( + `UPDATE deck_cards SET printing_id = ? WHERE id = ?`, + [replacementPrintingId, deckRow.id] + ); + } + } + } + // Remove if quantity is 0 or less db.run( `DELETE FROM owned_printings WHERE user_id = ? AND printing_id = ?`, From b60878644fe92b0d101e99ffabaf227be774d3dc Mon Sep 17 00:00:00 2001 From: HunterCustom Date: Sun, 30 Aug 2026 09:32:39 -0400 Subject: [PATCH 05/12] Use selected printing in card details --- client/src/components/cards.js | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/client/src/components/cards.js b/client/src/components/cards.js index 740df99..5157191 100644 --- a/client/src/components/cards.js +++ b/client/src/components/cards.js @@ -587,7 +587,7 @@ async function quickAddCard(cardId, deckId) { } } -export async function showCardDetail(cardId) { +export async function showCardDetail(cardId, printingId = null) { try { showLoading(); const [cardResult, ownershipResult] = await Promise.all([ @@ -596,7 +596,11 @@ export async function showCardDetail(cardId) { ]); const card = cardResult.card; const ownership = ownershipResult; - const firstPrinting = card.printings && card.printings.length > 0 ? card.printings[0] : null; + const firstPrinting = card.printings && card.printings.length > 0 + ? (printingId !== null + ? (card.printings.find(p => p.id == printingId) || card.printings[0]) + : card.printings[0]) + : null; hideLoading(); // Parse type line to extract supertypes, types, and subtypes @@ -1462,15 +1466,16 @@ async function showSwapPrintingModal(card, fromPrintingId, quantity, cardId, own try { showLoading(); // Remove from old printing - await api.setOwnedPrintingQuantity(fromPrintingId, 0); + await api.setOwnedPrintingQuantity(fromPrintingId, 0, toPrintingId); // Add to new printing (will add to existing if already owned) const existingOwned = ownership.ownedPrintings.find(op => op.printing_id === toPrintingId); const newQuantity = (existingOwned ? existingOwned.quantity : 0) + quantity; await api.setOwnedPrintingQuantity(toPrintingId, newQuantity); showToast('Printing changed!', 'success', 2000); - // Reload card detail - await showCardDetail(cardId); + window.dispatchEvent(new CustomEvent('inventory:refresh')); + // Reload card detail using the newly selected printing + await showCardDetail(cardId, toPrintingId); hideLoading(); } catch (error) { hideLoading(); From acf2bd3ae58ab86acd211cb86bcd3f468d1e7d56 Mon Sep 17 00:00:00 2001 From: HunterCustom Date: Sun, 30 Aug 2026 09:32:43 -0400 Subject: [PATCH 06/12] Open inventory details on owned printing --- client/src/components/inventory.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/client/src/components/inventory.js b/client/src/components/inventory.js index 390b2d2..2d5b926 100644 --- a/client/src/components/inventory.js +++ b/client/src/components/inventory.js @@ -19,8 +19,9 @@ let selectedCards = new Set(); // Track selected card IDs for multi-select let selectMode = false; // Whether multi-select mode is active export function setupInventory() { - // Load inventory data when page is shown + // Load inventory data when page is shown or when a printing swap changes ownership. window.addEventListener('page:inventory', loadInventoryData); + window.addEventListener('inventory:refresh', loadInventoryData); // Setup filter listeners setupFilterListeners(); @@ -887,7 +888,8 @@ function renderGridView(container) { cb.innerHTML = ``; } } else { - await showCardDetail(cardId); + const card = inventoryData.cards.find(c => c.card_id === cardId); + await showCardDetail(cardId, card?.selected_printing_id || null); } }); }); @@ -960,7 +962,8 @@ function renderListView(container) { cb.innerHTML = ``; } } else { - await showCardDetail(cardId); + const card = inventoryData.cards.find(c => c.card_id === cardId); + await showCardDetail(cardId, card?.selected_printing_id || null); } }); }); From b3d0a2d9aaa3f62ef93b0ee6eb8cd89c915880a9 Mon Sep 17 00:00:00 2001 From: HunterCustom Date: Sun, 30 Aug 2026 09:32:47 -0400 Subject: [PATCH 07/12] Keep deck detail modal on deck printing --- client/src/components/deckBuilder.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/client/src/components/deckBuilder.js b/client/src/components/deckBuilder.js index c1595b0..89cc59e 100644 --- a/client/src/components/deckBuilder.js +++ b/client/src/components/deckBuilder.js @@ -1738,7 +1738,7 @@ async function showCardModal(printingId) { try { const card = currentDeck.cards.find(c => c.printing_id == printingId); if (card && card.card_id) { - await showCardDetail(card.card_id); + await showCardDetail(card.card_id, card.printing_id); } else { console.error('Card not found or missing card_id:', { printingId, card, currentDeck: currentDeck?.cards?.length }); showToast('Card details not available', 'warning'); @@ -2476,8 +2476,9 @@ function renderExampleHand() { // Click to show modal cardEl.addEventListener('click', async () => { const cardId = cardEl.dataset.cardId; + const printingId = cardEl.dataset.printingId; if (cardId) { - await showCardDetail(cardId); + await showCardDetail(cardId, printingId || null); } }); From 5390e18241ba8f270ee06aa0c35a8a597e46d6d0 Mon Sep 17 00:00:00 2001 From: HunterCustom Date: Sun, 30 Aug 2026 10:12:33 -0400 Subject: [PATCH 08/12] Make inventory printing swaps atomic --- src/services/cardService.js | 178 ++++++++++++++++++++++++------------ 1 file changed, 118 insertions(+), 60 deletions(-) diff --git a/src/services/cardService.js b/src/services/cardService.js index 1b2b31c..b5b5d2a 100644 --- a/src/services/cardService.js +++ b/src/services/cardService.js @@ -649,7 +649,7 @@ export function getCardOwnedPrintings(userId, cardId) { * Add or update owned printing quantity * Also syncs with owned_cards table */ -export function setOwnedPrintingQuantity(userId, printingId, quantity, replacementPrintingId = null) { +export function setOwnedPrintingQuantity(userId, printingId, quantity) { // Get the card_id for this printing const printing = db.get( `SELECT card_id FROM printings WHERE id = ?`, @@ -663,65 +663,6 @@ export function setOwnedPrintingQuantity(userId, printingId, quantity, replaceme const cardId = printing.card_id; if (quantity <= 0) { - if (replacementPrintingId) { - const replacement = db.get( - `SELECT card_id FROM printings WHERE id = ?`, - [replacementPrintingId] - ); - - if (!replacement || replacement.card_id !== cardId) { - throw new Error('Replacement printing must be for the same card'); - } - - const affectedDeckRows = db.all( - `SELECT dc.id, dc.deck_id, dc.quantity, dc.is_sideboard, dc.is_commander, - COALESCE(dc.board_type, CASE WHEN dc.is_sideboard = 1 THEN 'sideboard' ELSE 'mainboard' END) as board_type - FROM deck_cards dc - JOIN decks d ON d.id = dc.deck_id - WHERE dc.printing_id = ? AND d.user_id = ?`, - [printingId, userId] - ); - - for (const deckRow of affectedDeckRows) { - // The database uniqueness constraint is based on deck/is_sideboard/printing. - // If the replacement already exists in the same logical board, merge the rows. - // If it exists in a different logical board that shares the legacy is_sideboard - // value (for example mainboard vs maybeboard), leave this row unchanged instead - // of collapsing cards across boards. - const existingDeckRow = db.get( - `SELECT id, quantity, is_commander, - COALESCE(board_type, CASE WHEN is_sideboard = 1 THEN 'sideboard' ELSE 'mainboard' END) as board_type - FROM deck_cards - WHERE deck_id = ? AND printing_id = ? AND is_sideboard = ?`, - [deckRow.deck_id, replacementPrintingId, deckRow.is_sideboard] - ); - - if (existingDeckRow) { - if (existingDeckRow.board_type !== deckRow.board_type) { - continue; - } - - db.run( - `UPDATE deck_cards - SET quantity = ?, is_commander = ? - WHERE id = ?`, - [ - existingDeckRow.quantity + deckRow.quantity, - existingDeckRow.is_commander || deckRow.is_commander ? 1 : 0, - existingDeckRow.id - ] - ); - - db.run(`DELETE FROM deck_cards WHERE id = ?`, [deckRow.id]); - } else { - db.run( - `UPDATE deck_cards SET printing_id = ? WHERE id = ?`, - [replacementPrintingId, deckRow.id] - ); - } - } - } - // Remove if quantity is 0 or less db.run( `DELETE FROM owned_printings WHERE user_id = ? AND printing_id = ?`, @@ -778,6 +719,123 @@ export function setOwnedPrintingQuantity(userId, printingId, quantity, replaceme return { success: true, quantity }; } +/** + * Atomically move all owned copies from one printing to another. + * Deck rows that explicitly use the old owned printing move with it. + */ +export function swapOwnedPrinting(userId, fromPrintingId, toPrintingId) { + if (fromPrintingId === toPrintingId) { + throw new Error('Replacement printing must be different'); + } + + const source = db.get( + `SELECT op.id as owned_printing_id, op.quantity, p.card_id + FROM owned_printings op + JOIN printings p ON op.printing_id = p.id + WHERE op.user_id = ? AND op.printing_id = ?`, + [userId, fromPrintingId] + ); + + if (!source) { + throw new Error('Owned printing not found'); + } + + const replacement = db.get( + `SELECT card_id FROM printings WHERE id = ?`, + [toPrintingId] + ); + + if (!replacement || replacement.card_id !== source.card_id) { + throw new Error('Replacement printing must be for the same card'); + } + + return db.transaction(() => { + const affectedDeckRows = db.all( + `SELECT dc.id, dc.deck_id, dc.quantity, dc.is_sideboard, dc.is_commander, + COALESCE(dc.board_type, CASE WHEN dc.is_sideboard = 1 THEN 'sideboard' ELSE 'mainboard' END) as board_type + FROM deck_cards dc + JOIN decks d ON d.id = dc.deck_id + WHERE dc.printing_id = ? AND d.user_id = ?`, + [fromPrintingId, userId] + ); + + for (const deckRow of affectedDeckRows) { + const existingDeckRow = db.get( + `SELECT id, quantity, is_commander, + COALESCE(board_type, CASE WHEN is_sideboard = 1 THEN 'sideboard' ELSE 'mainboard' END) as board_type + FROM deck_cards + WHERE deck_id = ? AND printing_id = ? AND is_sideboard = ?`, + [deckRow.deck_id, toPrintingId, deckRow.is_sideboard] + ); + + if (existingDeckRow) { + // Legacy uniqueness is based on is_sideboard. Do not merge two logical + // boards (for example mainboard and maybeboard) that share that flag. + if (existingDeckRow.board_type !== deckRow.board_type) { + continue; + } + + db.run( + `UPDATE deck_cards + SET quantity = ?, is_commander = ? + WHERE id = ?`, + [ + existingDeckRow.quantity + deckRow.quantity, + existingDeckRow.is_commander || deckRow.is_commander ? 1 : 0, + existingDeckRow.id + ] + ); + db.run(`DELETE FROM deck_cards WHERE id = ?`, [deckRow.id]); + } else { + db.run( + `UPDATE deck_cards SET printing_id = ? WHERE id = ?`, + [toPrintingId, deckRow.id] + ); + } + } + + const existingReplacement = db.get( + `SELECT id, quantity + FROM owned_printings + WHERE user_id = ? AND printing_id = ?`, + [userId, toPrintingId] + ); + + if (existingReplacement) { + db.run( + `UPDATE owned_printings + SET quantity = ?, updated_at = CURRENT_TIMESTAMP + WHERE id = ?`, + [existingReplacement.quantity + source.quantity, existingReplacement.id] + ); + } else { + db.run( + `INSERT INTO owned_printings (user_id, printing_id, quantity) + VALUES (?, ?, ?)`, + [userId, toPrintingId, source.quantity] + ); + } + + db.run( + `DELETE FROM owned_printings WHERE id = ?`, + [source.owned_printing_id] + ); + + db.run( + `INSERT INTO owned_cards (user_id, card_id, quantity) VALUES (?, ?, 1) + ON CONFLICT(user_id, card_id) DO UPDATE SET quantity = 1`, + [userId, source.card_id] + ); + + return { + success: true, + fromPrintingId, + toPrintingId, + quantity: source.quantity + }; + }); +} + /** * Get all decks that contain a specific card */ From 5dba3641cdfc0088fadfaa542d806639cdc9d3ac Mon Sep 17 00:00:00 2001 From: HunterCustom Date: Sun, 30 Aug 2026 10:12:36 -0400 Subject: [PATCH 09/12] Add atomic printing swap endpoint --- src/routes/cards.js | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/src/routes/cards.js b/src/routes/cards.js index 513a66f..4256396 100644 --- a/src/routes/cards.js +++ b/src/routes/cards.js @@ -14,6 +14,7 @@ import { getCardOwnershipStatus, getCardOwnedPrintings, setOwnedPrintingQuantity, + swapOwnedPrinting, getCardOwnershipAndUsage, } from '../services/cardService.js'; import { authenticate } from '../middleware/auth.js'; @@ -242,6 +243,26 @@ router.get('/:id/ownership-usage', authenticate, (req, res, next) => { } }); +/** + * POST /api/cards/printings/:printingId/quantity + * Set owned quantity for a specific printing + */ +router.post('/printings/:printingId/swap', authenticate, (req, res, next) => { + try { + const fromPrintingId = parseInt(req.params.printingId); + const toPrintingId = parseInt(req.body.replacementPrintingId); + + if (!Number.isInteger(toPrintingId)) { + return res.status(400).json({ error: 'replacementPrintingId is required' }); + } + + const result = swapOwnedPrinting(req.user.id, fromPrintingId, toPrintingId); + res.json(result); + } catch (error) { + next(error); + } +}); + /** * POST /api/cards/printings/:printingId/quantity * Set owned quantity for a specific printing @@ -250,22 +271,13 @@ router.post('/printings/:printingId/quantity', authenticate, (req, res, next) => try { const printingId = parseInt(req.params.printingId); const userId = req.user.id; - const { quantity, replacementPrintingId } = req.body; + const { quantity } = req.body; if (quantity === undefined || quantity === null) { return res.status(400).json({ error: 'Quantity is required' }); } - const replacementId = replacementPrintingId === undefined || replacementPrintingId === null - ? null - : parseInt(replacementPrintingId); - - const result = setOwnedPrintingQuantity( - userId, - printingId, - parseInt(quantity), - replacementId - ); + const result = setOwnedPrintingQuantity(userId, printingId, parseInt(quantity)); res.json(result); } catch (error) { next(error); From beccce15e6a9dcc4f7a29bbe5553c700279d723b Mon Sep 17 00:00:00 2001 From: HunterCustom Date: Sun, 30 Aug 2026 10:12:42 -0400 Subject: [PATCH 10/12] Use dedicated printing swap API --- client/src/services/api.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/client/src/services/api.js b/client/src/services/api.js index aba9daa..f112426 100644 --- a/client/src/services/api.js +++ b/client/src/services/api.js @@ -135,10 +135,17 @@ class ApiClient { return this.request(`/cards/${cardId}/ownership-usage`); } - async setOwnedPrintingQuantity(printingId, quantity, replacementPrintingId = null) { + async setOwnedPrintingQuantity(printingId, quantity) { return this.request(`/cards/printings/${printingId}/quantity`, { method: 'POST', - body: JSON.stringify({ quantity, replacementPrintingId }), + body: JSON.stringify({ quantity }), + }); + } + + async swapOwnedPrinting(fromPrintingId, replacementPrintingId) { + return this.request(`/cards/printings/${fromPrintingId}/swap`, { + method: 'POST', + body: JSON.stringify({ replacementPrintingId }), }); } From 2c6d8de07d82825888644220020216f1f854fc71 Mon Sep 17 00:00:00 2001 From: HunterCustom Date: Sun, 30 Aug 2026 10:12:45 -0400 Subject: [PATCH 11/12] Swap owned printings in one request --- client/src/components/cards.js | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/client/src/components/cards.js b/client/src/components/cards.js index 5157191..ff5e2d8 100644 --- a/client/src/components/cards.js +++ b/client/src/components/cards.js @@ -1465,12 +1465,8 @@ async function showSwapPrintingModal(card, fromPrintingId, quantity, cardId, own try { showLoading(); - // Remove from old printing - await api.setOwnedPrintingQuantity(fromPrintingId, 0, toPrintingId); - // Add to new printing (will add to existing if already owned) - const existingOwned = ownership.ownedPrintings.find(op => op.printing_id === toPrintingId); - const newQuantity = (existingOwned ? existingOwned.quantity : 0) + quantity; - await api.setOwnedPrintingQuantity(toPrintingId, newQuantity); + // Move inventory and matching deck usage together in one transaction. + await api.swapOwnedPrinting(fromPrintingId, toPrintingId); showToast('Printing changed!', 'success', 2000); window.dispatchEvent(new CustomEvent('inventory:refresh')); From 7f3412a57921d892465d729118b0dd3c6e0e582b Mon Sep 17 00:00:00 2001 From: HunterCustom Date: Sun, 30 Aug 2026 10:13:02 -0400 Subject: [PATCH 12/12] Clarify printing swap route documentation --- src/routes/cards.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/routes/cards.js b/src/routes/cards.js index 4256396..4e59ccb 100644 --- a/src/routes/cards.js +++ b/src/routes/cards.js @@ -244,8 +244,8 @@ router.get('/:id/ownership-usage', authenticate, (req, res, next) => { }); /** - * POST /api/cards/printings/:printingId/quantity - * Set owned quantity for a specific printing + * POST /api/cards/printings/:printingId/swap + * Atomically move owned copies to another printing */ router.post('/printings/:printingId/swap', authenticate, (req, res, next) => { try {