feat(mail): keep mail a player deletes, marked deleted, for staff

Deleting mail in game now sets mail.deleted_at (migrations mysql 95,
sqlite 78) instead of removing the row. Every read for the game skips
deleted mail: the mailbox, a single mail (claim, read, delete), the
unread count, the economy scan of waiting attachments and the UGC
lookup of mailed models. Deleting a character still removes its mail.

Check: delete a mail in game; it leaves the mailbox, the unread count
drops, and the row is still in the mail table with deleted_at set.
Parity test: ParitySeeded.Mail (DeleteMail).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Aaron Kimbrell
2026-09-29 00:35:46 -05:00
parent e42fd45c1f
commit acb0e03a74
9 changed files with 37 additions and 13 deletions

View File

@@ -179,7 +179,7 @@ nlohmann::json MySQLDatabase::GetTransfersForItems(const std::vector<LWOOBJID>&
}
void MySQLDatabase::ForEachMailAttachment(const std::function<void(const MailAttachment&)>& visit) {
auto result = ExecuteSelect("SELECT id, receiver_id, attachment_id, attachment_lot, attachment_count FROM mail WHERE attachment_lot > 0 AND attachment_count > 0;");
auto result = ExecuteSelect("SELECT id, receiver_id, attachment_id, attachment_lot, attachment_count FROM mail WHERE attachment_lot > 0 AND attachment_count > 0 AND deleted_at = 0;");
while (result->next()) {
visit({ result->getUInt64("id"), result->getInt64("receiver_id"), result->getInt64("attachment_id"),
result->getInt("attachment_lot"), static_cast<uint32_t>(result->getInt("attachment_count")) });