find((int) $this->option('abo')); if (! $userAbo) { $this->error('UserAbo wurde nicht gefunden.'); return self::FAILURE; } $targetUser = User::with('account')->find((int) $this->option('user')); if (! $targetUser || ! $targetUser->account) { $this->error('Ziel-User wurde nicht gefunden oder hat keinen Account.'); return self::FAILURE; } $userAboOrder = $this->resolveUserAboOrder($userAbo); if (! $userAboOrder || ! $userAboOrder->shopping_order) { $this->error('Keine passende Abo-Bestellung gefunden.'); return self::FAILURE; } $order = $userAboOrder->shopping_order; $order->loadMissing(['shopping_user', 'user_invoices', 'user_sales_volume']); if ($this->option('old-user') !== null && (int) $order->auth_user_id !== (int) $this->option('old-user')) { $this->error('Abbruch: auth_user_id der Bestellung entspricht nicht --old-user.'); return self::FAILURE; } $this->printPreview($userAbo, $order, $targetUser); if (! $this->option('fix')) { $this->warn('Trockenlauf. Nutze --fix zur Reparatur.'); return self::SUCCESS; } if (! $this->option('force') && ! $this->confirm('Diese Abo-Bestellung wirklich auf den Ziel-User korrigieren?')) { return self::SUCCESS; } $salesVolumeRecalculations = []; $newShoppingUserId = null; DB::transaction(function () use ($userAbo, $order, $targetUser, &$salesVolumeRecalculations, &$newShoppingUserId) { $lockedAbo = UserAbo::whereKey($userAbo->id)->lockForUpdate()->firstOrFail(); $lockedOrder = ShoppingOrder::whereKey($order->id)->lockForUpdate()->firstOrFail(); $newShoppingUser = $this->makeShoppingUserSnapshot($lockedAbo, $lockedOrder, $targetUser); $newShoppingUser->save(); $newShoppingUserId = $newShoppingUser->id; $lockedAbo->update([ 'user_id' => $targetUser->id, 'email' => $targetUser->email, ]); $lockedOrder->update([ 'shopping_user_id' => $newShoppingUser->id, 'auth_user_id' => $targetUser->id, 'member_id' => $lockedAbo->member_id, 'country_id' => $this->resolveShippingCountryId($targetUser, $lockedOrder), 'language' => $targetUser->getLocale(), ]); UserSalesVolume::where('shopping_order_id', $lockedOrder->id) ->get() ->each(function (UserSalesVolume $salesVolume) use ($targetUser, &$salesVolumeRecalculations) { $salesVolumeRecalculations[] = [ 'user_id' => $salesVolume->user_id, 'month' => $salesVolume->month, 'year' => $salesVolume->year, ]; $salesVolume->user_id = $targetUser->id; $salesVolume->save(); $salesVolumeRecalculations[] = [ 'user_id' => $targetUser->id, 'month' => $salesVolume->month, 'year' => $salesVolume->year, ]; }); }); $this->recalculateSalesVolumes($salesVolumeRecalculations); $this->info("Daten korrigiert. Neuer ShoppingUser: {$newShoppingUserId}"); if (! $this->option('no-documents')) { $this->regenerateDocuments($order->fresh(['user_invoice', 'shopping_user', 'shopping_order_items', 'shopping_payments.payment_transactions'])); } else { $this->warn('Dokumente wurden wegen --no-documents nicht neu gerendert.'); } return self::SUCCESS; } private function resolveUserAboOrder(UserAbo $userAbo): ?UserAboOrder { $query = UserAboOrder::with('shopping_order') ->where('user_abo_id', $userAbo->id); if ($this->option('order')) { $query->where('shopping_order_id', (int) $this->option('order')); } return $query->orderByDesc('id')->first(); } private function printPreview(UserAbo $userAbo, ShoppingOrder $order, User $targetUser): void { $this->table( ['Feld', 'Aktuell', 'Neu'], [ ['user_abo_id', $userAbo->id, $userAbo->id], ['shopping_order_id', $order->id, $order->id], ['user_abos.user_id', $userAbo->user_id, $targetUser->id], ['shopping_orders.auth_user_id', $order->auth_user_id, $targetUser->id], ['shopping_orders.member_id', $order->member_id ?: '-', $userAbo->member_id ?: '-'], ['shopping_orders.shopping_user_id', $order->shopping_user_id, 'neuer Snapshot'], ['Rechnungen/Lieferscheine', $order->user_invoices->count(), $this->option('no-documents') ? 'nicht neu rendern' : 'neu rendern'], ['SalesVolume-Eintraege', UserSalesVolume::where('shopping_order_id', $order->id)->count(), 'user_id aktualisieren'], ] ); } private function makeShoppingUserSnapshot(UserAbo $userAbo, ShoppingOrder $order, User $targetUser): ShoppingUser { $account = $targetUser->account; $source = $order->shopping_user ?: $userAbo->shopping_user; $shoppingUser = $source ? $source->replicate() : new ShoppingUser; $shoppingUser->auth_user_id = $targetUser->id; $shoppingUser->member_id = $userAbo->member_id; $shoppingUser->billing_salutation = $account->salutation; $shoppingUser->billing_company = $account->company; $shoppingUser->billing_firstname = $account->first_name; $shoppingUser->billing_lastname = $account->last_name; $shoppingUser->billing_address = $account->address; $shoppingUser->billing_address_2 = $account->address_2; $shoppingUser->billing_zipcode = $account->zipcode; $shoppingUser->billing_city = $account->city; $shoppingUser->billing_country_id = $account->country_id; $shoppingUser->billing_phone = $account->phone; $shoppingUser->billing_email = $targetUser->email; $shoppingUser->language = $targetUser->getLocale(); $shoppingUser->is_for = $userAbo->is_for; $shoppingUser->is_from = $shoppingUser->is_from ?: 'user_order'; $shoppingUser->mode = $order->mode; if ($account->same_as_billing) { $shoppingUser->same_as_billing = true; $shoppingUser->shipping_salutation = $account->salutation; $shoppingUser->shipping_company = $account->company; $shoppingUser->shipping_firstname = $account->first_name; $shoppingUser->shipping_lastname = $account->last_name; $shoppingUser->shipping_address = $account->address; $shoppingUser->shipping_address_2 = $account->address_2; $shoppingUser->shipping_zipcode = $account->zipcode; $shoppingUser->shipping_city = $account->city; $shoppingUser->shipping_country_id = $account->country_id; $shoppingUser->shipping_phone = $account->phone; $shoppingUser->shipping_postnumber = null; } else { $shoppingUser->same_as_billing = false; $shoppingUser->shipping_salutation = $account->shipping_salutation; $shoppingUser->shipping_company = $account->shipping_company; $shoppingUser->shipping_firstname = $account->shipping_firstname; $shoppingUser->shipping_lastname = $account->shipping_lastname; $shoppingUser->shipping_address = $account->shipping_address; $shoppingUser->shipping_address_2 = $account->shipping_address_2; $shoppingUser->shipping_zipcode = $account->shipping_zipcode; $shoppingUser->shipping_city = $account->shipping_city; $shoppingUser->shipping_country_id = $account->shipping_country_id; $shoppingUser->shipping_phone = $account->shipping_phone; $shoppingUser->shipping_postnumber = $account->shipping_postnumber; } return $shoppingUser; } private function resolveShippingCountryId(User $targetUser, ShoppingOrder $order): int { $account = $targetUser->account; $countryId = $account->same_as_billing ? $account->country_id : $account->shipping_country_id; $shippingCountry = ShippingCountry::where('country_id', $countryId)->first(); return $shippingCountry?->id ?? $order->country_id; } /** * @param list $recalculations */ private function recalculateSalesVolumes(array $recalculations): void { collect($recalculations) ->filter(fn (array $item) => $item['user_id'] && $item['month'] && $item['year']) ->unique(fn (array $item) => $item['user_id'].'-'.$item['month'].'-'.$item['year']) ->each(fn (array $item) => SalesPointsVolume::reCalculateSalesPointsVolume( (int) $item['user_id'], (int) $item['month'], (int) $item['year'] )); } private function regenerateDocuments(ShoppingOrder $order): void { if (! $order->user_invoice) { $this->warn('Keine Rechnung gefunden, Dokumente wurden nicht neu gerendert.'); return; } $invoiceRepository = new InvoiceRepository($order); $invoiceRepository->update(['invoice_send_mail' => false]); $this->info('Rechnung und Lieferschein wurden neu gerendert.'); } }