[WIP] Commit before rebase on latest #109 for user and view updates

Migration of printer_tray to v11 and integration with base_report_to_printer
This commit is contained in:
Graeme Gellatly
2017-10-06 01:16:33 +13:00
parent 4dcf26232d
commit d6500e4bfe
34 changed files with 383 additions and 622 deletions

View File

@@ -1,87 +0,0 @@
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
========================================
Report to printer - Paper tray selection
========================================
Extends the module **Report to printer** (``base_report_to_printer``)
to add the printers trays.
It detects trays on printers installation plus permits to select the
paper source on which you want to print directly.
You will find this option on default user config, on default report
config and on specific config per user per report.
This allows you to dedicate a specific paper source for example for
preprinted paper such as payment slip.
Installation
============
Considering that you already use the module **Report to printer**, you
just have to install this extension.
Configuration
=============
To configure this module, you need to:
* Update the CUPS printers in *Settings > Printing > Update Printers
from CUPS*
* If you want to print a report on a specific tray, you can change
their "Paper Source" in *Settings > Printing > Reports*
* If you want to print a report on a specific tray for a user, you can
change their "Paper Source" in *Settings > Printing > Reports* in
*Specific actions per user*
* Users may also select a default tray in their preferences
Usage
=====
There is no special usage, once configured, reports are printed in the
select tray. When no tray is configured for a report and a user, the
default tray setup on the CUPS server is used.
.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas
:alt: Try me on Runbot
:target: https://runbot.odoo-community.org/runbot/144/10.0
Known issues / Roadmap
======================
Bug Tracker
===========
Bugs are tracked on `GitHub Issues
<https://github.com/OCA/report-print-send/issues>`_. In case of trouble, please
check there if your issue has already been reported. If you spotted it first,
help us smashing it by providing a detailed and welcomed feedback.
Credits
=======
Contributors
------------
* Yannick Vaucher <yannick.vaucher@camptocamp.com>
* Guewen Baconnier <guewen.baconnier@camptocamp.com>
Maintainer
----------
.. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association
:target: https://odoo-community.org
This module is maintained by the OCA.
OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.
To contribute to this module, please visit https://odoo-community.org.

View File

