From 28118ce732132fb95a3a9ec35bde98e025642e64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Consultor=C3=ADa=20Alcaraz=20Salazar?= Date: Sat, 10 Oct 2026 10:27:42 +0000 Subject: [PATCH] fix: pago.py va en models/ (copia anterior quedo en ruta plana) --- odoo-addons/skeen_pagos/models/pago.py | 5 +- odoo-addons/skeen_pagos/pago.py | 201 ------------------------- 2 files changed, 4 insertions(+), 202 deletions(-) delete mode 100644 odoo-addons/skeen_pagos/pago.py diff --git a/odoo-addons/skeen_pagos/models/pago.py b/odoo-addons/skeen_pagos/models/pago.py index d400f25..1988f15 100644 --- a/odoo-addons/skeen_pagos/models/pago.py +++ b/odoo-addons/skeen_pagos/models/pago.py @@ -30,6 +30,7 @@ class SkeenPago(models.Model): ('card', 'Tarjeta'), ('transfer', 'Transferencia'), ('saldo_favor', 'Saldo a favor'), + ('points', 'Monedero'), ], string='Método de Pago', required=True) # Estado @@ -164,7 +165,9 @@ class SkeenPago(models.Model): 'amount_paid': self.amount, }) - # Acumular puntos en monedero + # Acumular puntos en monedero (excepto si el pago es canje de monedero) + if self.payment_method == 'points': + return True monedero = self.env['skeen.monedero'].search([('partner_id', '=', self.partner_id.id)], limit=1) if not monedero: monedero = self.env['skeen.monedero'].create({ diff --git a/odoo-addons/skeen_pagos/pago.py b/odoo-addons/skeen_pagos/pago.py deleted file mode 100644 index 1988f15..0000000 --- a/odoo-addons/skeen_pagos/pago.py +++ /dev/null @@ -1,201 +0,0 @@ -# -*- coding: utf-8 -*- - -from odoo import models, fields, api, _ -from odoo.exceptions import ValidationError -import requests -import json - - -class SkeenPago(models.Model): - _name = 'skeen.pago' - _description = 'Pago de Servicio' - _order = 'create_date desc' - - # Referencia - name = fields.Char(string='Referencia', readonly=True, copy=False) - - # Paciente y Cita - partner_id = fields.Many2one('res.partner', string='Paciente', required=True) - cita_id = fields.Many2one('skeen.cita', string='Cita') - - # Monto - amount = fields.Float(string='Monto', required=True) - currency_id = fields.Many2one('res.currency', string='Moneda', default=lambda self: self.env.ref('base.MXN')) - - # Método de pago - payment_method = fields.Selection([ - ('stripe', 'Stripe'), - ('mercadopago', 'MercadoPago'), - ('cash', 'Efectivo'), - ('card', 'Tarjeta'), - ('transfer', 'Transferencia'), - ('saldo_favor', 'Saldo a favor'), - ('points', 'Monedero'), - ], string='Método de Pago', required=True) - - # Estado - state = fields.Selection([ - ('pending', 'Pendiente'), - ('processing', 'Procesando'), - ('completed', 'Completado'), - ('failed', 'Fallido'), - ('refunded', 'Reembolsado'), - ], string='Estado', default='pending') - - # Datos del proveedor de pago - provider_reference = fields.Char(string='Referencia Proveedor') - provider_response = fields.Text(string='Respuesta Proveedor') - - # URLs - payment_url = fields.Char(string='URL de Pago') - success_url = fields.Char(string='URL de Éxito') - cancel_url = fields.Char(string='URL de Cancelación') - - # Fechas - create_date = fields.Datetime(string='Fecha Creación', readonly=True, default=fields.Datetime.now) - payment_date = fields.Datetime(string='Fecha de Pago') - - @api.model_create_multi - def create(self, vals_list): - for vals in vals_list: - if not vals.get('name'): - vals['name'] = self.env['ir.sequence'].next_by_code('skeen.pago') or 'PAGO-001' - return super(SkeenPago, self).create(vals_list) - - def action_generate_stripe_link(self): - """Generar link de pago Stripe""" - self.ensure_one() - stripe_key = self.env['ir.config_parameter'].sudo().get_param('skeen.stripe_secret_key') - if not stripe_key: - raise ValidationError(_('Stripe no está configurado!')) - - # Crear sesión de checkout - headers = { - 'Authorization': f'Bearer {stripe_key}', - 'Content-Type': 'application/x-www-form-urlencoded', - } - data = { - 'payment_method_types[]': 'card', - 'line_items[0][price_data][currency]': 'mxn', - 'line_items[0][price_data][product_data][name]': f'Servicio SKEEN - {self.cita_id.servicio_id.name}', - 'line_items[0][price_data][unit_amount]': int(self.amount * 100), - 'line_items[0][quantity]': 1, - 'mode': 'payment', - 'success_url': f'https://app.skeen.mx/pagos/exitoso?ref={self.name}', - 'cancel_url': f'https://app.skeen.mx/pagos/cancelado?ref={self.name}', - 'metadata[payment_id]': str(self.id), - 'metadata[patient_phone]': self.partner_id.phone or '', - } - - response = requests.post('https://api.stripe.com/v1/checkout/sessions', headers=headers, data=data) - if response.status_code == 200: - session = response.json() - self.write({ - 'payment_url': session['url'], - 'provider_reference': session['id'], - 'provider_response': json.dumps(session), - 'state': 'processing', - }) - else: - self.write({ - 'provider_response': response.text, - 'state': 'failed', - }) - - return True - - def action_generate_mercadopago_link(self): - """Generar link de pago MercadoPago""" - self.ensure_one() - mp_token = self.env['ir.config_parameter'].sudo().get_param('skeen.mercadopago_access_token') - if not mp_token: - raise ValidationError(_('MercadoPago no está configurado!')) - - headers = { - 'Authorization': f'Bearer {mp_token}', - 'Content-Type': 'application/json', - } - data = { - 'items': [{ - 'title': f'Servicio SKEEN - {self.cita_id.servicio_id.name}', - 'quantity': 1, - 'unit_price': int(self.amount), - }], - 'back_urls': { - 'success': f'https://app.skeen.mx/pagos/exitoso?ref={self.name}', - 'failure': f'https://app.skeen.mx/pagos/fallido?ref={self.name}', - 'pending': f'https://app.skeen.mx/pagos/pendiente?ref={self.name}', - }, - 'notification_url': 'https://skeen.mx/webhooks/mercadopago', - 'metadata': { - 'payment_id': str(self.id), - 'patient_phone': self.partner_id.phone or '', - }, - } - - response = requests.post('https://api.mercadopago.com/checkout/preferences', headers=headers, json=data) - if response.status_code == 201: - preference = response.json() - self.write({ - 'payment_url': preference['init_point'], - 'provider_reference': preference['id'], - 'provider_response': json.dumps(preference), - 'state': 'processing', - }) - else: - self.write({ - 'provider_response': response.text, - 'state': 'failed', - }) - - return True - - def action_confirm_payment(self): - """Confirmar pago recibido""" - self.ensure_one() - self.write({ - 'state': 'completed', - 'payment_date': fields.Datetime.now(), - }) - - # Actualizar estado de pago de la cita - if self.cita_id: - self.cita_id.write({ - 'payment_state': 'paid', - 'amount_paid': self.amount, - }) - - # Acumular puntos en monedero (excepto si el pago es canje de monedero) - if self.payment_method == 'points': - return True - monedero = self.env['skeen.monedero'].search([('partner_id', '=', self.partner_id.id)], limit=1) - if not monedero: - monedero = self.env['skeen.monedero'].create({ - 'partner_id': self.partner_id.id, - }) - - points = int(self.amount / 10) # 1 punto por cada $10 - monedero.add_points( - points=points, - description=f'Pago de servicio - {self.cita_id.servicio_id.name if self.cita_id else "N/A"}', - reference=self.name, - ) - - return True - - def action_refund(self): - """Procesar reembolso""" - self.ensure_one() - self.write({'state': 'refunded'}) - - # Restar puntos del monedero - monedero = self.env['skeen.monedero'].search([('partner_id', '=', self.partner_id.id)], limit=1) - if monedero: - points = int(self.amount / 10) - monedero.redeem_points( - points=points, - description=f'Reembolso - {self.name}', - reference=self.name, - ) - - return True