[ADD] website portal and digital download
Add an orders section to the e-commerce to display sales orders, delivery orders and invoices. Add support for digital products.
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_stock_picking,stock.picking,stock.model_stock_picking,base.group_portal,1,0,0,0
|
||||
access_stock_picking_type_portal,stock.picking.type portal,stock.model_stock_picking_type,base.group_portal,1,0,0,0
|
||||
access_stock_pack_operation_portal,stock.pack.operation portal,stock.model_stock_pack_operation,base.group_portal,1,0,0,0
|
||||
access_stock_move,stock.move,stock.model_stock_move,base.group_portal,1,0,0,0
|
||||
access_stock_warehouse_orderpoint,stock.warehouse.orderpoint,stock.model_stock_warehouse_orderpoint,base.group_portal,1,0,0,0
|
||||
|
||||
|
@@ -3,10 +3,17 @@
|
||||
<data noupdate="1">
|
||||
|
||||
<!-- Stock Portal Access Rules -->
|
||||
<record id="portal_stock_picking_user_rule" model="ir.rule">
|
||||
<field name="name">Portal Personal Pickings</field>
|
||||
<record id="portal_stock_picking_portal_user_rule" model="ir.rule">
|
||||
<field name="name">Portal Follower Pickings</field>
|
||||
<field name="model_id" ref="stock.model_stock_picking"/>
|
||||
<field name="domain_force">[('message_follower_ids','in',[user.partner_id.id])]</field>
|
||||
<field name="domain_force">['|', ('message_follower_ids','in',[user.partner_id.id]), ('partner_id.id','=',user.partner_id.id)]</field>
|
||||
<field name="groups" eval="[(4, ref('base.group_portal'))]"/>
|
||||
</record>
|
||||
|
||||
<record id="portal_stock_pack_operation_portal_user_rule" model="ir.rule">
|
||||
<field name="name">Portal Follower Pack Operations</field>
|
||||
<field name="model_id" ref="stock.model_stock_pack_operation"/>
|
||||
<field name="domain_force">['|', ('picking_id.message_follower_ids','in',[user.partner_id.id]), ('picking_id.partner_id.id','=',user.partner_id.id)]</field>
|
||||
<field name="groups" eval="[(4, ref('base.group_portal'))]"/>
|
||||
</record>
|
||||
</data>
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
import controllers
|
||||
import models
|
||||
import res_config
|
||||
|
||||
@@ -18,6 +18,7 @@ OpenERP E-Commerce
|
||||
'views/payment.xml',
|
||||
'views/sale_order.xml',
|
||||
'views/snippets.xml',
|
||||
'res_config_view.xml',
|
||||
'security/ir.model.access.csv',
|
||||
'security/website_sale.xml',
|
||||
],
|
||||
|
||||
@@ -336,6 +336,33 @@ class website_sale(http.Controller):
|
||||
})
|
||||
return value
|
||||
|
||||
@http.route([
|
||||
'/shop/orders',
|
||||
'/shop/orders/page/<int:page>',
|
||||
], type='http', auth="user", website=True)
|
||||
def orders_followup(self, page=1, by = 5, **post):
|
||||
partner = request.env['res.users'].browse(request.uid).partner_id
|
||||
orders = request.env['sale.order'].sudo().search([('partner_id', '=', partner.id), ('state', 'not in', ['draft', 'cancel'])])
|
||||
|
||||
nbr_pages = max((len(orders) / by) + (1 if len(orders) % by > 0 else 0), 1)
|
||||
page = min(page, nbr_pages)
|
||||
pager = request.website.pager(
|
||||
url='/shop/orders', total=nbr_pages, page=page, step=1,
|
||||
scope=by, url_args=post
|
||||
)
|
||||
orders = orders[by*(page-1):by*(page-1)+by]
|
||||
|
||||
order_invoice_lines = {}
|
||||
for o in orders:
|
||||
invoiced_lines = request.env['account.invoice.line'].sudo().search([('invoice_id', 'in', o.invoice_ids.ids)])
|
||||
order_invoice_lines[o.id] = {il.product_id.id: il.invoice_id for il in invoiced_lines}
|
||||
|
||||
return request.website.render("website_sale.orders_followup", {
|
||||
'orders': orders,
|
||||
'order_invoice_lines': order_invoice_lines,
|
||||
'pager': pager,
|
||||
})
|
||||
|
||||
#------------------------------------------------------
|
||||
# Checkout
|
||||
#------------------------------------------------------
|
||||
@@ -925,4 +952,4 @@ class website_sale(http.Controller):
|
||||
'currency': order.currency_id.name
|
||||
}
|
||||
ret['lines'] = self.order_lines_2_google_api(order.order_line)
|
||||
return ret
|
||||
return ret
|
||||
@@ -0,0 +1,9 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
from openerp import models, fields
|
||||
from openerp.addons.sale.res_config import sale_configuration
|
||||
|
||||
class website_sale_configuration(models.TransientModel):
|
||||
_inherit = 'sale.config.settings'
|
||||
|
||||
module_website_sale_digital = fields.Boolean('Sell digital products',
|
||||
help="Allow you to set mark a product as a digital product, allowing customers that have purchased the product to download its attachments. This installs the module website_sale_digital.")
|
||||
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<record id="view_website_sales_config" model="ir.ui.view">
|
||||
<field name="name">website_sale settings</field>
|
||||
<field name="model">sale.config.settings</field>
|
||||
<field name="inherit_id" ref="sale.view_sales_config"/>
|
||||
<field name="arch" type="xml">
|
||||
<div name="customer feature" position="before">
|
||||
<separator string="Products Management"/>
|
||||
<group>
|
||||
<label for="id" string="Product Types"/>
|
||||
<div>
|
||||
<div name="group_invoice_so_lines">
|
||||
<field name="module_website_sale_digital" class="oe_inline"/>
|
||||
<label for="module_website_sale_digital"/>
|
||||
</div>
|
||||
</div>
|
||||
</group>
|
||||
</div>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
@@ -1,101 +1,83 @@
|
||||
@charset "utf-8";
|
||||
/* ---- Default Styles ---- */
|
||||
.oe_product {
|
||||
border: 1px solid rgba(100, 100, 100, 0.2);
|
||||
}
|
||||
border: 1px solid rgba(100, 100, 100, 0.2); }
|
||||
|
||||
.products_pager {
|
||||
text-align: center;
|
||||
}
|
||||
.products_pager > div {
|
||||
margin: 0 auto;
|
||||
display: inline-block;
|
||||
}
|
||||
.products_pager > div > * {
|
||||
vertical-align: middle;
|
||||
float: none;
|
||||
padding: 0;
|
||||
}
|
||||
.products_pager > div > ul {
|
||||
padding-left: 10px;
|
||||
}
|
||||
.products_pager > ul {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
text-align: center; }
|
||||
.products_pager > div {
|
||||
margin: 0 auto;
|
||||
display: inline-block; }
|
||||
.products_pager > div > * {
|
||||
vertical-align: middle;
|
||||
float: none;
|
||||
padding: 0; }
|
||||
.products_pager > div > ul {
|
||||
padding-left: 10px; }
|
||||
.products_pager > ul {
|
||||
margin-left: auto;
|
||||
margin-right: auto; }
|
||||
|
||||
.oe_website_sale ul ul {
|
||||
margin-left: 1.5em;
|
||||
}
|
||||
margin-left: 1.5em; }
|
||||
|
||||
/* ---- Default Styles ---- */
|
||||
.oe_product {
|
||||
position: relative;
|
||||
}
|
||||
.oe_product .oe_product_image {
|
||||
position: absolute;
|
||||
left: 15px;
|
||||
right: 15px;
|
||||
top: 15px;
|
||||
bottom: 55px;
|
||||
text-align: center;
|
||||
}
|
||||
.oe_product .oe_product_image img {
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
margin: auto;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
z-index: 4;
|
||||
}
|
||||
.oe_product section {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
overflow: hidden;
|
||||
padding: 0 15px 24px 10px;
|
||||
min-height: 56px;
|
||||
border-top: 1px solid rgba(255, 255, 255, 0.2);
|
||||
background: rgba(255, 255, 255, 0.75);
|
||||
z-index: 5;
|
||||
}
|
||||
.oe_product .product_price {
|
||||
padding: 5px 0;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
}
|
||||
.oe_product .oe_product_cart {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.oe_product .oe_subdescription {
|
||||
font-size: 0.8em;
|
||||
overflow: hidden;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
position: relative; }
|
||||
.oe_product .oe_product_image {
|
||||
position: absolute;
|
||||
left: 15px;
|
||||
right: 15px;
|
||||
top: 15px;
|
||||
bottom: 55px;
|
||||
text-align: center; }
|
||||
.oe_product .oe_product_image img {
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
margin: auto;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
z-index: 4; }
|
||||
.oe_product section {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
overflow: hidden;
|
||||
padding: 0 15px 24px 10px;
|
||||
min-height: 56px;
|
||||
border-top: 1px solid rgba(255, 255, 255, 0.2);
|
||||
background: rgba(255, 255, 255, 0.75);
|
||||
z-index: 5; }
|
||||
.oe_product .product_price {
|
||||
padding: 5px 0;
|
||||
position: absolute;
|
||||
bottom: 0; }
|
||||
.oe_product .oe_product_cart {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%; }
|
||||
.oe_product .oe_subdescription {
|
||||
font-size: 0.8em;
|
||||
overflow: hidden;
|
||||
margin-bottom: 10px; }
|
||||
|
||||
.oe_mycart .input-group-addon {
|
||||
padding-left: 6px;
|
||||
padding-right: 6px;
|
||||
}
|
||||
padding-right: 6px; }
|
||||
|
||||
/* Products Options */
|
||||
.oe_product.oe_image_full .oe_product_image {
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
bottom: 0; }
|
||||
|
||||
/* Ribbon for promotionso on products */
|
||||
.oe_product.oe_ribbon_promo .ribbon-wrapper {
|
||||
display: block;
|
||||
}
|
||||
display: block; }
|
||||
.oe_product .ribbon-wrapper {
|
||||
display: none;
|
||||
width: 85px;
|
||||
@@ -104,8 +86,7 @@
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
}
|
||||
right: 0; }
|
||||
.oe_product .ribbon {
|
||||
font: bold 15px Sans-Serif;
|
||||
color: white;
|
||||
@@ -119,141 +100,99 @@
|
||||
left: -5px;
|
||||
top: 15px;
|
||||
width: 120px;
|
||||
cursor: default;
|
||||
}
|
||||
cursor: default; }
|
||||
|
||||
/* ---- Product Sizes ---- */
|
||||
.col-md-12 .oe-height-1 {
|
||||
height: 75px;
|
||||
}
|
||||
height: 75px; }
|
||||
.col-md-12 .oe-height-2 {
|
||||
height: 150px;
|
||||
}
|
||||
height: 150px; }
|
||||
.col-md-12 .oe-height-4 {
|
||||
height: 300px;
|
||||
}
|
||||
height: 300px; }
|
||||
.col-md-12 .oe-height-6 {
|
||||
height: 450px;
|
||||
}
|
||||
height: 450px; }
|
||||
.col-md-12 .oe-height-8 {
|
||||
height: 600px;
|
||||
}
|
||||
height: 600px; }
|
||||
|
||||
.col-md-9 .oe-height-1 {
|
||||
height: 70px;
|
||||
}
|
||||
height: 70px; }
|
||||
.col-md-9 .oe-height-2 {
|
||||
height: 140px;
|
||||
}
|
||||
height: 140px; }
|
||||
.col-md-9 .oe-height-4 {
|
||||
height: 280px;
|
||||
}
|
||||
height: 280px; }
|
||||
.col-md-9 .oe-height-6 {
|
||||
height: 420px;
|
||||
}
|
||||
height: 420px; }
|
||||
.col-md-9 .oe-height-8 {
|
||||
height: 560px;
|
||||
}
|
||||
height: 560px; }
|
||||
|
||||
@media (max-width: 768px) {
|
||||
#products_grid table, #products_grid tbody, #products_grid tr, #products_grid td {
|
||||
float: left;
|
||||
width: 100%;
|
||||
display: inline-block;
|
||||
}
|
||||
display: inline-block; }
|
||||
#products_grid .oe_product {
|
||||
float: left;
|
||||
width: 100%;
|
||||
height: 300px;
|
||||
display: inline-block;
|
||||
}
|
||||
display: inline-block; }
|
||||
|
||||
.products_pager .pagination {
|
||||
margin: 5px auto !important;
|
||||
}
|
||||
}
|
||||
margin: 5px auto !important; } }
|
||||
@media (max-width: 400px) {
|
||||
#products_grid .oe_product {
|
||||
height: 270px;
|
||||
}
|
||||
#products_grid .oe_product section {
|
||||
background: rgba(100, 100, 100, 0.2);
|
||||
}
|
||||
#products_grid .oe_product .oe_product_image {
|
||||
top: 0;
|
||||
bottom: 65px;
|
||||
}
|
||||
height: 270px; }
|
||||
#products_grid .oe_product section {
|
||||
background: rgba(100, 100, 100, 0.2); }
|
||||
#products_grid .oe_product .oe_product_image {
|
||||
top: 0;
|
||||
bottom: 65px; }
|
||||
|
||||
#products_grid .oe_product.oe_image_full .oe_product_image {
|
||||
bottom: 50px;
|
||||
}
|
||||
}
|
||||
bottom: 50px; } }
|
||||
@media (min-width: 992px) {
|
||||
.col-md-12 .oe-height-1 {
|
||||
height: 95px;
|
||||
}
|
||||
height: 95px; }
|
||||
.col-md-12 .oe-height-2 {
|
||||
height: 190px;
|
||||
}
|
||||
height: 190px; }
|
||||
.col-md-12 .oe-height-4 {
|
||||
height: 380px;
|
||||
}
|
||||
height: 380px; }
|
||||
.col-md-12 .oe-height-6 {
|
||||
height: 570px;
|
||||
}
|
||||
height: 570px; }
|
||||
.col-md-12 .oe-height-8 {
|
||||
height: 760px;
|
||||
}
|
||||
height: 760px; }
|
||||
|
||||
.col-md-9 .oe-height-1 {
|
||||
height: 72px;
|
||||
}
|
||||
height: 72px; }
|
||||
.col-md-9 .oe-height-2 {
|
||||
height: 144px;
|
||||
}
|
||||
height: 144px; }
|
||||
.col-md-9 .oe-height-4 {
|
||||
height: 288px;
|
||||
}
|
||||
height: 288px; }
|
||||
.col-md-9 .oe-height-6 {
|
||||
height: 432px;
|
||||
}
|
||||
height: 432px; }
|
||||
.col-md-9 .oe-height-8 {
|
||||
height: 576px;
|
||||
}
|
||||
}
|
||||
height: 576px; } }
|
||||
@media (min-width: 1200px) {
|
||||
.col-md-12 .oe-height-1 {
|
||||
height: 125px;
|
||||
}
|
||||
height: 125px; }
|
||||
.col-md-12 .oe-height-2 {
|
||||
height: 250px;
|
||||
}
|
||||
height: 250px; }
|
||||
.col-md-12 .oe-height-4 {
|
||||
height: 500px;
|
||||
}
|
||||
height: 500px; }
|
||||
.col-md-12 .oe-height-6 {
|
||||
height: 750px;
|
||||
}
|
||||
height: 750px; }
|
||||
.col-md-12 .oe-height-8 {
|
||||
height: 1000px;
|
||||
}
|
||||
height: 1000px; }
|
||||
|
||||
.col-md-9 .oe-height-1 {
|
||||
height: 95px;
|
||||
}
|
||||
height: 95px; }
|
||||
.col-md-9 .oe-height-2 {
|
||||
height: 190px;
|
||||
}
|
||||
height: 190px; }
|
||||
.col-md-9 .oe-height-4 {
|
||||
height: 380px;
|
||||
}
|
||||
height: 380px; }
|
||||
.col-md-9 .oe-height-6 {
|
||||
height: 570px;
|
||||
}
|
||||
height: 570px; }
|
||||
.col-md-9 .oe-height-8 {
|
||||
height: 760px;
|
||||
}
|
||||
}
|
||||
height: 760px; } }
|
||||
/* ---- Product list style ---- */
|
||||
@media (min-width: 400px) {
|
||||
.oe_product.oe_list {
|
||||
@@ -262,115 +201,98 @@
|
||||
width: 100%;
|
||||
min-height: 100px;
|
||||
position: relative;
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
.oe_product.oe_list .oe_product_image {
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
width: 170px;
|
||||
}
|
||||
.oe_product.oe_list section {
|
||||
position: relative;
|
||||
border: 0;
|
||||
top: 0;
|
||||
bottom: auto;
|
||||
left: 180px;
|
||||
background: transparent;
|
||||
}
|
||||
}
|
||||
padding-bottom: 5px; }
|
||||
.oe_product.oe_list .oe_product_image {
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
width: 170px; }
|
||||
.oe_product.oe_list section {
|
||||
position: relative;
|
||||
border: 0;
|
||||
top: 0;
|
||||
bottom: auto;
|
||||
left: 180px;
|
||||
background: transparent; } }
|
||||
.oe_website_sale .row .row .col-md-12 {
|
||||
float: none;
|
||||
}
|
||||
float: none; }
|
||||
|
||||
/* product detail */
|
||||
.css_attribute_color {
|
||||
display: inline-block;
|
||||
border: 1px solid #999999;
|
||||
text-align: center;
|
||||
}
|
||||
.css_attribute_color input {
|
||||
margin: 8px;
|
||||
height: 13px;
|
||||
opacity: 0;
|
||||
}
|
||||
.css_attribute_color.active {
|
||||
border: 3px ridge #66ee66;
|
||||
}
|
||||
.css_attribute_color.active input {
|
||||
margin: 6px;
|
||||
}
|
||||
text-align: center; }
|
||||
.css_attribute_color input {
|
||||
margin: 8px;
|
||||
height: 13px;
|
||||
opacity: 0; }
|
||||
.css_attribute_color.active {
|
||||
border: 3px ridge #66ee66; }
|
||||
.css_attribute_color.active input {
|
||||
margin: 6px; }
|
||||
|
||||
.css_not_available_msg {
|
||||
display: none;
|
||||
}
|
||||
display: none; }
|
||||
|
||||
.css_not_available.js_product > *:nth-child(4) > * {
|
||||
display: none;
|
||||
}
|
||||
display: none; }
|
||||
.css_not_available.js_product .product_price, .css_not_available.js_product .css_quantity {
|
||||
display: none;
|
||||
}
|
||||
display: none; }
|
||||
.css_not_available.js_product .css_not_available_msg {
|
||||
display: block;
|
||||
}
|
||||
display: block; }
|
||||
|
||||
option.css_not_available {
|
||||
color: #cccccc;
|
||||
}
|
||||
color: #ccc; }
|
||||
|
||||
label.css_not_available {
|
||||
opacity: 0.6;
|
||||
}
|
||||
opacity: 0.6; }
|
||||
|
||||
label.css_attribute_color.css_not_available {
|
||||
opacity: 1;
|
||||
background-image: url("/website_sale/static/src/img/redcross.png");
|
||||
background-size: cover;
|
||||
}
|
||||
background-size: cover; }
|
||||
|
||||
.product_detail_img {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
display: block;
|
||||
max-height: 500px;
|
||||
}
|
||||
max-height: 500px; }
|
||||
|
||||
.oe_default_price {
|
||||
display: none;
|
||||
}
|
||||
display: none; }
|
||||
|
||||
.discount .oe_default_price {
|
||||
display: block;
|
||||
}
|
||||
display: block; }
|
||||
|
||||
.oe_website_sale input.js_quantity {
|
||||
min-width: 48px;
|
||||
text-align: center;
|
||||
}
|
||||
text-align: center; }
|
||||
|
||||
/* ---- Publish managment and options ---- */
|
||||
.oe_overlay_options .dropdown ul[name="size"] table {
|
||||
margin-left: 20px;
|
||||
}
|
||||
margin-left: 20px; }
|
||||
.oe_overlay_options .dropdown ul[name="size"] td {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border: 1px #dddddd solid;
|
||||
cursor: pointer;
|
||||
}
|
||||
.oe_overlay_options .dropdown ul[name="size"] td.selected {
|
||||
background-color: #b1d4f1;
|
||||
}
|
||||
cursor: pointer; }
|
||||
.oe_overlay_options .dropdown ul[name="size"] td.selected {
|
||||
background-color: #B1D4F1; }
|
||||
.oe_overlay_options .dropdown ul[name="size"] table.oe_hover td.selected {
|
||||
background-color: transparent;
|
||||
}
|
||||
background-color: transparent; }
|
||||
.oe_overlay_options .dropdown ul[name="size"] table.oe_hover td.select {
|
||||
background-color: #b1d4f1;
|
||||
}
|
||||
background-color: #B1D4F1; }
|
||||
|
||||
/* ---- My Orders page ---- */
|
||||
.orders_vertical_align {
|
||||
display: flex;
|
||||
align-items: center; }
|
||||
|
||||
.orders_label_text_align {
|
||||
vertical-align: 15%; }
|
||||
|
||||
/* Wizard */
|
||||
ul.wizard {
|
||||
@@ -382,8 +304,7 @@ ul.wizard {
|
||||
border-radius: 4px;
|
||||
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.065);
|
||||
-moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.065);
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.065);
|
||||
}
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.065); }
|
||||
|
||||
ul.wizard li {
|
||||
border: 1px solid #d4d4d4;
|
||||
@@ -393,8 +314,7 @@ ul.wizard li {
|
||||
padding: 0 10px 0 20px;
|
||||
margin: 0;
|
||||
line-height: 38px;
|
||||
background: #fbfbfb;
|
||||
}
|
||||
background: #fbfbfb; }
|
||||
|
||||
ul.wizard li .chevron {
|
||||
position: absolute;
|
||||
@@ -404,8 +324,7 @@ ul.wizard li .chevron {
|
||||
display: block;
|
||||
border: 20px solid transparent;
|
||||
border-right: 0;
|
||||
border-left: 10px solid #d4d4d4;
|
||||
}
|
||||
border-left: 10px solid #d4d4d4; }
|
||||
|
||||
ul.wizard li .chevron:before {
|
||||
position: absolute;
|
||||
@@ -415,26 +334,22 @@ ul.wizard li .chevron:before {
|
||||
border: 20px solid transparent;
|
||||
border-right: 0;
|
||||
border-left: 10px solid #fbfbfb;
|
||||
content: "";
|
||||
}
|
||||
content: ""; }
|
||||
|
||||
ul.wizard li.text-success {
|
||||
background: #f3f4f5;
|
||||
}
|
||||
background: #f3f4f5; }
|
||||
|
||||
ul.wizard li.text-success .chevron:before {
|
||||
border-left: 10px solid whitesmoke;
|
||||
}
|
||||
border-left: 10px solid #f5f5f5; }
|
||||
|
||||
ul.wizard li.text-primary {
|
||||
background: #f1f6fc;
|
||||
}
|
||||
background: #f1f6fc; }
|
||||
|
||||
ul.wizard li.text-primary .chevron:before {
|
||||
border-left: 10px solid #f1f6fc;
|
||||
}
|
||||
border-left: 10px solid #f1f6fc; }
|
||||
|
||||
ul.wizard li:first-child {
|
||||
padding-left: 15px;
|
||||
border-radius: 4px 0 0 4px;
|
||||
}
|
||||
border-radius: 4px 0 0 4px; }
|
||||
|
||||
/*# sourceMappingURL=website_sale.css.map */
|
||||
|
||||
@@ -315,6 +315,17 @@ label.css_attribute_color.css_not_available
|
||||
table.oe_hover td.select
|
||||
background-color: #B1D4F1
|
||||
|
||||
/* ---- My Orders page ---- */
|
||||
|
||||
.orders_vertical_align
|
||||
display: flex
|
||||
align-items: center
|
||||
|
||||
|
||||
.orders_label_text_align
|
||||
vertical-align: 15%
|
||||
|
||||
|
||||
/* Wizard */
|
||||
|
||||
|
||||
|
||||
@@ -1212,5 +1212,216 @@
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<template id="orders_followup" name="Odoo - Follow your Orders">
|
||||
<t t-call="website.layout">
|
||||
<div id="wrap">
|
||||
<div class="oe_structure">
|
||||
<h1 class="text-center">
|
||||
Odoo Orders History
|
||||
</h1>
|
||||
<h2 class="text-center text-muted">
|
||||
Follow your Orders
|
||||
</h2>
|
||||
</div>
|
||||
<div class="container oe_website_sale">
|
||||
<t t-if="not orders">
|
||||
<h4 class="text-muted text-center mt64 mb64">
|
||||
You have yet to order anything, why not <a href="/shop/">start now</a> ?
|
||||
</h4>
|
||||
</t>
|
||||
|
||||
<t t-call="website_sale.orders_followup_navbar"/>
|
||||
|
||||
<t t-foreach="orders" t-as="o">
|
||||
<div class='row'>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<h4>
|
||||
<t t-if="o.state == 'sent'">
|
||||
Quotation N°
|
||||
</t>
|
||||
<t t-if="o.state != 'sent'">
|
||||
Order N°
|
||||
</t>
|
||||
<span t-field="o.name"/>
|
||||
</h4>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<!-- <hr/> -->
|
||||
<div class="mb8">
|
||||
<strong>Date:</strong> <span t-field="o.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="o.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 o.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-field="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="o.partner_shipping_id" t-field-options='{"widget": "contact", "fields": ["address", "name"], "no_marker": true}'/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr/>
|
||||
|
||||
<div id="product_lines">
|
||||
<!-- Product lines come here -->
|
||||
</div>
|
||||
|
||||
<hr/>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div>
|
||||
<strong>Contact</strong>
|
||||
</div>
|
||||
<div t-field="o.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="o.amount_untaxed" t-field-options='{"widget": "monetary", "display_currency": "o.company_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="o.amount_tax" t-field-options='{"widget": "monetary", "display_currency": "o.company_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="o.amount_total" t-field-options='{"widget": "monetary", "display_currency": "o.company_id.currency_id"}'/></strong>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<t t-if="len(orders) >= 2">
|
||||
<t t-call="website_sale.orders_followup_navbar"/>
|
||||
</t>
|
||||
|
||||
</div>
|
||||
<div class="oe_structure mb32"/>
|
||||
</div>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<template id="sales_backend_access" inherit_id='website_sale.orders_followup' customize_show="True" name="Backend Access">
|
||||
<xpath expr="//div[@class='container oe_website_sale']" position="before">
|
||||
<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>
|
||||
|
||||
<template id="order_invoice" name="Display Products similarly to Invoice form view" inherit_id="website_sale.orders_followup">
|
||||
<xpath expr="//div[@id='product_lines']" position="inside">
|
||||
<div class="row">
|
||||
<div class="col-md-8 col-md-offset-1">
|
||||
<strong>Product</strong>
|
||||
</div>
|
||||
<div class="col-md-1 text-right">
|
||||
<strong>Unit Price</strong>
|
||||
</div>
|
||||
<div class="col-md-1 text-right">
|
||||
<strong>Quantity</strong>
|
||||
</div>
|
||||
<div class="col-md-1 text-right">
|
||||
<strong>Subtotal</strong>
|
||||
</div>
|
||||
</div>
|
||||
<t t-foreach="o.order_line" t-as="ol">
|
||||
<div class="row orders_vertical_align">
|
||||
<div class="col-md-1 text-center">
|
||||
<a t-att-href="'/shop/product/%s' % str(ol.product_id.product_tmpl_id.id)">
|
||||
<img t-att-src="'/website/image/product.product/%s/image_small/48x48' % ol.product_id.id"/>
|
||||
</a>
|
||||
</div>
|
||||
<div id='product_name' class="col-md-8">
|
||||
<a t-att-href="'/shop/product/%s' % str(ol.product_id.product_tmpl_id.id)"><span t-field="ol.product_id.name"/></a>
|
||||
</div>
|
||||
<div class="col-md-1 text-right">
|
||||
<span t-field="ol.price_unit" t-field-options='{"widget": "monetary", "display_currency": "o.company_id.currency_id"}'/>
|
||||
</div>
|
||||
<div class="col-md-1 text-right">
|
||||
<t t-if="ol._name == 'sale.order.line'">
|
||||
<span t-field="ol.product_uom_qty"/>
|
||||
</t>
|
||||
<t t-if="ol._name == 'account.invoice.line'">
|
||||
<span t-field="ol.quantity"/>
|
||||
</t>
|
||||
</div>
|
||||
<div class="col-md-1 text-right">
|
||||
<span t-field="ol.price_subtotal" t-field-options='{"widget": "monetary", "display_currency": "o.company_id.currency_id"}'/>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<template id="orders_followup_navbar" name="Navbar for My Orders page">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<span class="pull-right">
|
||||
<t t-call="website.pager"/>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template id="orders_followup_link" name="Orders Followup Link from User Account" inherit_id="website.layout">
|
||||
<xpath expr="//li[@class='dropdown']/ul/li[contains(.,'Logout')]" position="before">
|
||||
<li><a href="/shop/orders" role="menuitem">My Orders</a></li>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
import controllers
|
||||
import product
|
||||
import account_invoice
|
||||
@@ -0,0 +1,21 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
{
|
||||
'name': 'Website Sale Digital - Sell digital products',
|
||||
'version': '0.1',
|
||||
'description': """
|
||||
Sell digital product using attachments to virtual products
|
||||
""",
|
||||
'author': 'Odoo S.A.',
|
||||
'depends': [
|
||||
'document',
|
||||
'website_sale',
|
||||
],
|
||||
'installable': True,
|
||||
'data': [
|
||||
'views/website_sale_digital.xml',
|
||||
'views/website_sale_digital_view.xml',
|
||||
],
|
||||
'demo': [
|
||||
'demo.xml',
|
||||
],
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
from openerp import models, fields, api, _
|
||||
|
||||
class account_invoice_line(models.Model):
|
||||
_inherit = ['account.invoice.line']
|
||||
|
||||
def get_digital_purchases(self,uid):
|
||||
user = self.env['res.users'].browse(uid)
|
||||
partner = user.partner_id
|
||||
|
||||
# Get paid invoices
|
||||
purchases = self.sudo().search_read(
|
||||
domain=[('invoice_id.state', '=', 'paid'), ('invoice_id.partner_id', '=', partner.id), ('product_id.product_tmpl_id.digital_content', '=', True)],
|
||||
fields=['product_id'],
|
||||
)
|
||||
|
||||
# I only want product_ids, but search_read insists in giving me a list of
|
||||
# (product_id: <id>, name: <product code> <template_name> <attributes>)
|
||||
return map(lambda x: x['product_id'][0], purchases)
|
||||
@@ -0,0 +1,2 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
import main
|
||||
@@ -0,0 +1,112 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import base64
|
||||
from openerp.addons.web import http
|
||||
from openerp.addons.web.http import request
|
||||
from openerp.addons.website.controllers.main import Website
|
||||
from openerp.addons.website_sale.controllers.main import website_sale
|
||||
from cStringIO import StringIO
|
||||
from werkzeug.utils import redirect
|
||||
|
||||
|
||||
class website_sale_digital(website_sale):
|
||||
|
||||
orders_page = '/shop/orders'
|
||||
|
||||
@http.route([
|
||||
'/shop/confirmation',
|
||||
], type='http', auth="public", website=True)
|
||||
def payment_confirmation(self, **post):
|
||||
response = super(website_sale_digital, self).payment_confirmation(**post)
|
||||
order_lines = response.qcontext['order'].order_line
|
||||
digital_content = map(lambda x: x.product_id.digital_content, order_lines)
|
||||
response.qcontext.update(digital=any(digital_content))
|
||||
return response
|
||||
|
||||
@http.route([
|
||||
'/shop/orders',
|
||||
'/shop/orders/page/<int:page>',
|
||||
], type='http', auth='user', website=True)
|
||||
def orders_followup(self, page=1, **post):
|
||||
response = super(website_sale_digital, self).orders_followup(**post)
|
||||
|
||||
order_products_attachments = {}
|
||||
for o in response.qcontext['orders']:
|
||||
invoiced_lines = request.env['account.invoice.line'].sudo().search([('invoice_id', 'in', o.invoice_ids.ids), ('invoice_id.state', '=', 'paid')])
|
||||
|
||||
purchased_products_attachments = {}
|
||||
for il in invoiced_lines:
|
||||
p_obj = il.product_id
|
||||
# Ignore products that do not have digital content
|
||||
if not p_obj.product_tmpl_id.digital_content:
|
||||
continue
|
||||
|
||||
# Search for product attachments
|
||||
A = request.env['ir.attachment']
|
||||
p_id = p_obj.id
|
||||
template = p_obj.product_tmpl_id
|
||||
att = A.search_read(
|
||||
domain=['|', '&', ('res_model', '=', p_obj._name), ('res_id', '=', p_id), '&', ('res_model', '=', template._name), ('res_id', '=', template.id)],
|
||||
fields=['name', 'write_date'],
|
||||
order='write_date desc',
|
||||
)
|
||||
|
||||
# Ignore products with no attachments
|
||||
if not att:
|
||||
continue
|
||||
|
||||
purchased_products_attachments[p_id] = att
|
||||
|
||||
order_products_attachments[o.id] = purchased_products_attachments
|
||||
|
||||
response.qcontext.update({
|
||||
'digital_attachments': order_products_attachments,
|
||||
})
|
||||
return response
|
||||
|
||||
@http.route([
|
||||
'/shop/download',
|
||||
], type='http', auth='public')
|
||||
def download_attachment(self, attachment_id):
|
||||
# Check if this is a valid attachment id
|
||||
attachment = request.env['ir.attachment'].sudo().search_read(
|
||||
[('id', '=', int(attachment_id))],
|
||||
["name", "datas", "file_type", "res_model", "res_id", "type", "url"]
|
||||
)
|
||||
|
||||
if attachment:
|
||||
attachment = attachment[0]
|
||||
else:
|
||||
return redirect(self.orders_page)
|
||||
|
||||
|
||||
# Check if the user has bought the associated product
|
||||
res_model = attachment['res_model']
|
||||
res_id = attachment['res_id']
|
||||
purchased_products = request.env['account.invoice.line'].get_digital_purchases(request.uid)
|
||||
|
||||
if res_model == 'product.product':
|
||||
if res_id not in purchased_products:
|
||||
return redirect(self.orders_page)
|
||||
|
||||
# Also check for attachments in the product templates
|
||||
elif res_model == 'product.template':
|
||||
P = request.env['product.product']
|
||||
template_ids = map(lambda x: P.browse(x).product_tmpl_id.id, purchased_products)
|
||||
if res_id not in template_ids:
|
||||
return redirect(self.orders_page)
|
||||
|
||||
else:
|
||||
return redirect(self.orders_page)
|
||||
|
||||
# The client has bought the product, otherwise it would have been blocked by now
|
||||
if attachment["type"] == "url":
|
||||
if attachment["url"]:
|
||||
return redirect(attachment["url"])
|
||||
else:
|
||||
return request.not_found()
|
||||
elif attachment["datas"]:
|
||||
data = StringIO(base64.standard_b64decode(attachment["datas"]))
|
||||
return http.send_file(data, filename=attachment['name'], as_attachment=True)
|
||||
else:
|
||||
return request.not_found()
|
||||
@@ -0,0 +1,21 @@
|
||||
<odoo>
|
||||
<record id="website_sale_digital.product_1" model="product.template">
|
||||
<field name="name">Alice's Adventures in Wonderland - Lewis Caroll</field>
|
||||
<field name="standard_price">2</field>
|
||||
<field name="list_price">4.50</field>
|
||||
<field name="type">service</field>
|
||||
<field name="digital_content" eval="True"/>
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="image" type="base64" file="website_sale_digital/static/digital_product_1.jpg"/>
|
||||
<field name="description">Novel by Lewis Caroll.</field>
|
||||
<field name="description_sale">Alice's Adventures in Wonderland (commonly shortened to Alice in Wonderland) is an 1865 novel written by English author Charles Lutwidge Dodgson under the pseudonym Lewis Carroll. It tells of a girl named Alice falling through a rabbit hole into a fantasy world populated by peculiar, anthropomorphic creatures. The tale plays with logic, giving the story lasting popularity with adults as well as with children. It is considered to be one of the best examples of the literary nonsense genre. Its narrative course and structure, characters and imagery have been enormously influential in both popular culture and literature, especially in the fantasy genre.</field>
|
||||
</record>
|
||||
<record id="website_sale_digital.attach1" model="ir.attachment">
|
||||
<field name="name">alice.pdf</field>
|
||||
<field name="datas_fname">alice.pdf</field>
|
||||
<field name="type">binary</field>
|
||||
<field name="datas" type="base64" file="website_sale_digital/static/alice.pdf"/>
|
||||
<field name="res_id" ref="website_sale_digital.product_1"/>
|
||||
<field name="res_model">product.template</field>
|
||||
</record>
|
||||
</odoo>
|
||||
@@ -0,0 +1,8 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
from openerp import models, fields, api, _
|
||||
|
||||
|
||||
class product_template(models.Model):
|
||||
_inherit = ['product.template']
|
||||
|
||||
digital_content = fields.Boolean('Digital Content', help="If checked, it will allow clients to download the product attachments when they have bought it.")
|
||||
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 185 KiB |
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<template id="orders_followup_downloads" name="Orders Downloads Followup" inherit_id="website_sale.order_invoice">
|
||||
<xpath expr="//div[@id='product_name']" position="inside">
|
||||
<t t-set="attachments" t-value="digital_attachments[o.id].get(ol.product_id.id)"/>
|
||||
<t t-if="attachments">
|
||||
<span class="dropdown">
|
||||
<button class="btn btn-xs btn-default dropdown-toggle" type="button" id="dropdownMenu1" data-toggle="dropdown">
|
||||
Downloads <span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu" role="menu" aria-labelledby="dropdownMenu1">
|
||||
<t t-foreach="attachments" t-as="a">
|
||||
<li role="presentation"><a role="menuitem" tabindex="-1" t-att-href="'/shop/download?attachment_id=%i' % a['id']"><t t-esc="a['name']"/></a></li>
|
||||
</t>
|
||||
</ul>
|
||||
</span>
|
||||
</t>
|
||||
</xpath>
|
||||
</template>
|
||||
</odoo>
|
||||
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" ?>
|
||||
<odoo>
|
||||
<record model="ir.ui.view" id="view_product_form_expiry">
|
||||
<field name="name">product.normal.form</field>
|
||||
<field name="model">product.template</field>
|
||||
<field name="inherit_id" ref="product.product_template_form_view" />
|
||||
<field name="arch" type="xml">
|
||||
<field name="type" position="after">
|
||||
<field name="digital_content" />
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
import controllers
|
||||
@@ -0,0 +1,20 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
{
|
||||
'name': 'Website Sale Stock - Website Delivery Informations',
|
||||
'version': '0.0.1',
|
||||
'description': """
|
||||
Display delivery orders (picking) infos on the website
|
||||
""",
|
||||
'author': 'Odoo S.A.',
|
||||
'depends': [
|
||||
'website_sale',
|
||||
'sale_stock',
|
||||
],
|
||||
'installable': True,
|
||||
'auto_install': True,
|
||||
'data': [
|
||||
'views/website_sale_stock.xml',
|
||||
],
|
||||
'demo': [
|
||||
],
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
import main
|
||||
@@ -0,0 +1,26 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from openerp.addons.web import http
|
||||
from openerp.addons.web.http import request
|
||||
from openerp.addons.website.controllers.main import Website
|
||||
from openerp.addons.website_sale.controllers.main import website_sale
|
||||
|
||||
|
||||
class website_sale_stock(website_sale):
|
||||
|
||||
@http.route([
|
||||
'/shop/orders',
|
||||
'/shop/orders/page/<int:page>',
|
||||
], type='http', auth='user', website=True)
|
||||
def orders_followup(self, page=1, **post):
|
||||
response = super(website_sale_stock, self).orders_followup(**post)
|
||||
|
||||
order_shipping_lines = {}
|
||||
for o in response.qcontext['orders']:
|
||||
shipping_lines = request.env['stock.move'].sudo().search([('picking_id', 'in', o.picking_ids.ids)])
|
||||
order_shipping_lines[o.id] = {sl.product_id.id: sl.picking_id for sl in shipping_lines}
|
||||
|
||||
response.qcontext.update({
|
||||
'order_shipping_lines': order_shipping_lines,
|
||||
})
|
||||
return response
|
||||
@@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<template id="orders_followup_shipping" name="Orders Shipping Followup" inherit_id="website_sale.order_invoice">
|
||||
<xpath expr="//div[@id='shipping_address']" position="inside">
|
||||
<t t-if="o.picking_ids">
|
||||
<div>
|
||||
<strong>Delivery Orders</strong>
|
||||
</div>
|
||||
<div>
|
||||
<t t-foreach="o.picking_ids" t-as="i">
|
||||
<t t-set="report_url" t-value="'/report/pdf/stock.report_picking/%s' % i.id"/>
|
||||
<div>
|
||||
<a t-att-href="report_url"><span class="fa fa-download"/></a>
|
||||
<a t-att-href="report_url"><span t-field="i.name"/></a>
|
||||
<span class="text-muted" t-field="i.date" t-field-options='{"widget": "date"}'/>
|
||||
<t t-if="i.state == 'done'">
|
||||
<span class="label label-success label-text-align"><i class="fa fa-fw fa-truck"/> Shipped</span>
|
||||
</t>
|
||||
<t t-if="i.state == 'partially_available'">
|
||||
<span class="label label-warning label-text-align"><i class="fa fa-fw fa-clock-o"/> Partially Available</span>
|
||||
</t>
|
||||
<t t-if="i.state == 'cancel'">
|
||||
<span class="label label-danger label-text-align"><i class="fa fa-fw fa-times"/> Cancelled</span>
|
||||
</t>
|
||||
<t t-if="i.state in ['draft', 'waiting', 'confirmed', 'assigned']">
|
||||
<span class="label label-info label-text-align"><i class="fa fa-fw fa-clock-o"/> Preparation</span>
|
||||
</t>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
</t>
|
||||
</xpath>
|
||||
</template>
|
||||
</odoo>
|
||||
Reference in New Issue
Block a user