├── Chapter01 ├── README.md └── odoo-install.sh ├── Chapter02 ├── README.md └── odoo-install.sh ├── Chapter03 ├── README.md ├── docker-compose.yaml ├── odoo-install.sh └── odoo-ssl ├── Chapter04 └── my_library │ ├── __init__.py │ ├── __manifest__.py │ ├── controllers │ ├── __init__.py │ └── __pycache__ │ │ └── __init__.cpython-35.pyc │ ├── models │ ├── __init__.py │ ├── __pycache__ │ │ ├── __init__.cpython-35.pyc │ │ └── library_book.cpython-35.pyc │ └── library_book.py │ ├── security │ ├── groups.xml │ └── ir.model.access.csv │ ├── static │ └── description │ │ └── icon.png │ └── views │ └── library_book.xml ├── Chapter05 ├── r10_reference_fields │ └── my_library │ │ ├── __init__.py │ │ ├── __manifest__.py │ │ ├── controllers │ │ ├── __init__.py │ │ └── __pycache__ │ │ │ └── __init__.cpython-35.pyc │ │ ├── models │ │ ├── __init__.py │ │ ├── __pycache__ │ │ │ ├── __init__.cpython-35.pyc │ │ │ ├── library_book.cpython-35.pyc │ │ │ └── library_book_categ.cpython-35.pyc │ │ ├── library_book.py │ │ └── library_book_categ.py │ │ ├── security │ │ ├── groups.xml │ │ └── ir.model.access.csv │ │ ├── static │ │ └── description │ │ │ └── icon.png │ │ └── views │ │ ├── library_book.xml │ │ └── library_book_categ.xml ├── r11_model_inheritance │ └── my_library │ │ ├── __init__.py │ │ ├── __manifest__.py │ │ ├── controllers │ │ ├── __init__.py │ │ └── __pycache__ │ │ │ └── __init__.cpython-35.pyc │ │ ├── models │ │ ├── __init__.py │ │ ├── __pycache__ │ │ │ ├── __init__.cpython-35.pyc │ │ │ ├── library_book.cpython-35.pyc │ │ │ └── library_book_categ.cpython-35.pyc │ │ ├── library_book.py │ │ └── library_book_categ.py │ │ ├── security │ │ ├── groups.xml │ │ └── ir.model.access.csv │ │ ├── static │ │ └── description │ │ │ └── icon.png │ │ └── views │ │ ├── library_book.xml │ │ └── library_book_categ.xml ├── r12_abstract_models │ └── my_library │ │ ├── __init__.py │ │ ├── __manifest__.py │ │ ├── controllers │ │ ├── __init__.py │ │ └── __pycache__ │ │ │ └── __init__.cpython-35.pyc │ │ ├── models │ │ ├── __init__.py │ │ ├── __pycache__ │ │ │ ├── __init__.cpython-35.pyc │ │ │ ├── library_book.cpython-35.pyc │ │ │ └── library_book_categ.cpython-35.pyc │ │ ├── library_book.py │ │ └── library_book_categ.py │ │ ├── security │ │ ├── groups.xml │ │ └── ir.model.access.csv │ │ ├── static │ │ └── description │ │ │ └── icon.png │ │ └── views │ │ ├── library_book.xml │ │ └── library_book_categ.xml ├── r1_model_attr │ └── my_library │ │ ├── __init__.py │ │ ├── __manifest__.py │ │ ├── controllers │ │ ├── __init__.py │ │ └── __pycache__ │ │ │ └── __init__.cpython-35.pyc │ │ ├── models │ │ ├── __init__.py │ │ ├── __pycache__ │ │ │ ├── __init__.cpython-35.pyc │ │ │ └── library_book.cpython-35.pyc │ │ └── library_book.py │ │ ├── security │ │ ├── groups.xml │ │ └── ir.model.access.csv │ │ ├── static │ │ └── description │ │ │ └── icon.png │ │ └── views │ │ └── library_book.xml ├── r2_fields │ └── my_library │ │ ├── __init__.py │ │ ├── __manifest__.py │ │ ├── controllers │ │ ├── __init__.py │ │ └── __pycache__ │ │ │ └── __init__.cpython-35.pyc │ │ ├── models │ │ ├── __init__.py │ │ ├── __pycache__ │ │ │ ├── __init__.cpython-35.pyc │ │ │ └── library_book.cpython-35.pyc │ │ └── library_book.py │ │ ├── security │ │ ├── groups.xml │ │ └── ir.model.access.csv │ │ ├── static │ │ └── description │ │ │ └── icon.png │ │ └── views │ │ └── library_book.xml ├── r3_decimal_precision │ └── my_library │ │ ├── __init__.py │ │ ├── __manifest__.py │ │ ├── controllers │ │ ├── __init__.py │ │ └── __pycache__ │ │ │ └── __init__.cpython-35.pyc │ │ ├── models │ │ ├── __init__.py │ │ ├── __pycache__ │ │ │ ├── __init__.cpython-35.pyc │ │ │ └── library_book.cpython-35.pyc │ │ └── library_book.py │ │ ├── security │ │ ├── groups.xml │ │ └── ir.model.access.csv │ │ ├── static │ │ └── description │ │ │ └── icon.png │ │ └── views │ │ └── library_book.xml ├── r4_monetary_field │ └── my_library │ │ ├── __init__.py │ │ ├── __manifest__.py │ │ ├── controllers │ │ ├── __init__.py │ │ └── __pycache__ │ │ │ └── __init__.cpython-35.pyc │ │ ├── models │ │ ├── __init__.py │ │ ├── __pycache__ │ │ │ ├── __init__.cpython-35.pyc │ │ │ └── library_book.cpython-35.pyc │ │ └── library_book.py │ │ ├── security │ │ ├── groups.xml │ │ └── ir.model.access.csv │ │ ├── static │ │ └── description │ │ │ └── icon.png │ │ └── views │ │ └── library_book.xml ├── r5_relational_fields │ └── my_library │ │ ├── __init__.py │ │ ├── __manifest__.py │ │ ├── controllers │ │ ├── __init__.py │ │ └── __pycache__ │ │ │ └── __init__.cpython-35.pyc │ │ ├── models │ │ ├── __init__.py │ │ ├── __pycache__ │ │ │ ├── __init__.cpython-35.pyc │ │ │ └── library_book.cpython-35.pyc │ │ └── library_book.py │ │ ├── security │ │ ├── groups.xml │ │ └── ir.model.access.csv │ │ ├── static │ │ └── description │ │ │ └── icon.png │ │ └── views │ │ └── library_book.xml ├── r6_hierarchy_model │ └── my_library │ │ ├── __init__.py │ │ ├── __manifest__.py │ │ ├── controllers │ │ ├── __init__.py │ │ └── __pycache__ │ │ │ └── __init__.cpython-35.pyc │ │ ├── models │ │ ├── __init__.py │ │ ├── __pycache__ │ │ │ ├── __init__.cpython-35.pyc │ │ │ ├── library_book.cpython-35.pyc │ │ │ └── library_book_categ.cpython-35.pyc │ │ ├── library_book.py │ │ └── library_book_categ.py │ │ ├── security │ │ ├── groups.xml │ │ └── ir.model.access.csv │ │ ├── static │ │ └── description │ │ │ └── icon.png │ │ └── views │ │ ├── library_book.xml │ │ └── library_book_categ.xml ├── r7_constraints │ └── my_library │ │ ├── __init__.py │ │ ├── __manifest__.py │ │ ├── controllers │ │ ├── __init__.py │ │ └── __pycache__ │ │ │ └── __init__.cpython-35.pyc │ │ ├── models │ │ ├── __init__.py │ │ ├── __pycache__ │ │ │ ├── __init__.cpython-35.pyc │ │ │ ├── library_book.cpython-35.pyc │ │ │ └── library_book_categ.cpython-35.pyc │ │ ├── library_book.py │ │ └── library_book_categ.py │ │ ├── security │ │ ├── groups.xml │ │ └── ir.model.access.csv │ │ ├── static │ │ └── description │ │ │ └── icon.png │ │ └── views │ │ ├── library_book.xml │ │ └── library_book_categ.xml ├── r8_compute_fields │ └── my_library │ │ ├── __init__.py │ │ ├── __manifest__.py │ │ ├── controllers │ │ ├── __init__.py │ │ └── __pycache__ │ │ │ └── __init__.cpython-35.pyc │ │ ├── models │ │ ├── __init__.py │ │ ├── __pycache__ │ │ │ ├── __init__.cpython-35.pyc │ │ │ ├── library_book.cpython-35.pyc │ │ │ └── library_book_categ.cpython-35.pyc │ │ ├── library_book.py │ │ └── library_book_categ.py │ │ ├── security │ │ ├── groups.xml │ │ └── ir.model.access.csv │ │ ├── static │ │ └── description │ │ │ └── icon.png │ │ └── views │ │ ├── library_book.xml │ │ └── library_book_categ.xml └── r9_related_fields │ └── my_library │ ├── __init__.py │ ├── __manifest__.py │ ├── controllers │ ├── __init__.py │ └── __pycache__ │ │ └── __init__.cpython-35.pyc │ ├── models │ ├── __init__.py │ ├── __pycache__ │ │ ├── __init__.cpython-35.pyc │ │ ├── library_book.cpython-35.pyc │ │ └── library_book_categ.cpython-35.pyc │ ├── library_book.py │ └── library_book_categ.py │ ├── security │ ├── groups.xml │ └── ir.model.access.csv │ ├── static │ └── description │ │ └── icon.png │ └── views │ ├── library_book.xml │ └── library_book_categ.xml └── README.md /Chapter01/README.md: -------------------------------------------------------------------------------- 1 | # Odoo 12.0 Install Script 2 | 3 | This script is based on Chapter 1 of Odoo 12 Development Cookbook Third Edition 4 | 5 | ## Installation procedure 6 | 7 | ##### 1. Download the script: 8 | ``` 9 | wget https://raw.githubusercontent.com/alanhou/odoo12-cookbook/master/Chapter01/odoo-install.sh 10 | ``` 11 | 12 | #### 2. Make the script executable 13 | ``` 14 | sudo chmod +x odoo-install.sh 15 | ``` 16 | ##### 3. Execute the script: 17 | ``` 18 | sudo ./odoo-install.sh 19 | ``` 20 | 21 | ##### 4. Stop all Odoo proccesses: 22 | ``` 23 | ps -ef | grep odoo | awk '{ print $2}' | xargs kill -9 24 | ``` 25 | 26 | ##### 5. To restart Odoo with logs enabled: 27 | ``` 28 | ~/odoo-12.0/bin/python3 ~/odoo-dev/odoo/odoo-bin -d odoo-test 29 | ``` 30 | -------------------------------------------------------------------------------- /Chapter01/odoo-install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ################################################################################ 3 | # Script for installing Odoo 12 on Ubuntu & Debian 4 | # Author: Alan Hou 5 | # Website: https://alanhou.org 6 | #------------------------------------------------------------------------------- 7 | # sudo chmod +x odoo-install.sh 8 | # ./odoo-install.sh 9 | ################################################################################ 10 | 11 | # IP_ADDR=`ifconfig -a|grep inet|grep -v 127.0.0.1|grep -v inet6|awk '{print $2}'|tr -d "addr:"​|head -1` 12 | IP_ADDR=`ip addr | grep 'state UP' -A2 | grep inet|grep -v docker|tail -n1 | awk '{print $2}' | cut -f1 -d'/'` 13 | 14 | echo -e "\n---- Update Ubuntu ----" 15 | sudo apt-get update 16 | 17 | echo -e "\n---- Install main dependencies ----" 18 | sudo apt-get install -y git python3.5 postgresql nano \ 19 | virtualenv xz-utils wget fontconfig libfreetype6 libx11-6 \ 20 | libxext6 libxrender1 xfonts-75dpi 21 | 22 | echo -e "\n---- Install wkhtmltopdf ----" 23 | wget "https://github.com/wkhtmltopdf/wkhtmltopdf/releases/download/0.12.5/wkhtmltox_0.12.5-1.xenial_amd64.deb" -O /tmp/wkhtml.deb 24 | sudo dpkg -i /tmp/wkhtml.deb 25 | sudo apt-get -fy install 26 | 27 | echo -e "\n---- Install build dependencies ----" 28 | sudo apt-get install -y gcc python3.5-dev libxml2-dev \ 29 | libxslt1-dev libevent-dev libsasl2-dev libssl-dev libldap2-dev \ 30 | libpq-dev libpng-dev libjpeg-dev 31 | 32 | echo -e "\n---- Configure PostgreSQL ----" 33 | sudo -u postgres createuser --createdb $(whoami) 34 | createdb $(whoami) 35 | 36 | # echo -e "\n---- Configure git ----" 37 | # git config --global user.name "Your Name" 38 | # git config --global user.email youremail@example.com 39 | 40 | echo -e "\n---- Clone the Odoo code base ----" 41 | mkdir ~/odoo-dev 42 | cd ~/odoo-dev 43 | git clone -b 12.0 --depth 1 --single-branch https://github.com/odoo/odoo.git 44 | cd odoo 45 | 46 | echo -e "\n---- Create virtualenv ----" 47 | virtualenv -p python3 ~/odoo-12.0 48 | # source ~/odoo-12.0/bin/activate 49 | 50 | echo -e "\n---- Install Python dependencies ----" 51 | ~/odoo-12.0/bin/pip3 install -r requirements.txt 52 | 53 | echo -e "\n---- Start Odoo instance ----" 54 | cd ~/odoo-dev/odoo/ 55 | nohup ~/odoo-12.0/bin/python3 ~/odoo-dev/odoo/odoo-bin -d odoo-test --addons-path=~/odoo-dev/odoo/addons \ 56 | --db-filter=odoo-test$ -i base >/dev/null 2>&1 & 57 | 58 | echo "-----------------------------------------------------------" 59 | echo "Done! Open your browser and visit http://localhost:8069 or http://${IP_ADDR}:8069" 60 | echo "Default login & password: admin" 61 | echo "Stop all Odoo proccesses: ps -ef | grep odoo | awk '{ print $2}' | xargs kill -9" 62 | echo "To restart Odoo with logs enabled: ~/odoo-12.0/bin/python3 ~/odoo-dev/odoo/odoo-bin -d odoo-test" 63 | echo "-----------------------------------------------------------" -------------------------------------------------------------------------------- /Chapter02/README.md: -------------------------------------------------------------------------------- 1 | # Odoo 12.0 Install Script 2 | #### With standardized structure for production 3 | 4 | This script is based on Chapter 2 of Odoo 12 Development Cookbook Third Edition 5 | 6 | ## Installation procedure 7 | 8 | ##### 1. Download the script: 9 | ``` 10 | wget https://raw.githubusercontent.com/alanhou/odoo12-cookbook/master/Chapter02/odoo-install.sh 11 | ``` 12 | 13 | #### 2. Make the script executable & Execute the script: 14 | ``` 15 | sudo chmod +x odoo-install.sh && bash odoo-install.sh 16 | ``` 17 | 18 | ##### 3. Start Odoo(you may need to change projectname & dbname): 19 | ``` 20 | ~/odoo-dev/projectname/bin/odoo -d dbname start Odoo 21 | ``` 22 | 23 | 24 | ## Start Odoo manually 25 | 26 | ##### 1. Activate virtualenv: 27 | ``` 28 | source ~/odoo-dev/projectname/env/bin/activate 29 | ``` 30 | 31 | ##### 2. Go to the Odoo source directory: 32 | ``` 33 | cd ~/odoo-dev/${projectname}/src/odoo 34 | ``` 35 | 36 | ##### 3. Start odoo: 37 | ``` 38 | ./odoo-bin --addons-path=addons,../../local -d test-12 -i account,sale,purchase --log-level=debug" 39 | ``` -------------------------------------------------------------------------------- /Chapter02/odoo-install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ################################################################################ 3 | # Script for installing Odoo 12 with standardized structure 4 | # Author: Alan Hou 5 | # Website: https://alanhou.org 6 | #------------------------------------------------------------------------------- 7 | # sudo chmod +x odoo-install.sh && bash odoo-install.sh 8 | ################################################################################ 9 | 10 | echo "Please input your project name:" 11 | read -t 30 -p "(Default: projectname):" projectname 12 | if [ -z "${projectname}" ];then 13 | projectname="projectname" 14 | fi 15 | 16 | read -t 30 -p "Please input your Git username(Hit Enter to skip):" git_user 17 | read -t 30 -p "Please input your Git email(Hit Enter to skip):" git_email 18 | 19 | # IP_ADDR=`ifconfig -a|grep inet|grep -v 127.0.0.1|grep -v inet6|awk '{print $2}'|tr -d "addr:"​|head -1` 20 | IP_ADDR=`ip addr | grep 'state UP' -A2 | grep inet|grep -v docker|tail -n1 | awk '{print $2}' | cut -f1 -d'/'` 21 | 22 | echo -e "\n---- Update Ubuntu ----" 23 | wget -q -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add - 24 | sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt/ $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list' 25 | sudo apt-get update 26 | 27 | echo -e "\n---- Install main dependencies ----" 28 | sudo apt-get install -y git python3.5 postgresql-10 nano \ 29 | virtualenv xz-utils wget fontconfig libfreetype6 libx11-6 \ 30 | libxext6 libxrender1 xfonts-75dpi 31 | 32 | echo -e "\n---- Install wkhtmltopdf ----" 33 | wget "https://github.com/wkhtmltopdf/wkhtmltopdf/releases/download/0.12.5/wkhtmltox_0.12.5-1.xenial_amd64.deb" -O /tmp/wkhtml.deb 34 | sudo dpkg -i /tmp/wkhtml.deb 35 | sudo apt-get -fy install 36 | 37 | echo -e "\n---- Install build dependencies ----" 38 | sudo apt-get install -y gcc python3.5-dev libxml2-dev \ 39 | libxslt1-dev libevent-dev libsasl2-dev libssl-dev libldap2-dev \ 40 | libpq-dev libpng-dev libjpeg-dev 41 | 42 | echo -e "\n---- Configure PostgreSQL ----" 43 | sudo -u postgres createuser --createdb $(whoami) 44 | createdb $(whoami) 45 | 46 | 47 | echo -e "\n---- Create Project Directory ----" 48 | mkdir -p ~/odoo-dev/${projectname} 49 | cd ~/odoo-dev/${projectname} 50 | 51 | echo -e "\n---- Create standardized directories ----" 52 | virtualenv -p python3 env 53 | mkdir src local bin filestore logs 54 | git clone -b 12.0 --depth 1 --single-branch https://github.com/odoo/odoo.git src/odoo 55 | env/bin/pip3 install -r src/odoo/requirements.txt 56 | 57 | 58 | echo -e "\n---- Create bin/odoo ----" 59 | cat>bin/odoo<\ 74 | local/dummy/__manifest__.py 75 | 76 | 77 | echo -e "\n---- Initialize config file ----" 78 | bin/odoo --stop-after-init --save \ 79 | --addons-path src/odoo/odoo/addons,src/odoo/addons,local \ 80 | --data-dir filestore 81 | 82 | echo -e "\n---- Add .gitignore ----" 83 | cat>.gitignore<~/odoo-prod/project/bin/start-odoo<<'EOF' 51 | #!/bin/sh 52 | PYTHON=~/env-odoo-12.0/bin/python3 53 | ODOO=~/odoo-prod/project/src/odoo/odoo-bin 54 | CONF=~/odoo-prod/project/production.conf 55 | \${PYTHON} \${ODOO} -c \${CONF} "\$@" 56 | EOF 57 | 58 | chmod +x ~/odoo-prod/project/bin/start-odoo 59 | cd ~/odoo-prod/project/ 60 | mkdir local-addons filestore logs 61 | echo -e "\n---- Dummy hack ----" 62 | mkdir -p local-addons/dummy 63 | touch local-addons/dummy/__init__.py 64 | echo '{"name": "dummy", "installable": False}' >\ 65 | local/dummy/__manifest__.py 66 | 67 | echo -e "\n---- Add .gitignore ----" 68 | cat>.gitignore< 2 | 3 | 4 | Librarians 5 | 6 | 7 | -------------------------------------------------------------------------------- /Chapter04/my_library/security/ir.model.access.csv: -------------------------------------------------------------------------------- 1 | id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink 2 | acl_book,library.book_default,model_library_book,,1,0,0,0 3 | acl_book_librarian,library.book_librarian,model_library_book,group_librarian,1,1,1,1 -------------------------------------------------------------------------------- /Chapter04/my_library/static/description/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanhou/odoo12-cookbook/db40c23e67668c081410de189c77b88d2afe1dd8/Chapter04/my_library/static/description/icon.png -------------------------------------------------------------------------------- /Chapter04/my_library/views/library_book.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | Library Books 6 | library.book 7 | form 8 | tree,form 9 | 10 | 11 | 12 | 14 | 15 | 16 | Library Book Form 17 | library.book 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 |
31 |
32 | 33 | 34 | Libray Book List 35 | library.book 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | Library Book Search 46 | library.book 47 | 48 | 49 | 50 | 51 | 54 | 55 | 56 | 57 |
-------------------------------------------------------------------------------- /Chapter05/r10_reference_fields/my_library/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from . import models 3 | from . import controllers -------------------------------------------------------------------------------- /Chapter05/r10_reference_fields/my_library/__manifest__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | { 3 | 'name': 'My Library', 4 | 'summary': '轻松管理图书', 5 | 'description': """长描述占位""", 6 | 'author': 'Alan Hou', 7 | 'website': 'https://alanhou.org', 8 | 'category': 'Uncategorized', 9 | 'version': '12.0.1', 10 | 'depends': ['base', 'decimal_precision'], 11 | 'data': [ 12 | 'security/groups.xml', 13 | 'security/ir.model.access.csv', 14 | 'views/library_book.xml', 15 | 'views/library_book_categ.xml', 16 | ], 17 | } -------------------------------------------------------------------------------- /Chapter05/r10_reference_fields/my_library/controllers/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanhou/odoo12-cookbook/db40c23e67668c081410de189c77b88d2afe1dd8/Chapter05/r10_reference_fields/my_library/controllers/__init__.py -------------------------------------------------------------------------------- /Chapter05/r10_reference_fields/my_library/controllers/__pycache__/__init__.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanhou/odoo12-cookbook/db40c23e67668c081410de189c77b88d2afe1dd8/Chapter05/r10_reference_fields/my_library/controllers/__pycache__/__init__.cpython-35.pyc -------------------------------------------------------------------------------- /Chapter05/r10_reference_fields/my_library/models/__init__.py: -------------------------------------------------------------------------------- 1 | from . import library_book 2 | from . import library_book_categ -------------------------------------------------------------------------------- /Chapter05/r10_reference_fields/my_library/models/__pycache__/__init__.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanhou/odoo12-cookbook/db40c23e67668c081410de189c77b88d2afe1dd8/Chapter05/r10_reference_fields/my_library/models/__pycache__/__init__.cpython-35.pyc -------------------------------------------------------------------------------- /Chapter05/r10_reference_fields/my_library/models/__pycache__/library_book.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanhou/odoo12-cookbook/db40c23e67668c081410de189c77b88d2afe1dd8/Chapter05/r10_reference_fields/my_library/models/__pycache__/library_book.cpython-35.pyc -------------------------------------------------------------------------------- /Chapter05/r10_reference_fields/my_library/models/__pycache__/library_book_categ.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanhou/odoo12-cookbook/db40c23e67668c081410de189c77b88d2afe1dd8/Chapter05/r10_reference_fields/my_library/models/__pycache__/library_book_categ.cpython-35.pyc -------------------------------------------------------------------------------- /Chapter05/r10_reference_fields/my_library/models/library_book.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from datetime import timedelta 3 | 4 | from odoo import models, fields, api 5 | from odoo.exceptions import ValidationError 6 | from odoo.addons import decimal_precision as dp 7 | 8 | 9 | class LibraryBook(models.Model): 10 | _name = 'library.book' 11 | _description = 'Library Book' 12 | _order = 'date_release desc, name' 13 | _rec_name = 'short_name' 14 | 15 | name = fields.Char('Title', required=True) 16 | short_name = fields.Char('Short Title', translate=True, index=True) 17 | notes = fields.Text('Internal Notes') 18 | state = fields.Selection( 19 | [('draft', 'Not Available'), 20 | ('available', 'Available'), 21 | ('lost', 'Lost')], 22 | 'State', default="draft") 23 | description = fields.Html('Description', sanitize=True, strip_style=False) 24 | cover = fields.Binary('Book Cover') 25 | out_of_print = fields.Boolean('Out of Print?') 26 | date_release = fields.Date('Release Date') 27 | date_updated = fields.Datetime('Last Updated') 28 | pages = fields.Integer('Number of Pages', 29 | groups="base.group_user", 30 | state={'lost': [('readonly', True)]}, 31 | help="Total book page count", company_dependent=False) 32 | reader_rating = fields.Float( 33 | 'Reader Average Rating', 34 | digits=(14, 4), # 可选精度(总数,小数) 35 | ) 36 | author_ids = fields.Many2many( 37 | 'res.partner', 38 | string='Authors' 39 | ) 40 | cost_price = fields.Float('Book Cost', digits=dp.get_precision('Book Price')) 41 | currency_id = fields.Many2one('res.currency', string='Currency') 42 | retail_price = fields.Monetary('Retail Price') # 可选属性:currency_field='currency_id',以防币种字段有currency_id 以外的名称 43 | 44 | publisher_id = fields.Many2one( 45 | 'res.partner', string='Publisher', 46 | # 下为可选项 47 | ondelete='set null', 48 | context = {}, 49 | domain = [], 50 | ) 51 | publisher_city = fields.Char('Publisher City', related='publisher_id.city', readonly=True) 52 | category_id = fields.Many2one('library.book.category') 53 | age_days = fields.Float( 54 | string='Days Since Release', 55 | compute='_compute_age', inverse='_inverse_age', search='_search_age', 56 | store=False, 57 | compute_sudo=False, 58 | ) 59 | ref_doc_id = fields.Reference(selection='_referencable_model', string='Reference Document') 60 | 61 | @api.depends('date_release') 62 | def _compute_age(self): 63 | today = fields.Date.today() 64 | for book in self.filtered('date_release'): 65 | delta = today - book.date_release 66 | book.age_days = delta.days 67 | 68 | 69 | # 这一_compute_age的反向方法用于让 age_days 字段可编辑 70 | # 这是可选项,如果不想让该计算字段可编辑可以进行删除 71 | def _inverse_age(self): 72 | today = fields.Date.today() 73 | for book in self.filtered('date_release'): 74 | d = today - timedelta(days=book.age_days) 75 | book.date_release = d 76 | 77 | # 用于启动对计算字段的搜索 78 | # 这是可选项,如果不想启用该搜索可以进行删除 79 | def _search_age(self, operator, value): 80 | today = fields.Date.today() 81 | value_days = timedelta(days=value) 82 | value_date = today - value_days 83 | # 转换运算符 84 | # age > value 对应 date < value_date 85 | operator_map = { 86 | '>': '<', '>=': '<=', 87 | '<': '>', '<=': '>=', 88 | } 89 | new_op = operator_map.get(operator, operator) 90 | return [('date_release', new_op, value_date)] 91 | 92 | @api.model 93 | def _referencable_model(self): 94 | models = self.env['ir.model'].search([('field_id.name', '=', 'message_ids')]) 95 | return [(x.model, x.name) for x in models] 96 | 97 | def name_get(self): 98 | """ 这个方法用于自定义记录的显示名称 """ 99 | result = [] 100 | for record in self: 101 | rec_name = "%s (%s)" % (record.name, record.date_release) 102 | result.append((record.id, rec_name)) 103 | return result 104 | 105 | _sql_constraints = [('name_uniq', 'UNIQUE(name)', 'Book title must be unique.')] 106 | 107 | @api.constrains('date_release') 108 | def _check_release_date(self): 109 | for record in self: 110 | if record.date_release and record.date_release > fields.Date.today(): 111 | raise models.ValidationError('Release date must be in the past') 112 | 113 | 114 | class ResPartner(models.Model): 115 | _inherit = 'res.partner' 116 | 117 | published_book_ids = fields.One2many( 118 | 'library.book', 119 | 'publisher_id', 120 | string='Published Books' 121 | ) 122 | authored_book_ids = fields.Many2many( 123 | 'library.book', 124 | string = 'Authored Books', 125 | # relation='library_book_res_partner_rel' # 可选项 126 | ) -------------------------------------------------------------------------------- /Chapter05/r10_reference_fields/my_library/models/library_book_categ.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from odoo import models, fields, api 3 | 4 | 5 | class BookCategory(models.Model): 6 | _name = 'library.book.category' 7 | 8 | _parent_store = True 9 | _parent_name = "parent_id" # 如字段为parent_id是可选项 10 | 11 | name = fields.Char('Category') 12 | parent_id = fields.Many2one( 13 | 'library.book.category', 14 | string='Parent Category', 15 | ondelete='restrict', 16 | index=True 17 | ) 18 | child_ids = fields.One2many( 19 | 'library.book.category', 'parent_id', 20 | string='Child Categories' 21 | ) 22 | parent_path = fields.Char(index=True) 23 | 24 | @api.constrains('parent_id') 25 | def _check_hierarchy(self): 26 | if not self._check_recursion(): 27 | raise models.ValidationError('Error! You cannot create recursive categories.') -------------------------------------------------------------------------------- /Chapter05/r10_reference_fields/my_library/security/groups.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Librarians 5 | 6 | 7 | -------------------------------------------------------------------------------- /Chapter05/r10_reference_fields/my_library/security/ir.model.access.csv: -------------------------------------------------------------------------------- 1 | id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink 2 | acl_book,library.book_default,model_library_book,,1,0,0,0 3 | acl_book_librarian,library.book_librarian,model_library_book,group_librarian,1,1,1,1 4 | acl_book_category,library.book_category_default,model_library_book_category,,1,0,0,0 5 | acl_book_category_librarian,library.book_category_librarian,model_library_book_category,group_librarian,1,1,1,1 -------------------------------------------------------------------------------- /Chapter05/r10_reference_fields/my_library/static/description/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanhou/odoo12-cookbook/db40c23e67668c081410de189c77b88d2afe1dd8/Chapter05/r10_reference_fields/my_library/static/description/icon.png -------------------------------------------------------------------------------- /Chapter05/r10_reference_fields/my_library/views/library_book.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | Library Books 6 | library.book 7 | form 8 | tree,form 9 | 10 | 11 | 12 | 14 | 15 | 16 | Library Book Form 17 | library.book 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 |
48 |
49 |
50 | 51 | 52 | Libray Book List 53 | library.book 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | Library Book Search 64 | library.book 65 | 66 | 67 | 68 | 69 | 72 | 73 | 74 | 75 |
-------------------------------------------------------------------------------- /Chapter05/r10_reference_fields/my_library/views/library_book_categ.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Book Categories 6 | library.book.category 7 | form 8 | tree,form 9 | 10 | 11 | 12 | 13 | 14 | 15 | Library Categories Form 16 | library.book.category 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 |
32 |
33 | 34 | 35 | 36 | Library Book List 37 | library.book.category 38 | 39 | 40 | 41 | 42 | 43 | 44 |
-------------------------------------------------------------------------------- /Chapter05/r11_model_inheritance/my_library/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from . import models 3 | from . import controllers -------------------------------------------------------------------------------- /Chapter05/r11_model_inheritance/my_library/__manifest__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | { 3 | 'name': 'My Library', 4 | 'summary': '轻松管理图书', 5 | 'description': """长描述占位""", 6 | 'author': 'Alan Hou', 7 | 'website': 'https://alanhou.org', 8 | 'category': 'Uncategorized', 9 | 'version': '12.0.1', 10 | 'depends': ['base', 'decimal_precision'], 11 | 'data': [ 12 | 'security/groups.xml', 13 | 'security/ir.model.access.csv', 14 | 'views/library_book.xml', 15 | 'views/library_book_categ.xml', 16 | ], 17 | } -------------------------------------------------------------------------------- /Chapter05/r11_model_inheritance/my_library/controllers/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanhou/odoo12-cookbook/db40c23e67668c081410de189c77b88d2afe1dd8/Chapter05/r11_model_inheritance/my_library/controllers/__init__.py -------------------------------------------------------------------------------- /Chapter05/r11_model_inheritance/my_library/controllers/__pycache__/__init__.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanhou/odoo12-cookbook/db40c23e67668c081410de189c77b88d2afe1dd8/Chapter05/r11_model_inheritance/my_library/controllers/__pycache__/__init__.cpython-35.pyc -------------------------------------------------------------------------------- /Chapter05/r11_model_inheritance/my_library/models/__init__.py: -------------------------------------------------------------------------------- 1 | from . import library_book 2 | from . import library_book_categ -------------------------------------------------------------------------------- /Chapter05/r11_model_inheritance/my_library/models/__pycache__/__init__.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanhou/odoo12-cookbook/db40c23e67668c081410de189c77b88d2afe1dd8/Chapter05/r11_model_inheritance/my_library/models/__pycache__/__init__.cpython-35.pyc -------------------------------------------------------------------------------- /Chapter05/r11_model_inheritance/my_library/models/__pycache__/library_book.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanhou/odoo12-cookbook/db40c23e67668c081410de189c77b88d2afe1dd8/Chapter05/r11_model_inheritance/my_library/models/__pycache__/library_book.cpython-35.pyc -------------------------------------------------------------------------------- /Chapter05/r11_model_inheritance/my_library/models/__pycache__/library_book_categ.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanhou/odoo12-cookbook/db40c23e67668c081410de189c77b88d2afe1dd8/Chapter05/r11_model_inheritance/my_library/models/__pycache__/library_book_categ.cpython-35.pyc -------------------------------------------------------------------------------- /Chapter05/r11_model_inheritance/my_library/models/library_book.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from datetime import timedelta 3 | 4 | from odoo import models, fields, api 5 | from odoo.exceptions import ValidationError 6 | from odoo.addons import decimal_precision as dp 7 | 8 | 9 | class LibraryBook(models.Model): 10 | _name = 'library.book' 11 | _description = 'Library Book' 12 | _order = 'date_release desc, name' 13 | _rec_name = 'short_name' 14 | 15 | name = fields.Char('Title', required=True) 16 | short_name = fields.Char('Short Title', translate=True, index=True) 17 | notes = fields.Text('Internal Notes') 18 | state = fields.Selection( 19 | [('draft', 'Not Available'), 20 | ('available', 'Available'), 21 | ('lost', 'Lost')], 22 | 'State', default="draft") 23 | description = fields.Html('Description', sanitize=True, strip_style=False) 24 | cover = fields.Binary('Book Cover') 25 | out_of_print = fields.Boolean('Out of Print?') 26 | date_release = fields.Date('Release Date') 27 | date_updated = fields.Datetime('Last Updated') 28 | pages = fields.Integer('Number of Pages', 29 | groups="base.group_user", 30 | state={'lost': [('readonly', True)]}, 31 | help="Total book page count", company_dependent=False) 32 | reader_rating = fields.Float( 33 | 'Reader Average Rating', 34 | digits=(14, 4), # 可选精度(总数,小数) 35 | ) 36 | author_ids = fields.Many2many( 37 | 'res.partner', 38 | string='Authors' 39 | ) 40 | cost_price = fields.Float('Book Cost', digits=dp.get_precision('Book Price')) 41 | currency_id = fields.Many2one('res.currency', string='Currency') 42 | retail_price = fields.Monetary('Retail Price') # 可选属性:currency_field='currency_id',以防币种字段有currency_id 以外的名称 43 | 44 | publisher_id = fields.Many2one( 45 | 'res.partner', string='Publisher', 46 | # 下为可选项 47 | ondelete='set null', 48 | context = {}, 49 | domain = [], 50 | ) 51 | publisher_city = fields.Char('Publisher City', related='publisher_id.city', readonly=True) 52 | category_id = fields.Many2one('library.book.category') 53 | age_days = fields.Float( 54 | string='Days Since Release', 55 | compute='_compute_age', inverse='_inverse_age', search='_search_age', 56 | store=False, 57 | compute_sudo=False, 58 | ) 59 | ref_doc_id = fields.Reference(selection='_referencable_model', string='Reference Document') 60 | 61 | @api.depends('date_release') 62 | def _compute_age(self): 63 | today = fields.Date.today() 64 | for book in self.filtered('date_release'): 65 | delta = today - book.date_release 66 | book.age_days = delta.days 67 | 68 | 69 | # 这一_compute_age的反向方法用于让 age_days 字段可编辑 70 | # 这是可选项,如果不想让该计算字段可编辑可以进行删除 71 | def _inverse_age(self): 72 | today = fields.Date.today() 73 | for book in self.filtered('date_release'): 74 | d = today - timedelta(days=book.age_days) 75 | book.date_release = d 76 | 77 | # 用于启动对计算字段的搜索 78 | # 这是可选项,如果不想启用该搜索可以进行删除 79 | def _search_age(self, operator, value): 80 | today = fields.Date.today() 81 | value_days = timedelta(days=value) 82 | value_date = today - value_days 83 | # 转换运算符 84 | # age > value 对应 date < value_date 85 | operator_map = { 86 | '>': '<', '>=': '<=', 87 | '<': '>', '<=': '>=', 88 | } 89 | new_op = operator_map.get(operator, operator) 90 | return [('date_release', new_op, value_date)] 91 | 92 | @api.model 93 | def _referencable_model(self): 94 | models = self.env['ir.model'].search([('field_id.name', '=', 'message_ids')]) 95 | return [(x.model, x.name) for x in models] 96 | 97 | def name_get(self): 98 | """ 这个方法用于自定义记录的显示名称 """ 99 | result = [] 100 | for record in self: 101 | rec_name = "%s (%s)" % (record.name, record.date_release) 102 | result.append((record.id, rec_name)) 103 | return result 104 | 105 | _sql_constraints = [('name_uniq', 'UNIQUE(name)', 'Book title must be unique.')] 106 | 107 | @api.constrains('date_release') 108 | def _check_release_date(self): 109 | for record in self: 110 | if record.date_release and record.date_release > fields.Date.today(): 111 | raise models.ValidationError('Release date must be in the past') 112 | 113 | 114 | class ResPartner(models.Model): 115 | _inherit = 'res.partner' 116 | 117 | published_book_ids = fields.One2many( 118 | 'library.book', 119 | 'publisher_id', 120 | string='Published Books' 121 | ) 122 | authored_book_ids = fields.Many2many( 123 | 'library.book', 124 | string = 'Authored Books', 125 | # relation='library_book_res_partner_rel' # 可选项 126 | ) 127 | count_books = fields.Integer('Number of Authored Books', compute='_compute_count_books') 128 | 129 | @api.depends('authored_book_ids') 130 | def _compute_count_books(self): 131 | for r in self: 132 | r.count_books = len(r.authored_book_ids) -------------------------------------------------------------------------------- /Chapter05/r11_model_inheritance/my_library/models/library_book_categ.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from odoo import models, fields, api 3 | 4 | 5 | class BookCategory(models.Model): 6 | _name = 'library.book.category' 7 | 8 | _parent_store = True 9 | _parent_name = "parent_id" # 如字段为parent_id是可选项 10 | 11 | name = fields.Char('Category') 12 | parent_id = fields.Many2one( 13 | 'library.book.category', 14 | string='Parent Category', 15 | ondelete='restrict', 16 | index=True 17 | ) 18 | child_ids = fields.One2many( 19 | 'library.book.category', 'parent_id', 20 | string='Child Categories' 21 | ) 22 | parent_path = fields.Char(index=True) 23 | 24 | @api.constrains('parent_id') 25 | def _check_hierarchy(self): 26 | if not self._check_recursion(): 27 | raise models.ValidationError('Error! You cannot create recursive categories.') -------------------------------------------------------------------------------- /Chapter05/r11_model_inheritance/my_library/security/groups.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Librarians 5 | 6 | 7 | -------------------------------------------------------------------------------- /Chapter05/r11_model_inheritance/my_library/security/ir.model.access.csv: -------------------------------------------------------------------------------- 1 | id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink 2 | acl_book,library.book_default,model_library_book,,1,0,0,0 3 | acl_book_librarian,library.book_librarian,model_library_book,group_librarian,1,1,1,1 4 | acl_book_category,library.book_category_default,model_library_book_category,,1,0,0,0 5 | acl_book_category_librarian,library.book_category_librarian,model_library_book_category,group_librarian,1,1,1,1 -------------------------------------------------------------------------------- /Chapter05/r11_model_inheritance/my_library/static/description/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanhou/odoo12-cookbook/db40c23e67668c081410de189c77b88d2afe1dd8/Chapter05/r11_model_inheritance/my_library/static/description/icon.png -------------------------------------------------------------------------------- /Chapter05/r11_model_inheritance/my_library/views/library_book.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | Library Books 6 | library.book 7 | form 8 | tree,form 9 | 10 | 11 | 12 | 14 | 15 | 16 | Library Book Form 17 | library.book 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 |
48 |
49 |
50 | 51 | 52 | Libray Book List 53 | library.book 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | Library Book Search 64 | library.book 65 | 66 | 67 | 68 | 69 | 72 | 73 | 74 | 75 |
-------------------------------------------------------------------------------- /Chapter05/r11_model_inheritance/my_library/views/library_book_categ.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Book Categories 6 | library.book.category 7 | form 8 | tree,form 9 | 10 | 11 | 12 | 13 | 14 | 15 | Library Categories Form 16 | library.book.category 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 |
32 |
33 | 34 | 35 | 36 | Library Book List 37 | library.book.category 38 | 39 | 40 | 41 | 42 | 43 | 44 |
-------------------------------------------------------------------------------- /Chapter05/r12_abstract_models/my_library/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from . import models 3 | from . import controllers -------------------------------------------------------------------------------- /Chapter05/r12_abstract_models/my_library/__manifest__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | { 3 | 'name': 'My Library', 4 | 'summary': '轻松管理图书', 5 | 'description': """长描述占位""", 6 | 'author': 'Alan Hou', 7 | 'website': 'https://alanhou.org', 8 | 'category': 'Uncategorized', 9 | 'version': '12.0.1', 10 | 'depends': ['base', 'decimal_precision'], 11 | 'data': [ 12 | 'security/groups.xml', 13 | 'security/ir.model.access.csv', 14 | 'views/library_book.xml', 15 | 'views/library_book_categ.xml', 16 | ], 17 | } -------------------------------------------------------------------------------- /Chapter05/r12_abstract_models/my_library/controllers/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanhou/odoo12-cookbook/db40c23e67668c081410de189c77b88d2afe1dd8/Chapter05/r12_abstract_models/my_library/controllers/__init__.py -------------------------------------------------------------------------------- /Chapter05/r12_abstract_models/my_library/controllers/__pycache__/__init__.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanhou/odoo12-cookbook/db40c23e67668c081410de189c77b88d2afe1dd8/Chapter05/r12_abstract_models/my_library/controllers/__pycache__/__init__.cpython-35.pyc -------------------------------------------------------------------------------- /Chapter05/r12_abstract_models/my_library/models/__init__.py: -------------------------------------------------------------------------------- 1 | from . import library_book 2 | from . import library_book_categ -------------------------------------------------------------------------------- /Chapter05/r12_abstract_models/my_library/models/__pycache__/__init__.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanhou/odoo12-cookbook/db40c23e67668c081410de189c77b88d2afe1dd8/Chapter05/r12_abstract_models/my_library/models/__pycache__/__init__.cpython-35.pyc -------------------------------------------------------------------------------- /Chapter05/r12_abstract_models/my_library/models/__pycache__/library_book.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanhou/odoo12-cookbook/db40c23e67668c081410de189c77b88d2afe1dd8/Chapter05/r12_abstract_models/my_library/models/__pycache__/library_book.cpython-35.pyc -------------------------------------------------------------------------------- /Chapter05/r12_abstract_models/my_library/models/__pycache__/library_book_categ.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanhou/odoo12-cookbook/db40c23e67668c081410de189c77b88d2afe1dd8/Chapter05/r12_abstract_models/my_library/models/__pycache__/library_book_categ.cpython-35.pyc -------------------------------------------------------------------------------- /Chapter05/r12_abstract_models/my_library/models/library_book.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from datetime import timedelta 3 | 4 | from odoo import models, fields, api 5 | from odoo.exceptions import ValidationError 6 | from odoo.addons import decimal_precision as dp 7 | 8 | 9 | class BaseArchive(models.AbstractModel): 10 | _name = 'base.archive' 11 | active = fields.Boolean(default=True) 12 | 13 | def do_archive(self): 14 | for record in self: 15 | record.active = not record.active 16 | 17 | 18 | class LibraryBook(models.Model): 19 | _name = 'library.book' 20 | _description = 'Library Book' 21 | 22 | _inherit = ['base.archive'] 23 | _order = 'date_release desc, name' 24 | _rec_name = 'short_name' 25 | 26 | name = fields.Char('Title', required=True) 27 | short_name = fields.Char('Short Title', translate=True, index=True) 28 | notes = fields.Text('Internal Notes') 29 | state = fields.Selection( 30 | [('draft', 'Not Available'), 31 | ('available', 'Available'), 32 | ('lost', 'Lost')], 33 | 'State', default="draft") 34 | description = fields.Html('Description', sanitize=True, strip_style=False) 35 | cover = fields.Binary('Book Cover') 36 | out_of_print = fields.Boolean('Out of Print?') 37 | date_release = fields.Date('Release Date') 38 | date_updated = fields.Datetime('Last Updated') 39 | pages = fields.Integer('Number of Pages', 40 | groups="base.group_user", 41 | state={'lost': [('readonly', True)]}, 42 | help="Total book page count", company_dependent=False) 43 | reader_rating = fields.Float( 44 | 'Reader Average Rating', 45 | digits=(14, 4), # 可选精度(总数,小数) 46 | ) 47 | author_ids = fields.Many2many( 48 | 'res.partner', 49 | string='Authors' 50 | ) 51 | cost_price = fields.Float('Book Cost', digits=dp.get_precision('Book Price')) 52 | currency_id = fields.Many2one('res.currency', string='Currency') 53 | retail_price = fields.Monetary('Retail Price') # 可选属性:currency_field='currency_id',以防币种字段有currency_id 以外的名称 54 | 55 | publisher_id = fields.Many2one( 56 | 'res.partner', string='Publisher', 57 | # 下为可选项 58 | ondelete='set null', 59 | context = {}, 60 | domain = [], 61 | ) 62 | publisher_city = fields.Char('Publisher City', related='publisher_id.city', readonly=True) 63 | category_id = fields.Many2one('library.book.category') 64 | age_days = fields.Float( 65 | string='Days Since Release', 66 | compute='_compute_age', inverse='_inverse_age', search='_search_age', 67 | store=False, 68 | compute_sudo=False, 69 | ) 70 | ref_doc_id = fields.Reference(selection='_referencable_model', string='Reference Document') 71 | 72 | @api.depends('date_release') 73 | def _compute_age(self): 74 | today = fields.Date.today() 75 | for book in self.filtered('date_release'): 76 | delta = today - book.date_release 77 | book.age_days = delta.days 78 | 79 | 80 | # 这一_compute_age的反向方法用于让 age_days 字段可编辑 81 | # 这是可选项,如果不想让该计算字段可编辑可以进行删除 82 | def _inverse_age(self): 83 | today = fields.Date.today() 84 | for book in self.filtered('date_release'): 85 | d = today - timedelta(days=book.age_days) 86 | book.date_release = d 87 | 88 | # 用于启动对计算字段的搜索 89 | # 这是可选项,如果不想启用该搜索可以进行删除 90 | def _search_age(self, operator, value): 91 | today = fields.Date.today() 92 | value_days = timedelta(days=value) 93 | value_date = today - value_days 94 | # 转换运算符 95 | # age > value 对应 date < value_date 96 | operator_map = { 97 | '>': '<', '>=': '<=', 98 | '<': '>', '<=': '>=', 99 | } 100 | new_op = operator_map.get(operator, operator) 101 | return [('date_release', new_op, value_date)] 102 | 103 | @api.model 104 | def _referencable_model(self): 105 | models = self.env['ir.model'].search([('field_id.name', '=', 'message_ids')]) 106 | return [(x.model, x.name) for x in models] 107 | 108 | def name_get(self): 109 | """ 这个方法用于自定义记录的显示名称 """ 110 | result = [] 111 | for record in self: 112 | rec_name = "%s (%s)" % (record.name, record.date_release) 113 | result.append((record.id, rec_name)) 114 | return result 115 | 116 | _sql_constraints = [('name_uniq', 'UNIQUE(name)', 'Book title must be unique.')] 117 | 118 | @api.constrains('date_release') 119 | def _check_release_date(self): 120 | for record in self: 121 | if record.date_release and record.date_release > fields.Date.today(): 122 | raise models.ValidationError('Release date must be in the past') 123 | 124 | 125 | class ResPartner(models.Model): 126 | _inherit = 'res.partner' 127 | 128 | published_book_ids = fields.One2many( 129 | 'library.book', 130 | 'publisher_id', 131 | string='Published Books' 132 | ) 133 | authored_book_ids = fields.Many2many( 134 | 'library.book', 135 | string = 'Authored Books', 136 | # relation='library_book_res_partner_rel' # 可选项 137 | ) 138 | count_books = fields.Integer('Number of Authored Books', compute='_compute_count_books') 139 | 140 | @api.depends('authored_book_ids') 141 | def _compute_count_books(self): 142 | for r in self: 143 | r.count_books = len(r.authored_book_ids) -------------------------------------------------------------------------------- /Chapter05/r12_abstract_models/my_library/models/library_book_categ.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from odoo import models, fields, api 3 | 4 | 5 | class BookCategory(models.Model): 6 | _name = 'library.book.category' 7 | 8 | _parent_store = True 9 | _parent_name = "parent_id" # 如字段为parent_id是可选项 10 | 11 | name = fields.Char('Category') 12 | parent_id = fields.Many2one( 13 | 'library.book.category', 14 | string='Parent Category', 15 | ondelete='restrict', 16 | index=True 17 | ) 18 | child_ids = fields.One2many( 19 | 'library.book.category', 'parent_id', 20 | string='Child Categories' 21 | ) 22 | parent_path = fields.Char(index=True) 23 | 24 | @api.constrains('parent_id') 25 | def _check_hierarchy(self): 26 | if not self._check_recursion(): 27 | raise models.ValidationError('Error! You cannot create recursive categories.') -------------------------------------------------------------------------------- /Chapter05/r12_abstract_models/my_library/security/groups.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Librarians 5 | 6 | 7 | -------------------------------------------------------------------------------- /Chapter05/r12_abstract_models/my_library/security/ir.model.access.csv: -------------------------------------------------------------------------------- 1 | id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink 2 | acl_book,library.book_default,model_library_book,,1,0,0,0 3 | acl_book_librarian,library.book_librarian,model_library_book,group_librarian,1,1,1,1 4 | acl_book_category,library.book_category_default,model_library_book_category,,1,0,0,0 5 | acl_book_category_librarian,library.book_category_librarian,model_library_book_category,group_librarian,1,1,1,1 -------------------------------------------------------------------------------- /Chapter05/r12_abstract_models/my_library/static/description/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanhou/odoo12-cookbook/db40c23e67668c081410de189c77b88d2afe1dd8/Chapter05/r12_abstract_models/my_library/static/description/icon.png -------------------------------------------------------------------------------- /Chapter05/r12_abstract_models/my_library/views/library_book.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | Library Books 6 | library.book 7 | form 8 | tree,form 9 | 10 | 11 | 12 | 14 | 15 | 16 | Library Book Form 17 | library.book 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 |
49 |
50 |
51 | 52 | 53 | Libray Book List 54 | library.book 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | Library Book Search 65 | library.book 66 | 67 | 68 | 69 | 70 | 73 | 74 | 75 | 76 |
-------------------------------------------------------------------------------- /Chapter05/r12_abstract_models/my_library/views/library_book_categ.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Book Categories 6 | library.book.category 7 | form 8 | tree,form 9 | 10 | 11 | 12 | 13 | 14 | 15 | Library Categories Form 16 | library.book.category 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 |
32 |
33 | 34 | 35 | 36 | Library Book List 37 | library.book.category 38 | 39 | 40 | 41 | 42 | 43 | 44 |
-------------------------------------------------------------------------------- /Chapter05/r1_model_attr/my_library/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from . import models 3 | from . import controllers -------------------------------------------------------------------------------- /Chapter05/r1_model_attr/my_library/__manifest__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | { 3 | 'name': 'My Library', 4 | 'summary': '轻松管理图书', 5 | 'description': """长描述占位""", 6 | 'author': 'Alan Hou', 7 | 'website': 'https://alanhou.org', 8 | 'category': 'Uncategorized', 9 | 'version': '12.0.1', 10 | 'depends': ['base'], 11 | 'data': [ 12 | 'security/groups.xml', 13 | 'security/ir.model.access.csv', 14 | 'views/library_book.xml', 15 | ], 16 | } -------------------------------------------------------------------------------- /Chapter05/r1_model_attr/my_library/controllers/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanhou/odoo12-cookbook/db40c23e67668c081410de189c77b88d2afe1dd8/Chapter05/r1_model_attr/my_library/controllers/__init__.py -------------------------------------------------------------------------------- /Chapter05/r1_model_attr/my_library/controllers/__pycache__/__init__.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanhou/odoo12-cookbook/db40c23e67668c081410de189c77b88d2afe1dd8/Chapter05/r1_model_attr/my_library/controllers/__pycache__/__init__.cpython-35.pyc -------------------------------------------------------------------------------- /Chapter05/r1_model_attr/my_library/models/__init__.py: -------------------------------------------------------------------------------- 1 | from . import library_book -------------------------------------------------------------------------------- /Chapter05/r1_model_attr/my_library/models/__pycache__/__init__.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanhou/odoo12-cookbook/db40c23e67668c081410de189c77b88d2afe1dd8/Chapter05/r1_model_attr/my_library/models/__pycache__/__init__.cpython-35.pyc -------------------------------------------------------------------------------- /Chapter05/r1_model_attr/my_library/models/__pycache__/library_book.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanhou/odoo12-cookbook/db40c23e67668c081410de189c77b88d2afe1dd8/Chapter05/r1_model_attr/my_library/models/__pycache__/library_book.cpython-35.pyc -------------------------------------------------------------------------------- /Chapter05/r1_model_attr/my_library/models/library_book.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from odoo import models, fields 3 | 4 | 5 | class LibraryBook(models.Model): 6 | _name = 'library.book' 7 | _description = 'Library Book' 8 | _order = 'date_release desc, name' 9 | _rec_name = 'short_name' 10 | 11 | name = fields.Char('Title', required=True) 12 | short_name = fields.Char('Short Title', required=True) 13 | date_release = fields.Date('Release Date') 14 | author_ids = fields.Many2many( 15 | 'res.partner', 16 | string='Authors' 17 | ) 18 | 19 | def name_get(self): 20 | result = [] 21 | for record in self: 22 | rec_name = "%s (%s)" % (record.name, record.date_release) 23 | result.append((record.id, rec_name)) 24 | return result -------------------------------------------------------------------------------- /Chapter05/r1_model_attr/my_library/security/groups.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Librarians 5 | 6 | 7 | -------------------------------------------------------------------------------- /Chapter05/r1_model_attr/my_library/security/ir.model.access.csv: -------------------------------------------------------------------------------- 1 | id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink 2 | acl_book,library.book_default,model_library_book,,1,0,0,0 3 | acl_book_librarian,library.book_librarian,model_library_book,group_librarian,1,1,1,1 -------------------------------------------------------------------------------- /Chapter05/r1_model_attr/my_library/static/description/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanhou/odoo12-cookbook/db40c23e67668c081410de189c77b88d2afe1dd8/Chapter05/r1_model_attr/my_library/static/description/icon.png -------------------------------------------------------------------------------- /Chapter05/r1_model_attr/my_library/views/library_book.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | Library Books 6 | library.book 7 | form 8 | tree,form 9 | 10 | 11 | 12 | 14 | 15 | 16 | Library Book Form 17 | library.book 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 |
32 |
33 | 34 | 35 | Libray Book List 36 | library.book 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | Library Book Search 47 | library.book 48 | 49 | 50 | 51 | 52 | 55 | 56 | 57 | 58 |
-------------------------------------------------------------------------------- /Chapter05/r2_fields/my_library/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from . import models 3 | from . import controllers -------------------------------------------------------------------------------- /Chapter05/r2_fields/my_library/__manifest__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | { 3 | 'name': 'My Library', 4 | 'summary': '轻松管理图书', 5 | 'description': """长描述占位""", 6 | 'author': 'Alan Hou', 7 | 'website': 'https://alanhou.org', 8 | 'category': 'Uncategorized', 9 | 'version': '12.0.1', 10 | 'depends': ['base'], 11 | 'data': [ 12 | 'security/groups.xml', 13 | 'security/ir.model.access.csv', 14 | 'views/library_book.xml', 15 | ], 16 | } -------------------------------------------------------------------------------- /Chapter05/r2_fields/my_library/controllers/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanhou/odoo12-cookbook/db40c23e67668c081410de189c77b88d2afe1dd8/Chapter05/r2_fields/my_library/controllers/__init__.py -------------------------------------------------------------------------------- /Chapter05/r2_fields/my_library/controllers/__pycache__/__init__.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanhou/odoo12-cookbook/db40c23e67668c081410de189c77b88d2afe1dd8/Chapter05/r2_fields/my_library/controllers/__pycache__/__init__.cpython-35.pyc -------------------------------------------------------------------------------- /Chapter05/r2_fields/my_library/models/__init__.py: -------------------------------------------------------------------------------- 1 | from . import library_book -------------------------------------------------------------------------------- /Chapter05/r2_fields/my_library/models/__pycache__/__init__.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanhou/odoo12-cookbook/db40c23e67668c081410de189c77b88d2afe1dd8/Chapter05/r2_fields/my_library/models/__pycache__/__init__.cpython-35.pyc -------------------------------------------------------------------------------- /Chapter05/r2_fields/my_library/models/__pycache__/library_book.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanhou/odoo12-cookbook/db40c23e67668c081410de189c77b88d2afe1dd8/Chapter05/r2_fields/my_library/models/__pycache__/library_book.cpython-35.pyc -------------------------------------------------------------------------------- /Chapter05/r2_fields/my_library/models/library_book.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from odoo import models, fields 3 | 4 | 5 | class LibraryBook(models.Model): 6 | _name = 'library.book' 7 | _description = 'Library Book' 8 | _order = 'date_release desc, name' 9 | _rec_name = 'short_name' 10 | 11 | name = fields.Char('Title', required=True) 12 | short_name = fields.Char('Short Title', translate=True, index=True) 13 | notes = fields.Text('Internal Notes') 14 | state = fields.Selection( 15 | [('draft', 'Not Available'), 16 | ('available', 'Available'), 17 | ('lost', 'Lost')], 18 | 'State', default="draft") 19 | description = fields.Html('Description', sanitize=True, strip_style=False) 20 | cover = fields.Binary('Book Cover') 21 | out_of_print = fields.Boolean('Out of Print?') 22 | date_release = fields.Date('Release Date') 23 | date_updated = fields.Datetime('Last Updated') 24 | pages = fields.Integer('Number of Pages', 25 | groups="base.group_user", 26 | state={'lost': [('readonly', True)]}, 27 | help="Total book page count", company_dependent=False) 28 | reader_rating = fields.Float( 29 | 'Reader Average Rating', 30 | digits=(14, 4), # 可选精度(总数,小数) 31 | ) 32 | author_ids = fields.Many2many( 33 | 'res.partner', 34 | string='Authors' 35 | ) 36 | 37 | def name_get(self): 38 | """ 这个方法用于自定义记录的显示名称 """ 39 | result = [] 40 | for record in self: 41 | rec_name = "%s (%s)" % (record.name, record.date_release) 42 | result.append((record.id, rec_name)) 43 | return result -------------------------------------------------------------------------------- /Chapter05/r2_fields/my_library/security/groups.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Librarians 5 | 6 | 7 | -------------------------------------------------------------------------------- /Chapter05/r2_fields/my_library/security/ir.model.access.csv: -------------------------------------------------------------------------------- 1 | id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink 2 | acl_book,library.book_default,model_library_book,,1,0,0,0 3 | acl_book_librarian,library.book_librarian,model_library_book,group_librarian,1,1,1,1 -------------------------------------------------------------------------------- /Chapter05/r2_fields/my_library/static/description/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanhou/odoo12-cookbook/db40c23e67668c081410de189c77b88d2afe1dd8/Chapter05/r2_fields/my_library/static/description/icon.png -------------------------------------------------------------------------------- /Chapter05/r2_fields/my_library/views/library_book.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | Library Books 6 | library.book 7 | form 8 | tree,form 9 | 10 | 11 | 12 | 14 | 15 | 16 | Library Book Form 17 | library.book 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 |
40 |
41 |
42 | 43 | 44 | Libray Book List 45 | library.book 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | Library Book Search 56 | library.book 57 | 58 | 59 | 60 | 61 | 64 | 65 | 66 | 67 |
-------------------------------------------------------------------------------- /Chapter05/r3_decimal_precision/my_library/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from . import models 3 | from . import controllers -------------------------------------------------------------------------------- /Chapter05/r3_decimal_precision/my_library/__manifest__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | { 3 | 'name': 'My Library', 4 | 'summary': '轻松管理图书', 5 | 'description': """长描述占位""", 6 | 'author': 'Alan Hou', 7 | 'website': 'https://alanhou.org', 8 | 'category': 'Uncategorized', 9 | 'version': '12.0.1', 10 | 'depends': ['base', 'decimal_precision'], 11 | 'data': [ 12 | 'security/groups.xml', 13 | 'security/ir.model.access.csv', 14 | 'views/library_book.xml', 15 | ], 16 | } -------------------------------------------------------------------------------- /Chapter05/r3_decimal_precision/my_library/controllers/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanhou/odoo12-cookbook/db40c23e67668c081410de189c77b88d2afe1dd8/Chapter05/r3_decimal_precision/my_library/controllers/__init__.py -------------------------------------------------------------------------------- /Chapter05/r3_decimal_precision/my_library/controllers/__pycache__/__init__.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanhou/odoo12-cookbook/db40c23e67668c081410de189c77b88d2afe1dd8/Chapter05/r3_decimal_precision/my_library/controllers/__pycache__/__init__.cpython-35.pyc -------------------------------------------------------------------------------- /Chapter05/r3_decimal_precision/my_library/models/__init__.py: -------------------------------------------------------------------------------- 1 | from . import library_book -------------------------------------------------------------------------------- /Chapter05/r3_decimal_precision/my_library/models/__pycache__/__init__.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanhou/odoo12-cookbook/db40c23e67668c081410de189c77b88d2afe1dd8/Chapter05/r3_decimal_precision/my_library/models/__pycache__/__init__.cpython-35.pyc -------------------------------------------------------------------------------- /Chapter05/r3_decimal_precision/my_library/models/__pycache__/library_book.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanhou/odoo12-cookbook/db40c23e67668c081410de189c77b88d2afe1dd8/Chapter05/r3_decimal_precision/my_library/models/__pycache__/library_book.cpython-35.pyc -------------------------------------------------------------------------------- /Chapter05/r3_decimal_precision/my_library/models/library_book.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from odoo import models, fields 3 | from odoo.addons import decimal_precision as dp 4 | 5 | 6 | class LibraryBook(models.Model): 7 | _name = 'library.book' 8 | _description = 'Library Book' 9 | _order = 'date_release desc, name' 10 | _rec_name = 'short_name' 11 | 12 | name = fields.Char('Title', required=True) 13 | short_name = fields.Char('Short Title', translate=True, index=True) 14 | notes = fields.Text('Internal Notes') 15 | state = fields.Selection( 16 | [('draft', 'Not Available'), 17 | ('available', 'Available'), 18 | ('lost', 'Lost')], 19 | 'State', default="draft") 20 | description = fields.Html('Description', sanitize=True, strip_style=False) 21 | cover = fields.Binary('Book Cover') 22 | out_of_print = fields.Boolean('Out of Print?') 23 | date_release = fields.Date('Release Date') 24 | date_updated = fields.Datetime('Last Updated') 25 | pages = fields.Integer('Number of Pages', 26 | groups="base.group_user", 27 | state={'lost': [('readonly', True)]}, 28 | help="Total book page count", company_dependent=False) 29 | reader_rating = fields.Float( 30 | 'Reader Average Rating', 31 | digits=(14, 4), # 可选精度(总数,小数) 32 | ) 33 | author_ids = fields.Many2many( 34 | 'res.partner', 35 | string='Authors' 36 | ) 37 | cost_price = fields.Float('Book Cost', digits=dp.get_precision('Book Price')) 38 | 39 | def name_get(self): 40 | """ 这个方法用于自定义记录的显示名称 """ 41 | result = [] 42 | for record in self: 43 | rec_name = "%s (%s)" % (record.name, record.date_release) 44 | result.append((record.id, rec_name)) 45 | return result -------------------------------------------------------------------------------- /Chapter05/r3_decimal_precision/my_library/security/groups.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Librarians 5 | 6 | 7 | -------------------------------------------------------------------------------- /Chapter05/r3_decimal_precision/my_library/security/ir.model.access.csv: -------------------------------------------------------------------------------- 1 | id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink 2 | acl_book,library.book_default,model_library_book,,1,0,0,0 3 | acl_book_librarian,library.book_librarian,model_library_book,group_librarian,1,1,1,1 -------------------------------------------------------------------------------- /Chapter05/r3_decimal_precision/my_library/static/description/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanhou/odoo12-cookbook/db40c23e67668c081410de189c77b88d2afe1dd8/Chapter05/r3_decimal_precision/my_library/static/description/icon.png -------------------------------------------------------------------------------- /Chapter05/r3_decimal_precision/my_library/views/library_book.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | Library Books 6 | library.book 7 | form 8 | tree,form 9 | 10 | 11 | 12 | 14 | 15 | 16 | Library Book Form 17 | library.book 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 |
41 |
42 |
43 | 44 | 45 | Libray Book List 46 | library.book 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | Library Book Search 57 | library.book 58 | 59 | 60 | 61 | 62 | 65 | 66 | 67 | 68 |
-------------------------------------------------------------------------------- /Chapter05/r4_monetary_field/my_library/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from . import models 3 | from . import controllers -------------------------------------------------------------------------------- /Chapter05/r4_monetary_field/my_library/__manifest__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | { 3 | 'name': 'My Library', 4 | 'summary': '轻松管理图书', 5 | 'description': """长描述占位""", 6 | 'author': 'Alan Hou', 7 | 'website': 'https://alanhou.org', 8 | 'category': 'Uncategorized', 9 | 'version': '12.0.1', 10 | 'depends': ['base', 'decimal_precision'], 11 | 'data': [ 12 | 'security/groups.xml', 13 | 'security/ir.model.access.csv', 14 | 'views/library_book.xml', 15 | ], 16 | } -------------------------------------------------------------------------------- /Chapter05/r4_monetary_field/my_library/controllers/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanhou/odoo12-cookbook/db40c23e67668c081410de189c77b88d2afe1dd8/Chapter05/r4_monetary_field/my_library/controllers/__init__.py -------------------------------------------------------------------------------- /Chapter05/r4_monetary_field/my_library/controllers/__pycache__/__init__.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanhou/odoo12-cookbook/db40c23e67668c081410de189c77b88d2afe1dd8/Chapter05/r4_monetary_field/my_library/controllers/__pycache__/__init__.cpython-35.pyc -------------------------------------------------------------------------------- /Chapter05/r4_monetary_field/my_library/models/__init__.py: -------------------------------------------------------------------------------- 1 | from . import library_book -------------------------------------------------------------------------------- /Chapter05/r4_monetary_field/my_library/models/__pycache__/__init__.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanhou/odoo12-cookbook/db40c23e67668c081410de189c77b88d2afe1dd8/Chapter05/r4_monetary_field/my_library/models/__pycache__/__init__.cpython-35.pyc -------------------------------------------------------------------------------- /Chapter05/r4_monetary_field/my_library/models/__pycache__/library_book.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanhou/odoo12-cookbook/db40c23e67668c081410de189c77b88d2afe1dd8/Chapter05/r4_monetary_field/my_library/models/__pycache__/library_book.cpython-35.pyc -------------------------------------------------------------------------------- /Chapter05/r4_monetary_field/my_library/models/library_book.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from odoo import models, fields 3 | from odoo.addons import decimal_precision as dp 4 | 5 | 6 | class LibraryBook(models.Model): 7 | _name = 'library.book' 8 | _description = 'Library Book' 9 | _order = 'date_release desc, name' 10 | _rec_name = 'short_name' 11 | 12 | name = fields.Char('Title', required=True) 13 | short_name = fields.Char('Short Title', translate=True, index=True) 14 | notes = fields.Text('Internal Notes') 15 | state = fields.Selection( 16 | [('draft', 'Not Available'), 17 | ('available', 'Available'), 18 | ('lost', 'Lost')], 19 | 'State', default="draft") 20 | description = fields.Html('Description', sanitize=True, strip_style=False) 21 | cover = fields.Binary('Book Cover') 22 | out_of_print = fields.Boolean('Out of Print?') 23 | date_release = fields.Date('Release Date') 24 | date_updated = fields.Datetime('Last Updated') 25 | pages = fields.Integer('Number of Pages', 26 | groups="base.group_user", 27 | state={'lost': [('readonly', True)]}, 28 | help="Total book page count", company_dependent=False) 29 | reader_rating = fields.Float( 30 | 'Reader Average Rating', 31 | digits=(14, 4), # 可选精度(总数,小数) 32 | ) 33 | author_ids = fields.Many2many( 34 | 'res.partner', 35 | string='Authors' 36 | ) 37 | cost_price = fields.Float('Book Cost', digits=dp.get_precision('Book Price')) 38 | currency_id = fields.Many2one('res.currency', string='Currency') 39 | retail_price = fields.Monetary('Retail Price') # 可选属性:currency_field='currency_id',以防币种字段有currency_id 以外的名称 40 | 41 | def name_get(self): 42 | """ This method used to customize display name of the record """ 43 | result = [] 44 | for record in self: 45 | rec_name = "%s (%s)" % (record.name, record.date_release) 46 | result.append((record.id, rec_name)) 47 | return result 48 | 49 | 50 | def name_get(self): 51 | """ 这个方法用于自定义记录的显示名称 """ 52 | result = [] 53 | for record in self: 54 | rec_name = "%s (%s)" % (record.name, record.date_release) 55 | result.append((record.id, rec_name)) 56 | return result -------------------------------------------------------------------------------- /Chapter05/r4_monetary_field/my_library/security/groups.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Librarians 5 | 6 | 7 | -------------------------------------------------------------------------------- /Chapter05/r4_monetary_field/my_library/security/ir.model.access.csv: -------------------------------------------------------------------------------- 1 | id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink 2 | acl_book,library.book_default,model_library_book,,1,0,0,0 3 | acl_book_librarian,library.book_librarian,model_library_book,group_librarian,1,1,1,1 -------------------------------------------------------------------------------- /Chapter05/r4_monetary_field/my_library/static/description/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanhou/odoo12-cookbook/db40c23e67668c081410de189c77b88d2afe1dd8/Chapter05/r4_monetary_field/my_library/static/description/icon.png -------------------------------------------------------------------------------- /Chapter05/r4_monetary_field/my_library/views/library_book.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | Library Books 6 | library.book 7 | form 8 | tree,form 9 | 10 | 11 | 12 | 14 | 15 | 16 | Library Book Form 17 | library.book 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 |
43 |
44 |
45 | 46 | 47 | Libray Book List 48 | library.book 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | Library Book Search 59 | library.book 60 | 61 | 62 | 63 | 64 | 67 | 68 | 69 | 70 |
-------------------------------------------------------------------------------- /Chapter05/r5_relational_fields/my_library/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from . import models 3 | from . import controllers -------------------------------------------------------------------------------- /Chapter05/r5_relational_fields/my_library/__manifest__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | { 3 | 'name': 'My Library', 4 | 'summary': '轻松管理图书', 5 | 'description': """长描述占位""", 6 | 'author': 'Alan Hou', 7 | 'website': 'https://alanhou.org', 8 | 'category': 'Uncategorized', 9 | 'version': '12.0.1', 10 | 'depends': ['base', 'decimal_precision'], 11 | 'data': [ 12 | 'security/groups.xml', 13 | 'security/ir.model.access.csv', 14 | 'views/library_book.xml', 15 | ], 16 | } -------------------------------------------------------------------------------- /Chapter05/r5_relational_fields/my_library/controllers/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanhou/odoo12-cookbook/db40c23e67668c081410de189c77b88d2afe1dd8/Chapter05/r5_relational_fields/my_library/controllers/__init__.py -------------------------------------------------------------------------------- /Chapter05/r5_relational_fields/my_library/controllers/__pycache__/__init__.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanhou/odoo12-cookbook/db40c23e67668c081410de189c77b88d2afe1dd8/Chapter05/r5_relational_fields/my_library/controllers/__pycache__/__init__.cpython-35.pyc -------------------------------------------------------------------------------- /Chapter05/r5_relational_fields/my_library/models/__init__.py: -------------------------------------------------------------------------------- 1 | from . import library_book -------------------------------------------------------------------------------- /Chapter05/r5_relational_fields/my_library/models/__pycache__/__init__.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanhou/odoo12-cookbook/db40c23e67668c081410de189c77b88d2afe1dd8/Chapter05/r5_relational_fields/my_library/models/__pycache__/__init__.cpython-35.pyc -------------------------------------------------------------------------------- /Chapter05/r5_relational_fields/my_library/models/__pycache__/library_book.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanhou/odoo12-cookbook/db40c23e67668c081410de189c77b88d2afe1dd8/Chapter05/r5_relational_fields/my_library/models/__pycache__/library_book.cpython-35.pyc -------------------------------------------------------------------------------- /Chapter05/r5_relational_fields/my_library/models/library_book.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from odoo import models, fields 3 | from odoo.addons import decimal_precision as dp 4 | 5 | 6 | class LibraryBook(models.Model): 7 | _name = 'library.book' 8 | _description = 'Library Book' 9 | _order = 'date_release desc, name' 10 | _rec_name = 'short_name' 11 | 12 | name = fields.Char('Title', required=True) 13 | short_name = fields.Char('Short Title', translate=True, index=True) 14 | notes = fields.Text('Internal Notes') 15 | state = fields.Selection( 16 | [('draft', 'Not Available'), 17 | ('available', 'Available'), 18 | ('lost', 'Lost')], 19 | 'State', default="draft") 20 | description = fields.Html('Description', sanitize=True, strip_style=False) 21 | cover = fields.Binary('Book Cover') 22 | out_of_print = fields.Boolean('Out of Print?') 23 | date_release = fields.Date('Release Date') 24 | date_updated = fields.Datetime('Last Updated') 25 | pages = fields.Integer('Number of Pages', 26 | groups="base.group_user", 27 | state={'lost': [('readonly', True)]}, 28 | help="Total book page count", company_dependent=False) 29 | reader_rating = fields.Float( 30 | 'Reader Average Rating', 31 | digits=(14, 4), # 可选精度(总数,小数) 32 | ) 33 | author_ids = fields.Many2many( 34 | 'res.partner', 35 | string='Authors' 36 | ) 37 | cost_price = fields.Float('Book Cost', digits=dp.get_precision('Book Price')) 38 | currency_id = fields.Many2one('res.currency', string='Currency') 39 | retail_price = fields.Monetary('Retail Price') # 可选属性:currency_field='currency_id',以防币种字段有currency_id 以外的名称 40 | 41 | publisher_id = fields.Many2one( 42 | 'res.partner', string='Publisher', 43 | # 下为可选项 44 | ondelete='set null', 45 | context = {}, 46 | domain = [], 47 | ) 48 | 49 | 50 | def name_get(self): 51 | """ 这个方法用于自定义记录的显示名称 """ 52 | result = [] 53 | for record in self: 54 | rec_name = "%s (%s)" % (record.name, record.date_release) 55 | result.append((record.id, rec_name)) 56 | return result 57 | 58 | class ResPartner(models.Model): 59 | _inherit = 'res.partner' 60 | 61 | published_book_ids = fields.One2many( 62 | 'library.book', 63 | 'publisher_id', 64 | string='Published Books' 65 | ) 66 | authored_book_ids = fields.Many2many( 67 | 'library.book', 68 | string = 'Authored Books', 69 | # relation='library_book_res_partner_rel' # 可选项 70 | ) -------------------------------------------------------------------------------- /Chapter05/r5_relational_fields/my_library/security/groups.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Librarians 5 | 6 | 7 | -------------------------------------------------------------------------------- /Chapter05/r5_relational_fields/my_library/security/ir.model.access.csv: -------------------------------------------------------------------------------- 1 | id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink 2 | acl_book,library.book_default,model_library_book,,1,0,0,0 3 | acl_book_librarian,library.book_librarian,model_library_book,group_librarian,1,1,1,1 -------------------------------------------------------------------------------- /Chapter05/r5_relational_fields/my_library/static/description/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanhou/odoo12-cookbook/db40c23e67668c081410de189c77b88d2afe1dd8/Chapter05/r5_relational_fields/my_library/static/description/icon.png -------------------------------------------------------------------------------- /Chapter05/r5_relational_fields/my_library/views/library_book.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | Library Books 6 | library.book 7 | form 8 | tree,form 9 | 10 | 11 | 12 | 14 | 15 | 16 | Library Book Form 17 | library.book 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 |
44 |
45 |
46 | 47 | 48 | Libray Book List 49 | library.book 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | Library Book Search 60 | library.book 61 | 62 | 63 | 64 | 65 | 68 | 69 | 70 | 71 |
-------------------------------------------------------------------------------- /Chapter05/r6_hierarchy_model/my_library/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from . import models 3 | from . import controllers -------------------------------------------------------------------------------- /Chapter05/r6_hierarchy_model/my_library/__manifest__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | { 3 | 'name': 'My Library', 4 | 'summary': '轻松管理图书', 5 | 'description': """长描述占位""", 6 | 'author': 'Alan Hou', 7 | 'website': 'https://alanhou.org', 8 | 'category': 'Uncategorized', 9 | 'version': '12.0.1', 10 | 'depends': ['base', 'decimal_precision'], 11 | 'data': [ 12 | 'security/groups.xml', 13 | 'security/ir.model.access.csv', 14 | 'views/library_book.xml', 15 | 'views/library_book_categ.xml', 16 | ], 17 | } -------------------------------------------------------------------------------- /Chapter05/r6_hierarchy_model/my_library/controllers/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanhou/odoo12-cookbook/db40c23e67668c081410de189c77b88d2afe1dd8/Chapter05/r6_hierarchy_model/my_library/controllers/__init__.py -------------------------------------------------------------------------------- /Chapter05/r6_hierarchy_model/my_library/controllers/__pycache__/__init__.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanhou/odoo12-cookbook/db40c23e67668c081410de189c77b88d2afe1dd8/Chapter05/r6_hierarchy_model/my_library/controllers/__pycache__/__init__.cpython-35.pyc -------------------------------------------------------------------------------- /Chapter05/r6_hierarchy_model/my_library/models/__init__.py: -------------------------------------------------------------------------------- 1 | from . import library_book 2 | from . import library_book_categ -------------------------------------------------------------------------------- /Chapter05/r6_hierarchy_model/my_library/models/__pycache__/__init__.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanhou/odoo12-cookbook/db40c23e67668c081410de189c77b88d2afe1dd8/Chapter05/r6_hierarchy_model/my_library/models/__pycache__/__init__.cpython-35.pyc -------------------------------------------------------------------------------- /Chapter05/r6_hierarchy_model/my_library/models/__pycache__/library_book.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanhou/odoo12-cookbook/db40c23e67668c081410de189c77b88d2afe1dd8/Chapter05/r6_hierarchy_model/my_library/models/__pycache__/library_book.cpython-35.pyc -------------------------------------------------------------------------------- /Chapter05/r6_hierarchy_model/my_library/models/__pycache__/library_book_categ.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanhou/odoo12-cookbook/db40c23e67668c081410de189c77b88d2afe1dd8/Chapter05/r6_hierarchy_model/my_library/models/__pycache__/library_book_categ.cpython-35.pyc -------------------------------------------------------------------------------- /Chapter05/r6_hierarchy_model/my_library/models/library_book.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from odoo import models, fields 3 | from odoo.addons import decimal_precision as dp 4 | 5 | 6 | class LibraryBook(models.Model): 7 | _name = 'library.book' 8 | _description = 'Library Book' 9 | _order = 'date_release desc, name' 10 | _rec_name = 'short_name' 11 | 12 | name = fields.Char('Title', required=True) 13 | short_name = fields.Char('Short Title', translate=True, index=True) 14 | notes = fields.Text('Internal Notes') 15 | state = fields.Selection( 16 | [('draft', 'Not Available'), 17 | ('available', 'Available'), 18 | ('lost', 'Lost')], 19 | 'State', default="draft") 20 | description = fields.Html('Description', sanitize=True, strip_style=False) 21 | cover = fields.Binary('Book Cover') 22 | out_of_print = fields.Boolean('Out of Print?') 23 | date_release = fields.Date('Release Date') 24 | date_updated = fields.Datetime('Last Updated') 25 | pages = fields.Integer('Number of Pages', 26 | groups="base.group_user", 27 | state={'lost': [('readonly', True)]}, 28 | help="Total book page count", company_dependent=False) 29 | reader_rating = fields.Float( 30 | 'Reader Average Rating', 31 | digits=(14, 4), # 可选精度(总数,小数) 32 | ) 33 | author_ids = fields.Many2many( 34 | 'res.partner', 35 | string='Authors' 36 | ) 37 | cost_price = fields.Float('Book Cost', digits=dp.get_precision('Book Price')) 38 | currency_id = fields.Many2one('res.currency', string='Currency') 39 | retail_price = fields.Monetary('Retail Price') # 可选属性:currency_field='currency_id',以防币种字段有currency_id 以外的名称 40 | 41 | publisher_id = fields.Many2one( 42 | 'res.partner', string='Publisher', 43 | # 下为可选项 44 | ondelete='set null', 45 | context = {}, 46 | domain = [], 47 | ) 48 | category_id = fields.Many2one('library.book.category') 49 | 50 | 51 | def name_get(self): 52 | """ 这个方法用于自定义记录的显示名称 """ 53 | result = [] 54 | for record in self: 55 | rec_name = "%s (%s)" % (record.name, record.date_release) 56 | result.append((record.id, rec_name)) 57 | return result 58 | 59 | class ResPartner(models.Model): 60 | _inherit = 'res.partner' 61 | 62 | published_book_ids = fields.One2many( 63 | 'library.book', 64 | 'publisher_id', 65 | string='Published Books' 66 | ) 67 | authored_book_ids = fields.Many2many( 68 | 'library.book', 69 | string = 'Authored Books', 70 | # relation='library_book_res_partner_rel' # 可选项 71 | ) -------------------------------------------------------------------------------- /Chapter05/r6_hierarchy_model/my_library/models/library_book_categ.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from odoo import models, fields, api 3 | 4 | 5 | class BookCategory(models.Model): 6 | _name = 'library.book.category' 7 | 8 | _parent_store = True 9 | _parent_name = "parent_id" # 如字段为parent_id是可选项 10 | 11 | name = fields.Char('Category') 12 | parent_id = fields.Many2one( 13 | 'library.book.category', 14 | string='Parent Category', 15 | ondelete='restrict', 16 | index=True 17 | ) 18 | child_ids = fields.One2many( 19 | 'library.book.category', 'parent_id', 20 | string='Child Categories' 21 | ) 22 | parent_path = fields.Char(index=True) 23 | 24 | @api.constrains('parent_id') 25 | def _check_hierarchy(self): 26 | if not self._check_recursion(): 27 | raise models.ValidationError('Error! You cannot create recursive categories.') -------------------------------------------------------------------------------- /Chapter05/r6_hierarchy_model/my_library/security/groups.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Librarians 5 | 6 | 7 | -------------------------------------------------------------------------------- /Chapter05/r6_hierarchy_model/my_library/security/ir.model.access.csv: -------------------------------------------------------------------------------- 1 | id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink 2 | acl_book,library.book_default,model_library_book,,1,0,0,0 3 | acl_book_librarian,library.book_librarian,model_library_book,group_librarian,1,1,1,1 4 | acl_book_category,library.book_category_default,model_library_book_category,,1,0,0,0 5 | acl_book_category_librarian,library.book_category_librarian,model_library_book_category,group_librarian,1,1,1,1 -------------------------------------------------------------------------------- /Chapter05/r6_hierarchy_model/my_library/static/description/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanhou/odoo12-cookbook/db40c23e67668c081410de189c77b88d2afe1dd8/Chapter05/r6_hierarchy_model/my_library/static/description/icon.png -------------------------------------------------------------------------------- /Chapter05/r6_hierarchy_model/my_library/views/library_book.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | Library Books 6 | library.book 7 | form 8 | tree,form 9 | 10 | 11 | 12 | 14 | 15 | 16 | Library Book Form 17 | library.book 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 |
45 |
46 |
47 | 48 | 49 | Libray Book List 50 | library.book 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | Library Book Search 61 | library.book 62 | 63 | 64 | 65 | 66 | 69 | 70 | 71 | 72 |
-------------------------------------------------------------------------------- /Chapter05/r6_hierarchy_model/my_library/views/library_book_categ.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Book Categories 6 | library.book.category 7 | form 8 | tree,form 9 | 10 | 11 | 12 | 13 | 14 | 15 | Library Categories Form 16 | library.book.category 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 |
32 |
33 | 34 | 35 | 36 | Library Book List 37 | library.book.category 38 | 39 | 40 | 41 | 42 | 43 | 44 |
-------------------------------------------------------------------------------- /Chapter05/r7_constraints/my_library/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from . import models 3 | from . import controllers -------------------------------------------------------------------------------- /Chapter05/r7_constraints/my_library/__manifest__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | { 3 | 'name': 'My Library', 4 | 'summary': '轻松管理图书', 5 | 'description': """长描述占位""", 6 | 'author': 'Alan Hou', 7 | 'website': 'https://alanhou.org', 8 | 'category': 'Uncategorized', 9 | 'version': '12.0.1', 10 | 'depends': ['base', 'decimal_precision'], 11 | 'data': [ 12 | 'security/groups.xml', 13 | 'security/ir.model.access.csv', 14 | 'views/library_book.xml', 15 | 'views/library_book_categ.xml', 16 | ], 17 | } -------------------------------------------------------------------------------- /Chapter05/r7_constraints/my_library/controllers/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanhou/odoo12-cookbook/db40c23e67668c081410de189c77b88d2afe1dd8/Chapter05/r7_constraints/my_library/controllers/__init__.py -------------------------------------------------------------------------------- /Chapter05/r7_constraints/my_library/controllers/__pycache__/__init__.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanhou/odoo12-cookbook/db40c23e67668c081410de189c77b88d2afe1dd8/Chapter05/r7_constraints/my_library/controllers/__pycache__/__init__.cpython-35.pyc -------------------------------------------------------------------------------- /Chapter05/r7_constraints/my_library/models/__init__.py: -------------------------------------------------------------------------------- 1 | from . import library_book 2 | from . import library_book_categ -------------------------------------------------------------------------------- /Chapter05/r7_constraints/my_library/models/__pycache__/__init__.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanhou/odoo12-cookbook/db40c23e67668c081410de189c77b88d2afe1dd8/Chapter05/r7_constraints/my_library/models/__pycache__/__init__.cpython-35.pyc -------------------------------------------------------------------------------- /Chapter05/r7_constraints/my_library/models/__pycache__/library_book.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanhou/odoo12-cookbook/db40c23e67668c081410de189c77b88d2afe1dd8/Chapter05/r7_constraints/my_library/models/__pycache__/library_book.cpython-35.pyc -------------------------------------------------------------------------------- /Chapter05/r7_constraints/my_library/models/__pycache__/library_book_categ.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanhou/odoo12-cookbook/db40c23e67668c081410de189c77b88d2afe1dd8/Chapter05/r7_constraints/my_library/models/__pycache__/library_book_categ.cpython-35.pyc -------------------------------------------------------------------------------- /Chapter05/r7_constraints/my_library/models/library_book.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from odoo import models, fields, api 3 | from odoo.exceptions import ValidationError 4 | from odoo.addons import decimal_precision as dp 5 | 6 | 7 | class LibraryBook(models.Model): 8 | _name = 'library.book' 9 | _description = 'Library Book' 10 | _order = 'date_release desc, name' 11 | _rec_name = 'short_name' 12 | 13 | name = fields.Char('Title', required=True) 14 | short_name = fields.Char('Short Title', translate=True, index=True) 15 | notes = fields.Text('Internal Notes') 16 | state = fields.Selection( 17 | [('draft', 'Not Available'), 18 | ('available', 'Available'), 19 | ('lost', 'Lost')], 20 | 'State', default="draft") 21 | description = fields.Html('Description', sanitize=True, strip_style=False) 22 | cover = fields.Binary('Book Cover') 23 | out_of_print = fields.Boolean('Out of Print?') 24 | date_release = fields.Date('Release Date') 25 | date_updated = fields.Datetime('Last Updated') 26 | pages = fields.Integer('Number of Pages', 27 | groups="base.group_user", 28 | state={'lost': [('readonly', True)]}, 29 | help="Total book page count", company_dependent=False) 30 | reader_rating = fields.Float( 31 | 'Reader Average Rating', 32 | digits=(14, 4), # 可选精度(总数,小数) 33 | ) 34 | author_ids = fields.Many2many( 35 | 'res.partner', 36 | string='Authors' 37 | ) 38 | cost_price = fields.Float('Book Cost', digits=dp.get_precision('Book Price')) 39 | currency_id = fields.Many2one('res.currency', string='Currency') 40 | retail_price = fields.Monetary('Retail Price') # 可选属性:currency_field='currency_id',以防币种字段有currency_id 以外的名称 41 | 42 | publisher_id = fields.Many2one( 43 | 'res.partner', string='Publisher', 44 | # 下为可选项 45 | ondelete='set null', 46 | context = {}, 47 | domain = [], 48 | ) 49 | category_id = fields.Many2one('library.book.category') 50 | 51 | 52 | def name_get(self): 53 | """ 这个方法用于自定义记录的显示名称 """ 54 | result = [] 55 | for record in self: 56 | rec_name = "%s (%s)" % (record.name, record.date_release) 57 | result.append((record.id, rec_name)) 58 | return result 59 | 60 | _sql_constraints = [('name_uniq', 'UNIQUE(name)', 'Book title must be unique.')] 61 | 62 | @api.constrains('date_release') 63 | def _check_release_date(self): 64 | for record in self: 65 | if record.date_release and record.date_release > fields.Date.today(): 66 | raise models.ValidationError('Release date must be in the past') 67 | 68 | 69 | class ResPartner(models.Model): 70 | _inherit = 'res.partner' 71 | 72 | published_book_ids = fields.One2many( 73 | 'library.book', 74 | 'publisher_id', 75 | string='Published Books' 76 | ) 77 | authored_book_ids = fields.Many2many( 78 | 'library.book', 79 | string = 'Authored Books', 80 | # relation='library_book_res_partner_rel' # 可选项 81 | ) -------------------------------------------------------------------------------- /Chapter05/r7_constraints/my_library/models/library_book_categ.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from odoo import models, fields, api 3 | 4 | 5 | class BookCategory(models.Model): 6 | _name = 'library.book.category' 7 | 8 | _parent_store = True 9 | _parent_name = "parent_id" # 如字段为parent_id是可选项 10 | 11 | name = fields.Char('Category') 12 | parent_id = fields.Many2one( 13 | 'library.book.category', 14 | string='Parent Category', 15 | ondelete='restrict', 16 | index=True 17 | ) 18 | child_ids = fields.One2many( 19 | 'library.book.category', 'parent_id', 20 | string='Child Categories' 21 | ) 22 | parent_path = fields.Char(index=True) 23 | 24 | @api.constrains('parent_id') 25 | def _check_hierarchy(self): 26 | if not self._check_recursion(): 27 | raise models.ValidationError('Error! You cannot create recursive categories.') -------------------------------------------------------------------------------- /Chapter05/r7_constraints/my_library/security/groups.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Librarians 5 | 6 | 7 | -------------------------------------------------------------------------------- /Chapter05/r7_constraints/my_library/security/ir.model.access.csv: -------------------------------------------------------------------------------- 1 | id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink 2 | acl_book,library.book_default,model_library_book,,1,0,0,0 3 | acl_book_librarian,library.book_librarian,model_library_book,group_librarian,1,1,1,1 4 | acl_book_category,library.book_category_default,model_library_book_category,,1,0,0,0 5 | acl_book_category_librarian,library.book_category_librarian,model_library_book_category,group_librarian,1,1,1,1 -------------------------------------------------------------------------------- /Chapter05/r7_constraints/my_library/static/description/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanhou/odoo12-cookbook/db40c23e67668c081410de189c77b88d2afe1dd8/Chapter05/r7_constraints/my_library/static/description/icon.png -------------------------------------------------------------------------------- /Chapter05/r7_constraints/my_library/views/library_book.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | Library Books 6 | library.book 7 | form 8 | tree,form 9 | 10 | 11 | 12 | 14 | 15 | 16 | Library Book Form 17 | library.book 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 |
45 |
46 |
47 | 48 | 49 | Libray Book List 50 | library.book 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | Library Book Search 61 | library.book 62 | 63 | 64 | 65 | 66 | 69 | 70 | 71 | 72 |
-------------------------------------------------------------------------------- /Chapter05/r7_constraints/my_library/views/library_book_categ.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Book Categories 6 | library.book.category 7 | form 8 | tree,form 9 | 10 | 11 | 12 | 13 | 14 | 15 | Library Categories Form 16 | library.book.category 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 |
32 |
33 | 34 | 35 | 36 | Library Book List 37 | library.book.category 38 | 39 | 40 | 41 | 42 | 43 | 44 |
-------------------------------------------------------------------------------- /Chapter05/r8_compute_fields/my_library/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from . import models 3 | from . import controllers -------------------------------------------------------------------------------- /Chapter05/r8_compute_fields/my_library/__manifest__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | { 3 | 'name': 'My Library', 4 | 'summary': '轻松管理图书', 5 | 'description': """长描述占位""", 6 | 'author': 'Alan Hou', 7 | 'website': 'https://alanhou.org', 8 | 'category': 'Uncategorized', 9 | 'version': '12.0.1', 10 | 'depends': ['base', 'decimal_precision'], 11 | 'data': [ 12 | 'security/groups.xml', 13 | 'security/ir.model.access.csv', 14 | 'views/library_book.xml', 15 | 'views/library_book_categ.xml', 16 | ], 17 | } -------------------------------------------------------------------------------- /Chapter05/r8_compute_fields/my_library/controllers/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanhou/odoo12-cookbook/db40c23e67668c081410de189c77b88d2afe1dd8/Chapter05/r8_compute_fields/my_library/controllers/__init__.py -------------------------------------------------------------------------------- /Chapter05/r8_compute_fields/my_library/controllers/__pycache__/__init__.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanhou/odoo12-cookbook/db40c23e67668c081410de189c77b88d2afe1dd8/Chapter05/r8_compute_fields/my_library/controllers/__pycache__/__init__.cpython-35.pyc -------------------------------------------------------------------------------- /Chapter05/r8_compute_fields/my_library/models/__init__.py: -------------------------------------------------------------------------------- 1 | from . import library_book 2 | from . import library_book_categ -------------------------------------------------------------------------------- /Chapter05/r8_compute_fields/my_library/models/__pycache__/__init__.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanhou/odoo12-cookbook/db40c23e67668c081410de189c77b88d2afe1dd8/Chapter05/r8_compute_fields/my_library/models/__pycache__/__init__.cpython-35.pyc -------------------------------------------------------------------------------- /Chapter05/r8_compute_fields/my_library/models/__pycache__/library_book.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanhou/odoo12-cookbook/db40c23e67668c081410de189c77b88d2afe1dd8/Chapter05/r8_compute_fields/my_library/models/__pycache__/library_book.cpython-35.pyc -------------------------------------------------------------------------------- /Chapter05/r8_compute_fields/my_library/models/__pycache__/library_book_categ.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanhou/odoo12-cookbook/db40c23e67668c081410de189c77b88d2afe1dd8/Chapter05/r8_compute_fields/my_library/models/__pycache__/library_book_categ.cpython-35.pyc -------------------------------------------------------------------------------- /Chapter05/r8_compute_fields/my_library/models/library_book.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from datetime import timedelta 3 | 4 | from odoo import models, fields, api 5 | from odoo.exceptions import ValidationError 6 | from odoo.addons import decimal_precision as dp 7 | 8 | 9 | class LibraryBook(models.Model): 10 | _name = 'library.book' 11 | _description = 'Library Book' 12 | _order = 'date_release desc, name' 13 | _rec_name = 'short_name' 14 | 15 | name = fields.Char('Title', required=True) 16 | short_name = fields.Char('Short Title', translate=True, index=True) 17 | notes = fields.Text('Internal Notes') 18 | state = fields.Selection( 19 | [('draft', 'Not Available'), 20 | ('available', 'Available'), 21 | ('lost', 'Lost')], 22 | 'State', default="draft") 23 | description = fields.Html('Description', sanitize=True, strip_style=False) 24 | cover = fields.Binary('Book Cover') 25 | out_of_print = fields.Boolean('Out of Print?') 26 | date_release = fields.Date('Release Date') 27 | date_updated = fields.Datetime('Last Updated') 28 | pages = fields.Integer('Number of Pages', 29 | groups="base.group_user", 30 | state={'lost': [('readonly', True)]}, 31 | help="Total book page count", company_dependent=False) 32 | reader_rating = fields.Float( 33 | 'Reader Average Rating', 34 | digits=(14, 4), # 可选精度(总数,小数) 35 | ) 36 | author_ids = fields.Many2many( 37 | 'res.partner', 38 | string='Authors' 39 | ) 40 | cost_price = fields.Float('Book Cost', digits=dp.get_precision('Book Price')) 41 | currency_id = fields.Many2one('res.currency', string='Currency') 42 | retail_price = fields.Monetary('Retail Price') # 可选属性:currency_field='currency_id',以防币种字段有currency_id 以外的名称 43 | 44 | publisher_id = fields.Many2one( 45 | 'res.partner', string='Publisher', 46 | # 下为可选项 47 | ondelete='set null', 48 | context = {}, 49 | domain = [], 50 | ) 51 | category_id = fields.Many2one('library.book.category') 52 | age_days = fields.Float( 53 | string='Days Since Release', 54 | compute='_compute_age', inverse='_inverse_age', search='_search_age', 55 | store=False, 56 | compute_sudo=False, 57 | ) 58 | 59 | @api.depends('date_release') 60 | def _compute_age(self): 61 | today = fields.Date.today() 62 | for book in self.filtered('date_release'): 63 | delta = today - book.date_release 64 | book.age_days = delta.days 65 | 66 | 67 | # 这一_compute_age的反向方法用于让 age_days 字段可编辑 68 | # 这是可选项,如果不想让该计算字段可编辑可以进行删除 69 | def _inverse_age(self): 70 | today = fields.Date.today() 71 | for book in self.filtered('date_release'): 72 | d = today - timedelta(days=book.age_days) 73 | book.date_release = d 74 | 75 | # 用于启动对计算字段的搜索 76 | # 这是可选项,如果不想启用该搜索可以进行删除 77 | def _search_age(self, operator, value): 78 | today = fields.Date.today() 79 | value_days = timedelta(days=value) 80 | value_date = today - value_days 81 | # 转换运算符 82 | # age > value 对应 date < value_date 83 | operator_map = { 84 | '>': '<', '>=': '<=', 85 | '<': '>', '<=': '>=', 86 | } 87 | new_op = operator_map.get(operator, operator) 88 | return [('date_release', new_op, value_date)] 89 | 90 | def name_get(self): 91 | """ 这个方法用于自定义记录的显示名称 """ 92 | result = [] 93 | for record in self: 94 | rec_name = "%s (%s)" % (record.name, record.date_release) 95 | result.append((record.id, rec_name)) 96 | return result 97 | 98 | _sql_constraints = [('name_uniq', 'UNIQUE(name)', 'Book title must be unique.')] 99 | 100 | @api.constrains('date_release') 101 | def _check_release_date(self): 102 | for record in self: 103 | if record.date_release and record.date_release > fields.Date.today(): 104 | raise models.ValidationError('Release date must be in the past') 105 | 106 | 107 | class ResPartner(models.Model): 108 | _inherit = 'res.partner' 109 | 110 | published_book_ids = fields.One2many( 111 | 'library.book', 112 | 'publisher_id', 113 | string='Published Books' 114 | ) 115 | authored_book_ids = fields.Many2many( 116 | 'library.book', 117 | string = 'Authored Books', 118 | # relation='library_book_res_partner_rel' # 可选项 119 | ) -------------------------------------------------------------------------------- /Chapter05/r8_compute_fields/my_library/models/library_book_categ.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from odoo import models, fields, api 3 | 4 | 5 | class BookCategory(models.Model): 6 | _name = 'library.book.category' 7 | 8 | _parent_store = True 9 | _parent_name = "parent_id" # 如字段为parent_id是可选项 10 | 11 | name = fields.Char('Category') 12 | parent_id = fields.Many2one( 13 | 'library.book.category', 14 | string='Parent Category', 15 | ondelete='restrict', 16 | index=True 17 | ) 18 | child_ids = fields.One2many( 19 | 'library.book.category', 'parent_id', 20 | string='Child Categories' 21 | ) 22 | parent_path = fields.Char(index=True) 23 | 24 | @api.constrains('parent_id') 25 | def _check_hierarchy(self): 26 | if not self._check_recursion(): 27 | raise models.ValidationError('Error! You cannot create recursive categories.') -------------------------------------------------------------------------------- /Chapter05/r8_compute_fields/my_library/security/groups.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Librarians 5 | 6 | 7 | -------------------------------------------------------------------------------- /Chapter05/r8_compute_fields/my_library/security/ir.model.access.csv: -------------------------------------------------------------------------------- 1 | id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink 2 | acl_book,library.book_default,model_library_book,,1,0,0,0 3 | acl_book_librarian,library.book_librarian,model_library_book,group_librarian,1,1,1,1 4 | acl_book_category,library.book_category_default,model_library_book_category,,1,0,0,0 5 | acl_book_category_librarian,library.book_category_librarian,model_library_book_category,group_librarian,1,1,1,1 -------------------------------------------------------------------------------- /Chapter05/r8_compute_fields/my_library/static/description/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanhou/odoo12-cookbook/db40c23e67668c081410de189c77b88d2afe1dd8/Chapter05/r8_compute_fields/my_library/static/description/icon.png -------------------------------------------------------------------------------- /Chapter05/r8_compute_fields/my_library/views/library_book.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | Library Books 6 | library.book 7 | form 8 | tree,form 9 | 10 | 11 | 12 | 14 | 15 | 16 | Library Book Form 17 | library.book 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 |
46 |
47 |
48 | 49 | 50 | Libray Book List 51 | library.book 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | Library Book Search 62 | library.book 63 | 64 | 65 | 66 | 67 | 70 | 71 | 72 | 73 |
-------------------------------------------------------------------------------- /Chapter05/r8_compute_fields/my_library/views/library_book_categ.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Book Categories 6 | library.book.category 7 | form 8 | tree,form 9 | 10 | 11 | 12 | 13 | 14 | 15 | Library Categories Form 16 | library.book.category 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 |
32 |
33 | 34 | 35 | 36 | Library Book List 37 | library.book.category 38 | 39 | 40 | 41 | 42 | 43 | 44 |
-------------------------------------------------------------------------------- /Chapter05/r9_related_fields/my_library/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from . import models 3 | from . import controllers -------------------------------------------------------------------------------- /Chapter05/r9_related_fields/my_library/__manifest__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | { 3 | 'name': 'My Library', 4 | 'summary': '轻松管理图书', 5 | 'description': """长描述占位""", 6 | 'author': 'Alan Hou', 7 | 'website': 'https://alanhou.org', 8 | 'category': 'Uncategorized', 9 | 'version': '12.0.1', 10 | 'depends': ['base', 'decimal_precision'], 11 | 'data': [ 12 | 'security/groups.xml', 13 | 'security/ir.model.access.csv', 14 | 'views/library_book.xml', 15 | 'views/library_book_categ.xml', 16 | ], 17 | } -------------------------------------------------------------------------------- /Chapter05/r9_related_fields/my_library/controllers/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanhou/odoo12-cookbook/db40c23e67668c081410de189c77b88d2afe1dd8/Chapter05/r9_related_fields/my_library/controllers/__init__.py -------------------------------------------------------------------------------- /Chapter05/r9_related_fields/my_library/controllers/__pycache__/__init__.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanhou/odoo12-cookbook/db40c23e67668c081410de189c77b88d2afe1dd8/Chapter05/r9_related_fields/my_library/controllers/__pycache__/__init__.cpython-35.pyc -------------------------------------------------------------------------------- /Chapter05/r9_related_fields/my_library/models/__init__.py: -------------------------------------------------------------------------------- 1 | from . import library_book 2 | from . import library_book_categ -------------------------------------------------------------------------------- /Chapter05/r9_related_fields/my_library/models/__pycache__/__init__.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanhou/odoo12-cookbook/db40c23e67668c081410de189c77b88d2afe1dd8/Chapter05/r9_related_fields/my_library/models/__pycache__/__init__.cpython-35.pyc -------------------------------------------------------------------------------- /Chapter05/r9_related_fields/my_library/models/__pycache__/library_book.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanhou/odoo12-cookbook/db40c23e67668c081410de189c77b88d2afe1dd8/Chapter05/r9_related_fields/my_library/models/__pycache__/library_book.cpython-35.pyc -------------------------------------------------------------------------------- /Chapter05/r9_related_fields/my_library/models/__pycache__/library_book_categ.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanhou/odoo12-cookbook/db40c23e67668c081410de189c77b88d2afe1dd8/Chapter05/r9_related_fields/my_library/models/__pycache__/library_book_categ.cpython-35.pyc -------------------------------------------------------------------------------- /Chapter05/r9_related_fields/my_library/models/library_book.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from datetime import timedelta 3 | 4 | from odoo import models, fields, api 5 | from odoo.exceptions import ValidationError 6 | from odoo.addons import decimal_precision as dp 7 | 8 | 9 | class LibraryBook(models.Model): 10 | _name = 'library.book' 11 | _description = 'Library Book' 12 | _order = 'date_release desc, name' 13 | _rec_name = 'short_name' 14 | 15 | name = fields.Char('Title', required=True) 16 | short_name = fields.Char('Short Title', translate=True, index=True) 17 | notes = fields.Text('Internal Notes') 18 | state = fields.Selection( 19 | [('draft', 'Not Available'), 20 | ('available', 'Available'), 21 | ('lost', 'Lost')], 22 | 'State', default="draft") 23 | description = fields.Html('Description', sanitize=True, strip_style=False) 24 | cover = fields.Binary('Book Cover') 25 | out_of_print = fields.Boolean('Out of Print?') 26 | date_release = fields.Date('Release Date') 27 | date_updated = fields.Datetime('Last Updated') 28 | pages = fields.Integer('Number of Pages', 29 | groups="base.group_user", 30 | state={'lost': [('readonly', True)]}, 31 | help="Total book page count", company_dependent=False) 32 | reader_rating = fields.Float( 33 | 'Reader Average Rating', 34 | digits=(14, 4), # 可选精度(总数,小数) 35 | ) 36 | author_ids = fields.Many2many( 37 | 'res.partner', 38 | string='Authors' 39 | ) 40 | cost_price = fields.Float('Book Cost', digits=dp.get_precision('Book Price')) 41 | currency_id = fields.Many2one('res.currency', string='Currency') 42 | retail_price = fields.Monetary('Retail Price') # 可选属性:currency_field='currency_id',以防币种字段有currency_id 以外的名称 43 | 44 | publisher_id = fields.Many2one( 45 | 'res.partner', string='Publisher', 46 | # 下为可选项 47 | ondelete='set null', 48 | context = {}, 49 | domain = [], 50 | ) 51 | publisher_city = fields.Char('Publisher City', related='publisher_id.city', readonly=True) 52 | category_id = fields.Many2one('library.book.category') 53 | age_days = fields.Float( 54 | string='Days Since Release', 55 | compute='_compute_age', inverse='_inverse_age', search='_search_age', 56 | store=False, 57 | compute_sudo=False, 58 | ) 59 | 60 | @api.depends('date_release') 61 | def _compute_age(self): 62 | today = fields.Date.today() 63 | for book in self.filtered('date_release'): 64 | delta = today - book.date_release 65 | book.age_days = delta.days 66 | 67 | 68 | # 这一_compute_age的反向方法用于让 age_days 字段可编辑 69 | # 这是可选项,如果不想让该计算字段可编辑可以进行删除 70 | def _inverse_age(self): 71 | today = fields.Date.today() 72 | for book in self.filtered('date_release'): 73 | d = today - timedelta(days=book.age_days) 74 | book.date_release = d 75 | 76 | # 用于启动对计算字段的搜索 77 | # 这是可选项,如果不想启用该搜索可以进行删除 78 | def _search_age(self, operator, value): 79 | today = fields.Date.today() 80 | value_days = timedelta(days=value) 81 | value_date = today - value_days 82 | # 转换运算符 83 | # age > value 对应 date < value_date 84 | operator_map = { 85 | '>': '<', '>=': '<=', 86 | '<': '>', '<=': '>=', 87 | } 88 | new_op = operator_map.get(operator, operator) 89 | return [('date_release', new_op, value_date)] 90 | 91 | def name_get(self): 92 | """ 这个方法用于自定义记录的显示名称 """ 93 | result = [] 94 | for record in self: 95 | rec_name = "%s (%s)" % (record.name, record.date_release) 96 | result.append((record.id, rec_name)) 97 | return result 98 | 99 | _sql_constraints = [('name_uniq', 'UNIQUE(name)', 'Book title must be unique.')] 100 | 101 | @api.constrains('date_release') 102 | def _check_release_date(self): 103 | for record in self: 104 | if record.date_release and record.date_release > fields.Date.today(): 105 | raise models.ValidationError('Release date must be in the past') 106 | 107 | 108 | class ResPartner(models.Model): 109 | _inherit = 'res.partner' 110 | 111 | published_book_ids = fields.One2many( 112 | 'library.book', 113 | 'publisher_id', 114 | string='Published Books' 115 | ) 116 | authored_book_ids = fields.Many2many( 117 | 'library.book', 118 | string = 'Authored Books', 119 | # relation='library_book_res_partner_rel' # 可选项 120 | ) -------------------------------------------------------------------------------- /Chapter05/r9_related_fields/my_library/models/library_book_categ.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from odoo import models, fields, api 3 | 4 | 5 | class BookCategory(models.Model): 6 | _name = 'library.book.category' 7 | 8 | _parent_store = True 9 | _parent_name = "parent_id" # 如字段为parent_id是可选项 10 | 11 | name = fields.Char('Category') 12 | parent_id = fields.Many2one( 13 | 'library.book.category', 14 | string='Parent Category', 15 | ondelete='restrict', 16 | index=True 17 | ) 18 | child_ids = fields.One2many( 19 | 'library.book.category', 'parent_id', 20 | string='Child Categories' 21 | ) 22 | parent_path = fields.Char(index=True) 23 | 24 | @api.constrains('parent_id') 25 | def _check_hierarchy(self): 26 | if not self._check_recursion(): 27 | raise models.ValidationError('Error! You cannot create recursive categories.') -------------------------------------------------------------------------------- /Chapter05/r9_related_fields/my_library/security/groups.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Librarians 5 | 6 | 7 | -------------------------------------------------------------------------------- /Chapter05/r9_related_fields/my_library/security/ir.model.access.csv: -------------------------------------------------------------------------------- 1 | id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink 2 | acl_book,library.book_default,model_library_book,,1,0,0,0 3 | acl_book_librarian,library.book_librarian,model_library_book,group_librarian,1,1,1,1 4 | acl_book_category,library.book_category_default,model_library_book_category,,1,0,0,0 5 | acl_book_category_librarian,library.book_category_librarian,model_library_book_category,group_librarian,1,1,1,1 -------------------------------------------------------------------------------- /Chapter05/r9_related_fields/my_library/static/description/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanhou/odoo12-cookbook/db40c23e67668c081410de189c77b88d2afe1dd8/Chapter05/r9_related_fields/my_library/static/description/icon.png -------------------------------------------------------------------------------- /Chapter05/r9_related_fields/my_library/views/library_book.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | Library Books 6 | library.book 7 | form 8 | tree,form 9 | 10 | 11 | 12 | 14 | 15 | 16 | Library Book Form 17 | library.book 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 |
47 |
48 |
49 | 50 | 51 | Libray Book List 52 | library.book 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | Library Book Search 63 | library.book 64 | 65 | 66 | 67 | 68 | 71 | 72 | 73 | 74 |
-------------------------------------------------------------------------------- /Chapter05/r9_related_fields/my_library/views/library_book_categ.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Book Categories 6 | library.book.category 7 | form 8 | tree,form 9 | 10 | 11 | 12 | 13 | 14 | 15 | Library Categories Form 16 | library.book.category 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 |
32 |
33 | 34 | 35 | 36 | Library Book List 37 | library.book.category 38 | 39 | 40 | 41 | 42 | 43 | 44 |
-------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Odoo 12开发者指南(Cookbook)第三版 2 | 3 | > ⚠️本书内容未经译者校对,错误较多,建议直接阅读[Odoo 14开发者指南(Cookbook)第四版](https://github.com/iTranslateX/odoo-cookbook) 4 | 5 | 其实是否翻译这本书我内心是纠结的,毕竟已经有了一套完整的[最好用的免费ERP系统Odoo 12开发手册](https://github.com/iTranslateX/odoo-essentials),且以我个人的工作的方向而言目前使用 Odoo 的地方真心不多。这几个月有部分读者视我为 Odoo 的专家,我也竭力地解答了大部分问题,但我其实是属于 Odoo 社区的外围人员,对它的了解并不是很深入,也几乎没在相关交流群和论坛中做过任何发言。此外五月我计划中的翻译重点是一套人工智能的书([Python之 AI人工智能初学者指南](https://alanhou.org/python-beginners-guide-artificial-intelligence/)),挑战还是蛮大的。 6 | 7 | 但冥冥中这本书的上一版([最好用的免费ERP系统Odoo 11开发指南](https://alanhou.org/odoo-11-development/))未完成翻译的挫败感和我深信未来会与 Odoo 有着紧密的交集促始我还是决定开始翻译这本书。不过翻译进度就真的是随缘了^-^ 8 | 9 | 话说新版加了作者,页面数也足足多了300页😂 10 | 11 | ![](http://upload-images.jianshu.io/upload_images/14565748-837479975d16fbed.jpg) 12 | 13 | 英文原书:Odoo 12 Development Cookbook - Third Edition *190+ unique recipes to build effective enterprise and business application*s by Parth Gajjar, Alexandre Fayolle, Holger Brunn, Daniel Reis 14 | 15 | ## 前言 16 | 17 | Odoo 是一个集成业务应用的套件。Odoo自带有25个不同的业务应用,涵盖CRM、生产制造、电商、会计等领域。简言之,它是一个覆盖你所有业务需求的多合一的解决方案。 18 | 19 | Odoo 对开人员也是一个很棒的软件。有赖于 Odoo 强大的框架,开发人员可以从头开始构建强大的应用。Odoo框架有内置的插件机制。Odoo的内置应用也使用相同框架进行创建,并且其可扩展性有助于开发人员创建插件模块来修改已有应用。 20 | 21 | Odoo涉及的领域很广,对于新手很难跟上这一学习曲线。Odoo 12开发者指南第三版提供一个逐步操作的指南来帮助你学习Odoo框架的方方面面,包括所有版本12的最新功能。它独特的设问和解决方案的方法有助于你解决日常Odoo开发中的问题。 22 | 23 | ## 本书面向的读者 24 | 25 | 这本书对于新手和有经验的开发人员都很适合。如果你有Python编程语言的基础知识,这本书可以帮助你很容易地习得Odoo框架的专业知识。如是你是一个想要使用Odoo框架开始高效业务应用,并想通过它来学习Odoo框架的实际案例,这本书非常适合你。 26 | 27 | ## 本书主要内容 28 | 29 | [第一章 安装Odoo开发环境](https://github.com/iTranslateX/odoo-cookbook/blob/v12/1.md):通过介绍Odoo生态系统进行开始。这里你将学习如何为开发环境安装并设置Odoo。你还将学习到如何激活开发工具。 30 | 31 | [第二章 管理Odoo服务器实例](https://github.com/iTranslateX/odoo-cookbook/blob/v12/2.md):有关安装和升级插件。它为你提供组织从GitHub上下载的自定义插件一些有用的小贴士。 32 | 33 | [第三章 服务器部署](https://github.com/iTranslateX/odoo-cookbook/blob/v12/3.md):有关如何为生产环境安装并配置Odoo实例。本章包含NGINX反向代理、SSL配置、启动服务和基本的Docker部署。还包含网站的CDN配置。 34 | 35 | [第四章 创建Odoo插件模块](https://github.com/iTranslateX/odoo-cookbook/blob/v12/4.md):讲解Odoo插件模块的结构并提供从零开始创建一个简单的Odoo模块的逐步操作指南。 36 | 37 | [第五章 应用模型](https://github.com/iTranslateX/odoo-cookbook/blob/v12/5.md):聚焦于Odoo模型结构,并讲解所有字段类型及它们的属性。本章还包含继承和扩展已有模型的不同方式。 38 | 39 | [第六章 基本服务端部署](https://github.com/iTranslateX/odoo-cookbook/blob/v12/6.md):介绍Odoo框架的API,展示增删改查(CRUD)方法以及其它常用方法的使用。本章还讲解如何在Odoo中编写业务逻辑。 40 | 41 | [第七章 模块数据](https://github.com/iTranslateX/odoo-cookbook/blob/v12/7.md):显示如何迁移你的插件模块和内置数据。还讲解编写迁移函数的基本步骤。 42 | 43 | [第八章 调试](https://github.com/iTranslateX/odoo-cookbook/blob/v12/8.md):提供调试Odoo代码的不同策略。本章包含开发者选项和Odoo shell的使用。 44 | 45 | [第九章 高级服务端开发技巧](https://github.com/iTranslateX/odoo-cookbook/blob/v12/9.md):讲解ORM框架更高级的课题。对于开发向导、SQL视图、安装钩子(hook)、on-change方法等非常有用。本章还讲解了如何在数据库中执行原生SQL查询。 46 | 47 | [第十章 后端视图](https://github.com/iTranslateX/odoo-cookbook/blob/v12/10.md):教授如何创建不同的UI视图以及如何从用户界面中触发业务逻辑。它涵盖了所有常用视图,如列表、表单、看板、日历、图形、搜索和透视表视图,还有一些新引入的视图,如cohort和仪表盘。本章还包含修改/继承已有视图的一些指导。 48 | 49 | [第十一章 权限安全](https://github.com/iTranslateX/odoo-cookbook/blob/v12/11.md):涵盖Odoo框架的安全方面。它显示了如何通过创建安全组、访问控制列表和记录级别规则来控制/限制用户对模型的访问。 50 | 51 | [第十二章 国际化](https://github.com/iTranslateX/odoo-cookbook/blob/v12/12.md):显示如何翻译你的插件模块的用户界面,并为管理翻译文件提供了有用的技巧。 52 | 53 | [第十三章 自动化、工作流和打印件](https://github.com/iTranslateX/odoo-cookbook/blob/v12/13.md):描绘了Odoo中实现更好的业务流程可用的不同工作和技巧。它展示如何使用服务端动作、自动化动作和基于时间的调度动作。本章还包含为你的模型创建PDF报告的指南。 54 | 55 | [第十四章 网页服务端开发](https://github.com/iTranslateX/odoo-cookbook/blob/v12/14.md):涵盖Odoo web服务的核心内容。它展示了如何创建自定义URL路径由来在指定URL上提供服务,以及如何对这些URL进行访问控制。 56 | 57 | [第十五章 CMS网站开发](https://github.com/iTranslateX/odoo-cookbook/blob/v12/15.md):讲解如何使用Odoo管理网站。还展示了如何创建和修改美观的网页和QWeb模板。本章还包含如何创建带选项的动态网页构建块。它包含一些管理 SEO、用户表单、UTM追踪、网站地图和获取访客地理信息的独立教程。本章还强调了Odoo中最新的多站点概念。 58 | 59 | [第十六章 网页客户端开发](https://github.com/iTranslateX/odoo-cookbook/blob/v12/16.md):深入到Odoo的JavaScript部分。涵盖了如何创建新字段控件以及对服务端发送RPC调用。还包含如何从零开始创建全新的视图。你还将学习如何创建操作向导。 60 | 61 | [第十七章 Odoo的应用内购买](https://github.com/iTranslateX/odoo-cookbook/blob/v12/17.md):涵盖有关Odoo最新的应用内购买(IAP)概念的所有内容。本章中你学习到如何为IAP创建客户端和服务模块。你还将学习到如何创建IAP账户并从终端用户提取IAP款项。 62 | 63 | [第十八章 自动化测试用例](https://github.com/iTranslateX/odoo-cookbook/blob/v12/18.md):涵盖如何在Odoo中编写和执行自动化测试用例,包含服务端、客户端以及操作向导集成的测试用例。本章还包含设置chrome-headless(无头浏览器模式)来截屏和录制视频来查看出错的客户端的测试用例的示范。 64 | 65 | [第十九章 使用Odoo.sh管理、部署和测试](https://github.com/iTranslateX/odoo-cookbook/blob/v12/19.md):讲解Odoo.sh,一个部署Odoo实例的PaaS平台,包含生产、模拟和开发分支的各方面。也讲解了该平台的不同选项。 66 | 67 | [第二十章 Odoo中的远程过程调用(RPC)](https://github.com/iTranslateX/odoo-cookbook/blob/v12/20.md):涵盖从外部应用连接Odoo实例的不同方式。本章教你如何通过XML-RPC、JSON-RPC和odoorpc库连接和从 Odoo实例访问数据。 68 | 69 | [第二十一章 性能优化](https://github.com/iTranslateX/odoo-cookbook/blob/v12/21.md):讲解用于获取Odoo中性能提升的不同概念和模式。本章包含预提取、ORM缓存和代码性能测试来监测性能问题的概念。 70 | 71 | [第二十二章 POS(销售点)](https://github.com/iTranslateX/odoo-cookbook/blob/v12/22.md):涵盖 POS 应用的自定义。包含用户界面、添加新动作按钮、修改业务流和扩展客户菜单的自定义。 72 | 73 | [第二十三章 在Odoo中管理email](https://github.com/iTranslateX/odoo-cookbook/blob/v12/23.md):讲解如何在Odoo中管理email和聊天工具。通过配置邮件服务器开始,然后讲解Odoo框架的邮件API。本章还涵盖Jinja2和QWeb邮件模板、表单视图、字段记录和活动的聊天工具。 74 | 75 | [第二十四章 IoT盒子](https://github.com/iTranslateX/odoo-cookbook/blob/v12/24.md):给出了最新的IoT盒子硬件的重点讲解。本章涵盖如何配置、访问和调试IoT盒子。不包含一个集成IoT盒子到你的自定义插件的示范。 76 | 77 | 78 | ## 其它相关 79 | 80 | [Odoo 12开发者指南补充知识](https://alanhou.org/odoo-12-supplement/) 81 | 82 | --------------------------------------------------------------------------------