[ADD] account: onboarding panel for invoicing
Add an onboarding panel for invoicing, it appears above the invoice list. After going through the steps the system should be all set to send real invoices. In the payment module, add a payment acquirer step and add it to the invoice onboarding panel. task: 60668
This commit is contained in:
committed by
Yannick Tivisse
parent
9744fecd05
commit
d1ec3306b8
@@ -63,6 +63,7 @@ Core mechanisms for the accounting modules. To display the menuitems, install th
|
||||
'data/payment_receipt_data.xml',
|
||||
'wizard/setup_wizards_view.xml',
|
||||
'views/account_dashboard_setup_bar.xml',
|
||||
'views/account_onboarding_templates.xml',
|
||||
'wizard/account_report_tax_view.xml',
|
||||
'views/report_tax.xml',
|
||||
'views/res_users_views.xml',
|
||||
|
||||
@@ -2,4 +2,5 @@
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from . import mail
|
||||
from . import onboarding
|
||||
from . import portal
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
from odoo import http
|
||||
from odoo.http import request
|
||||
|
||||
|
||||
class OnboardingController(http.Controller):
|
||||
|
||||
@http.route('/account/account_invoice_onboarding', auth='user', type='json')
|
||||
def account_invoice_onboarding(self):
|
||||
""" Returns the `banner` for the account invoice onboarding panel.
|
||||
It can be empty if the user has closed it or if he doesn't have
|
||||
the permission to see it. """
|
||||
|
||||
if not request.env.user._is_admin() or \
|
||||
request.env.user.company_id.account_invoice_onboarding_closed:
|
||||
return {}
|
||||
|
||||
return {
|
||||
'html': request.env.ref('account.account_invoice_onboarding_panel').render({
|
||||
'company': request.env.user.company_id,
|
||||
})
|
||||
}
|
||||
@@ -621,6 +621,7 @@ class AccountInvoice(models.Model):
|
||||
def message_post(self, **kwargs):
|
||||
if self.env.context.get('mark_invoice_as_sent'):
|
||||
self.filtered(lambda inv: not inv.sent).write({'sent': True})
|
||||
self.env.user.company_id.account_onboarding_sample_invoice_sent = True
|
||||
return super(AccountInvoice, self.with_context(mail_post_autofollow=True)).message_post(**kwargs)
|
||||
|
||||
@api.model
|
||||
|
||||
@@ -6,7 +6,7 @@ import time
|
||||
from dateutil.relativedelta import relativedelta
|
||||
|
||||
from odoo import fields, models, api, _
|
||||
from odoo.exceptions import ValidationError, UserError
|
||||
from odoo.exceptions import ValidationError, UserError, RedirectWarning
|
||||
from odoo.tools.misc import DEFAULT_SERVER_DATE_FORMAT
|
||||
from odoo.tools.float_utils import float_round, float_is_zero
|
||||
from odoo.tools import DEFAULT_SERVER_DATE_FORMAT, date_utils
|
||||
@@ -67,6 +67,19 @@ Best Regards,'''))
|
||||
account_setup_coa_done = fields.Boolean(string='Chart of Account Checked', help="Technical field holding the status of the chart of account setup step.")
|
||||
account_setup_bar_closed = fields.Boolean(string='Setup Bar Closed', help="Technical field set to True when setup bar has been closed by the user.")
|
||||
|
||||
# account invoice onboarding
|
||||
account_invoice_onboarding_closed = fields.Boolean(
|
||||
string="Account invoice onboarding panel closed",
|
||||
help="Refers to the account invoice onboarding panel closed state.")
|
||||
account_invoice_onboarding_folded = fields.Boolean(
|
||||
string="Account invoice onboarding panel folded",
|
||||
help="Refers to the account invoice onboarding panel folded state.")
|
||||
|
||||
account_onboarding_invoice_layout_done = fields.Boolean("Onboarding invoice layout step done",
|
||||
compute="_compute_account_onboarding_invoice_layout_done")
|
||||
account_onboarding_sample_invoice_sent = fields.Boolean(
|
||||
"Onboarding sample invoice step completed", default=False)
|
||||
|
||||
@api.multi
|
||||
def _check_lock_dates(self, vals):
|
||||
'''Check the lock dates for the current companies. This can't be done in a api.constrains because we need
|
||||
@@ -398,3 +411,100 @@ Best Regards,'''))
|
||||
'debit': credit_diff,
|
||||
'credit': debit_diff,
|
||||
})
|
||||
|
||||
@api.depends('logo', 'account_invoice_onboarding_closed')
|
||||
def _compute_account_onboarding_invoice_layout_done(self):
|
||||
""" The invoice onboarding step is marked as done if logo is filled
|
||||
and different from the default one. """
|
||||
for record in self:
|
||||
record.account_onboarding_invoice_layout_done = \
|
||||
record.account_invoice_onboarding_closed or (
|
||||
bool(record.logo) and record.logo != record._get_logo())
|
||||
|
||||
@api.model
|
||||
def action_toggle_fold_account_invoice_onboarding(self):
|
||||
""" Toggle the onboarding panel `folded` state. """
|
||||
self.env.user.company_id.account_invoice_onboarding_folded =\
|
||||
not self.env.user.company_id.account_invoice_onboarding_folded
|
||||
|
||||
@api.model
|
||||
def action_close_account_invoice_onboarding(self):
|
||||
""" Mark the onboarding panel as closed. """
|
||||
self.env.user.company_id.account_invoice_onboarding_closed = True
|
||||
|
||||
@api.model
|
||||
def action_open_account_onboarding_invoice_layout(self):
|
||||
""" Onboarding step for the invoice layout. """
|
||||
action = self.env.ref('account.action_open_account_onboarding_invoice_layout').read()[0]
|
||||
action['res_id'] = self.env.user.company_id.id
|
||||
return action
|
||||
|
||||
@api.model
|
||||
def _get_sample_invoice(self):
|
||||
""" Get a sample invoice or create one if it does not exist. """
|
||||
# use current user as partner
|
||||
partner = self.env.user.partner_id
|
||||
|
||||
company_id = self.env.user.company_id.id
|
||||
# try to find an existing sample invoice
|
||||
sample_invoice = self.env['account.invoice'].search(
|
||||
[('company_id', '=', company_id),
|
||||
('partner_id', '=', partner.id)], limit=1)
|
||||
|
||||
if len(sample_invoice) == 0:
|
||||
# If there are no existing accounts or no journal, fail
|
||||
account = self.env['account.account'].search([('company_id', '=', company_id)], limit=1)
|
||||
if len(account) == 0:
|
||||
action = self.env.ref('account.action_account_config')
|
||||
msg = _(
|
||||
"We cannot find a chart of accounts for this company, you should configure it. \n"
|
||||
"Please go to Account Configuration and select or install a fiscal localization.")
|
||||
raise RedirectWarning(msg, action.id, _("Go to the configuration panel"))
|
||||
|
||||
journal = self.env['account.journal'].search([('company_id', '=', company_id)], limit=1)
|
||||
if len(journal) == 0:
|
||||
action = self.env.ref('account.action_account_journal_form')
|
||||
msg = _("We cannot find any journal for this company. You should create one."
|
||||
"\nPlease go to Configuration > Journals.")
|
||||
raise RedirectWarning(msg, action.id, _("Go to the journal configuration"))
|
||||
|
||||
sample_invoice = self.env['account.invoice'].create({
|
||||
'name': _("Sample invoice"),
|
||||
'journal_id': journal.id,
|
||||
'partner_id': partner.id,
|
||||
})
|
||||
# sample invoice lines
|
||||
self.env['account.invoice.line'].create({
|
||||
'name': _("Sample invoice line name"),
|
||||
'invoice_id': sample_invoice.id,
|
||||
'account_id': account.id,
|
||||
'price_unit': 199.99,
|
||||
'quantity': 2,
|
||||
})
|
||||
self.env['account.invoice.line'].create({
|
||||
'name': _("Sample invoice line name 2"),
|
||||
'invoice_id': sample_invoice.id,
|
||||
'account_id': account.id,
|
||||
'price_unit': 25,
|
||||
'quantity': 1,
|
||||
})
|
||||
return sample_invoice
|
||||
|
||||
@api.model
|
||||
def action_open_account_onboarding_sample_invoice(self):
|
||||
""" Onboarding step for sending a sample invoice. Open a window to compose an email,
|
||||
with the edi_invoice_template message loaded by default. """
|
||||
sample_invoice = self._get_sample_invoice()
|
||||
template = self.env.ref('account.email_template_edi_invoice', False)
|
||||
action = self.env.ref('account.action_open_account_onboarding_sample_invoice').read()[0]
|
||||
action['context'] = {
|
||||
'default_res_id': sample_invoice.id,
|
||||
'default_use_template': bool(template),
|
||||
'default_template_id': template and template.id or False,
|
||||
'default_model': 'account.invoice',
|
||||
'default_composition_mode': 'comment',
|
||||
'mark_invoice_as_sent': True,
|
||||
'custom_layout': 'mail.mail_notification_borders',
|
||||
'force_email': True,
|
||||
}
|
||||
return action
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 23 KiB |
@@ -167,6 +167,18 @@
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="invoice_tree_with_onboarding" model="ir.ui.view">
|
||||
<field name="name">account.invoice.tree.with.onboarding</field>
|
||||
<field name="model">account.invoice</field>
|
||||
<field name="inherit_id" ref="invoice_tree"/>
|
||||
<field name="mode">primary</field>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//tree" position="attributes">
|
||||
<attribute name="banner_route">/account/account_invoice_onboarding</attribute>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="invoice_kanban">
|
||||
<field name="name">account.invoice.kanban</field>
|
||||
<field name="model">account.invoice</field>
|
||||
@@ -727,11 +739,10 @@
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
<record id="action_invoice_tree1_view1" model="ir.actions.act_window.view">
|
||||
<field eval="1" name="sequence"/>
|
||||
<field name="view_mode">tree</field>
|
||||
<field name="view_id" ref="invoice_tree"/>
|
||||
<field name="view_id" ref="invoice_tree_with_onboarding"/>
|
||||
<field name="act_window_id" ref="action_invoice_tree1"/>
|
||||
</record>
|
||||
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<!-- ONBOARDING STEPS -->
|
||||
<template id="onboarding_invoice_layout_step">
|
||||
<t t-call="base.onboarding_step">
|
||||
<t t-set="title">Invoice Layout</t>
|
||||
<t t-set="description">Create and send professional looking invoices.</t>
|
||||
<t t-set="done_icon" t-value="'fa-star'" />
|
||||
<t t-set="done_text">Looks great!</t>
|
||||
<t t-set="method" t-value="'action_open_account_onboarding_invoice_layout'" />
|
||||
<t t-set="model" t-value="'res.company'" />
|
||||
<t t-set="done" t-value="company.account_onboarding_invoice_layout_done" />
|
||||
</t>
|
||||
</template>
|
||||
<template id="onboarding_sample_invoice_step">
|
||||
<t t-call="base.onboarding_step">
|
||||
<t t-set="title">Sample Invoice</t>
|
||||
<t t-set="description">Quickly preview what your client sees by sending a sample invoice
|
||||
to yourself.
|
||||
</t>
|
||||
<t t-set="btn_text">I'm ready</t>
|
||||
<t t-set="done_text">Sample invoice sent!</t>
|
||||
<t t-set="method" t-value="'action_open_account_onboarding_sample_invoice'" />
|
||||
<t t-set="model" t-value="'res.company'" />
|
||||
<t t-set="done" t-value="company.account_onboarding_sample_invoice_sent" />
|
||||
</t>
|
||||
</template>
|
||||
<!-- ONBOARDING PANEL-->
|
||||
<template id="account_invoice_onboarding_panel" name="account.invoice.onboarding.panel">
|
||||
<t t-call="base.onboarding_container">
|
||||
<t t-set="classes">o_onboarding_blue</t>
|
||||
<t t-set="bg_image">/account/static/src/img/account_invoice_onboarding_bg.jpg</t>
|
||||
<t t-set="close_method">action_close_account_invoice_onboarding</t>
|
||||
<t t-set="close_model">res.company</t>
|
||||
<t t-set="fold_method">action_toggle_fold_account_invoice_onboarding</t>
|
||||
<t t-set="fold_model">res.company</t>
|
||||
<t t-set="folded_by_default" t-value="company.account_invoice_onboarding_folded" />
|
||||
<t t-call="base.onboarding_company_step" name="company_step" />
|
||||
<t t-call="account.onboarding_invoice_layout_step" name="invoice_layout_step" />
|
||||
<t t-call="account.onboarding_sample_invoice_step" name="sample_invoice_step" />
|
||||
</t>
|
||||
</template>
|
||||
<!-- INVOICE FORM -->
|
||||
<record id="action_open_account_onboarding_invoice_layout" model="ir.actions.act_window">
|
||||
<field name="name">Configure your document template</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">res.company</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_id" ref="base.view_company_document_template_form" />
|
||||
<field name="target">new</field>
|
||||
</record>
|
||||
<!-- SAMPLE INVOICE EMAIL -->
|
||||
<record model="ir.ui.view" id="email_compose_onboarding_sample_invoice">
|
||||
<field name="name">mail.compose.message.form.account_invoice_onboarding_sample_invoice
|
||||
</field>
|
||||
<field name="model">mail.compose.message</field>
|
||||
<field name="inherit_id" ref="mail.email_compose_message_wizard_form" />
|
||||
<field name="priority">1000</field>
|
||||
<field name="mode">primary</field>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//span[@name='document_followers_text']" position="attributes">
|
||||
<attribute name="invisible">1</attribute>
|
||||
</xpath>
|
||||
<xpath expr="//button[@name='save_as_template']" position="attributes">
|
||||
<attribute name="invisible">1</attribute>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='template_id']" position="attributes">
|
||||
<attribute name="invisible">1</attribute>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
<record id="action_open_account_onboarding_sample_invoice" model="ir.actions.act_window">
|
||||
<field name="name">Send a sample invoice</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">mail.compose.message</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_id" ref="email_compose_onboarding_sample_invoice" />
|
||||
<field name="target">new</field>
|
||||
</record>
|
||||
</odoo>
|
||||
@@ -52,7 +52,7 @@
|
||||
<span attrs="{'invisible': [('use_active_domain', '=', True)]}">the selected records</span>
|
||||
<span attrs="{'invisible': [('use_active_domain', '=', False)]}">the current search filter</span>.
|
||||
</span>
|
||||
<span attrs="{'invisible':['|', ('model', '=', False), ('composition_mode', '=', 'mass_mail')]}">Followers of the document and</span>
|
||||
<span name="document_followers_text" attrs="{'invisible':['|', ('model', '=', False), ('composition_mode', '=', 'mass_mail')]}">Followers of the document and</span>
|
||||
<field name="partner_ids" widget="many2many_tags_email" placeholder="Add contacts to notify..."
|
||||
context="{'force_email':True, 'show_email':True}"
|
||||
attrs="{'invisible': [('composition_mode', '!=', 'comment')]}"/>
|
||||
|
||||
@@ -2,4 +2,5 @@
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from . import models
|
||||
from . import controllers
|
||||
from . import controllers
|
||||
from . import wizards
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
'views/payment_views.xml',
|
||||
'views/account_payment_views.xml',
|
||||
'views/account_invoice_views.xml',
|
||||
'views/payment_acquirer_onboarding_templates.xml',
|
||||
'views/payment_templates.xml',
|
||||
'views/payment_portal_templates.xml',
|
||||
'views/assets.xml',
|
||||
|
||||
@@ -5,3 +5,4 @@ from . import account_invoice
|
||||
from . import res_partner
|
||||
from . import account_payment
|
||||
from . import chart_template
|
||||
from . import res_company
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
from odoo import _, api, fields, models
|
||||
|
||||
|
||||
class ResCompany(models.Model):
|
||||
_inherit = 'res.company'
|
||||
|
||||
# Step is marked as done if one payment module is installed or
|
||||
# `custom` payment has been changed or `skip this step` has been clicked
|
||||
payment_acquirer_onboarding_done = fields.Boolean('Payment acquirer onboarding done', default=False)
|
||||
|
||||
@api.model
|
||||
def action_open_payment_onboarding_payment_acquirer(self):
|
||||
""" Called by onboarding panel above the customer invoice list."""
|
||||
action = self.env.ref('payment.action_open_payment_onboarding_payment_acquirer_wizard').read()[0]
|
||||
return action
|
||||
@@ -0,0 +1,135 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<!-- onboarding step -->
|
||||
<template id="onboarding_payment_acquirer_step">
|
||||
<t t-call="base.onboarding_step">
|
||||
<t t-set="title">Payment Method</t>
|
||||
<t t-set="description">Choose the payment methods to collect payments on your invoices.</t>
|
||||
<t t-set="done_text">Payment method set!</t>
|
||||
<t t-set="method" t-value="'action_open_payment_onboarding_payment_acquirer'" />
|
||||
<t t-set="model" t-value="'res.company'" />
|
||||
<t t-set="id" t-value="company.id" />
|
||||
<t t-set="done" t-value="company.payment_acquirer_onboarding_done" />
|
||||
</t>
|
||||
</template>
|
||||
<!-- add it in the account invoice onboarding panel -->
|
||||
<template id="account_invoice_payment_acquirer_onboarding"
|
||||
name="account invoice payment acquirer onboarding"
|
||||
inherit_id="account.account_invoice_onboarding_panel">
|
||||
<xpath expr="//t[@name='sample_invoice_step']" position="before">
|
||||
<t t-call="payment.onboarding_payment_acquirer_step" name="payment_acquirer_step" />
|
||||
</xpath>
|
||||
</template>
|
||||
<!--PAYMENT ACQUIRER-->
|
||||
<record model="ir.ui.view" id="payment_acquirer_onboarding_wizard_form">
|
||||
<field name="name">payment.acquirer.onboarding.wizard.form</field>
|
||||
<field name="model">payment.acquirer.onboarding.wizard</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Choose a payment method">
|
||||
<div class="mb16">
|
||||
Configure our recommended payment methods or
|
||||
<a type="action" role="button" name="payment.action_payment_acquirer">
|
||||
see all other available methods.
|
||||
</a>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xs-1 mb16">
|
||||
<field name="paypal_checked" nolabel="1" />
|
||||
</div>
|
||||
<div>
|
||||
<label for="paypal_checked" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div attrs="{'invisible': [('paypal_checked', '=', False)]}"
|
||||
class="col-xs-offset-1">
|
||||
<a href="https://www.paypal.com" target="_blank">PayPal</a>
|
||||
is the easiest way to accept payments. It's easy to configure and it offers
|
||||
<a href="https://www.paypal.com/us/webapps/mpp/merchant-fees"
|
||||
target="_blank">
|
||||
a transparent fee structure.
|
||||
</a>
|
||||
<group>
|
||||
<field name="paypal_email_account"
|
||||
attrs="{'required': [('paypal_checked', '=', True)]}" />
|
||||
<field name="paypal_seller_account" />
|
||||
<field name="paypal_pdt_token"
|
||||
attrs="{'required': [('paypal_checked', '=', True)]}" />
|
||||
</group>
|
||||
<separator />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xs-1 mb16">
|
||||
<field name="stripe_checked" nolabel="1" />
|
||||
</div>
|
||||
<div>
|
||||
<label for="stripe_checked" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div attrs="{'invisible': [('stripe_checked', '=', False)]}"
|
||||
class="col-xs-offset-1">
|
||||
<a href="https://stripe.com" target="_blank">Stripe</a>
|
||||
is a payment provider with
|
||||
<a href="https://stripe.com/pricing" target="_blank">
|
||||
a simple fee structure and no hidden costs.
|
||||
</a>
|
||||
No other gateway or merchant account is required. We recommend this solution
|
||||
to manage credit card payments.
|
||||
<group>
|
||||
<field name="stripe_secret_key"
|
||||
attrs="{'required': [('stripe_checked', '=', True)]}" />
|
||||
<field name="stripe_publishable_key"
|
||||
attrs="{'required': [('stripe_checked', '=', True)]}" />
|
||||
<a href="https://dashboard.stripe.com/account/apikeys" target="_blank">
|
||||
<span class="fa fa-arrow-right">Get my Stripe keys</span>
|
||||
</a>
|
||||
</group>
|
||||
<separator />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xs-1">
|
||||
<field name="manual_checked" nolabel="1" />
|
||||
</div>
|
||||
<div>
|
||||
<label for="manual_checked" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div attrs="{'invisible': [('manual_checked', '=', False)]}"
|
||||
class="col-xs-offset-1">
|
||||
Provide customers with instructions to pay outside of your platform (wire
|
||||
transfer, cash on delivery, etc.).
|
||||
<group>
|
||||
<field name="manual_name"
|
||||
attrs="{'required': [('manual_checked', '=', True)]}" />
|
||||
<field name="manual_post_msg"
|
||||
attrs="{'required': [('manual_checked', '=', True)]}" />
|
||||
</group>
|
||||
</div>
|
||||
</div>
|
||||
<footer>
|
||||
<div class="mb16" name="skip_step_text">
|
||||
You can skip this step if invoices are pre-paid.
|
||||
</div>
|
||||
<button name="add_payment_methods" string="OK" class="oe_highlight"
|
||||
type="object" />
|
||||
<button name="action_skip_payment_onboarding_payment_acquirer_step" string="Skip this step"
|
||||
type="object" />
|
||||
<button special="cancel" string="Cancel" />
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
<record id="action_open_payment_onboarding_payment_acquirer_wizard" model="ir.actions.act_window">
|
||||
<field name="name">Choose a payment method</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">payment.acquirer.onboarding.wizard</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="view_id" ref="payment.payment_acquirer_onboarding_wizard_form" />
|
||||
<field name="target">new</field>
|
||||
</record>
|
||||
</odoo>
|
||||
@@ -0,0 +1 @@
|
||||
from . import payment_acquirer_onboarding_wizard
|
||||
@@ -0,0 +1,127 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import api, models, fields, _
|
||||
from odoo.exceptions import UserError
|
||||
|
||||
|
||||
class PaymentWizard(models.TransientModel):
|
||||
_name = 'payment.acquirer.onboarding.wizard'
|
||||
|
||||
paypal_checked = fields.Boolean('Paypal', default=lambda self: self._get_default_payment_acquirer_onboarding_value('paypal_checked'))
|
||||
paypal_email_account = fields.Char('Paypal Email ID', default=lambda self: self._get_default_payment_acquirer_onboarding_value('paypal_email_account'))
|
||||
paypal_seller_account = fields.Char('Paypal Merchant ID', default=lambda self: self._get_default_payment_acquirer_onboarding_value('paypal_seller_account'))
|
||||
paypal_pdt_token = fields.Char('Paypal PDT Token', default=lambda self: self._get_default_payment_acquirer_onboarding_value('paypal_pdt_token'))
|
||||
|
||||
stripe_checked = fields.Boolean('Credit Card (via Stripe)', default=lambda self: self._get_default_payment_acquirer_onboarding_value('stripe_checked'))
|
||||
stripe_secret_key = fields.Char(default=lambda self: self._get_default_payment_acquirer_onboarding_value('stripe_secret_key'))
|
||||
stripe_publishable_key = fields.Char(default=lambda self: self._get_default_payment_acquirer_onboarding_value('stripe_publishable_key'))
|
||||
|
||||
manual_checked = fields.Boolean('Manual Payment', default=lambda self: self._get_default_payment_acquirer_onboarding_value('manual_checked'))
|
||||
manual_name = fields.Char('Method name', default=lambda self: self._get_default_payment_acquirer_onboarding_value('manual_name'))
|
||||
manual_post_msg = fields.Html('Payment instructions', default=lambda self: self._get_default_payment_acquirer_onboarding_value('manual_post_msg'))
|
||||
|
||||
_payment_acquirer_onboarding_cache = {}
|
||||
_data_fetched = False
|
||||
|
||||
def _get_manual_payment(self, env=None):
|
||||
if env is None:
|
||||
env = self.env
|
||||
return env['payment.acquirer'].search(
|
||||
[('provider', '=', 'transfer'),
|
||||
('sequence', '=', 2),
|
||||
('company_id', '=', self.env.user.company_id.id)], limit=1)
|
||||
|
||||
def _get_default_payment_acquirer_onboarding_value(self, key):
|
||||
if not self.env.user._is_admin():
|
||||
raise UserError(_('Only administators can access this data.'))
|
||||
|
||||
if self._data_fetched:
|
||||
return self._payment_acquirer_onboarding_cache.get(key, '')
|
||||
|
||||
self._data_fetched = True
|
||||
|
||||
installed_modules = self.env['ir.module.module'].sudo().search([
|
||||
('name', 'in', ('payment_paypal', 'payment_stripe')),
|
||||
('state', '=', 'installed'),
|
||||
]).mapped('name')
|
||||
|
||||
if 'payment_paypal' in installed_modules:
|
||||
self._payment_acquirer_onboarding_cache['paypal_checked'] = True
|
||||
acquirer = self.env.ref('payment.payment_acquirer_paypal')
|
||||
self._payment_acquirer_onboarding_cache['paypal_email_account'] = acquirer['paypal_email_account']
|
||||
self._payment_acquirer_onboarding_cache['paypal_seller_account'] = acquirer['paypal_seller_account']
|
||||
self._payment_acquirer_onboarding_cache['paypal_pdt_token'] = acquirer['paypal_pdt_token']
|
||||
|
||||
if 'payment_stripe' in installed_modules:
|
||||
self._payment_acquirer_onboarding_cache['stripe_checked'] = True
|
||||
acquirer = self.env.ref('payment.payment_acquirer_stripe')
|
||||
self._payment_acquirer_onboarding_cache['stripe_secret_key'] = acquirer['stripe_secret_key']
|
||||
self._payment_acquirer_onboarding_cache['stripe_publishable_key'] = acquirer['stripe_publishable_key']
|
||||
|
||||
manual_payment = self._get_manual_payment()
|
||||
# manual payment is checked if the user has renamed it
|
||||
self._payment_acquirer_onboarding_cache['manual_checked'] = \
|
||||
(manual_payment['name'] != 'Wire Transfer')
|
||||
self._payment_acquirer_onboarding_cache['manual_name'] = manual_payment['name']
|
||||
self._payment_acquirer_onboarding_cache['manual_post_msg'] = manual_payment['post_msg']
|
||||
|
||||
return self._payment_acquirer_onboarding_cache.get(key, '')
|
||||
|
||||
def _install_module(self, module_name):
|
||||
module = self.env['ir.module.module'].sudo().search([('name', '=', module_name)])
|
||||
if module.state not in ('installed', 'to install', 'to upgrade'):
|
||||
module.button_immediate_install()
|
||||
|
||||
def _hook_on_save_onboarding_payment_acquirer(self):
|
||||
# if any payment method is selected activate "Online Payment" in invoicing settings
|
||||
self._install_module('account_payment')
|
||||
|
||||
@api.multi
|
||||
def add_payment_methods(self):
|
||||
if self.paypal_checked is True:
|
||||
self._install_module('payment_paypal')
|
||||
|
||||
if self.stripe_checked is True:
|
||||
self._install_module('payment_stripe')
|
||||
|
||||
if self.paypal_checked is True or self.stripe_checked is True or self.manual_checked is True:
|
||||
|
||||
# the wizard is inherited in `sale`
|
||||
self._hook_on_save_onboarding_payment_acquirer()
|
||||
|
||||
# create a new env including the freshly installed module(s)
|
||||
new_env = api.Environment(self.env.cr, self.env.uid, self.env.context)
|
||||
|
||||
if self.paypal_checked is True:
|
||||
new_env.ref('payment.payment_acquirer_paypal').write({
|
||||
'paypal_email_account': self.paypal_email_account,
|
||||
'paypal_seller_account': self.paypal_seller_account,
|
||||
'paypal_pdt_token': self.paypal_pdt_token,
|
||||
'website_published': True,
|
||||
})
|
||||
if self.stripe_checked is True:
|
||||
new_env.ref('payment.payment_acquirer_stripe').write({
|
||||
'stripe_secret_key': self.stripe_secret_key,
|
||||
'stripe_publishable_key': self.stripe_publishable_key,
|
||||
'website_published': True,
|
||||
})
|
||||
if self.manual_checked is True:
|
||||
self._get_manual_payment(new_env).write({
|
||||
'name': self.manual_name,
|
||||
'post_msg': self.manual_post_msg,
|
||||
'website_published': True,
|
||||
})
|
||||
self._set_payment_acquirer_onboarding_step_done()
|
||||
# delete wizard data immediately to get rid of residual credentials
|
||||
self.unlink()
|
||||
|
||||
return {'type': 'ir.actions.act_window_close'}
|
||||
|
||||
@api.multi
|
||||
def action_skip_payment_onboarding_payment_acquirer_step(self):
|
||||
self._set_payment_acquirer_onboarding_step_done()
|
||||
return {'type': 'ir.actions.act_window_close'}
|
||||
|
||||
def _set_payment_acquirer_onboarding_step_done(self):
|
||||
self.env.user.company_id.write({'payment_acquirer_onboarding_done': True})
|
||||
Reference in New Issue
Block a user