[REF] website_portal => website_portal, website_portal_sale
Split of website_portal into a generic (and mostly empty) website_portal and a sales-related website_portal_sale (sales order, quotes, invoices) This allows other modules to extend website_portal without depending on sales
This commit is contained in:
committed by
Antony Lesuisse
parent
1e90257e58
commit
5f48cb992e
@@ -77,7 +77,7 @@
|
||||
</template>
|
||||
|
||||
<template id="pay_meth_link" inherit_id="website_portal.account">
|
||||
<xpath expr="//div[@id='details']" position="inside">
|
||||
<xpath expr="//div[@class='o_my_details']" position="inside">
|
||||
<a href="/my/payment_method">Manage your payment methods</a>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
@@ -9,16 +9,10 @@ Allows your customers to manage their account from a beautiful web interface.
|
||||
'author': 'Odoo SA',
|
||||
'website': 'https://www.odoo.com/',
|
||||
'depends': [
|
||||
'sale',
|
||||
'website',
|
||||
],
|
||||
'data': [
|
||||
'views/templates.xml',
|
||||
],
|
||||
'qweb': [
|
||||
],
|
||||
'demo': [
|
||||
'data/demo.xml'
|
||||
],
|
||||
'installable': True,
|
||||
}
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import datetime
|
||||
|
||||
from openerp import http
|
||||
from openerp.http import request
|
||||
from openerp import tools
|
||||
@@ -11,61 +9,20 @@ class website_account(http.Controller):
|
||||
@http.route(['/my', '/my/home'], type='http', auth="public", website=True)
|
||||
def account(self):
|
||||
partner = request.env.user.partner_id
|
||||
values = {
|
||||
'date': datetime.date.today().strftime('%Y-%m-%d')
|
||||
}
|
||||
|
||||
res_sale_order = request.env['sale.order']
|
||||
res_invoices = request.env['account.invoice']
|
||||
quotations = res_sale_order.search([
|
||||
('partner_id.id', '=', partner.id),
|
||||
('state', 'in', ['sent', 'cancel'])
|
||||
])
|
||||
orders = res_sale_order.search([
|
||||
('partner_id.id', '=', partner.id),
|
||||
('state', 'in', ['progress', 'manual', 'shipping_except', 'invoice_except', 'done'])
|
||||
])
|
||||
invoices = res_invoices.search([
|
||||
('partner_id.id', '=', partner.id),
|
||||
('state', 'in', ['open', 'paid', 'cancelled'])
|
||||
])
|
||||
|
||||
values.update({
|
||||
'quotations': quotations,
|
||||
'orders': orders,
|
||||
'invoices': invoices
|
||||
})
|
||||
|
||||
# get customer sales rep
|
||||
if partner.user_id:
|
||||
sales_rep = partner.user_id
|
||||
else:
|
||||
sales_rep = False
|
||||
values.update({
|
||||
values = {
|
||||
'sales_rep': sales_rep,
|
||||
'company': request.website.company_id,
|
||||
'user': request.env.user
|
||||
})
|
||||
}
|
||||
|
||||
return request.website.render("website_portal.account", values)
|
||||
|
||||
@http.route(['/my/orders/<int:order>'], type='http', auth="user", website=True)
|
||||
def orders_followup(self, order=None):
|
||||
partner = request.env['res.users'].browse(request.uid).partner_id
|
||||
domain = [
|
||||
('partner_id.id', '=', partner.id),
|
||||
('state', 'not in', ['draft', 'cancel']),
|
||||
('id', '=', order)
|
||||
]
|
||||
order = request.env['sale.order'].search(domain)
|
||||
invoiced_lines = request.env['account.invoice.line'].search([('invoice_id', 'in', order.invoice_ids.ids)])
|
||||
order_invoice_lines = {il.product_id.id: il.invoice_id for il in invoiced_lines}
|
||||
|
||||
return request.website.render("website_portal.orders_followup", {
|
||||
'order': order.sudo(),
|
||||
'order_invoice_lines': order_invoice_lines,
|
||||
})
|
||||
|
||||
@http.route(['/my/account'], type='http', auth='user', website=True)
|
||||
def details(self, redirect=None, **post):
|
||||
partner = request.env['res.users'].browse(request.uid).partner_id
|
||||
@@ -123,7 +80,7 @@ class website_account(http.Controller):
|
||||
# quick and partial off-line checksum validation
|
||||
check_func = request.env["res.partner"].simple_vat_check
|
||||
vat_country, vat_number = request.env["res.partner"]._split_vat(data.get("vat"))
|
||||
if not check_func(vat_country, vat_number): # simple_vat_check
|
||||
if not check_func(vat_country, vat_number): # simple_vat_check
|
||||
error["vat"] = 'error'
|
||||
# error message for empty required fields
|
||||
if [err for err in error.values() if err == 'missing']:
|
||||
|
||||
@@ -1,24 +1,23 @@
|
||||
odoo.define('website_portal', function(require) {
|
||||
'use strict';
|
||||
require('website.website');
|
||||
|
||||
var base = require('web_editor.base');
|
||||
var qweb = require('qweb');
|
||||
base.ready().done(function() {
|
||||
if(!$('.o_website_portal_details, .o_my_show_more').length) {
|
||||
return $.Deferred().reject("DOM doesn't contain '.o_website_portal_details' or '.o_my_show_more'");
|
||||
}
|
||||
|
||||
$('.oe_website_portal').on('change', "select[name='country_id']", function () {
|
||||
var $select = $("select[name='state_id']");
|
||||
$select.find("option:not(:first)").hide();
|
||||
var nb = $select.find("option[data-country_id="+($(this).val() || 0)+"]").show().size();
|
||||
$select.parent().toggle(nb>1);
|
||||
});
|
||||
$('.oe_website_portal').find("select[name='country_id']").change();
|
||||
|
||||
$('.wp_show_more').on('click', function(ev) {
|
||||
ev.preventDefault();
|
||||
$(this).parents('table').find(".to_hide").toggleClass('hidden');
|
||||
$(this).find('span').toggleClass('hidden');
|
||||
});
|
||||
|
||||
$('.o_website_portal_details').on('change', "select[name='country_id']", function () {
|
||||
var $select = $("select[name='state_id']");
|
||||
$select.find("option:not(:first)").hide();
|
||||
var nb = $select.find("option[data-country_id="+($(this).val() || 0)+"]").show().size();
|
||||
$select.parent().toggle(nb>1);
|
||||
});
|
||||
$('.o_website_portal_details').find("select[name='country_id']").change();
|
||||
|
||||
$('.o_my_show_more').on('click', function(ev) {
|
||||
ev.preventDefault();
|
||||
$(this).parents('table').find(".to_hide").toggleClass('hidden');
|
||||
$(this).find('span').toggleClass('hidden');
|
||||
});
|
||||
});
|
||||
|
||||
+1
-13
@@ -1,16 +1,4 @@
|
||||
/* ---- My Orders page ---- */
|
||||
|
||||
.orders_vertical_align {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
|
||||
.orders_label_text_align {
|
||||
vertical-align: 15%;
|
||||
}
|
||||
|
||||
.status_table {
|
||||
.o_my_status_table {
|
||||
th,td {
|
||||
text-align: right;
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
<template id="assets_frontend" inherit_id="website.assets_frontend" name="Account Manager">
|
||||
<xpath expr="." position="inside">
|
||||
<link rel='stylesheet' href='/website_portal/static/src/css/website_portal.less'/>
|
||||
<link rel='stylesheet' href='/website_portal/static/src/less/website_portal.less'/>
|
||||
<script type="text/javascript" src="/website_portal/static/src/js/website_portal.js"></script>
|
||||
</xpath>
|
||||
</template>
|
||||
@@ -12,29 +12,29 @@
|
||||
<t t-call="website.layout">
|
||||
<div id="wrap">
|
||||
<div class="container mb64">
|
||||
<div class="col-md-8" id="documents_list">
|
||||
<t t-call="website_portal.quotations" />
|
||||
<t t-call="website_portal.sale_orders" />
|
||||
<t t-call="website_portal.invoices" />
|
||||
<div class="col-md-8 o_my_documents">
|
||||
<div class="oe_structure"/>
|
||||
</div>
|
||||
<div t-if="sales_rep" class="col-md-3">
|
||||
<t t-call="website_portal.contact" />
|
||||
<div class="oe_structure"/>
|
||||
</div>
|
||||
<div class="col-md-3 col-md-offset-1" id="details">
|
||||
<h3 class="page-header">Your Details <a href="/my/account" class="btn btn-default btn-xs">Change</a></h3>
|
||||
<div t-field="user.partner_id" t-field-options='{"widget": "contact", "fields": ["email", "phone", "address", "name"]}'/>
|
||||
<div class="col-md-3 col-md-offset-1 o_my_sidebar">
|
||||
<div class="o_my_details">
|
||||
<h3 class="page-header">Your Details <a href="/my/account" class="btn btn-default btn-xs">Change</a></h3>
|
||||
<div t-field="user.partner_id" t-field-options='{"widget": "contact", "fields": ["email", "phone", "address", "name"]}'/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="oe_structure"/>
|
||||
<div class="col-md-12 oe_structure"/>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<template id="website_portal.custom_panel" inherit_id='website_portal.account' customize_show="True" name="Editable Panel" active="False">
|
||||
<xpath expr="//div[@class='col-md-3']" position="after">
|
||||
<div class="col-md-3">
|
||||
<h3 class="page-header">You Custom Title</h3>
|
||||
<xpath expr="//div[@class='o_my_sidebar']" position="inside">
|
||||
<div class="oe_structure">
|
||||
<h3 class="page-header">Custom Panel</h3>
|
||||
<p>Place your content here.</p>
|
||||
</div>
|
||||
</xpath>
|
||||
@@ -48,306 +48,6 @@
|
||||
<p t-esc="sales_rep.city"/>
|
||||
</template>
|
||||
|
||||
<template id="quotations" name="Quotations">
|
||||
<h3 class="page-header">Your Quotes</h3>
|
||||
<t t-if="not quotations">
|
||||
<p>There are currently no quotes for your account.</p>
|
||||
</t>
|
||||
<t t-if="quotations">
|
||||
<table class="table table-hover status_table">
|
||||
<thead>
|
||||
<tr class="active">
|
||||
<th>Quotation #</th>
|
||||
<th>Valid Until</th>
|
||||
<th></th>
|
||||
<th>Total</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<t t-foreach="quotations" t-as="quotation">
|
||||
<tr t-att-class="'hidden to_hide' if quotation.state!='sent' and quotation_index > 4 else ''">
|
||||
<td>
|
||||
<a t-att-href="'/my/orders/'+str(quotation.id)"><t t-esc="quotation.name"/></a>
|
||||
</td>
|
||||
<td><span t-field="quotation.validity_date"/></td>
|
||||
<td>
|
||||
<t t-if="quotation.state == 'cancel'">
|
||||
<span class="label label-default"><i class="fa fa-fw fa-remove"/> Cancelled</span>
|
||||
</t>
|
||||
<t t-if="quotation.validity_date and quotation.validity_date < date">
|
||||
<span class="label label-default"><i class="fa fa-fw fa-clock-à"/> Expired</span>
|
||||
</t>
|
||||
</td>
|
||||
<td><span t-esc="quotation.amount_total" t-esc-options='{"widget": "monetary", "display_currency": "quotation.pricelist_id.currency_id"}'/>
|
||||
</td>
|
||||
</tr>
|
||||
</t>
|
||||
<tr t-att-class="'hidden' if len(quotations) < 5 else ''">
|
||||
<td colspan="5"><a href="" class="wp_show_more btn btn-xs btn-default"><span>Show more</span><span class="hidden">Show less</span></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<template id="sale_orders" name="Sales Orders">
|
||||
<h3 class="page-header">Your Orders</h3>
|
||||
<t t-if="not orders">
|
||||
<p>There are currently no orders for your account.</p>
|
||||
</t>
|
||||
<t t-if="orders">
|
||||
<table class="table table-hover status_table">
|
||||
<thead>
|
||||
<tr class="active">
|
||||
<th>Sale Order #</th>
|
||||
<th>Confirmation Date</th>
|
||||
<th></th>
|
||||
<th>Total</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<t t-foreach="orders" t-as="order">
|
||||
<tr t-att-class="'hidden to_hide' if order.state not in ['manual', 'progress'] and order_index > 4 else ''">
|
||||
<td>
|
||||
<a t-att-href="'/my/orders/'+str(order.id)"><t t-esc="order.name"/></a>
|
||||
</td>
|
||||
<td><span t-field="order.date_confirm"/></td>
|
||||
<td>
|
||||
<t t-if="order.state == 'progress'">
|
||||
<span class="label label-info"><i class="fa fa-fw fa-clock-o"/> Invoiced</span>
|
||||
</t>
|
||||
<t t-if="order.state in ['shipping_except','invoice_except']">
|
||||
<span class="label label-danger"><i class="fa fa-fw fa-warning"/> Problem</span>
|
||||
</t>
|
||||
<t t-if="order.state == 'done'">
|
||||
<span class="label label-default"><i class="fa fa-fw fa-check"/> Done</span>
|
||||
</t>
|
||||
</td>
|
||||
<td><span t-esc="order.amount_total" t-esc-options='{"widget": "monetary", "display_currency": "order.pricelist_id.currency_id"}'/></td>
|
||||
</tr>
|
||||
</t>
|
||||
<tr t-att-class="'hidden' if len(orders) < 5 else ''">
|
||||
<td colspan="4"><a href="" class="wp_show_more btn btn-xs btn-default"><span>Show more</span><span class="hidden">Show less</span></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<template id="invoices" name="Invoices and Payments">
|
||||
<h3 class="page-header">Your Invoices and Payments</h3>
|
||||
<t t-if="not invoices">
|
||||
<p>There are currently no invoices for your account.</p>
|
||||
</t>
|
||||
<t t-if="invoices">
|
||||
<table class="table table-hover status_table">
|
||||
<thead>
|
||||
<tr class="active">
|
||||
<th>Invoice #</th>
|
||||
<th>Invoice Date</th>
|
||||
<th>Due Date</th>
|
||||
<th></th>
|
||||
<th>Total</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<t t-foreach="invoices" t-as="invoice">
|
||||
<tr t-att-class="'hidden to_hide' if invoice.state!='open' and invoice_index > 4 else ''">
|
||||
<td>
|
||||
<a t-att-href="'/report/pdf/account.report_invoice/'+str(invoice.id)"><t t-esc="invoice.number"/></a>
|
||||
</td>
|
||||
<td><span t-field="invoice.date_invoice"/></td>
|
||||
<td><span t-field="invoice.date_due"/></td>
|
||||
<td>
|
||||
<t t-if="invoice.state == 'open'">
|
||||
<span class="label label-info"><i class="fa fa-fw fa-clock-o"/> Waiting for Payment</span>
|
||||
</t>
|
||||
<t t-if="invoice.state == 'paid'">
|
||||
<span class="label label-default"><i class="fa fa-fw fa-check"/> Paid</span>
|
||||
</t>
|
||||
<t t-if="invoice.state == 'cancel'">
|
||||
<span class="label label-default"><i class="fa fa-fw fa-remove"/> Cancelled</span>
|
||||
</t>
|
||||
</td>
|
||||
<td><span t-esc="invoice.amount_total" t-esc-options='{"widget": "monetary", "display_currency": "invoice.currency_id"}'/></td>
|
||||
</tr>
|
||||
</t>
|
||||
<tr t-att-class="'hidden' if len(invoices) < 5 else ''">
|
||||
<td colspan="5"><a href="" class="wp_show_more btn btn-xs btn-default"><span>Show more</span><span class="hidden">Show less</span></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<template id="orders_followup" name="Sales Order">
|
||||
<t t-call="website.layout">
|
||||
<div id="wrap">
|
||||
<div class="container">
|
||||
<div class="oe_structure">
|
||||
<div class="row">
|
||||
<div class="col-sm-4">
|
||||
<ol class="breadcrumb mt8">
|
||||
<li><a href="/my/home">My Account</a></li>
|
||||
<li>
|
||||
<t t-if="order.state == 'sent'">
|
||||
Quotation
|
||||
</t>
|
||||
<t t-if="order.state != 'sent'">
|
||||
Order
|
||||
</t>
|
||||
<t t-esc="order.name"/>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="optional_placeholder"></div>
|
||||
<div class="container">
|
||||
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<h4>
|
||||
<t t-if="order.state == 'sent'">
|
||||
Quotation
|
||||
</t>
|
||||
<t t-if="order.state != 'sent'">
|
||||
Order
|
||||
</t>
|
||||
<span t-esc="order.name"/>
|
||||
</h4>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<!-- <hr/> -->
|
||||
<div class="mb8">
|
||||
<strong>Date:</strong> <span t-field="order.create_date" t-field-options='{"widget": "date"}'/>
|
||||
</div>
|
||||
<div class='row'>
|
||||
<div class="col-md-6">
|
||||
<div>
|
||||
<strong>Invoicing Address</strong>
|
||||
</div>
|
||||
<div>
|
||||
<address t-field="order.partner_invoice_id" t-field-options='{"widget": "contact", "fields": ["address", "name"], "no_marker": true}'/>
|
||||
</div>
|
||||
<t t-set="invoices" t-value="[i for i in order.invoice_ids if i.state not in ['draft', 'cancel']]"/>
|
||||
<t t-if="invoices">
|
||||
<div>
|
||||
<strong>Invoices</strong>
|
||||
</div>
|
||||
<div>
|
||||
<t t-foreach="invoices" t-as="i">
|
||||
<t t-set="report_url" t-value="'/report/pdf/account.report_invoice/%s' % i.id"/>
|
||||
<div>
|
||||
<a t-att-href="report_url"><span class="fa fa-download"/></a>
|
||||
<a t-att-href="report_url"><span t-esc="i.number"/></a>
|
||||
<span class="text-muted" t-field="i.date_invoice"/>
|
||||
<t t-if="i.state == 'paid'">
|
||||
<span class="label label-success orders_label_text_align"><i class="fa fa-fw fa-check"/> Paid</span>
|
||||
</t>
|
||||
<t t-if="i.state != 'paid'">
|
||||
<span class="label label-info orders_label_text_align"><i class="fa fa-fw fa-clock-o"/> Waiting</span>
|
||||
</t>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
<div id="shipping_address" class="col-md-6">
|
||||
<div>
|
||||
<strong>Shipping Address</strong>
|
||||
</div>
|
||||
<div>
|
||||
<address t-field="order.partner_shipping_id" t-field-options='{"widget": "contact", "fields": ["address", "name"], "no_marker": true}'/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr/>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<strong>Product</strong>
|
||||
</div>
|
||||
<div class="col-md-2 text-right">
|
||||
<strong>Unit Price</strong>
|
||||
</div>
|
||||
<div class="col-md-2 text-right">
|
||||
<strong>Quantity</strong>
|
||||
</div>
|
||||
<div class="col-md-2 text-right">
|
||||
<strong>Subtotal</strong>
|
||||
</div>
|
||||
</div>
|
||||
<t t-foreach="order.order_line" t-as="ol">
|
||||
<div class="row orders_vertical_align">
|
||||
<div class="col-md-1 text-center">
|
||||
<img t-att-src="'/web_editor/image/product.product/%s/image_small/48x48' % ol.product_id.id"/>
|
||||
</div>
|
||||
<div id='product_name' class="col-md-5">
|
||||
<span t-esc="ol.product_id.name"/>
|
||||
</div>
|
||||
<div class="col-md-2 text-right">
|
||||
<span t-field="ol.price_unit" t-field-options='{"widget": "monetary", "display_currency": "order.pricelist_id.currency_id"}'/>
|
||||
</div>
|
||||
<div class="col-md-2 text-right">
|
||||
<t t-if="ol._name == 'sale.order.line'">
|
||||
<span t-esc="ol.product_uom_qty"/>
|
||||
</t>
|
||||
<t t-if="ol._name == 'account.invoice.line'">
|
||||
<span t-esc="ol.quantity"/>
|
||||
</t>
|
||||
</div>
|
||||
<div class="col-md-2 text-right">
|
||||
<span t-field="ol.price_subtotal" t-field-options='{"widget": "monetary", "display_currency": "order.pricelist_id.currency_id"}'/>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<hr/>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div>
|
||||
<strong>Contact</strong>
|
||||
</div>
|
||||
<div t-field="order.user_id.partner_id" t-field-options='{"widget": "contact", "fields": ["email", "phone"]}'/>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="row">
|
||||
<div class="col-md-10 text-right">
|
||||
Untaxed Amount:
|
||||
</div>
|
||||
<div class="col-md-2 text-right">
|
||||
<span t-field="order.amount_untaxed" t-field-options='{"widget": "monetary", "display_currency": "order.pricelist_id.currency_id"}'/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-10 text-right">
|
||||
Taxes:
|
||||
</div>
|
||||
<div class="col-md-2 text-right">
|
||||
<span t-field="order.amount_tax" t-field-options='{"widget": "monetary", "display_currency": "order.pricelist_id.currency_id"}'/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-10 text-right">
|
||||
<strong>Total:</strong>
|
||||
</div>
|
||||
<div class="col-md-2 text-right">
|
||||
<strong><span t-field="order.amount_total" t-field-options='{"widget": "monetary", "display_currency": "order.pricelist_id.currency_id"}'/></strong>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="oe_structure mb32"/>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<template id="details">
|
||||
<t t-call="website.layout">
|
||||
<t t-set="additional_title">Contact Details</t>
|
||||
@@ -363,7 +63,7 @@
|
||||
</div>
|
||||
<h1>Contact Details</h1>
|
||||
<form action="/my/account" method="post">
|
||||
<div class="row oe_website_portal">
|
||||
<div class="row o_website_portal_details">
|
||||
<div class="col-md-8">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
@@ -450,19 +150,4 @@
|
||||
<li><a href="/my/home" role="menuitem">My Account</a></li>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<template id="sale_backend_link" inherit_id='website_portal.sale_orders' customize_show="True" name="Link to Sales Backend" active="False">
|
||||
<xpath expr="//h3[@class='page-header']" position="inside">
|
||||
<a href="/web#action=portal_sale.action_orders_portal" target="_blank" class="btn btn-default btn-xs pull-right"> Access the complete Sale application</a>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<template id="sales_backend_access" inherit_id='website_portal.orders_followup' customize_show="True" name="Backend Access" active="False">
|
||||
<xpath expr="//div[@id='optional_placeholder']" position="inside">
|
||||
<h4 class="text-muted text-center mt64 mb64">
|
||||
If you wish to access the complete application to manage your orders, you can follow
|
||||
<a href="/web#action=portal_sale.action_orders_portal">this link</a>.
|
||||
</h4>
|
||||
</xpath>
|
||||
</template>
|
||||
</odoo>
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
import controllers
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
'name': 'Website Portal for Sales',
|
||||
'category': 'Website',
|
||||
'summary': 'Add your sales document in the frontend portal (sales order, quotations, invoices)',
|
||||
'version': '1.0',
|
||||
'description': """
|
||||
Add your sales document in the frontend portal. Your customers will be able to connect to their portal to see the list (and the state) of their invoices (pdf report), sales orders and quotations (web pages).
|
||||
""",
|
||||
'author': 'Odoo SA',
|
||||
'website': 'https://www.odoo.com/',
|
||||
'depends': [
|
||||
'sale',
|
||||
'website_portal',
|
||||
],
|
||||
'data': [
|
||||
'views/templates.xml',
|
||||
],
|
||||
'demo': [
|
||||
'data/demo.xml'
|
||||
],
|
||||
'installable': True,
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
import main
|
||||
@@ -0,0 +1,55 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import datetime
|
||||
|
||||
from openerp import http
|
||||
from openerp.http import request
|
||||
|
||||
from openerp.addons.website_portal.controllers.main import website_account
|
||||
|
||||
|
||||
class website_account(website_account):
|
||||
@http.route(['/my/home'], type='http', auth="user", website=True)
|
||||
def account(self, **kw):
|
||||
""" Add sales documents to main account page """
|
||||
response = super(website_account, self).account()
|
||||
partner = request.env.user.partner_id
|
||||
|
||||
res_sale_order = request.env['sale.order']
|
||||
res_invoices = request.env['account.invoice']
|
||||
quotations = res_sale_order.search([
|
||||
('partner_id.id', '=', partner.id),
|
||||
('state', 'in', ['sent', 'cancel'])
|
||||
])
|
||||
orders = res_sale_order.search([
|
||||
('partner_id.id', '=', partner.id),
|
||||
('state', 'in', ['progress', 'manual', 'shipping_except', 'invoice_except', 'done'])
|
||||
])
|
||||
invoices = res_invoices.search([
|
||||
('partner_id.id', '=', partner.id),
|
||||
('state', 'in', ['open', 'paid', 'cancelled'])
|
||||
])
|
||||
|
||||
response.qcontext.update({
|
||||
'date': datetime.date.today().strftime('%Y-%m-%d'),
|
||||
'quotations': quotations,
|
||||
'orders': orders,
|
||||
'invoices': invoices,
|
||||
})
|
||||
return response
|
||||
|
||||
@http.route(['/my/orders/<int:order>'], type='http', auth="user", website=True)
|
||||
def orders_followup(self, order=None):
|
||||
partner = request.env['res.users'].browse(request.uid).partner_id
|
||||
domain = [
|
||||
('partner_id.id', '=', partner.id),
|
||||
('state', 'not in', ['draft', 'cancel']),
|
||||
('id', '=', order)
|
||||
]
|
||||
order = request.env['sale.order'].search(domain)
|
||||
invoiced_lines = request.env['account.invoice.line'].search([('invoice_id', 'in', order.invoice_ids.ids)])
|
||||
order_invoice_lines = {il.product_id.id: il.invoice_id for il in invoiced_lines}
|
||||
|
||||
return request.website.render("website_portal_sale.orders_followup", {
|
||||
'order': order.sudo(),
|
||||
'order_invoice_lines': order_invoice_lines,
|
||||
})
|
||||
@@ -0,0 +1,11 @@
|
||||
/* ---- My Orders page ---- */
|
||||
|
||||
.orders_vertical_align {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
|
||||
.orders_label_text_align {
|
||||
vertical-align: 15%;
|
||||
}
|
||||
@@ -0,0 +1,332 @@
|
||||
<odoo>
|
||||
|
||||
<template id="assets_frontend" inherit_id="website.assets_frontend" name="Website Portal Sale">
|
||||
<xpath expr="." position="inside">
|
||||
<link rel='stylesheet' href='/website_portal_sale/static/src/less/website_portal_sale.less'/>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<template id="account" name="Account" inherit_id="website_portal.account">
|
||||
<xpath expr="//div[contains(@class,'o_my_documents')]" position="inside">
|
||||
<t t-call="website_portal_sale.quotations" />
|
||||
<t t-call="website_portal_sale.sale_orders" />
|
||||
<t t-call="website_portal_sale.invoices" />
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<template id="quotations" name="Quotations">
|
||||
<h3 class="page-header">Your Quotes</h3>
|
||||
<t t-if="not quotations">
|
||||
<p>There are currently no quotes for your account.</p>
|
||||
</t>
|
||||
<t t-if="quotations">
|
||||
<table class="table table-hover o_my_status_table">
|
||||
<thead>
|
||||
<tr class="active">
|
||||
<th>Quotation #</th>
|
||||
<th>Valid Until</th>
|
||||
<th></th>
|
||||
<th>Total</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<t t-foreach="quotations" t-as="quotation">
|
||||
<tr t-att-class="'hidden to_hide' if quotation.state!='sent' and quotation_index > 4 else ''">
|
||||
<td>
|
||||
<a t-att-href="'/my/orders/'+str(quotation.id)"><t t-esc="quotation.name"/></a>
|
||||
</td>
|
||||
<td><span t-field="quotation.validity_date"/></td>
|
||||
<td>
|
||||
<t t-if="quotation.state == 'cancel'">
|
||||
<span class="label label-default"><i class="fa fa-fw fa-remove"/> Cancelled</span>
|
||||
</t>
|
||||
<t t-if="quotation.validity_date and quotation.validity_date < date">
|
||||
<span class="label label-default"><i class="fa fa-fw fa-clock-à"/> Expired</span>
|
||||
</t>
|
||||
</td>
|
||||
<td><span t-esc="quotation.amount_total" t-esc-options='{"widget": "monetary", "display_currency": "quotation.pricelist_id.currency_id"}'/>
|
||||
</td>
|
||||
</tr>
|
||||
</t>
|
||||
<tr t-att-class="'hidden' if len(quotations) < 5 else ''">
|
||||
<td colspan="5"><a href="" class="o_my_show_more btn btn-xs btn-default"><span>Show more</span><span class="hidden">Show less</span></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<template id="sale_orders" name="Sales Orders">
|
||||
<h3 class="page-header">Your Orders</h3>
|
||||
<t t-if="not orders">
|
||||
<p>There are currently no orders for your account.</p>
|
||||
</t>
|
||||
<t t-if="orders">
|
||||
<table class="table table-hover o_my_status_table">
|
||||
<thead>
|
||||
<tr class="active">
|
||||
<th>Sale Order #</th>
|
||||
<th>Confirmation Date</th>
|
||||
<th></th>
|
||||
<th>Total</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<t t-foreach="orders" t-as="order">
|
||||
<tr t-att-class="'hidden to_hide' if order.state not in ['manual', 'progress'] and order_index > 4 else ''">
|
||||
<td>
|
||||
<a t-att-href="'/my/orders/'+str(order.id)"><t t-esc="order.name"/></a>
|
||||
</td>
|
||||
<td><span t-field="order.date_confirm"/></td>
|
||||
<td>
|
||||
<t t-if="order.state == 'progress'">
|
||||
<span class="label label-info"><i class="fa fa-fw fa-clock-o"/> Invoiced</span>
|
||||
</t>
|
||||
<t t-if="order.state in ['shipping_except','invoice_except']">
|
||||
<span class="label label-danger"><i class="fa fa-fw fa-warning"/> Problem</span>
|
||||
</t>
|
||||
<t t-if="order.state == 'done'">
|
||||
<span class="label label-default"><i class="fa fa-fw fa-check"/> Done</span>
|
||||
</t>
|
||||
</td>
|
||||
<td><span t-esc="order.amount_total" t-esc-options='{"widget": "monetary", "display_currency": "order.pricelist_id.currency_id"}'/></td>
|
||||
</tr>
|
||||
</t>
|
||||
<tr t-att-class="'hidden' if len(orders) < 5 else ''">
|
||||
<td colspan="4"><a href="" class="o_my_show_more btn btn-xs btn-default"><span>Show more</span><span class="hidden">Show less</span></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<template id="invoices" name="Invoices and Payments">
|
||||
<h3 class="page-header">Your Invoices and Payments</h3>
|
||||
<t t-if="not invoices">
|
||||
<p>There are currently no invoices for your account.</p>
|
||||
</t>
|
||||
<t t-if="invoices">
|
||||
<table class="table table-hover o_my_status_table">
|
||||
<thead>
|
||||
<tr class="active">
|
||||
<th>Invoice #</th>
|
||||
<th>Invoice Date</th>
|
||||
<th>Due Date</th>
|
||||
<th></th>
|
||||
<th>Total</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<t t-foreach="invoices" t-as="invoice">
|
||||
<tr t-att-class="'hidden to_hide' if invoice.state!='open' and invoice_index > 4 else ''">
|
||||
<td>
|
||||
<a t-att-href="'/report/pdf/account.report_invoice/'+str(invoice.id)"><t t-esc="invoice.number"/></a>
|
||||
</td>
|
||||
<td><span t-field="invoice.date_invoice"/></td>
|
||||
<td><span t-field="invoice.date_due"/></td>
|
||||
<td>
|
||||
<t t-if="invoice.state == 'open'">
|
||||
<span class="label label-info"><i class="fa fa-fw fa-clock-o"/> Waiting for Payment</span>
|
||||
</t>
|
||||
<t t-if="invoice.state == 'paid'">
|
||||
<span class="label label-default"><i class="fa fa-fw fa-check"/> Paid</span>
|
||||
</t>
|
||||
<t t-if="invoice.state == 'cancel'">
|
||||
<span class="label label-default"><i class="fa fa-fw fa-remove"/> Cancelled</span>
|
||||
</t>
|
||||
</td>
|
||||
<td><span t-esc="invoice.amount_total" t-esc-options='{"widget": "monetary", "display_currency": "invoice.currency_id"}'/></td>
|
||||
</tr>
|
||||
</t>
|
||||
<tr t-att-class="'hidden' if len(invoices) < 5 else ''">
|
||||
<td colspan="5"><a href="" class="o_my_show_more btn btn-xs btn-default"><span>Show more</span><span class="hidden">Show less</span></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<template id="orders_followup" name="Sales Order">
|
||||
<t t-call="website.layout">
|
||||
<div id="wrap">
|
||||
<div class="container">
|
||||
<div class="oe_structure">
|
||||
<div class="row">
|
||||
<div class="col-sm-4">
|
||||
<ol class="breadcrumb mt8">
|
||||
<li><a href="/my/home">My Account</a></li>
|
||||
<li>
|
||||
<t t-if="order.state == 'sent'">
|
||||
Quotation
|
||||
</t>
|
||||
<t t-if="order.state != 'sent'">
|
||||
Order
|
||||
</t>
|
||||
<t t-esc="order.name"/>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="optional_placeholder"></div>
|
||||
<div class="container">
|
||||
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<h4>
|
||||
<t t-if="order.state == 'sent'">
|
||||
Quotation
|
||||
</t>
|
||||
<t t-if="order.state != 'sent'">
|
||||
Order
|
||||
</t>
|
||||
<span t-esc="order.name"/>
|
||||
</h4>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<!-- <hr/> -->
|
||||
<div class="mb8">
|
||||
<strong>Date:</strong> <span t-field="order.create_date" t-field-options='{"widget": "date"}'/>
|
||||
</div>
|
||||
<div class='row'>
|
||||
<div class="col-md-6">
|
||||
<div>
|
||||
<strong>Invoicing Address</strong>
|
||||
</div>
|
||||
<div>
|
||||
<address t-field="order.partner_invoice_id" t-field-options='{"widget": "contact", "fields": ["address", "name"], "no_marker": true}'/>
|
||||
</div>
|
||||
<t t-set="invoices" t-value="[i for i in order.invoice_ids if i.state not in ['draft', 'cancel']]"/>
|
||||
<t t-if="invoices">
|
||||
<div>
|
||||
<strong>Invoices</strong>
|
||||
</div>
|
||||
<div>
|
||||
<t t-foreach="invoices" t-as="i">
|
||||
<t t-set="report_url" t-value="'/report/pdf/account.report_invoice/%s' % i.id"/>
|
||||
<div>
|
||||
<a t-att-href="report_url"><span class="fa fa-download"/></a>
|
||||
<a t-att-href="report_url"><span t-esc="i.number"/></a>
|
||||
<span class="text-muted" t-field="i.date_invoice"/>
|
||||
<t t-if="i.state == 'paid'">
|
||||
<span class="label label-success orders_label_text_align"><i class="fa fa-fw fa-check"/> Paid</span>
|
||||
</t>
|
||||
<t t-if="i.state != 'paid'">
|
||||
<span class="label label-info orders_label_text_align"><i class="fa fa-fw fa-clock-o"/> Waiting</span>
|
||||
</t>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
<div id="shipping_address" class="col-md-6">
|
||||
<div>
|
||||
<strong>Shipping Address</strong>
|
||||
</div>
|
||||
<div>
|
||||
<address t-field="order.partner_shipping_id" t-field-options='{"widget": "contact", "fields": ["address", "name"], "no_marker": true}'/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr/>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<strong>Product</strong>
|
||||
</div>
|
||||
<div class="col-md-2 text-right">
|
||||
<strong>Unit Price</strong>
|
||||
</div>
|
||||
<div class="col-md-2 text-right">
|
||||
<strong>Quantity</strong>
|
||||
</div>
|
||||
<div class="col-md-2 text-right">
|
||||
<strong>Subtotal</strong>
|
||||
</div>
|
||||
</div>
|
||||
<t t-foreach="order.order_line" t-as="ol">
|
||||
<div class="row orders_vertical_align">
|
||||
<div class="col-md-1 text-center">
|
||||
<img t-att-src="'/web_editor/image/product.product/%s/image_small/48x48' % ol.product_id.id"/>
|
||||
</div>
|
||||
<div id='product_name' class="col-md-5">
|
||||
<span t-esc="ol.product_id.name"/>
|
||||
</div>
|
||||
<div class="col-md-2 text-right">
|
||||
<span t-field="ol.price_unit" t-field-options='{"widget": "monetary", "display_currency": "order.pricelist_id.currency_id"}'/>
|
||||
</div>
|
||||
<div class="col-md-2 text-right">
|
||||
<t t-if="ol._name == 'sale.order.line'">
|
||||
<span t-esc="ol.product_uom_qty"/>
|
||||
</t>
|
||||
<t t-if="ol._name == 'account.invoice.line'">
|
||||
<span t-esc="ol.quantity"/>
|
||||
</t>
|
||||
</div>
|
||||
<div class="col-md-2 text-right">
|
||||
<span t-field="ol.price_subtotal" t-field-options='{"widget": "monetary", "display_currency": "order.pricelist_id.currency_id"}'/>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<hr/>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div>
|
||||
<strong>Contact</strong>
|
||||
</div>
|
||||
<div t-field="order.user_id.partner_id" t-field-options='{"widget": "contact", "fields": ["email", "phone"]}'/>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="row">
|
||||
<div class="col-md-10 text-right">
|
||||
Untaxed Amount:
|
||||
</div>
|
||||
<div class="col-md-2 text-right">
|
||||
<span t-field="order.amount_untaxed" t-field-options='{"widget": "monetary", "display_currency": "order.pricelist_id.currency_id"}'/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-10 text-right">
|
||||
Taxes:
|
||||
</div>
|
||||
<div class="col-md-2 text-right">
|
||||
<span t-field="order.amount_tax" t-field-options='{"widget": "monetary", "display_currency": "order.pricelist_id.currency_id"}'/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-10 text-right">
|
||||
<strong>Total:</strong>
|
||||
</div>
|
||||
<div class="col-md-2 text-right">
|
||||
<strong><span t-field="order.amount_total" t-field-options='{"widget": "monetary", "display_currency": "order.pricelist_id.currency_id"}'/></strong>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="oe_structure mb32"/>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<template id="sale_backend_link" inherit_id='website_portal_sale.sale_orders' customize_show="True" name="Link to Sales Backend" active="False">
|
||||
<xpath expr="//h3[@class='page-header']" position="inside">
|
||||
<a href="/web#action=portal_sale.action_orders_portal" target="_blank" class="btn btn-default btn-xs pull-right"> Access the complete Sale application</a>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<template id="sales_backend_access" inherit_id='website_portal_sale.orders_followup' customize_show="True" name="Backend Access" active="False">
|
||||
<xpath expr="//div[@id='optional_placeholder']" position="inside">
|
||||
<h4 class="text-muted text-center mt64 mb64">
|
||||
If you wish to access the complete application to manage your orders, you can follow
|
||||
<a href="/web#action=portal_sale.action_orders_portal">this link</a>.
|
||||
</h4>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
</odoo>
|
||||
@@ -10,7 +10,7 @@ OpenERP E-Commerce
|
||||
|
||||
""",
|
||||
'author': 'OpenERP SA',
|
||||
'depends': ['sale', 'website_payment', 'website_portal'],
|
||||
'depends': ['sale', 'website_payment', 'website_portal_sale'],
|
||||
'data': [
|
||||
'data/data.xml',
|
||||
'data/web_planner_data.xml',
|
||||
|
||||
@@ -1435,7 +1435,7 @@
|
||||
</template>
|
||||
|
||||
<!-- Add a link to the product page in the portal orders followup page -->
|
||||
<template id="orders_followup_products_links" name="Orders Followup Products Links" inherit_id="website_portal.orders_followup">
|
||||
<template id="orders_followup_products_links" name="Orders Followup Products Links" inherit_id="website_portal_sale.orders_followup">
|
||||
<xpath expr="//span[@t-esc='ol.product_id.name']" position="replace">
|
||||
<a t-att-href="ol.product_id.website_url">
|
||||
<span t-esc="ol.product_id.name"/>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<template id="orders_followup_downloads" name="Orders Downloads Followup" inherit_id="website_portal.orders_followup">
|
||||
<template id="orders_followup_downloads" name="Orders Downloads Followup" inherit_id="website_portal_sale.orders_followup">
|
||||
<xpath expr="//div[@id='product_name']" position="inside">
|
||||
<t t-set="attachments" t-value="digital_attachments.get(ol.product_id.id)"/>
|
||||
<t t-if="attachments">
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<template id="orders_followup_shipping" name="Orders Shipping Followup" inherit_id="website_portal.orders_followup">
|
||||
<template id="orders_followup_shipping" name="Orders Shipping Followup" inherit_id="website_portal_sale.orders_followup">
|
||||
<xpath expr="//div[@id='shipping_address']" position="inside">
|
||||
<t t-if="order.picking_ids">
|
||||
<div>
|
||||
|
||||
Reference in New Issue
Block a user