如何在 Odoo 16 网站中创建自定义日历

Odoo 是一款 ERP 软件,包含各种业务管理工具,如 CRM、网站和电子商务、发票、会计、制造、仓库管理、项目管理、销售管理、采购管理、人力资源管理和库存管理。

在这篇博客中,我们可以看到Odoo 16如何在网站上创建自定义日历。为了便于说明,我创建了一个示例模型,用于定义在网站上创建日历视图的字段。 

下面,我创建了一个 test.model 并在 python 文件中定义了它的字段,

# -*- coding: utf-8 -*-
from odoo import fields, models
class TestModel(models.Model):
	"""Test model for defining fields required for calendar view"""
	_name = 'test.model'
	name = fields.Char(string='Event Name', required=True,
                   	help="Your test model record name")
	start_date = fields.Datetime(string='Start Date', required=True,
                             	help="Start date of the test model record")
	end_date = fields.Datetime(string='End Date', required=True,
                           	help="End date of the test model record")
	description = fields.Text(string='Description',
                          	help="Description of the test model record")

测试模型的安全性在 ir.model.access.csv 中定义如下, 

id,name,model_id/id,group_id/id,perm_read,perm_write,perm_create,perm_unlink
access_test_model,test.model,model_test_model,,1,1,1,1

现在我已经定义了测试模型的表单视图、窗口操作和测试模型的菜单项,如下所示, 

<?xml version="1.0" encoding="utf-8"?>
<odoo>
	<!-- Test Model Form View   -->
	<record id="view_test_model_form" model="ir.ui.view">
    	<field name="name">test.model.view.form</field>
    	<field name="model">test.model</field>
    	<field name="arch" type="xml">
        	<form string="Test">
            	<sheet>
                	<group>
                    	<group>
                        	<field name="name"/>
                        	<field name="start_date"/>
                        	<field name="end_date"/>
                        	<field name="description"/>
                    	</group>
                	</group>
            	</sheet>
        	</form>
    	</field>
	</record>
     <!-- Test Model Tree View   -->
     <record id="view_test_model_tree" model="ir.ui.view">
    	<field name="name">test.model.view.tree</field>
    	<field name="model">test.model</field>
    	<field name="arch" type="xml">
        	<tree>
            	<field name="name"/>
            	<field name="start_date"/>
            	<field name="end_date"/>
        	</tree>
    	</field>
	</record>
      <record id="test_model_calendar_action"
        	model="ir.actions.act_window">
    	<field name="name">Test Model Action</field>
    	<field name="res_model">test.model</field>
    	<field name="view_mode">tree,form</field>
	</record>
	<menuitem id="test_model_calendar_menu_action" name="Test model"
          	parent="website.menu_website_global_configuration" sequence="12"
          	action="test_model_calendar_action"/>
</odoo>

由于我们已将“website.menu_website_global_configuration”设置为父菜单,因此测试模型菜单项属于网站全局配置菜单,如下所示。

如何在 odoo-16-website-1-cybrosys 中创建自定义日历

接下来是创建如下所示的测试记录。填写开始和结束日期,并添加模型的其他必填字段。

如何在 odoo-16-website-2-cybrosys 中创建自定义日历

现在,定义日历模板。为此,我创建了日历模板,并使用 t-call 将该模板调用到另一个模板中,该模板使用控制器路由呈现,我目前已将其添加为菜单 URL。

<?xml version="1.0" encoding="utf-8"?>
<odoo>
	<template id="website_test_model_calendar_template">
    	<section class="test_model_calendar_main_class">
        	<div class="container">
            	<div class="row">
                	<div class="col-lg-5">
                    	<h4>Test Model Calendar</h4>
                    	<div class="test_model_calendar"/>
                	</div>
            	</div>
        	</div>
    	</section>
	</template>
	<template id="global_events_calendar" name="Global Calendar Events">
    	<t t-call="website.layout">
        	<div class="oe_structure oe_empty">
            	<t t-call="test_model_calendar.website_test_model_calendar_template"/>
        	</div>
    	</t>
	</template>
</odoo>

从网站菜单和 rpc 调用访问的 http 控制器在 Python 文件中定义如下,

