has('date_from') ? strip_tags($request->get('date_from')) : $request->session()->get('pay_date_from', ''); $dateTo = $request->has('date_to') ? strip_tags($request->get('date_to')) : $request->session()->get('pay_date_to', ''); if ($request->has('date_from')) $request->session()->put('pay_date_from', $dateFrom); if ($request->has('date_to')) $request->session()->put('pay_date_to', $dateTo); $contracts = FinishedContracts::with(['suppliers.user', 'suppliers.banks']) ->whereIn('status_id', [3, 9]) ->where('paid', false) ->where('transaction_id', '!=', 'NO APPLY') ->when($dateFrom, fn($q) => $q->whereDate('appointment', '>=', $dateFrom)) ->when($dateTo, fn($q) => $q->whereDate('appointment', '<=', $dateTo)) ->get(); $field = in_array($request->input('field'), ['company_name', 'email', 'rfc_curp', 'clabe', 'bank', 'contract_count', 'total_amount', 'total_revenue', 'total_iva', 'total_isr', 'total_fee']) ? $request->input('field') : 'total_amount'; $sort = $request->input('sort', 'desc') === 'asc' ? 'asc' : 'desc'; $grouped = $contracts->groupBy('supplier_id')->map(function ($group) { $first = $group->first(); return (object) [ 'suppliers' => $first->suppliers, 'contract_count' => $group->count(), 'total_amount' => $group->sum('amount'), 'total_revenue' => $group->sum('revenue'), 'total_iva' => $group->sum('IVA'), 'total_isr' => $group->sum('ISR'), 'total_fee' => $group->sum('ichamba_fee'), ]; })->values(); $sortCallbacks = [ 'company_name' => fn($r) => optional($r->suppliers)->company_name, 'email' => fn($r) => optional(optional($r->suppliers)->user)->email, 'rfc_curp' => fn($r) => optional($r->suppliers)->RFC ?: optional($r->suppliers)->CURP, 'clabe' => fn($r) => optional($r->suppliers)->clabe, 'bank' => fn($r) => optional(optional($r->suppliers)->banks)->name, 'contract_count' => fn($r) => $r->contract_count, 'total_amount' => fn($r) => $r->total_amount, 'total_revenue' => fn($r) => $r->total_revenue, 'total_iva' => fn($r) => $r->total_iva, 'total_isr' => fn($r) => $r->total_isr, 'total_fee' => fn($r) => $r->total_fee, ]; $grouped = $sort === 'asc' ? $grouped->sortBy($sortCallbacks[$field])->values() : $grouped->sortByDesc($sortCallbacks[$field])->values(); $perPage = 15; $page = $request->input('page', 1); $payments = new LengthAwarePaginator( $grouped->slice(($page - 1) * $perPage, $perPage)->values(), $grouped->count(), $perPage, $page, ['path' => $request->url(), 'query' => $request->query()] ); if ($request->ajax()) { return view('payments.index', compact('payments', 'dateFrom', 'dateTo')); } else { return view('payments.ajax', compact('payments', 'dateFrom', 'dateTo')); } } public function intent(Request $request) { $validator = Validator::make($request->all(), [ 'supplier_id' => 'required|numeric', ]); if ($validator->fails()) { return response()->json($validator->errors(), 422); } $user = Auth::user(); $supplier = Suppliers::find($request->supplier_id); if (!$supplier) { return response()->json(['message' => 'Proveedor no encontrado'], 404); } Stripe::setApiKey(env('STRIPE_SECRET')); if (!$user->stripe_customer_id) { $customer = Customer::create([ 'email' => $user->email, 'name' => $user->name, ]); $user->stripe_customer_id = $customer->id; $user->save(); } $amount = max((int) $supplier->minimun_fee, 150); try { $ephemeralKey = \Stripe\EphemeralKey::create( ['customer' => $user->stripe_customer_id], ['stripe_version' => \Stripe\Stripe::$apiVersion] ); $intent = \Stripe\PaymentIntent::create([ 'amount' => $amount * 100, 'currency' => env('STRIPE_CURRENCY', 'mxn'), 'customer' => $user->stripe_customer_id, 'automatic_payment_methods' => ['enabled' => true], ]); } catch (\Exception $e) { return response()->json(['message' => $e->getMessage()], 422); } return response()->json([ 'payment_intent_id' => $intent->id, 'client_secret' => $intent->client_secret, 'customer' => $user->stripe_customer_id, 'ephemeral_key' => $ephemeralKey->secret, ]); } public function getcards(Request $request) { $user = Auth::user(); $cards = Cards::where('user_id', $user->id)->get()->map(fn($c) => [ 'id' => $c->id, 'payment_method_id' => $c->stripe_pm_id, 'brand' => $c->brand, 'last4' => $c->last4, 'exp_month' => $c->exp_month, 'exp_year' => $c->exp_year, ]); return response()->json($cards); } public function generate(Request $request) { $dateFrom = $request->input('date_from', ''); $dateTo = $request->input('date_to', ''); $contracts = FinishedContracts::with(['suppliers.user', 'suppliers.banks']) ->whereIn('status_id', [3, 9]) ->where('paid', false) ->where('transaction_id', '!=', 'NO APPLY') ->when($dateFrom, fn($q) => $q->whereDate('appointment', '>=', $dateFrom)) ->when($dateTo, fn($q) => $q->whereDate('appointment', '<=', $dateTo)) ->get(); if ($contracts->isEmpty()) { return redirect('payments')->with('warning', 'No hay contratos pendientes de pago con los filtros seleccionados.'); } $contractIds = $contracts->pluck('id'); $grouped = $contracts->groupBy('supplier_id')->map(function ($group) { $first = $group->first(); return [ 'suppliers' => $first->suppliers, 'contract_count' => $group->count(), 'total_amount' => $group->sum('amount'), 'total_revenue' => $group->sum('revenue'), 'total_iva' => $group->sum('IVA'), 'total_isr' => $group->sum('ISR'), 'total_fee' => $group->sum('ichamba_fee'), ]; })->values(); // Generar Excel $spreadsheet = new Spreadsheet(); $sheet = $spreadsheet->getActiveSheet(); $sheet->setTitle('Pagos'); $headers = ['Proveedor', 'Email', 'RFC / CURP', 'CLABE', 'Banco', 'Contratos', 'Monto Total', 'Utilidad', 'Ret. IVA', 'Ret. ISR', 'Ret. JobHero']; foreach ($headers as $i => $header) { $sheet->setCellValueByColumnAndRow($i + 1, 1, $header); } foreach ($grouped as $idx => $data) { $row = $idx + 2; $supplier = $data['suppliers']; $sheet->setCellValueByColumnAndRow(1, $row, optional($supplier)->company_name ?? ''); $sheet->setCellValueByColumnAndRow(2, $row, optional(optional($supplier)->user)->email ?? ''); $sheet->setCellValueByColumnAndRow(3, $row, optional($supplier)->RFC ?: (optional($supplier)->CURP ?? '')); $sheet->setCellValueByColumnAndRow(4, $row, optional($supplier)->clabe ?? ''); $sheet->setCellValueByColumnAndRow(5, $row, optional(optional($supplier)->banks)->name ?? ''); $sheet->setCellValueByColumnAndRow(6, $row, $data['contract_count']); $sheet->setCellValueByColumnAndRow(7, $row, $data['total_amount']); $sheet->setCellValueByColumnAndRow(8, $row, $data['total_revenue']); $sheet->setCellValueByColumnAndRow(9, $row, $data['total_iva']); $sheet->setCellValueByColumnAndRow(10, $row, $data['total_isr']); $sheet->setCellValueByColumnAndRow(11, $row, $data['total_fee']); } $now = now(); $fileName = 'pagos_' . $now->format('Y-m-d_H-i-s') . '.xlsx'; $relativePath = 'payment-batches/' . $fileName; $absolutePath = storage_path('app/' . $relativePath); if (!is_dir(storage_path('app/payment-batches'))) { mkdir(storage_path('app/payment-batches'), 0755, true); } $writer = new Xlsx($spreadsheet); $writer->save($absolutePath); PaymentBatch::create([ 'file_name' => $fileName, 'file_path' => $relativePath, 'generated_by' => Auth::id(), 'date_from' => $dateFrom ?: null, 'date_to' => $dateTo ?: null, ]); FinishedContracts::whereIn('id', $contractIds)->update([ 'paid' => true, 'paid_at' => $now, ]); return response()->download($absolutePath, $fileName); } }