From 0a5368bb64b0fb5a292edc6e3bfbbac966dd8188 Mon Sep 17 00:00:00 2001 From: mtpc4s9 Date: Tue, 18 Nov 2025 22:50:50 +0700 Subject: [PATCH 01/30] ok --- docker-compose.yml | 27 +++++++++++++++------------ etc/logrotate | 0 etc/requirements.txt | 0 3 files changed, 15 insertions(+), 12 deletions(-) mode change 100644 => 100755 etc/logrotate mode change 100644 => 100755 etc/requirements.txt diff --git a/docker-compose.yml b/docker-compose.yml index dc4423e..8898dce 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,36 +1,39 @@ -version: '2' +version: '3.1' # Nâng cấp version lên chuẩn mới hơn + services: db: image: postgres:17 - user: root + # ĐÃ XÓA "user: root". Hãy để nó tự chạy bằng user "postgres". environment: - POSTGRES_USER=odoo - POSTGRES_PASSWORD=odoo18@2024 - POSTGRES_DB=postgres - restart: always # run as a service + restart: always volumes: - - ./postgresql:/var/lib/postgresql/data + # Dùng Named Volume thay vì thư mục ./postgresql để tránh lỗi permission + - pgdata:/var/lib/postgresql/data odoo18: image: odoo:18 - user: root + # ĐÃ XÓA "user: root". Hãy để nó tự chạy bằng user "odoo". depends_on: - db ports: - "10018:8069" - - "20018:8072" # live chat + - "20018:8072" tty: true - command: -- + # Chỉ định rõ file config + command: --config /etc/odoo/odoo.conf environment: - HOST=db - USER=odoo - PASSWORD=odoo18@2024 - PIP_BREAK_SYSTEM_PACKAGES=1 volumes: - #- /etc/timezone:/etc/timezone:ro - #- /etc/localtime:/etc/localtime:ro - - ./entrypoint.sh:/entrypoint.sh - ./addons:/mnt/extra-addons - ./etc:/etc/odoo - restart: always # run as a service - \ No newline at end of file + restart: always + +# Định nghĩa nơi lưu dữ liệu DB do Docker quản lý +volumes: + pgdata: \ No newline at end of file diff --git a/etc/logrotate b/etc/logrotate old mode 100644 new mode 100755 diff --git a/etc/requirements.txt b/etc/requirements.txt old mode 100644 new mode 100755 From bcc07836d41a7819234177192b65478563ee2260 Mon Sep 17 00:00:00 2001 From: mtpc4s9 Date: Tue, 18 Nov 2025 23:01:22 +0700 Subject: [PATCH 02/30] ok --- docker-compose.yml | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 8898dce..4b40431 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,33 +3,31 @@ version: '3.1' # Nâng cấp version lên chuẩn mới hơn services: db: image: postgres:17 - # ĐÃ XÓA "user: root". Hãy để nó tự chạy bằng user "postgres". environment: - POSTGRES_USER=odoo - POSTGRES_PASSWORD=odoo18@2024 - POSTGRES_DB=postgres restart: always volumes: - # Dùng Named Volume thay vì thư mục ./postgresql để tránh lỗi permission - - pgdata:/var/lib/postgresql/data + - pgdata:/var/lib/postgresql/data odoo18: image: odoo:18 - # ĐÃ XÓA "user: root". Hãy để nó tự chạy bằng user "odoo". depends_on: - db ports: - "10018:8069" - "20018:8072" tty: true - # Chỉ định rõ file config - command: --config /etc/odoo/odoo.conf + + command: -- --config /etc/odoo/odoo.conf environment: - HOST=db - USER=odoo - PASSWORD=odoo18@2024 - PIP_BREAK_SYSTEM_PACKAGES=1 volumes: + - ./entrypoint.sh:/entrypoint.sh - ./addons:/mnt/extra-addons - ./etc:/etc/odoo restart: always From 7de328e3077c1c7964f53bd743d2c7b8c980be67 Mon Sep 17 00:00:00 2001 From: mtpc4s9 Date: Tue, 18 Nov 2025 23:04:27 +0700 Subject: [PATCH 03/30] ok --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index 4b40431..712e2db 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -9,7 +9,7 @@ services: - POSTGRES_DB=postgres restart: always volumes: - - pgdata:/var/lib/postgresql/data + - ./postgresql:/var/lib/postgresql/data odoo18: image: odoo:18 From 53ccb17a498047695e695fb174f0cede629ac774 Mon Sep 17 00:00:00 2001 From: mtpc4s9 Date: Tue, 18 Nov 2025 23:10:13 +0700 Subject: [PATCH 04/30] ok --- docker-compose.yml | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 712e2db..b2c1818 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,34 +3,37 @@ version: '3.1' # Nâng cấp version lên chuẩn mới hơn services: db: image: postgres:17 + environment: - POSTGRES_USER=odoo - POSTGRES_PASSWORD=odoo18@2024 - POSTGRES_DB=postgres - restart: always + restart: always # run as a service volumes: - ./postgresql:/var/lib/postgresql/data odoo18: image: odoo:18 + user: root depends_on: - db ports: - "10018:8069" - - "20018:8072" + - "20018:8072" # live chat tty: true - - command: -- --config /etc/odoo/odoo.conf + entrypoint: /entrypoint.sh environment: - HOST=db - USER=odoo - PASSWORD=odoo18@2024 - PIP_BREAK_SYSTEM_PACKAGES=1 volumes: + #- /etc/timezone:/etc/timezone:ro + #- /etc/localtime:/etc/localtime:ro - ./entrypoint.sh:/entrypoint.sh - ./addons:/mnt/extra-addons - ./etc:/etc/odoo - restart: always + restart: always # run as a service # Định nghĩa nơi lưu dữ liệu DB do Docker quản lý volumes: From f21eef4b3ddf688c28ed9ca41672f0e4359000e4 Mon Sep 17 00:00:00 2001 From: mtpc4s9 Date: Tue, 18 Nov 2025 23:20:18 +0700 Subject: [PATCH 05/30] ok --- docker-compose.yml | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index b2c1818..84c8afb 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,9 +1,7 @@ -version: '3.1' # Nâng cấp version lên chuẩn mới hơn - +version: '3.1' services: db: image: postgres:17 - environment: - POSTGRES_USER=odoo - POSTGRES_PASSWORD=odoo18@2024 @@ -34,7 +32,4 @@ services: - ./addons:/mnt/extra-addons - ./etc:/etc/odoo restart: always # run as a service - -# Định nghĩa nơi lưu dữ liệu DB do Docker quản lý -volumes: - pgdata: \ No newline at end of file + \ No newline at end of file From a3d955910708f5ef8a97b9653892a0c09070f725 Mon Sep 17 00:00:00 2001 From: mtpc4s9 Date: Tue, 18 Nov 2025 23:23:11 +0700 Subject: [PATCH 06/30] ok --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index 84c8afb..c9f2097 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -19,7 +19,7 @@ services: - "10018:8069" - "20018:8072" # live chat tty: true - entrypoint: /entrypoint.sh + command: -- environment: - HOST=db - USER=odoo From 416f7cfea046c4b5076c0e1f4b59d2a14fd0c009 Mon Sep 17 00:00:00 2001 From: mtpc4s9 Date: Tue, 18 Nov 2025 23:25:18 +0700 Subject: [PATCH 07/30] ok --- docker-compose.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index c9f2097..6a4b858 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,7 +1,8 @@ -version: '3.1' +version: '2' services: db: image: postgres:17 + #user: root environment: - POSTGRES_USER=odoo - POSTGRES_PASSWORD=odoo18@2024 From 2a95e71a39b334d1df43ed42f271811e13f82602 Mon Sep 17 00:00:00 2001 From: mtpc4s9 Date: Tue, 18 Nov 2025 23:30:50 +0700 Subject: [PATCH 08/30] ok --- docker-compose.yml | 3 +-- etc/odoo.conf | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 6a4b858..c9f2097 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,8 +1,7 @@ -version: '2' +version: '3.1' services: db: image: postgres:17 - #user: root environment: - POSTGRES_USER=odoo - POSTGRES_PASSWORD=odoo18@2024 diff --git a/etc/odoo.conf b/etc/odoo.conf index 2535225..c316b40 100755 --- a/etc/odoo.conf +++ b/etc/odoo.conf @@ -59,6 +59,39 @@ data_dir = /etc/odoo admin_passwd = minhng.info +; ========================== +; | Database Configuration | +; ========================== +; ------ +; -d / --database | specify the database name +; ------ +; db_name = + +; ------ +; -r / --db-user | specify the database user name +; ------ +db_user = odoo + +; ------ +; -w / --db-password | specify the database password +; ------ +db_password = odoo18@2024 + +; ------ +; --db-host | specify the database host +; ------ +db_host = db + +; ------ +; --db-port | specify the database port +; ------ +db_port = 5432 + +; ------ +; --db-sslmode | specify the database ssl mode [allow|prefer|require|disable] +; ------ +db_sslmode = prefer + ; ============================== ; | HTTP Service Configuration | ; ============================== From c12a1742d03ff5d0e8ae3cd55cc8883c2660e329 Mon Sep 17 00:00:00 2001 From: mtpc4s9 Date: Tue, 18 Nov 2025 23:52:13 +0700 Subject: [PATCH 09/30] ok --- addons/foo/__manifest__.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 addons/foo/__manifest__.py diff --git a/addons/foo/__manifest__.py b/addons/foo/__manifest__.py new file mode 100644 index 0000000..39254db --- /dev/null +++ b/addons/foo/__manifest__.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +# https://www.odoo.com/documentation/18.0/developer/reference/backend/module.html +{ + 'name': 'Foo', + 'summary': """Foo custom addon""", + 'description': """Foo module description""", + 'author': 'minhng.info', + 'maintainer': 'minhng.info', + 'website': 'https://minhng.info', + 'category': 'Uncategorized', # https://github.com/odoo/odoo/blob/18.0/odoo/addons/base/data/ir_module_category_data.xml + 'version': '0.1', + 'depends': [ + 'sale', + 'hr', + ], + 'data': [], + 'demo': [], + 'css': [], + # 'qweb': ['static/src/xml/*.xml'], + 'installable': True, + 'auto_install': False, + 'application': True, +} \ No newline at end of file From d95f80636b3adddc08f542aaacd36b0a16c4d486 Mon Sep 17 00:00:00 2001 From: mtpc4s9 Date: Wed, 19 Nov 2025 00:00:02 +0700 Subject: [PATCH 10/30] ok --- addons/zoo/__init__.py | 1 + addons/zoo/__manifest__.py | 22 ++++++++++++++++++++++ addons/zoo/models/__init__.py | 1 + addons/zoo/models/zoo_animal.py | 23 +++++++++++++++++++++++ addons/zoo/static/description/icon.png | Bin 0 -> 5832 bytes 5 files changed, 47 insertions(+) create mode 100644 addons/zoo/__init__.py create mode 100644 addons/zoo/__manifest__.py create mode 100644 addons/zoo/models/__init__.py create mode 100644 addons/zoo/models/zoo_animal.py create mode 100644 addons/zoo/static/description/icon.png diff --git a/addons/zoo/__init__.py b/addons/zoo/__init__.py new file mode 100644 index 0000000..9a7e03e --- /dev/null +++ b/addons/zoo/__init__.py @@ -0,0 +1 @@ +from . import models \ No newline at end of file diff --git a/addons/zoo/__manifest__.py b/addons/zoo/__manifest__.py new file mode 100644 index 0000000..4fdcfeb --- /dev/null +++ b/addons/zoo/__manifest__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# https://www.odoo.com/documentation/18.0/developer/reference/backend/module.html +{ + 'name': 'Zoo City', + 'summary': """Zoo City Tutorials""", + 'description': """Building my own zoo city""", + 'author': 'minhng.info', + 'maintainer': 'minhng.info', + 'website': 'https://minhng.info', + 'category': 'Uncategorized', # https://github.com/odoo/odoo/blob/18.0/odoo/addons/base/data/ir_module_category_data.xml + 'version': '0.1', + 'depends': [ + 'product', + ], + 'data': [], + 'demo': [], + 'css': [], + # 'qweb': ['static/src/xml/*.xml'], + 'installable': True, + 'auto_install': False, + 'application': True, +} \ No newline at end of file diff --git a/addons/zoo/models/__init__.py b/addons/zoo/models/__init__.py new file mode 100644 index 0000000..b3a9fb6 --- /dev/null +++ b/addons/zoo/models/__init__.py @@ -0,0 +1 @@ +from . import zoo_animal \ No newline at end of file diff --git a/addons/zoo/models/zoo_animal.py b/addons/zoo/models/zoo_animal.py new file mode 100644 index 0000000..a3e2b08 --- /dev/null +++ b/addons/zoo/models/zoo_animal.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +from odoo import api, fields, models, tools, _ +from odoo.exceptions import UserError, ValidationError + +import datetime + +class ZooAnimal(models.Model): + _name = "zoo.animal" + _description = "Animal in the zoo" + + name = fields.Char('Animal Name', required=True) + description = fields.Text('Description') + dob = fields.Date('DOB', required=False) + gender = fields.Selection([ + ('male', 'Male'), + ('female', 'Female') + ], string='Gender', default='male', required=True) + feed_time = fields.Datetime('Feed Time', copy=False) + is_alive = fields.Boolean('Is Alive', default=True) + image = fields.Binary("Image", attachment=True, help="Animal Image") + weight = fields.Float('Weight (kg)') + weight_pound = fields.Float('Weight (pounds)') + introduction = fields.Text('Introduction (EN)') \ No newline at end of file diff --git a/addons/zoo/static/description/icon.png b/addons/zoo/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..1b45871e3f4d750c907934443afbdb69c28572fc GIT binary patch literal 5832 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 E0dTP^%>V!Z literal 0 HcmV?d00001 From 0611c1eb3cf000f881e3e5a734d47d4587ed8d67 Mon Sep 17 00:00:00 2001 From: mtpc4s9 Date: Wed, 19 Nov 2025 20:00:35 +0700 Subject: [PATCH 11/30] ok --- addons/zoo/__manifest__.py | 5 ++++ addons/zoo/models/__init__.py | 3 +- addons/zoo/models/zoo_animal.py | 49 ++++++++++++++++++++++++++++++- addons/zoo/models/zoo_creature.py | 17 +++++++++++ 4 files changed, 72 insertions(+), 2 deletions(-) create mode 100644 addons/zoo/models/zoo_creature.py diff --git a/addons/zoo/__manifest__.py b/addons/zoo/__manifest__.py index 4fdcfeb..d0824d2 100644 --- a/addons/zoo/__manifest__.py +++ b/addons/zoo/__manifest__.py @@ -19,4 +19,9 @@ 'installable': True, 'auto_install': False, 'application': True, + + # Depends declaration + 'depends': [ + 'product', + ], } \ No newline at end of file diff --git a/addons/zoo/models/__init__.py b/addons/zoo/models/__init__.py index b3a9fb6..f19462e 100644 --- a/addons/zoo/models/__init__.py +++ b/addons/zoo/models/__init__.py @@ -1 +1,2 @@ -from . import zoo_animal \ No newline at end of file +from . import zoo_animal +from . import zoo_creature \ No newline at end of file diff --git a/addons/zoo/models/zoo_animal.py b/addons/zoo/models/zoo_animal.py index a3e2b08..1d63eea 100644 --- a/addons/zoo/models/zoo_animal.py +++ b/addons/zoo/models/zoo_animal.py @@ -20,4 +20,51 @@ class ZooAnimal(models.Model): image = fields.Binary("Image", attachment=True, help="Animal Image") weight = fields.Float('Weight (kg)') weight_pound = fields.Float('Weight (pounds)') - introduction = fields.Text('Introduction (EN)') \ No newline at end of file + introduction = fields.Text('Introduction (EN)') + + # thêm vào cuối: + + age = fields.Integer('Pet Age', compute='_compute_age') + + # thêm các trường quan hệ sau: + mother_id = fields.Many2one(comodel_name='zoo.animal', string='Mother', ondelete='set null') # ondelete: 'set null', 'restrict', 'cascade' + mother_name = fields.Char('Mother Name', related='mother_id.name') + female_children_ids = fields.One2many(comodel_name='zoo.animal', inverse_name='mother_id', string='Female Children') + + toy_ids = fields.Many2many(comodel_name='product.product', + string="Toys", + relation='animal_product_toy_rel', + column1='col_animal_id', + column2='col_product_id') + + creature_id = fields.Many2one(comodel_name='zoo.creature', string='Creature') + + @api.depends('dob') + def _compute_age(self): + now = datetime.datetime.now() + current_year = now.year + for record in self: + dob = record.dob + if dob: + dob_year = dob.year + delta_year = current_year - dob_year + if delta_year < 0: + raise ValidationError(_("Negative age: current year < DOB year!")) + record.age = delta_year + else: + record.age = False + pass + + @api.constrains('dob') + def _check_dob(self): + for record in self: + if record.dob and record.dob.year < 1900: + raise ValidationError(_("Invalid DOB!")) + + @api.onchange('weight') + def _update_weight_pound(self): + self.weight_pound = self.weight * 2.204623 + + @api.onchange('weight_pound') + def _update_weight_kg(self): + self.weight = self.weight_pound / 2.204623 \ No newline at end of file diff --git a/addons/zoo/models/zoo_creature.py b/addons/zoo/models/zoo_creature.py new file mode 100644 index 0000000..65bdbe7 --- /dev/null +++ b/addons/zoo/models/zoo_creature.py @@ -0,0 +1,17 @@ +# -*- coding: utf-8 -*- +from odoo import api, fields, models, tools, _ +from odoo.exceptions import UserError, ValidationError + +class ZooCreature(models.Model): + _name = "zoo.creature" + _description = "Creature" + + name = fields.Char('Name', required=True) + environment = fields.Selection([ + ('water', 'Water'), + ('ground', 'Ground'), + ('sky', 'Sky'), + ], string='Environment', default='ground') + is_rare = fields.Boolean('Is Rare', default=False) + + animal_ids = fields.One2many(comodel_name='zoo.animal', inverse_name='creature_id', string='Animals') \ No newline at end of file From 63083705b26c73ec182130998e3120f56a20e1c3 Mon Sep 17 00:00:00 2001 From: mtpc4s9 Date: Wed, 19 Nov 2025 20:22:27 +0700 Subject: [PATCH 12/30] ok --- addons/zoo/__manifest__.py | 6 ++ addons/zoo/security/ir.model.access.csv | 3 + addons/zoo/views/zoo_animal_views.xml | 112 ++++++++++++++++++++++++ 3 files changed, 121 insertions(+) create mode 100644 addons/zoo/security/ir.model.access.csv create mode 100644 addons/zoo/views/zoo_animal_views.xml diff --git a/addons/zoo/__manifest__.py b/addons/zoo/__manifest__.py index d0824d2..08fbb52 100644 --- a/addons/zoo/__manifest__.py +++ b/addons/zoo/__manifest__.py @@ -24,4 +24,10 @@ 'depends': [ 'product', ], + + # Data files declaration + 'data': [ + 'security/ir.model.access.csv', + 'views/zoo_animal_views.xml', + ], } \ No newline at end of file diff --git a/addons/zoo/security/ir.model.access.csv b/addons/zoo/security/ir.model.access.csv new file mode 100644 index 0000000..9207661 --- /dev/null +++ b/addons/zoo/security/ir.model.access.csv @@ -0,0 +1,3 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_zoo_animal,access_zoo_animal,model_zoo_animal,base.group_user,1,1,1,1 +access_zoo_creature,access_zoo_creature,model_zoo_creature,base.group_user,1,1,1,1 \ No newline at end of file diff --git a/addons/zoo/views/zoo_animal_views.xml b/addons/zoo/views/zoo_animal_views.xml new file mode 100644 index 0000000..3b45458 --- /dev/null +++ b/addons/zoo/views/zoo_animal_views.xml @@ -0,0 +1,112 @@ + + + + + zoo.animal.form.view + zoo.animal + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ + + zoo.animal.list.view + zoo.animal + + + + + + + + + + + + + + + + Zoo Animal + ir.actions.act_window + zoo.animal + + + + + + + +
+
\ No newline at end of file From c0f50d8f8bc3d2582fc92bb2cbb378ae3272b8a9 Mon Sep 17 00:00:00 2001 From: mtpc4s9 Date: Wed, 19 Nov 2025 20:36:33 +0700 Subject: [PATCH 13/30] ok --- addons/zoo/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 164 bytes .../models/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 211 bytes .../__pycache__/zoo_animal.cpython-312.pyc | Bin 0 -> 4132 bytes .../__pycache__/zoo_creature.cpython-312.pyc | Bin 0 -> 1118 bytes 4 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 addons/zoo/__pycache__/__init__.cpython-312.pyc create mode 100644 addons/zoo/models/__pycache__/__init__.cpython-312.pyc create mode 100644 addons/zoo/models/__pycache__/zoo_animal.cpython-312.pyc create mode 100644 addons/zoo/models/__pycache__/zoo_creature.cpython-312.pyc diff --git a/addons/zoo/__pycache__/__init__.cpython-312.pyc b/addons/zoo/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e93f347d48a2fe4518de2c302b4df613d1c5eac3 GIT binary patch literal 164 zcmX@j%ge<80?TAFMS#>}Fb7I7LFvx|K*n^26owSW9EM!RC`LwxN+wO_myAGRO~zYn zx%nxnImLdOOt%<{n1Ny|89sw_{!-M>%`4GQttcr<)J;rD$$jEq)L8OQc$N>N~3?vr- literal 0 HcmV?d00001 diff --git a/addons/zoo/models/__pycache__/__init__.cpython-312.pyc b/addons/zoo/models/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..165872ca4d7c05e1713c484b3961a1ee263e06e6 GIT binary patch literal 211 zcmX@j%ge<81jYMhGmU}tV-N=hn4pZ$GC;<3h7^Vr#vF!R#wbQc5St0eW{P5BWT<4; zWO>O5RHDgvi>oR>KRz)pGdD2@$m0R=l8aIkOG=AU{WO_xF%&Ta)fKS-iIohWfh5B( z4gK7_68+SQlA=W2#FUi$ykdQzF8$p6l+>JJ{rLFIyv&mLc)fzkUmP|-!P1;myCP1Y aMv#TY+(6<3Gb1D8T?UDJ3{pkxKt2G_zB11M literal 0 HcmV?d00001 diff --git a/addons/zoo/models/__pycache__/zoo_animal.cpython-312.pyc b/addons/zoo/models/__pycache__/zoo_animal.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0ea30c4d77d54c43735b9e54a7bca36020809b7b GIT binary patch literal 4132 zcma)8TTC0-8J@9c#&;VqcQ6dO04Bt2$c=>TZW0m_nuKk;39Y=@oppQ;U}Dd(X9fZz zh@4f_g1Qw@se(KuQu{y@9`e|??t5QAW*c|3QX_4ps&Ax8U-qg0Ib$0qa;jSLng5*s zJOAaJ|8o8k2zWX8>3@!-#(?^PPKrOVK)k*K#5#vK#HYCoALlcUxFh3?J2OID$cS-~ zr#wem%DCdLj63dTb7$HU_c*vK91JTAA9o^0TySt$obs1%uxaE(!j|~VVb9_&hO4T8lb-Pf47duiD!7PT$XzDO z$8e1mWO9mNXhyZ zhOBhAZK!=qE=g=O@_rdn@{^kTh}my_WW%BU`;C z{T+ZiFg093>e1rqpx8t1Spg6~#PC1)pZLBqd?&+?R=|Hyl7FlW-~C>Ee+hrQ3?H38 z5j|;n;+l3rO=S{k(`#y4EMe2t_L`hhWn&V{z%hM=rO`wN-;DB>o8YfzQUoK*cM0oB zlA5NeY&kD|a&Z_kT>z2T5^lf$ z!*(kv6r)%wnBa86fCKfESZ2sRFnMS)l|}@sQ74H|q5hOQi;0f+^_Zb)+k;r)YY8{C zdEKhFuT&|lDuy<%fFdi9)Y3|UmqJ#MPK%fnii%86!2@O(y3TI3h_ zsY1mq=Px=IxJ%sUBOJHrTyRcNeee7hg$051F9;QPiwlkg(S)|TC@n~czYG0@)Eb_m z2*X#TkfWGe#qZbrg0$dNN*cczLSRAJ{F=bcb5UWG&?aSej^YXEfwNeK;5sWOX9!%f zAjW$a4P(*1rh0?*!Xl1P|^659Wf0mz?>A=JmO?xg~$T zzWLvr$8&ILIA7Da-m})TH1xMnO}?e=@xY^jRd+rT-MqRJIkD=^ha*q;-+lCbb9Ad? zyZ2_U=T@$HY`b~%XtE?K{r=91b+pbb&iG0Ik<2dP!#;m zPv^g>s?3=xJT}TV*dYUZdW_;*j5CT)8hCLPgQfWWnrA`b98IMGW%@_dS^7Al_uml} z>`RV;g8iF@{Gv^l^uwT23uKv`gpcJ_l9M=jSAn}VYs+t=xJo;wej0`>_mUpB!*d3X zJ5;w~{>I!Ge?0YQ>aq4ndoJYKPJCZ~_>YOrV6O9Yu6|&5umt&H!YO^~knik%B)gvKs?f=q)uI;&@vHwiTls$WXg$pF)@smaNN z3ii!G#K6W{a0yHx|(k$fn!G`n(t`ToY#^FzC# z)7h(ef78rR-LH2`22j zw|(;RZp|=w*c{#HeBAe_@A<;^&p+QDzqi{ww=Fch47M$ezX-PN1lzWIKg@R>%||cf zyHDr42i|yu(An&jJwF#d0B6;=*0*{8+o|1}pJlJT6sxkI{`#{ApRLyA#D-UnfEak~ zR0HhW4{on^=fsv*4qiM?*{yq& z0*6ZMSWfIHu@5lHzH)loQNJZ3vw%>ax01G9U`U3DfD zP;pdeX{<0@VPR=yWn!ZVMly{i7RHVUHdM~+atDQz?3?d<@6EUG&CjQ7HVxQ#_o3*_ z2mt)#q%-6rux~QZ0tg`J0uP$d6HLJqP0^D~$&*bP@|fT%o@%O|W@-=!UAi{@dAY1kjhaIunAg*KvNGxOeP5l2+cjR zT?g5b6Zo;Cax4x&xAOPQ+X5Jv5CKy_&=iqiN&>+0LgwUx1S1hiZF!sR10SXu=k+G+ zq@4puc@2?@w05f7Nh;1hbuur(D2?=XrmL#Qd1wBUmqk4&*Y52qW@~w)Ky@<+CJ45p zD#7(kJqSvbBSy83pGwoVhaVV_Y6LG;9fFY|vi*{u+Yu&Ie#|Gvl{pereMFV1cxE0k zd{(343^V$qzwD5}_pl$4JS&gqhY@l7IjSN&YggT@7o05Fd#Y2a_VVbknKC3 z?NYr{nB^dPa2zZA1JGe9@c;k- literal 0 HcmV?d00001 From 6accf394c9cbf0099e6a215299b713a33fccc42c Mon Sep 17 00:00:00 2001 From: mtpc4s9 Date: Wed, 19 Nov 2025 20:54:45 +0700 Subject: [PATCH 14/30] =?UTF-8?q?T=E1=BA=A1o=20th=C3=AAm=20m=E1=BB=99t=20s?= =?UTF-8?q?=E1=BB=91=20tr=C6=B0=E1=BB=9Dng=20thu=E1=BB=99c=20t=C3=ADnh=20c?= =?UTF-8?q?ho=20th=C3=BA=20nu=C3=B4i=20trong=20s=E1=BB=9F=20th=C3=BA:=20-?= =?UTF-8?q?=20Nickname:=20Char=20-=20Gi=E1=BB=9Bi=20thi=E1=BB=87u=20th?= =?UTF-8?q?=C3=B4ng=20tin=20(ti=E1=BA=BFng=20Vi=E1=BB=87t):=20Text=20d?= =?UTF-8?q?=C3=B9ng=20html=20-=20Th=C3=BA=20c=C3=B3=20t=E1=BB=ABng=20?= =?UTF-8?q?=C4=91=C6=B0=E1=BB=A3c=20mua=20v=E1=BB=81=20hay=20kh=C3=B4ng=3F?= =?UTF-8?q?:=20Boolean=20-=20Gi=C3=A1=20mua=20n=E1=BA=BFu=20t=E1=BB=ABng?= =?UTF-8?q?=20=C4=91=C6=B0=E1=BB=A3c=20mua=20v=E1=BB=81:=20Float=20-=20Cha?= =?UTF-8?q?=20c=E1=BB=A7a=20th=C3=BA=20nu=C3=B4i:=20Many2one=20-=20Con=20c?= =?UTF-8?q?=E1=BB=A7a=20th=C3=BA=20nu=C3=B4i=20(n=E1=BA=BFu=20l=C3=A0=20gi?= =?UTF-8?q?=E1=BB=9Bi=20t=C3=ADnh=20=C4=91=E1=BB=B1c):=20One2many=20(male?= =?UTF-8?q?=5Fchildren=5Fids)=20-=20T=C3=ADnh=20to=C3=A1n=20t=E1=BB=B1=20?= =?UTF-8?q?=C4=91=E1=BB=99ng=20s=E1=BB=91=20con=20(number=20of=20children)?= =?UTF-8?q?=20c=E1=BB=A7a=20th=C3=BA=20nu=C3=B4i:=20s=E1=BB=AD=20d?= =?UTF-8?q?=E1=BB=A5ng=20computed=20field=20-=20B=C3=A1c=20s=C4=A9=20ph?= =?UTF-8?q?=E1=BB=A5=20tr=C3=A1ch=20ch=C4=83m=20s=C3=B3c:=20link=20Many2on?= =?UTF-8?q?e=20t=E1=BB=9Bi=20model=20res.partner?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- addons/zoo/models/zoo_animal.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/addons/zoo/models/zoo_animal.py b/addons/zoo/models/zoo_animal.py index 1d63eea..a5c9b24 100644 --- a/addons/zoo/models/zoo_animal.py +++ b/addons/zoo/models/zoo_animal.py @@ -21,10 +21,18 @@ class ZooAnimal(models.Model): weight = fields.Float('Weight (kg)') weight_pound = fields.Float('Weight (pounds)') introduction = fields.Text('Introduction (EN)') + nickname = fields.Char('Nickname') + introduction_vn = fields.Html('Introduction (VI)') + is_purchased = fields.Boolean('Has Been Purchased', default=False) + purchase_price = fields.Float('Purchase Price') + parent_id = fields.Many2one(comodel_name='zoo.animal', string='Parent', ondelete='set null') + male_children_ids = fields.One2many(comodel_name='zoo.animal', inverse_name='parent_id', string='Children') + veterinarian_id = fields.Many2one(comodel_name='res.partner', string='Veterinarian') # thêm vào cuối: age = fields.Integer('Pet Age', compute='_compute_age') + number_of_children = fields.Integer('Number of Children', compute='_compute_number_of_children') # thêm các trường quan hệ sau: mother_id = fields.Many2one(comodel_name='zoo.animal', string='Mother', ondelete='set null') # ondelete: 'set null', 'restrict', 'cascade' @@ -55,6 +63,11 @@ class ZooAnimal(models.Model): record.age = False pass + @api.depends('male_children_ids') + def _compute_number_of_children(self): + for record in self: + record.number_of_children = len(record.male_children_ids) + @api.constrains('dob') def _check_dob(self): for record in self: From 4374256c5cd512c9f9367d898021d760c6740e24 Mon Sep 17 00:00:00 2001 From: mtpc4s9 Date: Wed, 19 Nov 2025 21:10:16 +0700 Subject: [PATCH 15/30] Cap nhat views --- .../__pycache__/zoo_animal.cpython-312.pyc | Bin 4132 -> 5213 bytes .../__pycache__/zoo_creature.cpython-312.pyc | Bin 1118 -> 1118 bytes addons/zoo/models/zoo_animal.py | 6 ++-- addons/zoo/views/zoo_animal_views.xml | 32 ++++++++++++++---- 4 files changed, 29 insertions(+), 9 deletions(-) diff --git a/addons/zoo/models/__pycache__/zoo_animal.cpython-312.pyc b/addons/zoo/models/__pycache__/zoo_animal.cpython-312.pyc index 0ea30c4d77d54c43735b9e54a7bca36020809b7b..c7af4df628b41a3564c29e8e8237bb0f139f5e30 100644 GIT binary patch delta 1893 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 Tx}%`yp7VjH?D@&jr8VLYR}0%U diff --git a/addons/zoo/models/__pycache__/zoo_creature.cpython-312.pyc b/addons/zoo/models/__pycache__/zoo_creature.cpython-312.pyc index f9516ac31f7c778258a517b561cd7237bba7a02c..2f0e94299a6a8731af48c648f9abade0d0fa4b86 100644 GIT binary patch delta 19 Zcmcb|agT%RG%qg~0}z})zL6`01pqn;1#bWV delta 19 Zcmcb|agT%RG%qg~0}yOEw2>=>1pqlt1y29~ diff --git a/addons/zoo/models/zoo_animal.py b/addons/zoo/models/zoo_animal.py index a5c9b24..6eeed05 100644 --- a/addons/zoo/models/zoo_animal.py +++ b/addons/zoo/models/zoo_animal.py @@ -25,8 +25,6 @@ class ZooAnimal(models.Model): introduction_vn = fields.Html('Introduction (VI)') is_purchased = fields.Boolean('Has Been Purchased', default=False) purchase_price = fields.Float('Purchase Price') - parent_id = fields.Many2one(comodel_name='zoo.animal', string='Parent', ondelete='set null') - male_children_ids = fields.One2many(comodel_name='zoo.animal', inverse_name='parent_id', string='Children') veterinarian_id = fields.Many2one(comodel_name='res.partner', string='Veterinarian') # thêm vào cuối: @@ -38,6 +36,10 @@ class ZooAnimal(models.Model): mother_id = fields.Many2one(comodel_name='zoo.animal', string='Mother', ondelete='set null') # ondelete: 'set null', 'restrict', 'cascade' mother_name = fields.Char('Mother Name', related='mother_id.name') female_children_ids = fields.One2many(comodel_name='zoo.animal', inverse_name='mother_id', string='Female Children') + father_id = fields.Many2one(comodel_name='zoo.animal', string='Father', ondelete='set null') + father_name = fields.Char('Father Name', related='father_id.name') + male_children_ids = fields.One2many(comodel_name='zoo.animal', inverse_name='father_id', string='Male Children') + toy_ids = fields.Many2many(comodel_name='product.product', string="Toys", diff --git a/addons/zoo/views/zoo_animal_views.xml b/addons/zoo/views/zoo_animal_views.xml index 3b45458..a6a37ed 100644 --- a/addons/zoo/views/zoo_animal_views.xml +++ b/addons/zoo/views/zoo_animal_views.xml @@ -23,11 +23,17 @@ + + + + + + @@ -38,6 +44,10 @@