add tests for caldav_sync, new module preamble_on_quotation
This commit is contained in:
parent
a0e5d8664d
commit
a76182dcd4
12 changed files with 3524 additions and 0 deletions
3312
caldav_sync/tests/data/Calendar.ics
Normal file
3312
caldav_sync/tests/data/Calendar.ics
Normal file
File diff suppressed because it is too large
Load diff
45
caldav_sync/tests/data/Mail Attachment.ics
Normal file
45
caldav_sync/tests/data/Mail Attachment.ics
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
BEGIN:VCALENDAR
|
||||||
|
PRODID:-//Apple Inc.//macOS 15.3.2//EN
|
||||||
|
VERSION:2.0
|
||||||
|
METHOD:REQUEST
|
||||||
|
CALSCALE:GREGORIAN
|
||||||
|
BEGIN:VTIMEZONE
|
||||||
|
TZID:America/Toronto
|
||||||
|
BEGIN:DAYLIGHT
|
||||||
|
DTSTART:20070311T020000
|
||||||
|
RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU
|
||||||
|
TZNAME:EDT
|
||||||
|
TZOFFSETFROM:-0500
|
||||||
|
TZOFFSETTO:-0400
|
||||||
|
END:DAYLIGHT
|
||||||
|
BEGIN:STANDARD
|
||||||
|
DTSTART:20071104T020000
|
||||||
|
RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU
|
||||||
|
TZNAME:EST
|
||||||
|
TZOFFSETFROM:-0400
|
||||||
|
TZOFFSETTO:-0500
|
||||||
|
END:STANDARD
|
||||||
|
END:VTIMEZONE
|
||||||
|
BEGIN:VEVENT
|
||||||
|
CREATED:20250410T122458Z
|
||||||
|
DTEND;TZID=America/Toronto:20250414T140000
|
||||||
|
DTSTAMP:20250410T122459Z
|
||||||
|
DTSTART;TZID=America/Toronto:20250414T131500
|
||||||
|
LAST-MODIFIED:20250410T122458Z
|
||||||
|
SEQUENCE:0
|
||||||
|
SUMMARY:Test
|
||||||
|
TRANSP:OPAQUE
|
||||||
|
UID:02EEF1D6-F3D2-4EB2-AD7A-1C381A629DC5
|
||||||
|
X-APPLE-CREATOR-IDENTITY:com.apple.calendar
|
||||||
|
X-APPLE-CREATOR-TEAM-IDENTITY:0000000000
|
||||||
|
BEGIN:VALARM
|
||||||
|
ACTION:NONE
|
||||||
|
TRIGGER;VALUE=DATE-TIME:19760401T005545Z
|
||||||
|
END:VALARM
|
||||||
|
ATTENDEE;PARTSTAT=NEEDS-ACTION;EMAIL=mdurepos@durpro.com;CN=Marc Durepos;CU
|
||||||
|
TYPE=INDIVIDUAL;RSVP=TRUE:mailto:mdurepos@durpro.com
|
||||||
|
ORGANIZER;CN=Marc Durepos;EMAIL=deploy@bemade.org:mailto:marc@bemade.org
|
||||||
|
CLASS:PUBLIC
|
||||||
|
END:VEVENT
|
||||||
|
END:VCALENDAR
|
||||||
|
|
||||||
14
caldav_sync/tests/data/test_external_no_organizer.ics
Normal file
14
caldav_sync/tests/data/test_external_no_organizer.ics
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
BEGIN:VCALENDAR
|
||||||
|
VERSION:2.0
|
||||||
|
PRODID:-//Odoo//CalDAV Client//EN
|
||||||
|
BEGIN:VEVENT
|
||||||
|
UID:external-organizer-test-123
|
||||||
|
DTSTART:20250207T143000Z
|
||||||
|
DTEND:20250207T153000Z
|
||||||
|
DTSTAMP:20250207T143000Z
|
||||||
|
ATTENDEE;PARTSTAT=ACCEPTED;CN=Test User:mailto:test@example.com
|
||||||
|
ATTENDEE;PARTSTAT=ACCEPTED;CN=Mister External:mailto:mister.external@otherdomain.com
|
||||||
|
SUMMARY:Meeting with External Organizer
|
||||||
|
DESCRIPTION:This is a test event with an external organizer
|
||||||
|
END:VEVENT
|
||||||
|
END:VCALENDAR
|
||||||
|
|
@ -53,3 +53,29 @@ class TestExternalOrganizer(TransactionCase, CaldavTestCommon):
|
||||||
external_attendee,
|
external_attendee,
|
||||||
"External organizer should be present in attendees list",
|
"External organizer should be present in attendees list",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_no_organizer_external_event_sync(self):
|
||||||
|
"""Test that events without organizers are assigned to the calendar's user."""
|
||||||
|
# Setup mock for CalDAV client with our test ICS file
|
||||||
|
with _patch_caldav_with_events_from_ics(
|
||||||
|
[_get_ics_path("test_external_no_organizer.ics")], self.user
|
||||||
|
):
|
||||||
|
self.user._compute_is_caldav_enabled()
|
||||||
|
# Make sure that the current user is not the admin user
|
||||||
|
self.assertNotEqual(self.user.id, self.env.ref("base.user_admin").id)
|
||||||
|
self.env["calendar.event"].poll_caldav_server()
|
||||||
|
|
||||||
|
# Find the synced event
|
||||||
|
event = self.env["calendar.event"].search(
|
||||||
|
[("caldav_uid", "=", "external-organizer-test-123")]
|
||||||
|
)
|
||||||
|
|
||||||
|
# Verify event was created
|
||||||
|
self.assertTrue(event, "Event should be created")
|
||||||
|
|
||||||
|
# Verify user_id is set to the calendar's user
|
||||||
|
self.assertEqual(
|
||||||
|
event.user_id,
|
||||||
|
self.user,
|
||||||
|
"Event without organizer should have user_id set to calendar's user",
|
||||||
|
)
|
||||||
|
|
|
||||||
1
preamble_on_quotation/__init__.py
Normal file
1
preamble_on_quotation/__init__.py
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
from . import models
|
||||||
44
preamble_on_quotation/__manifest__.py
Normal file
44
preamble_on_quotation/__manifest__.py
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
# Bemade Inc.
|
||||||
|
#
|
||||||
|
# Copyright (C) 2025-April Bemade Inc. (<https://www.bemade.org>).
|
||||||
|
# Author: Marc Durepos (Contact : mdurepos@durpro.com)
|
||||||
|
#
|
||||||
|
# This program is under the terms of the GNU Lesser General Public License (LGPL-3)
|
||||||
|
# For details, visit https://www.gnu.org/licenses/lgpl-3.0.en.html
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "Quotation PDF Preamble",
|
||||||
|
"version": "18.0.0.1.0",
|
||||||
|
"license": "LGPL-3",
|
||||||
|
"category": "Sales",
|
||||||
|
"summary": "Add customizable HTML preamble to quotation PDFs",
|
||||||
|
"author": "Bemade Inc.",
|
||||||
|
"website": "https://www.bemade.org",
|
||||||
|
"depends": ["base", "sale"],
|
||||||
|
"data": [
|
||||||
|
"views/sale_order_views.xml",
|
||||||
|
"report/sale_report_templates.xml",
|
||||||
|
"views/res_company_views.xml",
|
||||||
|
],
|
||||||
|
"description": """
|
||||||
|
Quotation PDF Preamble
|
||||||
|
======================
|
||||||
|
|
||||||
|
This module enhances the standard quotation PDF reports by allowing users to add a
|
||||||
|
customizable HTML preamble at the beginning of the document. The preamble appears
|
||||||
|
before the quotation details, similar to how the terms and conditions appear after.
|
||||||
|
|
||||||
|
Features:
|
||||||
|
---------
|
||||||
|
* Add a configurable HTML preamble field to sales orders
|
||||||
|
* Display the preamble at the top of quotation PDF reports
|
||||||
|
* Company-specific default preambles that can be overridden per quotation
|
||||||
|
* Uses Odoo's standard HTML field type for content editing
|
||||||
|
|
||||||
|
This module is ideal for businesses that need to include standard disclaimers,
|
||||||
|
terms and conditions, or promotional content at the beginning of their quotations.
|
||||||
|
""",
|
||||||
|
"installable": True,
|
||||||
|
"application": False,
|
||||||
|
"auto_install": False,
|
||||||
|
}
|
||||||
2
preamble_on_quotation/models/__init__.py
Normal file
2
preamble_on_quotation/models/__init__.py
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
from . import sale_order
|
||||||
|
from . import res_company
|
||||||
12
preamble_on_quotation/models/res_company.py
Normal file
12
preamble_on_quotation/models/res_company.py
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
from odoo import fields, models
|
||||||
|
|
||||||
|
|
||||||
|
class ResCompany(models.Model):
|
||||||
|
_inherit = "res.company"
|
||||||
|
|
||||||
|
default_quotation_preamble = fields.Html(
|
||||||
|
string="Default Quotation Preamble",
|
||||||
|
help="Default HTML content to display at the beginning of quotation PDFs",
|
||||||
|
sanitize=True,
|
||||||
|
sanitize_tags=True,
|
||||||
|
)
|
||||||
21
preamble_on_quotation/models/sale_order.py
Normal file
21
preamble_on_quotation/models/sale_order.py
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
from odoo import api, fields, models
|
||||||
|
|
||||||
|
|
||||||
|
class SaleOrder(models.Model):
|
||||||
|
_inherit = "sale.order"
|
||||||
|
|
||||||
|
preamble = fields.Html(
|
||||||
|
string="Quotation Preamble",
|
||||||
|
help="HTML content to display at the beginning of the quotation PDF",
|
||||||
|
sanitize=True,
|
||||||
|
sanitize_tags=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
@api.model_create_multi
|
||||||
|
def create(self, vals_list):
|
||||||
|
"""Set default preamble from company settings when creating a new sale order."""
|
||||||
|
record = super().create(vals_list)
|
||||||
|
for record in self:
|
||||||
|
if not record.preamble and record.company_id.default_quotation_preamble:
|
||||||
|
record.preamble = record.company_id.default_quotation_preamble
|
||||||
|
return record
|
||||||
15
preamble_on_quotation/report/sale_report_templates.xml
Normal file
15
preamble_on_quotation/report/sale_report_templates.xml
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<odoo>
|
||||||
|
<!-- This template adds the preamble as a cover page before the main document -->
|
||||||
|
<template id="report_saleorder_document_preamble" inherit_id="sale.report_saleorder_document">
|
||||||
|
<xpath expr="//t[@t-call='web.external_layout']" position="before">
|
||||||
|
<t t-if="doc.preamble and doc.state in ['draft', 'sent']">
|
||||||
|
<div class="article" style="page-break-after: always;">
|
||||||
|
<div class="mt-4 mb-4">
|
||||||
|
<span t-field="doc.preamble"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</t>
|
||||||
|
</xpath>
|
||||||
|
</template>
|
||||||
|
</odoo>
|
||||||
17
preamble_on_quotation/views/res_company_views.xml
Normal file
17
preamble_on_quotation/views/res_company_views.xml
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<odoo>
|
||||||
|
<record id="view_company_form_inherit_preamble" model="ir.ui.view">
|
||||||
|
<field name="name">res.company.form.inherit.preamble</field>
|
||||||
|
<field name="model">res.company</field>
|
||||||
|
<field name="inherit_id" ref="base.view_company_form"/>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<xpath expr="//notebook" position="inside">
|
||||||
|
<page string="Quotation Preamble" name="quotation_preamble">
|
||||||
|
<group>
|
||||||
|
<field name="default_quotation_preamble" nolabel="1" placeholder="Set a default HTML preamble for all quotations..."/>
|
||||||
|
</group>
|
||||||
|
</page>
|
||||||
|
</xpath>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
</odoo>
|
||||||
15
preamble_on_quotation/views/sale_order_views.xml
Normal file
15
preamble_on_quotation/views/sale_order_views.xml
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<odoo>
|
||||||
|
<record id="view_order_form_inherit_preamble" model="ir.ui.view">
|
||||||
|
<field name="name">sale.order.form.inherit.preamble</field>
|
||||||
|
<field name="model">sale.order</field>
|
||||||
|
<field name="inherit_id" ref="sale.view_order_form"/>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<xpath expr="//page[@name='other_information']" position="after">
|
||||||
|
<page string="Quotation Preamble" name="quotation_preamble">
|
||||||
|
<field name="preamble" nolabel="1" placeholder="Add an HTML preamble to be displayed at the top of the quotation PDF..."/>
|
||||||
|
</page>
|
||||||
|
</xpath>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
</odoo>
|
||||||
Loading…
Reference in a new issue