Ambito del recesso esplicito (intero ordine) + avviso auto-annullo + A6-ter in roadmap

Base legale (ANALISI-REQUISITI-LEGALI.md §5): il considerando 37 della Dir. (UE)
2023/2673 dice che il professionista *can* offrire il recesso su parte del
contratto, non che *deve*. Un pulsante a livello di ordine e' conforme. Ma il form
non lo diceva, mentre le automazioni agivano in modo totale.

- statementTemplate: 'relativo all'INTERO ordine #X' (la dichiarazione ora
  corrisponde a cio' che l'app fa davvero).
- SCOPE_HINT sotto la dichiarazione: il recesso riguarda l'intero ordine, per il
  parziale contattare il negozio (canale modulo tipo/email, sempre valido).
- Admin: banner quando autoCancelUnfulfilled e' attivo -> annulla e rimborsa
  l'INTERO ordine, irreversibile; con ordini multi-articolo meglio tenerlo spento.
- PLAN: A6-ter (recesso parziale) come attivita' OPZIONALE con toggle per-shop
  partialWithdrawalEnabled, default OFF. Include la nota che l'idempotenza
  (shop, orderId) di fa8ee9c andra' riportata a (shop, orderId, articoli).
- ANALISI-REQUISITI-LEGALI.md §5: punto chiarito + panorama concorrenti (Revize
  fa il parziale, Rescindly no, Shopify non ha pulsante nativo, LegalBlink non e'
  un concorrente ma un generatore di documenti).
This commit is contained in:
2026-07-10 10:56:50 +02:00
parent fa8ee9c93f
commit aa0c77289d
5 changed files with 91 additions and 2 deletions

View File

@@ -23,9 +23,20 @@ export const FIELD = {
// Dichiarazione precompilata (editabile), deriva dall'Allegato I-B.
export function statementTemplate(orderName: string): string {
return `Con la presente comunico il recesso dal contratto di vendita relativo all'ordine ${orderName}.`;
return `Con la presente comunico il recesso dal contratto di vendita relativo all'intero ordine ${orderName}.`;
}
/**
* Ambito del recesso esercitato tramite questa funzione. La funzione dell'art.
* 54-bis puo' legittimamente operare a livello di CONTRATTO (ordine): offrire
* il recesso parziale e' una facolta' del professionista (considerando 37 Dir.
* UE 2023/2673, "the trader CAN provide..."), non un obbligo. Il diritto al
* recesso parziale resta comunque esercitabile dagli altri canali (modulo tipo,
* email), che non vanno mai disabilitati: per questo li indichiamo.
*/
export const SCOPE_HINT =
"Questo recesso riguarda l'intero ordine. Per restituire solo alcuni articoli, contatta il negozio.";
// Informazioni sul diritto di recesso (Art. 49) + alternative (coesistenza).
// Mostrate su richiesta dal pulsante info "i", per non appesantire il flusso.
export const INFO_TITLE = "Il tuo diritto di recesso";

View File

@@ -16,7 +16,14 @@
import { createHash } from "node:crypto";
import type { AdminApiContext } from "@shopify/shopify-app-remix/server";
import type { ExclusionRule } from "@prisma/client";
import { FIELD, INFO_TITLE, INFO_BODY, CONFIRM_LABEL, PAGE_TITLE } from "./recesso.copy";
import {
FIELD,
INFO_TITLE,
INFO_BODY,
CONFIRM_LABEL,
PAGE_TITLE,
SCOPE_HINT,
} from "./recesso.copy";
// ---------------------------------------------------------------------------
// Costanti path storefront (prefix "apps" + subpath "recesso" da shopify.app.toml).
@@ -1107,6 +1114,7 @@ export function renderStep2(data: {
<label for="statementText">${escapeHtml(FIELD.statement.label)}</label>
<textarea id="statementText" name="statementText" required>${escapeHtml(data.statementText)}</textarea>
<p class="hint">${escapeHtml(SCOPE_HINT)}</p>
<label for="email">${escapeHtml(FIELD.email.label)}</label>
<input type="email" id="email" name="email" value="${attr(data.email)}" autocomplete="email" required>

View File

@@ -536,6 +536,17 @@ export default function SettingsPage() {
onChange={setAutoCancelUnfulfilled}
helpText="Al recesso, se l'ordine non è evaso: annullo + rimborso automatici. Irreversibile."
/>
{autoCancelUnfulfilled ? (
<Banner tone="warning" title="Annulla l'INTERO ordine">
<Text as="p">
Il recesso da questa funzione riguarda tutto l'ordine.
Se il cliente voleva restituire solo alcuni articoli,
l'annullo automatico gli cancella e rimborsa l'intero
ordine, e non è reversibile. Con ordini multi-articolo
valuta di tenerlo spento e decidere caso per caso.
</Text>
</Banner>
) : null}
<Checkbox
label="Spese di restituzione a carico del cliente (Art. 57)"
checked={returnAtCustomerExpense}