Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 17 additions & 11 deletions subscription_oca/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,9 @@ To create subscriptions with the sale of a product:
Known issues / Roadmap
======================

- Refactor all the onchanges that have business logic to computed
write-able fields when possible. Keep onchanges only for UI purposes.
- Add tests.
- Refactor all the onchanges that have business logic to computed
write-able fields when possible. Keep onchanges only for UI purposes.
- Add tests.

Bug Tracker
===========
Expand All @@ -95,17 +95,23 @@ Authors
Contributors
------------

- Carlos Martínez <carlos@domatix.com>
- Carolina Ferrer <carolina@domatix.com>
- `Ooops404 <https://www.ooops404.com>`__:
- Carlos Martínez <carlos@domatix.com>
- Carolina Ferrer <carolina@domatix.com>
- `Ooops404 <https://www.ooops404.com>`__:

- Ilyas <irazor147@gmail.com>
- Ilyas <irazor147@gmail.com>

- `Sygel <https://www.sygel.es>`__:
- `Sygel <https://www.sygel.es>`__:

- Harald Panten
- Valentin Vinagre
- Alberto Martínez
- Harald Panten
- Valentin Vinagre
- Alberto Martínez

- `Binhex <https://www.binhex.cloud>`__:

- Adasat Torres de León <a.torres@binhex.cloud>

- Chris Mann

Maintainers
-----------
Expand Down
88 changes: 87 additions & 1 deletion subscription_oca/models/sale_subscription.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,37 @@ class SaleSubscription(models.Model):
ondelete="restrict",
)

payment_token_id = fields.Many2one(
comodel_name="payment.token",
string="Payment Token",
store=True,
compute="_compute_payment_token_id",
domain="[('partner_id', '=', partner_id)]",
)
invoicing_mode = fields.Selection(related="template_id.invoicing_mode")

@api.depends("partner_id", "template_id")
def _compute_payment_token_id(self):
for record in self:
if record.template_id.invoicing_mode not in [
"invoice_and_payment",
]:
record.payment_token_id = False
continue
payment_token = (
self.env["payment.token"]
.sudo()
.with_company(record.company_id)
.search(
[
("partner_id", "=", record.partner_id.id),
],
limit=1,
order="write_date desc",
)
)
record.payment_token_id = payment_token.id if payment_token else False

@api.model
def _read_group_stage_ids(self, stages, domain, order):
stage_ids = stages.search([], order=order)
Expand Down Expand Up @@ -311,10 +342,17 @@ def create_sale_order(self):
def generate_invoice(self):
invoice_number = ""
msg_static = _("Created invoice with reference")
if self.template_id.invoicing_mode in ["draft", "invoice", "invoice_send"]:
if self.template_id.invoicing_mode in [
"draft",
"invoice",
"invoice_send",
"invoice_and_payment",
]:
invoice = self.create_invoice()
if self.template_id.invoicing_mode != "draft":
invoice.action_post()
if self.template_id.invoicing_mode == "invoice_and_payment":
self.create_payment(invoice)
mail_template = self.template_id.invoice_mail_template_id
invoice.with_context(force_send=True)._generate_pdf_and_send_invoice(
mail_template
Expand Down Expand Up @@ -466,3 +504,51 @@ def create(self, vals_list):
.id
)
return super().create(vals_list)

def create_payment(self, invoice):
invoice.ensure_one()
if not self.payment_token_id:
self.message_post(
body=_(
"No payment token found for partner %s" % invoice.partner_id.name
)
)
return
provider = self.payment_token_id.provider_id
method_line = self.env["account.payment.method.line"].search(
[
("payment_method_id.code", "=", provider.code),
("company_id", "=", invoice.company_id.id),
],
limit=1,
)

if not method_line:
self.message_post(
body=_(
"No payment method line found for payment provider %s"
% provider.name
)
)
return
payment_register = self.env["account.payment.register"]
payment_vals = {
"currency_id": invoice.currency_id.id,
"journal_id": provider.journal_id.id,
"company_id": invoice.company_id.id,
"partner_id": invoice.partner_id.id,
"communication": invoice.name,
"payment_type": "inbound",
"partner_type": "customer",
"payment_difference_handling": "open",
"writeoff_label": "Write-Off",
"payment_date": fields.Date.today(),
"amount": invoice.amount_total,
"payment_method_line_id": method_line.id,
"payment_token_id": self.payment_token_id.id,
}
payment_register.with_context(
active_model="account.move",
active_ids=invoice.ids,
active_id=invoice.id,
).create(payment_vals).action_create_payments()
1 change: 1 addition & 0 deletions subscription_oca/models/sale_subscription_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class SaleSubscriptionTemplate(models.Model):
("invoice", "Invoice"),
("invoice_send", "Invoice & send"),
("sale_and_invoice", "Sale order & Invoice"),
("invoice_and_payment", "Invoice & Recurring Payment"),
],
)
code = fields.Char()
Expand Down
3 changes: 3 additions & 0 deletions subscription_oca/readme/CONTRIBUTORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,6 @@
- Harald Panten
- Valentin Vinagre
- Alberto Martínez
- [Binhex](https://www.binhex.cloud):
- Adasat Torres de León \<<a.torres@binhex.cloud>\>
- Chris Mann <chrisandrewmann>
5 changes: 5 additions & 0 deletions subscription_oca/static/description/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,11 @@ <h2><a class="toc-backref" href="#toc-entry-6">Contributors</a></h2>
<li>Alberto Martínez</li>
</ul>
</li>
<li><a class="reference external" href="https://www.binhex.cloud">Binhex</a>:<ul>
<li>Adasat Torres de León &lt;<a class="reference external" href="mailto:a.torres&#64;binhex.cloud">a.torres&#64;binhex.cloud</a>&gt;</li>
</ul>
</li>
<li>Chris Mann</li>
</ul>
</div>
<div class="section" id="maintainers">
Expand Down
93 changes: 92 additions & 1 deletion subscription_oca/tests/test_subscription_oca.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,13 @@ def setUpClass(cls):
"recurring_rule_type": "days",
}
)
cls.tmpl6 = cls.create_sub_template(
{
"recurring_rule_boundary": "unlimited",
"invoicing_mode": "invoice_and_payment",
"recurring_rule_type": "years",
}
)

