Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[16.0] [ADD] recurring_payment_stripe module #1151

Open
wants to merge 13 commits into
base: 16.0
Choose a base branch
from
Open
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ addon | version | maintainers | summary
[contract_variable_quantity](contract_variable_quantity/) | 16.0.1.1.0 | | Variable quantity in contract recurrent invoicing
[product_contract](product_contract/) | 16.0.1.0.0 | [![sbejaoui](https://github.com/sbejaoui.png?size=30px)](https://github.com/sbejaoui) | Recurring - Product Contract
[subscription_oca](subscription_oca/) | 16.0.1.0.0 | | Generate recurring invoices.
[recurring_payments_stripe](recurring_payments_stripe/) | 16.0.1.0.0 | | Pay automatically with Stripe

[//]: # (end addons)

Expand Down
2 changes: 1 addition & 1 deletion contract_sale/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
13 changes: 8 additions & 5 deletions contract_sale/static/description/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@

/*
:Author: David Goodger ([email protected])
: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.
Expand Down Expand Up @@ -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 }
Expand All @@ -300,7 +301,7 @@
span.pre {
white-space: pre }

span.problematic {
span.problematic, pre.problematic {
color: red }

span.section-subtitle {
Expand Down Expand Up @@ -366,7 +367,7 @@ <h1 class="title">Contract from Sale</h1>
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:00fb3cdc565442ffcd3351e97d0516ce6f4ceb55402981b183f7e717a1e23173
!! source digest: sha256:c2e49dd78cebc553bbe7e5bfa2c8658e29e120878e688512e9599b43144815dd
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Production/Stable" src="https://img.shields.io/badge/maturity-Production%2FStable-green.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/contract/tree/16.0/contract_sale"><img alt="OCA/contract" src="https://img.shields.io/badge/github-OCA%2Fcontract-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/contract-16-0/contract-16-0-contract_sale"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/contract&amp;target_branch=16.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
<p>This module allows access to contracts for sale employees without account
Expand Down Expand Up @@ -428,7 +429,9 @@ <h2><a class="toc-backref" href="#toc-entry-5">Contributors</a></h2>
<div class="section" id="maintainers">
<h2><a class="toc-backref" href="#toc-entry-6">Maintainers</a></h2>
<p>This module is maintained by the OCA.</p>
<a class="reference external image-reference" href="https://odoo-community.org"><img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" /></a>
<a class="reference external image-reference" href="https://odoo-community.org">
<img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" />
</a>
<p>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.</p>
Expand Down
78 changes: 78 additions & 0 deletions recurring_payment_stripe/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
=============================
Recurring Payment 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_payment_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_payment_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 <https://github.com/OCA/contract/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 <https://github.com/OCA/contract/issues/new?body=module:%20recurring_payment_stripe%0Aversion:%2016.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.

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.

.. |maintainer-mjavint| image:: https://github.com/mjavint.png?size=40px
:target: https://github.com/mjavint
:alt: mjavint

Current `maintainer <https://odoo-community.org/page/maintainer-role>`__:

|maintainer-mjavint|

This module is part of the `OCA/contract <https://github.com/OCA/contract/tree/16.0/recurring_payment_stripe>`_ project on GitHub.

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
1 change: 1 addition & 0 deletions recurring_payment_stripe/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import models
18 changes: 18 additions & 0 deletions recurring_payment_stripe/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"name": "Recurring Payment with Stripe",
"version": "16.0.1.0.0",
"summary": """Recurring Payment 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,
"external_dependencies": {"python": ["stripe"]},
"maintainers": ["mjavint"],
}
13 changes: 13 additions & 0 deletions recurring_payment_stripe/data/ir_cron.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<odoo noupdate="1">
<!-- Cron Job para Procesar Facturas Vencidas Diariamente -->
<record id="ir_cron_process_due_invoices" model="ir.cron">
<field name="name">Process Overdue Invoices for Subscriptions</field>
<field name="model_id" ref="recurring_payment_stripe.model_account_move" />
<field name="state">code</field>
<field name="code">model.cron_process_due_invoices()</field>
<field name="interval_number">1</field>
<field name="interval_type">days</field>
<field name="numbercall">-1</field>
<field name="active">True</field>
</record>
</odoo>
2 changes: 2 additions & 0 deletions recurring_payment_stripe/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from . import sale_subscription
from . import account_move
94 changes: 94 additions & 0 deletions recurring_payment_stripe/models/account_move.py
Original file line number Diff line number Diff line change
@@ -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 warning on line 21 in recurring_payment_stripe/models/account_move.py

View check run for this annotation

Codecov / codecov/patch

recurring_payment_stripe/models/account_move.py#L21

Added line #L21 was not covered by tests

# 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(

Check warning on line 27 in recurring_payment_stripe/models/account_move.py

View check run for this annotation

Codecov / codecov/patch

recurring_payment_stripe/models/account_move.py#L25-L27

Added lines #L25 - L27 were not covered by tests
[("provider_id", "=", provider.id)]
)
try:

Check warning on line 30 in recurring_payment_stripe/models/account_move.py

View check run for this annotation

Codecov / codecov/patch

recurring_payment_stripe/models/account_move.py#L30

Added line #L30 was not covered by tests
# Create the PaymentIntent and confirm it immediately
payment_intent = stripe.PaymentIntent.create(

Check warning on line 32 in recurring_payment_stripe/models/account_move.py

View check run for this annotation

Codecov / codecov/patch

recurring_payment_stripe/models/account_move.py#L32

Added line #L32 was not covered by tests
# 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)},
)

# Handling the result of the 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 = {

Check warning on line 49 in recurring_payment_stripe/models/account_move.py

View check run for this annotation

Codecov / codecov/patch

recurring_payment_stripe/models/account_move.py#L48-L49

Added lines #L48 - L49 were not covered by tests
"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"

Check warning on line 64 in recurring_payment_stripe/models/account_move.py

View check run for this annotation

Codecov / codecov/patch

recurring_payment_stripe/models/account_move.py#L62-L64

Added lines #L62 - L64 were not covered by tests
elif payment_intent["status"] == "requires_action":
raise UserError(

Check warning on line 66 in recurring_payment_stripe/models/account_move.py

View check run for this annotation

Codecov / codecov/patch

recurring_payment_stripe/models/account_move.py#L66

Added line #L66 was not covered by tests
_("Payment requires additional authentication (3D Secure).")
)
else:
raise UserError(

Check warning on line 70 in recurring_payment_stripe/models/account_move.py

View check run for this annotation

Codecov / codecov/patch

recurring_payment_stripe/models/account_move.py#L70

Added line #L70 was not covered by tests
f"Stripe payment error: {payment_intent['status']}"
)

except stripe.StripeError as e:
raise UserError(f"Stripe error: {e}") from e

Check warning on line 75 in recurring_payment_stripe/models/account_move.py

View check run for this annotation

Codecov / codecov/patch

recurring_payment_stripe/models/account_move.py#L74-L75

Added lines #L74 - L75 were not covered by tests

else:
return super(AccountMove, self).action_register_payment()

Check warning on line 78 in recurring_payment_stripe/models/account_move.py

View check run for this annotation

Codecov / codecov/patch

recurring_payment_stripe/models/account_move.py#L78

Added line #L78 was not covered by tests

@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 warning on line 86 in recurring_payment_stripe/models/account_move.py

View check run for this annotation

Codecov / codecov/patch

recurring_payment_stripe/models/account_move.py#L86

Added line #L86 was not covered by tests

# Check if it's a recurring subscription with Stripe
if subscription and subscription.charge_automatically:
try:

Check warning on line 90 in recurring_payment_stripe/models/account_move.py

View check run for this annotation

Codecov / codecov/patch

recurring_payment_stripe/models/account_move.py#L90

Added line #L90 was not covered by tests
# Register the payment
invoice.action_register_payment()
except Exception as e:
_logger.error(f"Error Processing Due Invoices: {str(e)}")

Check warning on line 94 in recurring_payment_stripe/models/account_move.py

View check run for this annotation

Codecov / codecov/patch

recurring_payment_stripe/models/account_move.py#L92-L94

Added lines #L92 - L94 were not covered by tests
35 changes: 35 additions & 0 deletions recurring_payment_stripe/models/sale_subscription.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import stripe

from odoo import api, fields, models


class SaleSubscription(models.Model):
_inherit = "sale.subscription"

charge_automatically = fields.Boolean()
stripe_customer = fields.Char("Stripe Customer ID")
provider_id = fields.Many2one(
string="Provider",
domain=[("code", "=", "stripe")],
comodel_name="payment.provider",
)

def create_stripe_customer(self):
provider = self.provider_id

Check warning on line 18 in recurring_payment_stripe/models/sale_subscription.py

View check run for this annotation

Codecov / codecov/patch

recurring_payment_stripe/models/sale_subscription.py#L18

Added line #L18 was not covered by tests
if provider:
stripe.api_key = provider.stripe_secret_key

Check warning on line 20 in recurring_payment_stripe/models/sale_subscription.py

View check run for this annotation

Codecov / codecov/patch

recurring_payment_stripe/models/sale_subscription.py#L20

Added line #L20 was not covered by tests

if not self.stripe_customer:
customer = stripe.Customer.create(

Check warning on line 23 in recurring_payment_stripe/models/sale_subscription.py

View check run for this annotation

Codecov / codecov/patch

recurring_payment_stripe/models/sale_subscription.py#L23

Added line #L23 was not covered by tests
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

Check warning on line 29 in recurring_payment_stripe/models/sale_subscription.py

View check run for this annotation

Codecov / codecov/patch

recurring_payment_stripe/models/sale_subscription.py#L28-L29

Added lines #L28 - L29 were not covered by tests

@api.onchange("charge_automatically")
def _onchange_charge_automatically(self):
for record in self:
if record.charge_automatically:
record.create_stripe_customer()

Check warning on line 35 in recurring_payment_stripe/models/sale_subscription.py

View check run for this annotation

Codecov / codecov/patch

recurring_payment_stripe/models/sale_subscription.py#L35

Added line #L35 was not covered by tests
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Loading
Loading