iT邦幫忙

2023 iThome 鐵人賽

DAY 29
0
Odoo

Odoo 魔法學院: 一步一腳印帶你成為客製化大師系列 第 29

[Day29] 設計圖書館使用者前端會員功能

  • 分享至 

  • xImage
  •  

先前設計的大多是給管理者的介面,今天則是來設計前端介面,讓外部使用者來做存取。
圖書館會員使用前端功能時,可以為會員分配一個使用者登入名,以存取其圖書結帳請求。

新增模組

我們會在新增一個模組,library_portal,/manifest.py,

{
  "name": "Library Portal",
  "description": "Portal for library members",
  "author": "Daniel Reis",
  "license": "AGPL-3",
  "depends": [
      "library_checkout", "portal"
  ],

  "data": [
    "security/library_security.xml",
    "security/ir.model.access.csv",
    "views/main_templates.xml",
    "views/checkout_portal_templates.xml",
  ],
}

設置一個前端介面,需要兩個元件 web controller(存取特定URL時觸發)跟QWeb template(產生由該URL呈現的HTML)

web controller

到__init__.py

from . import controllers

controllers/init.py

from . import main

controllers/main.py

from odoo import http
class Main(http.Controller):

    @http.route("/library/catalog", auth="public", website=True)
    def catalog(self, **kwargs):
        Book = http.request.env["library.book"]
        books = Book.sudo().search([])
        res =  http.request.render(
            "library_portal.book_catalog",
            {"books": books},
        )

QWeb template

library_portal/views/main_templates.xml

<odoo>
<template id="book_catalog" name="Book List">
  <t t-call="web.frontend_layout">
    <t t-set="title">Book Catalog</t>
      <div class="oe_structure">
        <div class="container">
          <h1 class="h1-book-catalog">
            Book Catalog</h1>
          <table class="table">
            <thead>
              <tr>
                <th scope="col">Title</th>
                <th scope="col">Published</th>
                <th scope="col">Publisher</th>
              </tr>
            </thead>
            <tbody>
      <t t-foreach="books" t-as="book">
        <tr scope="row">
          <td><span t-field="book.name" /></td>
          <td><span t-field="book.date_published"/></td>
          <td><span t-field="book.publisher_id"/></td>
        </tr>
      </t>
            </tbody>
          </table>
      </div>
    </div>
  </t>
</template>
</odoo>

另外之前也有學過怎麼新增css或js。

library_portal/static/src/css/library.css
.h1-book-catalog {
    font-size: 62px;
}

在library_portal/manifest.py

"assets": {
    "web.assets_backend": {
      "library_portal/static/src/css/library.css",
    }
  },

基本介面有了,之後來新增入口網站功能,分成三個access security,controllers,QWeb templates

access security

設置用戶的安全性,security/ir.model.access.csv:

id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_book_portal,Book Portal Access,library_app.model_library_book,base.group_portal,1,0,0,0
access_member_portal,Member Portal Access,library_member.model_library_member,base.group_portal,1,0,0,0
access_stage_portal,Checkout Stage Portal Access,library_checkout.model_library_checkout_stage,base.group_portal,1,0,0,0
access_checkout_portal,Checkout Portal Access,library_checkout.model_library_checkout,base.group_portal,1,0,0,0
access_checkout_portal_line,Checkout Portal Line Access,library_checkout.model_library_checkout_line,base.group_portal,1,0,0,0

security/library_security.xml

<odoo>
  <data noupdate="1">
    <record id="member_portal_rule" model="ir.rule">
      <field name="name">
        Library Member Portal Access</field>
      <field name="model_id"
             ref= "library_member.model_library_member"/>
      <field name="domain_force"
        >[('partner_id', '=',
         user.partner_id.id)]</field>
      <field name="groups"
        eval="[(4,ref('base.group_portal'))]"/>
    </record>
    <record id="checkout_portal_rule" model="ir.rule">
      <field name="name">
        Library Checkout Portal Access</field>
      <field name="model_id"
         ref="library_checkout.model_library_checkout"/>
      <field name="domain_force"
        >[('member_id.partner_id', '=',
           user.partner_id.id)]</field>
      <field name="groups"
             eval="[(4,ref('base.group_portal'))]"/>
    </record>
  </data>
</odoo>

controllers

自己的帳戶會顯示多種可用的文件類型,例如銷售訂單和發票,以及每種類型的項目數量。在controllers/init.py新增:

from . import portal

controllers/portal.py

from odoo.http import route, request
from odoo.addons.portal.controllers import portal
class CustomerPortal(portal.CustomerPortal):
    def _prepare_home_portal_values(self, counters):
        values = super()
          ._prepare_home_portal_values(counters)
        if "book_checkout_count" in counters:
            count =
           request.env[
            "library.checkout"].search_count([])
            values["book_checkout_count"] = count
        return values

views/portal_templates.py

<odoo>
    <template id="portal_my_home"
      inherit_id="portal.portal_my_home"
        name="Show Book Checkouts" priority="100"
        customize_show="True">
        <xpath expr="//div[hasclass('o_portal_docs')]"
            position="inside">
            <t t-call="portal.portal_docs_entry">
                <t t-set="title">Book Checkouts</t>
                <t t-set="url"
                 t-value="'/my/book-checkouts'"/>
                <t t-set="placeholder_count"
                   t-value="'book_checkout_count'"/>
            </t>
        </xpath>
    </template>

QWeb templates

在自己的帳戶主頁列出了各種可用的文件類型。
controllers/portal.py

    @route(
        ["/my/book-checkouts", "/my/book-checkouts/page/<int:page>"],
        auth="user",
        website=True,
    )
    def my_book_checkouts(self, page=1, **kw):
        Checkout = request.env["library.checkout"]
        domain = []
        # Prepare pager data
        checkout_count = Checkout.search_count(domain)
        pager_data = portal.pager(
            url="/my/book_checkouts",
            total=checkout_count,
            page=page,
            step=self._items_per_page,
        )
        # Recordset according to pager and domain filter
        checkouts = Checkout.search(
            domain, limit=self._items_per_page, offset=pager_data["offset"]
        )
        # Prepare template values
        values = self._prepare_portal_layout_values()
        values.update(
            {
                "checkouts": checkouts,
                "page_name": "book-checkouts",
                "default_url": "/my/book-checkouts",
                "pager": pager_data,
            }
        )
        return request.render("library_portal.my_book_checkouts", values)

views/portal_templates.xml

<template id="my_book_checkouts" name="My Book Checkouts">
      <t t-call="portal.portal_layout">
        <t t-if="checkouts" t-call="portal.portal_table">
          <thead>
            <tr>
              <th>Title</th>
              <th>Request Date</th>
              <th>Stage</th>
            </tr>
          </thead>
          <tbody>
            <tr t-foreach="checkouts" t-as="doc">
              <td>
                <a t-attf-href="/my/book-checkout/{{slug(doc)}}">
                  <span t-field="doc.name"/>
                </a>
              </td>
              <td>
                <span t-field="doc.request_date"/>
              </td>
              <td>
                <span t-field="doc.stage_id.name" class="badge badge-pill badge-info"/>
              </td>
            </tr>
          </tbody>
        </t>
        <t t-else="">
            <div class="alert alert-warning" role="alert">
              There are no book checkouts.
            </div>
        </t>
      </t>
    </template>

上一篇
[Day28] 客製化 PDF 輸出
下一篇
[Day30] 文章回顧,以及誰會需要客製化呢 !?
系列文
Odoo 魔法學院: 一步一腳印帶你成為客製化大師30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言