cls.stage = cls.env["sale.subscription.stage"].create(
{
Expand Down Expand Up @@ -181,6 +188,13 @@ def setUpClass(cls):
"journal_id": cls.cash_journal.id,
}
)
cls.sub10 = cls.create_sub(
{
"template_id": cls.tmpl6.id,
"recurring_rule_boundary": False,
"date_start": fields.Date.today(),
}
)

cls.sub_line = cls.create_sub_line(cls.sub1)
cls.sub_line2 = cls.env["sale.subscription.line"].create(
Expand All @@ -199,6 +213,7 @@ def setUpClass(cls):
cls.sub_line52 = cls.create_sub_line(cls.sub5, cls.product_2.id)
cls.sub_line71 = cls.create_sub_line(cls.sub7)
cls.sub_line72 = cls.create_sub_line(cls.sub7, cls.product_2.id)
cls.sub_line102 = cls.create_sub_line(cls.sub10, cls.product_2.id)

cls.close_reason = cls.env["sale.subscription.close.reason"].create(
{
Expand Down Expand Up @@ -516,7 +531,7 @@ def test_subscription_oca_sub_stage(self):

def test_x_subscription_oca_pricelist_related(self):
res = self.partner.read(["subscription_count", "subscription_ids"])
self.assertEqual(res[0]["subscription_count"], 8)
self.assertEqual(res[0]["subscription_count"], 9)
res = self.partner.action_view_subscription_ids()
self.assertIsInstance(res, dict)
sale_order = self.sub1.create_sale_order()
Expand Down Expand Up @@ -686,3 +701,79 @@ def _collect_all_sub_test_results(self, subscription):
)
test_res.append(group_stage_ids)
return test_res

def test_subscription_invoice_and_payment(self):
payment_method_unknown = self.env.ref("payment.payment_method_unknown")

account_payment_method = self.env["account.payment.method"].create(
{
"name": "Test Payment Method",
"code": "none",
"payment_type": "inbound",
}
)

account_payment_method_line = self.env["account.payment.method.line"].create(
{
"payment_method_id": account_payment_method.id,
"company_id": self.env.ref("base.main_company").id,
"name": "Test Method Line",
}
)

journal = self.env["account.journal"].create(
{
"name": "Test Journal",
"type": "bank",
"company_id": self.env.ref("base.main_company").id,
"code": "TESTJNL",
}
)

provider_test = self.env["payment.provider"].create(
{
"name": "Test Provider for Subscriptions",
"code": "none",
"company_id": self.env.ref("base.main_company").id,
"journal_id": journal.id,
"state": "test",
}
)

subscription = self.sub10
subscription.generate_invoice()
error_count = len(
self.sub10.message_ids.filtered(
lambda msg: "No payment token found for partner" in msg.body
)
)
self.assertEqual(error_count, 1)
self.assertEqual(len(subscription.invoice_ids), 1)
self.assertEqual(subscription.invoice_ids.state, "posted")
self.sub10.payment_token_id = self.env["payment.token"].create(
{
"payment_details": "1234",
"provider_id": provider_test.id,
"partner_id": self.partner.id,
"payment_method_id": payment_method_unknown.id,
"provider_ref": "provider Ref (TEST)",
"active": True,
}
)
subscription.generate_invoice()
self.assertEqual(len(subscription.invoice_ids), 2)
last_invoice = subscription.invoice_ids[-1]
self.assertEqual(last_invoice.state, "posted")
error_count = len(
self.sub10.message_ids.filtered(
lambda msg: "No payment method line found for payment provider"
in msg.body
)
)
journal.write(
{"inbound_payment_method_line_ids": [(4, account_payment_method_line.id)]}
)
subscription.generate_invoice()
self.assertEqual(len(subscription.invoice_ids), 3)
last_invoice = subscription.invoice_ids[-1]
self.assertEqual(last_invoice.state, "posted")
5 changes: 1 addition & 4 deletions subscription_oca/views/sale_subscription_template_views.xml
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@
<field name="invoicing_mode" widget="radio" />
<field
name="invoice_mail_template_id"
invisible="invoicing_mode != 'invoice_send'"
invisible="invoicing_mode not in ['invoice_send', 'invoice_and_payment']"
required="invoicing_mode == 'invoice_send'"
/>
</group>
Expand All @@ -97,12 +97,9 @@
/>
</page>
</notebook>

</sheet>

</form>
</field>

</record>

<record id="sale_subscription_template_tree" model="ir.ui.view">
Expand Down
7 changes: 7 additions & 0 deletions subscription_oca/views/sale_subscription_views.xml
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,13 @@
<field name="date" invisible="recurring_rule_boundary" />
<field name="close_reason_id" invisible="active" />
<field name="recurring_rule_boundary" invisible="1" />
<field name="invoicing_mode" invisible="1" />

<field
name="payment_token_id"
invisible="partner_id == False or invoicing_mode != 'invoice_and_payment'"
readonly="in_progress == True"
/>

</group>
<group name="right_group">
Expand Down