20-02-2026

This commit is contained in:
Kevin Adametz 2026-02-20 17:55:06 +01:00
parent a8b395e20d
commit a00c42e770
252 changed files with 28785 additions and 8907 deletions

View file

@ -18,6 +18,7 @@ use Illuminate\Database\Eloquent\Model;
* @property \Illuminate\Support\Carbon|null $display_date
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
*
* @mixin \Eloquent
*/
class DashboardNews extends Model
@ -55,9 +56,10 @@ class DashboardNews extends Model
return $this->{$key};
}
$trans = $this->getTrans($key, $lang);
if (!$trans || $trans == '') {
if (! $trans || $trans == '') {
return $this->{$key};
}
return $trans;
}
@ -66,29 +68,44 @@ class DashboardNews extends Model
*/
public function getTrans($key, $lang)
{
$transKey = 'trans_' . $key;
if (!empty($this->{$transKey}[$lang])) {
$transKey = 'trans_'.$key;
if (! empty($this->{$transKey}[$lang])) {
return $this->{$transKey}[$lang];
}
return "";
return '';
}
/**
* Get active news
*/
public static function getActiveNews()
public static function getActiveNews(): ?self
{
return self::where('active', true)
->orderBy('created_at', 'DESC')
->first();
}
/**
* Get all archived (non-active) news ordered by display date descending
*
* @return \Illuminate\Database\Eloquent\Collection<int, self>
*/
public static function getArchiveNews(): \Illuminate\Database\Eloquent\Collection
{
return self::where('active', false)
->orderBy('display_date', 'DESC')
->orderBy('created_at', 'DESC')
->get();
}
/**
* Get formatted display date or created_at as fallback
*/
public function getDisplayDateFormatted()
{
$date = $this->display_date ?: $this->created_at;
return $date ? $date->format('d.m.Y') : '';
}
@ -97,11 +114,11 @@ class DashboardNews extends Model
*/
public function getFileLinks($lang = null)
{
if (!$lang) {
if (! $lang) {
$lang = \App::getLocale();
}
if (!$this->file_links || !isset($this->file_links[$lang])) {
if (! $this->file_links || ! isset($this->file_links[$lang])) {
return [];
}
@ -115,6 +132,7 @@ class DashboardNews extends Model
];
}
}
return null;
})->filter()->values();
}

170
app/Models/DatevExport.php Normal file
View file

@ -0,0 +1,170 @@
<?php
namespace App\Models;
use App\User;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class DatevExport extends Model
{
use SoftDeletes;
protected $table = 'datev_exports';
// Status-Konstanten
const STATUS_DRAFT = 0;
const STATUS_GENERATED = 1;
const STATUS_DOWNLOADED = 2;
const STATUS_LOCKED = 3;
const STATUS_LABELS = [
self::STATUS_DRAFT => 'Entwurf',
self::STATUS_GENERATED => 'Generiert',
self::STATUS_DOWNLOADED => 'Heruntergeladen',
self::STATUS_LOCKED => 'Gesperrt',
];
const STATUS_BADGES = [
self::STATUS_DRAFT => 'secondary',
self::STATUS_GENERATED => 'info',
self::STATUS_DOWNLOADED => 'success',
self::STATUS_LOCKED => 'dark',
];
protected $fillable = [
'period_from',
'period_to',
'month',
'year',
'status',
'berater_nr',
'mandant_nr',
'invoice_count',
'credit_count',
'cancellation_count',
'total_revenue',
'total_commissions',
'filename',
'file_path',
'file_hash',
'created_by',
'warning_count',
'error_count',
'validation_summary',
];
protected $casts = [
'period_from' => 'date',
'period_to' => 'date',
'total_revenue' => 'decimal:2',
'total_commissions' => 'decimal:2',
'validation_summary' => 'array',
];
/*
|--------------------------------------------------------------------------
| Relationships
|--------------------------------------------------------------------------
*/
public function lines()
{
return $this->hasMany(DatevExportLine::class, 'datev_export_id');
}
public function creator()
{
return $this->belongsTo(User::class, 'created_by');
}
/*
|--------------------------------------------------------------------------
| Scopes
|--------------------------------------------------------------------------
*/
public function scopeForPeriod($query, int $month, int $year)
{
return $query->where('month', $month)->where('year', $year);
}
public function scopeGenerated($query)
{
return $query->where('status', '>=', self::STATUS_GENERATED);
}
public function scopeLocked($query)
{
return $query->where('status', self::STATUS_LOCKED);
}
/*
|--------------------------------------------------------------------------
| Accessors
|--------------------------------------------------------------------------
*/
public function getStatusLabelAttribute(): string
{
return self::STATUS_LABELS[$this->status] ?? '-';
}
public function getStatusBadgeAttribute(): string
{
$badge = self::STATUS_BADGES[$this->status] ?? 'secondary';
return '<span class="badge badge-'.$badge.'">'.$this->status_label.'</span>';
}
public function getPeriodLabelAttribute(): string
{
return str_pad($this->month, 2, '0', STR_PAD_LEFT).'/'.$this->year;
}
public function getTotalLinesAttribute(): int
{
return $this->invoice_count + $this->credit_count + $this->cancellation_count;
}
/*
|--------------------------------------------------------------------------
| Methods
|--------------------------------------------------------------------------
*/
public function isLocked(): bool
{
return $this->status === self::STATUS_LOCKED;
}
public function isGenerated(): bool
{
return $this->status >= self::STATUS_GENERATED;
}
public function markAsDownloaded(): void
{
if ($this->status === self::STATUS_GENERATED) {
$this->update(['status' => self::STATUS_DOWNLOADED]);
}
}
public function lock(): void
{
$this->update(['status' => self::STATUS_LOCKED]);
}
public function getStoragePath(): string
{
return config('datev.storage_path').'/'.$this->year.'/'.str_pad($this->month, 2, '0', STR_PAD_LEFT);
}
public function getFullFilePath(): string
{
return $this->getStoragePath().'/'.$this->filename;
}
}

View file

@ -0,0 +1,100 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class DatevExportLine extends Model
{
protected $table = 'datev_export_lines';
// Source Types
const SOURCE_INVOICE = 'invoice';
const SOURCE_CREDIT = 'credit';
const SOURCE_CANCELLATION = 'cancellation';
protected $fillable = [
'datev_export_id',
'source_type',
'source_id',
'line_number',
'amount_gross',
'soll_haben',
'konto',
'gegenkonto',
'bu_schluessel',
'belegdatum',
'belegfeld1',
'buchungstext',
'eu_ustid',
'eu_land',
'row_csv',
];
protected $casts = [
'amount_gross' => 'decimal:2',
'belegdatum' => 'date',
];
/*
|--------------------------------------------------------------------------
| Relationships
|--------------------------------------------------------------------------
*/
public function datev_export()
{
return $this->belongsTo(DatevExport::class, 'datev_export_id');
}
/*
|--------------------------------------------------------------------------
| Scopes
|--------------------------------------------------------------------------
*/
public function scopeInvoices($query)
{
return $query->where('source_type', self::SOURCE_INVOICE);
}
public function scopeCredits($query)
{
return $query->where('source_type', self::SOURCE_CREDIT);
}
public function scopeCancellations($query)
{
return $query->where('source_type', self::SOURCE_CANCELLATION);
}
/*
|--------------------------------------------------------------------------
| Accessors
|--------------------------------------------------------------------------
*/
public function getSourceTypeLabelAttribute(): string
{
return match ($this->source_type) {
self::SOURCE_INVOICE => 'Rechnung',
self::SOURCE_CREDIT => 'Gutschrift',
self::SOURCE_CANCELLATION => 'Storno',
default => $this->source_type,
};
}
public function getFormattedAmountAttribute(): string
{
$prefix = $this->soll_haben === 'S' ? '-' : '';
return $prefix.number_format(abs($this->amount_gross), 2, ',', '.').' €';
}
public function getFormattedBelegdatumAttribute(): string
{
return $this->belegdatum ? $this->belegdatum->format('d.m.Y') : '-';
}
}

View file

@ -189,6 +189,8 @@ class Product extends Model
'active' => 'bool',
'no_commission' => 'bool',
'no_free_shipping' => 'bool',
'free_shipping_consultant' => 'bool',
'is_membership_only' => 'bool',
'buying_restriction' => 'bool',
'buying_restriction_amount' => 'int',
'sponsor_buying_points' => 'bool',
@ -212,6 +214,8 @@ class Product extends Model
'weight',
'no_commission',
'no_free_shipping',
'free_shipping_consultant',
'is_membership_only',
'contents',
'contents_total',
'unit',

View file

