from odoo import fields, models, api class Textbook(models.Model): _name = 'yuthon.school.textbook' _description = '教材' _order = 'category_id, sequence, name' name = fields.Char( string='教材名称', required=True, help='如:Odoo 18 基础入门、Odoo 18 视图开发实战', ) sequence = fields.Integer( string='排序', default=10, ) category_id = fields.Many2one( 'yuthon.school.category', string='学习分类', ondelete='restrict', help='该教材所属的学习分类', ) description = fields.Text( string='教材简介', help='教材的内容概要和适用人群', ) difficulty = fields.Selection( [('beginner', '入门'), ('intermediate', '进阶'), ('advanced', '高级')], string='难度等级', default='beginner', ) state = fields.Selection( [('draft', '草稿'), ('published', '已发布')], string='状态', default='draft', ) total_hours = fields.Float( string='总学时', compute='_compute_total_hours', store=True, help='自动统计各章学时之和', ) total_chapters = fields.Integer( string='章节数', compute='_compute_total_chapters', store=True, ) total_videos = fields.Integer( string='视频数', compute='_compute_total_videos', store=True, ) chapter_ids = fields.One2many( 'yuthon.school.chapter', 'textbook_id', string='章节', ) active = fields.Boolean( string='启用', default=True, ) @api.depends('chapter_ids.hours') def _compute_total_hours(self): for record in self: record.total_hours = sum(record.chapter_ids.mapped('hours')) @api.depends('chapter_ids') def _compute_total_chapters(self): for record in self: record.total_chapters = len(record.chapter_ids) @api.depends('chapter_ids.video_ids') def _compute_total_videos(self): for record in self: record.total_videos = sum(len(ch.video_ids) for ch in record.chapter_ids) def action_confirm(self): """发布教材:将状态从草稿改为已发布""" self.write({'state': 'published'}) def action_set_draft(self): """退回草稿:将状态从已发布改回草稿""" self.write({'state': 'draft'}) class Chapter(models.Model): _name = 'yuthon.school.chapter' _description = '章节' _order = 'textbook_id, sequence, name' _sql_constraints = [ ('unique_chapter_seq', 'unique(textbook_id, sequence)', '同一教材下章节序号不能重复!'), ] name = fields.Char( string='章节标题', required=True, ) sequence = fields.Integer( string='排序', default=10, ) textbook_id = fields.Many2one( 'yuthon.school.textbook', string='所属教材', required=True, ondelete='cascade', ) summary = fields.Text( string='内容概述', help='本章涵盖的内容概述', ) key_points = fields.Text( string='知识要点', help='本章需要掌握的关键知识点', ) hours = fields.Float( string='学时', default=1.0, help='本章预计学习时长(小时)', ) video_ids = fields.One2many( 'yuthon.school.video', 'chapter_id', string='视频', ) video_count = fields.Integer( string='视频数', compute='_compute_video_count', store=True, ) @api.depends('video_ids') def _compute_video_count(self): for record in self: record.video_count = len(record.video_ids) @api.onchange('video_ids') def _onchange_video_ids(self): """当视频列表变化时,自动建议学时(每个视频按 0.5 学时计算)""" if self.video_ids: suggested = max(1.0, len(self.video_ids) * 0.5) self.hours = suggested