from datetime import timedelta
from odoo import http
from odoo.fields import Date
from odoo.http import request
class WebsiteCalendar(http.Controller):
	@http.route('/test-model/calendar', type='json', website=True, auth='public')
	def test_model_website_calendar(self,  start, end):
    	"""Day with events"""
    	events = request.env["test.model"].search([
        	"|",
        	("start_date", "<=", end),
        	("end_date", ">=", start),
    	])
    	days = set()
    	one_day = timedelta(days=1)
    	start = Date.from_string(start)
    	end = Date.from_string(end)
    	for event in events:
        	now = max(Date.from_string(event.start_date), start)
        	event_end = min(Date.from_string(event.end_date), end)
        	while now <= event_end:
            	days.add(now)
            	now += one_day
    	return [Date.to_string(day) for day in days]
	@http.route(['/test_model_calendar_menu'], type='http', auth="user",
            	website=True)
	def global_calendar_events(self):
    	"""Url for Test model calendar menu"""
    	return request.render(
        	"test_model_calendar.global_events_calendar")

在static文件夹中创建了用于扩展网站动画类的JS文件。 

odoo.define('test_model_calendar.calendar', function (require) {
	"use strict";
	var animation = require('website.content.snippets.animation');
	var core = require("web.core");
	var time = require("web.time");
	var ajax = require("web.ajax");
	var DATE_FORMAT = time.strftime_to_moment_format("%Y-%m-%d");
	var DATETIME_FORMAT = time.strftime_to_moment_format(
    	"%Y-%m-%d %H:%M:%S");
	var INVERSE_FORMAT = "L";
	var CalendarList = animation.Class.extend({
    	selector: ".test_model_calendar_main_class",
    	init: function () {
        	this.datepicker_options = {
            	inline: true,
            	minDate: moment().subtract(100, "years"),
            	maxDate: moment().add(100, "years"),
            	icons: {
                	previous: "fa fa-chevron-left",
                	next: "fa fa-chevron-right",
            	},
            	format: DATE_FORMAT,
            	useCurrent: false,
            	locale: moment.locale(),
        	};
        	return this._super.apply(this, arguments);
    	},
    	start: function (editable_mode) {
        	this._super.apply(this, arguments);
        	if (editable_mode) {
            	return;
        	}
        	this._dates = {
            	min: null,
            	max: null,
            	matches: [],
        	};
        	this.$calendar = this.$target.find('.test_model_calendar')
            	.on("change.datetimepicker", $.proxy(this, "day_selected"))
            	.on("update.datetimepicker", $.proxy(this, "calendar_moved"));
        	this.preload_dates(moment())
            	.then($.proxy(this, "render_calendar"));
    	},
    	calendar_moved: function (event) {
        	if (event.change !== "M") {
            	return;
        	}
        	this.preload_dates(event.viewDate);
    	},
    	preload_dates: function (when) {
        	var margin = moment.duration(4, "months");
        	if (
            	this._dates.min && this._dates.max &&
            	this._dates.min <= when - margin &&
            	this._dates.max >= when + margin
        	) {
            	return $.Deferred().resolve();
        	}
        	margin.add(2, "months");
        	var start = moment(when - margin),
            	end = moment(when + margin);
        	if (this._dates.min) {
            	start.subtract(6, "months");
        	}
        	if (this._dates.max) {
            	end.add(6, "months");
        	}
        	return this.load_dates(start, end);
    	},
    	load_dates: function (start, end) {
        	return ajax.rpc(
            	"/test-model/calendar",
            	{
                	start: start.format(DATE_FORMAT),
                	end: end.format(DATE_FORMAT),
            	}
        	).then($.proxy(this, "_update_dates_cache", start, end));
    	},
    	_update_dates_cache: function (start, end, dates) {
        	if (!this._dates.min || this._dates.min > start) {
            	this._dates.min = start;
        	}
        	if (!this._dates.max || this._dates.max < end) {
            	this._dates.max = end;
        	}
        	this._dates.matches = _.union(this._dates.matches, dates);
    	},
    	render_calendar: function () {
        	var enabledDates = _.map(this._dates.matches, function (ndate) {
            	return moment(ndate, DATE_FORMAT);
        	});
        	this.$calendar.empty().datetimepicker(_.extend({},
            	this.datepicker_options, {'enabledDates': enabledDates}));
    	},
	});
	animation.registry.test_model_calendar = CalendarList;
	return {
    	DATE_FORMAT: DATE_FORMAT,
    	DATETIME_FORMAT: DATETIME_FORMAT,
    	INVERSE_FORMAT: INVERSE_FORMAT,
	};
});

将“/test_model_calendar_menu”链接到网站菜单后的最终结果,

如何在 odoo-16-website-3-cybrosys 中创建自定义日历

以上,我们讨论了一种示例方法,用于解释如何在 Odoo 16 网站上为任何模型创建自定义日历。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

奔跑的蜗牛..

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值