@ -17,6 +17,7 @@ use Illuminate\Database\Eloquent\Model;
* @property-read \App\User|null $auth_user
* @property-read \App\Models\Country $country
* @property-read \App\Models\UserShop $user_shop
*
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingInstance newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingInstance newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingInstance query()
@ -27,24 +28,38 @@ use Illuminate\Database\Eloquent\Model;
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingInstance whereSubdomain($value)
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingInstance whereUpdatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingInstance whereUserShopId($value)
*
* @property int|null $payment
*
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingInstance wherePayment($value)
*
* @property array|null $shopping_data
* @property string|null $back
*
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingInstance whereBack($value)
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingInstance whereShoppingData($value)
*
* @property string|null $language
*
* @method static \Illuminate\Database\Eloquent\Builder|ShoppingInstance whereLanguage($value)
*
* @property int|null $status
* @property float|null $amount
* @property int|null $shopping_user_id
*
* @method static \Illuminate\Database\Eloquent\Builder|ShoppingInstance whereAmount($value)
* @method static \Illuminate\Database\Eloquent\Builder|ShoppingInstance whereShoppingUserId($value)
* @method static \Illuminate\Database\Eloquent\Builder|ShoppingInstance whereStatus($value)
*
* @mixin \Eloquent
*/
class ShoppingInstance extends Model
{
protected $primaryKey = 'identifier';
public $incrementing = false;
protected $keyType = 'string';
public $paymentTypes = [
1 => 'Customer Shop',
@ -72,17 +87,30 @@ class ShoppingInstance extends Model
protected $casts = ['shopping_data' => 'array', 'amount' => 'float'];
protected $fillable = [
'identifier', 'user_shop_id', 'auth_user_id', 'status', 'payment', 'subdomain', 'language', 'country_id', 'amount', 'shopping_user_id', 'shopping_data', 'back'
'identifier',
'user_shop_id',
'auth_user_id',
'status',
'payment',
'subdomain',
'language',
'country_id',
'amount',
'shopping_user_id',
'shopping_data',
'back',
];
public function getStatus(){
public function getStatus()
{
return isset($this->statuses[$this->status]) ? $this->statuses[$this->status] : 'link_sent';
}
public function getLocale(){
public function getLocale()
{
return $this->language ? $this->language : \App::getLocale();
}
public function user_shop()
{
return $this->belongsTo('App\Models\UserShop', 'user_shop_id');
@ -93,17 +121,14 @@ class ShoppingInstance extends Model
return $this->belongsTo('App\Models\Country', 'country_id');
}
//can null
// can null
public function auth_user()
{
return $this->belongsTo('App\User','auth_user_id');
return $this->belongsTo('App\User', 'auth_user_id');
}
public function getAmountFormatted(){
public function getAmountFormatted()
{
return formatNumber($this->amount);
}
}

View file

@ -32,6 +32,7 @@ use Illuminate\Database\Eloquent\SoftDeletes;
* @property-read int|null $shopping_payments_count
* @property-read \App\Models\ShoppingUser $shopping_user
* @property-read \App\Models\UserShop $user_shop
*
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingOrder newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingOrder newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingOrder query()
@ -51,21 +52,28 @@ use Illuminate\Database\Eloquent\SoftDeletes;
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingOrder whereUpdatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingOrder whereUserShopId($value)
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingOrder whereWeight($value)
*
* @property int|null $payment_for
*
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingOrder wherePaymentFor($value)
*
* @property int|null $member_id
* @property string|null $mode
* @property-read \App\User|null $member
* @property-read \App\Models\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 string|null $user_deleted_at
*
* @method static \Illuminate\Database\Query\Builder|\App\Models\ShoppingOrder onlyTrashed()
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingOrder whereDeletedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingOrder whereUserDeletedAt($value)
* @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 float|null $shipping_net
* @property float|null $subtotal_ws
@ -73,40 +81,53 @@ use Illuminate\Database\Eloquent\SoftDeletes;
* @property int|null $shipped
* @property string|null $tracking
* @property string|null $wp_invoice_path
*
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingOrder wherePoints($value)
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingOrder whereShipped($value)
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingOrder whereShippingNet($value)
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingOrder whereSubtotalWs($value)
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingOrder whereTracking($value)
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingOrder whereWpInvoicePath($value)
*
* @property int|null $homeparty_id
* @property array|null $api_notice
* @property int|null $api_status
* @property-read \App\Models\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 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 array|null $net_split
*
* @method static \Illuminate\Database\Eloquent\Builder|ShoppingOrder whereNetSplit($value)
*
* @property string|null $language
*
* @method static \Illuminate\Database\Eloquent\Builder|ShoppingOrder whereLanguage($value)
*
* @property bool|null $is_abo
* @property int|null $abo_interval
*
* @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 int|null $dhl_outbound_shipments_count
* @property-read \Illuminate\Database\Eloquent\Collection<int, \Acme\Dhl\Models\DhlShipment> $dhlReturnShipments
* @property-read int|null $dhl_return_shipments_count
* @property-read \Illuminate\Database\Eloquent\Collection<int, \Acme\Dhl\Models\DhlShipment> $dhlShipments
* @property-read int|null $dhl_shipments_count
*
* @mixin \Eloquent
*/
class ShoppingOrder extends Model
@ -114,6 +135,7 @@ class ShoppingOrder extends Model
protected $table = 'shopping_orders';
use SoftDeletes;
protected $dates = ['deleted_at'];
protected $fillable = [
@ -145,7 +167,7 @@ class ShoppingOrder extends Model
'api_status',
'mode',
'shipped',
'tracking'
'tracking',
];
protected $casts = [
@ -163,16 +185,16 @@ class ShoppingOrder extends Model
2 => 'shipped',
3 => 'completed',
4 => 'trade_fair',
10 => 'cancelled'
10 => 'cancelled',
];
public static $apiShippedTypes = [
0 => 'open', //(Fullfilment durch Händler)',
1 => 'process', //(Fullfilment durch MIVITA: nicht Versand)
2 => 'sent', //(Fullfilment durch MIVITA: Versand erfolgt)'
3 => 'close', //(Fullfilment durch MIVITA: Versand erfolgt)',
4 => 'trade', //(Fullfilment durch MIVITA: Versand erfolgt)',
10 => 'cancel'
0 => 'open', // (Fullfilment durch Händler)',
1 => 'process', // (Fullfilment durch MIVITA: nicht Versand)
2 => 'sent', // (Fullfilment durch MIVITA: Versand erfolgt)'
3 => 'close', // (Fullfilment durch MIVITA: Versand erfolgt)',
4 => 'trade', // (Fullfilment durch MIVITA: Versand erfolgt)',
10 => 'cancel',
];
public static $apiStatusTypes = [
@ -181,12 +203,14 @@ class ShoppingOrder extends Model
2 => 'paid',
5 => 'removed',
];
public static $apiStatusColors = [
0 => 'warning',
1 => 'warning',
2 => 'success',
5 => 'danger',
];
public static $shippedColors = [
0 => 'warning',
1 => 'info',
@ -221,11 +245,10 @@ class ShoppingOrder extends Model
8 => 'info',
9 => 'default',
10 => 'info',
11 => 'default'
11 => 'default',
];
public function shopping_user()
{
return $this->belongsTo('App\Models\ShoppingUser', 'shopping_user_id');
@ -251,12 +274,13 @@ class ShoppingOrder extends Model
return $this->belongsTo('App\Models\UserShop', 'user_shop_id');
}
//can null
// can null
public function member()
{
return $this->belongsTo('App\User', 'member_id');
}
//can null
// can null
public function auth_user()
{
return $this->belongsTo('App\User', 'auth_user_id');
@ -267,9 +291,42 @@ class ShoppingOrder extends Model
return $this->hasOne('App\Models\UserHistory', 'shopping_order_id')->latest();
}
/**
* Original-Rechnung (nicht die Stornorechnung)
*
* Unterscheidung: Die Original-Rechnung hat entweder cancellation=false/null (vor Storno)
* oder cancellation_id gesetzt (nach Storno, zeigt auf die Stornorechnung).
* Die Stornorechnung hat cancellation=true UND cancellation_id=null.
*/
public function user_invoice()
{
return $this->hasOne('App\Models\UserInvoice', 'shopping_order_id', '');
return $this->hasOne('App\Models\UserInvoice', 'shopping_order_id', 'id')
->where(function ($query) {
$query->where('cancellation', false)
->orWhereNull('cancellation')
->orWhereNotNull('cancellation_id');
});
}
/**
* Stornorechnung für diese Bestellung
*
* Die Stornorechnung hat cancellation=true und KEINEN cancellation_id
* (cancellation_id wird nur auf der Original-Rechnung gesetzt).
*/
public function user_cancellation_invoice()
{
return $this->hasOne('App\Models\UserInvoice', 'shopping_order_id', 'id')
->where('cancellation', true)
->whereNull('cancellation_id');
}
/**
* Alle Rechnungen (Original + Storno) für diese Bestellung
*/
public function user_invoices()
{
return $this->hasMany('App\Models\UserInvoice', 'shopping_order_id', 'id');
}
public function shopping_collect_order()
@ -294,7 +351,7 @@ class ShoppingOrder extends Model
public function user_sales_volume_no_userid()
{
return $this->hasOne('App\Models\UserSalesVolume', 'shopping_order_id')->where('user_id', '=', NULL)->first();
return $this->hasOne('App\Models\UserSalesVolume', 'shopping_order_id')->where('user_id', '=', null)->first();
}
public function getUserAbo()
@ -303,6 +360,7 @@ class ShoppingOrder extends Model
if ($UserAboOrder && $UserAboOrder->user_abo) {
return $UserAboOrder->user_abo;
}
return null;
}
@ -332,7 +390,8 @@ class ShoppingOrder extends Model
return $shopping_payment->reference;
}
}
return "";
return '';
}
public function getLastShoppingPaymentTransaction()
@ -346,40 +405,43 @@ class ShoppingOrder extends Model
}
}
}
return false;
}
public function getShippedType()
{
return isset(self::$shippedTypes[$this->shipped]) ? __('payment.' . self::$shippedTypes[$this->shipped]) : "";
return isset(self::$shippedTypes[$this->shipped]) ? __('payment.'.self::$shippedTypes[$this->shipped]) : '';
}
public static function getTransShippedType()
{
$ret = [];
foreach (self::$shippedTypes as $key => $val) {
$ret[$key] = trans('payment.' . $val);
$ret[$key] = trans('payment.'.$val);
}
return $ret;
}
public function getAPIShippedType()
{
return isset(self::$apiShippedTypes[$this->shipped]) ? self::$apiShippedTypes[$this->shipped] : "free";
return isset(self::$apiShippedTypes[$this->shipped]) ? self::$apiShippedTypes[$this->shipped] : 'free';
}
public function getShippedColor()
{
return isset(self::$shippedColors[$this->shipped]) ? self::$shippedColors[$this->shipped] : "default";
return isset(self::$shippedColors[$this->shipped]) ? self::$shippedColors[$this->shipped] : 'default';
}
public function getAPIStatusType()
{
return isset(self::$apiStatusTypes[$this->api_status]) ? __('payment.' . self::$apiStatusTypes[$this->api_status]) : "bestellt";
return isset(self::$apiStatusTypes[$this->api_status]) ? __('payment.'.self::$apiStatusTypes[$this->api_status]) : 'bestellt';
}
public function getAPIStatusColor()
{
return isset(self::$apiStatusColors[$this->api_status]) ? self::$apiStatusColors[$this->api_status] : "warning";
return isset(self::$apiStatusColors[$this->api_status]) ? self::$apiStatusColors[$this->api_status] : 'warning';
}
public function getFormattedTotal()
@ -429,7 +491,7 @@ class ShoppingOrder extends Model
public function getFormattedPoints()
{
return isset($this->attributes['points']) ? formatNumber($this->attributes['points']) : "";
return isset($this->attributes['points']) ? formatNumber($this->attributes['points']) : '';
}
public function getPriceVkNetBy($product_id)
@ -439,16 +501,18 @@ class ShoppingOrder extends Model
return $product->getPriceWith(true, false, $this->shipping_country->country);
}
}
return 0;
}
public function getPaymentForType()
{
return isset(self::$paymentForTypes[$this->payment_for]) ? __('payment.' . self::$paymentForTypes[$this->payment_for]) : "";
return isset(self::$paymentForTypes[$this->payment_for]) ? __('payment.'.self::$paymentForTypes[$this->payment_for]) : '';
}
public function getPaymentForColor()
{
return isset(self::$paymentForColors[$this->payment_for]) ? self::$paymentForColors[$this->payment_for] : "";
return isset(self::$paymentForColors[$this->payment_for]) ? self::$paymentForColors[$this->payment_for] : '';
}
public function getUserDiscount()
@ -459,6 +523,7 @@ class ShoppingOrder extends Model
if ($this->member && $this->member->user_level) {
return $this->member->user_level->getFormattedMargin();
}
return 0;
}
@ -470,21 +535,49 @@ class ShoppingOrder extends Model
$count += $shopping_order_item->qty;
}
}
return $count;
}
public function isInvoice()
{
return $this->user_invoice ? true : false;
}
/**
* Prüft ob eine Stornorechnung für diese Bestellung existiert.
* Die echte Stornorechnung hat cancellation=true und cancellation_id=null.
*/
public function isCancellationInvoice()
{
return \App\Models\UserInvoice::where('shopping_order_id', $this->id)
->where('cancellation', true)
->whereNull('cancellation_id')
->exists();
}
/**
* Holt die Stornorechnung für diese Bestellung.
* Die echte Stornorechnung hat cancellation=true und cancellation_id=null.
*/
public function getCancellationInvoice()
{
return \App\Models\UserInvoice::where('shopping_order_id', $this->id)
->where('cancellation', true)
->whereNull('cancellation_id')
->first();
}
public function getStatusByOrder()
{
if ($this->payment_for) {
if ($this->payment_for === 6) { //Kunde-Shop
if ($this->payment_for === 6) { // Kunde-Shop
return 2;
}
return 1;
}
return 0;
}
@ -538,7 +631,7 @@ class ShoppingOrder extends Model
}
if (isset($tax_split[5])) {
if (!isset($tax_split[16])) {
if (! isset($tax_split[16])) {
$tax_split[16] = ['vk_tax' => $order_vk_tax, 'ek_tax' => $order_ek_tax];
$net_split[16] = ['vk_net' => $order_vk_net, 'ek_net' => $order_ek_net];
}
@ -548,7 +641,7 @@ class ShoppingOrder extends Model
$net_split[16]['ek_net'] = round($net_split[16]['ek_net'] - $net_split[5]['ek_net'], 2);
}
if (isset($tax_split[7])) {
if (!isset($tax_split[19])) {
if (! isset($tax_split[19])) {
$tax_split[19] = ['vk_tax' => $order_vk_tax, 'ek_tax' => $order_ek_tax];
$net_split[19] = ['vk_net' => $order_vk_net, 'ek_net' => $order_ek_net];
}
@ -558,7 +651,6 @@ class ShoppingOrder extends Model
$net_split[19]['ek_net'] = round($net_split[19]['ek_net'] - $net_split[7]['ek_net'], 2);
}
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);
@ -569,14 +661,13 @@ class ShoppingOrder extends Model
$net_split[$key]['ek_net'] = number_format($value['ek_net'], 2);
}
}
if (!isset($tax_split[16]) && !isset($tax_split[19])) {
$tax_split = NULL;
if (! isset($tax_split[16]) && ! isset($tax_split[19])) {
$tax_split = null;
}
if (!isset($net_split[16]) && !isset($net_split[19])) {
$net_split = NULL;
if (! isset($net_split[16]) && ! isset($net_split[19])) {
$net_split = null;
}
$this->tax_split = $tax_split;
$this->net_split = $net_split;
$this->save();
@ -584,8 +675,8 @@ class ShoppingOrder extends Model
public function makeTaxSplit()
{
$tax_split = NULL;
$net_split = NULL;
$tax_split = null;
$net_split = null;
if ($this->tax > 0) {
$tax_split = [];
@ -613,7 +704,7 @@ class ShoppingOrder extends Model
}
if (isset($tax_split[5])) {
if (!isset($tax_split[16])) {
if (! isset($tax_split[16])) {
$tax_split[16] = $this->tax;
$net_split[16] = $this->subtotal_ws;
}
@ -621,7 +712,7 @@ class ShoppingOrder extends Model
$net_split[16] = round($net_split[16] - $net_split[5], 2);
}
if (isset($tax_split[7])) {
if (!isset($tax_split[19])) {
if (! isset($tax_split[19])) {
$tax_split[19] = $this->tax;
$net_split[19] = $this->subtotal_ws;
}
@ -647,12 +738,12 @@ class ShoppingOrder extends Model
if ($this->shopping_user) {
$fullname = $this->shopping_user->getFullNameAsArray();
$ret = "";
$ret .= $fullname['company'] ? $fullname['company'] . ' | ' : '';
$ret .= $fullname['salutation'] ? \App\Services\HTMLHelper::getSalutationLang($fullname['salutation']) . ' ' : '';
$ret .= $fullname['firstname'] ? $fullname['firstname'] . ' ' : '';
$ret = '';
$ret .= $fullname['company'] ? $fullname['company'].' | ' : '';
$ret .= $fullname['salutation'] ? \App\Services\HTMLHelper::getSalutationLang($fullname['salutation']).' ' : '';
$ret .= $fullname['firstname'] ? $fullname['firstname'].' ' : '';
$ret .= $fullname['lastname'] ? $fullname['lastname'] : '';
$ret .= $fullname['email'] ? ' | ' . $fullname['email'] . '' : '';
$ret .= $fullname['email'] ? ' | '.$fullname['email'].'' : '';
}
return $ret;

View file

@ -243,9 +243,43 @@ class ShoppingUser extends Model
return $this->hasOne('App\Models\ShoppingOrder', 'shopping_user_id');
}
public function getLocale()
/**
* Accessor für das language Attribut.
* Gibt die App-Locale zurück, wenn keine Sprache gesetzt ist.
*
* @param string|null $value
* @return string Sprachcode (de, en, es)
*/
public function getLanguageAttribute($value): string
{
return $this->language ? $this->language : \App::getLocale();
return $value ?: \App::getLocale();
}
/**
* Alias für getLanguageAttribute - für Konsistenz mit anderen Models.
*
* @return string Sprachcode (de, en, es)
*/
public function getLocale(): string
{
return $this->language;
}
/**
* Liefert die verfügbaren Sprachen aus der Config als Array für Select-Felder.
*
* @return array ['code' => 'Native Name', ...]
*/
public static function getAvailableLanguages(): array
{
$locales = config('localization.supportedLocales', []);
$languages = [];
foreach ($locales as $code => $locale) {
$languages[$code] = $locale['native'] ?? $locale['name'] ?? $code;
}
return $languages;
}
public function setNotice($key, $value)

View file

@ -6,11 +6,11 @@
namespace App\Models;
use App\Services\Util;
use App\User;
use Carbon\Carbon;
use App\Services\Util;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
/**
@ -34,7 +34,6 @@ use Illuminate\Database\Eloquent\SoftDeletes;
* @property Carbon|null $user_deleted_at
* @property User $user
* @property Collection|UserAboOrder[] $user_abo_orders
* @package App\Models
* @property int|null $member_id
* @property int $shopping_user_id
* @property string|null $email
@ -48,6 +47,7 @@ use Illuminate\Database\Eloquent\SoftDeletes;
* @property-read Collection<int, \App\Models\UserAboItem> $user_abo_items
* @property-read int|null $user_abo_items_count
* @property-read int|null $user_abo_orders_count
*
* @method static \Illuminate\Database\Eloquent\Builder|UserAbo newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|UserAbo newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|UserAbo onlyTrashed()
@ -76,177 +76,213 @@ use Illuminate\Database\Eloquent\SoftDeletes;
* @method static \Illuminate\Database\Eloquent\Builder|UserAbo whereWallettype($value)
* @method static \Illuminate\Database\Eloquent\Builder|UserAbo withTrashed()
* @method static \Illuminate\Database\Eloquent\Builder|UserAbo withoutTrashed()
*
* @mixin \Eloquent
*/
class UserAbo extends Model
{
use SoftDeletes;
protected $table = 'user_abos';
use SoftDeletes;
protected $casts = [
'user_id' => 'int',
'member_id' => 'int',
'shopping_user_id' => 'int',
'payone_userid' => 'int',
'active' => 'bool',
'status' => 'int',
'abo_interval' => 'int',
'amount' => 'int',
'start_date' => 'datetime',
'last_date' => 'datetime',
'next_date' => 'datetime',
'cancel_date' => 'datetime',
'user_deleted_at' => 'datetime',
'carddata' => 'array'
protected $table = 'user_abos';
];
protected $casts = [
'user_id' => 'int',
'member_id' => 'int',
'shopping_user_id' => 'int',
'payone_userid' => 'int',
'active' => 'bool',
'status' => 'int',
'abo_interval' => 'int',
'amount' => 'int',
'start_date' => 'datetime',
'last_date' => 'datetime',
'next_date' => 'datetime',
'cancel_date' => 'datetime',
'user_deleted_at' => 'datetime',
'carddata' => 'array',
protected $fillable = [
'user_id',
'member_id',
'shopping_user_id',
'is_for',
'email',
'payone_userid',
'clearingtype',
'wallettype',
'carddata',
'amount',
'active',
'status',
'abo_interval',
'start_date',
'last_date',
'next_date',
'cancel_date',
'user_deleted_at'
];
];
public static $aboDeliveryDays = [5, 10, 20, 25];
protected $fillable = [
'user_id',
'member_id',
'shopping_user_id',
'is_for',
'email',
'payone_userid',
'clearingtype',
'wallettype',
'carddata',
'amount',
'active',
'status',
'abo_interval',
'start_date',
'last_date',
'next_date',
'cancel_date',
'user_deleted_at',
];
public static $statusTypes = [
0 => 'abo_new',
1 => 'abo_new',
2 => 'abo_okay',
3 => 'abo_hold',
4 => 'abo_cancel',
5 => 'abo_finish',
6 => 'abo_inactive',
7 => 'abo_grace'
];
public static $aboDeliveryDays = [5, 10, 20, 25];
public static $statusColors = [
0 => 'success',
1 => 'success',
2 => 'secondary',
3 => 'warning',
4 => 'danger',
5 => 'info',
6 => 'warning',
7 => 'danger'
];
public static $statusTypes = [
0 => 'abo_new',
1 => 'abo_new',
2 => 'abo_okay',
3 => 'abo_hold',
4 => 'abo_cancel',
5 => 'abo_finish',
6 => 'abo_inactive',
7 => 'abo_grace',
];
public static $statusColors = [
0 => 'success',
1 => 'success',
2 => 'secondary',
3 => 'warning',
4 => 'danger',
5 => 'info',
6 => 'warning',
7 => 'danger',
];
public function user()
{
return $this->belongsTo(User::class, 'user_id');
}
public function user()
{
return $this->belongsTo(User::class, 'user_id');
}
public function member()
{
return $this->belongsTo(User::class, 'member_id');
}
public function member()
{
return $this->belongsTo(User::class, 'member_id');
}
public function shopping_user()
{
return $this->belongsTo('App\Models\ShoppingUser', 'shopping_user_id');
}
public function shopping_user()
{
return $this->belongsTo('App\Models\ShoppingUser', 'shopping_user_id');
}
public function user_abo_orders()
{
return $this->hasMany(UserAboOrder::class);
}
public function user_abo_orders()
{
return $this->hasMany(UserAboOrder::class);
}
public function user_abo_items()
{
return $this->hasMany(UserAboItem::class);
}
public function user_abo_items()
{
return $this->hasMany(UserAboItem::class);
}
public function user_abo_item_histories()
{
return $this->hasMany(UserAboItemHistory::class);
}
public function getCountOrders()
{
//sind bezahlte Bestellungen
return $this->user_abo_orders->where('status', '>=', 2)->count();
}
public function getInitialItems()
{
return $this->user_abo_item_histories()
->where('is_initial', true)
->where('comp', 0)
->orderBy('created_at')
->get();
}
public function getCountPaidOrders()
{
//sind bezahlte Bestellungen
return $this->user_abo_orders->where('status', '>=', 2)->where('paid', true)->count();
}
public function getInitialCompItems()
{
return $this->user_abo_item_histories()
->where('is_initial', true)
->where('comp', '>', 0)
->orderBy('comp')
->get();
}
public function setStartDateAttribute($value)
{
$this->attributes['start_date'] = isset($value) ? (new Carbon($value))->format('Y-m-d') : NULL;
}
public function getStartDateAttribute()
{
return $this->attributes['start_date'] ? Carbon::parse($this->attributes['start_date'])->format(\Util::formatDateDB()) : '';
}
public function getChangeHistory()
{
return $this->user_abo_item_histories()
->where('is_initial', false)
->orderByDesc('created_at')
->get();
}
public function setLastDateAttribute($value)
{
$this->attributes['last_date'] = isset($value) ? (new Carbon($value))->format('Y-m-d') : NULL;
}
public function getLastDateAttribute()
{
return $this->attributes['last_date'] ? Carbon::parse($this->attributes['last_date'])->format(\Util::formatDateDB()) : '';
}
public function getCountOrders()
{
// sind bezahlte Bestellungen
return $this->user_abo_orders->where('status', '>=', 2)->count();
}
public function setNextDateAttribute($value)
{
$this->attributes['next_date'] = isset($value) ? (new Carbon($value))->format('Y-m-d') : NULL;
}
public function getNextDateAttribute()
{
return $this->attributes['next_date'] ? Carbon::parse($this->attributes['next_date'])->format(\Util::formatDateDB()) : '';
}
public function getCountPaidOrders()
{
// sind bezahlte Bestellungen
return $this->user_abo_orders->where('status', '>=', 2)->where('paid', true)->count();
}
public function setCancelDateAttribute($value)
{
$this->attributes['cancel_date'] = isset($value) ? (new Carbon($value))->format('Y-m-d') : NULL;
}
public function getCancelDateAttribute()
{
return $this->attributes['cancel_date'] ? Carbon::parse($this->attributes['cancel_date'])->format(\Util::formatDateDB()) : '';
}
public function setStartDateAttribute($value)
{
$this->attributes['start_date'] = isset($value) ? (new Carbon($value))->format('Y-m-d') : null;
}
public function getFormattedAmount()
{
return isset($this->attributes['amount']) ? Util::formatNumber($this->attributes['amount'] / 100) : "";
}
public function getIsForFormated()
{
return $this->attributes['is_for'] === 'me' ? '<span class="badge badge-outline-warning-dark">' . __('tables.adviser') . '</span>' : '<span class="badge badge-outline-info">' . __('tables.customer') . '</span>';
}
public function getStartDateAttribute()
{
return $this->attributes['start_date'] ? Carbon::parse($this->attributes['start_date'])->format(\Util::formatDateDB()) : '';
}
public function getStatusFormated()
{
return '<span class="badge badge-pill badge-' . $this->getStatusColor() . '">' . $this->getStatusType() . '</span>';
}
public function setLastDateAttribute($value)
{
$this->attributes['last_date'] = isset($value) ? (new Carbon($value))->format('Y-m-d') : null;
}
public function getStatusType()
{
return isset(self::$statusTypes[$this->status]) ? __('abo.' . self::$statusTypes[$this->status]) : "";
}
public function getLastDateAttribute()
{
return $this->attributes['last_date'] ? Carbon::parse($this->attributes['last_date'])->format(\Util::formatDateDB()) : '';
}
public function getStatusColor()
{
return isset(self::$statusColors[$this->status]) ? self::$statusColors[$this->status] : "default";
}
public function setNextDateAttribute($value)
{
$this->attributes['next_date'] = isset($value) ? (new Carbon($value))->format('Y-m-d') : null;
}
public function getPaymentType()
{
return $this->clearingtype === 'wlt' ? __('payment.paypal') : __('payment.credit_card');
}
public function getNextDateAttribute()
{
return $this->attributes['next_date'] ? Carbon::parse($this->attributes['next_date'])->format(\Util::formatDateDB()) : '';
}
public function setCancelDateAttribute($value)
{
$this->attributes['cancel_date'] = isset($value) ? (new Carbon($value))->format('Y-m-d') : null;
}
public function getCancelDateAttribute()
{
return $this->attributes['cancel_date'] ? Carbon::parse($this->attributes['cancel_date'])->format(\Util::formatDateDB()) : '';
}
public function getFormattedAmount()
{
return isset($this->attributes['amount']) ? Util::formatNumber($this->attributes['amount'] / 100) : '';
}
public function getIsForFormated()
{
return $this->attributes['is_for'] === 'me' ? '<span class="badge badge-outline-warning-dark">'.__('tables.adviser').'</span>' : '<span class="badge badge-outline-info">'.__('tables.customer').'</span>';
}
public function getStatusFormated()
{
return '<span class="badge badge-pill badge-'.$this->getStatusColor().'">'.$this->getStatusType().'</span>';
}
public function getStatusType()
{
return isset(self::$statusTypes[$this->status]) ? __('abo.'.self::$statusTypes[$this->status]) : '';
}
public function getStatusColor()
{
return isset(self::$statusColors[$this->status]) ? self::$statusColors[$this->status] : 'default';
}
public function getPaymentType()
{
return $this->clearingtype === 'wlt' ? __('payment.paypal') : __('payment.credit_card');
}
}

View file

@ -0,0 +1,187 @@
<?php
namespace App\Models;
use App\Services\Util;
use App\User;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Model;
class UserAboItemHistory extends Model
{
protected $table = 'user_abo_item_histories';
const ACTION_INITIAL = 'initial';
const ACTION_ADDED = 'added';
const ACTION_REMOVED = 'removed';
const ACTION_QTY_CHANGED = 'qty_changed';
const ACTION_COMP_CHANGED = 'comp_product_changed';
const ACTION_COMP_ADDED = 'comp_added';
const ACTION_COMP_REMOVED = 'comp_removed';
const ACTION_ROLLBACK = 'rollback';
const CHANNEL_ADMIN = 'admin';
const CHANNEL_USER_ME = 'user_me';
const CHANNEL_USER_OT = 'user_ot';
const CHANNEL_PORTAL = 'portal';
const CHANNEL_SYSTEM = 'system';
public static $actionLabels = [
'initial' => 'abo_history.action_initial',
'added' => 'abo_history.action_added',
'removed' => 'abo_history.action_removed',
'qty_changed' => 'abo_history.action_qty_changed',
'comp_product_changed' => 'abo_history.action_comp_changed',
'comp_added' => 'abo_history.action_comp_added',
'comp_removed' => 'abo_history.action_comp_removed',
'rollback' => 'abo_history.action_rollback',
];
public static $actionColors = [
'initial' => 'info',
'added' => 'success',
'removed' => 'danger',
'qty_changed' => 'warning',
'comp_product_changed' => 'primary',
'comp_added' => 'success',
'comp_removed' => 'danger',
'rollback' => 'dark',
];
public static $channelLabels = [
'admin' => 'abo_history.channel_admin',
'user_me' => 'abo_history.channel_user_me',
'user_ot' => 'abo_history.channel_user_ot',
'portal' => 'abo_history.channel_portal',
'system' => 'abo_history.channel_system',
];
public static $channelColors = [
'admin' => 'danger',
'user_me' => 'warning',
'user_ot' => 'info',
'portal' => 'secondary',
'system' => 'default',
];
protected $casts = [
'user_abo_id' => 'int',
'user_abo_item_id' => 'int',
'product_id' => 'int',
'unit_price' => 'float',
'total_price' => 'float',
'qty_before' => 'int',
'qty_after' => 'int',
'old_product_id' => 'int',
'comp' => 'int',
'changed_by_user_id' => 'int',
'is_initial' => 'bool',
];
protected $fillable = [
'user_abo_id',
'user_abo_item_id',
'product_id',
'action',
'product_name',
'product_number',
'unit_price',
'total_price',
'qty_before',
'qty_after',
'old_product_id',
'old_product_name',
'comp',
'changed_by_user_id',
'changed_by_name',
'channel',
'batch_id',
'is_initial',
];
public function user_abo()
{
return $this->belongsTo(UserAbo::class);
}
public function product()
{
return $this->belongsTo(Product::class);
}
public function old_product()
{
return $this->belongsTo(Product::class, 'old_product_id');
}
public function changed_by()
{
return $this->belongsTo(User::class, 'changed_by_user_id');
}
public function getActionBadge()
{
$label = isset(self::$actionLabels[$this->action]) ? __(self::$actionLabels[$this->action]) : $this->action;
$color = self::$actionColors[$this->action] ?? 'secondary';
return '<span class="badge badge-'.$color.'">'.$label.'</span>';
}
public function getChannelBadge()
{
$label = isset(self::$channelLabels[$this->channel]) ? __(self::$channelLabels[$this->channel]) : $this->channel;
$color = self::$channelColors[$this->channel] ?? 'secondary';
return '<span class="badge badge-outline-'.$color.'">'.$label.'</span>';
}
public function getChangeDescription()
{
switch ($this->action) {
case self::ACTION_INITIAL:
return __('abo_history.desc_initial', ['qty' => $this->qty_after]);
case self::ACTION_ADDED:
return __('abo_history.desc_added', ['qty' => $this->qty_after]);
case self::ACTION_REMOVED:
return __('abo_history.desc_removed');
case self::ACTION_QTY_CHANGED:
return __('abo_history.desc_qty_changed', ['from' => $this->qty_before, 'to' => $this->qty_after]);
case self::ACTION_COMP_CHANGED:
return __('abo_history.desc_comp_changed', ['old' => $this->old_product_name]);
case self::ACTION_COMP_ADDED:
return __('abo_history.desc_comp_added');
case self::ACTION_COMP_REMOVED:
return __('abo_history.desc_comp_removed');
case self::ACTION_ROLLBACK:
return __('abo_history.desc_rollback');
default:
return '';
}
}
public function getFormattedUnitPrice()
{
return Util::formatNumber($this->unit_price);
}
public function getFormattedTotalPrice()
{
return Util::formatNumber($this->total_price);
}
public function getFormattedDate()
{
return Carbon::parse($this->created_at)->format('d.m.Y H:i');
}
}

View file

@ -2,10 +2,9 @@
namespace App\Models;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Carbon\Carbon;
/**
* App\Models\UserAccount
@ -18,6 +17,7 @@ use Carbon\Carbon;
* @property-read \App\Models\Country $pre_mobil
* @property-read \App\Models\Country $pre_phone
* @property-read \App\User $user
*
* @method static bool|null forceDelete()
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\UserAccount newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\UserAccount newQuery()
@ -26,6 +26,7 @@ use Carbon\Carbon;
* @method static bool|null restore()
* @method static \Illuminate\Database\Query\Builder|\App\Models\UserAccount withTrashed()
* @method static \Illuminate\Database\Query\Builder|\App\Models\UserAccount withoutTrashed()
*
* @property int $id
* @property string|null $salutation
* @property string|null $first_name
@ -63,6 +64,7 @@ use Carbon\Carbon;
* @property \Illuminate\Support\Carbon|null $deleted_at
* @property-read \App\Models\Country $shipping_country
* @property-read \App\Models\Country|null $shipping_pre_phone
*
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\UserAccount whereAddress($value)
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\UserAccount whereAddress2($value)
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\UserAccount whereBirthday($value)
@ -100,41 +102,53 @@ use Carbon\Carbon;
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\UserAccount whereUpdatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\UserAccount whereWebsite($value)
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\UserAccount whereZipcode($value)
*
* @property string|null $m_account
* @property string|null $m_salutation
* @property string|null $m_first_name
* @property string|null $m_last_name
* @property string|null $m_notes
* @property int|null $taxable_sales
*
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\UserAccount whereMAccount($value)
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\UserAccount whereMFirstName($value)
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\UserAccount whereMLastName($value)
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\UserAccount whereMNotes($value)
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\UserAccount whereMSalutation($value)
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\UserAccount whereTaxableSales($value)
*
* @property array|null $payment_data
*
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\UserAccount wherePaymentData($value)
*
* @property string|null $accepted_contract
* @property array|null $notice
*
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\UserAccount whereAcceptedContract($value)
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\UserAccount whereNotice($value)
*
* @property int $reverse_charge
* @property string|null $reverse_charge_code
* @property string|null $reverse_charge_valid
*
* @method static \Illuminate\Database\Eloquent\Builder|UserAccount whereReverseCharge($value)
* @method static \Illuminate\Database\Eloquent\Builder|UserAccount whereReverseChargeCode($value)
* @method static \Illuminate\Database\Eloquent\Builder|UserAccount whereReverseChargeValid($value)
*
* @property string|null $bank_owner
* @property string|null $bank_iban
* @property string|null $bank_bic
*
* @method static \Illuminate\Database\Eloquent\Builder|UserAccount whereBankBic($value)
* @method static \Illuminate\Database\Eloquent\Builder|UserAccount whereBankIban($value)
* @method static \Illuminate\Database\Eloquent\Builder|UserAccount whereBankOwner($value)
*
* @mixin \Eloquent
*/
class UserAccount extends Model
{
protected $table = 'user_accounts';
protected $fillable = [
'm_account',
'm_salutation',
@ -178,19 +192,20 @@ class UserAccount extends Model
'bank_owner',
'bank_iban',
'bank_bic',
'notice'
'notice',
'language',
];
//'reverse_charge', 'reverse_charge_valid'
// 'reverse_charge', 'reverse_charge_valid'
protected $casts = [
'payment_data' => 'array',
'notice' => 'array',
//'reverse_charge' => 'bool'
// 'reverse_charge' => 'bool'
];
use SoftDeletes;
protected $dates = ['deleted_at'];
protected $dates = ['deleted_at'];
public function user()
{
@ -224,38 +239,42 @@ class UserAccount extends Model
public function getBirthdayAttribute($value)
{
if (!$value) {
return "";
if (! $value) {
return '';
}
return Carbon::parse($value)->format(\Util::formatDateDB());
}
public function setBirthdayAttribute($value)
{
$this->attributes['birthday'] = isset($value) ? (new Carbon($value))->format('Y-m-d') : NULL;
$this->attributes['birthday'] = isset($value) ? (new Carbon($value))->format('Y-m-d') : null;
}
public function getDataProtectionFormat()
{
if (!$this->attributes['data_protection']) {
return "";
if (! $this->attributes['data_protection']) {
return '';
}
return Carbon::parse($this->attributes['data_protection'])->format(\Util::formatDateTimeDB());
}
public function getAcceptContractFormat()
{
if (!$this->attributes['accept_contract']) {
return "";
if (! $this->attributes['accept_contract']) {
return '';
}
return Carbon::parse($this->attributes['accept_contract'])->format(\Util::formatDateTimeDB());
}
public function getReverseChargeValidFormat()
{
if (!$this->attributes['reverse_charge_valid']) {
return "";
if (! $this->attributes['reverse_charge_valid']) {
return '';
}
return Carbon::parse($this->attributes['reverse_charge_valid'])->format(\Util::formatDateTimeDB());
}
@ -268,10 +287,12 @@ class UserAccount extends Model
if ($as) {
return $as;
}
return true;
}
}
return "";
return '';
}
public function setNotice($key, $value)
@ -289,35 +310,77 @@ class UserAccount extends Model
public function getPhoneNumber()
{
if ($this->mobil && $this->mobil !== "") {
return ($this->pre_mobil ? $this->pre_mobil->phone : '') . " " . $this->mobil;
if ($this->mobil && $this->mobil !== '') {
return ($this->pre_mobil ? $this->pre_mobil->phone : '').' '.$this->mobil;
}
if ($this->phone && $this->phone !== "") {
return ($this->pre_phone ? $this->pre_phone->phone : '') . " " . $this->phone;
if ($this->phone && $this->phone !== '') {
return ($this->pre_phone ? $this->pre_phone->phone : '').' '.$this->phone;
}
}
public function getPhoneFull()
{
if ($this->phone && $this->phone !== "") {
return ($this->pre_phone ? $this->pre_phone->phone : '') . " " . $this->phone;
if ($this->phone && $this->phone !== '') {
return ($this->pre_phone ? $this->pre_phone->phone : '').' '.$this->phone;
}
return "";
return '';
}
public function getMobilFull()
{
if ($this->mobil && $this->mobil !== "") {
return ($this->pre_mobil ? $this->pre_mobil->phone : '') . " " . $this->mobil;
if ($this->mobil && $this->mobil !== '') {
return ($this->pre_mobil ? $this->pre_mobil->phone : '').' '.$this->mobil;
}
return "";
return '';
}
public function getShippingPhoneFull()
{
if ($this->shipping_phone && $this->shipping_phone !== "") {
return ($this->shipping_pre_phone ? $this->shipping_pre_phone->phone : '') . " " . $this->shipping_phone;
if ($this->shipping_phone && $this->shipping_phone !== '') {
return ($this->shipping_pre_phone ? $this->shipping_pre_phone->phone : '').' '.$this->shipping_phone;
}
return "";
return '';
}
/**
* Accessor für das language Attribut.
* Gibt die App-Locale zurück, wenn keine Sprache gesetzt ist.
*
* @param string|null $value
* @return string Sprachcode (de, en, es)
*/
public function getLanguageAttribute($value): string
{
return $value ?: \App::getLocale();
}
/**
* Alias für getLanguageAttribute - für Konsistenz mit anderen Models.
*
* @return string Sprachcode (de, en, es)
*/
public function getLocale(): string
{
return $this->language;
}
/**
* Liefert die verfügbaren Sprachen aus der Config als Array für Select-Felder.
*
* @return array ['code' => 'Native Name', ...]
*/
public static function getAvailableLanguages(): array
{
$locales = config('localization.supportedLocales', []);
$languages = [];
foreach ($locales as $code => $locale) {
$languages[$code] = $locale['native'] ?? $locale['name'] ?? $code;
}
return $languages;
}
}

View file

@ -8,8 +8,8 @@ namespace App\Models;
use App\User;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
/**
@ -41,9 +41,9 @@ use Illuminate\Database\Eloquent\SoftDeletes;
* @property string|null $deleted_at
* @property User $user
* @property Collection|UserCreditItem[] $user_credit_items
* @package App\Models
* @property bool $taxable
* @property-read int|null $user_credit_items_count
*
* @method static \Illuminate\Database\Eloquent\Builder|UserCredit newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|UserCredit newQuery()
* @method static \Illuminate\Database\Query\Builder|UserCredit onlyTrashed()
@ -75,146 +75,246 @@ use Illuminate\Database\Eloquent\SoftDeletes;
* @method static \Illuminate\Database\Eloquent\Builder|UserCredit whereYear($value)
* @method static \Illuminate\Database\Query\Builder|UserCredit withTrashed()
* @method static \Illuminate\Database\Query\Builder|UserCredit withoutTrashed()
*
* @mixin \Eloquent
*/
class UserCredit extends Model
{
use SoftDeletes;
protected $table = 'user_credits';
use SoftDeletes;
protected $casts = [
'user_id' => 'int',
'month' => 'int',
'year' => 'int',
'number' => 'int',
'net' => 'float',
'tax_rate' => 'float',
'tax' => 'float',
'taxable' => 'int',
'total' => 'float',
'paid_out' => 'bool',
'cancellation' => 'bool',
'cancellation_id' => 'int',
'status' => 'int',
'infos' => 'array'
];
protected $table = 'user_credits';
protected $dates = [
'date',
'paid_out_date',
'cancellation_date'
];
protected $casts = [
'user_id' => 'int',
'month' => 'int',
'year' => 'int',
'number' => 'int',
'net' => 'float',
'tax_rate' => 'float',
'tax' => 'float',
'taxable' => 'int',
'total' => 'float',
'paid_out' => 'bool',
'cancellation' => 'bool',
'cancellation_id' => 'int',
'status' => 'int',
'infos' => 'array',
];
protected $fillable = [
'user_id',
'month',
'year',
'date',
'full_number',
'number',
'net',
'tax_rate',
'tax',
'total',
'taxable',
'filename',
'dir',
'disk',
'infos',
'paid_out',
'paid_out_date',
'cancellation',
'cancellation_id',
'cancellation_date',
'status'
];
protected $dates = [
'date',
'paid_out_date',
'cancellation_date',
];
public static $statusTypes = [
protected $fillable = [
'user_id',
'month',
'year',
'date',
'full_number',
'number',
'net',
'tax_rate',
'tax',
'total',
'taxable',
'filename',
'dir',
'disk',
'infos',
'paid_out',
'paid_out_date',
'cancellation',
'cancellation_id',
'cancellation_date',
'status',
];
public static $statusTypes = [
0 => 'open',
1 => 'paid',
2 => 'check',
10 => 'cancelled'
10 => 'cancelled',
];
public static $statusColors = [
0 => 'warning',
1 => 'success',
1 => 'success',
2 => 'secondary',
10 => 'danger',
10 => 'danger',
];
public static $taxableTypes = [
public static $taxableTypes = [
0 => '',
1 => 'umsatzsteuerpflichtig / DE', //payment.to_sales_tax_de
2 => 'nicht umsatzsteuerpflichtig / DE', //payment.not_to_sales_tax_de
3 => 'nicht umsatzsteuerpflichtig / Ausland' //payment.not_to_sales_tax_foreign
1 => 'umsatzsteuerpflichtig / DE', // payment.to_sales_tax_de
2 => 'nicht umsatzsteuerpflichtig / DE', // payment.not_to_sales_tax_de
3 => 'nicht umsatzsteuerpflichtig / Ausland', // payment.not_to_sales_tax_foreign
];
public function user()
{
return $this->belongsTo(User::class);
}
public function user()
{
return $this->belongsTo(User::class);
}
public function user_credit_items()
{
return $this->hasMany(UserCreditItem::class);
}
public function user_credit_items()
{
return $this->hasMany(UserCreditItem::class);
}
public function isCredit(){
public function isCredit()
{
return $this->filename ? true : false;
}
public function getDateAttribute($value)
public function getDateAttribute($value)
{
return $value ? Carbon::parse($value)->format(\Util::formatDateDB()) : "";
return $value ? Carbon::parse($value)->format(\Util::formatDateDB()) : '';
}
public function setDateAttribute( $value ) {
$this->attributes['date'] = isset($value) ? (new Carbon($value))->format('Y-m-d') : NULL;
}
public function getDateRaw(){
return isset($this->attributes['date']) ? $this->attributes['date'] : NULL;
public function setDateAttribute($value)
{
$this->attributes['date'] = isset($value) ? (new Carbon($value))->format('Y-m-d') : null;
}
public function getFormattedTax()
public function getDateRaw()
{
return isset($this->attributes['date']) ? $this->attributes['date'] : null;
}
public function getFormattedTax()
{
return formatNumber($this->attributes['tax']);
}
public function getFormattedNet()
public function getFormattedNet()
{
return formatNumber($this->attributes['net']);
}
public function getFormattedTotal()
public function getFormattedTotal()
{
return formatNumber($this->attributes['total']);
}
public function getStatusType(){
//trans('payment.cancelled')
return isset(self::$statusTypes[$this->status]) ? __('payment.'.self::$statusTypes[$this->status]) : "";
public function getStatusType()
{
// trans('payment.cancelled')
return isset(self::$statusTypes[$this->status]) ? __('payment.'.self::$statusTypes[$this->status]) : '';
}
public function getStatusColor(){
return isset(self::$statusColors[$this->status]) ? self::$statusColors[$this->status] : "default";
public function getStatusColor()
{
return isset(self::$statusColors[$this->status]) ? self::$statusColors[$this->status] : 'default';
}
public static function getTransStatusType(){
$ret = [];
foreach(self::$statusTypes as $key=>$val){
$ret[$key] = trans('payment.'.$val);
}
return $ret;
public static function getTransStatusType()
{
$ret = [];
foreach (self::$statusTypes as $key => $val) {
$ret[$key] = trans('payment.'.$val);
}
return $ret;
}
public function getDownloadPath($full = false){
if(!$full){
public function getDownloadPath($full = false)
{
if (! $full) {
return $this->dir.$this->filename;
}
return \Storage::disk($this->disk)->path($this->dir.$this->filename);
}
/**
* Gibt den Download-Pfad für die lokalisierte Gutschrift zurück.
* Bei 'de' oder nicht vorhandener Locale-Version wird das Original zurückgegeben.
*
* @param string|null $locale Sprachcode (de, en, es)
* @param bool $full Vollständiger Dateisystempfad oder relativer Pfad
* @return string
*/
public function getDownloadPathLocale($locale = null, $full = false)
{
// Bei Deutsch oder keiner Angabe: Original zurückgeben
if (! $locale || $locale === 'de') {
return $this->getDownloadPath($full);
}
// Dateiname mit Locale-Suffix
$filename = str_replace('.pdf', '-'.$locale.'.pdf', $this->filename);
$path = $this->dir.$filename;
// Prüfen ob Locale-Version existiert, sonst Fallback auf DE
if (! \Storage::disk($this->disk)->exists($path)) {
return $this->getDownloadPath($full);
}
return $full ? \Storage::disk($this->disk)->path($path) : $path;
}
/**
* Gibt den lokalisierten Dateinamen für die Gutschrift zurück.
*
* @param string|null $locale
* @return string
*/
public function getFilenameLocale($locale = null)
{
if (! $locale || $locale === 'de') {
return $this->filename;
}
$filename = str_replace('.pdf', '-'.$locale.'.pdf', $this->filename);
$path = $this->dir.$filename;
// Fallback auf Original wenn nicht vorhanden
if (! \Storage::disk($this->disk)->exists($path)) {
return $this->filename;
}
return $filename;
}
/**
* Gibt alle verfügbaren lokalisierten Versionen der Gutschrift zurück (außer DE).
*
* @return array Array mit Sprachcodes, z.B. ['en', 'es']
*/
public function getAvailableLocales(): array
{
$availableTemplates = config('localization.availableTemplates', ['de']);
$locales = [];
foreach ($availableTemplates as $locale) {
if ($locale === 'de') {
continue;
}
$filename = str_replace('.pdf', '-'.$locale.'.pdf', $this->filename);
$path = $this->dir.$filename;
if (\Storage::disk($this->disk)->exists($path)) {
$locales[] = $locale;
}
}
return $locales;
}
/**
* Prüft ob eine lokalisierte Version für die angegebene Sprache existiert.
*/
public function hasLocale(string $locale): bool
{
if ($locale === 'de') {
return true;
}
$filename = str_replace('.pdf', '-'.$locale.'.pdf', $this->filename);
$path = $this->dir.$filename;
return \Storage::disk($this->disk)->exists($path);
}
}

View file

@ -25,8 +25,8 @@ use Illuminate\Database\Eloquent\Model;
* @property Carbon|null $updated_at
* @property UserCredit|null $user_credit
* @property User $user
* @package App\Models
* @property int|null $user_business_id
*
* @method static \Illuminate\Database\Eloquent\Builder|UserCreditItem newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|UserCreditItem newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|UserCreditItem query()
@ -40,103 +40,109 @@ use Illuminate\Database\Eloquent\Model;
* @method static \Illuminate\Database\Eloquent\Builder|UserCreditItem whereUserBusinessId($value)
* @method static \Illuminate\Database\Eloquent\Builder|UserCreditItem whereUserCreditId($value)
* @method static \Illuminate\Database\Eloquent\Builder|UserCreditItem whereUserId($value)
*
* @property int|null $from_month
* @property int|null $from_year
*
* @method static \Illuminate\Database\Eloquent\Builder|UserCreditItem whereFromMonth($value)
* @method static \Illuminate\Database\Eloquent\Builder|UserCreditItem whereFromYear($value)
*
* @mixin \Eloquent
*/
class UserCreditItem extends Model
{
public static $statusTypes = [
1 => 'commission_shop',
2 => 'commission_payline',
3 => 'credit_added',
4 => 'commission',
5 => 'commission_growth_bonus',
public static $statusTypes = [
1 => 'commission_shop',
2 => 'commission_payline',
3 => 'credit_added',
4 => 'commission',
5 => 'commission_growth_bonus',
];
public static $statusColors = [
0 => 'warning',
1 => 'success',
2 => 'secondary',
3 => 'warning',
4 => 'info',
5 => 'secondary',
10 => 'danger',
];
public static $statusColors = [
0 => 'warning',
1 => 'success',
2 => 'secondary',
3 => 'warning',
4 => 'info',
5 => 'secondary',
10 => 'danger',
];
protected $table = 'user_credit_items';
protected $table = 'user_credit_items';
protected $casts = [
'user_id' => 'int',
'user_credit_id' => 'int',
'user_business_id' => 'int',
'credit' => 'float',
'status' => 'int',
'from_month' => 'int',
'from_year' => 'int',
'paid' => 'bool'
];
protected $casts = [
'user_id' => 'int',
'user_credit_id' => 'int',
'user_business_id' => 'int',
'credit' => 'float',
'status' => 'int',
'from_month' => 'int',
'from_year' => 'int',
'paid' => 'bool',
];
protected $fillable = [
'user_id',
'user_credit_id',
'user_business_id',
'credit',
'message',
'status',
'from_month',
'from_year',
'paid'
];
protected $fillable = [
'user_id',
'user_credit_id',
'user_business_id',
'credit',
'message',
'status',
'from_month',
'from_year',
'paid',
];
public function user_credit()
{
return $this->belongsTo(UserCredit::class);
}
public function user()
{
return $this->belongsTo(User::class);
}
public function deleteTime(){
$time = '+100 min';
if(Carbon::parse($this->created_at)->modify($time)->gt(Carbon::now())){
return Carbon::now()->diffInMinutes(Carbon::parse($this->created_at)->modify($time));
}
return false;
}
public function getStatusType(){
return isset(self::$statusTypes[$this->status]) ? __('payment.'.self::$statusTypes[$this->status]) : "";
public function user_credit()
{
return $this->belongsTo(UserCredit::class);
}
public function getStatusColor(){
return isset(self::$statusColors[$this->status]) ? self::$statusColors[$this->status] : "default";
public function user()
{
return $this->belongsTo(User::class);
}
public function getTransMessage(){
$ret = "";
if(strpos($this->message, '#')){
$em = explode("#", $this->message);
if(isset($em[0])){ //Provision
$ret .= trans($em[0])." ";
}
if(isset($em[1])){ //month
$ret .= HTMLHelper::getMonth($em[1])." ";
}
if(isset($em[2])){ //year
$ret .= $em[2];
}
}
return $ret;
}
public function deleteTime()
{
$time = '+100 min';
if (Carbon::parse($this->created_at)->modify($time)->gt(Carbon::now())) {
return Carbon::now()->diffInMinutes(Carbon::parse($this->created_at)->modify($time));
}
return false;
}
public function getStatusType()
{
return isset(self::$statusTypes[$this->status]) ? __('payment.'.self::$statusTypes[$this->status]) : '';
}
public function getStatusColor()
{
return isset(self::$statusColors[$this->status]) ? self::$statusColors[$this->status] : 'default';
}
public function getTransMessage()
{
$ret = '';
if (strpos($this->message, '#')) {
$em = explode('#', $this->message);
if (isset($em[0])) { // Provision
$ret .= trans($em[0]).' ';
}
if (isset($em[1])) { // month
$ret .= HTMLHelper::getMonth($em[1]).' ';
}
if (isset($em[2])) { // year
$ret .= $em[2];
}
} else {
$ret = $this->message;
}
return $ret;
}
}

View file

@ -32,12 +32,12 @@ use Illuminate\Database\Eloquent\SoftDeletes;
* @property Carbon|null $updated_at
* @property string|null $deleted_at
* @property ShoppingOrder $shopping_order
* @package App\Models
* @property string|null $filename
* @property string|null $dir
* @property string|null $delivery_filename
* @property string|null $delivery_dir
* @property string|null $disk
*
* @method static \Illuminate\Database\Eloquent\Builder|UserInvoice newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|UserInvoice newQuery()
* @method static \Illuminate\Database\Query\Builder|UserInvoice onlyTrashed()
@ -66,143 +66,285 @@ use Illuminate\Database\Eloquent\SoftDeletes;
* @method static \Illuminate\Database\Eloquent\Builder|UserInvoice whereYear($value)
* @method static \Illuminate\Database\Query\Builder|UserInvoice withTrashed()
* @method static \Illuminate\Database\Query\Builder|UserInvoice withoutTrashed()
*
* @mixin \Eloquent
*/
class UserInvoice extends Model
{
use SoftDeletes;
protected $table = 'user_invoices';
use SoftDeletes;
protected $casts = [
'shopping_order_id' => 'int',
'month' => 'int',
'year' => 'int',
'number' => 'int',
'paid' => 'bool',
'cancellation' => 'bool',
'cancellation_id' => 'int',
'status' => 'int',
'infos' => 'array',
];
protected $table = 'user_invoices';
protected $dates = [
'date',
'paid_date',
'cancellation_date'
];
protected $casts = [
'shopping_order_id' => 'int',
'month' => 'int',
'year' => 'int',
'number' => 'int',
'paid' => 'bool',
'cancellation' => 'bool',
'cancellation_id' => 'int',
'status' => 'int',
'infos' => 'array',
];
protected $fillable = [
'shopping_order_id',
'month',
'year',
'date',
'full_number',
'number',
'filename',
'dir',
'delivery_filename',
'delivery_dir',
'disk',
'infos',
'paid',
'paid_date',
'cancellation',
'cancellation_id',
'cancellation_date',
'status'
];
protected $dates = [
'date',
'paid_date',
'cancellation_date',
];
public static $monthNames = [
1 => 'Januar',
2 => 'Februar',
3 => 'März',
4 => 'April',
5 => 'Mai',
6 => 'Juni',
7 => 'Juli',
8 => 'August',
9 => 'September',
10 => 'Oktober',
11 => 'November',
12 => 'Dezember'
];
protected $fillable = [
'shopping_order_id',
'month',
'year',
'date',
'full_number',
'number',
'filename',
'dir',
'delivery_filename',
'delivery_dir',
'disk',
'infos',
'paid',
'paid_date',
'cancellation',
'cancellation_id',
'cancellation_date',
'status',
];
public static $statusTypes = [
0 => '-',
public static $monthNames = [
1 => 'Januar',
2 => 'Februar',
3 => 'März',
4 => 'April',
5 => 'Mai',
6 => 'Juni',
7 => 'Juli',
8 => 'August',
9 => 'September',
10 => 'Oktober',
11 => 'November',
12 => 'Dezember',
];
public static $statusTypes = [
0 => '-',
1 => 'Bestellung',
2 => 'Shop',
11 => 'storniert B.',
12 => 'storniert Shop',
12 => 'storniert Shop',
];
public static $statusColors = [
0 => 'warning',
1 => 'success',
1 => 'success',
2 => 'secondary',
11 => 'danger',
12 => 'danger',
11 => 'danger',
12 => 'danger',
];
public function shopping_order(){
return $this->belongsTo(ShoppingOrder::class);
}
public function getDateAttribute($value){
return $this->attributes['date'] ? Carbon::parse($this->attributes['date'])->format(\Util::formatDateDB()) : '';
}
public function setDateAttribute( $value ) {
$this->attributes['date'] = isset($value) ? (new Carbon($value))->format('Y-m-d') : NULL;
}
public function getDateRaw(){
return isset($this->attributes['date']) ? $this->attributes['date'] : NULL;
}
public function getPaidDateAttribute($value){
return $this->attributes['paid_date'] ? Carbon::parse($this->attributes['paid_date'])->format(\Util::formatDateDB()) : '';
}
public function setPaidDateAttribute( $value ) {
$this->attributes['paid_date'] = isset($value) ? (new Carbon($value))->format('Y-m-d') : NULL;
}
public function getPaidDateRaw(){
return isset($this->attributes['paid_date']) ? $this->attributes['paid_date'] : NULL;
}
public function getCancellationDateAttribute($value){
return $this->attributes['cancellation_date'] ? Carbon::parse($this->attributes['cancellation_date'])->format(\Util::formatDateDB()) : '';
}
public function setCancellationDateAttribute( $value ) {
$this->attributes['cancellation_date'] = isset($value) ? (new Carbon($value))->format('Y-m-d') : NULL;
}
public function getCancellationDateRaw(){
return isset($this->attributes['cancellation_date']) ? $this->attributes['cancellation_date'] : NULL;
}
public static function getMonthName($month)
public function shopping_order()
{
return isset(self::$monthNames[$month]) ? self::$monthNames[$month] : $month;
return $this->belongsTo(ShoppingOrder::class);
}
public function getStatusType(){
return isset(self::$statusTypes[$this->status]) ? self::$statusTypes[$this->status] : "";
public function getDateAttribute($value)
{
return $this->attributes['date'] ? Carbon::parse($this->attributes['date'])->format(\Util::formatDateDB()) : '';
}
public function getStatusColor(){
return isset(self::$statusColors[$this->status]) ? self::$statusColors[$this->status] : "default";
public function setDateAttribute($value)
{
$this->attributes['date'] = isset($value) ? (new Carbon($value))->format('Y-m-d') : null;
}
public function getDownloadPath($full = false){
if(!$full){
public function getDateRaw()
{
return isset($this->attributes['date']) ? $this->attributes['date'] : null;
}
public function getPaidDateAttribute($value)
{
return $this->attributes['paid_date'] ? Carbon::parse($this->attributes['paid_date'])->format(\Util::formatDateDB()) : '';
}
public function setPaidDateAttribute($value)
{
$this->attributes['paid_date'] = isset($value) ? (new Carbon($value))->format('Y-m-d') : null;
}
public function getPaidDateRaw()
{
return isset($this->attributes['paid_date']) ? $this->attributes['paid_date'] : null;
}
public function getCancellationDateAttribute($value)
{
return $this->attributes['cancellation_date'] ? Carbon::parse($this->attributes['cancellation_date'])->format(\Util::formatDateDB()) : '';
}
public function setCancellationDateAttribute($value)
{
$this->attributes['cancellation_date'] = isset($value) ? (new Carbon($value))->format('Y-m-d') : null;
}
public function getCancellationDateRaw()
{
return isset($this->attributes['cancellation_date']) ? $this->attributes['cancellation_date'] : null;
}
public static function getMonthName($month)
{
return isset(self::$monthNames[$month]) ? self::$monthNames[$month] : $month;
}
public function getStatusType()
{
return isset(self::$statusTypes[$this->status]) ? self::$statusTypes[$this->status] : '';
}
public function getStatusColor()
{
return isset(self::$statusColors[$this->status]) ? self::$statusColors[$this->status] : 'default';
}
public function getDownloadPath($full = false)
{
if (! $full) {
return $this->dir.$this->filename;
}
return \Storage::disk($this->disk)->path($this->dir.$this->filename);
}
public function getDownloadPathDelivery($full = false){
if(!$full){
public function getDownloadPathDelivery($full = false)
{
if (! $full) {
return $this->delivery_dir.$this->delivery_filename;
}
return \Storage::disk($this->disk)->path($this->delivery_dir.$this->delivery_filename);
}
}
/**
* Gibt den Download-Pfad für die lokalisierte Rechnung zurück.
* Bei 'de' oder nicht vorhandener Locale-Version wird das Original zurückgegeben.
*
* @param string|null $locale Sprachcode (de, en, es)
* @param bool $full Vollständiger Dateisystempfad oder relativer Pfad
* @return string
*/
public function getDownloadPathLocale($locale = null, $full = false)
{
// Bei Deutsch oder keiner Angabe: Original zurückgeben
if (! $locale || $locale === 'de') {
return $this->getDownloadPath($full);
}
// Dateiname mit Locale-Suffix
$filename = str_replace('.pdf', '-'.$locale.'.pdf', $this->filename);
$path = $this->dir.$filename;
// Prüfen ob Locale-Version existiert, sonst Fallback auf DE
if (! \Storage::disk($this->disk)->exists($path)) {
return $this->getDownloadPath($full);
}
return $full ? \Storage::disk($this->disk)->path($path) : $path;
}
/**
* Gibt den Download-Pfad für den lokalisierten Lieferschein zurück.
* Bei 'de' oder nicht vorhandener Locale-Version wird das Original zurückgegeben.
*
* @param string|null $locale Sprachcode (de, en, es)
* @param bool $full Vollständiger Dateisystempfad oder relativer Pfad
* @return string
*/
public function getDownloadPathDeliveryLocale($locale = null, $full = false)
{
// Bei Deutsch oder keiner Angabe: Original zurückgeben
if (! $locale || $locale === 'de') {
return $this->getDownloadPathDelivery($full);
}
// Dateiname mit Locale-Suffix
$filename = str_replace('.pdf', '-'.$locale.'.pdf', $this->delivery_filename);
$path = $this->delivery_dir.$filename;
// Prüfen ob Locale-Version existiert, sonst Fallback auf DE
if (! \Storage::disk($this->disk)->exists($path)) {
return $this->getDownloadPathDelivery($full);
}
return $full ? \Storage::disk($this->disk)->path($path) : $path;
}
/**
* Gibt den lokalisierten Dateinamen für die Rechnung zurück.
*
* @param string|null $locale
* @return string
*/
public function getFilenameLocale($locale = null)
{
if (! $locale || $locale === 'de') {
return $this->filename;
}
$filename = str_replace('.pdf', '-'.$locale.'.pdf', $this->filename);
$path = $this->dir.$filename;
// Fallback auf Original wenn nicht vorhanden
if (! \Storage::disk($this->disk)->exists($path)) {
return $this->filename;
}
return $filename;
}
/**
* Gibt alle verfügbaren lokalisierten Versionen der Rechnung zurück (außer DE).
*
* @return array Array mit Sprachcodes, z.B. ['en', 'es']
*/
public function getAvailableLocales(): array
{
$availableTemplates = config('localization.availableTemplates', ['de']);
$locales = [];
foreach ($availableTemplates as $locale) {
if ($locale === 'de') {
continue;
}
$filename = str_replace('.pdf', '-'.$locale.'.pdf', $this->filename);
$path = $this->dir.$filename;
if (\Storage::disk($this->disk)->exists($path)) {
$locales[] = $locale;
}
}
return $locales;
}
/**
* Prüft ob eine lokalisierte Version für die angegebene Sprache existiert.
*/
public function hasLocale(string $locale): bool
{
if ($locale === 'de') {
return true;
}
$filename = str_replace('.pdf', '-'.$locale.'.pdf', $this->filename);
$path = $this->dir.$filename;
return \Storage::disk($this->disk)->exists($path);
}
}

View file

@ -6,10 +6,9 @@
namespace App\Models;
use App\User;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Model;
use App\Models\ShoppingOrder;
use App\User;
/**
* Class UserSalesVolume
@ -32,11 +31,11 @@ use App\User;
* @property Carbon|null $updated_at
* @property ShoppingOrder|null $shopping_order
* @property User $user
* @package App\Models
* @property int|null $user_invoice_id
* @property int|null $month_shop_points
* @property float|null $month_shop_total_net
* @property-read \App\Models\UserInvoice|null $user_invoice
*
* @method static \Illuminate\Database\Eloquent\Builder|UserSalesVolume newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|UserSalesVolume newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|UserSalesVolume query()
@ -57,275 +56,293 @@ use App\User;
* @method static \Illuminate\Database\Eloquent\Builder|UserSalesVolume whereUserId($value)
* @method static \Illuminate\Database\Eloquent\Builder|UserSalesVolume whereUserInvoiceId($value)
* @method static \Illuminate\Database\Eloquent\Builder|UserSalesVolume whereYear($value)
*
* @property array|null $syslog
*
* @method static \Illuminate\Database\Eloquent\Builder|UserSalesVolume whereSyslog($value)
* @method static \Illuminate\Database\Eloquent\Builder|UserSalesVolume whereInfo($value)
* @method static \Illuminate\Database\Eloquent\Builder|UserSalesVolume whereStatusPoints($value)
*
* @property int|null $month_KP_points
* @property int|null $month_TP_points
*
* @method static \Illuminate\Database\Eloquent\Builder|UserSalesVolume whereMonthKPPoints($value)
* @method static \Illuminate\Database\Eloquent\Builder|UserSalesVolume whereMonthTPPoints($value)
*
* @property int|null $status_turnover
*
* @method static \Illuminate\Database\Eloquent\Builder|UserSalesVolume whereStatusTurnover($value)
*
* @mixin \Eloquent
*/
class UserSalesVolume extends Model
{
protected $table = 'user_sales_volumes';
protected $table = 'user_sales_volumes';
protected $casts = [
'user_id' => 'int',
'shopping_order_id' => 'int',
'user_invoice_id' => 'int',
'month' => 'int',
'year' => 'int',
'points' => 'float',
'month_KP_points' => 'float',
'month_TP_points' => 'float',
'month_shop_points' => 'float',
'status_points' => 'int',
'status_turnover' => 'int',
'total_net' => 'float',
'month_total_net' => 'float',
'month_shop_total_net' => 'float',
'status' => 'int',
'syslog' => 'array'
];
protected $casts = [
'user_id' => 'int',
'shopping_order_id' => 'int',
'user_invoice_id' => 'int',
'month' => 'int',
'year' => 'int',
'points' => 'float',
'month_KP_points' => 'float',
'month_TP_points' => 'float',
'month_shop_points' => 'float',
'status_points' => 'int',
'status_turnover' => 'int',
'total_net' => 'float',
'month_total_net' => 'float',
'month_shop_total_net' => 'float',
'status' => 'int',
'syslog' => 'array',
];
protected $dates = [
'date'
];
protected $dates = [
'date',
];
protected $fillable = [
'user_id',
'shopping_order_id',
'user_invoice_id',
'month',
'year',
'date',
'points',
'month_KP_points',
'month_TP_points',
'month_shop_points',
'status_points',
'status_turnover',
'total_net',
'month_total_net',
'month_shop_total_net',
'message',
'info',
'status',
'syslog'
];
protected $fillable = [
'user_id',
'shopping_order_id',
'user_invoice_id',
'month',
'year',
'date',
'points',
'month_KP_points',
'month_TP_points',
'month_shop_points',
'status_points',
'status_turnover',
'total_net',
'month_total_net',
'month_shop_total_net',
'message',
'info',
'status',
'syslog',
];
public static $statusPointsTypes = [
1 => 'KU + TP', // Eigene + Team
2 => 'KU', // nur Eigene nicht Team
];
public static $statusPointsTypes = [
1 => 'KU + TP', //Eigene + Team
2 => 'KU', //nur Eigene nicht Team
];
public static $statusTurnoverTypes = [
1 => 'advisor_order', // hinzugefügt aus
2 => 'shoporder', // hinzugefügt aus
];
public static $statusTurnoverTypes = [
1 => 'advisor_order', //hinzugefügt aus
2 => 'shoporder', //hinzugefügt aus
];
public static $statusTypes = [
0 => 'not_assigned',
1 => 'advisor_order', // hinzugefügt aus
2 => 'shoporder', // hinzugefügt aus
3 => 'shoporder_pending', // hinzugefügt aus
4 => 'credit', // hinzugefügt aus
5 => 'registration', // hinzugefügt aus
6 => 'cancelled', // Stornorechnung
// 10 => ''
];
public static $statusTypes = [
0 => 'not_assigned',
1 => 'advisor_order', //hinzugefügt aus
2 => 'shoporder', //hinzugefügt aus
3 => 'shoporder_pending', //hinzugefügt aus
4 => 'credit', //hinzugefügt aus
5 => 'registration', //hinzugefügt aus
// 10 => ''
];
public static $statusColors = [
0 => 'warning',
1 => 'success',
2 => 'secondary',
3 => 'warning',
4 => 'info',
5 => 'info',
6 => 'danger',
10 => 'danger',
];
public static $statusColors = [
0 => 'warning',
1 => 'success',
2 => 'secondary',
3 => 'warning',
4 => 'info',
5 => 'info',
10 => 'danger',
];
public function shopping_order()
{
return $this->belongsTo(ShoppingOrder::class);
}
public function shopping_order()
{
return $this->belongsTo(ShoppingOrder::class);
}
public function user()
{
return $this->belongsTo(User::class);
}
public function user()
{
return $this->belongsTo(User::class);
}
public function user_invoice()
{
return $this->belongsTo(UserInvoice::class);
}
public function user_invoice()
{
return $this->belongsTo(UserInvoice::class);
}
public function getDateAttribute()
{
return $this->attributes['date'] ? Carbon::parse($this->attributes['date'])->format(\Util::formatDateDB()) : '';
}
public function getDateAttribute()
{
return $this->attributes['date'] ? Carbon::parse($this->attributes['date'])->format(\Util::formatDateDB()) : '';
}
public function setDateAttribute($value)
{
$this->attributes['date'] = isset($value) ? (new Carbon($value))->format('Y-m-d') : NULL;
}
public function getDateRaw()
{
return isset($this->attributes['date']) ? $this->attributes['date'] : NULL;
}
public function setDateAttribute($value)
{
$this->attributes['date'] = isset($value) ? (new Carbon($value))->format('Y-m-d') : null;
}
// Points Setter/Getter für deutsches Zahlenformat
public function setPointsAttribute($value)
{
$this->attributes['points'] = $value !== null ? \Util::reFormatNumber($value) : null;
}
public function getDateRaw()
{
return isset($this->attributes['date']) ? $this->attributes['date'] : null;
}
public function setMonthKPPointsAttribute($value)
{
$this->attributes['month_KP_points'] = $value !== null ? \Util::reFormatNumber($value) : null;
}
// Points Setter/Getter für deutsches Zahlenformat
public function setPointsAttribute($value)
{
$this->attributes['points'] = $value !== null ? \Util::reFormatNumber($value) : null;
}
public function setMonthTPPointsAttribute($value)
{
$this->attributes['month_TP_points'] = $value !== null ? \Util::reFormatNumber($value) : null;
}
public function setMonthKPPointsAttribute($value)
{
$this->attributes['month_KP_points'] = $value !== null ? \Util::reFormatNumber($value) : null;
}
public function setMonthShopPointsAttribute($value)
{
$this->attributes['month_shop_points'] = $value !== null ? \Util::reFormatNumber($value) : null;
}
public function setMonthTPPointsAttribute($value)
{
$this->attributes['month_TP_points'] = $value !== null ? \Util::reFormatNumber($value) : null;
}
public function getFormattedPoints()
{
return isset($this->attributes['points']) ? \Util::formatNumber($this->attributes['points']) : "";
}
public function setMonthShopPointsAttribute($value)
{
$this->attributes['month_shop_points'] = $value !== null ? \Util::reFormatNumber($value) : null;
}
public function getFormattedMonthKPPoints()
{
return isset($this->attributes['month_KP_points']) ? \Util::formatNumber($this->attributes['month_KP_points']) : 0;
}
public function getFormattedPoints()
{
return isset($this->attributes['points']) ? \Util::formatNumber($this->attributes['points']) : '';
}
public function getFormattedMonthTPPoints()
{
return isset($this->attributes['month_TP_points']) ? \Util::formatNumber($this->attributes['month_TP_points']) : 0;
}
public function getFormattedMonthKPPoints()
{
return isset($this->attributes['month_KP_points']) ? \Util::formatNumber($this->attributes['month_KP_points']) : 0;
}
public function getFormattedMonthShopPoints()
{
return isset($this->attributes['month_shop_points']) ? \Util::formatNumber($this->attributes['month_shop_points']) : 0;
}
public function getFormattedMonthTPPoints()
{
return isset($this->attributes['month_TP_points']) ? \Util::formatNumber($this->attributes['month_TP_points']) : 0;
}
public function getPointsKPSum()
{
return $this->month_KP_points + $this->month_shop_points; //only KP für SUM - KP is for User
}
public function getPointsTPSum()
{
return $this->month_TP_points + $this->month_shop_points; //only TP für SUM - TP is only for Payline
}
public function getFormattedMonthShopPoints()
{
return isset($this->attributes['month_shop_points']) ? \Util::formatNumber($this->attributes['month_shop_points']) : 0;
}
public function getTotalNetSum()
{
return $this->month_total_net + $this->month_shop_total_net;
}
public function getPointsKPSum()
{
return $this->month_KP_points + $this->month_shop_points; // only KP für SUM - KP is for User
}
public function getStatusType()
{
return isset(self::$statusTypes[$this->status]) ? __('payment.' . self::$statusTypes[$this->status]) : "";
}
public function getPointsTPSum()
{
return $this->month_TP_points + $this->month_shop_points; // only TP für SUM - TP is only for Payline
}
public static function getTransStatusType()
{
$ret = [];
foreach (self::$statusTypes as $key => $val) {
$ret[$key] = trans('payment.' . $val);
}
return $ret;
}
public function getTotalNetSum()
{
return $this->month_total_net + $this->month_shop_total_net;
}
public static function getTransTurnoverTypes()
{
$ret = [];
foreach (self::$statusTurnoverTypes as $key => $val) {
$ret[$key] = trans('payment.' . $val);
}
return $ret;
}
public function getStatusType()
{
return isset(self::$statusTypes[$this->status]) ? __('payment.'.self::$statusTypes[$this->status]) : '';
}
public function getStatusColor()
{
return isset(self::$statusColors[$this->status]) ? self::$statusColors[$this->status] : "default";
}
public static function getTransStatusType()
{
$ret = [];
foreach (self::$statusTypes as $key => $val) {
$ret[$key] = trans('payment.'.$val);
}
public function getStatusPointsType()
{
return isset(self::$statusPointsTypes[$this->status_points]) ? self::$statusPointsTypes[$this->status_points] : "";
}
public function getStatusPointsColor()
{
return isset(self::$statusColors[$this->status_points]) ? self::$statusColors[$this->status_points] : "default";
}
return $ret;
}
public function getStatusTurnoverType()
{
switch ($this->status) {
case 1: //Bestellung Berater
return 'E';
case 2: //Shop
return 'S';
case 4: //Gutschrift
if ($this->status_turnover === 2) {
return 'S';
} else {
return 'E';
}
case 5: //Registrierung
return 'E';
}
return "";
}
public function getStatusTurnoverColor()
{
public static function getTransTurnoverTypes()
{
$ret = [];
foreach (self::$statusTurnoverTypes as $key => $val) {
$ret[$key] = trans('payment.'.$val);
}
return $ret;
}
switch ($this->status) {
case 1: //Bestellung Berater
return 'success';
case 2: //Shop
return 'secondary';
case 4: //Gutschrift
if ($this->status_turnover === 2) {
return 'secondary';
} else {
return 'success';
}
case 5: //Registrierung
return 'success';
}
return "default";
}
public function getStatusColor()
{
return isset(self::$statusColors[$this->status]) ? self::$statusColors[$this->status] : 'default';
}
public function getFormatedMonthYear()
{
return str_pad($this->month, 2, "0", STR_PAD_LEFT) . "/" . $this->year;
}
public function getStatusPointsType()
{
return isset(self::$statusPointsTypes[$this->status_points]) ? self::$statusPointsTypes[$this->status_points] : '';
}
public function isCurrentMonthYear()
{
if ($this->month === intval(date('m')) && $this->year === intval(date('Y'))) {
return true;
}
return false;
}
public function getStatusPointsColor()
{
return isset(self::$statusColors[$this->status_points]) ? self::$statusColors[$this->status_points] : 'default';
}
public function caluCommissonTotalNet($margin)
{
if ($this->total_net > 0 && $margin > 0) {
return $this->total_net / 100 * $margin;
}
return 0;
}
public function getStatusTurnoverType()
{
switch ($this->status) {
case 1: // Bestellung Berater
return 'E';
case 2: // Shop
return 'S';
case 4: // Gutschrift
if ($this->status_turnover === 2) {
return 'S';
} else {
return 'E';
}
case 5: // Registrierung
return 'E';
}
return '';
}
public function getStatusTurnoverColor()
{
switch ($this->status) {
case 1: // Bestellung Berater
return 'success';
case 2: // Shop
return 'secondary';
case 4: // Gutschrift
if ($this->status_turnover === 2) {
return 'secondary';
} else {
return 'success';
}
case 5: // Registrierung
return 'success';
}
return 'default';
}
public function getFormatedMonthYear()
{
return str_pad($this->month, 2, '0', STR_PAD_LEFT).'/'.$this->year;
}
public function isCurrentMonthYear()
{
if ($this->month === intval(date('m')) && $this->year === intval(date('Y'))) {
return true;
}
return false;
}
public function caluCommissonTotalNet($margin)
{
if ($this->total_net > 0 && $margin > 0) {
return $this->total_net / 100 * $margin;
}
return 0;
}
}