- Created ExampleTest and RoutesTest for basic application response and route testing. - Implemented IsolatedDatabaseTestCase for isolated database testing. - Added unit tests for various models and services including Contract, CPE, and LeadDetail. - Developed request validation tests for CreateClientRequest, UpdateClientRequest, and ContractRequest. - Introduced Vite configuration for asset management in the Laravel application.
225 lines
6.0 KiB
PHP
225 lines
6.0 KiB
PHP
<?php
|
|
|
|
namespace App\Models;
|
|
|
|
use Carbon\Carbon;
|
|
use Illuminate\Database\Eloquent\Model;
|
|
use Illuminate\Database\Eloquent\Casts\Attribute;
|
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
|
|
|
class Contract extends Model
|
|
{
|
|
protected $fillable = [
|
|
'client_id',
|
|
'paid',
|
|
'chargeback',
|
|
'chargeback_value',
|
|
'chargeback_date',
|
|
'contract_value',
|
|
'commission_value',
|
|
'profit_value',
|
|
'seller_id',
|
|
'supply_type',
|
|
'supply_address',
|
|
'annual_consumption',
|
|
'code',
|
|
'contract_type_id',
|
|
'status_id',
|
|
'commission_rate',
|
|
'notes',
|
|
'power_tier_id',
|
|
'payment_method_id',
|
|
'delivery_method',
|
|
'delivery_email',
|
|
'previous_supplier_id',
|
|
'new_supplier_id',
|
|
'typology_id',
|
|
'cui_tier_id',
|
|
'activation_date',
|
|
'contract_date',
|
|
'validity',
|
|
'contract_end_date',
|
|
'go_ki'
|
|
];
|
|
|
|
public function histories()
|
|
{
|
|
return $this->hasMany(ContractHistory::class)->orderBy('created_at', 'desc');
|
|
}
|
|
|
|
public function client(): BelongsTo
|
|
{
|
|
return $this->belongsTo(Clients::class);
|
|
}
|
|
|
|
public function contractType(): BelongsTo
|
|
{
|
|
return $this->belongsTo(ContractType::class);
|
|
}
|
|
|
|
public function status(): BelongsTo
|
|
{
|
|
return $this->belongsTo(ContractStatus::class);
|
|
}
|
|
|
|
public function payments(): HasMany
|
|
{
|
|
return $this->hasMany(Payment::class);
|
|
}
|
|
|
|
public function powerTier(): BelongsTo
|
|
{
|
|
return $this->belongsTo(PowerTier::class);
|
|
}
|
|
|
|
public function cuiTier(): BelongsTo
|
|
{
|
|
return $this->belongsTo(CuiTier::class);
|
|
}
|
|
|
|
public function paymentMethod(): BelongsTo
|
|
{
|
|
return $this->belongsTo(PaymentMethod::class);
|
|
}
|
|
|
|
public function previousSupplier(): BelongsTo
|
|
{
|
|
return $this->belongsTo(Supplier::class, 'previous_supplier_id');
|
|
}
|
|
|
|
public function newSupplier(): BelongsTo
|
|
{
|
|
return $this->belongsTo(Supplier::class, 'new_supplier_id');
|
|
}
|
|
|
|
public function typology()
|
|
{
|
|
return $this->belongsTo(Typology::class);
|
|
}
|
|
|
|
public function installments()
|
|
{
|
|
return $this->hasMany(ContractInstallment::class);
|
|
}
|
|
|
|
// Gerar parcelas automaticamente
|
|
public function createInstallments()
|
|
{
|
|
$amount = $this->contract_value / $this->installment_count;
|
|
for ($i = 1; $i <= $this->installment_count; $i++) {
|
|
$this->installments()->create([
|
|
'installment_number' => $i,
|
|
'amount' => $amount,
|
|
'due_date' => now()->addMonths($i - 1),
|
|
]);
|
|
}
|
|
}
|
|
|
|
|
|
// Scopes
|
|
public function scopeCpe($query)
|
|
{
|
|
return $query->where('type', 'cpe');
|
|
}
|
|
|
|
public function scopeCpi($query)
|
|
{
|
|
return $query->where('type', 'cpi');
|
|
}
|
|
|
|
public function seller()
|
|
{
|
|
return $this->belongsTo(User::class, 'seller_id');
|
|
}
|
|
|
|
public function scopeBetweenDates($query, $from, $to)
|
|
{
|
|
return $query->when($from, fn($q) => $q->where('contract_date', '>=', $from))
|
|
->when($to, fn($q) => $q->where('contract_date', '<=', $to));
|
|
}
|
|
|
|
public static function getMonthlyGrowth($from = null, $to = null)
|
|
{
|
|
$driver = \Illuminate\Support\Facades\DB::getDriverName();
|
|
$monthExpression = $driver === 'sqlite'
|
|
? "strftime('%Y-%m', contract_date)"
|
|
: "DATE_FORMAT(contract_date, '%Y-%m')";
|
|
|
|
return self::query()
|
|
->betweenDates($from, $to)
|
|
->selectRaw($monthExpression . ' as mes, SUM(contract_value) as total')
|
|
->groupByRaw($monthExpression)
|
|
->orderByRaw($monthExpression)
|
|
->get();
|
|
}
|
|
|
|
// Mutators & Accessors
|
|
protected function activationDate(): Attribute
|
|
{
|
|
return Attribute::make(
|
|
// Getter: returns a Carbon instance or null
|
|
get: fn ($value) => $value ? Carbon::parse($value) : null,
|
|
|
|
// Setter: accepts 'd/m/Y' from form, converts to 'Y-m-d' for DB
|
|
set: fn ($value) => $this->convertDateToDbFormat($value)
|
|
);
|
|
}
|
|
|
|
protected function contractDate(): Attribute
|
|
{
|
|
return Attribute::make(
|
|
// Getter: returns a Carbon instance or null
|
|
get: fn ($value) => $value ? Carbon::parse($value) : null,
|
|
|
|
// Setter: accepts 'd/m/Y' from form, converts to 'Y-m-d' for DB
|
|
set: fn ($value) => $this->convertDateToDbFormat($value)
|
|
);
|
|
}
|
|
|
|
protected function validity(): Attribute
|
|
{
|
|
return Attribute::make(
|
|
// Getter: returns a Carbon instance or null
|
|
get: fn ($value) => $value ? Carbon::parse($value) : null,
|
|
|
|
// Setter: accepts 'd/m/Y' from form, converts to 'Y-m-d' for DB
|
|
set: fn ($value) => $this->convertDateToDbFormat($value)
|
|
);
|
|
}
|
|
|
|
protected function contractEndDate(): Attribute
|
|
{
|
|
return Attribute::make(
|
|
get: fn ($value) => $value ? Carbon::parse($value) : null,
|
|
set: fn ($value) => $this->convertDateToDbFormat($value)
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Converts a date string from 'd/m/Y' or other formats to 'Y-m-d' for DB storage.
|
|
*
|
|
* @param string|null $value
|
|
* @return string|null
|
|
*/
|
|
private function convertDateToDbFormat($value)
|
|
{
|
|
$value = trim($value);
|
|
if (!$value) return null;
|
|
|
|
try {
|
|
// Try parsing d/m/Y format
|
|
return Carbon::createFromFormat('d/m/Y', $value)->format('Y-m-d');
|
|
} catch (\Exception $e) {
|
|
try {
|
|
// Fallback: parse standard date formats (e.g., Y-m-d)
|
|
return Carbon::parse($value)->format('Y-m-d');
|
|
} catch (\Exception $e) {
|
|
// If parsing fails, store null
|
|
return null;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|