@@ -1,5 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2013-2014 Camptocamp (<http://www.camptocamp.com>)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from . import models

View File

@@ -1,28 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2013-2014 Camptocamp (<http://www.camptocamp.com>)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
{
'name': 'Report to printer - Paper tray selection',
'version': '11.0.1.0.0',
'category': 'Printer',
'author': "Camptocamp, Odoo Community Association (OCA)",
'maintainer': 'Camptocamp',
'website': 'http://www.camptocamp.com/',
'license': 'AGPL-3',
'depends': [
'base_report_to_printer',
],
'data': [
'views/res_users.xml',
'views/ir_actions_report.xml',
'views/printing_printer.xml',
'views/printing_report_xml_action.xml',
'security/ir.model.access.csv',
],
'external_dependencies': {
'python': ['cups'],
},
'installable': True,
'application': False,
}

View File

@@ -1,9 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2013-2014 Camptocamp (<http://www.camptocamp.com>)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from . import ir_actions_report
from . import printing_tray
from . import printing_printer
from . import res_users
from . import printing_report_xml_action

View File

@@ -1,20 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2013-2014 Camptocamp (<http://www.camptocamp.com>)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import api, fields, models
class IrActionsReport(models.Model):
_inherit = 'ir.actions.report'
printer_tray_id = fields.Many2one(
comodel_name='printing.tray',
string='Paper Source',
domain="[('printer_id', '=', printing_printer_id)]",
)
@api.onchange('printing_printer_id')
def onchange_printing_printer_id(self):
""" Reset the tray when the printer is changed """
self.printer_tray_id = False

View File

@@ -1,98 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2013-2014 Camptocamp (<http://www.camptocamp.com>)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
import errno
import logging
import os
from odoo import api, fields, models
_logger = logging.getLogger(__name__)
try:
import cups
except ImportError:
_logger.debug('Cannot `import cups`.')
class PrintingPrinter(models.Model):
_inherit = 'printing.printer'
tray_ids = fields.One2many(comodel_name='printing.tray',
inverse_name='printer_id',
string='Paper Sources')
@api.multi
def _prepare_update_from_cups(self, cups_connection, cups_printer):
vals = super(PrintingPrinter, self)._prepare_update_from_cups(
cups_connection, cups_printer)
printer_uri = cups_printer['printer-uri-supported']
printer_system_name = printer_uri[printer_uri.rfind('/') + 1:]
ppd_info = cups_connection.getPPD3(printer_system_name)
ppd_path = ppd_info[2]
if not ppd_path:
return vals
ppd = cups.PPD(ppd_path)
option = ppd.findOption('InputSlot')
try:
os.unlink(ppd_path)
except OSError as err:
# ENOENT means No such file or directory
# The file has already been deleted, we can continue the update
if err.errno != errno.ENOENT:
raise
if not option:
return vals
vals['tray_ids'] = []
cups_trays = {
tray_option['choice']: tray_option['text']
for tray_option in option.choices
}
# Add new trays
vals['tray_ids'].extend([
(0, 0, {'name': text, 'system_name': choice})
for choice, text in cups_trays.items()
if choice not in self.tray_ids.mapped('system_name')
])
# Remove deleted trays
vals['tray_ids'].extend([
(2, tray.id)
for tray in self.tray_ids.filtered(
lambda record: record.system_name not in cups_trays.keys())
])
return vals
@api.multi
def print_options(self, report=None, format=None, copies=1):
""" Hook to define Tray """
printing_act_obj = self.env['printing.report.xml.action']
options = super(PrintingPrinter, self).print_options(report, format)
if report is not None:
# Retrieve report default values
if report.printer_tray_id:
tray = report.printer_tray_id
else:
# Retrieve user default values
tray = self.env.user.printer_tray_id
# Retrieve report-user specific values
action = printing_act_obj.search([
('report_id', '=', report.id),
('user_id', '=', self.env.uid),
('action', '!=', 'user_default'),
], limit=1)
if action.printer_tray_id:
tray = action.printer_tray_id
if tray:
options['InputSlot'] = str(tray.system_name)
return options

View File

@@ -1,27 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2013-2014 Camptocamp (<http://www.camptocamp.com>)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import api, fields, models
class PrintingReportXMLAction(models.Model):
_inherit = 'printing.report.xml.action'
printer_tray_id = fields.Many2one(
comodel_name='printing.tray',
string='Paper Source',
domain="[('printer_id', '=', printer_id)]",
)
@api.multi
def behaviour(self):
self.ensure_one()
res = super(PrintingReportXMLAction, self).behaviour()
res['tray'] = self.printer_tray_id.system_name
return res
@api.onchange('printer_id')
def onchange_printer_id(self):
""" Reset the tray when the printer is changed """
self.printer_tray_id = False

View File

@@ -1,22 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2013-2014 Camptocamp (<http://www.camptocamp.com>)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import fields, models
class PrinterTray(models.Model):
_name = 'printing.tray'
_description = 'Printer Tray'
_order = 'name asc'
name = fields.Char(required=True)
system_name = fields.Char(required=True, readonly=True)
printer_id = fields.Many2one(
comodel_name='printing.printer',
string='Printer',
required=True,
readonly=True,
ondelete='cascade',
)

View File

@@ -1,20 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2013-2014 Camptocamp (<http://www.camptocamp.com>)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import api, fields, models
class ResUsers(models.Model):
_inherit = "res.users"
printer_tray_id = fields.Many2one(
comodel_name='printing.tray',
string='Default Printer Paper Source',
domain="[('printer_id', '=', printing_printer_id)]",
)
@api.onchange('printing_printer_id')
def onchange_printing_printer_id(self):
""" Reset the tray when the printer is changed """
self.printer_tray_id = False

View File

@@ -1,3 +0,0 @@
"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
access_printing_tray_all,printing_tray all,model_printing_tray,base_report_to_printer.printing_group_user,1,0,0,0
access_printing_tray_operator,printing_tray operator,model_printing_tray,base_report_to_printer.printing_group_manager,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_printing_tray_all printing_tray all model_printing_tray base_report_to_printer.printing_group_user 1 0 0 0
3 access_printing_tray_operator printing_tray operator model_printing_tray base_report_to_printer.printing_group_manager 1 1 1 1

View File

@@ -1,9 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright 2016 LasLabs Inc.
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from . import test_ir_actions_report
from . import test_printing_printer
from . import test_printing_report_xml_action
from . import test_printing_tray
from . import test_res_users

View File

@@ -1,38 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright 2017 SYLEAM Info Services
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo.tests.common import TransactionCase
class TestIrActionsReportXml(TransactionCase):
def test_onchange_printer_tray_id_empty(self):
action = self.env['ir.actions.report'].new(
{'printer_tray_id': False})
action.onchange_printing_printer_id()
self.assertFalse(action.printer_tray_id)
def test_onchange_printer_tray_id_not_empty(self):
server = self.env['printing.server'].create({})
printer = self.env['printing.printer'].create({
'name': 'Printer',
'server_id': server.id,
'system_name': 'Sys Name',
'default': True,
'status': 'unknown',
'status_message': 'Msg',
'model': 'res.users',
'location': 'Location',
'uri': 'URI',
})
tray = self.env['printing.tray'].create({
'name': 'Tray',
'system_name': 'TrayName',
'printer_id': printer.id,
})
action = self.env['ir.actions.report'].new(
{'printer_tray_id': tray.id})
self.assertEqual(action.printer_tray_id, tray)
action.onchange_printing_printer_id()
self.assertFalse(action.printer_tray_id)

View File

@@ -1,330 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright 2016 LasLabs Inc.
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
import errno
import mock
import tempfile
from odoo.tests.common import TransactionCase
model = 'odoo.addons.base_report_to_printer.models.printing_printer'
server_model = 'odoo.addons.base_report_to_printer.models.printing_server'
ppd_header = '*PPD-Adobe: "4.3"'
ppd_input_slot_header = """
*OpenUI *InputSlot: PickOne
*DefaultInputSlot: Auto
*InputSlot Auto/Auto (Default): "
<< /DeferredMediaSelection true /ManualFeed false
/MediaPosition null /MediaType null >> setpagedevice
userdict /TSBMediaType 0 put"
*End
"""
ppd_input_slot_body = """
*InputSlot {name}/{text}: "
<< /DeferredMediaSelection true /ManualFeed false
/MediaPosition null /MediaType null >> setpagedevice
userdict /TSBMediaType 0 put"
*End
"""
ppd_input_slot_footer = """
*CloseUI: *InputSlot
"""
class TestPrintingPrinter(TransactionCase):
def setUp(self):
super(TestPrintingPrinter, self).setUp()
self.Model = self.env['printing.printer']
self.ServerModel = self.env['printing.server']
self.server = self.env['printing.server'].create({})
self.printer = self.env['printing.printer'].create({
'name': 'Printer',
'server_id': self.server.id,
'system_name': 'Sys Name',
'default': True,
'status': 'unknown',
'status_message': 'Msg',
'model': 'res.users',
'location': 'Location',
'uri': 'URI',
})
self.tray_vals = {
'name': 'Tray',
'system_name': 'TrayName',
'printer_id': self.printer.id,
}
def new_tray(self, vals=None):
values = self.tray_vals
if vals is not None:
values.update(vals)
return self.env['printing.tray'].create(values)
def build_ppd(self, input_slots=None):
"""
Builds a fake PPD file declaring defined input slots
"""
ppd_contents = ppd_header
ppd_contents += ppd_input_slot_header
if input_slots is not None:
for input_slot in input_slots:
ppd_contents += ppd_input_slot_body.format(
name=input_slot['name'],
text=input_slot['text'],
)
ppd_contents += ppd_input_slot_footer
return ppd_contents
def mock_cups_ppd(self, cups, file_name=None, input_slots=None):
"""
Create a fake PPD file (if needed), then mock the getPPD3 method
return value to give that file
"""
if file_name is None:
fd, file_name = tempfile.mkstemp()
if file_name:
ppd_contents = self.build_ppd(input_slots=input_slots)
with open(file_name, 'w') as fp:
fp.write(ppd_contents)
cups.Connection().getPPD3.return_value = (200, 0, file_name)
cups.Connection().getPrinters.return_value = {
self.printer.system_name: {
'printer-info': 'info',
'printer-uri-supported': 'uri',
},
}
def test_print_options(self):
"""
It should generate the right options dictionnary
"""
report = self.env['ir.actions.report'].search([], limit=1)
action = self.env['printing.report.xml.action'].create({
'user_id': self.env.user.id,
'report_id': report.id,
'action': 'server',
})
user_tray = self.new_tray({
'system_name': 'User tray',
})
report_tray = self.new_tray({
'system_name': 'Report tray',
})
action_tray = self.new_tray({
'system_name': 'Action tray',
})
# No report passed
self.env.user.printer_tray_id = False
options = self.Model.print_options()
self.assertFalse('InputSlot' in options)
# No tray defined
self.env.user.printer_tray_id = False
report.printer_tray_id = False
action.printer_tray_id = False
options = self.Model.print_options(report, 'pdf')
self.assertFalse('InputSlot' in options)
# Only user tray is defined
self.env.user.printer_tray_id = user_tray
report.printer_tray_id = False
action.printer_tray_id = False
options = self.Model.print_options(report, 'pdf')
self.assertEquals(options, {
'InputSlot': 'User tray',
})
# Only report tray is defined
self.env.user.printer_tray_id = False
report.printer_tray_id = report_tray
action.printer_tray_id = False
options = self.Model.print_options(report, 'pdf')
self.assertEquals(options, {
'InputSlot': 'Report tray',
})
# Only action tray is defined
self.env.user.printer_tray_id = False
report.printer_tray_id = False
action.printer_tray_id = action_tray
options = self.Model.print_options(report, 'pdf')
self.assertEquals(options, {
'InputSlot': 'Action tray',
})
# All trays are defined
self.env.user.printer_tray_id = user_tray
report.printer_tray_id = report_tray
action.printer_tray_id = action_tray
options = self.Model.print_options(report, 'pdf')
self.assertEquals(options, {
'InputSlot': 'Action tray',
})
@mock.patch('%s.cups' % server_model)
def test_update_printers(self, cups):
"""
Check that the update_printers method calls _prepare_update_from_cups
"""
self.mock_cups_ppd(cups, file_name=False)
self.assertEqual(self.printer.name, 'Printer')
self.ServerModel.update_printers()
self.assertEqual(self.printer.name, 'info')
@mock.patch('%s.cups' % server_model)
def test_prepare_update_from_cups_no_ppd(self, cups):
"""
Check that the tray_ids field has no value when no PPD is available
"""
self.mock_cups_ppd(cups, file_name=False)
connection = cups.Connection()
cups_printer = connection.getPrinters()[self.printer.system_name]
vals = self.printer._prepare_update_from_cups(connection, cups_printer)
self.assertFalse('tray_ids' in vals)
@mock.patch('%s.cups' % server_model)
def test_prepare_update_from_cups_empty_ppd(self, cups):
"""
Check that the tray_ids field has no value when the PPD file has
no input slot declared
"""
fd, file_name = tempfile.mkstemp()
self.mock_cups_ppd(cups, file_name=file_name)
# Replace the ppd file's contents by an empty file
with open(file_name, 'w') as fp:
fp.write(ppd_header)
connection = cups.Connection()
cups_printer = connection.getPrinters()[self.printer.system_name]
vals = self.printer._prepare_update_from_cups(connection, cups_printer)
self.assertFalse('tray_ids' in vals)
@mock.patch('%s.cups' % server_model)
@mock.patch('os.unlink')
def test_prepare_update_from_cups_unlink_error(self, os_unlink, cups):
"""
When OSError other than ENOENT is encountered, the exception is raised
"""
# Break os.unlink
os_unlink.side_effect = OSError(errno.EIO, 'Error')
self.mock_cups_ppd(cups)
connection = cups.Connection()
cups_printer = connection.getPrinters()[self.printer.system_name]
with self.assertRaises(OSError):
self.printer._prepare_update_from_cups(connection, cups_printer)
@mock.patch('%s.cups' % server_model)
@mock.patch('os.unlink')
def test_prepare_update_from_cups_unlink_error_enoent(
self, os_unlink, cups):
"""
When a ENOENT error is encountered, the file has already been unlinked
This is not an issue, as we were trying to delete the file.
The update can continue.
"""
# Break os.unlink
os_unlink.side_effect = OSError(errno.ENOENT, 'Error')
self.mock_cups_ppd(cups)
connection = cups.Connection()
cups_printer = connection.getPrinters()[self.printer.system_name]
vals = self.printer._prepare_update_from_cups(connection, cups_printer)
self.assertEqual(vals['tray_ids'], [(0, 0, {
'name': 'Auto (Default)',
'system_name': 'Auto',
})])
@mock.patch('%s.cups' % server_model)
def test_prepare_update_from_cups(self, cups):
"""
Check the return value when adding a single tray
"""
self.mock_cups_ppd(cups)
connection = cups.Connection()
cups_printer = connection.getPrinters()[self.printer.system_name]
vals = self.printer._prepare_update_from_cups(connection, cups_printer)
self.assertEqual(vals['tray_ids'], [(0, 0, {
'name': 'Auto (Default)',
'system_name': 'Auto',
})])
@mock.patch('%s.cups' % server_model)
def test_prepare_update_from_cups_with_multiple_trays(self, cups):
"""
Check the return value when adding multiple trays at once
"""
self.mock_cups_ppd(cups, input_slots=[
{'name': 'Tray1', 'text': 'Tray 1'},
])
connection = cups.Connection()
cups_printer = connection.getPrinters()[self.printer.system_name]
vals = self.printer._prepare_update_from_cups(connection, cups_printer)
self.assertItemsEqual(vals['tray_ids'], [(0, 0, {
'name': 'Auto (Default)',
'system_name': 'Auto',
}), (0, 0, {
'name': 'Tray 1',
'system_name': 'Tray1',
})])
@mock.patch('%s.cups' % server_model)
def test_prepare_update_from_cups_already_known_trays(self, cups):
"""
Check that calling the method twice doesn't create the trays multiple
times
"""
self.mock_cups_ppd(cups, input_slots=[
{'name': 'Tray1', 'text': 'Tray 1'},
])
connection = cups.Connection()
cups_printer = connection.getPrinters()[self.printer.system_name]
# Create a tray which is in the PPD file
self.new_tray({'system_name': 'Tray1'})
vals = self.printer._prepare_update_from_cups(connection, cups_printer)
self.assertEqual(vals['tray_ids'], [(0, 0, {
'name': 'Auto (Default)',
'system_name': 'Auto',
})])
@mock.patch('%s.cups' % server_model)
def test_prepare_update_from_cups_unknown_trays(self, cups):
"""
Check that trays which are not in the PPD file are removed from Odoo
"""
self.mock_cups_ppd(cups)
connection = cups.Connection()
cups_printer = connection.getPrinters()[self.printer.system_name]
# Create a tray which is absent from the PPD file
tray = self.new_tray()
vals = self.printer._prepare_update_from_cups(connection, cups_printer)
self.assertEqual(vals['tray_ids'], [(0, 0, {
'name': 'Auto (Default)',
'system_name': 'Auto',
}), (2, tray.id)])

View File

@@ -1,38 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright 2017 SYLEAM Info Services
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo.tests.common import TransactionCase
class TestPrintingReportXmlAction(TransactionCase):
def test_onchange_printer_tray_id_empty(self):
action = self.env['printing.report.xml.action'].new(
{'printer_tray_id': False})
action.onchange_printer_id()
self.assertFalse(action.printer_tray_id)
def test_onchange_printer_tray_id_not_empty(self):
server = self.env['printing.server'].create({})
printer = self.env['printing.printer'].create({
'name': 'Printer',
'server_id': server.id,
'system_name': 'Sys Name',
'default': True,
'status': 'unknown',
'status_message': 'Msg',
'model': 'res.users',
'location': 'Location',
'uri': 'URI',
})
tray = self.env['printing.tray'].create({
'name': 'Tray',
'system_name': 'TrayName',
'printer_id': printer.id,
})
action = self.env['printing.report.xml.action'].new(
{'printer_tray_id': tray.id})
self.assertEqual(action.printer_tray_id, tray)
action.onchange_printer_id()
self.assertFalse(action.printer_tray_id)

View File

@@ -1,52 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright 2016 LasLabs Inc.
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from odoo.tests.common import TransactionCase
model = 'odoo.addons.base_report_to_printer.models.printing_server'
class TestPrintingTray(TransactionCase):
def setUp(self):
super(TestPrintingTray, self).setUp()
self.Model = self.env['printing.tray']
self.server = self.env['printing.server'].create({})
self.printer = self.env['printing.printer'].create({
'name': 'Printer',
'server_id': self.server.id,
'system_name': 'Sys Name',
'default': True,
'status': 'unknown',
'status_message': 'Msg',
'model': 'res.users',
'location': 'Location',
'uri': 'URI',
})
self.tray_vals = {
'name': 'Tray',
'system_name': 'TrayName',
'printer_id': self.printer.id,
}
def new_tray(self):
return self.env['printing.tray'].create(self.tray_vals)
def test_report_behaviour(self):
""" It should add the selected tray in the report data """
ir_report = self.env['ir.actions.report'].search([], limit=1)
report = self.env['printing.report.xml.action'].create({
'user_id': self.env.user.id,
'report_id': ir_report.id,
'action': 'server',
})
report.printer_tray_id = False
behaviour = report.behaviour()
self.assertEqual(behaviour['tray'], False)
# Check that we have te right value
report.printer_tray_id = self.new_tray()
behaviour = report.behaviour()
self.assertEqual(behaviour['tray'], report.printer_tray_id.system_name)

View File

@@ -1,38 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright 2017 SYLEAM Info Services
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo.tests.common import TransactionCase
class TestResUsers(TransactionCase):
def test_onchange_printer_tray_id_empty(self):
user = self.env['res.users'].new(
{'printer_tray_id': False})
user.onchange_printing_printer_id()
self.assertFalse(user.printer_tray_id)
def test_onchange_printer_tray_id_not_empty(self):
server = self.env['printing.server'].create({})
printer = self.env['printing.printer'].create({
'name': 'Printer',
'server_id': server.id,
'system_name': 'Sys Name',
'default': True,
'status': 'unknown',
'status_message': 'Msg',
'model': 'res.users',
'location': 'Location',
'uri': 'URI',
})
tray = self.env['printing.tray'].create({
'name': 'Tray',
'system_name': 'TrayName',
'printer_id': printer.id,
})
user = self.env['res.users'].new(
{'printer_tray_id': tray.id})
self.assertEqual(user.printer_tray_id, tray)
user.onchange_printing_printer_id()
self.assertFalse(user.printer_tray_id)

View File

@@ -1,16 +0,0 @@
<?xml version="1.0"?>
<odoo>
<!-- ir.report form view -->
<record model="ir.ui.view" id="act_report_xml_view">
<field name="name">ir.actions.report.xml.add.printer.tray</field>
<field name="model">ir.actions.report</field>
<field name="inherit_id" ref="base_report_to_printer.act_report_xml_view"/>
<field name="arch" type="xml">
<field name="printing_printer_id" position="after">
<field name="printer_tray_id"/>
</field>
</field>
</record>
</odoo>

View File

@@ -1,24 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record model="ir.ui.view" id="printing_printer_view_form">
<field name="name">printing.printer.form</field>
<field name="model">printing.printer</field>
<field name="inherit_id" ref="base_report_to_printer.printing_printer_view_form"/>
<field name="arch" type="xml">
<xpath expr="//sheet/group[3]" position="after">
<group string="Trays" name="trays">
<field name="tray_ids" nolabel="1">
<form>
<group name="name_fields">
<field name="name"/>
<field name="system_name"/>
</group>
</form>
</field>
</group>
</xpath>
</field>
</record>
</odoo>

View File

@@ -1,26 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="printing_report_xml_action_view_form" model="ir.ui.view">
<field name="name">printing.report.xml.action.form</field>
<field name="model">printing.report.xml.action</field>
<field name="inherit_id" ref="base_report_to_printer.printing_report_xml_action_view_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='printer_id']" position="after">
<field name="printer_tray_id"/>
</xpath>
</field>
</record>
<record id="printing_report_xml_action_view_tree" model="ir.ui.view">
<field name="name">printing.report.xml.action.form</field>
<field name="model">printing.report.xml.action</field>
<field name="inherit_id" ref="base_report_to_printer.printing_report_xml_action_view_tree"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='printer_id']" position="after">
<field name="printer_tray_id"/>
</xpath>
</field>
</record>
</odoo>