store: reembolsar solo lo no entregado si el envío falla a medias

Un carrito de más de 12 entradas se envía en varios correos. Si fallaba el 3.º
de 9, los 2 primeros ya estaban en el buzón del jugador y aun así se le devolvía
el carrito ENTERO: se quedaba los objetos gratis. Con las cantidades por línea
(f232f0f) llegar ahí es fácil: 100 copias son 9 correos.

sendStoreItems devuelve ahora CUÁNTAS entradas entregó en vez de un booleano: un
correo enviado no se puede deshacer, así que quien llama necesita saber dónde se
cortó. Cada `.send items` es un correo, así que el troceo es atómico por correo:
un chunk sale entero o no sale. purchaseStoreCart reembolsa solo las entradas
que quedaron sin enviar (cada una lleva su precio y su moneda) y devuelve
`partialDelivery`, con un mensaje que dice la verdad: parte llegó al correo del
juego y solo se ha devuelto el resto. Si no sale ni un correo, sigue siendo el
`deliveryFailed` de siempre con la devolución completa.

En el pago con tarjeta no se puede hacer lo mismo (el dinero ya lo cobró la
pasarela): fulfillStoreOrder devuelve false si no salió todo. No puede duplicar
porque claimPaidCheckout reclama el pago una sola vez, pero por eso mismo
tampoco hay reintento y un envío a medias hay que rescatarlo a mano desde
home_store_order. Queda anotado en el código.

Verificado de punta a punta, no solo razonado: con un parche temporal del SOAP
que deja salir el 1.er correo y tumba el resto, 13 copias de un ítem de 10 PD
(130 PD, 12+1 entradas) dejan el saldo en 500 -> 380, o sea 500-130+10: se
devuelve SOLO la entrada que no salió y se cobran las 12 entregadas. El parche
se revirtió y producción se reconstruyó limpia.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-15 10:19:09 +00:00
parent f232f0fc5f
commit 0be3dc5280
3 changed files with 60 additions and 22 deletions
+1
View File
@@ -1961,6 +1961,7 @@
"insufficientPd": "No tienes suficientes PD para esta compra.",
"insufficientVp": "No tienes suficientes PV para esta compra.",
"deliveryFailed": "No se pudieron enviar los objetos (servidor de juego no disponible). Se te ha devuelto el saldo.",
"partialDelivery": "Solo se pudo enviar parte de la compra (el servidor de juego dejó de responder). Los objetos que sí llegaron están en tu correo del juego; se te ha devuelto el saldo del resto.",
"invalidCharacter": "El personaje no es válido.",
"emptyCart": "Tu carrito está vacío.",
"generic": "Ha ocurrido un error. Inténtalo de nuevo.",