Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
61.54% covered (warning)
61.54%
8 / 13
54.55% covered (warning)
54.55%
6 / 11
CRAP
0.00% covered (danger)
0.00%
0 / 1
Vendor
61.54% covered (warning)
61.54%
8 / 13
54.55% covered (warning)
54.55%
6 / 11
17.88
0.00% covered (danger)
0.00%
0 / 1
 user
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 products
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 commissions
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 payouts
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 applications
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 scopeActive
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 scopePending
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 scopeKycApproved
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 totalEarnings
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 pendingEarnings
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 totalSales
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3namespace App\Models;
4
5use Illuminate\Database\Eloquent\Factories\HasFactory;
6use Illuminate\Database\Eloquent\Model;
7use Illuminate\Database\Eloquent\SoftDeletes;
8use Illuminate\Support\Facades\DB;
9
10/**
11 * Marketplace vendor. Activated by the `multi_vendor` feature flag.
12 * When the flag is OFF every product/order belongs to the platform owner
13 * (vendor_id = NULL everywhere).
14 */
15class Vendor extends Model
16{
17    use HasFactory, SoftDeletes;
18
19    protected $fillable = [
20        'name', 'slug', 'email', 'phone', 'status',
21        'commission_pct', 'user_id', 'address', 'logo',
22        // KYC & bank (Phase 12)
23        'bank_name', 'account_name', 'account_number', 'routing_number',
24        'mobile_banking', 'mobile_banking_type',
25        'nid_number', 'kyc_status', 'kyc_note',
26        'bio', 'store_name', 'store_banner', 'approved_at',
27    ];
28
29    protected $casts = [
30        'commission_pct' => 'decimal:2',
31        'approved_at'    => 'datetime',
32    ];
33
34    /* ─── Relationships ─── */
35
36    public function user()
37    {
38        return $this->belongsTo(User::class);
39    }
40
41    public function products()
42    {
43        return $this->hasMany(\App\Models\admin\Product::class, 'vendor_id');
44    }
45
46    public function commissions()
47    {
48        return $this->hasMany(Commission::class);
49    }
50
51    public function payouts()
52    {
53        return $this->hasMany(Payout::class);
54    }
55
56    public function applications()
57    {
58        return $this->hasMany(VendorApplication::class);
59    }
60
61    /* ─── Scopes ─── */
62
63    public function scopeActive($q)
64    {
65        return $q->where('status', 'active');
66    }
67
68    public function scopePending($q)
69    {
70        return $q->where('status', 'pending');
71    }
72
73    public function scopeKycApproved($q)
74    {
75        return $q->where('kyc_status', 'approved');
76    }
77
78    /* ─── Helpers ─── */
79
80    /**
81     * The vendor's net take = gross sale − the platform's commission cut.
82     * (commission_amount is what the PLATFORM keeps, not the vendor — see
83     * PayoutService::createPayout, where net_amount = gross − commission.)
84     * Query builder's sum() returns 0 (not null) when there are no rows.
85     */
86    public function totalEarnings(): float
87    {
88        return (float) $this->commissions()->where('status', 'paid')
89            ->sum(DB::raw('sale_amount - commission_amount'));
90    }
91
92    /** Vendor's net earnings pending payout. */
93    public function pendingEarnings(): float
94    {
95        return (float) $this->commissions()->where('status', 'pending')
96            ->sum(DB::raw('sale_amount - commission_amount'));
97    }
98
99    /** Gross sales value across all commissions. */
100    public function totalSales(): float
101    {
102        return (float) $this->commissions()->sum('sale_amount');
103    }
104}