Add category-template selection to the line, mag and enigma edit forms and to
the reseller active-code (voucher) form, plus a reseller navbar entry. Extract
the shared custom_data resolver into CategoryTemplateService::applyCustomData()
and route the Line/Mag/Enigma saves through it, removing the triplicated inline
block; covered by a new unit test.
Review fixes folded in:
- getRecentBatchNames filtered a non-existent `user_id` column and used
DISTINCT + ORDER BY id (rejected by MySQL ONLY_FULL_GROUP_BY). Restore the
correct created_by + GROUP BY MAX(created_at) query (kept the empty-batch
guard).
- routes/admin.php: import ActiveCodeDetailsController (fatal short-name use
without it) for the active_code_details route.
- Revert the accidental re-inline of the ancestorOwnerIds() helper in
getTemplatesForUser and the getResellersWithCodes all-users fallback.
Also: settings save only zeroes checkbox flags on the full settings form
(submit_settings), and reseller bootstrap tolerates a missing language.