added and fix some of things

Signed-off-by: Kenneth Obsequio <k80308392@gmail.com>
This commit is contained in:
2026-08-03 12:03:02 +08:00
parent 6765c1faba
commit d246c09cdd
31 changed files with 724 additions and 510 deletions
@@ -259,6 +259,13 @@ exports.createAdvertisement = async (req, res) => {
try {
const advertisement = await Advertisement.build({ placement, type: entry.format, createdBy });
await applyAdvertisementFields(advertisement, req.body);
// No manual "order" input in the UI anymore — new ads always append to
// the end of their placement's priority list rather than colliding at 0.
if (req.body.order === undefined) {
advertisement.order = await Advertisement.count({ where: { placement, ...notDeleted }, transaction: t });
}
await advertisement.save({ transaction: t });
await t.commit();
@@ -305,6 +312,57 @@ exports.updateAdvertisement = async (req, res) => {
}
};
// ─── REORDER ──────────────────────────────────────────────────────────────────
// `order` is scoped per placement (mirrors controllers/client/advertisements.controller.js's
// getActiveAdvertisement[List], which picks the lowest `order` within a placement to show
// first) — Move Up/Down swaps position among siblings sharing the same placement, then
// re-sequences the whole group to 0..n-1. Re-sequencing (not just swapping the two `order`
// values) is what makes this self-healing against legacy ties, since every ad defaulted to
// order: 0 before this feature existed — a plain swap between two tied rows would no-op.
exports.reorderAdvertisement = async (req, res) => {
try {
const { advertisementId } = req.params;
const { direction } = req.body;
if (!["up", "down"].includes(direction)) return R.error(res, "direction must be 'up' or 'down'.", 400);
const advertisement = await Advertisement.findOne({ where: { advertisement_id: advertisementId, ...notDeleted } });
if (!advertisement) return R.error(res, "Advertisement not found.", 404);
const group = await Advertisement.findAll({
where: { placement: advertisement.placement, ...notDeleted },
order: [["order", "ASC"], ["createdAt", "DESC"]],
});
const index = group.findIndex((a) => a.advertisement_id === advertisement.advertisement_id);
const swapWith = direction === "up" ? index - 1 : index + 1;
if (swapWith < 0 || swapWith >= group.length) {
return R.error(res, `This ad is already at the ${direction === "up" ? "top" : "bottom"} of its placement.`, 400);
}
[group[index], group[swapWith]] = [group[swapWith], group[index]];
const t = await sequelize.transaction();
try {
await Promise.all(group.map((a, i) => a.update({ order: i }, { transaction: t })));
await t.commit();
} catch (dbErr) {
try { await t.rollback(); } catch { /* connection gone */ }
throw dbErr;
}
logActivity(req.user?.user_id, 'reorder_advertisement', {
entityType: 'advertisement', entityId: Number(advertisementId),
details: { placement: advertisement.placement, direction },
});
return R.success(res, "Order updated.", {
data: { updates: group.map((a) => ({ advertisement_id: a.advertisement_id, order: a.order })) },
});
} catch (err) {
console.error("[ADVERTISEMENT][REORDER]", err);
return R.error(res, "Internal server error.", 500);
}
};
// ─── ARCHIVE (single) ─────────────────────────────────────────────────────────
exports.archiveAdvertisement = async (req, res) => {