mivita/app/Services/CustomerPriority.php
Kevin Adametz 9ad69a3218 Kundenhoheit: E-Mail-Aenderung mit Bestaetigung, Zuordnungsfehler behoben, Admin-Uebersicht
- E-Mail-Aenderung durch Berater wird erst nach Bestaetigung durch den Kunden
  aktiv (Link an die neue Adresse, Portal kunde/email-bestaetigen); danach
  ziehen alle Eintraege des Kunden und seine Abos mit. Admins aendern direkt.
- Kundenhoheit: E-Mail eines Beraterkontos oder eines Kunden eines anderen
  Beraters wird abgelehnt (beim Speichern und bei der Bestaetigung).
- Fix CustomerPriority::entryExists: aelteste gepruefte Zuordnung gilt,
  Eintraege in Pruefung (is_like) dienen nicht mehr als Vorlage.
- "Berater zuweisen" voreingestellt auf alle Bestellungen des Kunden.
- Neue Admin-Seite Kundenhoheit: offene Pruefungen, Kunden bei mehreren
  Beratern, abgelehnte/offene E-Mail-Aenderungen; Zaehler im Menue.
- Neue Tabelle shopping_user_email_changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 08:48:17 +00:00

373 lines
14 KiB
PHP

<?php
namespace App\Services;
use App\Mail\MailCheckout;
use App\Mail\MailInfo;
use App\Models\ShoppingUser;
use App\Services\BusinessPlan\SalesPointsVolume;
use App\User;
use Illuminate\Support\Facades\Mail;
class CustomerPriority
{
protected static $start_number = 1000;
protected static $user_notice_key = 'like';
public static function checkForAll()
{
// only extern no members with no numbers
$shopping_users = ShoppingUser::where('auth_user_id', '=', null)->where('number', '=', null)->orderBy('created_at', 'ASC')->get();
foreach ($shopping_users as $shopping_user) {
if ($shopping_user->shopping_order && $shopping_user->shopping_order->user_shop) {
self::checkOne($shopping_user);
}
}
return $shopping_users;
}
public static function checkOne($shopping_user, $mail = false, $newCustomer = true, $entryExistsLike = false)
{
// ist die Mail ein Berater, dann sich selbst zuweisen.
if (self::entryIsMember($shopping_user)) {
return 'self';
}
// look for entry
if ($entryExistsLike) {
if (self::entryExistsLike($shopping_user)) { // existiert die Email bei einem anderem member?
if ($mail) { // send mail
Mail::to(config('app.priority_mail'))->send(new MailInfo($shopping_user, 'check_is_like_customer'));
}
return 'exists';
}
} else {
if (self::entryExists($shopping_user)) { // Berater zuweisen, wenn die Mail existiert
return 'exists';
}
}
if (self::entryLike($shopping_user)) { // existiert die Adresse bei einem anderem member?
if ($mail) { // send mail
Mail::to(config('app.priority_mail'))->send(new MailInfo($shopping_user, 'check_is_like_customer'));
}
return 'like'.$shopping_user->member_id;
}
if ($newCustomer) {
self::newCustomer($shopping_user);
}
return 'new';
}
public static function setIsLike($shopping_user, $set_like_shopping_user, $send_member_mail, $change_shopping_user = false)
{
if ($shopping_user->id === $set_like_shopping_user->id) {
// set new customer for shopping_user
if ($change_shopping_user) {
self::newCustomerNumber($shopping_user);
$send_member_mail = false;
} else {
self::newCustomer($shopping_user);
}
} else {
// set existing customer for shopping_user
self::existingCustomer($shopping_user, $set_like_shopping_user);
}
self::clearIsLike($shopping_user);
// SEND MAIL TO MEMBER
if ($send_member_mail) {
if ($shopping_user->shopping_order && $shopping_user->shopping_order->shopping_payments) {
Mail::to($shopping_user->member->email)->send(new MailCheckout($shopping_user->shopping_order->txaction, $shopping_user->shopping_order, $shopping_user->shopping_order->shopping_payments->last(), false, $shopping_user->shopping_order->mode));
}
}
// set Points and Volume
if ($shopping_user->shopping_order && $user_sales_volume = $shopping_user->shopping_order->user_sales_volume_no_userid()) {
SalesPointsVolume::setToUserAndReCalculate($user_sales_volume, $shopping_user->member_id);
}
return true;
}
public static function newMemberForOrder($shopping_order, $member_id, bool $all = false)
{
if ($all) {
if ($shopping_order->shopping_user && $shopping_order->shopping_user->number) {
$shopping_users = ShoppingUser::where('number', '=', $shopping_order->shopping_user->number)->get();
$new_number = self::nextNumber();
foreach ($shopping_users as $shopping_user) {
self::changeCustomer($shopping_user, $member_id, $new_number);
}
}
} else {
$shopping_order->member_id = $member_id;
$shopping_order->save();
if ($shopping_order->shopping_user) {
$shopping_order->shopping_user->member_id = $member_id;
$shopping_order->shopping_user->number = self::nextNumber();
$shopping_order->shopping_user->save();
}
}
}
public static function newMemberForCustomer($shopping_user, $member_id, bool $all = false)
{
if ($all) {
if ($shopping_user && $shopping_user->number) {
$shopping_users = ShoppingUser::where('number', '=', $shopping_user->number)->get();
$new_number = self::nextNumber();
foreach ($shopping_users as $s_user) {
self::changeCustomer($s_user, $member_id, $new_number);
}
}
} else {
$shopping_user->member_id = $member_id;
$shopping_user->number = self::nextNumber();
$shopping_user->save();
if ($shopping_user->shopping_order) {
$shopping_user->shopping_order->member_id = $member_id;
$shopping_user->shopping_order->save();
}
}
}
public static function checkChangeOne($shopping_user, $data, $mail = false)
{
$matches = [];
$change = [];
$ret = 'update';
// email geändert
if (isset($data['billing_email']) && $shopping_user->billing_email != $data['billing_email']) {
$found = ShoppingUser::where('auth_user_id', '=', null)
->where('number', '!=', null) // has number
->where('id', '!=', $shopping_user->id)
->where('billing_email', '=', $data['billing_email'])
->where('member_id', '!=', $shopping_user->member_id)
->get()->pluck('number', 'id')->unique()->toArray();
if ($found && count($found)) {
foreach ($found as $key => $val) {
$matches[$key] = $val;
}
$ret = 'exists';
$change['billing_email'] = $data['billing_email'];
}
}
// Anschrift geändert
if (isset($data['billing_lastname']) && isset($data['billing_zipcode']) && ($shopping_user->billing_lastname != $data['billing_lastname'] || $shopping_user->billing_zipcode != $data['billing_zipcode'])) {
$found = ShoppingUser::select('*')
->where('auth_user_id', '=', null)
->where('number', '!=', null) // has number
->where('id', '!=', $shopping_user->id)
->where('billing_lastname', '=', $data['billing_lastname'])
->where('billing_zipcode', '=', $data['billing_zipcode'])
->where('member_id', '!=', $shopping_user->member_id)
->get()->pluck('number', 'id')->unique()->toArray();
if ($found && count($found)) {
foreach ($found as $key => $val) {
$matches[$key] = $val;
}
$ret = 'like';
$change['billing_lastname'] = $data['billing_lastname'];
$change['billing_zipcode'] = $data['billing_zipcode'];
}
}
if ($matches) {
$shopping_user->is_like = true;
$shopping_user->setNotice(self::$user_notice_key, $matches);
$shopping_user->save();
}
// look for entry
if ($matches && $mail) { // send mail
Mail::to(config('app.priority_mail'))->send(new MailInfo($shopping_user, 'change_is_like_customer', $change));
}
return $ret;
}
public static function checkNewOne($shopping_user, $mail = false)
{
if (self::entryLike($shopping_user)) {
if ($mail) { // send mail
Mail::to(config('app.priority_mail'))->send(new MailInfo($shopping_user, 'check_is_like_customer'));
}
// return 'like';
}
$shopping_user->number = self::nextNumber();
$shopping_user->save();
return true;
}
public static function entryIsMember($shopping_user)
{
if ($user = User::whereEmail($shopping_user->billing_email)->whereActive(1)->first()) {
$member_id = $user->id;
$shopping_user->member_id = $member_id;
$shopping_user->number = self::nextNumber();
$shopping_user->save();
if ($shopping_user->shopping_order) {
$shopping_user->shopping_order->member_id = $member_id;
$shopping_user->shopping_order->save();
}
return true;
}
return false;
}
private static function entryExists($shopping_user)
{
// check same email: die älteste geprüfte Zuordnung gilt (Kundenhoheit). Einträge, die noch
// in Prüfung sind (is_like), dürfen nicht als Vorlage dienen, sonst erbt der Kunde eine
// ungeprüfte Zuordnung und bleibt nach der Prüfung beim falschen Berater hängen.
$match = ShoppingUser::where('auth_user_id', '=', null)
->where('number', '!=', null) // has number
->whereNotNull('member_id')
->where('id', '!=', $shopping_user->id)
->where('billing_email', '=', $shopping_user->billing_email)
->where(function ($query) {
$query->where('is_like', false)->orWhereNull('is_like');
})
->orderBy('id')
->first();
if ($match) {
$shopping_user->member_id = $match->member_id;
$shopping_user->number = $match->number;
$shopping_user->save();
// has order
if ($shopping_user->shopping_order) {
$shopping_user->shopping_order->member_id = $match->member_id;
$shopping_user->shopping_order->save();
}
return true;
}
return false;
}
private static function entryExistsLike($shopping_user)
{
// existiert die Email bei einem anderem member?
$matches = ShoppingUser::where('auth_user_id', '=', null)
->where('number', '!=', null) // has number
->where('id', '!=', $shopping_user->id)
->where('member_id', '!=', $shopping_user->member_id)
->where('billing_email', '=', $shopping_user->billing_email)
->get()->pluck('number', 'id')->unique()->toArray();
if ($matches && count($matches)) {
$shopping_user->is_like = true;
$shopping_user->setNotice(self::$user_notice_key, $matches);
$shopping_user->save();
return true;
}
return false;
}
private static function entryLike($shopping_user)
{
// check same last name und PLZ
$matches = ShoppingUser::select('*')
->where('auth_user_id', '=', null)
->where('number', '!=', null) // has number
->where('id', '!=', $shopping_user->id)
->where('member_id', '!=', $shopping_user->member_id)
->where('billing_lastname', '=', $shopping_user->billing_lastname)
->where('billing_zipcode', '=', $shopping_user->billing_zipcode)
->get()->pluck('number', 'id')->unique()->toArray();
if ($matches && count($matches)) {
$shopping_user->is_like = true;
$shopping_user->setNotice(self::$user_notice_key, $matches);
$shopping_user->save();
return true;
}
return false;
}
private static function newCustomer($shopping_user)
{
if ($shopping_user->shopping_order && $shopping_user->shopping_order->user_shop) {
$member_id = $shopping_user->shopping_order->user_shop->user_id;
$shopping_user->member_id = $member_id;
$shopping_user->number = self::nextNumber();
$shopping_user->save();
$shopping_user->shopping_order->member_id = $member_id;
$shopping_user->shopping_order->save();
}
}
private static function newCustomerNumber($shopping_user)
{
Shop::newUserOrder($shopping_user->number);
$shopping_user->number = self::nextNumber();
$shopping_user->save();
Shop::newUserOrder($shopping_user->number);
}
private static function changeCustomer($shopping_user, $member_id, $number)
{
$old_number = $shopping_user->number;
$shopping_user->member_id = $member_id;
$shopping_user->number = $number;
$shopping_user->save();
if ($shopping_user->shopping_order) {
$shopping_user->shopping_order->member_id = $member_id;
$shopping_user->shopping_order->save();
}
Shop::newUserOrder($old_number);
Shop::newUserOrder($number);
}
private static function existingCustomer($shopping_user, $set_like_shopping_user)
{
$old_number = $shopping_user->number;
$shopping_user->member_id = $set_like_shopping_user->member_id;
$shopping_user->number = $set_like_shopping_user->number;
$shopping_user->save();
if ($shopping_user->shopping_order) {
$shopping_user->shopping_order->member_id = $set_like_shopping_user->member_id;
$shopping_user->shopping_order->save();
}
Shop::newUserOrder($old_number);
Shop::newUserOrder($set_like_shopping_user->number);
}
/**
* Prüffall abschließen, ohne Berater oder Kundennummer zu ändern (Übersicht Kundenhoheit).
*/
public static function keepAssignment(ShoppingUser $shopping_user): void
{
self::clearIsLike($shopping_user);
}
private static function clearIsLike($shopping_user)
{
$shopping_user->is_like = false;
$shopping_user->removeNotice(self::$user_notice_key);
$shopping_user->save();
}
private static function nextNumber()
{
if (! $number = ShoppingUser::max('number')) {
$number = self::$start_number;
}
return $number + 1;
}
}