Abo: Einmalprodukte bereits bei der Abo-Anlage + es/fr-Sprachsync
Einmalprodukte (Normalsortiment, show_on 3) können jetzt schon beim Abo-Abschluss hinzugefügt werden – im Portal-Wizard (Abschnitt im Upgrade-Schritt) und in allen drei Sales-Center-Abo-Strecken (eigene Produktliste). Variante A: Zeilen laufen als Cart-Option abo_addon mit durch den Checkout, werden sofort bezahlt und mit der Erstlieferung verschickt (Rechnung/Lieferschein gruppieren automatisch). - Checkout persistiert is_abo_addon (CheckoutRepository, PaymentHelper) - createAboItems/ensureUserAboItemsFromLatestOrder überspringen Addons (sonst würden Einmalprodukte dauerhaft wiederkehren); amount ohne Addon-Anteil; aboHasBaseProduct ignoriert Addon-Zeilen - CreateAboReplacementOrder propagiert is_abo_addon in Ersatzbestellungen - iq-shopping-cart.js: zweite Datatable + abo_addon-Flag-Weitergabe - i18n: neue abo.onetime_create_*-Keys (de/en/es/fr); zusätzlich es/fr komplett synchronisiert (abo-Kartenblock, navigation, payment, weborder inkl. Entfernung PAYONE-Altlasten, withdrawal.php neu) - Tests: AboCreateOneTimeItemsTest, AboCreateOneTimeCartTest, AboPortalCreateOneTimeTest (17 neue, 122 Tests gesamt grün) Plan: dev/2026-07-21-abo-einmalprodukte-anlage/ Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
1e7ae92d0c
commit
cdb121fde0
32 changed files with 1479 additions and 52 deletions
|
|
@ -153,6 +153,9 @@ class AboHelper
|
|||
public static function aboHasBaseProduct($yard_products)
|
||||
{
|
||||
foreach ($yard_products as $product) {
|
||||
if ($product->options->abo_addon ?? false) {
|
||||
continue;
|
||||
}
|
||||
if (is_array($product->options->show_on)) {
|
||||
if (in_array('12', $product->options->show_on)) {
|
||||
return true;
|
||||
|
|
@ -343,6 +346,19 @@ class AboHelper
|
|||
$payment_transaction = $shopping_payment->payment_transactions->last();
|
||||
$payoneUserId = ! $isStripe && $payment_transaction ? (int) $payment_transaction->userid : 0;
|
||||
|
||||
/*
|
||||
* Einmalprodukte der Erstbestellung (is_abo_addon) gehören nicht zum wiederkehrenden
|
||||
* Abo-Betrag: amount analog zu AboOrderCart::makeOrderYard() (Abo-Artikel + Versand,
|
||||
* in Cent) um den Addon-Bruttoanteil reduzieren.
|
||||
*/
|
||||
$aboAmount = (int) $shopping_payment->amount;
|
||||
$addonGross = (float) $order->shopping_order_items
|
||||
->where('is_abo_addon', true)
|
||||
->reduce(fn ($carry, $item) => $carry + ((float) $item->price * (int) $item->qty), 0.0);
|
||||
if ($addonGross > 0) {
|
||||
$aboAmount = max(0, $aboAmount - (int) round($addonGross * 100));
|
||||
}
|
||||
|
||||
// next_date immer im nächsten Monat starten
|
||||
// is auth_user_id = Berater bestellung
|
||||
// is member_id = Kunden bestellung
|
||||
|
|
@ -360,7 +376,7 @@ class AboHelper
|
|||
'clearingtype' => $shopping_payment->clearingtype,
|
||||
'wallettype' => $shopping_payment->wallettype,
|
||||
'carddata' => $shopping_payment->carddata,
|
||||
'amount' => $shopping_payment->amount,
|
||||
'amount' => $aboAmount,
|
||||
'status' => 1,
|
||||
'abo_interval' => $aboInterval,
|
||||
'start_date' => now(),
|
||||
|
|
@ -483,6 +499,9 @@ class AboHelper
|
|||
public static function createAboItems($user_abo, ShoppingPayment $shopping_payment)
|
||||
{
|
||||
foreach ($shopping_payment->shopping_order->shopping_order_items as $item) {
|
||||
if ($item->is_abo_addon) {
|
||||
continue;
|
||||
}
|
||||
UserAboItem::create([
|
||||
'user_abo_id' => $user_abo->id,
|
||||
'product_id' => $item->product_id,
|
||||
|
|
@ -525,6 +544,9 @@ class AboHelper
|
|||
}
|
||||
|
||||
foreach ($order->shopping_order_items as $item) {
|
||||
if ($item->is_abo_addon) {
|
||||
continue;
|
||||
}
|
||||
UserAboItem::create([
|
||||
'user_abo_id' => $userAbo->id,
|
||||
'product_id' => $item->product_id,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue