diff --git a/contract_sale/README.rst b/contract_sale/README.rst
index e125136f45..2930853090 100644
--- a/contract_sale/README.rst
+++ b/contract_sale/README.rst
@@ -7,7 +7,7 @@ Contract from Sale
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- !! source digest: sha256:00fb3cdc565442ffcd3351e97d0516ce6f4ceb55402981b183f7e717a1e23173
+ !! source digest: sha256:c2e49dd78cebc553bbe7e5bfa2c8658e29e120878e688512e9599b43144815dd
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.. |badge1| image:: https://img.shields.io/badge/maturity-Production%2FStable-green.png
diff --git a/contract_sale/readme/CONFIGURE.rst b/contract_sale/readme/CONFIGURE.rst
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/contract_sale/readme/CREDITS.rst b/contract_sale/readme/CREDITS.rst
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/contract_sale/readme/DEVELOP.rst b/contract_sale/readme/DEVELOP.rst
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/contract_sale/readme/HISTORY.rst b/contract_sale/readme/HISTORY.rst
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/contract_sale/readme/INSTALL.rst b/contract_sale/readme/INSTALL.rst
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/contract_sale/readme/ROADMAP.rst b/contract_sale/readme/ROADMAP.rst
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/contract_sale/static/description/index.html b/contract_sale/static/description/index.html
index 2fec06806d..c4924509c2 100644
--- a/contract_sale/static/description/index.html
+++ b/contract_sale/static/description/index.html
@@ -8,10 +8,11 @@
/*
:Author: David Goodger (goodger@python.org)
-:Id: $Id: html4css1.css 8954 2022-01-20 10:10:25Z milde $
+:Id: $Id: html4css1.css 9511 2024-01-13 09:50:07Z milde $
:Copyright: This stylesheet has been placed in the public domain.
Default cascading style sheet for the HTML output of Docutils.
+Despite the name, some widely supported CSS2 features are used.
See https://docutils.sourceforge.io/docs/howto/html-stylesheets.html for how to
customize this style sheet.
@@ -274,7 +275,7 @@
margin-left: 2em ;
margin-right: 2em }
-pre.code .ln { color: grey; } /* line numbers */
+pre.code .ln { color: gray; } /* line numbers */
pre.code, code { background-color: #eeeeee }
pre.code .comment, code .comment { color: #5C6576 }
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
@@ -300,7 +301,7 @@
span.pre {
white-space: pre }
-span.problematic {
+span.problematic, pre.problematic {
color: red }
span.section-subtitle {
@@ -366,7 +367,7 @@
This module allows access to contracts for sale employees without account
@@ -428,7 +429,9 @@
This module is maintained by the OCA.
-
+
+
+
OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.
diff --git a/recurring_payments_stripe/README.rst b/recurring_payments_stripe/README.rst
new file mode 100644
index 0000000000..31fcb6beb7
--- /dev/null
+++ b/recurring_payments_stripe/README.rst
@@ -0,0 +1,70 @@
+==============================
+Recurring Payments with Stripe
+==============================
+
+..
+ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ !! This file is generated by oca-gen-addon-readme !!
+ !! changes will be overwritten. !!
+ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ !! source digest: sha256:7aacc5b46917b14e43404143f0ccd1519d1411d580330b8eb8a8ef608fe3a5a1
+ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
+ :target: https://odoo-community.org/page/development-status
+ :alt: Beta
+.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
+ :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
+ :alt: License: AGPL-3
+.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fcontract-lightgray.png?logo=github
+ :target: https://github.com/OCA/contract/tree/16.0/recurring_payments_stripe
+ :alt: OCA/contract
+.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
+ :target: https://translation.odoo-community.org/projects/contract-16-0/contract-16-0-recurring_payments_stripe
+ :alt: Translate me on Weblate
+.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png
+ :target: https://runboat.odoo-community.org/builds?repo=OCA/contract&target_branch=16.0
+ :alt: Try me on Runboat
+
+|badge1| |badge2| |badge3| |badge4| |badge5|
+
+
+**Table of contents**
+
+.. contents::
+ :local:
+
+Bug Tracker
+===========
+
+Bugs are tracked on `GitHub Issues
`_.
+In case of trouble, please check there if your issue has already been reported.
+If you spotted it first, help us to smash it by providing a detailed and welcomed
+`feedback `_.
+
+Do not contact contributors directly about support or help with technical issues.
+
+Credits
+=======
+
+Authors
+~~~~~~~
+
+* Binhex
+
+Maintainers
+~~~~~~~~~~~
+
+This module is maintained by the OCA.
+
+.. image:: https://odoo-community.org/logo.png
+ :alt: Odoo Community Association
+ :target: https://odoo-community.org
+
+OCA, or the Odoo Community Association, is a nonprofit organization whose
+mission is to support the collaborative development of Odoo features and
+promote its widespread use.
+
+This module is part of the `OCA/contract `_ project on GitHub.
+
+You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
diff --git a/recurring_payments_stripe/__init__.py b/recurring_payments_stripe/__init__.py
new file mode 100644
index 0000000000..0650744f6b
--- /dev/null
+++ b/recurring_payments_stripe/__init__.py
@@ -0,0 +1 @@
+from . import models
diff --git a/recurring_payments_stripe/__manifest__.py b/recurring_payments_stripe/__manifest__.py
new file mode 100644
index 0000000000..ca812198c9
--- /dev/null
+++ b/recurring_payments_stripe/__manifest__.py
@@ -0,0 +1,16 @@
+{
+ "name": "Recurring Payments with Stripe",
+ "version": "16.0.1.0.0",
+ "summary": """ Recurring Payments with Stripe """,
+ "author": "Binhex, Odoo Community Association (OCA)",
+ "website": "https://github.com/OCA/contract",
+ "license": "AGPL-3",
+ "category": "Subscription Management",
+ "depends": ["subscription_oca", "payment_stripe", "payment"],
+ "data": [
+ "views/sale_subscription_views.xml",
+ "data/ir_cron.xml",
+ ],
+ "installable": True,
+ "auto_install": False,
+}
diff --git a/recurring_payments_stripe/data/ir_cron.xml b/recurring_payments_stripe/data/ir_cron.xml
new file mode 100644
index 0000000000..ff41276318
--- /dev/null
+++ b/recurring_payments_stripe/data/ir_cron.xml
@@ -0,0 +1,13 @@
+
+
+
+ Process Overdue Invoices for Subscriptions
+
+ code
+ model.cron_process_due_invoices()
+ 1
+ days
+ -1
+ True
+
+
diff --git a/recurring_payments_stripe/models/__init__.py b/recurring_payments_stripe/models/__init__.py
new file mode 100644
index 0000000000..fe83caa1a8
--- /dev/null
+++ b/recurring_payments_stripe/models/__init__.py
@@ -0,0 +1,2 @@
+from . import sale_subscription
+from . import account_move
diff --git a/recurring_payments_stripe/models/account_move.py b/recurring_payments_stripe/models/account_move.py
new file mode 100644
index 0000000000..14d29e011e
--- /dev/null
+++ b/recurring_payments_stripe/models/account_move.py
@@ -0,0 +1,94 @@
+import logging
+
+import stripe
+
+from odoo import api, models
+from odoo.exceptions import UserError
+
+_logger = logging.getLogger(__name__)
+
+
+class AccountMove(models.Model):
+ _inherit = "account.move"
+
+ def action_register_payment(self):
+ """
+ Override `action_register_payment` to automatically process Stripe
+ payment on subscriptions.
+ """
+ for invoice in self:
+ # Find the subscription associated with the invoice, if it exists
+ subscription = invoice.subscription_id
+
+ # Check if the subscription is recurring and has a payment method
+ if subscription and subscription.charge_automatically:
+ provider = subscription.provider_id
+ stripe.api_key = provider.stripe_secret_key
+ token = self.env["payment.token"].search(
+ [("provider_id", "=", provider.id)]
+ )
+ try:
+ # Create the PaymentIntent and confirm it immediately
+ payment_intent = stripe.PaymentIntent.create(
+ # Stripe usa centavos
+ amount=int(invoice.amount_total * 100),
+ currency=invoice.currency_id.name.lower(),
+ customer=token.provider_ref,
+ payment_method=token.stripe_payment_method,
+ # Para pagos automáticos sin intervención del usuario
+ off_session=True,
+ # Confirmar el PaymentIntent inmediatamente
+ confirm=True,
+ metadata={"odoo_invoice_id": str(invoice.id)},
+ )
+
+ # Manejar el resultado del PaymentIntent
+ if payment_intent["status"] == "succeeded":
+ # If the payment is successful, record the payment on the invoice
+ Payment = self.env["account.payment"].sudo()
+ payment_vals = {
+ "journal_id": self.env["account.journal"]
+ .search([("type", "=", "bank")], limit=1)
+ .id,
+ "amount": invoice.amount_total,
+ "payment_type": "inbound",
+ "partner_type": "customer",
+ "partner_id": invoice.partner_id.id,
+ "payment_method_id": self.env.ref(
+ "account.account_payment_method_manual_in"
+ ).id,
+ "ref": f"Stripe PaymentIntent {payment_intent['id']}",
+ }
+ payment = Payment.create(payment_vals)
+ payment.action_post()
+ invoice.payment_state = "paid"
+ elif payment_intent["status"] == "requires_action":
+ raise UserError(
+ "Payment requires additional authentication (3D Secure)."
+ )
+ else:
+ raise UserError(
+ f"Stripe payment error: {payment_intent['status']}"
+ )
+
+ except stripe.StripeError as e:
+ raise UserError(f"Stripe error: {e.user_message or str(e)}")
+
+ else:
+ return super(AccountMove, self).action_register_payment()
+
+ @api.model
+ def cron_process_due_invoices(self):
+ """Process payment of overdue invoices for recurring subscriptions."""
+
+ for invoice in self:
+ # Find the subscription associated with the invoice
+ subscription = invoice.subscription_id
+
+ # Check if it's a recurring subscription with Stripe
+ if subscription and subscription.charge_automatically:
+ try:
+ # Register the payment
+ invoice.action_register_payment()
+ except Exception as e:
+ _logger.error(f"Error Processing Due Invoices: {str(e)}")
diff --git a/recurring_payments_stripe/models/sale_subscription.py b/recurring_payments_stripe/models/sale_subscription.py
new file mode 100644
index 0000000000..ccc60eaf70
--- /dev/null
+++ b/recurring_payments_stripe/models/sale_subscription.py
@@ -0,0 +1,35 @@
+import stripe
+
+from odoo import api, fields, models
+
+
+class SaleSubscription(models.Model):
+ _inherit = "sale.subscription"
+
+ charge_automatically = fields.Boolean(string="Charge Automatically")
+ stripe_customer = fields.Char(string="Stripe Customer ID")
+ provider_id = fields.Many2one(
+ string="Provider_id",
+ domain=[("code", "=", "stripe")],
+ comodel_name="payment.provider",
+ )
+
+ def create_stripe_customer(self):
+ provider = self.provider_id
+ if provider:
+ stripe.api_key = provider.stripe_secret_key
+
+ if not self.stripe_customer:
+ customer = stripe.Customer.create(
+ email=self.env.user.email,
+ name=self.env.user.name,
+ metadata={"odoo_subscription": str(self.id)},
+ )
+ self.stripe_customer = customer["id"]
+ return self.stripe_customer
+
+ @api.onchange("charge_automatically")
+ def _onchange_charge_automatically(self):
+ for record in self:
+ if record.charge_automatically:
+ record.create_stripe_customer()
diff --git a/recurring_payments_stripe/readme/CONFIGURE.rst b/recurring_payments_stripe/readme/CONFIGURE.rst
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/recurring_payments_stripe/readme/CONTRIBUTORS.rst b/recurring_payments_stripe/readme/CONTRIBUTORS.rst
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/recurring_payments_stripe/readme/CREDITS.rst b/recurring_payments_stripe/readme/CREDITS.rst
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/recurring_payments_stripe/readme/DESCRIPTION.rst b/recurring_payments_stripe/readme/DESCRIPTION.rst
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/recurring_payments_stripe/readme/DEVELOP.rst b/recurring_payments_stripe/readme/DEVELOP.rst
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/recurring_payments_stripe/readme/HISTORY.rst b/recurring_payments_stripe/readme/HISTORY.rst
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/recurring_payments_stripe/readme/INSTALL.rst b/recurring_payments_stripe/readme/INSTALL.rst
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/recurring_payments_stripe/readme/ROADMAP.rst b/recurring_payments_stripe/readme/ROADMAP.rst
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/recurring_payments_stripe/readme/USAGE.rst b/recurring_payments_stripe/readme/USAGE.rst
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/recurring_payments_stripe/static/description/index.html b/recurring_payments_stripe/static/description/index.html
new file mode 100644
index 0000000000..d9629f4109
--- /dev/null
+++ b/recurring_payments_stripe/static/description/index.html
@@ -0,0 +1,415 @@
+
+
+
+
+
+Recurring Payments with Stripe
+
+
+
+
+
Recurring Payments with Stripe
+
+
+
+
Table of contents
+
+
+
+
Bugs are tracked on GitHub Issues.
+In case of trouble, please check there if your issue has already been reported.
+If you spotted it first, help us to smash it by providing a detailed and welcomed
+feedback.
+
Do not contact contributors directly about support or help with technical issues.
+
+
+
+
+
+
+
This module is maintained by the OCA.
+
+
+
+
OCA, or the Odoo Community Association, is a nonprofit organization whose
+mission is to support the collaborative development of Odoo features and
+promote its widespread use.
+
This module is part of the OCA/contract project on GitHub.
+
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
+
+
+
+
+
diff --git a/recurring_payments_stripe/views/sale_subscription_views.xml b/recurring_payments_stripe/views/sale_subscription_views.xml
new file mode 100644
index 0000000000..bdfc7c87c0
--- /dev/null
+++ b/recurring_payments_stripe/views/sale_subscription_views.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+ sale.subscription.form
+ sale.subscription
+
+
+
+
+
+
+
+
+
+
+
diff --git a/setup/recurring_payments_stripe/odoo/addons/recurring_payments_stripe b/setup/recurring_payments_stripe/odoo/addons/recurring_payments_stripe
new file mode 120000
index 0000000000..0bdeb61a53
--- /dev/null
+++ b/setup/recurring_payments_stripe/odoo/addons/recurring_payments_stripe
@@ -0,0 +1 @@
+../../../../recurring_payments_stripe
\ No newline at end of file
diff --git a/setup/recurring_payments_stripe/setup.py b/setup/recurring_payments_stripe/setup.py
new file mode 100644
index 0000000000..28c57bb640
--- /dev/null
+++ b/setup/recurring_payments_stripe/setup.py
@@ -0,0 +1,6 @@
+import setuptools
+
+setuptools.setup(
+ setup_requires=['setuptools-odoo'],
+ odoo_addon=True,
+)