diff --git a/addons/portal_stock/security/ir.model.access.csv b/addons/portal_stock/security/ir.model.access.csv index 49617d3eefd..7a49d266538 100644 --- a/addons/portal_stock/security/ir.model.access.csv +++ b/addons/portal_stock/security/ir.model.access.csv @@ -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 diff --git a/addons/portal_stock/security/portal_security.xml b/addons/portal_stock/security/portal_security.xml index 2751996ac67..2a206a213ad 100644 --- a/addons/portal_stock/security/portal_security.xml +++ b/addons/portal_stock/security/portal_security.xml @@ -3,10 +3,17 @@ - - Portal Personal Pickings + + Portal Follower Pickings - [('message_follower_ids','in',[user.partner_id.id])] + ['|', ('message_follower_ids','in',[user.partner_id.id]), ('partner_id.id','=',user.partner_id.id)] + + + + + Portal Follower Pack Operations + + ['|', ('picking_id.message_follower_ids','in',[user.partner_id.id]), ('picking_id.partner_id.id','=',user.partner_id.id)] diff --git a/addons/website_sale/__init__.py b/addons/website_sale/__init__.py index 9f86759e32b..de2a0facac5 100644 --- a/addons/website_sale/__init__.py +++ b/addons/website_sale/__init__.py @@ -1,2 +1,3 @@ import controllers import models +import res_config diff --git a/addons/website_sale/__openerp__.py b/addons/website_sale/__openerp__.py index d09fd17415f..88e1dd29516 100644 --- a/addons/website_sale/__openerp__.py +++ b/addons/website_sale/__openerp__.py @@ -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', ], diff --git a/addons/website_sale/controllers/main.py b/addons/website_sale/controllers/main.py index 2068d5c071e..6ada56a55c5 100644 --- a/addons/website_sale/controllers/main.py +++ b/addons/website_sale/controllers/main.py @@ -336,6 +336,33 @@ class website_sale(http.Controller): }) return value + @http.route([ + '/shop/orders', + '/shop/orders/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 \ No newline at end of file diff --git a/addons/website_sale/res_config.py b/addons/website_sale/res_config.py new file mode 100644 index 00000000000..f80ca0d0303 --- /dev/null +++ b/addons/website_sale/res_config.py @@ -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.") \ No newline at end of file diff --git a/addons/website_sale/res_config_view.xml b/addons/website_sale/res_config_view.xml new file mode 100644 index 00000000000..72356b5b9c8 --- /dev/null +++ b/addons/website_sale/res_config_view.xml @@ -0,0 +1,23 @@ + + + + website_sale settings + sale.config.settings + + +
+ + + +
+
+
+ +
diff --git a/addons/website_sale/static/src/css/website_sale.css b/addons/website_sale/static/src/css/website_sale.css index 5af720731ab..24af7d36087 100644 --- a/addons/website_sale/static/src/css/website_sale.css +++ b/addons/website_sale/static/src/css/website_sale.css @@ -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 */ diff --git a/addons/website_sale/static/src/css/website_sale.sass b/addons/website_sale/static/src/css/website_sale.sass index ecf4081d356..598baf7cee6 100644 --- a/addons/website_sale/static/src/css/website_sale.sass +++ b/addons/website_sale/static/src/css/website_sale.sass @@ -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 */ diff --git a/addons/website_sale/views/templates.xml b/addons/website_sale/views/templates.xml index e5d04822666..550ceabdf2f 100644 --- a/addons/website_sale/views/templates.xml +++ b/addons/website_sale/views/templates.xml @@ -1212,5 +1212,216 @@ + + + + + + + + + + diff --git a/addons/website_sale_digital/__init__.py b/addons/website_sale_digital/__init__.py new file mode 100644 index 00000000000..dedfc9ab606 --- /dev/null +++ b/addons/website_sale_digital/__init__.py @@ -0,0 +1,4 @@ +# -*- encoding: utf-8 -*- +import controllers +import product +import account_invoice diff --git a/addons/website_sale_digital/__openerp__.py b/addons/website_sale_digital/__openerp__.py new file mode 100644 index 00000000000..9883efe53ac --- /dev/null +++ b/addons/website_sale_digital/__openerp__.py @@ -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', + ], +} diff --git a/addons/website_sale_digital/account_invoice.py b/addons/website_sale_digital/account_invoice.py new file mode 100644 index 00000000000..29ab67fb7a4 --- /dev/null +++ b/addons/website_sale_digital/account_invoice.py @@ -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: , name: ) + return map(lambda x: x['product_id'][0], purchases) \ No newline at end of file diff --git a/addons/website_sale_digital/controllers/__init__.py b/addons/website_sale_digital/controllers/__init__.py new file mode 100644 index 00000000000..1d9fb74e019 --- /dev/null +++ b/addons/website_sale_digital/controllers/__init__.py @@ -0,0 +1,2 @@ +# -*- encoding: utf-8 -*- +import main diff --git a/addons/website_sale_digital/controllers/main.py b/addons/website_sale_digital/controllers/main.py new file mode 100644 index 00000000000..276d1752c4e --- /dev/null +++ b/addons/website_sale_digital/controllers/main.py @@ -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/', + ], 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() diff --git a/addons/website_sale_digital/demo.xml b/addons/website_sale_digital/demo.xml new file mode 100644 index 00000000000..8572f210aaa --- /dev/null +++ b/addons/website_sale_digital/demo.xml @@ -0,0 +1,21 @@ + + + Alice's Adventures in Wonderland - Lewis Caroll + 2 + 4.50 + service + + + + Novel by Lewis Caroll. + 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. + + + alice.pdf + alice.pdf + binary + + + product.template + + diff --git a/addons/website_sale_digital/product.py b/addons/website_sale_digital/product.py new file mode 100644 index 00000000000..beeb5edb330 --- /dev/null +++ b/addons/website_sale_digital/product.py @@ -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.") diff --git a/addons/website_sale_digital/static/alice.pdf b/addons/website_sale_digital/static/alice.pdf new file mode 100644 index 00000000000..10276ceb279 Binary files /dev/null and b/addons/website_sale_digital/static/alice.pdf differ diff --git a/addons/website_sale_digital/static/digital_product_1.jpg b/addons/website_sale_digital/static/digital_product_1.jpg new file mode 100644 index 00000000000..51d7780ee65 Binary files /dev/null and b/addons/website_sale_digital/static/digital_product_1.jpg differ diff --git a/addons/website_sale_digital/views/website_sale_digital.xml b/addons/website_sale_digital/views/website_sale_digital.xml new file mode 100644 index 00000000000..b62c315fdb6 --- /dev/null +++ b/addons/website_sale_digital/views/website_sale_digital.xml @@ -0,0 +1,20 @@ + + + + \ No newline at end of file diff --git a/addons/website_sale_digital/views/website_sale_digital_view.xml b/addons/website_sale_digital/views/website_sale_digital_view.xml new file mode 100644 index 00000000000..d4c4c708d15 --- /dev/null +++ b/addons/website_sale_digital/views/website_sale_digital_view.xml @@ -0,0 +1,14 @@ + + + + product.normal.form + product.template + + + + + + + + + diff --git a/addons/website_sale_stock/__init__.py b/addons/website_sale_stock/__init__.py new file mode 100644 index 00000000000..e11f0b560a7 --- /dev/null +++ b/addons/website_sale_stock/__init__.py @@ -0,0 +1,2 @@ +# -*- encoding: utf-8 -*- +import controllers \ No newline at end of file diff --git a/addons/website_sale_stock/__openerp__.py b/addons/website_sale_stock/__openerp__.py new file mode 100644 index 00000000000..4e976429714 --- /dev/null +++ b/addons/website_sale_stock/__openerp__.py @@ -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': [ + ], +} diff --git a/addons/website_sale_stock/controllers/__init__.py b/addons/website_sale_stock/controllers/__init__.py new file mode 100644 index 00000000000..8ee9bae18d9 --- /dev/null +++ b/addons/website_sale_stock/controllers/__init__.py @@ -0,0 +1 @@ +import main diff --git a/addons/website_sale_stock/controllers/main.py b/addons/website_sale_stock/controllers/main.py new file mode 100644 index 00000000000..35eb7a08cf3 --- /dev/null +++ b/addons/website_sale_stock/controllers/main.py @@ -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/', + ], 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 \ No newline at end of file diff --git a/addons/website_sale_stock/views/website_sale_stock.xml b/addons/website_sale_stock/views/website_sale_stock.xml new file mode 100644 index 00000000000..3216e95aea4 --- /dev/null +++ b/addons/website_sale_stock/views/website_sale_stock.xml @@ -0,0 +1,34 @@ + + + + \ No newline at end of file