Statistiken/Abo: Kundenfeedback 2026-07-24 komplett umgesetzt + Steuern: DATEV-Fixes 08+09/2025 (Sammel-Commit Branch-WIP)
Feedback-Umsetzung (dev/2026-07-22/feedback-analyse-2026-07-24.md, alle 10 Punkte):
- VIP-Statistik: eigener Berater ('ich', Linie 0) in Neue-Kundenabos- und beiden Top-10-Listen; Top-10-Umsatz sortiert nach abgerechneten Ist-Punkten + Abo-Anzahl-Spalte; Fußnote nicht-payline-wirksame Punkte (SalesVolumePoints::nonPaylinePoints)
- Führungskräfte-Liste: beide Sichten 'direkt' (an nächster FK abgeschnitten, additiv) und 'gesamt' (komplette Downline), Gesamt-Spalte nach Kundenzählweise
- Team-Abos: je Ebene 'abgerechnet (Monat)' und 'bis zum 25. erwartet'; Payline-Karte mit Teamabo-/Kundenabo-Zählern
- Incentive-Live-Ranking: Qualifizierte zuerst nummeriert (fixt auch isWinner rank<=max_winners)
- Porto: Netto-/Brutto-Kennzeichnung (Berater netto, Endkunden inkl. MwSt., portal_view-Flag; auch CRM-/Shop-Warenkorb + Checkout), Yard::shipping_tax-Fix
- Struktur-Ansicht: Abo-Badges 'A' (eigenes Abo) und '(n)' (Kundenabos) je Teampartner, gebatcht
- Abo-Löschung: Softdelete setzt active=0 (UserAbo deleting-Hook) + Bereinigungs-Migration für gelöschte-aber-aktive Abos
- Doku: technische Analyse + Kundinnen-Feedback-Dokument unter dev/2026-07-22/
- Tests: IncentiveRankingTest, TeamStructureAboBadgesTest, YardShippingTaxTest (neu); BackofficeStatisticsListsTest, TeamAboOverviewTest, PaylineForecastServiceTest, AboAdminDeleteTest, AboOneTimeViewTest erweitert
Außerdem enthalten (Branch-WIP vor dem Feedback): DATEV-Abgleich-Fixes 08+09/2025, USt-ID-Live-Validierung sowie restliche unkommittete Stände (u. a. Abo-Pause-Sprachkeys).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
657d4bd5b7
commit
ac3bd6e8ea
136 changed files with 7610 additions and 2688 deletions
|
|
@ -2,9 +2,14 @@
|
|||
|
||||
namespace App\Models;
|
||||
|
||||
use Acme\Dhl\Models\DhlShipment;
|
||||
use App\Services\HTMLHelper;
|
||||
use App\User;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Illuminate\Support\Carbon;
|
||||
|
||||
/**
|
||||
* App\Models\ShoppingOrder
|
||||
|
|
@ -23,16 +28,16 @@ use Illuminate\Database\Eloquent\SoftDeletes;
|
|||
* @property int|null $weight
|
||||
* @property int|null $paid
|
||||
* @property string|null $txaction
|
||||
* @property \Illuminate\Support\Carbon|null $created_at
|
||||
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||
* @property-read \App\User|null $auth_user
|
||||
* @property-read \App\Models\Country $country
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\ShoppingOrderItem[] $shopping_order_items
|
||||
* @property Carbon|null $created_at
|
||||
* @property Carbon|null $updated_at
|
||||
* @property-read User|null $auth_user
|
||||
* @property-read Country $country
|
||||
* @property-read Collection|ShoppingOrderItem[] $shopping_order_items
|
||||
* @property-read int|null $shopping_order_items_count
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\ShoppingPayment[] $shopping_payments
|
||||
* @property-read Collection|ShoppingPayment[] $shopping_payments
|
||||
* @property-read int|null $shopping_payments_count
|
||||
* @property-read \App\Models\ShoppingUser $shopping_user
|
||||
* @property-read \App\Models\UserShop $user_shop
|
||||
* @property-read ShoppingUser $shopping_user
|
||||
* @property-read UserShop $user_shop
|
||||
*
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingOrder newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingOrder newQuery()
|
||||
|
|
@ -60,13 +65,13 @@ use Illuminate\Database\Eloquent\SoftDeletes;
|
|||
*
|
||||
* @property int|null $member_id
|
||||
* @property string|null $mode
|
||||
* @property-read \App\User|null $member
|
||||
* @property-read \App\Models\UserHistory|null $user_history
|
||||
* @property-read User|null $member
|
||||
* @property-read UserHistory|null $user_history
|
||||
*
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingOrder whereMemberId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingOrder whereMode($value)
|
||||
*
|
||||
* @property \Illuminate\Support\Carbon|null $deleted_at
|
||||
* @property Carbon|null $deleted_at
|
||||
* @property string|null $user_deleted_at
|
||||
*
|
||||
* @method static \Illuminate\Database\Query\Builder|\App\Models\ShoppingOrder onlyTrashed()
|
||||
|
|
@ -75,7 +80,7 @@ use Illuminate\Database\Eloquent\SoftDeletes;
|
|||
* @method static \Illuminate\Database\Query\Builder|\App\Models\ShoppingOrder withTrashed()
|
||||
* @method static \Illuminate\Database\Query\Builder|\App\Models\ShoppingOrder withoutTrashed()
|
||||
*
|
||||
* @property-read \App\Models\ShippingCountry $shipping_country
|
||||
* @property-read ShippingCountry $shipping_country
|
||||
* @property float|null $shipping_net
|
||||
* @property float|null $subtotal_ws
|
||||
* @property int|null $points
|
||||
|
|
@ -93,21 +98,21 @@ use Illuminate\Database\Eloquent\SoftDeletes;
|
|||
* @property int|null $homeparty_id
|
||||
* @property array|null $api_notice
|
||||
* @property int|null $api_status
|
||||
* @property-read \App\Models\Homeparty|null $homeparty
|
||||
* @property-read Homeparty|null $homeparty
|
||||
*
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|ShoppingOrder whereHomepartyId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|ShoppingOrder whereWpNotice($value)
|
||||
*
|
||||
* @property array|null $tax_split
|
||||
* @property-read \App\Models\UserInvoice|null $user_invoice
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\UserSalesVolume[] $user_sales_volume
|
||||
* @property-read UserInvoice|null $user_invoice
|
||||
* @property-read Collection|UserSalesVolume[] $user_sales_volume
|
||||
* @property-read int|null $user_sales_volume_count
|
||||
*
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|ShoppingOrder whereTaxSplit($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|ShoppingOrder whereApiNotice($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|ShoppingOrder whereApiStatus($value)
|
||||
*
|
||||
* @property-read \App\Models\ShoppingCollectOrder|null $shopping_collect_order
|
||||
* @property-read ShoppingCollectOrder|null $shopping_collect_order
|
||||
* @property array|null $net_split
|
||||
*
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|ShoppingOrder whereNetSplit($value)
|
||||
|
|
@ -122,11 +127,11 @@ use Illuminate\Database\Eloquent\SoftDeletes;
|
|||
* @method static \Illuminate\Database\Eloquent\Builder|ShoppingOrder whereAboInterval($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|ShoppingOrder whereIsAbo($value)
|
||||
*
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \Acme\Dhl\Models\DhlShipment> $dhlOutboundShipments
|
||||
* @property-read Collection<int, DhlShipment> $dhlOutboundShipments
|
||||
* @property-read int|null $dhl_outbound_shipments_count
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \Acme\Dhl\Models\DhlShipment> $dhlReturnShipments
|
||||
* @property-read Collection<int, DhlShipment> $dhlReturnShipments
|
||||
* @property-read int|null $dhl_return_shipments_count
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \Acme\Dhl\Models\DhlShipment> $dhlShipments
|
||||
* @property-read Collection<int, DhlShipment> $dhlShipments
|
||||
* @property-read int|null $dhl_shipments_count
|
||||
*
|
||||
* @mixin \Eloquent
|
||||
|
|
@ -608,7 +613,7 @@ class ShoppingOrder extends Model
|
|||
*/
|
||||
public function isCancellationInvoice()
|
||||
{
|
||||
return \App\Models\UserInvoice::where('shopping_order_id', $this->id)
|
||||
return UserInvoice::where('shopping_order_id', $this->id)
|
||||
->where('cancellation', true)
|
||||
->whereNull('cancellation_id')
|
||||
->exists();
|
||||
|
|
@ -620,7 +625,7 @@ class ShoppingOrder extends Model
|
|||
*/
|
||||
public function getCancellationInvoice()
|
||||
{
|
||||
return \App\Models\UserInvoice::where('shopping_order_id', $this->id)
|
||||
return UserInvoice::where('shopping_order_id', $this->id)
|
||||
->where('cancellation', true)
|
||||
->whereNull('cancellation_id')
|
||||
->first();
|
||||
|
|
@ -710,13 +715,13 @@ class ShoppingOrder extends Model
|
|||
}
|
||||
|
||||
foreach ($tax_split as $key => $value) {
|
||||
$tax_split[$key]['vk_tax'] = number_format($value['vk_tax'], 2);
|
||||
$tax_split[$key]['ek_tax'] = number_format($value['ek_tax'], 2);
|
||||
$tax_split[$key]['vk_tax'] = number_format($value['vk_tax'], 2, '.', '');
|
||||
$tax_split[$key]['ek_tax'] = number_format($value['ek_tax'], 2, '.', '');
|
||||
}
|
||||
|
||||
foreach ($net_split as $key => $value) {
|
||||
$net_split[$key]['vk_net'] = number_format($value['vk_net'], 2);
|
||||
$net_split[$key]['ek_net'] = number_format($value['ek_net'], 2);
|
||||
$net_split[$key]['vk_net'] = number_format($value['vk_net'], 2, '.', '');
|
||||
$net_split[$key]['ek_net'] = number_format($value['ek_net'], 2, '.', '');
|
||||
}
|
||||
}
|
||||
if (! isset($tax_split[16]) && ! isset($tax_split[19])) {
|
||||
|
|
@ -779,10 +784,10 @@ class ShoppingOrder extends Model
|
|||
}
|
||||
|
||||
foreach ($tax_split as $key => $value) {
|
||||
$tax_split[$key] = number_format($value, 2);
|
||||
$tax_split[$key] = number_format($value, 2, '.', '');
|
||||
}
|
||||
foreach ($net_split as $key => $value) {
|
||||
$net_split[$key] = number_format($value, 2);
|
||||
$net_split[$key] = number_format($value, 2, '.', '');
|
||||
}
|
||||
}
|
||||
$this->tax_split = $tax_split;
|
||||
|
|
@ -798,7 +803,7 @@ class ShoppingOrder extends Model
|
|||
$fullname = $this->shopping_user->getFullNameAsArray();
|
||||
$ret = '';
|
||||
$ret .= $fullname['company'] ? $fullname['company'].' | ' : '';
|
||||
$ret .= $fullname['salutation'] ? \App\Services\HTMLHelper::getSalutationLang($fullname['salutation']).' ' : '';
|
||||
$ret .= $fullname['salutation'] ? HTMLHelper::getSalutationLang($fullname['salutation']).' ' : '';
|
||||
$ret .= $fullname['firstname'] ? $fullname['firstname'].' ' : '';
|
||||
$ret .= $fullname['lastname'] ? $fullname['lastname'] : '';
|
||||
$ret .= $fullname['email'] ? ' | '.$fullname['email'].'' : '';
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue