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 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