feat: branch betos — propiedades, oferta de proveedores, chat en contratos y flujo de postulacion renovado

- Sistema de propiedades: tabla, modelo, CRUD API para que el cliente guarde direcciones nombradas
- Postulacion renovada: cliente elige propiedad sin precio ni fecha, sube fotos a GCS/S3
- Proveedores ofertan date_1, date_2 y amount al postularse via pivot; sort por fecha/monto/membresia
- Contratacion: selected_date recibe date_1 o date_2, amount desde pivot (depreca minimun_fee)
- Cancelacion/repostulacion: archive con status=perdido, related_postulation_id para vincular
- Chat en contratos activos: tabla contract_comments, controller, rutas web+API, vista panel, notificaciones bilingues
- PaymentIntent calcula amount desde pivot en vez de recibirlo del front
- getpendingcontracts: sin filtro de tiempo, filtra por status=active, agrega time_created
- Expiracion de postulaciones reducida a 1000 min

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-07-03 11:26:10 -06:00
parent 0ed98c96ee
commit 700ddafba4
21 changed files with 944 additions and 180 deletions

View File

@@ -165,6 +165,7 @@ class ContractController extends Controller
$rules = [
'postulation_id' => 'required|numeric',
'supplier_id' => 'required|numeric',
'selected_date' => 'required|in:date_1,date_2',
'payment_intent_id' => $paymentBypass ? 'nullable|string' : 'required|string',
'coupon' => 'nullable|string',
];
@@ -192,6 +193,14 @@ class ContractController extends Controller
$ichambafee = iChambaParameter::where('parameter', 'ichamba_fee')->first();
$category = Categories::where('id', $postulation->category_id)->first();
// Tomar amount del pivot (oferta del proveedor elegido por el cliente)
$pivotSupplier = $postulation->suppliers()
->where('suppliers.id', $request->supplier_id)
->first();
$minFee = 150;
$pivotAmount = $pivotSupplier ? ($pivotSupplier->pivot->amount ?? $minFee) : $minFee;
$finalAmount = max($pivotAmount, $minFee);
if (true) { // autorización verificada arriba con user_id == postulation->user_id
$contract = new CurrentContracts();
@@ -206,16 +215,17 @@ class ContractController extends Controller
$contract->int_number = 0;
}
$contract->references = $postulation->references;
$contract->appointment = $postulation->appointment;
$contract->amount = ($supplier->minimun_fee < 150 ? 150 : $supplier->minimun_fee);
$selectedDate = $request->selected_date;
$contract->appointment = Carbon::parse($pivotSupplier->pivot->$selectedDate);
$contract->amount = $finalAmount;
if (isset($IVA->num_value) && isset($IVA->num_value)) {
$contract->IVA = $IVA->num_value;
$contract->ISR = $ISR->num_value;
$contract->revenue = ((($supplier->minimun_fee < 150 ? 150 : $supplier->minimun_fee) * ((100 - $ichambafee->num_value) / 100)) * ((100 - $IVA->num_value - $ISR->num_value) / 100));
$contract->revenue = (($finalAmount * ((100 - $ichambafee->num_value) / 100)) * ((100 - $IVA->num_value - $ISR->num_value) / 100));
} else {
$contract->IVA = 0;
$contract->ISR = 0;
$contract->revenue = (($supplier->minimun_fee < 150 ? 150 : $supplier->minimun_fee) * ((100 - $ichambafee->num_value) / 100));
$contract->revenue = ($finalAmount * ((100 - $ichambafee->num_value) / 100));
}
$contract->ichamba_fee = $ichambafee->num_value;
$contract->details = $postulation->details;
@@ -229,40 +239,18 @@ class ContractController extends Controller
if ($coupon->limit > 0) {
if(!isset($checkccontracts) && !isset($checkccontracts)) {
$fee = ($supplier->minimun_fee < 150 ? 150 : $supplier->minimun_fee);
$fee = $finalAmount;
$discount = (($fee*(($coupon->percentage = null ? 0 : $coupon->percentage)/100))+($coupon->amount = null ? 0 : $coupon->amount));
$contract->coupon_id = $coupon->id;
// Solo crear chargeData si no estamos en bypass mode
if (!$paymentBypass && $card) {
$chargeData = array(
'source_id' => $card->token,
'method' => 'card',
'amount' => ((($supplier->minimun_fee < 150 ? 150 : $supplier->minimun_fee)*(1 - (($coupon->percentage = null ? 0 : $coupon->percentage)/100)))-($coupon->amount = null ? 0 : $coupon->amount)),
'description' => ('Contrato del usuario: ' . $user->name . ' del servicio ' . $category->name . ' realizado por el proveedor: ' . $supplier->company_name),
'device_session_id' => $request->device_id,
'cvv2' => $request->code
);
}
}
}
} else {
$fee = ($supplier->minimun_fee < 150 ? 150 : $supplier->minimun_fee);
$fee = $finalAmount;
$discount = 0;
$contract->coupon_id = null;
// Solo crear chargeData si no estamos en bypass mode
if (!$paymentBypass && $card) {
$chargeData = array(
'source_id' => $card->token,
'method' => 'card',
'amount' => ($supplier->minimun_fee < 150 ? 150 : $supplier->minimun_fee),
'description' => ('Contrato del usuario: ' . $user->name . ' del servicio ' . $category->name . ' realizado por el proveedor: ' . $supplier->company_name),
'device_session_id' => $request->device_id,
'cvv2' => $request->code
);
}
}
@@ -344,8 +332,9 @@ class ContractController extends Controller
$rules = [
'postulation_id' => 'required|numeric',
'supplier_id' => 'required|numeric',
'coupon' => 'required|string|regex:/(^[A-Za-z0-9 ]+$)+/',
'supplier_id' => 'required|numeric',
'selected_date' => 'required|in:date_1,date_2',
'coupon' => 'required|string|regex:/(^[A-Za-z0-9 ]+$)+/',
];
$validator = Validator::make($request->all(), $rules);
@@ -387,16 +376,23 @@ class ContractController extends Controller
$contract->int_number = 0;
}
$contract->references = $postulation->references;
$contract->appointment = $postulation->appointment;
$contract->amount = ($supplier->minimun_fee < 150 ? 150 : $supplier->minimun_fee);
$pivotForCoupon = $postulation->suppliers()->where('suppliers.id', $request->supplier_id)->first();
$couponDate = $request->selected_date;
$contract->appointment = $pivotForCoupon
? Carbon::parse($pivotForCoupon->pivot->$couponDate)
: Carbon::now();
$minFeeC = 150;
$pivotAmountC = $pivotForCoupon ? ($pivotForCoupon->pivot->amount ?? $minFeeC) : $minFeeC;
$finalAmountC = max($pivotAmountC, $minFeeC);
$contract->amount = $finalAmountC;
if (isset($IVA->num_value) && isset($IVA->num_value)) {
$contract->IVA = $IVA->num_value;
$contract->ISR = $ISR->num_value;
$contract->revenue = ((($supplier->minimun_fee < 150 ? 150 : $supplier->minimun_fee) * ((100 - $ichambafee->num_value) / 100)) * ((100 - $IVA->num_value - $ISR->num_value) / 100));
$contract->revenue = (($finalAmountC * ((100 - $ichambafee->num_value) / 100)) * ((100 - $IVA->num_value - $ISR->num_value) / 100));
} else {
$contract->IVA = 0;
$contract->ISR = 0;
$contract->revenue = (($supplier->minimun_fee < 150 ? 150 : $supplier->minimun_fee) * ((100 - $ichambafee->num_value) / 100));
$contract->revenue = ($finalAmountC * ((100 - $ichambafee->num_value) / 100));
}
$contract->ichamba_fee = $ichambafee->num_value;
$contract->details = $postulation->details;