Files
voltcerto/app/Models/Contract.php
Luis Medon e488ae3342 Add feature tests, unit tests, and configuration for Laravel application
- 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.
2026-10-29 11:30:06 +00:00

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;
}
}
}
}