first commit
This commit is contained in:
11
modules/stock/__init__.py
Normal file
11
modules/stock/__init__.py
Normal file
@@ -0,0 +1,11 @@
|
||||
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
|
||||
__all__ = ['StockMixin']
|
||||
|
||||
|
||||
def __getattr__(name):
|
||||
if name == 'StockMixin':
|
||||
from .move import StockMixin
|
||||
return StockMixin
|
||||
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
||||
BIN
modules/stock/__pycache__/__init__.cpython-311.pyc
Normal file
BIN
modules/stock/__pycache__/__init__.cpython-311.pyc
Normal file
Binary file not shown.
BIN
modules/stock/__pycache__/configuration.cpython-311.pyc
Normal file
BIN
modules/stock/__pycache__/configuration.cpython-311.pyc
Normal file
Binary file not shown.
BIN
modules/stock/__pycache__/exceptions.cpython-311.pyc
Normal file
BIN
modules/stock/__pycache__/exceptions.cpython-311.pyc
Normal file
Binary file not shown.
BIN
modules/stock/__pycache__/inventory.cpython-311.pyc
Normal file
BIN
modules/stock/__pycache__/inventory.cpython-311.pyc
Normal file
Binary file not shown.
BIN
modules/stock/__pycache__/ir.cpython-311.pyc
Normal file
BIN
modules/stock/__pycache__/ir.cpython-311.pyc
Normal file
Binary file not shown.
BIN
modules/stock/__pycache__/location.cpython-311.pyc
Normal file
BIN
modules/stock/__pycache__/location.cpython-311.pyc
Normal file
Binary file not shown.
BIN
modules/stock/__pycache__/move.cpython-311.pyc
Normal file
BIN
modules/stock/__pycache__/move.cpython-311.pyc
Normal file
Binary file not shown.
BIN
modules/stock/__pycache__/party.cpython-311.pyc
Normal file
BIN
modules/stock/__pycache__/party.cpython-311.pyc
Normal file
Binary file not shown.
BIN
modules/stock/__pycache__/period.cpython-311.pyc
Normal file
BIN
modules/stock/__pycache__/period.cpython-311.pyc
Normal file
Binary file not shown.
BIN
modules/stock/__pycache__/product.cpython-311.pyc
Normal file
BIN
modules/stock/__pycache__/product.cpython-311.pyc
Normal file
Binary file not shown.
BIN
modules/stock/__pycache__/res.cpython-311.pyc
Normal file
BIN
modules/stock/__pycache__/res.cpython-311.pyc
Normal file
Binary file not shown.
BIN
modules/stock/__pycache__/shipment.cpython-311.pyc
Normal file
BIN
modules/stock/__pycache__/shipment.cpython-311.pyc
Normal file
Binary file not shown.
BIN
modules/stock/__pycache__/stock_reporting.cpython-311.pyc
Normal file
BIN
modules/stock/__pycache__/stock_reporting.cpython-311.pyc
Normal file
Binary file not shown.
BIN
modules/stock/__pycache__/stock_reporting_margin.cpython-311.pyc
Normal file
BIN
modules/stock/__pycache__/stock_reporting_margin.cpython-311.pyc
Normal file
Binary file not shown.
196
modules/stock/configuration.py
Normal file
196
modules/stock/configuration.py
Normal file
@@ -0,0 +1,196 @@
|
||||
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
from trytond.model import (
|
||||
ModelSingleton, ModelSQL, ModelView, ValueMixin, fields)
|
||||
from trytond.modules.company.model import (
|
||||
CompanyMultiValueMixin, CompanyValueMixin)
|
||||
from trytond.pool import Pool
|
||||
from trytond.pyson import Eval, Id
|
||||
|
||||
sequences = ['shipment_in_sequence', 'shipment_in_return_sequence',
|
||||
'shipment_out_sequence', 'shipment_out_return_sequence',
|
||||
'shipment_internal_sequence', 'inventory_sequence']
|
||||
shipment_internal_transit = fields.Many2One(
|
||||
'stock.location', "Internal Shipment Transit", required=True,
|
||||
domain=[
|
||||
('type', '=', 'storage'),
|
||||
('parent', '=', None),
|
||||
],
|
||||
help="The default location used for stock that is in transit between "
|
||||
"warehouses.")
|
||||
|
||||
|
||||
def default_func(field_name):
|
||||
@classmethod
|
||||
def default(cls, **pattern):
|
||||
return getattr(
|
||||
cls.multivalue_model(field_name),
|
||||
'default_%s' % field_name, lambda: None)()
|
||||
return default
|
||||
|
||||
|
||||
def default_sequence(name):
|
||||
@classmethod
|
||||
def default(cls):
|
||||
pool = Pool()
|
||||
ModelData = pool.get('ir.model.data')
|
||||
try:
|
||||
return ModelData.get_id('stock', name)
|
||||
except KeyError:
|
||||
return None
|
||||
return default
|
||||
|
||||
|
||||
class Configuration(
|
||||
ModelSingleton, ModelSQL, ModelView, CompanyMultiValueMixin):
|
||||
__name__ = 'stock.configuration'
|
||||
shipment_in_sequence = fields.MultiValue(fields.Many2One(
|
||||
'ir.sequence', "Supplier Shipment Sequence", required=True,
|
||||
domain=[
|
||||
('company', 'in',
|
||||
[Eval('context', {}).get('company', -1), None]),
|
||||
('sequence_type', '=',
|
||||
Id('stock', 'sequence_type_shipment_in')),
|
||||
],
|
||||
help="Used to generate the number given to supplier shipments."))
|
||||
shipment_in_return_sequence = fields.MultiValue(fields.Many2One(
|
||||
'ir.sequence', "Supplier Return Shipment Sequence", required=True,
|
||||
domain=[
|
||||
('company', 'in',
|
||||
[Eval('context', {}).get('company', -1), None]),
|
||||
('sequence_type', '=',
|
||||
Id('stock', 'sequence_type_shipment_in_return')),
|
||||
],
|
||||
help="Used to generate the number given to supplier return "
|
||||
"shipments."))
|
||||
shipment_out_sequence = fields.MultiValue(fields.Many2One(
|
||||
'ir.sequence', "Customer Shipment Sequence", required=True,
|
||||
domain=[
|
||||
('company', 'in',
|
||||
[Eval('context', {}).get('company', -1), None]),
|
||||
('sequence_type', '=',
|
||||
Id('stock', 'sequence_type_shipment_out')),
|
||||
],
|
||||
help="Used to generate the number given to customer "
|
||||
"shipments."))
|
||||
shipment_out_return_sequence = fields.MultiValue(fields.Many2One(
|
||||
'ir.sequence', "Customer Return Shipment Sequence", required=True,
|
||||
domain=[
|
||||
('company', 'in',
|
||||
[Eval('context', {}).get('company', -1), None]),
|
||||
('sequence_type', '=',
|
||||
Id('stock', 'sequence_type_shipment_out_return')),
|
||||
],
|
||||
help="Used to generate the number given to customer return "
|
||||
"shipments."))
|
||||
shipment_internal_sequence = fields.MultiValue(fields.Many2One(
|
||||
'ir.sequence', "Internal Shipment Sequence", required=True,
|
||||
domain=[
|
||||
('company', 'in',
|
||||
[Eval('context', {}).get('company', -1), None]),
|
||||
('sequence_type', '=',
|
||||
Id('stock', 'sequence_type_shipment_internal')),
|
||||
],
|
||||
help="Used to generate the number given to internal "
|
||||
"shipments."))
|
||||
inventory_sequence = fields.MultiValue(fields.Many2One(
|
||||
'ir.sequence', "Inventory Sequence", required=True,
|
||||
domain=[
|
||||
('company', 'in',
|
||||
[Eval('context', {}).get('company', -1), None]),
|
||||
('sequence_type', '=',
|
||||
Id('stock', 'sequence_type_inventory')),
|
||||
],
|
||||
help="Used to generate the number given to inventories."))
|
||||
shipment_internal_transit = fields.MultiValue(shipment_internal_transit)
|
||||
|
||||
@classmethod
|
||||
def multivalue_model(cls, field):
|
||||
pool = Pool()
|
||||
if field in sequences:
|
||||
return pool.get('stock.configuration.sequence')
|
||||
if field == 'shipment_internal_transit':
|
||||
return pool.get('stock.configuration.location')
|
||||
return super().multivalue_model(field)
|
||||
|
||||
default_shipment_in_sequence = default_func('shipment_in_sequence')
|
||||
default_shipment_in_return_sequence = default_func(
|
||||
'shipment_in_return_sequence')
|
||||
default_shipment_out_sequence = default_func('shipment_out_sequence')
|
||||
default_shipment_out_return_sequence = default_func(
|
||||
'shipment_out_return_sequence')
|
||||
default_shipment_internal_sequence = default_func(
|
||||
'shipment_internal_sequence')
|
||||
default_inventory_sequence = default_func('inventory_sequence')
|
||||
default_shipment_internal_transit = default_func(
|
||||
'shipment_internal_transit')
|
||||
|
||||
|
||||
class ConfigurationSequence(ModelSQL, CompanyValueMixin):
|
||||
__name__ = 'stock.configuration.sequence'
|
||||
shipment_in_sequence = fields.Many2One(
|
||||
'ir.sequence', "Supplier Shipment Sequence", required=True,
|
||||
domain=[
|
||||
('company', 'in', [Eval('company', -1), None]),
|
||||
('sequence_type', '=',
|
||||
Id('stock', 'sequence_type_shipment_in')),
|
||||
])
|
||||
shipment_in_return_sequence = fields.Many2One(
|
||||
'ir.sequence', "Supplier Return Shipment Sequence", required=True,
|
||||
domain=[
|
||||
('company', 'in', [Eval('company', -1), None]),
|
||||
('sequence_type', '=',
|
||||
Id('stock', 'sequence_type_shipment_in_return')),
|
||||
])
|
||||
shipment_out_sequence = fields.Many2One(
|
||||
'ir.sequence', "Customer Shipment Sequence", required=True,
|
||||
domain=[
|
||||
('company', 'in', [Eval('company', -1), None]),
|
||||
('sequence_type', '=',
|
||||
Id('stock', 'sequence_type_shipment_out')),
|
||||
])
|
||||
shipment_out_return_sequence = fields.Many2One(
|
||||
'ir.sequence', "Customer Return Shipment Sequence", required=True,
|
||||
domain=[
|
||||
('company', 'in', [Eval('company', -1), None]),
|
||||
('sequence_type', '=',
|
||||
Id('stock', 'sequence_type_shipment_out_return')),
|
||||
])
|
||||
shipment_internal_sequence = fields.Many2One(
|
||||
'ir.sequence', "Internal Shipment Sequence", required=True,
|
||||
domain=[
|
||||
('company', 'in', [Eval('company', -1), None]),
|
||||
('sequence_type', '=',
|
||||
Id('stock', 'sequence_type_shipment_internal')),
|
||||
])
|
||||
inventory_sequence = fields.Many2One(
|
||||
'ir.sequence', "Inventory Sequence", required=True,
|
||||
domain=[
|
||||
('company', 'in', [Eval('company', -1), None]),
|
||||
('sequence_type', '=',
|
||||
Id('stock', 'sequence_type_inventory')),
|
||||
])
|
||||
|
||||
default_shipment_in_sequence = default_sequence('sequence_shipment_in')
|
||||
default_shipment_in_return_sequence = default_sequence(
|
||||
'sequence_shipment_in_return')
|
||||
default_shipment_out_sequence = default_sequence('sequence_shipment_out')
|
||||
default_shipment_out_return_sequence = default_sequence(
|
||||
'sequence_shipment_out_return')
|
||||
default_shipment_internal_sequence = default_sequence(
|
||||
'sequence_shipment_internal')
|
||||
default_inventory_sequence = default_sequence('sequence_inventory')
|
||||
|
||||
|
||||
class ConfigurationLocation(ModelSQL, ValueMixin):
|
||||
__name__ = 'stock.configuration.location'
|
||||
shipment_internal_transit = shipment_internal_transit
|
||||
|
||||
@classmethod
|
||||
def default_shipment_internal_transit(cls):
|
||||
pool = Pool()
|
||||
ModelData = pool.get('ir.model.data')
|
||||
try:
|
||||
return ModelData.get_id('stock', 'location_transit')
|
||||
except KeyError:
|
||||
return None
|
||||
46
modules/stock/configuration.xml
Normal file
46
modules/stock/configuration.xml
Normal file
@@ -0,0 +1,46 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
this repository contains the full copyright notices and license terms. -->
|
||||
<tryton>
|
||||
<data>
|
||||
<record model="ir.ui.view" id="stock_configuration_view_form">
|
||||
<field name="model">stock.configuration</field>
|
||||
<field name="type">form</field>
|
||||
<field name="name">configuration_form</field>
|
||||
</record>
|
||||
<record model="ir.action.act_window" id="act_stock_configuration_form">
|
||||
<field name="name">Configuration</field>
|
||||
<field name="res_model">stock.configuration</field>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view"
|
||||
id="act_stock_configuration_view1">
|
||||
<field name="sequence" eval="1"/>
|
||||
<field name="view" ref="stock_configuration_view_form"/>
|
||||
<field name="act_window" ref="act_stock_configuration_form"/>
|
||||
</record>
|
||||
<menuitem
|
||||
parent="menu_configuration"
|
||||
action="act_stock_configuration_form"
|
||||
sequence="10"
|
||||
id="menu_stock_configuration"
|
||||
icon="tryton-list"/>
|
||||
|
||||
<record model="ir.model.access" id="access_configuration">
|
||||
<field name="model">stock.configuration</field>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
<field name="perm_create" eval="False"/>
|
||||
<field name="perm_delete" eval="False"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.access" id="access_configuration_admin">
|
||||
<field name="model">stock.configuration</field>
|
||||
<field name="group" ref="group_stock_admin"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="True"/>
|
||||
<field name="perm_create" eval="False"/>
|
||||
<field name="perm_delete" eval="False"/>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</tryton>
|
||||
612
modules/stock/customer_return_restocking_list.fodt
Normal file
612
modules/stock/customer_return_restocking_list.fodt
Normal file
@@ -0,0 +1,612 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<office:document xmlns:css3t="http://www.w3.org/TR/css3-text/" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:rpt="http://openoffice.org/2005/report" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:officeooo="http://openoffice.org/2009/office" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.text">
|
||||
<office:meta><meta:generator>LibreOffice/7.6.4.1$Linux_X86_64 LibreOffice_project/60$Build-1</meta:generator><meta:initial-creator>Bertrand Chenal</meta:initial-creator><meta:creation-date>2009-03-26T13:54:48</meta:creation-date><dc:date>2024-04-19T23:15:38.475520081</dc:date><meta:editing-cycles>61</meta:editing-cycles><meta:editing-duration>PT7H7M38S</meta:editing-duration><meta:document-statistic meta:table-count="1" meta:image-count="0" meta:object-count="0" meta:page-count="3" meta:paragraph-count="46" meta:word-count="103" meta:character-count="1103" meta:non-whitespace-character-count="1045"/><meta:user-defined meta:name="Info 1"/><meta:user-defined meta:name="Info 2"/><meta:user-defined meta:name="Info 3"/><meta:user-defined meta:name="Info 4"/></office:meta>
|
||||
<office:settings>
|
||||
<config:config-item-set config:name="ooo:view-settings">
|
||||
<config:config-item config:name="ViewAreaTop" config:type="long">0</config:config-item>
|
||||
<config:config-item config:name="ViewAreaLeft" config:type="long">0</config:config-item>
|
||||
<config:config-item config:name="ViewAreaWidth" config:type="long">25269</config:config-item>
|
||||
<config:config-item config:name="ViewAreaHeight" config:type="long">23973</config:config-item>
|
||||
<config:config-item config:name="ShowRedlineChanges" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="InBrowseMode" config:type="boolean">false</config:config-item>
|
||||
<config:config-item-map-indexed config:name="Views">
|
||||
<config:config-item-map-entry>
|
||||
<config:config-item config:name="ViewId" config:type="string">view2</config:config-item>
|
||||
<config:config-item config:name="ViewLeft" config:type="long">5955</config:config-item>
|
||||
<config:config-item config:name="ViewTop" config:type="long">10248</config:config-item>
|
||||
<config:config-item config:name="VisibleLeft" config:type="long">0</config:config-item>
|
||||
<config:config-item config:name="VisibleTop" config:type="long">0</config:config-item>
|
||||
<config:config-item config:name="VisibleRight" config:type="long">25268</config:config-item>
|
||||
<config:config-item config:name="VisibleBottom" config:type="long">23971</config:config-item>
|
||||
<config:config-item config:name="ZoomType" config:type="short">0</config:config-item>
|
||||
<config:config-item config:name="ViewLayoutColumns" config:type="short">0</config:config-item>
|
||||
<config:config-item config:name="ViewLayoutBookMode" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="ZoomFactor" config:type="short">100</config:config-item>
|
||||
<config:config-item config:name="IsSelectedFrame" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="KeepRatio" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="AnchoredTextOverflowLegacy" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="LegacySingleLineFontwork" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="ConnectorUseSnapRect" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="IgnoreBreakAfterMultilineField" config:type="boolean">false</config:config-item>
|
||||
</config:config-item-map-entry>
|
||||
</config:config-item-map-indexed>
|
||||
</config:config-item-set>
|
||||
<config:config-item-set config:name="ooo:configuration-settings">
|
||||
<config:config-item config:name="PrintRightPages" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="PrintProspectRTL" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="PrintLeftPages" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="PrintPaperFromSetup" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="PrintControls" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="PrintProspect" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="PrintBlackFonts" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="PrintAnnotationMode" config:type="short">0</config:config-item>
|
||||
<config:config-item config:name="PrintEmptyPages" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="PrintSingleJobs" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="AutoFirstLineIndentDisregardLineSpace" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="HeaderSpacingBelowLastPara" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="ProtectBookmarks" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="ContinuousEndnotes" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="DisableOffPagePositioning" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="PrintTables" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="SubtractFlysAnchoredAtFlys" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="ApplyParagraphMarkFormatToNumbering" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="PrintFaxName" config:type="string"/>
|
||||
<config:config-item config:name="SurroundTextWrapSmall" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="TreatSingleColumnBreakAsPageBreak" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="PropLineSpacingShrinksFirstLine" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="TabOverSpacing" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="TabOverMargin" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="EmbedComplexScriptFonts" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="EmbedLatinScriptFonts" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="EmbedOnlyUsedFonts" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="EmbedFonts" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="ClippedPictures" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="FrameAutowidthWithMorePara" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="FloattableNomargins" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="UnbreakableNumberings" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="AllowPrintJobCancel" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="UseFormerObjectPositioning" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="UseOldNumbering" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="RsidRoot" config:type="int">68753</config:config-item>
|
||||
<config:config-item config:name="PrinterPaperFromSetup" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="CurrentDatabaseDataSource" config:type="string"/>
|
||||
<config:config-item config:name="UpdateFromTemplate" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="AddFrameOffsets" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="LoadReadonly" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="Rsid" config:type="int">737627</config:config-item>
|
||||
<config:config-item config:name="FootnoteInColumnToPageEnd" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="ProtectFields" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="SaveGlobalDocumentLinks" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="ClipAsCharacterAnchoredWriterFlyFrames" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="LinkUpdateMode" config:type="short">1</config:config-item>
|
||||
<config:config-item config:name="AddExternalLeading" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="PrintGraphics" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="EmbedSystemFonts" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="IsLabelDocument" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="AddParaLineSpacingToTableCells" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="UseFormerTextWrapping" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="HyphenateURLs" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="AddParaTableSpacingAtStart" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="TabsRelativeToIndent" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="FieldAutoUpdate" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="SaveVersionOnClose" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="ChartAutoUpdate" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="ImagePreferredDPI" config:type="int">0</config:config-item>
|
||||
<config:config-item config:name="PrinterSetup" config:type="base64Binary"/>
|
||||
<config:config-item config:name="SmallCapsPercentage66" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="AlignTabStopPosition" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="DropCapPunctuation" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="MathBaselineAlignment" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="PrinterName" config:type="string"/>
|
||||
<config:config-item config:name="CharacterCompressionType" config:type="short">0</config:config-item>
|
||||
<config:config-item config:name="AddParaTableSpacing" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="DoNotJustifyLinesWithManualBreak" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="PrintHiddenText" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="IsKernAsianPunctuation" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="PrinterIndependentLayout" config:type="string">high-resolution</config:config-item>
|
||||
<config:config-item config:name="TabOverflow" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="AddParaSpacingToTableCells" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="AddVerticalFrameOffsets" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="TabAtLeftIndentForParagraphsInList" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="ApplyUserData" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="MsWordCompMinLineHeightByFly" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="PrintTextPlaceholder" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="IgnoreFirstLineIndentInNumbering" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="UseFormerLineSpacing" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="PrintPageBackground" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="RedlineProtectionKey" config:type="base64Binary"/>
|
||||
<config:config-item config:name="EmbedAsianScriptFonts" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="BackgroundParaOverDrawings" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="SaveThumbnail" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="ConsiderTextWrapOnObjPos" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="EmbeddedDatabaseName" config:type="string"/>
|
||||
<config:config-item config:name="ProtectForm" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="DoNotResetParaAttrsForNumFont" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="MsWordCompTrailingBlanks" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="EmptyDbFieldHidesPara" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="TableRowKeep" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="NoNumberingShowFollowBy" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="InvertBorderSpacing" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="IgnoreTabsAndBlanksForLineCalculation" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="DoNotCaptureDrawObjsOnPage" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="GutterAtTop" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="StylesNoDefault" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="UnxForceZeroExtLeading" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="PrintReversed" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="UseOldPrinterMetrics" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="CurrentDatabaseCommandType" config:type="int">0</config:config-item>
|
||||
<config:config-item config:name="PrintDrawings" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="OutlineLevelYieldsNumbering" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="CurrentDatabaseCommand" config:type="string"/>
|
||||
<config:config-item config:name="CollapseEmptyCellPara" config:type="boolean">true</config:config-item>
|
||||
</config:config-item-set>
|
||||
</office:settings>
|
||||
<office:scripts>
|
||||
<office:script script:language="ooo:Basic">
|
||||
<ooo:libraries xmlns:ooo="http://openoffice.org/2004/office" xmlns:xlink="http://www.w3.org/1999/xlink"/>
|
||||
</office:script>
|
||||
</office:scripts>
|
||||
<office:font-face-decls>
|
||||
<style:font-face style:name="Andale Sans UI" svg:font-family="'Andale Sans UI'" style:font-family-generic="system" style:font-pitch="variable"/>
|
||||
<style:font-face style:name="DejaVu Sans" svg:font-family="'DejaVu Sans'" style:font-family-generic="system" style:font-pitch="variable"/>
|
||||
<style:font-face style:name="Liberation Sans" svg:font-family="'Liberation Sans'" style:font-adornments="Regular" style:font-family-generic="swiss" style:font-pitch="variable"/>
|
||||
<style:font-face style:name="Liberation Serif" svg:font-family="'Liberation Serif'" style:font-family-generic="roman" style:font-pitch="variable"/>
|
||||
<style:font-face style:name="Liberation Serif1" svg:font-family="'Liberation Serif'" style:font-adornments="Bold" style:font-family-generic="roman" style:font-pitch="variable"/>
|
||||
<style:font-face style:name="Liberation Serif2" svg:font-family="'Liberation Serif'" style:font-adornments="Regular" style:font-family-generic="roman" style:font-pitch="variable"/>
|
||||
<style:font-face style:name="StarSymbol" svg:font-family="StarSymbol"/>
|
||||
<style:font-face style:name="Thorndale AMT" svg:font-family="'Thorndale AMT'" style:font-family-generic="roman" style:font-pitch="variable"/>
|
||||
</office:font-face-decls>
|
||||
<office:styles>
|
||||
<style:default-style style:family="graphic">
|
||||
<style:graphic-properties svg:stroke-color="#000000" draw:fill-color="#99ccff" fo:wrap-option="no-wrap" draw:shadow-offset-x="0.3cm" draw:shadow-offset-y="0.3cm" draw:start-line-spacing-horizontal="0.283cm" draw:start-line-spacing-vertical="0.283cm" draw:end-line-spacing-horizontal="0.283cm" draw:end-line-spacing-vertical="0.283cm" style:writing-mode="lr-tb" style:flow-with-text="false"/>
|
||||
<style:paragraph-properties style:text-autospace="ideograph-alpha" style:line-break="strict" loext:tab-stop-distance="0cm" style:writing-mode="lr-tb" style:font-independent-line-spacing="false">
|
||||
<style:tab-stops/>
|
||||
</style:paragraph-properties>
|
||||
<style:text-properties style:use-window-font-color="true" loext:opacity="0%" style:font-name="Thorndale AMT" fo:font-size="12pt" fo:language="en" fo:country="US" style:letter-kerning="true" style:font-name-asian="Andale Sans UI" style:font-size-asian="10.5pt" style:language-asian="zxx" style:country-asian="none" style:font-name-complex="Andale Sans UI" style:font-size-complex="12pt" style:language-complex="zxx" style:country-complex="none"/>
|
||||
</style:default-style>
|
||||
<style:default-style style:family="paragraph">
|
||||
<style:paragraph-properties fo:hyphenation-ladder-count="no-limit" style:text-autospace="ideograph-alpha" style:punctuation-wrap="hanging" style:line-break="strict" style:tab-stop-distance="1.251cm" style:writing-mode="lr-tb"/>
|
||||
<style:text-properties style:use-window-font-color="true" loext:opacity="0%" style:font-name="Thorndale AMT" fo:font-size="12pt" fo:language="en" fo:country="US" style:letter-kerning="true" style:font-name-asian="Andale Sans UI" style:font-size-asian="10.5pt" style:language-asian="zxx" style:country-asian="none" style:font-name-complex="Andale Sans UI" style:font-size-complex="12pt" style:language-complex="zxx" style:country-complex="none" fo:hyphenate="false" fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2" loext:hyphenation-no-caps="false" loext:hyphenation-no-last-word="false" loext:hyphenation-word-char-count="5" loext:hyphenation-zone="no-limit"/>
|
||||
</style:default-style>
|
||||
<style:default-style style:family="table">
|
||||
<style:table-properties table:border-model="collapsing"/>
|
||||
</style:default-style>
|
||||
<style:default-style style:family="table-row">
|
||||
<style:table-row-properties fo:keep-together="auto"/>
|
||||
</style:default-style>
|
||||
<style:style style:name="Standard" style:family="paragraph" style:class="text">
|
||||
<style:text-properties style:font-name="Liberation Sans" fo:font-family="'Liberation Sans'" style:font-style-name="Regular" style:font-family-generic="swiss" style:font-pitch="variable" style:font-size-asian="10.5pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="Heading" style:family="paragraph" style:parent-style-name="Standard" style:next-style-name="Text_20_body" style:class="text">
|
||||
<style:paragraph-properties fo:margin-top="0.423cm" fo:margin-bottom="0.212cm" style:contextual-spacing="false" fo:keep-with-next="always"/>
|
||||
<style:text-properties style:font-name="Liberation Serif2" fo:font-family="'Liberation Serif'" style:font-style-name="Regular" style:font-family-generic="roman" style:font-pitch="variable" fo:font-size="16pt" style:font-name-asian="DejaVu Sans" style:font-family-asian="'DejaVu Sans'" style:font-family-generic-asian="system" style:font-pitch-asian="variable" style:font-size-asian="14pt" style:font-name-complex="DejaVu Sans" style:font-family-complex="'DejaVu Sans'" style:font-family-generic-complex="system" style:font-pitch-complex="variable" style:font-size-complex="14pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="Text_20_body" style:display-name="Text body" style:family="paragraph" style:parent-style-name="Standard" style:class="text">
|
||||
<style:paragraph-properties fo:margin-top="0cm" fo:margin-bottom="0.212cm" style:contextual-spacing="false"/>
|
||||
<style:text-properties style:font-name="Liberation Sans" fo:font-family="'Liberation Sans'" style:font-style-name="Regular" style:font-family-generic="swiss" style:font-pitch="variable" style:font-size-asian="10.5pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="List" style:family="paragraph" style:parent-style-name="Text_20_body" style:class="list">
|
||||
<style:text-properties style:font-size-asian="12pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="Caption" style:family="paragraph" style:parent-style-name="Standard" style:class="extra">
|
||||
<style:paragraph-properties fo:margin-top="0.212cm" fo:margin-bottom="0.212cm" style:contextual-spacing="false" text:number-lines="false" text:line-number="0"/>
|
||||
<style:text-properties fo:font-size="12pt" fo:font-style="italic" style:font-size-asian="12pt" style:font-style-asian="italic" style:font-size-complex="12pt" style:font-style-complex="italic"/>
|
||||
</style:style>
|
||||
<style:style style:name="Index" style:family="paragraph" style:parent-style-name="Standard" style:class="index">
|
||||
<style:paragraph-properties text:number-lines="false" text:line-number="0"/>
|
||||
<style:text-properties style:font-size-asian="12pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="Heading_20_1" style:display-name="Heading 1" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:class="text">
|
||||
<style:text-properties fo:font-size="16pt" fo:font-weight="bold" style:font-size-asian="115%" style:font-weight-asian="bold" style:font-size-complex="115%" style:font-weight-complex="bold"/>
|
||||
</style:style>
|
||||
<style:style style:name="Table_20_Contents" style:display-name="Table Contents" style:family="paragraph" style:parent-style-name="Standard" style:class="extra">
|
||||
<style:paragraph-properties text:number-lines="false" text:line-number="0"/>
|
||||
<style:text-properties style:font-size-asian="10.5pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="Table_20_Heading" style:display-name="Table Heading" style:family="paragraph" style:parent-style-name="Table_20_Contents" style:class="extra" style:master-page-name="">
|
||||
<style:paragraph-properties fo:text-align="center" style:justify-single-word="false" style:page-number="auto" text:number-lines="false" text:line-number="0"/>
|
||||
<style:text-properties style:font-name="Liberation Serif1" fo:font-family="'Liberation Serif'" style:font-style-name="Bold" style:font-family-generic="roman" style:font-pitch="variable" fo:font-weight="bold" style:font-size-asian="10.5pt" style:font-weight-asian="bold" style:font-weight-complex="bold"/>
|
||||
</style:style>
|
||||
<style:style style:name="Header_20_and_20_Footer" style:display-name="Header and Footer" style:family="paragraph" style:parent-style-name="Standard" style:class="extra">
|
||||
<style:paragraph-properties text:number-lines="false" text:line-number="0">
|
||||
<style:tab-stops>
|
||||
<style:tab-stop style:position="8.795cm" style:type="center"/>
|
||||
<style:tab-stop style:position="17.59cm" style:type="right"/>
|
||||
</style:tab-stops>
|
||||
</style:paragraph-properties>
|
||||
</style:style>
|
||||
<style:style style:name="Header" style:family="paragraph" style:parent-style-name="Standard" style:class="extra">
|
||||
<style:paragraph-properties text:number-lines="false" text:line-number="0">
|
||||
<style:tab-stops>
|
||||
<style:tab-stop style:position="8.795cm" style:type="center"/>
|
||||
<style:tab-stop style:position="17.59cm" style:type="right"/>
|
||||
</style:tab-stops>
|
||||
</style:paragraph-properties>
|
||||
<style:text-properties fo:font-size="9pt" style:font-size-asian="10.5pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="Heading_20_2" style:display-name="Heading 2" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:class="text">
|
||||
<style:text-properties fo:font-size="14pt" fo:font-style="italic" fo:font-weight="bold" style:font-size-asian="14pt" style:font-style-asian="italic" style:font-weight-asian="bold" style:font-size-complex="14pt" style:font-style-complex="italic" style:font-weight-complex="bold"/>
|
||||
</style:style>
|
||||
<style:style style:name="Footer" style:family="paragraph" style:parent-style-name="Standard" style:class="extra">
|
||||
<style:paragraph-properties text:number-lines="false" text:line-number="0">
|
||||
<style:tab-stops>
|
||||
<style:tab-stop style:position="8.795cm" style:type="center"/>
|
||||
<style:tab-stop style:position="17.59cm" style:type="right"/>
|
||||
</style:tab-stops>
|
||||
</style:paragraph-properties>
|
||||
<style:text-properties fo:font-size="9pt" style:font-size-asian="10.5pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="Heading_20_3" style:display-name="Heading 3" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:class="text">
|
||||
<style:text-properties fo:font-size="14pt" fo:font-weight="bold" style:font-size-asian="14pt" style:font-weight-asian="bold" style:font-size-complex="14pt" style:font-weight-complex="bold"/>
|
||||
</style:style>
|
||||
<style:style style:name="Text_20_body_20_indent" style:display-name="Text body indent" style:family="paragraph" style:parent-style-name="Text_20_body" style:class="text">
|
||||
<style:paragraph-properties fo:margin-left="0.499cm" fo:margin-right="0cm" fo:margin-top="0cm" fo:margin-bottom="0cm" style:contextual-spacing="false" fo:text-indent="0cm" style:auto-text-indent="false"/>
|
||||
</style:style>
|
||||
<style:style style:name="Text" style:family="paragraph" style:parent-style-name="Caption" style:class="extra"/>
|
||||
<style:style style:name="Quotations" style:family="paragraph" style:parent-style-name="Standard" style:class="html">
|
||||
<style:paragraph-properties fo:margin-left="1cm" fo:margin-right="1cm" fo:margin-top="0cm" fo:margin-bottom="0.499cm" style:contextual-spacing="false" fo:text-indent="0cm" style:auto-text-indent="false"/>
|
||||
</style:style>
|
||||
<style:style style:name="Title" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:class="chapter">
|
||||
<style:paragraph-properties fo:text-align="center" style:justify-single-word="false"/>
|
||||
<style:text-properties fo:font-size="28pt" fo:font-weight="bold" style:font-size-asian="28pt" style:font-weight-asian="bold" style:font-size-complex="28pt" style:font-weight-complex="bold"/>
|
||||
</style:style>
|
||||
<style:style style:name="Subtitle" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:class="chapter">
|
||||
<style:paragraph-properties fo:margin-top="0.106cm" fo:margin-bottom="0.212cm" style:contextual-spacing="false" fo:text-align="center" style:justify-single-word="false"/>
|
||||
<style:text-properties fo:font-size="18pt" style:font-size-asian="18pt" style:font-size-complex="18pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="Frame_20_contents" style:display-name="Frame contents" style:family="paragraph" style:parent-style-name="Standard" style:class="extra"/>
|
||||
<style:style style:name="Placeholder" style:family="text">
|
||||
<style:text-properties fo:font-variant="small-caps" fo:color="#008080" loext:opacity="100%" style:text-underline-style="dotted" style:text-underline-width="auto" style:text-underline-color="font-color"/>
|
||||
</style:style>
|
||||
<style:style style:name="Bullet_20_Symbols" style:display-name="Bullet Symbols" style:family="text">
|
||||
<style:text-properties style:font-name="StarSymbol" fo:font-family="StarSymbol" fo:font-size="9pt" style:font-name-asian="StarSymbol" style:font-family-asian="StarSymbol" style:font-size-asian="9pt" style:font-name-complex="StarSymbol" style:font-family-complex="StarSymbol" style:font-size-complex="9pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="Frame" style:family="graphic">
|
||||
<style:graphic-properties text:anchor-type="paragraph" svg:x="0cm" svg:y="0cm" fo:margin-left="0.201cm" fo:margin-right="0.201cm" fo:margin-top="0.201cm" fo:margin-bottom="0.201cm" style:wrap="parallel" style:number-wrapped-paragraphs="no-limit" style:wrap-contour="false" style:vertical-pos="top" style:vertical-rel="paragraph-content" style:horizontal-pos="center" style:horizontal-rel="paragraph-content" fo:background-color="transparent" draw:fill="none" draw:fill-color="#99ccff" fo:padding="0.15cm" fo:border="0.06pt solid #000000"/>
|
||||
</style:style>
|
||||
<text:outline-style style:name="Outline">
|
||||
<text:outline-level-style text:level="1" loext:num-list-format="%1%" style:num-format="">
|
||||
<style:list-level-properties text:min-label-distance="0.381cm"/>
|
||||
</text:outline-level-style>
|
||||
<text:outline-level-style text:level="2" loext:num-list-format="%2%" style:num-format="">
|
||||
<style:list-level-properties text:min-label-distance="0.381cm"/>
|
||||
</text:outline-level-style>
|
||||
<text:outline-level-style text:level="3" loext:num-list-format="%3%" style:num-format="">
|
||||
<style:list-level-properties text:min-label-distance="0.381cm"/>
|
||||
</text:outline-level-style>
|
||||
<text:outline-level-style text:level="4" loext:num-list-format="%4%" style:num-format="">
|
||||
<style:list-level-properties text:min-label-distance="0.381cm"/>
|
||||
</text:outline-level-style>
|
||||
<text:outline-level-style text:level="5" loext:num-list-format="%5%" style:num-format="">
|
||||
<style:list-level-properties text:min-label-distance="0.381cm"/>
|
||||
</text:outline-level-style>
|
||||
<text:outline-level-style text:level="6" loext:num-list-format="%6%" style:num-format="">
|
||||
<style:list-level-properties text:min-label-distance="0.381cm"/>
|
||||
</text:outline-level-style>
|
||||
<text:outline-level-style text:level="7" loext:num-list-format="%7%" style:num-format="">
|
||||
<style:list-level-properties text:min-label-distance="0.381cm"/>
|
||||
</text:outline-level-style>
|
||||
<text:outline-level-style text:level="8" loext:num-list-format="%8%" style:num-format="">
|
||||
<style:list-level-properties text:min-label-distance="0.381cm"/>
|
||||
</text:outline-level-style>
|
||||
<text:outline-level-style text:level="9" loext:num-list-format="%9%" style:num-format="">
|
||||
<style:list-level-properties text:min-label-distance="0.381cm"/>
|
||||
</text:outline-level-style>
|
||||
<text:outline-level-style text:level="10" loext:num-list-format="%10%" style:num-format="">
|
||||
<style:list-level-properties text:min-label-distance="0.381cm"/>
|
||||
</text:outline-level-style>
|
||||
</text:outline-style>
|
||||
<text:notes-configuration text:note-class="footnote" style:num-format="1" text:start-value="0" text:footnotes-position="page" text:start-numbering-at="document"/>
|
||||
<text:notes-configuration text:note-class="endnote" style:num-format="i" text:start-value="0"/>
|
||||
<text:linenumbering-configuration text:number-lines="false" text:offset="0.499cm" style:num-format="1" text:number-position="left" text:increment="5"/>
|
||||
<loext:theme loext:name="Office Theme">
|
||||
<loext:theme-colors loext:name="LibreOffice">
|
||||
<loext:color loext:name="dark1" loext:color="#000000"/>
|
||||
<loext:color loext:name="light1" loext:color="#ffffff"/>
|
||||
<loext:color loext:name="dark2" loext:color="#000000"/>
|
||||
<loext:color loext:name="light2" loext:color="#ffffff"/>
|
||||
<loext:color loext:name="accent1" loext:color="#18a303"/>
|
||||
<loext:color loext:name="accent2" loext:color="#0369a3"/>
|
||||
<loext:color loext:name="accent3" loext:color="#a33e03"/>
|
||||
<loext:color loext:name="accent4" loext:color="#8e03a3"/>
|
||||
<loext:color loext:name="accent5" loext:color="#c99c00"/>
|
||||
<loext:color loext:name="accent6" loext:color="#c9211e"/>
|
||||
<loext:color loext:name="hyperlink" loext:color="#0000ee"/>
|
||||
<loext:color loext:name="followed-hyperlink" loext:color="#551a8b"/>
|
||||
</loext:theme-colors>
|
||||
</loext:theme>
|
||||
</office:styles>
|
||||
<office:automatic-styles>
|
||||
<style:style style:name="Table1" style:family="table">
|
||||
<style:table-properties style:width="16.999cm" fo:margin-left="0cm" fo:margin-right="0cm" fo:margin-top="0.381cm" fo:margin-bottom="0cm" table:align="margins"/>
|
||||
</style:style>
|
||||
<style:style style:name="Table1.A" style:family="table-column">
|
||||
<style:table-column-properties style:column-width="4.683cm" style:rel-column-width="18053*"/>
|
||||
</style:style>
|
||||
<style:style style:name="Table1.C" style:family="table-column">
|
||||
<style:table-column-properties style:column-width="4.685cm" style:rel-column-width="18060*"/>
|
||||
</style:style>
|
||||
<style:style style:name="Table1.D" style:family="table-column">
|
||||
<style:table-column-properties style:column-width="2.949cm" style:rel-column-width="11369*"/>
|
||||
</style:style>
|
||||
<style:style style:name="Table1.A1" style:family="table-cell">
|
||||
<style:table-cell-properties fo:background-color="#cccccc" fo:padding="0.097cm" fo:border-left="0.05pt solid #000000" fo:border-right="none" fo:border-top="0.05pt solid #000000" fo:border-bottom="0.05pt solid #000000">
|
||||
<style:background-image/>
|
||||
</style:table-cell-properties>
|
||||
</style:style>
|
||||
<style:style style:name="Table1.D1" style:family="table-cell">
|
||||
<style:table-cell-properties fo:background-color="#cccccc" fo:padding="0.097cm" fo:border="0.05pt solid #000000">
|
||||
<style:background-image/>
|
||||
</style:table-cell-properties>
|
||||
</style:style>
|
||||
<style:style style:name="Table1.A2" style:family="table-cell">
|
||||
<style:table-cell-properties fo:padding="0.097cm" fo:border-left="0.05pt solid #000000" fo:border-right="none" fo:border-top="none" fo:border-bottom="0.05pt solid #000000"/>
|
||||
</style:style>
|
||||
<style:style style:name="Table1.C2" style:family="table-cell">
|
||||
<style:table-cell-properties fo:padding="0.097cm" fo:border-left="0.05pt solid #000000" fo:border-right="none" fo:border-top="none" fo:border-bottom="0.05pt solid #000000"/>
|
||||
</style:style>
|
||||
<style:style style:name="Table1.D2" style:family="table-cell">
|
||||
<style:table-cell-properties fo:padding="0.097cm" fo:border-left="0.05pt solid #000000" fo:border-right="0.05pt solid #000000" fo:border-top="none" fo:border-bottom="0.05pt solid #000000"/>
|
||||
</style:style>
|
||||
<style:style style:name="Table1.A3" style:family="table-cell">
|
||||
<style:table-cell-properties fo:padding="0.097cm" fo:border-left="0.05pt solid #000000" fo:border-right="none" fo:border-top="none" fo:border-bottom="0.05pt solid #000000"/>
|
||||
</style:style>
|
||||
<style:style style:name="Table1.B3" style:family="table-cell">
|
||||
<style:table-cell-properties fo:padding="0.097cm" fo:border-left="0.05pt solid #000000" fo:border-right="none" fo:border-top="none" fo:border-bottom="0.05pt solid #000000"/>
|
||||
</style:style>
|
||||
<style:style style:name="Table1.C3" style:family="table-cell">
|
||||
<style:table-cell-properties fo:padding="0.097cm" fo:border-left="0.05pt solid #000000" fo:border-right="none" fo:border-top="none" fo:border-bottom="0.05pt solid #000000"/>
|
||||
</style:style>
|
||||
<style:style style:name="Table1.D3" style:family="table-cell">
|
||||
<style:table-cell-properties fo:padding="0.097cm" fo:border-left="0.05pt solid #000000" fo:border-right="0.05pt solid #000000" fo:border-top="none" fo:border-bottom="0.05pt solid #000000"/>
|
||||
</style:style>
|
||||
<style:style style:name="Table1.A4" style:family="table-cell">
|
||||
<style:table-cell-properties fo:padding="0.097cm" fo:border-left="0.05pt solid #000000" fo:border-right="none" fo:border-top="none" fo:border-bottom="0.05pt solid #000000"/>
|
||||
</style:style>
|
||||
<style:style style:name="Table1.C4" style:family="table-cell">
|
||||
<style:table-cell-properties fo:padding="0.097cm" fo:border-left="0.05pt solid #000000" fo:border-right="none" fo:border-top="none" fo:border-bottom="0.05pt solid #000000"/>
|
||||
</style:style>
|
||||
<style:style style:name="Table1.D4" style:family="table-cell">
|
||||
<style:table-cell-properties fo:padding="0.097cm" fo:border-left="0.05pt solid #000000" fo:border-right="0.05pt solid #000000" fo:border-top="none" fo:border-bottom="0.05pt solid #000000"/>
|
||||
</style:style>
|
||||
<style:style style:name="P1" style:family="paragraph" style:parent-style-name="Header">
|
||||
<style:paragraph-properties fo:text-align="center" style:justify-single-word="false"/>
|
||||
<style:text-properties officeooo:paragraph-rsid="00053457"/>
|
||||
</style:style>
|
||||
<style:style style:name="P2" style:family="paragraph" style:parent-style-name="Footer">
|
||||
<style:paragraph-properties fo:text-align="center" style:justify-single-word="false"/>
|
||||
<style:text-properties officeooo:paragraph-rsid="00053457"/>
|
||||
</style:style>
|
||||
<style:style style:name="P3" style:family="paragraph" style:parent-style-name="Header">
|
||||
<style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/>
|
||||
<style:text-properties fo:font-size="12pt" officeooo:paragraph-rsid="000b415b" style:font-size-asian="12pt" style:font-size-complex="12pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="P4" style:family="paragraph" style:parent-style-name="Frame_20_contents">
|
||||
<style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/>
|
||||
</style:style>
|
||||
<style:style style:name="P5" style:family="paragraph" style:parent-style-name="Footer">
|
||||
<style:paragraph-properties fo:text-align="end" style:justify-single-word="false"/>
|
||||
</style:style>
|
||||
<style:style style:name="P6" style:family="paragraph" style:parent-style-name="Header">
|
||||
<style:paragraph-properties fo:text-align="center" style:justify-single-word="false"/>
|
||||
<style:text-properties officeooo:paragraph-rsid="00053457"/>
|
||||
</style:style>
|
||||
<style:style style:name="P7" style:family="paragraph" style:parent-style-name="Footer">
|
||||
<style:paragraph-properties fo:text-align="center" style:justify-single-word="false"/>
|
||||
<style:text-properties officeooo:paragraph-rsid="00053457"/>
|
||||
</style:style>
|
||||
<style:style style:name="P8" style:family="paragraph" style:parent-style-name="Footer">
|
||||
<style:paragraph-properties fo:text-align="center" style:justify-single-word="false"/>
|
||||
<style:text-properties officeooo:paragraph-rsid="0007d4d7"/>
|
||||
</style:style>
|
||||
<style:style style:name="P9" style:family="paragraph" style:parent-style-name="Header">
|
||||
<style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/>
|
||||
<style:text-properties fo:font-size="12pt" officeooo:paragraph-rsid="0007d4d7" style:font-size-asian="12pt" style:font-size-complex="12pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="P10" style:family="paragraph" style:parent-style-name="Header">
|
||||
<style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/>
|
||||
<style:text-properties fo:font-size="12pt" officeooo:paragraph-rsid="00053457" style:font-size-asian="12pt" style:font-size-complex="12pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="P11" style:family="paragraph" style:parent-style-name="Frame_20_contents">
|
||||
<style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/>
|
||||
</style:style>
|
||||
<style:style style:name="P12" style:family="paragraph" style:parent-style-name="Footer">
|
||||
<style:paragraph-properties fo:text-align="end" style:justify-single-word="false"/>
|
||||
</style:style>
|
||||
<style:style style:name="P13" style:family="paragraph" style:parent-style-name="Table_20_Contents">
|
||||
<style:paragraph-properties fo:text-align="end" style:justify-single-word="false"/>
|
||||
</style:style>
|
||||
<style:style style:name="P14" style:family="paragraph" style:parent-style-name="Table_20_Heading">
|
||||
<style:paragraph-properties fo:text-align="center" style:justify-single-word="false"/>
|
||||
<style:text-properties style:font-name="Liberation Serif"/>
|
||||
</style:style>
|
||||
<style:style style:name="P15" style:family="paragraph" style:parent-style-name="Table_20_Contents">
|
||||
<style:text-properties style:font-name="Liberation Serif"/>
|
||||
</style:style>
|
||||
<style:style style:name="P16" style:family="paragraph" style:parent-style-name="Standard">
|
||||
<style:paragraph-properties fo:break-before="page"/>
|
||||
</style:style>
|
||||
<style:style style:name="P17" style:family="paragraph" style:parent-style-name="Heading_20_1" style:master-page-name="">
|
||||
<style:paragraph-properties fo:text-align="center" style:justify-single-word="false" style:page-number="auto" fo:break-before="page"/>
|
||||
<style:text-properties style:text-underline-style="solid" style:text-underline-width="auto" style:text-underline-color="font-color" fo:font-weight="bold" style:font-weight-asian="bold" style:font-weight-complex="bold"/>
|
||||
</style:style>
|
||||
<style:style style:name="P18" style:family="paragraph" style:parent-style-name="Heading_20_1">
|
||||
<style:paragraph-properties fo:text-align="center" style:justify-single-word="false"/>
|
||||
<style:text-properties style:text-underline-style="solid" style:text-underline-width="auto" style:text-underline-color="font-color" fo:font-weight="bold" style:font-weight-asian="bold" style:font-weight-complex="bold"/>
|
||||
</style:style>
|
||||
<style:style style:name="P19" style:family="paragraph" style:parent-style-name="Heading_20_1">
|
||||
<style:paragraph-properties fo:text-align="center" style:justify-single-word="false"/>
|
||||
<style:text-properties style:text-underline-style="solid" style:text-underline-width="auto" style:text-underline-color="font-color" fo:font-weight="bold" officeooo:paragraph-rsid="000796e5" style:font-weight-asian="bold" style:font-weight-complex="bold"/>
|
||||
</style:style>
|
||||
<style:style style:name="P20" style:family="paragraph" style:parent-style-name="Standard">
|
||||
<style:text-properties officeooo:paragraph-rsid="0002e6f0"/>
|
||||
</style:style>
|
||||
<style:style style:name="P21" style:family="paragraph" style:parent-style-name="Standard">
|
||||
<style:text-properties officeooo:paragraph-rsid="000796e5"/>
|
||||
</style:style>
|
||||
<style:style style:name="P22" style:family="paragraph" style:parent-style-name="Frame_20_contents">
|
||||
<style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/>
|
||||
</style:style>
|
||||
<style:style style:name="P23" style:family="paragraph" style:parent-style-name="Header">
|
||||
<style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/>
|
||||
<style:text-properties fo:font-size="12pt" officeooo:paragraph-rsid="000b415b" style:font-size-asian="12pt" style:font-size-complex="12pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="T1" style:family="text">
|
||||
<style:text-properties fo:font-weight="bold" style:font-weight-asian="bold" style:font-weight-complex="bold"/>
|
||||
</style:style>
|
||||
<style:style style:name="T2" style:family="text">
|
||||
<style:text-properties fo:font-weight="bold" officeooo:rsid="0002e6f0" style:font-weight-asian="bold" style:font-weight-complex="bold"/>
|
||||
</style:style>
|
||||
<style:style style:name="T3" style:family="text">
|
||||
<style:text-properties fo:font-weight="bold" officeooo:rsid="00058f93" style:font-weight-asian="bold" style:font-weight-complex="bold"/>
|
||||
</style:style>
|
||||
<style:style style:name="T4" style:family="text">
|
||||
<style:text-properties fo:font-weight="bold" officeooo:rsid="0006a771" style:font-weight-asian="bold" style:font-weight-complex="bold"/>
|
||||
</style:style>
|
||||
<style:style style:name="T5" style:family="text">
|
||||
<style:text-properties fo:font-weight="normal" style:font-weight-asian="normal" style:font-weight-complex="normal"/>
|
||||
</style:style>
|
||||
<style:style style:name="T6" style:family="text">
|
||||
<style:text-properties officeooo:rsid="000796e5"/>
|
||||
</style:style>
|
||||
<style:style style:name="fr1" style:family="graphic" style:parent-style-name="Frame">
|
||||
<style:graphic-properties fo:margin-left="0cm" fo:margin-right="0cm" fo:margin-top="0cm" fo:margin-bottom="0cm" style:wrap="parallel" style:number-wrapped-paragraphs="no-limit" style:vertical-pos="middle" style:vertical-rel="baseline" style:horizontal-pos="left" style:horizontal-rel="paragraph" draw:opacity="100%" fo:padding="0cm" fo:border="none" draw:wrap-influence-on-position="once-concurrent" loext:allow-overlap="true">
|
||||
<style:columns fo:column-count="1" fo:column-gap="0cm"/>
|
||||
</style:graphic-properties>
|
||||
</style:style>
|
||||
<style:page-layout style:name="pm1">
|
||||
<style:page-layout-properties fo:page-width="20.999cm" fo:page-height="29.699cm" style:num-format="1" style:print-orientation="portrait" fo:margin-top="2cm" fo:margin-bottom="2cm" fo:margin-left="2cm" fo:margin-right="2cm" style:writing-mode="lr-tb" style:layout-grid-color="#c0c0c0" style:layout-grid-lines="20" style:layout-grid-base-height="0.706cm" style:layout-grid-ruby-height="0.353cm" style:layout-grid-mode="none" style:layout-grid-ruby-below="false" style:layout-grid-print="false" style:layout-grid-display="false" style:footnote-max-height="0cm" loext:margin-gutter="0cm">
|
||||
<style:footnote-sep style:width="0.018cm" style:distance-before-sep="0.101cm" style:distance-after-sep="0.101cm" style:line-style="none" style:adjustment="left" style:rel-width="25%" style:color="#000000"/>
|
||||
</style:page-layout-properties>
|
||||
<style:header-style>
|
||||
<style:header-footer-properties fo:min-height="0cm" fo:margin-left="0cm" fo:margin-right="0cm" fo:margin-bottom="0.499cm"/>
|
||||
</style:header-style>
|
||||
<style:footer-style>
|
||||
<style:header-footer-properties fo:min-height="0cm" fo:margin-left="0cm" fo:margin-right="0cm" fo:margin-top="0.499cm"/>
|
||||
</style:footer-style>
|
||||
</style:page-layout>
|
||||
<style:style style:name="dp1" style:family="drawing-page">
|
||||
<style:drawing-page-properties draw:background-size="full"/>
|
||||
</style:style>
|
||||
</office:automatic-styles>
|
||||
<office:master-styles>
|
||||
<style:master-page style:name="Standard" style:page-layout-name="pm1" draw:style-name="dp1">
|
||||
<style:header>
|
||||
<text:p text:style-name="P1"><text:placeholder text:placeholder-type="text"><if test="company and company.header"></text:placeholder></text:p>
|
||||
<text:p text:style-name="P1"><text:placeholder text:placeholder-type="text"><for each="line in company.header_used.split('\n')"></text:placeholder></text:p>
|
||||
<text:p text:style-name="P1"><text:placeholder text:placeholder-type="text"><line></text:placeholder></text:p>
|
||||
<text:p text:style-name="P1"><text:placeholder text:placeholder-type="text"></for></text:placeholder></text:p>
|
||||
<text:p text:style-name="P2"><text:placeholder text:placeholder-type="text"></if></text:placeholder></text:p>
|
||||
<text:p text:style-name="P3"><text:placeholder text:placeholder-type="text"><choose></text:placeholder></text:p>
|
||||
<text:p text:style-name="P3"><text:placeholder text:placeholder-type="text"><when test="company and company.logo"></text:placeholder></text:p>
|
||||
<text:p text:style-name="P3"><draw:frame draw:style-name="fr1" draw:name="image:company.get_logo_cm(7, 3.5)" text:anchor-type="as-char" svg:width="7.001cm" draw:z-index="2">
|
||||
<draw:text-box fo:min-height="3cm">
|
||||
<text:p text:style-name="P4"/>
|
||||
</draw:text-box>
|
||||
</draw:frame></text:p>
|
||||
<text:p text:style-name="P3"><text:placeholder text:placeholder-type="text"></when></text:placeholder></text:p>
|
||||
<text:p text:style-name="P3"><text:placeholder text:placeholder-type="text"><when test="company"></text:placeholder></text:p>
|
||||
<text:p text:style-name="P3"><text:placeholder text:placeholder-type="text"><company.rec_name></text:placeholder></text:p>
|
||||
<text:p text:style-name="P3"><text:placeholder text:placeholder-type="text"></when></text:placeholder></text:p>
|
||||
<text:p text:style-name="P3"><text:placeholder text:placeholder-type="text"></choose></text:placeholder></text:p>
|
||||
</style:header>
|
||||
<style:footer>
|
||||
<text:p text:style-name="P2"><text:placeholder text:placeholder-type="text"><if test="company and company.footer"></text:placeholder></text:p>
|
||||
<text:p text:style-name="P2"><text:placeholder text:placeholder-type="text"><for each="line in company.footer_used.split('\n')"></text:placeholder></text:p>
|
||||
<text:p text:style-name="P2"><text:placeholder text:placeholder-type="text"><line></text:placeholder></text:p>
|
||||
<text:p text:style-name="P2"><text:placeholder text:placeholder-type="text"></for></text:placeholder></text:p>
|
||||
<text:p text:style-name="P2"><text:placeholder text:placeholder-type="text"></if></text:placeholder></text:p>
|
||||
<text:p text:style-name="P5"><text:page-number text:select-page="current">3</text:page-number>/<text:page-count>3</text:page-count></text:p>
|
||||
</style:footer>
|
||||
</style:master-page>
|
||||
</office:master-styles>
|
||||
<office:body>
|
||||
<office:text text:use-soft-page-breaks="true">
|
||||
<office:forms form:automatic-focus="false" form:apply-design-mode="false"/>
|
||||
<text:sequence-decls>
|
||||
<text:sequence-decl text:display-outline-level="0" text:name="Illustration"/>
|
||||
<text:sequence-decl text:display-outline-level="0" text:name="Table"/>
|
||||
<text:sequence-decl text:display-outline-level="0" text:name="Text"/>
|
||||
<text:sequence-decl text:display-outline-level="0" text:name="Drawing"/>
|
||||
<text:sequence-decl text:display-outline-level="0" text:name="Figure"/>
|
||||
</text:sequence-decls>
|
||||
<text:p text:style-name="P16"><text:placeholder text:placeholder-type="text"><for each="shipment in records"></text:placeholder></text:p>
|
||||
<text:p text:style-name="P16"><text:placeholder text:placeholder-type="text"><choose test="shipment.state"></text:placeholder></text:p>
|
||||
<text:p text:style-name="Standard"><text:placeholder text:placeholder-type="text"><when test="'draft'"></text:placeholder></text:p>
|
||||
<text:p text:style-name="P19"><text:span text:style-name="T6">Draft </text:span>Restocking List</text:p>
|
||||
<text:p text:style-name="Standard"><text:placeholder text:placeholder-type="text"></when></text:placeholder></text:p>
|
||||
<text:p text:style-name="P21"><text:placeholder text:placeholder-type="text"><when test="'cancelled'"></text:placeholder></text:p>
|
||||
<text:p text:style-name="P19"><text:span text:style-name="T6">Cancelled </text:span>Restocking List</text:p>
|
||||
<text:p text:style-name="P21"><text:placeholder text:placeholder-type="text"></when></text:placeholder></text:p>
|
||||
<text:p text:style-name="Standard"><text:placeholder text:placeholder-type="text"><otherwise></text:placeholder></text:p>
|
||||
<text:p text:style-name="P18">Restocking List No: <text:span text:style-name="T6"><text:placeholder text:placeholder-type="text"><shipment.number></text:placeholder></text:span></text:p>
|
||||
<text:p text:style-name="Standard"><text:placeholder text:placeholder-type="text"></otherwise></text:placeholder></text:p>
|
||||
<text:p text:style-name="Standard"><text:placeholder text:placeholder-type="text"></choose></text:placeholder></text:p>
|
||||
<text:p text:style-name="P20"><text:span text:style-name="T1">Reference:</text:span><text:span text:style-name="T5"> </text:span><text:span text:style-name="T5"><text:placeholder text:placeholder-type="text"><shipment.origins or ''></text:placeholder></text:span><text:span text:style-name="T5"><text:placeholder text:placeholder-type="text"><', ' if (shipment.origins and shipment.reference) else ''></text:placeholder></text:span><text:span text:style-name="T5"><text:placeholder text:placeholder-type="text"><shipment.reference or ''></text:placeholder></text:span></text:p>
|
||||
<text:p text:style-name="Standard"><text:span text:style-name="T2">Customer</text:span><text:span text:style-name="T1">:</text:span><text:span text:style-name="T5"> </text:span><text:span text:style-name="T5"><text:placeholder text:placeholder-type="text"><shipment.customer.rec_name></text:placeholder></text:span></text:p>
|
||||
<text:p text:style-name="Standard"><text:span text:style-name="T1">Planned Date:</text:span><text:span text:style-name="T5"> </text:span><text:span text:style-name="T5"><text:placeholder text:placeholder-type="text"><shipment.planned_date and format_date(shipment.planned_date, user.language) or ''></text:placeholder></text:span></text:p>
|
||||
<text:p text:style-name="Standard"><text:span text:style-name="T1">Warehouse:</text:span><text:span text:style-name="T5"> </text:span><text:span text:style-name="T5"><text:placeholder text:placeholder-type="text"><shipment.warehouse.rec_name></text:placeholder></text:span></text:p>
|
||||
<table:table table:name="Table1" table:style-name="Table1">
|
||||
<table:table-column table:style-name="Table1.A" table:number-columns-repeated="2"/>
|
||||
<table:table-column table:style-name="Table1.C"/>
|
||||
<table:table-column table:style-name="Table1.D"/>
|
||||
<table:table-header-rows>
|
||||
<table:table-row>
|
||||
<table:table-cell table:style-name="Table1.A1" office:value-type="string">
|
||||
<text:p text:style-name="P14">From Location</text:p>
|
||||
</table:table-cell>
|
||||
<table:table-cell table:style-name="Table1.A1" office:value-type="string">
|
||||
<text:p text:style-name="P14">To Location</text:p>
|
||||
</table:table-cell>
|
||||
<table:table-cell table:style-name="Table1.A1" office:value-type="string">
|
||||
<text:p text:style-name="P14">Product</text:p>
|
||||
</table:table-cell>
|
||||
<table:table-cell table:style-name="Table1.D1" office:value-type="string">
|
||||
<text:p text:style-name="P14">Quantity</text:p>
|
||||
</table:table-cell>
|
||||
</table:table-row>
|
||||
</table:table-header-rows>
|
||||
<table:table-row>
|
||||
<table:table-cell table:style-name="Table1.A2" table:number-columns-spanned="2" office:value-type="string">
|
||||
<text:p text:style-name="P15"><text:placeholder text:placeholder-type="text"><for each="move in moves(shipment)"></text:placeholder></text:p>
|
||||
</table:table-cell>
|
||||
<table:covered-table-cell/>
|
||||
<table:table-cell table:style-name="Table1.C2" office:value-type="string">
|
||||
<text:p text:style-name="P15"/>
|
||||
</table:table-cell>
|
||||
<table:table-cell table:style-name="Table1.D2" office:value-type="string">
|
||||
<text:p text:style-name="P15"/>
|
||||
</table:table-cell>
|
||||
</table:table-row>
|
||||
<table:table-row>
|
||||
<table:table-cell table:style-name="Table1.A3" office:value-type="string">
|
||||
<text:p text:style-name="Table_20_Contents"><text:placeholder text:placeholder-type="text"><move.from_location_name></text:placeholder></text:p>
|
||||
</table:table-cell>
|
||||
<table:table-cell table:style-name="Table1.A3" office:value-type="string">
|
||||
<text:p text:style-name="Table_20_Contents"><text:placeholder text:placeholder-type="text"><move.to_location_name></text:placeholder></text:p>
|
||||
</table:table-cell>
|
||||
<table:table-cell table:style-name="Table1.C2" office:value-type="string">
|
||||
<text:p text:style-name="Table_20_Contents"><text:placeholder text:placeholder-type="text"><move.product.rec_name></text:placeholder></text:p>
|
||||
</table:table-cell>
|
||||
<table:table-cell table:style-name="Table1.D2" office:value-type="string">
|
||||
<text:p text:style-name="P13"><text:placeholder text:placeholder-type="text"><format_number_symbol(move.quantity, user.language, move.unit, digits=move.unit.digits)></text:placeholder><text:soft-page-break/></text:p>
|
||||
</table:table-cell>
|
||||
</table:table-row>
|
||||
<table:table-row>
|
||||
<table:table-cell table:style-name="Table1.A2" table:number-columns-spanned="2" office:value-type="string">
|
||||
<text:p text:style-name="Table_20_Contents"><text:placeholder text:placeholder-type="text"></for></text:placeholder></text:p>
|
||||
</table:table-cell>
|
||||
<table:covered-table-cell/>
|
||||
<table:table-cell table:style-name="Table1.C2" office:value-type="string">
|
||||
<text:p text:style-name="P15"/>
|
||||
</table:table-cell>
|
||||
<table:table-cell table:style-name="Table1.D2" office:value-type="string">
|
||||
<text:p text:style-name="P15"/>
|
||||
</table:table-cell>
|
||||
</table:table-row>
|
||||
</table:table>
|
||||
<text:p text:style-name="Text_20_body"><text:placeholder text:placeholder-type="text"></for></text:placeholder></text:p>
|
||||
</office:text>
|
||||
</office:body>
|
||||
</office:document>
|
||||
601
modules/stock/delivery_note.fodt
Normal file
601
modules/stock/delivery_note.fodt
Normal file
@@ -0,0 +1,601 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<office:document xmlns:css3t="http://www.w3.org/TR/css3-text/" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:rpt="http://openoffice.org/2005/report" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:officeooo="http://openoffice.org/2009/office" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.text">
|
||||
<office:meta><meta:generator>LibreOffice/7.6.4.1$Linux_X86_64 LibreOffice_project/60$Build-1</meta:generator><meta:creation-date>2008-06-07T15:29:02</meta:creation-date><dc:date>2009-03-26T18:33:13</dc:date><meta:editing-cycles>1</meta:editing-cycles><meta:editing-duration>PT0S</meta:editing-duration><meta:document-statistic meta:table-count="1" meta:image-count="0" meta:object-count="0" meta:page-count="3" meta:paragraph-count="52" meta:word-count="118" meta:character-count="1471" meta:non-whitespace-character-count="1404"/><meta:user-defined meta:name="Info 1"/><meta:user-defined meta:name="Info 2"/><meta:user-defined meta:name="Info 3"/><meta:user-defined meta:name="Info 4"/></office:meta>
|
||||
<office:settings>
|
||||
<config:config-item-set config:name="ooo:view-settings">
|
||||
<config:config-item config:name="ViewAreaTop" config:type="long">0</config:config-item>
|
||||
<config:config-item config:name="ViewAreaLeft" config:type="long">0</config:config-item>
|
||||
<config:config-item config:name="ViewAreaWidth" config:type="long">25269</config:config-item>
|
||||
<config:config-item config:name="ViewAreaHeight" config:type="long">23973</config:config-item>
|
||||
<config:config-item config:name="ShowRedlineChanges" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="InBrowseMode" config:type="boolean">false</config:config-item>
|
||||
<config:config-item-map-indexed config:name="Views">
|
||||
<config:config-item-map-entry>
|
||||
<config:config-item config:name="ViewId" config:type="string">view2</config:config-item>
|
||||
<config:config-item config:name="ViewLeft" config:type="long">5955</config:config-item>
|
||||
<config:config-item config:name="ViewTop" config:type="long">10248</config:config-item>
|
||||
<config:config-item config:name="VisibleLeft" config:type="long">0</config:config-item>
|
||||
<config:config-item config:name="VisibleTop" config:type="long">0</config:config-item>
|
||||
<config:config-item config:name="VisibleRight" config:type="long">25268</config:config-item>
|
||||
<config:config-item config:name="VisibleBottom" config:type="long">23971</config:config-item>
|
||||
<config:config-item config:name="ZoomType" config:type="short">0</config:config-item>
|
||||
<config:config-item config:name="ViewLayoutColumns" config:type="short">0</config:config-item>
|
||||
<config:config-item config:name="ViewLayoutBookMode" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="ZoomFactor" config:type="short">100</config:config-item>
|
||||
<config:config-item config:name="IsSelectedFrame" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="KeepRatio" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="AnchoredTextOverflowLegacy" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="LegacySingleLineFontwork" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="ConnectorUseSnapRect" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="IgnoreBreakAfterMultilineField" config:type="boolean">false</config:config-item>
|
||||
</config:config-item-map-entry>
|
||||
</config:config-item-map-indexed>
|
||||
</config:config-item-set>
|
||||
<config:config-item-set config:name="ooo:configuration-settings">
|
||||
<config:config-item config:name="PrintRightPages" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="PrintProspectRTL" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="PrintLeftPages" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="PrintPaperFromSetup" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="PrintControls" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="PrintProspect" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="PrintBlackFonts" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="PrintAnnotationMode" config:type="short">0</config:config-item>
|
||||
<config:config-item config:name="PrintEmptyPages" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="PrintSingleJobs" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="AutoFirstLineIndentDisregardLineSpace" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="HeaderSpacingBelowLastPara" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="ProtectBookmarks" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="ContinuousEndnotes" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="DisableOffPagePositioning" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="PrintTables" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="SubtractFlysAnchoredAtFlys" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="ApplyParagraphMarkFormatToNumbering" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="PrintFaxName" config:type="string"/>
|
||||
<config:config-item config:name="SurroundTextWrapSmall" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="TreatSingleColumnBreakAsPageBreak" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="PropLineSpacingShrinksFirstLine" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="TabOverSpacing" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="TabOverMargin" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="EmbedComplexScriptFonts" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="EmbedLatinScriptFonts" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="EmbedOnlyUsedFonts" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="EmbedFonts" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="ClippedPictures" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="FrameAutowidthWithMorePara" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="FloattableNomargins" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="UnbreakableNumberings" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="AllowPrintJobCancel" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="UseFormerObjectPositioning" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="UseOldNumbering" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="RsidRoot" config:type="int">1813180</config:config-item>
|
||||
<config:config-item config:name="PrinterPaperFromSetup" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="CurrentDatabaseDataSource" config:type="string"/>
|
||||
<config:config-item config:name="UpdateFromTemplate" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="AddFrameOffsets" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="LoadReadonly" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="Rsid" config:type="int">3382560</config:config-item>
|
||||
<config:config-item config:name="FootnoteInColumnToPageEnd" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="ProtectFields" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="SaveGlobalDocumentLinks" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="ClipAsCharacterAnchoredWriterFlyFrames" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="LinkUpdateMode" config:type="short">1</config:config-item>
|
||||
<config:config-item config:name="AddExternalLeading" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="PrintGraphics" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="EmbedSystemFonts" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="IsLabelDocument" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="AddParaLineSpacingToTableCells" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="UseFormerTextWrapping" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="HyphenateURLs" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="AddParaTableSpacingAtStart" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="TabsRelativeToIndent" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="FieldAutoUpdate" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="SaveVersionOnClose" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="ChartAutoUpdate" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="ImagePreferredDPI" config:type="int">0</config:config-item>
|
||||
<config:config-item config:name="PrinterSetup" config:type="base64Binary"/>
|
||||
<config:config-item config:name="SmallCapsPercentage66" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="AlignTabStopPosition" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="DropCapPunctuation" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="MathBaselineAlignment" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="PrinterName" config:type="string"/>
|
||||
<config:config-item config:name="CharacterCompressionType" config:type="short">0</config:config-item>
|
||||
<config:config-item config:name="AddParaTableSpacing" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="DoNotJustifyLinesWithManualBreak" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="PrintHiddenText" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="IsKernAsianPunctuation" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="PrinterIndependentLayout" config:type="string">high-resolution</config:config-item>
|
||||
<config:config-item config:name="TabOverflow" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="AddParaSpacingToTableCells" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="AddVerticalFrameOffsets" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="TabAtLeftIndentForParagraphsInList" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="ApplyUserData" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="MsWordCompMinLineHeightByFly" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="PrintTextPlaceholder" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="IgnoreFirstLineIndentInNumbering" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="UseFormerLineSpacing" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="PrintPageBackground" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="RedlineProtectionKey" config:type="base64Binary"/>
|
||||
<config:config-item config:name="EmbedAsianScriptFonts" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="BackgroundParaOverDrawings" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="SaveThumbnail" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="ConsiderTextWrapOnObjPos" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="EmbeddedDatabaseName" config:type="string"/>
|
||||
<config:config-item config:name="ProtectForm" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="DoNotResetParaAttrsForNumFont" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="MsWordCompTrailingBlanks" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="EmptyDbFieldHidesPara" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="TableRowKeep" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="NoNumberingShowFollowBy" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="InvertBorderSpacing" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="IgnoreTabsAndBlanksForLineCalculation" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="DoNotCaptureDrawObjsOnPage" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="GutterAtTop" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="StylesNoDefault" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="UnxForceZeroExtLeading" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="PrintReversed" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="UseOldPrinterMetrics" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="CurrentDatabaseCommandType" config:type="int">0</config:config-item>
|
||||
<config:config-item config:name="PrintDrawings" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="OutlineLevelYieldsNumbering" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="CurrentDatabaseCommand" config:type="string"/>
|
||||
<config:config-item config:name="CollapseEmptyCellPara" config:type="boolean">true</config:config-item>
|
||||
</config:config-item-set>
|
||||
</office:settings>
|
||||
<office:scripts>
|
||||
<office:script script:language="ooo:Basic">
|
||||
<ooo:libraries xmlns:ooo="http://openoffice.org/2004/office" xmlns:xlink="http://www.w3.org/1999/xlink"/>
|
||||
</office:script>
|
||||
</office:scripts>
|
||||
<office:font-face-decls>
|
||||
<style:font-face style:name="Andale Sans UI" svg:font-family="'Andale Sans UI'" style:font-family-generic="system" style:font-pitch="variable"/>
|
||||
<style:font-face style:name="DejaVu Sans" svg:font-family="'DejaVu Sans'" style:font-family-generic="system" style:font-pitch="variable"/>
|
||||
<style:font-face style:name="Liberation Sans" svg:font-family="'Liberation Sans'" style:font-family-generic="swiss" style:font-pitch="variable"/>
|
||||
<style:font-face style:name="Liberation Sans1" svg:font-family="'Liberation Sans'" style:font-adornments="Regular" style:font-family-generic="swiss" style:font-pitch="variable"/>
|
||||
<style:font-face style:name="Liberation Serif" svg:font-family="'Liberation Serif'" style:font-family-generic="roman" style:font-pitch="variable"/>
|
||||
<style:font-face style:name="Liberation Serif1" svg:font-family="'Liberation Serif'" style:font-adornments="Bold" style:font-family-generic="roman" style:font-pitch="variable"/>
|
||||
<style:font-face style:name="Liberation Serif2" svg:font-family="'Liberation Serif'" style:font-adornments="Regular" style:font-family-generic="roman" style:font-pitch="variable"/>
|
||||
<style:font-face style:name="StarSymbol" svg:font-family="StarSymbol"/>
|
||||
<style:font-face style:name="Thorndale AMT" svg:font-family="'Thorndale AMT'" style:font-family-generic="roman" style:font-pitch="variable"/>
|
||||
</office:font-face-decls>
|
||||
<office:styles>
|
||||
<style:default-style style:family="graphic">
|
||||
<style:graphic-properties svg:stroke-color="#000000" draw:fill-color="#99ccff" fo:wrap-option="no-wrap" draw:shadow-offset-x="0.3cm" draw:shadow-offset-y="0.3cm" draw:start-line-spacing-horizontal="0.283cm" draw:start-line-spacing-vertical="0.283cm" draw:end-line-spacing-horizontal="0.283cm" draw:end-line-spacing-vertical="0.283cm" style:writing-mode="lr-tb" style:flow-with-text="false"/>
|
||||
<style:paragraph-properties style:text-autospace="ideograph-alpha" style:line-break="strict" loext:tab-stop-distance="0cm" style:font-independent-line-spacing="false">
|
||||
<style:tab-stops/>
|
||||
</style:paragraph-properties>
|
||||
<style:text-properties style:use-window-font-color="true" loext:opacity="0%" style:font-name="Thorndale AMT" fo:font-size="12pt" fo:language="en" fo:country="US" style:letter-kerning="true" style:font-name-asian="Andale Sans UI" style:font-size-asian="10.5pt" style:language-asian="zxx" style:country-asian="none" style:font-name-complex="Andale Sans UI" style:font-size-complex="12pt" style:language-complex="zxx" style:country-complex="none"/>
|
||||
</style:default-style>
|
||||
<style:default-style style:family="paragraph">
|
||||
<style:paragraph-properties fo:hyphenation-ladder-count="no-limit" style:text-autospace="ideograph-alpha" style:punctuation-wrap="hanging" style:line-break="strict" style:tab-stop-distance="1.251cm" style:writing-mode="lr-tb"/>
|
||||
<style:text-properties style:use-window-font-color="true" loext:opacity="0%" style:font-name="Thorndale AMT" fo:font-size="12pt" fo:language="en" fo:country="US" style:letter-kerning="true" style:font-name-asian="Andale Sans UI" style:font-size-asian="10.5pt" style:language-asian="zxx" style:country-asian="none" style:font-name-complex="Andale Sans UI" style:font-size-complex="12pt" style:language-complex="zxx" style:country-complex="none" fo:hyphenate="false" fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2" loext:hyphenation-no-caps="false" loext:hyphenation-no-last-word="false" loext:hyphenation-word-char-count="5" loext:hyphenation-zone="no-limit"/>
|
||||
</style:default-style>
|
||||
<style:default-style style:family="table">
|
||||
<style:table-properties table:border-model="collapsing"/>
|
||||
</style:default-style>
|
||||
<style:default-style style:family="table-row">
|
||||
<style:table-row-properties fo:keep-together="auto"/>
|
||||
</style:default-style>
|
||||
<style:style style:name="Standard" style:family="paragraph" style:class="text">
|
||||
<style:text-properties style:font-name="Liberation Sans1" fo:font-family="'Liberation Sans'" style:font-style-name="Regular" style:font-family-generic="swiss" style:font-pitch="variable" style:font-size-asian="10.5pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="Heading" style:family="paragraph" style:parent-style-name="Standard" style:next-style-name="Text_20_body" style:class="text">
|
||||
<style:paragraph-properties fo:margin-top="0.423cm" fo:margin-bottom="0.212cm" style:contextual-spacing="false" fo:keep-with-next="always"/>
|
||||
<style:text-properties style:font-name="Liberation Serif2" fo:font-family="'Liberation Serif'" style:font-style-name="Regular" style:font-family-generic="roman" style:font-pitch="variable" fo:font-size="16pt" style:font-name-asian="DejaVu Sans" style:font-family-asian="'DejaVu Sans'" style:font-family-generic-asian="system" style:font-pitch-asian="variable" style:font-size-asian="14pt" style:font-name-complex="DejaVu Sans" style:font-family-complex="'DejaVu Sans'" style:font-family-generic-complex="system" style:font-pitch-complex="variable" style:font-size-complex="14pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="Text_20_body" style:display-name="Text body" style:family="paragraph" style:parent-style-name="Standard" style:class="text">
|
||||
<style:paragraph-properties fo:margin-top="0cm" fo:margin-bottom="0.212cm" style:contextual-spacing="false"/>
|
||||
<style:text-properties style:font-name="Liberation Sans1" fo:font-family="'Liberation Sans'" style:font-style-name="Regular" style:font-family-generic="swiss" style:font-pitch="variable" style:font-size-asian="10.5pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="List" style:family="paragraph" style:parent-style-name="Text_20_body" style:class="list">
|
||||
<style:text-properties style:font-size-asian="12pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="Caption" style:family="paragraph" style:parent-style-name="Standard" style:class="extra">
|
||||
<style:paragraph-properties fo:margin-top="0.212cm" fo:margin-bottom="0.212cm" style:contextual-spacing="false" text:number-lines="false" text:line-number="0"/>
|
||||
<style:text-properties fo:font-size="12pt" fo:font-style="italic" style:font-size-asian="12pt" style:font-style-asian="italic" style:font-size-complex="12pt" style:font-style-complex="italic"/>
|
||||
</style:style>
|
||||
<style:style style:name="Index" style:family="paragraph" style:parent-style-name="Standard" style:class="index">
|
||||
<style:paragraph-properties text:number-lines="false" text:line-number="0"/>
|
||||
<style:text-properties style:font-size-asian="12pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="Table_20_Contents" style:display-name="Table Contents" style:family="paragraph" style:parent-style-name="Standard" style:class="extra">
|
||||
<style:paragraph-properties text:number-lines="false" text:line-number="0"/>
|
||||
<style:text-properties style:font-size-asian="10.5pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="Table_20_Heading" style:display-name="Table Heading" style:family="paragraph" style:parent-style-name="Table_20_Contents" style:class="extra" style:master-page-name="">
|
||||
<style:paragraph-properties fo:text-align="center" style:justify-single-word="false" style:page-number="auto" text:number-lines="false" text:line-number="0"/>
|
||||
<style:text-properties style:font-name="Liberation Serif1" fo:font-family="'Liberation Serif'" style:font-style-name="Bold" style:font-family-generic="roman" style:font-pitch="variable" fo:font-weight="bold" style:font-size-asian="10.5pt" style:font-weight-asian="bold" style:font-weight-complex="bold"/>
|
||||
</style:style>
|
||||
<style:style style:name="Heading_20_1" style:display-name="Heading 1" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:class="text">
|
||||
<style:text-properties fo:font-size="16pt" fo:font-weight="bold" style:font-size-asian="115%" style:font-weight-asian="bold" style:font-size-complex="115%" style:font-weight-complex="bold"/>
|
||||
</style:style>
|
||||
<style:style style:name="Heading_20_2" style:display-name="Heading 2" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:class="text">
|
||||
<style:text-properties fo:font-size="14pt" fo:font-style="italic" fo:font-weight="bold" style:font-size-asian="14pt" style:font-style-asian="italic" style:font-weight-asian="bold" style:font-size-complex="14pt" style:font-style-complex="italic" style:font-weight-complex="bold"/>
|
||||
</style:style>
|
||||
<style:style style:name="Heading_20_3" style:display-name="Heading 3" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:class="text">
|
||||
<style:text-properties fo:font-size="14pt" fo:font-weight="bold" style:font-size-asian="14pt" style:font-weight-asian="bold" style:font-size-complex="14pt" style:font-weight-complex="bold"/>
|
||||
</style:style>
|
||||
<style:style style:name="Header_20_and_20_Footer" style:display-name="Header and Footer" style:family="paragraph" style:parent-style-name="Standard" style:class="extra">
|
||||
<style:paragraph-properties text:number-lines="false" text:line-number="0">
|
||||
<style:tab-stops>
|
||||
<style:tab-stop style:position="8.5cm" style:type="center"/>
|
||||
<style:tab-stop style:position="17cm" style:type="right"/>
|
||||
</style:tab-stops>
|
||||
</style:paragraph-properties>
|
||||
</style:style>
|
||||
<style:style style:name="Header" style:family="paragraph" style:parent-style-name="Standard" style:class="extra">
|
||||
<style:paragraph-properties text:number-lines="false" text:line-number="0">
|
||||
<style:tab-stops>
|
||||
<style:tab-stop style:position="8.795cm" style:type="center"/>
|
||||
<style:tab-stop style:position="17.59cm" style:type="right"/>
|
||||
</style:tab-stops>
|
||||
</style:paragraph-properties>
|
||||
<style:text-properties fo:font-size="9pt" style:font-size-asian="10.5pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="Footer" style:family="paragraph" style:parent-style-name="Standard" style:class="extra">
|
||||
<style:paragraph-properties text:number-lines="false" text:line-number="0">
|
||||
<style:tab-stops>
|
||||
<style:tab-stop style:position="8.795cm" style:type="center"/>
|
||||
<style:tab-stop style:position="17.59cm" style:type="right"/>
|
||||
</style:tab-stops>
|
||||
</style:paragraph-properties>
|
||||
<style:text-properties fo:font-size="9pt" style:font-size-asian="10.5pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="Text_20_body_20_indent" style:display-name="Text body indent" style:family="paragraph" style:parent-style-name="Text_20_body" style:class="text">
|
||||
<style:paragraph-properties fo:margin-left="0.499cm" fo:margin-right="0cm" fo:text-indent="0cm" style:auto-text-indent="false"/>
|
||||
</style:style>
|
||||
<style:style style:name="Text" style:family="paragraph" style:parent-style-name="Caption" style:class="extra"/>
|
||||
<style:style style:name="Quotations" style:family="paragraph" style:parent-style-name="Standard" style:class="html">
|
||||
<style:paragraph-properties fo:margin-left="1cm" fo:margin-right="1cm" fo:margin-top="0cm" fo:margin-bottom="0.499cm" style:contextual-spacing="false" fo:text-indent="0cm" style:auto-text-indent="false"/>
|
||||
</style:style>
|
||||
<style:style style:name="Title" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:class="chapter">
|
||||
<style:paragraph-properties fo:text-align="center" style:justify-single-word="false"/>
|
||||
<style:text-properties fo:font-size="28pt" fo:font-weight="bold" style:font-size-asian="28pt" style:font-weight-asian="bold" style:font-size-complex="28pt" style:font-weight-complex="bold"/>
|
||||
</style:style>
|
||||
<style:style style:name="Subtitle" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:class="chapter">
|
||||
<style:paragraph-properties fo:margin-top="0.106cm" fo:margin-bottom="0.212cm" style:contextual-spacing="false" fo:text-align="center" style:justify-single-word="false"/>
|
||||
<style:text-properties fo:font-size="18pt" style:font-size-asian="18pt" style:font-size-complex="18pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="Frame_20_contents" style:display-name="Frame contents" style:family="paragraph" style:parent-style-name="Standard" style:class="extra"/>
|
||||
<style:style style:name="Placeholder" style:family="text">
|
||||
<style:text-properties fo:font-variant="small-caps" fo:color="#008080" loext:opacity="100%" style:text-underline-style="dotted" style:text-underline-width="auto" style:text-underline-color="font-color"/>
|
||||
</style:style>
|
||||
<style:style style:name="Bullet_20_Symbols" style:display-name="Bullet Symbols" style:family="text">
|
||||
<style:text-properties style:font-name="StarSymbol" fo:font-family="StarSymbol" fo:font-size="9pt" style:font-name-asian="StarSymbol" style:font-family-asian="StarSymbol" style:font-size-asian="9pt" style:font-name-complex="StarSymbol" style:font-family-complex="StarSymbol" style:font-size-complex="9pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="Frame" style:family="graphic">
|
||||
<style:graphic-properties text:anchor-type="paragraph" svg:x="0cm" svg:y="0cm" fo:margin-left="0.201cm" fo:margin-right="0.201cm" fo:margin-top="0.201cm" fo:margin-bottom="0.201cm" style:wrap="parallel" style:number-wrapped-paragraphs="no-limit" style:wrap-contour="false" style:vertical-pos="top" style:vertical-rel="paragraph-content" style:horizontal-pos="center" style:horizontal-rel="paragraph-content" fo:background-color="transparent" draw:fill="none" draw:fill-color="#99ccff" fo:padding="0.15cm" fo:border="0.06pt solid #000000"/>
|
||||
</style:style>
|
||||
<text:outline-style style:name="Outline">
|
||||
<text:outline-level-style text:level="1" loext:num-list-format="%1%" style:num-format="">
|
||||
<style:list-level-properties text:min-label-distance="0.381cm"/>
|
||||
</text:outline-level-style>
|
||||
<text:outline-level-style text:level="2" loext:num-list-format="%2%" style:num-format="">
|
||||
<style:list-level-properties text:min-label-distance="0.381cm"/>
|
||||
</text:outline-level-style>
|
||||
<text:outline-level-style text:level="3" loext:num-list-format="%3%" style:num-format="">
|
||||
<style:list-level-properties text:min-label-distance="0.381cm"/>
|
||||
</text:outline-level-style>
|
||||
<text:outline-level-style text:level="4" loext:num-list-format="%4%" style:num-format="">
|
||||
<style:list-level-properties text:min-label-distance="0.381cm"/>
|
||||
</text:outline-level-style>
|
||||
<text:outline-level-style text:level="5" loext:num-list-format="%5%" style:num-format="">
|
||||
<style:list-level-properties text:min-label-distance="0.381cm"/>
|
||||
</text:outline-level-style>
|
||||
<text:outline-level-style text:level="6" loext:num-list-format="%6%" style:num-format="">
|
||||
<style:list-level-properties text:min-label-distance="0.381cm"/>
|
||||
</text:outline-level-style>
|
||||
<text:outline-level-style text:level="7" loext:num-list-format="%7%" style:num-format="">
|
||||
<style:list-level-properties text:min-label-distance="0.381cm"/>
|
||||
</text:outline-level-style>
|
||||
<text:outline-level-style text:level="8" loext:num-list-format="%8%" style:num-format="">
|
||||
<style:list-level-properties text:min-label-distance="0.381cm"/>
|
||||
</text:outline-level-style>
|
||||
<text:outline-level-style text:level="9" loext:num-list-format="%9%" style:num-format="">
|
||||
<style:list-level-properties text:min-label-distance="0.381cm"/>
|
||||
</text:outline-level-style>
|
||||
<text:outline-level-style text:level="10" loext:num-list-format="%10%" style:num-format="">
|
||||
<style:list-level-properties text:min-label-distance="0.381cm"/>
|
||||
</text:outline-level-style>
|
||||
</text:outline-style>
|
||||
<text:notes-configuration text:note-class="footnote" style:num-format="1" text:start-value="0" text:footnotes-position="page" text:start-numbering-at="document"/>
|
||||
<text:notes-configuration text:note-class="endnote" style:num-format="i" text:start-value="0"/>
|
||||
<text:linenumbering-configuration text:number-lines="false" text:offset="0.499cm" style:num-format="1" text:number-position="left" text:increment="5"/>
|
||||
<loext:theme loext:name="Office Theme">
|
||||
<loext:theme-colors loext:name="LibreOffice">
|
||||
<loext:color loext:name="dark1" loext:color="#000000"/>
|
||||
<loext:color loext:name="light1" loext:color="#ffffff"/>
|
||||
<loext:color loext:name="dark2" loext:color="#000000"/>
|
||||
<loext:color loext:name="light2" loext:color="#ffffff"/>
|
||||
<loext:color loext:name="accent1" loext:color="#18a303"/>
|
||||
<loext:color loext:name="accent2" loext:color="#0369a3"/>
|
||||
<loext:color loext:name="accent3" loext:color="#a33e03"/>
|
||||
<loext:color loext:name="accent4" loext:color="#8e03a3"/>
|
||||
<loext:color loext:name="accent5" loext:color="#c99c00"/>
|
||||
<loext:color loext:name="accent6" loext:color="#c9211e"/>
|
||||
<loext:color loext:name="hyperlink" loext:color="#0000ee"/>
|
||||
<loext:color loext:name="followed-hyperlink" loext:color="#551a8b"/>
|
||||
</loext:theme-colors>
|
||||
</loext:theme>
|
||||
</office:styles>
|
||||
<office:automatic-styles>
|
||||
<style:style style:name="Table1" style:family="table">
|
||||
<style:table-properties style:width="16.999cm" fo:margin-left="0cm" fo:margin-right="0cm" fo:margin-top="0.381cm" fo:margin-bottom="0cm" table:align="margins"/>
|
||||
</style:style>
|
||||
<style:style style:name="Table1.A" style:family="table-column">
|
||||
<style:table-column-properties style:column-width="9.606cm" style:rel-column-width="37032*"/>
|
||||
</style:style>
|
||||
<style:style style:name="Table1.B" style:family="table-column">
|
||||
<style:table-column-properties style:column-width="7.392cm" style:rel-column-width="28503*"/>
|
||||
</style:style>
|
||||
<style:style style:name="Table1.A1" style:family="table-cell">
|
||||
<style:table-cell-properties fo:background-color="#cccccc" fo:padding="0.097cm" fo:border-left="0.05pt solid #000000" fo:border-right="none" fo:border-top="0.05pt solid #000000" fo:border-bottom="0.05pt solid #000000">
|
||||
<style:background-image/>
|
||||
</style:table-cell-properties>
|
||||
</style:style>
|
||||
<style:style style:name="Table1.B1" style:family="table-cell">
|
||||
<style:table-cell-properties fo:background-color="#cccccc" fo:padding="0.097cm" fo:border="0.05pt solid #000000">
|
||||
<style:background-image/>
|
||||
</style:table-cell-properties>
|
||||
</style:style>
|
||||
<style:style style:name="Table1.A2" style:family="table-cell">
|
||||
<style:table-cell-properties fo:padding="0.097cm" fo:border-left="0.05pt solid #000000" fo:border-right="0.05pt solid #000000" fo:border-top="none" fo:border-bottom="0.05pt solid #000000"/>
|
||||
</style:style>
|
||||
<style:style style:name="Table1.A3" style:family="table-cell">
|
||||
<style:table-cell-properties fo:padding="0.097cm" fo:border-left="0.05pt solid #000000" fo:border-right="none" fo:border-top="none" fo:border-bottom="0.05pt solid #000000"/>
|
||||
</style:style>
|
||||
<style:style style:name="Table1.B3" style:family="table-cell">
|
||||
<style:table-cell-properties fo:padding="0.097cm" fo:border-left="0.05pt solid #000000" fo:border-right="0.05pt solid #000000" fo:border-top="none" fo:border-bottom="0.05pt solid #000000"/>
|
||||
</style:style>
|
||||
<style:style style:name="Table1.A4" style:family="table-cell">
|
||||
<style:table-cell-properties fo:padding="0.097cm" fo:border-left="0.05pt solid #000000" fo:border-right="0.05pt solid #000000" fo:border-top="none" fo:border-bottom="0.05pt solid #000000"/>
|
||||
</style:style>
|
||||
<style:style style:name="P1" style:family="paragraph" style:parent-style-name="Header">
|
||||
<style:paragraph-properties fo:text-align="center" style:justify-single-word="false"/>
|
||||
<style:text-properties officeooo:paragraph-rsid="00224f9c"/>
|
||||
</style:style>
|
||||
<style:style style:name="P2" style:family="paragraph" style:parent-style-name="Footer">
|
||||
<style:paragraph-properties fo:text-align="center" style:justify-single-word="false"/>
|
||||
<style:text-properties officeooo:paragraph-rsid="00224f9c"/>
|
||||
</style:style>
|
||||
<style:style style:name="P3" style:family="paragraph" style:parent-style-name="Header">
|
||||
<style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/>
|
||||
<style:text-properties fo:font-size="12pt" officeooo:paragraph-rsid="00339d20" style:font-size-asian="12pt" style:font-size-complex="12pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="P4" style:family="paragraph" style:parent-style-name="Frame_20_contents">
|
||||
<style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/>
|
||||
</style:style>
|
||||
<style:style style:name="P5" style:family="paragraph" style:parent-style-name="Footer">
|
||||
<style:paragraph-properties fo:text-align="end" style:justify-single-word="false"/>
|
||||
</style:style>
|
||||
<style:style style:name="P6" style:family="paragraph" style:parent-style-name="Header">
|
||||
<style:paragraph-properties fo:text-align="center" style:justify-single-word="false"/>
|
||||
<style:text-properties officeooo:paragraph-rsid="00224f9c"/>
|
||||
</style:style>
|
||||
<style:style style:name="P7" style:family="paragraph" style:parent-style-name="Footer">
|
||||
<style:paragraph-properties fo:text-align="center" style:justify-single-word="false"/>
|
||||
<style:text-properties officeooo:paragraph-rsid="00224f9c"/>
|
||||
</style:style>
|
||||
<style:style style:name="P8" style:family="paragraph" style:parent-style-name="Footer">
|
||||
<style:paragraph-properties fo:text-align="center" style:justify-single-word="false"/>
|
||||
<style:text-properties officeooo:paragraph-rsid="002fecfa"/>
|
||||
</style:style>
|
||||
<style:style style:name="P9" style:family="paragraph" style:parent-style-name="Header">
|
||||
<style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/>
|
||||
<style:text-properties fo:font-size="12pt" officeooo:paragraph-rsid="002fecfa" style:font-size-asian="12pt" style:font-size-complex="12pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="P10" style:family="paragraph" style:parent-style-name="Header">
|
||||
<style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/>
|
||||
<style:text-properties fo:font-size="12pt" officeooo:paragraph-rsid="00224f9c" style:font-size-asian="12pt" style:font-size-complex="12pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="P11" style:family="paragraph" style:parent-style-name="Frame_20_contents">
|
||||
<style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/>
|
||||
</style:style>
|
||||
<style:style style:name="P12" style:family="paragraph" style:parent-style-name="Footer">
|
||||
<style:paragraph-properties fo:text-align="end" style:justify-single-word="false"/>
|
||||
</style:style>
|
||||
<style:style style:name="P13" style:family="paragraph" style:parent-style-name="Text_20_body">
|
||||
<style:text-properties style:font-name="Liberation Serif"/>
|
||||
</style:style>
|
||||
<style:style style:name="P14" style:family="paragraph" style:parent-style-name="Table_20_Heading">
|
||||
<style:paragraph-properties fo:text-align="center" style:justify-single-word="false"/>
|
||||
<style:text-properties style:font-name="Liberation Serif"/>
|
||||
</style:style>
|
||||
<style:style style:name="P15" style:family="paragraph" style:parent-style-name="Table_20_Contents">
|
||||
<style:text-properties style:font-name="Liberation Serif"/>
|
||||
</style:style>
|
||||
<style:style style:name="P16" style:family="paragraph" style:parent-style-name="Table_20_Contents">
|
||||
<style:paragraph-properties fo:text-align="end" style:justify-single-word="false"/>
|
||||
<style:text-properties style:font-name="Liberation Serif"/>
|
||||
</style:style>
|
||||
<style:style style:name="P17" style:family="paragraph" style:parent-style-name="Table_20_Contents">
|
||||
<style:text-properties style:font-name="Liberation Serif" officeooo:paragraph-rsid="0025e811"/>
|
||||
</style:style>
|
||||
<style:style style:name="P18" style:family="paragraph" style:parent-style-name="Standard">
|
||||
<style:paragraph-properties fo:break-before="page"/>
|
||||
</style:style>
|
||||
<style:style style:name="P19" style:family="paragraph" style:parent-style-name="Standard">
|
||||
<style:paragraph-properties fo:margin-left="11.28cm" fo:margin-right="0cm" fo:text-indent="0cm" style:auto-text-indent="false"/>
|
||||
<style:text-properties style:font-name="Liberation Sans"/>
|
||||
</style:style>
|
||||
<style:style style:name="P20" style:family="paragraph" style:parent-style-name="Standard" style:master-page-name="">
|
||||
<style:paragraph-properties fo:margin-left="11.28cm" fo:margin-right="0cm" fo:text-indent="0cm" style:auto-text-indent="false" style:page-number="auto" fo:break-before="page"/>
|
||||
<style:text-properties style:font-name="Liberation Sans"/>
|
||||
</style:style>
|
||||
<style:style style:name="P21" style:family="paragraph" style:parent-style-name="Standard">
|
||||
<style:paragraph-properties fo:margin-left="11.28cm" fo:margin-right="0cm" fo:text-indent="0cm" style:auto-text-indent="false"/>
|
||||
<style:text-properties style:font-name="Liberation Sans" officeooo:paragraph-rsid="0028d873"/>
|
||||
</style:style>
|
||||
<style:style style:name="P22" style:family="paragraph" style:parent-style-name="Standard" style:master-page-name="">
|
||||
<style:paragraph-properties fo:margin-left="11.28cm" fo:margin-right="0cm" fo:text-indent="0cm" style:auto-text-indent="false" style:page-number="auto" fo:break-before="page"/>
|
||||
<style:text-properties style:font-name="Liberation Sans" officeooo:paragraph-rsid="0028d873"/>
|
||||
</style:style>
|
||||
<style:style style:name="P23" style:family="paragraph" style:parent-style-name="Standard" style:master-page-name="">
|
||||
<style:paragraph-properties fo:margin-left="0cm" fo:margin-right="0cm" fo:text-indent="0cm" style:auto-text-indent="false" style:page-number="auto" fo:break-before="page"/>
|
||||
<style:text-properties style:font-name="Liberation Sans" fo:font-size="6pt" officeooo:paragraph-rsid="0028d873" style:font-size-asian="5.25pt" style:font-size-complex="6pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="P24" style:family="paragraph" style:parent-style-name="Heading_20_1">
|
||||
<style:paragraph-properties fo:text-align="center" style:justify-single-word="false"/>
|
||||
<style:text-properties style:text-underline-style="solid" style:text-underline-width="auto" style:text-underline-color="font-color"/>
|
||||
</style:style>
|
||||
<style:style style:name="P25" style:family="paragraph" style:parent-style-name="Heading_20_1">
|
||||
<style:paragraph-properties fo:text-align="center" style:justify-single-word="false"/>
|
||||
<style:text-properties style:text-underline-style="solid" style:text-underline-width="auto" style:text-underline-color="font-color" officeooo:paragraph-rsid="002e5ea4"/>
|
||||
</style:style>
|
||||
<style:style style:name="P26" style:family="paragraph" style:parent-style-name="Standard">
|
||||
<style:text-properties officeooo:paragraph-rsid="001d64ef"/>
|
||||
</style:style>
|
||||
<style:style style:name="P27" style:family="paragraph" style:parent-style-name="Standard">
|
||||
<style:text-properties officeooo:paragraph-rsid="002e5ea4"/>
|
||||
</style:style>
|
||||
<style:style style:name="P28" style:family="paragraph" style:parent-style-name="Standard">
|
||||
<style:text-properties officeooo:paragraph-rsid="002f19d1"/>
|
||||
</style:style>
|
||||
<style:style style:name="P29" style:family="paragraph" style:parent-style-name="Standard">
|
||||
<style:text-properties officeooo:rsid="002f19d1" officeooo:paragraph-rsid="002f19d1"/>
|
||||
</style:style>
|
||||
<style:style style:name="P30" style:family="paragraph" style:parent-style-name="Standard">
|
||||
<style:text-properties fo:font-weight="normal" officeooo:paragraph-rsid="002f19d1" style:font-weight-asian="normal" style:font-weight-complex="normal"/>
|
||||
</style:style>
|
||||
<style:style style:name="P31" style:family="paragraph" style:parent-style-name="Frame_20_contents">
|
||||
<style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/>
|
||||
</style:style>
|
||||
<style:style style:name="P32" style:family="paragraph" style:parent-style-name="Header">
|
||||
<style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/>
|
||||
<style:text-properties fo:font-size="12pt" officeooo:paragraph-rsid="00339d20" style:font-size-asian="12pt" style:font-size-complex="12pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="T1" style:family="text">
|
||||
<style:text-properties fo:font-weight="bold" style:font-weight-asian="bold" style:font-weight-complex="bold"/>
|
||||
</style:style>
|
||||
<style:style style:name="T2" style:family="text">
|
||||
<style:text-properties fo:font-weight="normal" style:font-weight-asian="normal" style:font-weight-complex="normal"/>
|
||||
</style:style>
|
||||
<style:style style:name="T3" style:family="text">
|
||||
<style:text-properties officeooo:rsid="002e5ea4"/>
|
||||
</style:style>
|
||||
<style:style style:name="fr1" style:family="graphic" style:parent-style-name="Frame">
|
||||
<style:graphic-properties fo:margin-left="0cm" fo:margin-right="0cm" fo:margin-top="0cm" fo:margin-bottom="0cm" style:wrap="parallel" style:number-wrapped-paragraphs="no-limit" style:vertical-pos="middle" style:vertical-rel="baseline" style:horizontal-pos="left" style:horizontal-rel="paragraph" draw:opacity="100%" fo:padding="0cm" fo:border="none" draw:wrap-influence-on-position="once-concurrent" loext:allow-overlap="true">
|
||||
<style:columns fo:column-count="1" fo:column-gap="0cm"/>
|
||||
</style:graphic-properties>
|
||||
</style:style>
|
||||
<style:page-layout style:name="pm1">
|
||||
<style:page-layout-properties fo:page-width="20.999cm" fo:page-height="29.699cm" style:num-format="1" style:print-orientation="portrait" fo:margin-top="2cm" fo:margin-bottom="2cm" fo:margin-left="2cm" fo:margin-right="2cm" style:writing-mode="lr-tb" style:layout-grid-color="#c0c0c0" style:layout-grid-lines="44" style:layout-grid-base-height="0.55cm" style:layout-grid-ruby-height="0cm" style:layout-grid-mode="none" style:layout-grid-ruby-below="false" style:layout-grid-print="true" style:layout-grid-display="true" style:footnote-max-height="0cm" loext:margin-gutter="0cm">
|
||||
<style:footnote-sep style:width="0.018cm" style:distance-before-sep="0.101cm" style:distance-after-sep="0.101cm" style:line-style="none" style:adjustment="left" style:rel-width="25%" style:color="#000000"/>
|
||||
</style:page-layout-properties>
|
||||
<style:header-style>
|
||||
<style:header-footer-properties fo:min-height="0cm" fo:margin-left="0cm" fo:margin-right="0cm" fo:margin-bottom="0.499cm"/>
|
||||
</style:header-style>
|
||||
<style:footer-style>
|
||||
<style:header-footer-properties fo:min-height="0cm" fo:margin-left="0cm" fo:margin-right="0cm" fo:margin-top="0.499cm"/>
|
||||
</style:footer-style>
|
||||
</style:page-layout>
|
||||
<style:style style:name="dp1" style:family="drawing-page">
|
||||
<style:drawing-page-properties draw:background-size="full"/>
|
||||
</style:style>
|
||||
</office:automatic-styles>
|
||||
<office:master-styles>
|
||||
<style:master-page style:name="Standard" style:page-layout-name="pm1" draw:style-name="dp1">
|
||||
<style:header>
|
||||
<text:p text:style-name="P1"><text:placeholder text:placeholder-type="text"><if test="company and company.header"></text:placeholder></text:p>
|
||||
<text:p text:style-name="P1"><text:placeholder text:placeholder-type="text"><for each="line in company.header_used.split('\n')"></text:placeholder></text:p>
|
||||
<text:p text:style-name="P1"><text:placeholder text:placeholder-type="text"><line></text:placeholder></text:p>
|
||||
<text:p text:style-name="P1"><text:placeholder text:placeholder-type="text"></for></text:placeholder></text:p>
|
||||
<text:p text:style-name="P2"><text:placeholder text:placeholder-type="text"></if></text:placeholder></text:p>
|
||||
<text:p text:style-name="P3"><text:placeholder text:placeholder-type="text"><choose></text:placeholder></text:p>
|
||||
<text:p text:style-name="P3"><text:placeholder text:placeholder-type="text"><when test="company and company.logo"></text:placeholder></text:p>
|
||||
<text:p text:style-name="P3"><draw:frame draw:style-name="fr1" draw:name="image:company.get_logo_cm(7, 3.5)" text:anchor-type="as-char" svg:width="7.001cm" draw:z-index="2">
|
||||
<draw:text-box fo:min-height="3cm">
|
||||
<text:p text:style-name="P4"/>
|
||||
</draw:text-box>
|
||||
</draw:frame></text:p>
|
||||
<text:p text:style-name="P3"><text:placeholder text:placeholder-type="text"></when></text:placeholder></text:p>
|
||||
<text:p text:style-name="P3"><text:placeholder text:placeholder-type="text"><when test="company"></text:placeholder></text:p>
|
||||
<text:p text:style-name="P3"><text:placeholder text:placeholder-type="text"><company.rec_name></text:placeholder></text:p>
|
||||
<text:p text:style-name="P3"><text:placeholder text:placeholder-type="text"></when></text:placeholder></text:p>
|
||||
<text:p text:style-name="P3"><text:placeholder text:placeholder-type="text"></choose></text:placeholder></text:p>
|
||||
</style:header>
|
||||
<style:footer>
|
||||
<text:p text:style-name="P2"><text:placeholder text:placeholder-type="text"><if test="company and company.footer"></text:placeholder></text:p>
|
||||
<text:p text:style-name="P2"><text:placeholder text:placeholder-type="text"><for each="line in company.footer_used.split('\n')"></text:placeholder></text:p>
|
||||
<text:p text:style-name="P2"><text:placeholder text:placeholder-type="text"><line></text:placeholder></text:p>
|
||||
<text:p text:style-name="P2"><text:placeholder text:placeholder-type="text"></for></text:placeholder></text:p>
|
||||
<text:p text:style-name="P2"><text:placeholder text:placeholder-type="text"></if></text:placeholder></text:p>
|
||||
<text:p text:style-name="P5"><text:page-number text:select-page="current">3</text:page-number>/<text:page-count>3</text:page-count></text:p>
|
||||
</style:footer>
|
||||
</style:master-page>
|
||||
</office:master-styles>
|
||||
<office:body>
|
||||
<office:text text:use-soft-page-breaks="true">
|
||||
<office:forms form:automatic-focus="false" form:apply-design-mode="false"/>
|
||||
<text:sequence-decls>
|
||||
<text:sequence-decl text:display-outline-level="0" text:name="Illustration"/>
|
||||
<text:sequence-decl text:display-outline-level="0" text:name="Table"/>
|
||||
<text:sequence-decl text:display-outline-level="0" text:name="Text"/>
|
||||
<text:sequence-decl text:display-outline-level="0" text:name="Drawing"/>
|
||||
<text:sequence-decl text:display-outline-level="0" text:name="Figure"/>
|
||||
</text:sequence-decls>
|
||||
<text:p text:style-name="P18"><text:placeholder text:placeholder-type="text"><for each="shipment in records"></text:placeholder></text:p>
|
||||
<text:p text:style-name="P23"/>
|
||||
<text:p text:style-name="P21"><text:placeholder text:placeholder-type="text"><replace text:p="set_lang(shipment.delivery_address.party.lang)"></text:placeholder></text:p>
|
||||
<text:p text:style-name="P21"><text:placeholder text:placeholder-type="text"><replace text:p="shipment.set_lang(shipment.delivery_address.party.lang)"></text:placeholder></text:p>
|
||||
<text:p text:style-name="P21"><text:placeholder text:placeholder-type="text"><shipment.customer.full_name></text:placeholder></text:p>
|
||||
<text:p text:style-name="P21"><text:placeholder text:placeholder-type="text"><for each="line in shipment.delivery_address.full_address.split('\n')"></text:placeholder></text:p>
|
||||
<text:p text:style-name="P19"><text:placeholder text:placeholder-type="text"><line></text:placeholder></text:p>
|
||||
<text:p text:style-name="P19"><text:placeholder text:placeholder-type="text"></for></text:placeholder></text:p>
|
||||
<text:p text:style-name="Standard"><text:placeholder text:placeholder-type="text"><choose></text:placeholder></text:p>
|
||||
<text:p text:style-name="Standard"><text:placeholder text:placeholder-type="text"><when test="shipment.state in ['packed', 'done']"></text:placeholder></text:p>
|
||||
<text:p text:style-name="P24">Delivery Note No: <text:span text:style-name="T3"><text:placeholder text:placeholder-type="text"><shipment.number></text:placeholder></text:span></text:p>
|
||||
<text:p text:style-name="Standard"><text:placeholder text:placeholder-type="text"></when></text:placeholder></text:p>
|
||||
<text:p text:style-name="Standard"><text:placeholder text:placeholder-type="text"><when test="shipment.state == 'cancelled'"></text:placeholder></text:p>
|
||||
<text:p text:style-name="P25"><text:span text:style-name="T3">Cancelled </text:span>Delivery Note</text:p>
|
||||
<text:p text:style-name="Standard"><text:placeholder text:placeholder-type="text"></when></text:placeholder></text:p>
|
||||
<text:p text:style-name="P27"><text:placeholder text:placeholder-type="text"><otherwise></text:placeholder></text:p>
|
||||
<text:p text:style-name="P25"><text:span text:style-name="T3">Draft </text:span>Delivery Note</text:p>
|
||||
<text:p text:style-name="P27"><text:placeholder text:placeholder-type="text"></otherwise></text:placeholder></text:p>
|
||||
<text:p text:style-name="Standard"><text:soft-page-break/><text:placeholder text:placeholder-type="text"></choose></text:placeholder></text:p>
|
||||
<text:p text:style-name="Standard"><text:placeholder text:placeholder-type="text"><if test="shipment.customer.code"></text:placeholder></text:p>
|
||||
<text:p text:style-name="P28"><text:span text:style-name="T1">Customer Code: </text:span><text:span text:style-name="T2"><text:placeholder text:placeholder-type="text"><shipment.customer.code></text:placeholder></text:span></text:p>
|
||||
<text:p text:style-name="P30"><text:placeholder text:placeholder-type="text"></if></text:placeholder></text:p>
|
||||
<text:p text:style-name="P28"><text:span text:style-name="T1">Reference: </text:span><text:span text:style-name="T2"><text:placeholder text:placeholder-type="text"><shipment.origins or ''></text:placeholder></text:span><text:span text:style-name="T2"><text:placeholder text:placeholder-type="text"><', ' if (shipment.origins and shipment.reference) else ''></text:placeholder></text:span><text:span text:style-name="T2"><text:placeholder text:placeholder-type="text"><shipment.reference or ''></text:placeholder></text:span></text:p>
|
||||
<text:p text:style-name="P30"><text:placeholder text:placeholder-type="text"><if test="shipment.warehouse.address and shipment.warehouse.address.country"></text:placeholder></text:p>
|
||||
<text:p text:style-name="P29"><text:span text:style-name="T1">Location:</text:span><text:span text:style-name="T2"> </text:span><text:span text:style-name="T2"><text:placeholder text:placeholder-type="text"><shipment.warehouse.address.country.name></text:placeholder></text:span></text:p>
|
||||
<text:p text:style-name="P30"><text:placeholder text:placeholder-type="text"></if></text:placeholder></text:p>
|
||||
<text:p text:style-name="P28"><text:span text:style-name="T1">Date: </text:span><text:span text:style-name="T2"><text:placeholder text:placeholder-type="text"><format_date(shipment.effective_date or datetime.date.today(), shipment.delivery_address.party.lang)></text:placeholder></text:span></text:p>
|
||||
<table:table table:name="Table1" table:style-name="Table1">
|
||||
<table:table-column table:style-name="Table1.A"/>
|
||||
<table:table-column table:style-name="Table1.B"/>
|
||||
<table:table-header-rows>
|
||||
<table:table-row>
|
||||
<table:table-cell table:style-name="Table1.A1" office:value-type="string">
|
||||
<text:p text:style-name="P14">Product</text:p>
|
||||
</table:table-cell>
|
||||
<table:table-cell table:style-name="Table1.B1" office:value-type="string">
|
||||
<text:p text:style-name="P14">Quantity</text:p>
|
||||
</table:table-cell>
|
||||
</table:table-row>
|
||||
</table:table-header-rows>
|
||||
<table:table-row>
|
||||
<table:table-cell table:style-name="Table1.A2" table:number-columns-spanned="2" office:value-type="string">
|
||||
<text:p text:style-name="P15"><text:placeholder text:placeholder-type="text"><for each="move in moves(shipment)"></text:placeholder></text:p>
|
||||
</table:table-cell>
|
||||
<table:covered-table-cell/>
|
||||
</table:table-row>
|
||||
<table:table-row>
|
||||
<table:table-cell table:style-name="Table1.A3" office:value-type="string">
|
||||
<text:p text:style-name="P17"><text:placeholder text:placeholder-type="text"><move.product_name></text:placeholder></text:p>
|
||||
</table:table-cell>
|
||||
<table:table-cell table:style-name="Table1.B3" office:value-type="string">
|
||||
<text:p text:style-name="P16"><text:placeholder text:placeholder-type="text"><format_number_symbol(move.quantity, shipment.delivery_address.party.lang, move.unit, digits=move.unit.digits)></text:placeholder></text:p>
|
||||
</table:table-cell>
|
||||
</table:table-row>
|
||||
<table:table-row>
|
||||
<table:table-cell table:style-name="Table1.A2" table:number-columns-spanned="2" office:value-type="string">
|
||||
<text:p text:style-name="P15"><text:placeholder text:placeholder-type="text"></for></text:placeholder></text:p>
|
||||
</table:table-cell>
|
||||
<table:covered-table-cell/>
|
||||
</table:table-row>
|
||||
</table:table>
|
||||
<text:p text:style-name="P13"><text:placeholder text:placeholder-type="text"></for></text:placeholder></text:p>
|
||||
</office:text>
|
||||
</office:body>
|
||||
</office:document>
|
||||
48
modules/stock/exceptions.py
Normal file
48
modules/stock/exceptions.py
Normal file
@@ -0,0 +1,48 @@
|
||||
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
from trytond.exceptions import UserError, UserWarning
|
||||
from trytond.model.exceptions import ValidationError
|
||||
|
||||
|
||||
class AssignError(UserError):
|
||||
pass
|
||||
|
||||
|
||||
class MoveValidationError(ValidationError):
|
||||
pass
|
||||
|
||||
|
||||
class LocationValidationError(ValidationError):
|
||||
pass
|
||||
|
||||
|
||||
class PeriodCloseError(UserError):
|
||||
pass
|
||||
|
||||
|
||||
class InventoryValidationError(ValidationError):
|
||||
pass
|
||||
|
||||
|
||||
class InventoryCountWarning(UserWarning):
|
||||
pass
|
||||
|
||||
|
||||
class MoveOriginWarning(UserWarning):
|
||||
pass
|
||||
|
||||
|
||||
class MoveFutureWarning(UserWarning):
|
||||
pass
|
||||
|
||||
|
||||
class ProductCostPriceError(ValidationError):
|
||||
pass
|
||||
|
||||
|
||||
class ProductStockWarning(UserWarning):
|
||||
pass
|
||||
|
||||
|
||||
class ShipmentCheckQuantityWarning(UserWarning):
|
||||
pass
|
||||
1
modules/stock/icons/tryton-shipment-in.svg
Normal file
1
modules/stock/icons/tryton-shipment-in.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M0 0h24v24H0z" fill="none"/><path d="M4 8h3V4h14c1.1 0 2 .9 2 2v11h-2c0 1.66-1.34 3-3 3s-3-1.34-3-3H9c0 1.66-1.34 3-3 3s-3-1.34-3-3H1v-5zm14 10.5c.83 0 1.5-.67 1.5-1.5s-.67-1.5-1.5-1.5-1.5.67-1.5 1.5.67 1.5 1.5 1.5zm-13.5-9L2.54 12H7V9.5zm1.5 9c.83 0 1.5-.67 1.5-1.5s-.67-1.5-1.5-1.5-1.5.67-1.5 1.5.67 1.5 1.5 1.5z"/></svg>
|
||||
|
After Width: | Height: | Size: 416 B |
1
modules/stock/icons/tryton-shipment-out.svg
Normal file
1
modules/stock/icons/tryton-shipment-out.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M0 0h24v24H0z" fill="none"/><path d="M20 8h-3V4H3c-1.1 0-2 .9-2 2v11h2c0 1.66 1.34 3 3 3s3-1.34 3-3h6c0 1.66 1.34 3 3 3s3-1.34 3-3h2v-5l-3-4zM6 18.5c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5zm13.5-9l1.96 2.5H17V9.5h2.5zm-1.5 9c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5z"/></svg>
|
||||
|
After Width: | Height: | Size: 426 B |
4
modules/stock/icons/tryton-stock.svg
Normal file
4
modules/stock/icons/tryton-stock.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
|
||||
<path d="M0 0h24v24H0z" fill="none"/>
|
||||
<path d="M19 7V4H5v3H2v13h8v-4h4v4h8V7h-3zm-8 3H9v1h2v1H8V9h2V8H8V7h3v3zm5 2h-1v-2h-2V7h1v2h1V7h1v5z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 241 B |
610
modules/stock/internal_shipment.fodt
Normal file
610
modules/stock/internal_shipment.fodt
Normal file
@@ -0,0 +1,610 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<office:document xmlns:css3t="http://www.w3.org/TR/css3-text/" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:rpt="http://openoffice.org/2005/report" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:officeooo="http://openoffice.org/2009/office" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.text">
|
||||
<office:meta><meta:generator>LibreOffice/7.6.4.1$Linux_X86_64 LibreOffice_project/60$Build-1</meta:generator><meta:initial-creator>Bertrand Chenal</meta:initial-creator><meta:creation-date>2009-03-26T13:54:48</meta:creation-date><dc:date>2024-04-19T23:16:19.369202166</dc:date><meta:editing-cycles>66</meta:editing-cycles><meta:editing-duration>PT7H29M8S</meta:editing-duration><meta:document-statistic meta:table-count="1" meta:image-count="0" meta:object-count="0" meta:page-count="3" meta:paragraph-count="41" meta:word-count="91" meta:character-count="1078" meta:non-whitespace-character-count="1027"/><meta:user-defined meta:name="Info 1"/><meta:user-defined meta:name="Info 2"/><meta:user-defined meta:name="Info 3"/><meta:user-defined meta:name="Info 4"/></office:meta>
|
||||
<office:settings>
|
||||
<config:config-item-set config:name="ooo:view-settings">
|
||||
<config:config-item config:name="ViewAreaTop" config:type="long">0</config:config-item>
|
||||
<config:config-item config:name="ViewAreaLeft" config:type="long">0</config:config-item>
|
||||
<config:config-item config:name="ViewAreaWidth" config:type="long">25269</config:config-item>
|
||||
<config:config-item config:name="ViewAreaHeight" config:type="long">23973</config:config-item>
|
||||
<config:config-item config:name="ShowRedlineChanges" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="InBrowseMode" config:type="boolean">false</config:config-item>
|
||||
<config:config-item-map-indexed config:name="Views">
|
||||
<config:config-item-map-entry>
|
||||
<config:config-item config:name="ViewId" config:type="string">view2</config:config-item>
|
||||
<config:config-item config:name="ViewLeft" config:type="long">5955</config:config-item>
|
||||
<config:config-item config:name="ViewTop" config:type="long">10248</config:config-item>
|
||||
<config:config-item config:name="VisibleLeft" config:type="long">0</config:config-item>
|
||||
<config:config-item config:name="VisibleTop" config:type="long">0</config:config-item>
|
||||
<config:config-item config:name="VisibleRight" config:type="long">25268</config:config-item>
|
||||
<config:config-item config:name="VisibleBottom" config:type="long">23971</config:config-item>
|
||||
<config:config-item config:name="ZoomType" config:type="short">0</config:config-item>
|
||||
<config:config-item config:name="ViewLayoutColumns" config:type="short">0</config:config-item>
|
||||
<config:config-item config:name="ViewLayoutBookMode" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="ZoomFactor" config:type="short">100</config:config-item>
|
||||
<config:config-item config:name="IsSelectedFrame" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="KeepRatio" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="AnchoredTextOverflowLegacy" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="LegacySingleLineFontwork" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="ConnectorUseSnapRect" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="IgnoreBreakAfterMultilineField" config:type="boolean">false</config:config-item>
|
||||
</config:config-item-map-entry>
|
||||
</config:config-item-map-indexed>
|
||||
</config:config-item-set>
|
||||
<config:config-item-set config:name="ooo:configuration-settings">
|
||||
<config:config-item config:name="PrintRightPages" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="PrintProspectRTL" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="PrintLeftPages" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="PrintPaperFromSetup" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="PrintControls" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="PrintProspect" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="PrintBlackFonts" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="PrintAnnotationMode" config:type="short">0</config:config-item>
|
||||
<config:config-item config:name="PrintEmptyPages" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="PrintSingleJobs" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="AutoFirstLineIndentDisregardLineSpace" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="HeaderSpacingBelowLastPara" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="ProtectBookmarks" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="ContinuousEndnotes" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="DisableOffPagePositioning" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="PrintTables" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="SubtractFlysAnchoredAtFlys" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="ApplyParagraphMarkFormatToNumbering" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="PrintFaxName" config:type="string"/>
|
||||
<config:config-item config:name="SurroundTextWrapSmall" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="TreatSingleColumnBreakAsPageBreak" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="PropLineSpacingShrinksFirstLine" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="TabOverSpacing" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="TabOverMargin" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="EmbedComplexScriptFonts" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="EmbedLatinScriptFonts" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="EmbedOnlyUsedFonts" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="EmbedFonts" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="ClippedPictures" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="FrameAutowidthWithMorePara" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="FloattableNomargins" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="UnbreakableNumberings" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="AllowPrintJobCancel" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="UseFormerObjectPositioning" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="UseOldNumbering" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="RsidRoot" config:type="int">1178252</config:config-item>
|
||||
<config:config-item config:name="PrinterPaperFromSetup" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="CurrentDatabaseDataSource" config:type="string"/>
|
||||
<config:config-item config:name="UpdateFromTemplate" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="AddFrameOffsets" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="LoadReadonly" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="Rsid" config:type="int">2325796</config:config-item>
|
||||
<config:config-item config:name="FootnoteInColumnToPageEnd" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="ProtectFields" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="SaveGlobalDocumentLinks" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="ClipAsCharacterAnchoredWriterFlyFrames" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="LinkUpdateMode" config:type="short">1</config:config-item>
|
||||
<config:config-item config:name="AddExternalLeading" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="PrintGraphics" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="EmbedSystemFonts" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="IsLabelDocument" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="AddParaLineSpacingToTableCells" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="UseFormerTextWrapping" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="HyphenateURLs" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="AddParaTableSpacingAtStart" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="TabsRelativeToIndent" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="FieldAutoUpdate" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="SaveVersionOnClose" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="ChartAutoUpdate" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="ImagePreferredDPI" config:type="int">0</config:config-item>
|
||||
<config:config-item config:name="PrinterSetup" config:type="base64Binary"/>
|
||||
<config:config-item config:name="SmallCapsPercentage66" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="AlignTabStopPosition" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="DropCapPunctuation" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="MathBaselineAlignment" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="PrinterName" config:type="string"/>
|
||||
<config:config-item config:name="CharacterCompressionType" config:type="short">0</config:config-item>
|
||||
<config:config-item config:name="AddParaTableSpacing" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="DoNotJustifyLinesWithManualBreak" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="PrintHiddenText" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="IsKernAsianPunctuation" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="PrinterIndependentLayout" config:type="string">high-resolution</config:config-item>
|
||||
<config:config-item config:name="TabOverflow" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="AddParaSpacingToTableCells" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="AddVerticalFrameOffsets" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="TabAtLeftIndentForParagraphsInList" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="ApplyUserData" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="MsWordCompMinLineHeightByFly" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="PrintTextPlaceholder" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="IgnoreFirstLineIndentInNumbering" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="UseFormerLineSpacing" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="PrintPageBackground" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="RedlineProtectionKey" config:type="base64Binary"/>
|
||||
<config:config-item config:name="EmbedAsianScriptFonts" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="BackgroundParaOverDrawings" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="SaveThumbnail" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="ConsiderTextWrapOnObjPos" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="EmbeddedDatabaseName" config:type="string"/>
|
||||
<config:config-item config:name="ProtectForm" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="DoNotResetParaAttrsForNumFont" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="MsWordCompTrailingBlanks" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="EmptyDbFieldHidesPara" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="TableRowKeep" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="NoNumberingShowFollowBy" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="InvertBorderSpacing" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="IgnoreTabsAndBlanksForLineCalculation" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="DoNotCaptureDrawObjsOnPage" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="GutterAtTop" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="StylesNoDefault" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="UnxForceZeroExtLeading" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="PrintReversed" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="UseOldPrinterMetrics" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="CurrentDatabaseCommandType" config:type="int">0</config:config-item>
|
||||
<config:config-item config:name="PrintDrawings" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="OutlineLevelYieldsNumbering" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="CurrentDatabaseCommand" config:type="string"/>
|
||||
<config:config-item config:name="CollapseEmptyCellPara" config:type="boolean">true</config:config-item>
|
||||
</config:config-item-set>
|
||||
</office:settings>
|
||||
<office:scripts>
|
||||
<office:script script:language="ooo:Basic">
|
||||
<ooo:libraries xmlns:ooo="http://openoffice.org/2004/office" xmlns:xlink="http://www.w3.org/1999/xlink"/>
|
||||
</office:script>
|
||||
</office:scripts>
|
||||
<office:font-face-decls>
|
||||
<style:font-face style:name="Andale Sans UI" svg:font-family="'Andale Sans UI'" style:font-family-generic="system" style:font-pitch="variable"/>
|
||||
<style:font-face style:name="DejaVu Sans" svg:font-family="'DejaVu Sans'" style:font-family-generic="system" style:font-pitch="variable"/>
|
||||
<style:font-face style:name="Liberation Sans" svg:font-family="'Liberation Sans'" style:font-adornments="Regular" style:font-family-generic="swiss" style:font-pitch="variable"/>
|
||||
<style:font-face style:name="Liberation Serif" svg:font-family="'Liberation Serif'" style:font-family-generic="roman" style:font-pitch="variable"/>
|
||||
<style:font-face style:name="Liberation Serif1" svg:font-family="'Liberation Serif'" style:font-adornments="Bold" style:font-family-generic="roman" style:font-pitch="variable"/>
|
||||
<style:font-face style:name="Liberation Serif2" svg:font-family="'Liberation Serif'" style:font-adornments="Regular" style:font-family-generic="roman" style:font-pitch="variable"/>
|
||||
<style:font-face style:name="StarSymbol" svg:font-family="StarSymbol"/>
|
||||
<style:font-face style:name="Thorndale AMT" svg:font-family="'Thorndale AMT'" style:font-family-generic="roman" style:font-pitch="variable"/>
|
||||
</office:font-face-decls>
|
||||
<office:styles>
|
||||
<style:default-style style:family="graphic">
|
||||
<style:graphic-properties svg:stroke-color="#000000" draw:fill-color="#99ccff" fo:wrap-option="no-wrap" draw:shadow-offset-x="0.3cm" draw:shadow-offset-y="0.3cm" draw:start-line-spacing-horizontal="0.283cm" draw:start-line-spacing-vertical="0.283cm" draw:end-line-spacing-horizontal="0.283cm" draw:end-line-spacing-vertical="0.283cm" style:writing-mode="lr-tb" style:flow-with-text="false"/>
|
||||
<style:paragraph-properties style:text-autospace="ideograph-alpha" style:line-break="strict" loext:tab-stop-distance="0cm" style:font-independent-line-spacing="false">
|
||||
<style:tab-stops/>
|
||||
</style:paragraph-properties>
|
||||
<style:text-properties style:use-window-font-color="true" loext:opacity="0%" style:font-name="Thorndale AMT" fo:font-size="12pt" fo:language="en" fo:country="US" style:letter-kerning="true" style:font-name-asian="Andale Sans UI" style:font-size-asian="10.5pt" style:language-asian="zxx" style:country-asian="none" style:font-name-complex="Andale Sans UI" style:font-size-complex="12pt" style:language-complex="zxx" style:country-complex="none"/>
|
||||
</style:default-style>
|
||||
<style:default-style style:family="paragraph">
|
||||
<style:paragraph-properties fo:hyphenation-ladder-count="no-limit" style:text-autospace="ideograph-alpha" style:punctuation-wrap="hanging" style:line-break="strict" style:tab-stop-distance="1.251cm" style:writing-mode="lr-tb"/>
|
||||
<style:text-properties style:use-window-font-color="true" loext:opacity="0%" style:font-name="Thorndale AMT" fo:font-size="12pt" fo:language="en" fo:country="US" style:letter-kerning="true" style:font-name-asian="Andale Sans UI" style:font-size-asian="10.5pt" style:language-asian="zxx" style:country-asian="none" style:font-name-complex="Andale Sans UI" style:font-size-complex="12pt" style:language-complex="zxx" style:country-complex="none" fo:hyphenate="false" fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2" loext:hyphenation-no-caps="false" loext:hyphenation-no-last-word="false" loext:hyphenation-word-char-count="5" loext:hyphenation-zone="no-limit"/>
|
||||
</style:default-style>
|
||||
<style:default-style style:family="table">
|
||||
<style:table-properties table:border-model="collapsing"/>
|
||||
</style:default-style>
|
||||
<style:default-style style:family="table-row">
|
||||
<style:table-row-properties fo:keep-together="auto"/>
|
||||
</style:default-style>
|
||||
<style:style style:name="Standard" style:family="paragraph" style:class="text">
|
||||
<style:text-properties style:font-name="Liberation Sans" fo:font-family="'Liberation Sans'" style:font-style-name="Regular" style:font-family-generic="swiss" style:font-pitch="variable" style:font-size-asian="10.5pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="Heading" style:family="paragraph" style:parent-style-name="Standard" style:next-style-name="Text_20_body" style:class="text">
|
||||
<style:paragraph-properties fo:margin-top="0.423cm" fo:margin-bottom="0.212cm" style:contextual-spacing="false" fo:keep-with-next="always"/>
|
||||
<style:text-properties style:font-name="Liberation Serif2" fo:font-family="'Liberation Serif'" style:font-style-name="Regular" style:font-family-generic="roman" style:font-pitch="variable" fo:font-size="16pt" style:font-name-asian="DejaVu Sans" style:font-family-asian="'DejaVu Sans'" style:font-family-generic-asian="system" style:font-pitch-asian="variable" style:font-size-asian="14pt" style:font-name-complex="DejaVu Sans" style:font-family-complex="'DejaVu Sans'" style:font-family-generic-complex="system" style:font-pitch-complex="variable" style:font-size-complex="14pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="Text_20_body" style:display-name="Text body" style:family="paragraph" style:parent-style-name="Standard" style:class="text">
|
||||
<style:paragraph-properties fo:margin-top="0cm" fo:margin-bottom="0.212cm" style:contextual-spacing="false"/>
|
||||
<style:text-properties style:font-name="Liberation Sans" fo:font-family="'Liberation Sans'" style:font-style-name="Regular" style:font-family-generic="swiss" style:font-pitch="variable" style:font-size-asian="10.5pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="List" style:family="paragraph" style:parent-style-name="Text_20_body" style:class="list">
|
||||
<style:text-properties style:font-size-asian="12pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="Caption" style:family="paragraph" style:parent-style-name="Standard" style:class="extra">
|
||||
<style:paragraph-properties fo:margin-top="0.212cm" fo:margin-bottom="0.212cm" style:contextual-spacing="false" text:number-lines="false" text:line-number="0"/>
|
||||
<style:text-properties fo:font-size="12pt" fo:font-style="italic" style:font-size-asian="12pt" style:font-style-asian="italic" style:font-size-complex="12pt" style:font-style-complex="italic"/>
|
||||
</style:style>
|
||||
<style:style style:name="Index" style:family="paragraph" style:parent-style-name="Standard" style:class="index">
|
||||
<style:paragraph-properties text:number-lines="false" text:line-number="0"/>
|
||||
<style:text-properties style:font-size-asian="12pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="Heading_20_1" style:display-name="Heading 1" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:class="text">
|
||||
<style:text-properties fo:font-size="16pt" fo:font-weight="bold" style:font-size-asian="115%" style:font-weight-asian="bold" style:font-size-complex="115%" style:font-weight-complex="bold"/>
|
||||
</style:style>
|
||||
<style:style style:name="Table_20_Contents" style:display-name="Table Contents" style:family="paragraph" style:parent-style-name="Standard" style:class="extra">
|
||||
<style:paragraph-properties text:number-lines="false" text:line-number="0"/>
|
||||
<style:text-properties style:font-size-asian="10.5pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="Table_20_Heading" style:display-name="Table Heading" style:family="paragraph" style:parent-style-name="Table_20_Contents" style:class="extra" style:master-page-name="">
|
||||
<style:paragraph-properties fo:text-align="center" style:justify-single-word="false" style:page-number="auto" text:number-lines="false" text:line-number="0"/>
|
||||
<style:text-properties style:font-name="Liberation Serif1" fo:font-family="'Liberation Serif'" style:font-style-name="Bold" style:font-family-generic="roman" style:font-pitch="variable" fo:font-weight="bold" style:font-size-asian="10.5pt" style:font-weight-asian="bold" style:font-weight-complex="bold"/>
|
||||
</style:style>
|
||||
<style:style style:name="Header_20_and_20_Footer" style:display-name="Header and Footer" style:family="paragraph" style:parent-style-name="Standard" style:class="extra">
|
||||
<style:paragraph-properties text:number-lines="false" text:line-number="0">
|
||||
<style:tab-stops>
|
||||
<style:tab-stop style:position="8.5cm" style:type="center"/>
|
||||
<style:tab-stop style:position="17cm" style:type="right"/>
|
||||
</style:tab-stops>
|
||||
</style:paragraph-properties>
|
||||
</style:style>
|
||||
<style:style style:name="Header" style:family="paragraph" style:parent-style-name="Standard" style:class="extra">
|
||||
<style:paragraph-properties text:number-lines="false" text:line-number="0">
|
||||
<style:tab-stops>
|
||||
<style:tab-stop style:position="8.795cm" style:type="center"/>
|
||||
<style:tab-stop style:position="17.59cm" style:type="right"/>
|
||||
</style:tab-stops>
|
||||
</style:paragraph-properties>
|
||||
<style:text-properties fo:font-size="9pt" style:font-size-asian="10.5pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="Heading_20_2" style:display-name="Heading 2" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:class="text">
|
||||
<style:text-properties fo:font-size="14pt" fo:font-style="italic" fo:font-weight="bold" style:font-size-asian="14pt" style:font-style-asian="italic" style:font-weight-asian="bold" style:font-size-complex="14pt" style:font-style-complex="italic" style:font-weight-complex="bold"/>
|
||||
</style:style>
|
||||
<style:style style:name="Footer" style:family="paragraph" style:parent-style-name="Standard" style:class="extra">
|
||||
<style:paragraph-properties text:number-lines="false" text:line-number="0">
|
||||
<style:tab-stops>
|
||||
<style:tab-stop style:position="8.795cm" style:type="center"/>
|
||||
<style:tab-stop style:position="17.59cm" style:type="right"/>
|
||||
</style:tab-stops>
|
||||
</style:paragraph-properties>
|
||||
<style:text-properties fo:font-size="9pt" style:font-size-asian="10.5pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="Heading_20_3" style:display-name="Heading 3" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:class="text">
|
||||
<style:text-properties fo:font-size="14pt" fo:font-weight="bold" style:font-size-asian="14pt" style:font-weight-asian="bold" style:font-size-complex="14pt" style:font-weight-complex="bold"/>
|
||||
</style:style>
|
||||
<style:style style:name="Text_20_body_20_indent" style:display-name="Text body indent" style:family="paragraph" style:parent-style-name="Text_20_body" style:class="text">
|
||||
<style:paragraph-properties fo:margin-left="0.499cm" fo:margin-right="0cm" fo:margin-top="0cm" fo:margin-bottom="0cm" style:contextual-spacing="false" fo:text-indent="0cm" style:auto-text-indent="false"/>
|
||||
</style:style>
|
||||
<style:style style:name="Text" style:family="paragraph" style:parent-style-name="Caption" style:class="extra"/>
|
||||
<style:style style:name="Quotations" style:family="paragraph" style:parent-style-name="Standard" style:class="html">
|
||||
<style:paragraph-properties fo:margin-left="1cm" fo:margin-right="1cm" fo:margin-top="0cm" fo:margin-bottom="0.499cm" style:contextual-spacing="false" fo:text-indent="0cm" style:auto-text-indent="false"/>
|
||||
</style:style>
|
||||
<style:style style:name="Title" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:class="chapter">
|
||||
<style:paragraph-properties fo:text-align="center" style:justify-single-word="false"/>
|
||||
<style:text-properties fo:font-size="28pt" fo:font-weight="bold" style:font-size-asian="28pt" style:font-weight-asian="bold" style:font-size-complex="28pt" style:font-weight-complex="bold"/>
|
||||
</style:style>
|
||||
<style:style style:name="Subtitle" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:class="chapter">
|
||||
<style:paragraph-properties fo:margin-top="0.106cm" fo:margin-bottom="0.212cm" style:contextual-spacing="false" fo:text-align="center" style:justify-single-word="false"/>
|
||||
<style:text-properties fo:font-size="18pt" style:font-size-asian="18pt" style:font-size-complex="18pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="Frame_20_contents" style:display-name="Frame contents" style:family="paragraph" style:parent-style-name="Standard" style:class="extra"/>
|
||||
<style:style style:name="Placeholder" style:family="text">
|
||||
<style:text-properties fo:font-variant="small-caps" fo:color="#008080" loext:opacity="100%" style:text-underline-style="dotted" style:text-underline-width="auto" style:text-underline-color="font-color"/>
|
||||
</style:style>
|
||||
<style:style style:name="Bullet_20_Symbols" style:display-name="Bullet Symbols" style:family="text">
|
||||
<style:text-properties style:font-name="StarSymbol" fo:font-family="StarSymbol" fo:font-size="9pt" style:font-name-asian="StarSymbol" style:font-family-asian="StarSymbol" style:font-size-asian="9pt" style:font-name-complex="StarSymbol" style:font-family-complex="StarSymbol" style:font-size-complex="9pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="Frame" style:family="graphic">
|
||||
<style:graphic-properties text:anchor-type="paragraph" svg:x="0cm" svg:y="0cm" fo:margin-left="0.201cm" fo:margin-right="0.201cm" fo:margin-top="0.201cm" fo:margin-bottom="0.201cm" style:wrap="parallel" style:number-wrapped-paragraphs="no-limit" style:wrap-contour="false" style:vertical-pos="top" style:vertical-rel="paragraph-content" style:horizontal-pos="center" style:horizontal-rel="paragraph-content" fo:background-color="transparent" draw:fill="none" draw:fill-color="#99ccff" fo:padding="0.15cm" fo:border="0.06pt solid #000000"/>
|
||||
</style:style>
|
||||
<text:outline-style style:name="Outline">
|
||||
<text:outline-level-style text:level="1" loext:num-list-format="%1%" style:num-format="">
|
||||
<style:list-level-properties text:min-label-distance="0.381cm"/>
|
||||
</text:outline-level-style>
|
||||
<text:outline-level-style text:level="2" loext:num-list-format="%2%" style:num-format="">
|
||||
<style:list-level-properties text:min-label-distance="0.381cm"/>
|
||||
</text:outline-level-style>
|
||||
<text:outline-level-style text:level="3" loext:num-list-format="%3%" style:num-format="">
|
||||
<style:list-level-properties text:min-label-distance="0.381cm"/>
|
||||
</text:outline-level-style>
|
||||
<text:outline-level-style text:level="4" loext:num-list-format="%4%" style:num-format="">
|
||||
<style:list-level-properties text:min-label-distance="0.381cm"/>
|
||||
</text:outline-level-style>
|
||||
<text:outline-level-style text:level="5" loext:num-list-format="%5%" style:num-format="">
|
||||
<style:list-level-properties text:min-label-distance="0.381cm"/>
|
||||
</text:outline-level-style>
|
||||
<text:outline-level-style text:level="6" loext:num-list-format="%6%" style:num-format="">
|
||||
<style:list-level-properties text:min-label-distance="0.381cm"/>
|
||||
</text:outline-level-style>
|
||||
<text:outline-level-style text:level="7" loext:num-list-format="%7%" style:num-format="">
|
||||
<style:list-level-properties text:min-label-distance="0.381cm"/>
|
||||
</text:outline-level-style>
|
||||
<text:outline-level-style text:level="8" loext:num-list-format="%8%" style:num-format="">
|
||||
<style:list-level-properties text:min-label-distance="0.381cm"/>
|
||||
</text:outline-level-style>
|
||||
<text:outline-level-style text:level="9" loext:num-list-format="%9%" style:num-format="">
|
||||
<style:list-level-properties text:min-label-distance="0.381cm"/>
|
||||
</text:outline-level-style>
|
||||
<text:outline-level-style text:level="10" loext:num-list-format="%10%" style:num-format="">
|
||||
<style:list-level-properties text:min-label-distance="0.381cm"/>
|
||||
</text:outline-level-style>
|
||||
</text:outline-style>
|
||||
<text:notes-configuration text:note-class="footnote" style:num-format="1" text:start-value="0" text:footnotes-position="page" text:start-numbering-at="document"/>
|
||||
<text:notes-configuration text:note-class="endnote" style:num-format="i" text:start-value="0"/>
|
||||
<text:linenumbering-configuration text:number-lines="false" text:offset="0.499cm" style:num-format="1" text:number-position="left" text:increment="5"/>
|
||||
<loext:theme loext:name="Office Theme">
|
||||
<loext:theme-colors loext:name="LibreOffice">
|
||||
<loext:color loext:name="dark1" loext:color="#000000"/>
|
||||
<loext:color loext:name="light1" loext:color="#ffffff"/>
|
||||
<loext:color loext:name="dark2" loext:color="#000000"/>
|
||||
<loext:color loext:name="light2" loext:color="#ffffff"/>
|
||||
<loext:color loext:name="accent1" loext:color="#18a303"/>
|
||||
<loext:color loext:name="accent2" loext:color="#0369a3"/>
|
||||
<loext:color loext:name="accent3" loext:color="#a33e03"/>
|
||||
<loext:color loext:name="accent4" loext:color="#8e03a3"/>
|
||||
<loext:color loext:name="accent5" loext:color="#c99c00"/>
|
||||
<loext:color loext:name="accent6" loext:color="#c9211e"/>
|
||||
<loext:color loext:name="hyperlink" loext:color="#0000ee"/>
|
||||
<loext:color loext:name="followed-hyperlink" loext:color="#551a8b"/>
|
||||
</loext:theme-colors>
|
||||
</loext:theme>
|
||||
</office:styles>
|
||||
<office:automatic-styles>
|
||||
<style:style style:name="Table1" style:family="table">
|
||||
<style:table-properties style:width="16.999cm" fo:margin-left="0cm" fo:margin-right="0cm" fo:margin-top="0.381cm" fo:margin-bottom="0cm" table:align="margins"/>
|
||||
</style:style>
|
||||
<style:style style:name="Table1.A" style:family="table-column">
|
||||
<style:table-column-properties style:column-width="4.683cm" style:rel-column-width="18053*"/>
|
||||
</style:style>
|
||||
<style:style style:name="Table1.C" style:family="table-column">
|
||||
<style:table-column-properties style:column-width="4.685cm" style:rel-column-width="18060*"/>
|
||||
</style:style>
|
||||
<style:style style:name="Table1.D" style:family="table-column">
|
||||
<style:table-column-properties style:column-width="2.949cm" style:rel-column-width="11369*"/>
|
||||
</style:style>
|
||||
<style:style style:name="Table1.A1" style:family="table-cell">
|
||||
<style:table-cell-properties fo:background-color="#cccccc" fo:padding="0.097cm" fo:border-left="0.05pt solid #000000" fo:border-right="none" fo:border-top="0.05pt solid #000000" fo:border-bottom="0.05pt solid #000000">
|
||||
<style:background-image/>
|
||||
</style:table-cell-properties>
|
||||
</style:style>
|
||||
<style:style style:name="Table1.D1" style:family="table-cell">
|
||||
<style:table-cell-properties fo:background-color="#cccccc" fo:padding="0.097cm" fo:border="0.05pt solid #000000">
|
||||
<style:background-image/>
|
||||
</style:table-cell-properties>
|
||||
</style:style>
|
||||
<style:style style:name="Table1.A2" style:family="table-cell">
|
||||
<style:table-cell-properties fo:padding="0.097cm" fo:border-left="0.05pt solid #000000" fo:border-right="none" fo:border-top="none" fo:border-bottom="0.05pt solid #000000"/>
|
||||
</style:style>
|
||||
<style:style style:name="Table1.C2" style:family="table-cell">
|
||||
<style:table-cell-properties fo:padding="0.097cm" fo:border-left="0.05pt solid #000000" fo:border-right="none" fo:border-top="none" fo:border-bottom="0.05pt solid #000000"/>
|
||||
</style:style>
|
||||
<style:style style:name="Table1.D2" style:family="table-cell">
|
||||
<style:table-cell-properties fo:padding="0.097cm" fo:border-left="0.05pt solid #000000" fo:border-right="0.05pt solid #000000" fo:border-top="none" fo:border-bottom="0.05pt solid #000000"/>
|
||||
</style:style>
|
||||
<style:style style:name="Table1.A3" style:family="table-cell">
|
||||
<style:table-cell-properties fo:padding="0.097cm" fo:border-left="0.05pt solid #000000" fo:border-right="none" fo:border-top="none" fo:border-bottom="0.05pt solid #000000"/>
|
||||
</style:style>
|
||||
<style:style style:name="Table1.B3" style:family="table-cell">
|
||||
<style:table-cell-properties fo:padding="0.097cm" fo:border-left="0.05pt solid #000000" fo:border-right="none" fo:border-top="none" fo:border-bottom="0.05pt solid #000000"/>
|
||||
</style:style>
|
||||
<style:style style:name="Table1.C3" style:family="table-cell">
|
||||
<style:table-cell-properties fo:padding="0.097cm" fo:border-left="0.05pt solid #000000" fo:border-right="none" fo:border-top="none" fo:border-bottom="0.05pt solid #000000"/>
|
||||
</style:style>
|
||||
<style:style style:name="Table1.D3" style:family="table-cell">
|
||||
<style:table-cell-properties fo:padding="0.097cm" fo:border-left="0.05pt solid #000000" fo:border-right="0.05pt solid #000000" fo:border-top="none" fo:border-bottom="0.05pt solid #000000"/>
|
||||
</style:style>
|
||||
<style:style style:name="Table1.A4" style:family="table-cell">
|
||||
<style:table-cell-properties fo:padding="0.097cm" fo:border-left="0.05pt solid #000000" fo:border-right="none" fo:border-top="none" fo:border-bottom="0.05pt solid #000000"/>
|
||||
</style:style>
|
||||
<style:style style:name="Table1.C4" style:family="table-cell">
|
||||
<style:table-cell-properties fo:padding="0.097cm" fo:border-left="0.05pt solid #000000" fo:border-right="none" fo:border-top="none" fo:border-bottom="0.05pt solid #000000"/>
|
||||
</style:style>
|
||||
<style:style style:name="Table1.D4" style:family="table-cell">
|
||||
<style:table-cell-properties fo:padding="0.097cm" fo:border-left="0.05pt solid #000000" fo:border-right="0.05pt solid #000000" fo:border-top="none" fo:border-bottom="0.05pt solid #000000"/>
|
||||
</style:style>
|
||||
<style:style style:name="P1" style:family="paragraph" style:parent-style-name="Header">
|
||||
<style:paragraph-properties fo:text-align="center" style:justify-single-word="false"/>
|
||||
<style:text-properties officeooo:paragraph-rsid="0019177b"/>
|
||||
</style:style>
|
||||
<style:style style:name="P2" style:family="paragraph" style:parent-style-name="Footer">
|
||||
<style:paragraph-properties fo:text-align="center" style:justify-single-word="false"/>
|
||||
<style:text-properties officeooo:paragraph-rsid="0019177b"/>
|
||||
</style:style>
|
||||
<style:style style:name="P3" style:family="paragraph" style:parent-style-name="Header">
|
||||
<style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/>
|
||||
<style:text-properties fo:font-size="12pt" officeooo:paragraph-rsid="00237d24" style:font-size-asian="12pt" style:font-size-complex="12pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="P4" style:family="paragraph" style:parent-style-name="Frame_20_contents">
|
||||
<style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/>
|
||||
</style:style>
|
||||
<style:style style:name="P5" style:family="paragraph" style:parent-style-name="Footer">
|
||||
<style:paragraph-properties fo:text-align="end" style:justify-single-word="false"/>
|
||||
</style:style>
|
||||
<style:style style:name="P6" style:family="paragraph" style:parent-style-name="Header">
|
||||
<style:paragraph-properties fo:text-align="center" style:justify-single-word="false"/>
|
||||
<style:text-properties officeooo:paragraph-rsid="0019177b"/>
|
||||
</style:style>
|
||||
<style:style style:name="P7" style:family="paragraph" style:parent-style-name="Footer">
|
||||
<style:paragraph-properties fo:text-align="center" style:justify-single-word="false"/>
|
||||
<style:text-properties officeooo:paragraph-rsid="0019177b"/>
|
||||
</style:style>
|
||||
<style:style style:name="P8" style:family="paragraph" style:parent-style-name="Footer">
|
||||
<style:paragraph-properties fo:text-align="center" style:justify-single-word="false"/>
|
||||
<style:text-properties officeooo:paragraph-rsid="001ff59d"/>
|
||||
</style:style>
|
||||
<style:style style:name="P9" style:family="paragraph" style:parent-style-name="Heading_20_1">
|
||||
<style:paragraph-properties fo:text-align="center" style:justify-single-word="false"/>
|
||||
</style:style>
|
||||
<style:style style:name="P10" style:family="paragraph" style:parent-style-name="Header">
|
||||
<style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/>
|
||||
<style:text-properties fo:font-size="12pt" officeooo:paragraph-rsid="001ff59d" style:font-size-asian="12pt" style:font-size-complex="12pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="P11" style:family="paragraph" style:parent-style-name="Header">
|
||||
<style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/>
|
||||
<style:text-properties fo:font-size="12pt" officeooo:paragraph-rsid="0019177b" style:font-size-asian="12pt" style:font-size-complex="12pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="P12" style:family="paragraph" style:parent-style-name="Frame_20_contents">
|
||||
<style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/>
|
||||
</style:style>
|
||||
<style:style style:name="P13" style:family="paragraph" style:parent-style-name="Footer">
|
||||
<style:paragraph-properties fo:text-align="end" style:justify-single-word="false"/>
|
||||
</style:style>
|
||||
<style:style style:name="P14" style:family="paragraph" style:parent-style-name="Table_20_Contents">
|
||||
<style:paragraph-properties fo:text-align="end" style:justify-single-word="false"/>
|
||||
</style:style>
|
||||
<style:style style:name="P15" style:family="paragraph" style:parent-style-name="Standard">
|
||||
<style:paragraph-properties fo:margin-left="11.25cm" fo:margin-right="0cm" fo:text-align="end" style:justify-single-word="false" fo:text-indent="0cm" style:auto-text-indent="false"/>
|
||||
</style:style>
|
||||
<style:style style:name="P16" style:family="paragraph" style:parent-style-name="Standard" style:master-page-name="">
|
||||
<style:paragraph-properties fo:margin-left="11.25cm" fo:margin-right="0cm" fo:text-align="end" style:justify-single-word="false" fo:text-indent="0cm" style:auto-text-indent="false" style:page-number="auto" fo:break-before="page"/>
|
||||
</style:style>
|
||||
<style:style style:name="P17" style:family="paragraph" style:parent-style-name="Table_20_Heading">
|
||||
<style:paragraph-properties fo:text-align="center" style:justify-single-word="false"/>
|
||||
<style:text-properties style:font-name="Liberation Serif"/>
|
||||
</style:style>
|
||||
<style:style style:name="P18" style:family="paragraph" style:parent-style-name="Table_20_Contents">
|
||||
<style:text-properties style:font-name="Liberation Serif"/>
|
||||
</style:style>
|
||||
<style:style style:name="P19" style:family="paragraph" style:parent-style-name="Standard">
|
||||
<style:paragraph-properties fo:break-before="page"/>
|
||||
</style:style>
|
||||
<style:style style:name="P20" style:family="paragraph" style:parent-style-name="Standard">
|
||||
<style:text-properties officeooo:paragraph-rsid="00139706"/>
|
||||
</style:style>
|
||||
<style:style style:name="P21" style:family="paragraph" style:parent-style-name="Heading_20_1">
|
||||
<style:paragraph-properties fo:text-align="center" style:justify-single-word="false"/>
|
||||
<style:text-properties style:text-underline-style="solid" style:text-underline-width="auto" style:text-underline-color="font-color" fo:font-weight="bold" style:font-weight-asian="bold" style:font-weight-complex="bold"/>
|
||||
</style:style>
|
||||
<style:style style:name="P22" style:family="paragraph" style:parent-style-name="Standard" style:master-page-name="">
|
||||
<style:paragraph-properties fo:margin-left="0cm" fo:margin-right="0cm" fo:text-align="start" style:justify-single-word="false" fo:text-indent="0cm" style:auto-text-indent="false" style:page-number="auto" fo:break-before="page"/>
|
||||
<style:text-properties fo:font-size="6pt" style:font-size-asian="5.25pt" style:font-size-complex="6pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="P23" style:family="paragraph" style:parent-style-name="Frame_20_contents">
|
||||
<style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/>
|
||||
</style:style>
|
||||
<style:style style:name="P24" style:family="paragraph" style:parent-style-name="Header">
|
||||
<style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/>
|
||||
<style:text-properties fo:font-size="12pt" officeooo:paragraph-rsid="00237d24" style:font-size-asian="12pt" style:font-size-complex="12pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="T1" style:family="text">
|
||||
<style:text-properties fo:font-weight="bold" style:font-weight-asian="bold" style:font-weight-complex="bold"/>
|
||||
</style:style>
|
||||
<style:style style:name="T2" style:family="text">
|
||||
<style:text-properties fo:font-weight="bold" officeooo:rsid="001d148e" style:font-weight-asian="bold" style:font-weight-complex="bold"/>
|
||||
</style:style>
|
||||
<style:style style:name="T3" style:family="text">
|
||||
<style:text-properties fo:font-weight="normal" style:font-weight-asian="normal" style:font-weight-complex="normal"/>
|
||||
</style:style>
|
||||
<style:style style:name="T4" style:family="text">
|
||||
<style:text-properties officeooo:rsid="001f6b1d"/>
|
||||
</style:style>
|
||||
<style:style style:name="T5" style:family="text">
|
||||
<style:text-properties style:text-underline-style="solid" style:text-underline-width="auto" style:text-underline-color="font-color" fo:font-weight="bold" style:font-weight-asian="bold" style:font-weight-complex="bold"/>
|
||||
</style:style>
|
||||
<style:style style:name="T6" style:family="text">
|
||||
<style:text-properties style:text-underline-style="solid" style:text-underline-width="auto" style:text-underline-color="font-color" fo:font-weight="bold" officeooo:rsid="001f6b1d" style:font-weight-asian="bold" style:font-weight-complex="bold"/>
|
||||
</style:style>
|
||||
<style:style style:name="fr1" style:family="graphic" style:parent-style-name="Frame">
|
||||
<style:graphic-properties fo:margin-left="0cm" fo:margin-right="0cm" fo:margin-top="0cm" fo:margin-bottom="0cm" style:wrap="parallel" style:number-wrapped-paragraphs="no-limit" style:vertical-pos="middle" style:vertical-rel="baseline" style:horizontal-pos="left" style:horizontal-rel="paragraph" draw:opacity="100%" fo:padding="0cm" fo:border="none" draw:wrap-influence-on-position="once-concurrent" loext:allow-overlap="true">
|
||||
<style:columns fo:column-count="1" fo:column-gap="0cm"/>
|
||||
</style:graphic-properties>
|
||||
</style:style>
|
||||
<style:page-layout style:name="pm1">
|
||||
<style:page-layout-properties fo:page-width="20.999cm" fo:page-height="29.699cm" style:num-format="1" style:print-orientation="portrait" fo:margin-top="2cm" fo:margin-bottom="2cm" fo:margin-left="2cm" fo:margin-right="2cm" style:writing-mode="lr-tb" style:layout-grid-color="#c0c0c0" style:layout-grid-lines="20" style:layout-grid-base-height="0.706cm" style:layout-grid-ruby-height="0.353cm" style:layout-grid-mode="none" style:layout-grid-ruby-below="false" style:layout-grid-print="false" style:layout-grid-display="false" style:footnote-max-height="0cm" loext:margin-gutter="0cm">
|
||||
<style:footnote-sep style:width="0.018cm" style:distance-before-sep="0.101cm" style:distance-after-sep="0.101cm" style:line-style="none" style:adjustment="left" style:rel-width="25%" style:color="#000000"/>
|
||||
</style:page-layout-properties>
|
||||
<style:header-style>
|
||||
<style:header-footer-properties fo:min-height="0cm" fo:margin-left="0cm" fo:margin-right="0cm" fo:margin-bottom="0.499cm"/>
|
||||
</style:header-style>
|
||||
<style:footer-style>
|
||||
<style:header-footer-properties fo:min-height="0cm" fo:margin-left="0cm" fo:margin-right="0cm" fo:margin-top="0.499cm"/>
|
||||
</style:footer-style>
|
||||
</style:page-layout>
|
||||
<style:style style:name="dp1" style:family="drawing-page">
|
||||
<style:drawing-page-properties draw:background-size="full"/>
|
||||
</style:style>
|
||||
</office:automatic-styles>
|
||||
<office:master-styles>
|
||||
<style:master-page style:name="Standard" style:page-layout-name="pm1" draw:style-name="dp1">
|
||||
<style:header>
|
||||
<text:p text:style-name="P1"><text:placeholder text:placeholder-type="text"><if test="company and company.header"></text:placeholder></text:p>
|
||||
<text:p text:style-name="P1"><text:placeholder text:placeholder-type="text"><for each="line in company.header_used.split('\n')"></text:placeholder></text:p>
|
||||
<text:p text:style-name="P1"><text:placeholder text:placeholder-type="text"><line></text:placeholder></text:p>
|
||||
<text:p text:style-name="P1"><text:placeholder text:placeholder-type="text"></for></text:placeholder></text:p>
|
||||
<text:p text:style-name="P2"><text:placeholder text:placeholder-type="text"></if></text:placeholder></text:p>
|
||||
<text:p text:style-name="P3"><text:placeholder text:placeholder-type="text"><choose></text:placeholder></text:p>
|
||||
<text:p text:style-name="P3"><text:placeholder text:placeholder-type="text"><when test="company and company.logo"></text:placeholder></text:p>
|
||||
<text:p text:style-name="P3"><draw:frame draw:style-name="fr1" draw:name="image:company.get_logo_cm(7, 3.5)" text:anchor-type="as-char" svg:width="7.001cm" draw:z-index="2">
|
||||
<draw:text-box fo:min-height="3cm">
|
||||
<text:p text:style-name="P4"/>
|
||||
</draw:text-box>
|
||||
</draw:frame></text:p>
|
||||
<text:p text:style-name="P3"><text:placeholder text:placeholder-type="text"></when></text:placeholder></text:p>
|
||||
<text:p text:style-name="P3"><text:placeholder text:placeholder-type="text"><when test="company"></text:placeholder></text:p>
|
||||
<text:p text:style-name="P3"><text:placeholder text:placeholder-type="text"><company.rec_name></text:placeholder></text:p>
|
||||
<text:p text:style-name="P3"><text:placeholder text:placeholder-type="text"></when></text:placeholder></text:p>
|
||||
<text:p text:style-name="P3"><text:placeholder text:placeholder-type="text"></choose></text:placeholder></text:p>
|
||||
</style:header>
|
||||
<style:footer>
|
||||
<text:p text:style-name="P2"><text:placeholder text:placeholder-type="text"><if test="company and company.footer"></text:placeholder></text:p>
|
||||
<text:p text:style-name="P2"><text:placeholder text:placeholder-type="text"><for each="line in company.footer_used.split('\n')"></text:placeholder></text:p>
|
||||
<text:p text:style-name="P2"><text:placeholder text:placeholder-type="text"><line></text:placeholder></text:p>
|
||||
<text:p text:style-name="P2"><text:placeholder text:placeholder-type="text"></for></text:placeholder></text:p>
|
||||
<text:p text:style-name="P2"><text:placeholder text:placeholder-type="text"></if></text:placeholder></text:p>
|
||||
<text:p text:style-name="P5"><text:page-number text:select-page="current">3</text:page-number>/<text:page-count>3</text:page-count></text:p>
|
||||
</style:footer>
|
||||
</style:master-page>
|
||||
</office:master-styles>
|
||||
<office:body>
|
||||
<office:text text:use-soft-page-breaks="true">
|
||||
<office:forms form:automatic-focus="false" form:apply-design-mode="false"/>
|
||||
<text:sequence-decls>
|
||||
<text:sequence-decl text:display-outline-level="0" text:name="Illustration"/>
|
||||
<text:sequence-decl text:display-outline-level="0" text:name="Table"/>
|
||||
<text:sequence-decl text:display-outline-level="0" text:name="Text"/>
|
||||
<text:sequence-decl text:display-outline-level="0" text:name="Drawing"/>
|
||||
<text:sequence-decl text:display-outline-level="0" text:name="Figure"/>
|
||||
</text:sequence-decls>
|
||||
<text:p text:style-name="P19"><text:placeholder text:placeholder-type="text"><for each="shipment in records"></text:placeholder></text:p>
|
||||
<text:p text:style-name="P22"/>
|
||||
<text:p text:style-name="P15"><text:placeholder text:placeholder-type="text"><if test="shipment.to_location.warehouse and shipment.to_location.warehouse.address"></text:placeholder></text:p>
|
||||
<text:p text:style-name="P15"><text:placeholder text:placeholder-type="text"><for each="line in shipment.to_location.warehouse.address.full_address.split('\n')"></text:placeholder></text:p>
|
||||
<text:p text:style-name="P15"><text:placeholder text:placeholder-type="text"><line></text:placeholder></text:p>
|
||||
<text:p text:style-name="P15"><text:placeholder text:placeholder-type="text"></for></text:placeholder></text:p>
|
||||
<text:p text:style-name="P15"><text:placeholder text:placeholder-type="text"></if></text:placeholder></text:p>
|
||||
<text:p text:style-name="P9"><text:span text:style-name="T5"><text:placeholder text:placeholder-type="text"><shipment.state_string></text:placeholder></text:span><text:span text:style-name="T5"><text:s/>Internal Shipment No: </text:span><text:span text:style-name="T6"><text:placeholder text:placeholder-type="text"><shipment.number></text:placeholder></text:span></text:p>
|
||||
<text:p text:style-name="Standard"><text:span text:style-name="T1">Reference:</text:span><text:span text:style-name="T3"> </text:span><text:span text:style-name="T3"><text:placeholder text:placeholder-type="text"><shipment.reference or ''></text:placeholder></text:span></text:p>
|
||||
<text:p text:style-name="Standard"><text:span text:style-name="T1">From Location:</text:span> <text:placeholder text:placeholder-type="text"><shipment.from_location.rec_name></text:placeholder></text:p>
|
||||
<text:p text:style-name="Standard"><text:span text:style-name="T1">To Location:</text:span> <text:placeholder text:placeholder-type="text"><shipment.to_location.rec_name></text:placeholder></text:p>
|
||||
<text:p text:style-name="Standard"><text:span text:style-name="T1">Planned Date:</text:span><text:span text:style-name="T3"> </text:span><text:span text:style-name="T3"><text:placeholder text:placeholder-type="text"><shipment.planned_date and format_date(shipment.planned_date, user.language) or ''></text:placeholder></text:span></text:p>
|
||||
<table:table table:name="Table1" table:style-name="Table1">
|
||||
<table:table-column table:style-name="Table1.A" table:number-columns-repeated="2"/>
|
||||
<table:table-column table:style-name="Table1.C"/>
|
||||
<table:table-column table:style-name="Table1.D"/>
|
||||
<table:table-header-rows>
|
||||
<table:table-row>
|
||||
<table:table-cell table:style-name="Table1.A1" office:value-type="string">
|
||||
<text:p text:style-name="P17">From Location</text:p>
|
||||
</table:table-cell>
|
||||
<table:table-cell table:style-name="Table1.A1" office:value-type="string">
|
||||
<text:p text:style-name="P17">To Location</text:p>
|
||||
</table:table-cell>
|
||||
<table:table-cell table:style-name="Table1.A1" office:value-type="string">
|
||||
<text:p text:style-name="P17">Product</text:p>
|
||||
</table:table-cell>
|
||||
<table:table-cell table:style-name="Table1.D1" office:value-type="string">
|
||||
<text:p text:style-name="P17">Quantity</text:p>
|
||||
</table:table-cell>
|
||||
</table:table-row>
|
||||
</table:table-header-rows>
|
||||
<table:table-row>
|
||||
<table:table-cell table:style-name="Table1.A2" table:number-columns-spanned="2" office:value-type="string">
|
||||
<text:p text:style-name="Table_20_Contents"><text:placeholder text:placeholder-type="text"><for each="move in moves(shipment)"></text:placeholder></text:p>
|
||||
</table:table-cell>
|
||||
<table:covered-table-cell/>
|
||||
<table:table-cell table:style-name="Table1.C2" office:value-type="string">
|
||||
<text:p text:style-name="P18"/>
|
||||
</table:table-cell>
|
||||
<table:table-cell table:style-name="Table1.D2" office:value-type="string">
|
||||
<text:p text:style-name="P18"/>
|
||||
</table:table-cell>
|
||||
</table:table-row>
|
||||
<table:table-row>
|
||||
<table:table-cell table:style-name="Table1.A3" office:value-type="string">
|
||||
<text:p text:style-name="Table_20_Contents"><text:placeholder text:placeholder-type="text"><move.from_location_name></text:placeholder></text:p>
|
||||
</table:table-cell>
|
||||
<table:table-cell table:style-name="Table1.A3" office:value-type="string">
|
||||
<text:p text:style-name="Table_20_Contents"><text:placeholder text:placeholder-type="text"><move.to_location_name></text:placeholder></text:p>
|
||||
</table:table-cell>
|
||||
<table:table-cell table:style-name="Table1.C2" office:value-type="string">
|
||||
<text:p text:style-name="Table_20_Contents"><text:placeholder text:placeholder-type="text"><move.product.rec_name></text:placeholder></text:p>
|
||||
</table:table-cell>
|
||||
<table:table-cell table:style-name="Table1.D2" office:value-type="string">
|
||||
<text:p text:style-name="P14"><text:placeholder text:placeholder-type="text"><format_number_symbol(move.quantity, user.language, move.unit, digits=move.unit.digits)></text:placeholder><text:soft-page-break/></text:p>
|
||||
</table:table-cell>
|
||||
</table:table-row>
|
||||
<table:table-row>
|
||||
<table:table-cell table:style-name="Table1.A2" table:number-columns-spanned="2" office:value-type="string">
|
||||
<text:p text:style-name="Table_20_Contents"><text:placeholder text:placeholder-type="text"></for></text:placeholder></text:p>
|
||||
</table:table-cell>
|
||||
<table:covered-table-cell/>
|
||||
<table:table-cell table:style-name="Table1.C2" office:value-type="string">
|
||||
<text:p text:style-name="P18"/>
|
||||
</table:table-cell>
|
||||
<table:table-cell table:style-name="Table1.D2" office:value-type="string">
|
||||
<text:p text:style-name="P18"/>
|
||||
</table:table-cell>
|
||||
</table:table-row>
|
||||
</table:table>
|
||||
<text:p text:style-name="Text_20_body"><text:placeholder text:placeholder-type="text"></for></text:placeholder></text:p>
|
||||
</office:text>
|
||||
</office:body>
|
||||
</office:document>
|
||||
619
modules/stock/inventory.py
Normal file
619
modules/stock/inventory.py
Normal file
@@ -0,0 +1,619 @@
|
||||
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
from collections import defaultdict
|
||||
|
||||
from sql import Null
|
||||
from sql.functions import CharLength
|
||||
|
||||
from trytond.i18n import gettext
|
||||
from trytond.model import (
|
||||
ChatMixin, Check, Index, Model, ModelSQL, ModelView, Workflow, fields)
|
||||
from trytond.model.exceptions import AccessError
|
||||
from trytond.pool import Pool
|
||||
from trytond.pyson import Bool, Eval, If
|
||||
from trytond.tools import grouped_slice, is_full_text, lstrip_wildcard
|
||||
from trytond.transaction import Transaction
|
||||
from trytond.wizard import Button, StateTransition, StateView, Wizard
|
||||
|
||||
from .exceptions import InventoryCountWarning, InventoryValidationError
|
||||
|
||||
|
||||
class Inventory(Workflow, ModelSQL, ModelView, ChatMixin):
|
||||
__name__ = 'stock.inventory'
|
||||
_rec_name = 'number'
|
||||
|
||||
_states = {
|
||||
'readonly': Eval('state') != 'draft',
|
||||
}
|
||||
|
||||
number = fields.Char('Number', readonly=True,
|
||||
help="The main identifier for the inventory.")
|
||||
location = fields.Many2One(
|
||||
'stock.location', 'Location', required=True,
|
||||
domain=[('type', '=', 'storage')], states={
|
||||
'readonly': (Eval('state') != 'draft') | Eval('lines', [0]),
|
||||
},
|
||||
help="The location inventoried.")
|
||||
date = fields.Date('Date', required=True, states={
|
||||
'readonly': (Eval('state') != 'draft') | Eval('lines', [0]),
|
||||
},
|
||||
help="The date of the stock count.")
|
||||
lines = fields.One2Many(
|
||||
'stock.inventory.line', 'inventory', 'Lines',
|
||||
states={
|
||||
'readonly': (_states['readonly'] | ~Eval('location')
|
||||
| ~Eval('date')),
|
||||
})
|
||||
empty_quantity = fields.Selection([
|
||||
(None, ""),
|
||||
('keep', "Keep"),
|
||||
('empty', "Empty"),
|
||||
], "Empty Quantity", states=_states,
|
||||
help="How lines without a quantity are handled.")
|
||||
company = fields.Many2One('company.company', 'Company', required=True,
|
||||
states={
|
||||
'readonly': (Eval('state') != 'draft') | Eval('lines', [0]),
|
||||
},
|
||||
help="The company the inventory is associated with.")
|
||||
state = fields.Selection([
|
||||
('draft', "Draft"),
|
||||
('done', "Done"),
|
||||
('cancelled', "Cancelled"),
|
||||
], "State", readonly=True, sort=False,
|
||||
help="The current state of the inventory.")
|
||||
|
||||
del _states
|
||||
|
||||
@classmethod
|
||||
def __setup__(cls):
|
||||
cls.number.search_unaccented = False
|
||||
super().__setup__()
|
||||
t = cls.__table__()
|
||||
cls._sql_indexes.add(
|
||||
Index(
|
||||
t,
|
||||
(t.state, Index.Equality(cardinality='low')),
|
||||
where=t.state == 'draft'))
|
||||
cls._order.insert(0, ('date', 'DESC'))
|
||||
cls._transitions |= set((
|
||||
('draft', 'done'),
|
||||
('draft', 'cancelled'),
|
||||
))
|
||||
cls._buttons.update({
|
||||
'confirm': {
|
||||
'invisible': Eval('state').in_(['done', 'cancelled']),
|
||||
'depends': ['state'],
|
||||
},
|
||||
'cancel': {
|
||||
'invisible': Eval('state').in_(['cancelled', 'done']),
|
||||
'depends': ['state'],
|
||||
},
|
||||
'complete_lines': {
|
||||
'readonly': Eval('state') != 'draft',
|
||||
'depends': ['state'],
|
||||
},
|
||||
'do_count': {
|
||||
'readonly': Eval('state') != 'draft',
|
||||
'depends': ['state'],
|
||||
},
|
||||
})
|
||||
|
||||
@classmethod
|
||||
def order_number(cls, tables):
|
||||
table, _ = tables[None]
|
||||
return [
|
||||
~((table.state == 'cancelled') & (table.number == Null)),
|
||||
CharLength(table.number), table.number]
|
||||
|
||||
@staticmethod
|
||||
def default_state():
|
||||
return 'draft'
|
||||
|
||||
@staticmethod
|
||||
def default_date():
|
||||
Date = Pool().get('ir.date')
|
||||
return Date.today()
|
||||
|
||||
@staticmethod
|
||||
def default_company():
|
||||
return Transaction().context.get('company')
|
||||
|
||||
def get_rec_name(self, name):
|
||||
pool = Pool()
|
||||
Lang = pool.get('ir.lang')
|
||||
lang = Lang.get()
|
||||
date = lang.strftime(self.date)
|
||||
return f"[{self.number}] {self.location.rec_name} @ {date}"
|
||||
|
||||
@classmethod
|
||||
def search_rec_name(cls, name, clause):
|
||||
_, operator, operand, *extra = clause
|
||||
if operator.startswith('!') or operator.startswith('not '):
|
||||
bool_op = 'AND'
|
||||
else:
|
||||
bool_op = 'OR'
|
||||
number_value = operand
|
||||
if operator.endswith('like') and is_full_text(operand):
|
||||
number_value = lstrip_wildcard(operand)
|
||||
return [bool_op,
|
||||
('number', operator, number_value, *extra),
|
||||
('location.rec_name', operator, operand, *extra),
|
||||
]
|
||||
|
||||
@classmethod
|
||||
def view_attributes(cls):
|
||||
return super().view_attributes() + [
|
||||
('/tree', 'visual', If(Eval('state') == 'cancelled', 'muted', '')),
|
||||
]
|
||||
|
||||
@classmethod
|
||||
@ModelView.button
|
||||
@Workflow.transition('done')
|
||||
def confirm(cls, inventories):
|
||||
pool = Pool()
|
||||
Move = pool.get('stock.move')
|
||||
transaction = Transaction()
|
||||
moves = []
|
||||
for inventory in inventories:
|
||||
keys = set()
|
||||
for line in inventory.lines:
|
||||
key = line.unique_key
|
||||
if key in keys:
|
||||
raise InventoryValidationError(
|
||||
gettext('stock.msg_inventory_line_unique',
|
||||
line=line.rec_name,
|
||||
inventory=inventory.rec_name))
|
||||
keys.add(key)
|
||||
move = line.get_move()
|
||||
if move:
|
||||
moves.append(move)
|
||||
if moves:
|
||||
with transaction.set_context(_product_replacement=False):
|
||||
Move.save(moves)
|
||||
Move.do(moves)
|
||||
|
||||
@classmethod
|
||||
@ModelView.button
|
||||
@Workflow.transition('cancelled')
|
||||
def cancel(cls, inventories):
|
||||
Line = Pool().get("stock.inventory.line")
|
||||
Line.cancel_move([l for i in inventories for l in i.lines])
|
||||
|
||||
@classmethod
|
||||
def preprocess_values(cls, mode, values):
|
||||
pool = Pool()
|
||||
Configuration = pool.get('stock.configuration')
|
||||
values = super().preprocess_values(mode, values)
|
||||
if mode == 'create' and not values.get('number'):
|
||||
company_id = values.get('company', cls.default_company())
|
||||
if company_id is not None:
|
||||
configuration = Configuration(1)
|
||||
if sequence := configuration.get_multivalue(
|
||||
'inventory_sequence', company=company_id):
|
||||
values['number'] = sequence.get()
|
||||
return values
|
||||
|
||||
@classmethod
|
||||
def on_modification(cls, mode, inventories, field_names=None):
|
||||
super().on_modification(mode, inventories, field_names=field_names)
|
||||
if mode in {'create', 'write'}:
|
||||
cls.complete_lines(inventories, fill=False)
|
||||
|
||||
@classmethod
|
||||
def check_modification(
|
||||
cls, mode, inventories, values=None, external=False):
|
||||
super().check_modification(
|
||||
mode, inventories, values=values, external=external)
|
||||
if mode == 'delete':
|
||||
for inventory in inventories:
|
||||
if inventory.state not in {'cancelled', 'draft'}:
|
||||
raise AccessError(gettext(
|
||||
'stock.msg_inventory_delete_cancel',
|
||||
inventory=inventory.rec_name))
|
||||
|
||||
@classmethod
|
||||
def copy(cls, inventories, default=None):
|
||||
pool = Pool()
|
||||
Date = pool.get('ir.date')
|
||||
|
||||
if default is None:
|
||||
default = {}
|
||||
else:
|
||||
default = default.copy()
|
||||
default.setdefault('date', Date.today())
|
||||
default.setdefault('lines.moves', None)
|
||||
default.setdefault('number', None)
|
||||
|
||||
return super().copy(inventories, default=default)
|
||||
|
||||
@staticmethod
|
||||
def grouping():
|
||||
return ('product',)
|
||||
|
||||
@classmethod
|
||||
@ModelView.button
|
||||
def complete_lines(cls, inventories, fill=True):
|
||||
'''
|
||||
Complete or update the inventories
|
||||
'''
|
||||
pool = Pool()
|
||||
Line = pool.get('stock.inventory.line')
|
||||
Product = pool.get('product.product')
|
||||
|
||||
grouping = cls.grouping()
|
||||
to_save, to_delete = [], []
|
||||
for inventory in inventories:
|
||||
# Once done computation is wrong because include created moves
|
||||
if inventory.state == 'done':
|
||||
continue
|
||||
# Compute product quantities
|
||||
with Transaction().set_context(
|
||||
company=inventory.company.id,
|
||||
stock_date_end=inventory.date):
|
||||
if fill:
|
||||
pbl = Product.products_by_location(
|
||||
[inventory.location.id],
|
||||
grouping=grouping)
|
||||
else:
|
||||
product_ids = [l.product.id for l in inventory.lines]
|
||||
pbl = defaultdict(int)
|
||||
for product_ids in grouped_slice(product_ids):
|
||||
pbl.update(Product.products_by_location(
|
||||
[inventory.location.id],
|
||||
grouping=grouping,
|
||||
grouping_filter=(list(product_ids),)))
|
||||
|
||||
# Update existing lines
|
||||
for line in inventory.lines:
|
||||
if line.product.type != 'goods':
|
||||
to_delete.append(line)
|
||||
continue
|
||||
|
||||
key = (inventory.location.id,) + line.unique_key
|
||||
if key in pbl:
|
||||
quantity = pbl.pop(key)
|
||||
else:
|
||||
quantity = 0.0
|
||||
line.update_for_complete(quantity)
|
||||
to_save.append(line)
|
||||
|
||||
if not fill:
|
||||
continue
|
||||
|
||||
product_idx = grouping.index('product') + 1
|
||||
# Index some data
|
||||
product2type = {}
|
||||
product2consumable = {}
|
||||
for product in Product.browse({line[product_idx] for line in pbl}):
|
||||
product2type[product.id] = product.type
|
||||
product2consumable[product.id] = product.consumable
|
||||
|
||||
# Create lines if needed
|
||||
for key, quantity in pbl.items():
|
||||
product_id = key[product_idx]
|
||||
if (product2type[product_id] != 'goods'
|
||||
or product2consumable[product_id]):
|
||||
continue
|
||||
if not quantity:
|
||||
continue
|
||||
|
||||
line = Line(
|
||||
inventory=inventory,
|
||||
**{fname: key[i] for i, fname in enumerate(grouping, 1)})
|
||||
line.update_for_complete(quantity)
|
||||
to_save.append(line)
|
||||
if to_delete:
|
||||
Line.delete(to_delete)
|
||||
if to_save:
|
||||
Line.save(to_save)
|
||||
|
||||
@classmethod
|
||||
@ModelView.button_action('stock.wizard_inventory_count')
|
||||
def do_count(cls, inventories):
|
||||
cls.complete_lines(inventories)
|
||||
|
||||
|
||||
class InventoryLine(ModelSQL, ModelView):
|
||||
__name__ = 'stock.inventory.line'
|
||||
_states = {
|
||||
'readonly': Eval('inventory_state') != 'draft',
|
||||
}
|
||||
|
||||
product = fields.Many2One('product.product', 'Product', required=True,
|
||||
domain=[
|
||||
('type', '=', 'goods'),
|
||||
], states=_states)
|
||||
unit = fields.Function(fields.Many2One(
|
||||
'product.uom', "Unit",
|
||||
help="The unit in which the quantity is specified."),
|
||||
'get_unit')
|
||||
expected_quantity = fields.Float(
|
||||
"Expected Quantity", digits='unit', required=True, readonly=True,
|
||||
states={
|
||||
'invisible': Eval('id', -1) < 0,
|
||||
},
|
||||
help="The quantity the system calculated should be in the location.")
|
||||
quantity = fields.Float(
|
||||
"Actual Quantity", digits='unit', states=_states,
|
||||
domain=[
|
||||
If(Eval('quantity', None),
|
||||
('quantity', '>=', 0),
|
||||
()),
|
||||
],
|
||||
help="The actual quantity found in the location.")
|
||||
moves = fields.One2Many('stock.move', 'origin', 'Moves', readonly=True)
|
||||
inventory = fields.Many2One('stock.inventory', 'Inventory', required=True,
|
||||
ondelete='CASCADE',
|
||||
states={
|
||||
'readonly': _states['readonly'] & Bool(Eval('inventory')),
|
||||
},
|
||||
help="The inventory the line belongs to.")
|
||||
inventory_location = fields.Function(
|
||||
fields.Many2One('stock.location', "Location"),
|
||||
'on_change_with_inventory_location',
|
||||
searcher='search_inventory_location')
|
||||
inventory_date = fields.Function(
|
||||
fields.Date("Date"),
|
||||
'on_change_with_inventory_date',
|
||||
searcher='search_inventory_date')
|
||||
inventory_state = fields.Function(
|
||||
fields.Selection('get_inventory_states', "Inventory State",
|
||||
depends={'inventory'}),
|
||||
'on_change_with_inventory_state')
|
||||
|
||||
@classmethod
|
||||
def __setup__(cls):
|
||||
super().__setup__()
|
||||
cls.__access__.add('inventory')
|
||||
t = cls.__table__()
|
||||
cls._sql_constraints += [
|
||||
('check_line_qty_pos', Check(t, t.quantity >= 0),
|
||||
'stock.msg_inventory_line_quantity_positive'),
|
||||
]
|
||||
cls._order.insert(0, ('product', 'ASC'))
|
||||
|
||||
@staticmethod
|
||||
def default_expected_quantity():
|
||||
return 0.
|
||||
|
||||
@fields.depends('product')
|
||||
def on_change_product(self):
|
||||
if self.product:
|
||||
self.unit = self.product.default_uom
|
||||
|
||||
@fields.depends('inventory', '_parent_inventory.location')
|
||||
def on_change_with_inventory_location(self, name=None):
|
||||
return self.inventory.location if self.inventory else None
|
||||
|
||||
@classmethod
|
||||
def search_inventory_location(cls, name, clause):
|
||||
nested = clause[0][len(name):]
|
||||
return [('inventory.location' + nested, *clause[1:])]
|
||||
|
||||
@fields.depends('inventory', '_parent_inventory.date')
|
||||
def on_change_with_inventory_date(self, name=None):
|
||||
if self.inventory:
|
||||
return self.inventory.date
|
||||
|
||||
@classmethod
|
||||
def search_inventory_date(cls, name, clause):
|
||||
return [('inventory.date',) + tuple(clause[1:])]
|
||||
|
||||
@classmethod
|
||||
def get_inventory_states(cls):
|
||||
pool = Pool()
|
||||
Inventory = pool.get('stock.inventory')
|
||||
return Inventory.fields_get(['state'])['state']['selection']
|
||||
|
||||
@fields.depends('inventory', '_parent_inventory.state')
|
||||
def on_change_with_inventory_state(self, name=None):
|
||||
if self.inventory:
|
||||
return self.inventory.state
|
||||
return 'draft'
|
||||
|
||||
def get_rec_name(self, name):
|
||||
return self.product.rec_name
|
||||
|
||||
@classmethod
|
||||
def search_rec_name(cls, name, clause):
|
||||
return [('product.rec_name',) + tuple(clause[1:])]
|
||||
|
||||
def get_unit(self, name):
|
||||
return self.product.default_uom
|
||||
|
||||
@property
|
||||
def unique_key(self):
|
||||
key = []
|
||||
for fname in self.inventory.grouping():
|
||||
value = getattr(self, fname)
|
||||
if isinstance(value, Model):
|
||||
value = value.id
|
||||
key.append(value)
|
||||
return tuple(key)
|
||||
|
||||
@classmethod
|
||||
def cancel_move(cls, lines):
|
||||
Move = Pool().get('stock.move')
|
||||
moves = [m for l in lines for m in l.moves if l.moves]
|
||||
Move.cancel(moves)
|
||||
Move.delete(moves)
|
||||
|
||||
def get_move(self):
|
||||
'''
|
||||
Return Move instance for the inventory line
|
||||
'''
|
||||
pool = Pool()
|
||||
Move = pool.get('stock.move')
|
||||
|
||||
qty = self.quantity
|
||||
if qty is None:
|
||||
if self.inventory.empty_quantity is None:
|
||||
raise InventoryValidationError(
|
||||
gettext('stock.msg_inventory_missing_empty_quantity',
|
||||
inventory=self.inventory.rec_name))
|
||||
if self.inventory.empty_quantity == 'keep':
|
||||
return
|
||||
else:
|
||||
qty = 0.0
|
||||
|
||||
delta_qty = self.unit.round(self.expected_quantity - qty)
|
||||
if delta_qty == 0.0:
|
||||
return
|
||||
from_location = self.inventory.location
|
||||
to_location = self.inventory.location.lost_found_used
|
||||
if not to_location:
|
||||
raise InventoryValidationError(
|
||||
gettext('stock.msg_inventory_location_missing_lost_found',
|
||||
inventory=self.inventory.rec_name,
|
||||
location=self.inventory.location.rec_name))
|
||||
if delta_qty < 0:
|
||||
(from_location, to_location, delta_qty) = \
|
||||
(to_location, from_location, -delta_qty)
|
||||
|
||||
return Move(
|
||||
from_location=from_location,
|
||||
to_location=to_location,
|
||||
quantity=delta_qty,
|
||||
product=self.product,
|
||||
unit=self.unit,
|
||||
company=self.inventory.company,
|
||||
effective_date=self.inventory.date,
|
||||
origin=self,
|
||||
)
|
||||
|
||||
@fields.depends('expected_quantity')
|
||||
def update_for_complete(self, quantity):
|
||||
if self.expected_quantity != quantity:
|
||||
self.expected_quantity = quantity
|
||||
|
||||
@classmethod
|
||||
def check_modification(cls, mode, lines, values=None, external=False):
|
||||
super().check_modification(
|
||||
mode, lines, values=values, external=external)
|
||||
if mode == 'delete':
|
||||
for line in lines:
|
||||
if line.inventory_state not in {'cancelled', 'draft'}:
|
||||
raise AccessError(gettext(
|
||||
'stock.msg_inventory_line_delete_cancel',
|
||||
line=line.rec_name,
|
||||
inventory=line.inventory.rec_name))
|
||||
|
||||
|
||||
class Count(Wizard):
|
||||
__name__ = 'stock.inventory.count'
|
||||
start_state = 'search'
|
||||
|
||||
search = StateView(
|
||||
'stock.inventory.count.search',
|
||||
'stock.inventory_count_search_view_form', [
|
||||
Button("End", 'end', 'tryton-cancel'),
|
||||
Button("Select", 'quantity', 'tryton-forward', default=True),
|
||||
])
|
||||
quantity = StateView(
|
||||
'stock.inventory.count.quantity',
|
||||
'stock.inventory_count_quantity_view_form', [
|
||||
Button("Cancel", 'search', 'tryton-cancel'),
|
||||
Button("Add", 'add', 'tryton-ok', default=True),
|
||||
])
|
||||
add = StateTransition()
|
||||
|
||||
def default_quantity(self, fields):
|
||||
pool = Pool()
|
||||
InventoryLine = pool.get('stock.inventory.line')
|
||||
Warning = pool.get('res.user.warning')
|
||||
values = {}
|
||||
lines = InventoryLine.search(
|
||||
self.get_line_domain(self.record), limit=1)
|
||||
if not lines:
|
||||
warning_name = '%s.%s.count_create' % (
|
||||
self.record, self.search.search)
|
||||
if Warning.check(warning_name):
|
||||
raise InventoryCountWarning(warning_name,
|
||||
gettext('stock.msg_inventory_count_create_line',
|
||||
search=self.search.search.rec_name))
|
||||
line = self.get_line()
|
||||
line.update_for_complete(0)
|
||||
line.save()
|
||||
else:
|
||||
line, = lines
|
||||
values['line'] = line.id
|
||||
values['product'] = line.product.id
|
||||
values['unit'] = line.unit.id
|
||||
if line.unit.rounding == 1:
|
||||
values['quantity'] = 1.
|
||||
return values
|
||||
|
||||
def get_line_domain(self, inventory):
|
||||
pool = Pool()
|
||||
Product = pool.get('product.product')
|
||||
domain = [
|
||||
('inventory', '=', inventory.id),
|
||||
]
|
||||
if isinstance(self.search.search, Product):
|
||||
domain.append(('product', '=', self.search.search.id))
|
||||
return domain
|
||||
|
||||
def get_line(self):
|
||||
pool = Pool()
|
||||
Product = pool.get('product.product')
|
||||
InventoryLine = pool.get('stock.inventory.line')
|
||||
|
||||
line = InventoryLine(inventory=self.record)
|
||||
if isinstance(self.search.search, Product):
|
||||
line.product = self.search.search
|
||||
return line
|
||||
|
||||
def transition_add(self):
|
||||
if self.quantity.line and self.quantity.quantity:
|
||||
line = self.quantity.line
|
||||
if line.quantity:
|
||||
line.quantity += self.quantity.quantity
|
||||
else:
|
||||
line.quantity = self.quantity.quantity
|
||||
line.save()
|
||||
return 'search'
|
||||
|
||||
|
||||
class CountSearch(ModelView):
|
||||
__name__ = 'stock.inventory.count.search'
|
||||
|
||||
search = fields.Reference(
|
||||
"Search", [
|
||||
('product.product', "Product"),
|
||||
],
|
||||
required=True,
|
||||
domain={
|
||||
'product.product': [
|
||||
('type', '=', 'goods'),
|
||||
('consumable', '=', False),
|
||||
],
|
||||
},
|
||||
help="The item that's counted.")
|
||||
|
||||
@classmethod
|
||||
def default_search(cls):
|
||||
return 'product.product,-1'
|
||||
|
||||
|
||||
class CountQuantity(ModelView):
|
||||
__name__ = 'stock.inventory.count.quantity'
|
||||
|
||||
line = fields.Many2One(
|
||||
'stock.inventory.line', "Line", readonly=True, required=True)
|
||||
product = fields.Many2One('product.product', "Product", readonly=True)
|
||||
unit = fields.Many2One(
|
||||
'product.uom', "Unit", readonly=True,
|
||||
help="The unit in which the quantities are specified.")
|
||||
total_quantity = fields.Float(
|
||||
"Total Quantity", digits='unit', readonly=True,
|
||||
help="The total amount of the line counted so far.")
|
||||
|
||||
quantity = fields.Float(
|
||||
"Quantity", digits='unit', required=True,
|
||||
help="The quantity to add to the existing count.")
|
||||
|
||||
@fields.depends('quantity', 'line')
|
||||
def on_change_quantity(self):
|
||||
if self.line:
|
||||
self.total_quantity = (
|
||||
(self.line.quantity or 0) + (self.quantity or 0))
|
||||
175
modules/stock/inventory.xml
Normal file
175
modules/stock/inventory.xml
Normal file
@@ -0,0 +1,175 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
this repository contains the full copyright notices and license terms. -->
|
||||
<tryton>
|
||||
<data>
|
||||
|
||||
<record model="ir.ui.view" id="inventory_view_form">
|
||||
<field name="model">stock.inventory</field>
|
||||
<field name="type">form</field>
|
||||
<field name="name">inventory_form</field>
|
||||
</record>
|
||||
<record model="ir.ui.view" id="inventory_view_tree">
|
||||
<field name="model">stock.inventory</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="name">inventory_tree</field>
|
||||
</record>
|
||||
<record model="ir.action.act_window" id="act_inventory_form">
|
||||
<field name="name">Inventories</field>
|
||||
<field name="res_model">stock.inventory</field>
|
||||
<field name="search_value"
|
||||
eval="[('create_date', '>=', DateTime(hour=0, minute=0, second=0, microsecond=0, delta_years=-1))]"
|
||||
pyson="1"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view"
|
||||
id="act_inventory_form_view1">
|
||||
<field name="sequence" eval="1"/>
|
||||
<field name="view" ref="inventory_view_tree"/>
|
||||
<field name="act_window" ref="act_inventory_form"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view"
|
||||
id="act_inventory_form_view2">
|
||||
<field name="sequence" eval="2"/>
|
||||
<field name="view" ref="inventory_view_form"/>
|
||||
<field name="act_window" ref="act_inventory_form"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.domain" id="act_inventory_form_domain_draft">
|
||||
<field name="name">Draft</field>
|
||||
<field name="sequence" eval="10"/>
|
||||
<field name="domain" eval="[('state', '=', 'draft')]" pyson="1"/>
|
||||
<field name="count" eval="True"/>
|
||||
<field name="act_window" ref="act_inventory_form"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.domain" id="act_inventory_form_domain_all">
|
||||
<field name="name">All</field>
|
||||
<field name="sequence" eval="9999"/>
|
||||
<field name="domain"></field>
|
||||
<field name="act_window" ref="act_inventory_form"/>
|
||||
</record>
|
||||
<menuitem
|
||||
parent="menu_stock"
|
||||
action="act_inventory_form"
|
||||
sequence="20"
|
||||
id="menu_inventory_form"/>
|
||||
|
||||
<record model="ir.ui.view" id="inventory_line_view_form">
|
||||
<field name="model">stock.inventory.line</field>
|
||||
<field name="type">form</field>
|
||||
<field name="name">inventory_line_form</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="inventory_line_view_list">
|
||||
<field name="model">stock.inventory.line</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="name">inventory_line_list</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.action.act_window" id="act_inventory_line_relate">
|
||||
<field name="name">Inventory Lines</field>
|
||||
<field name="res_model">stock.inventory.line</field>
|
||||
<field
|
||||
name="domain"
|
||||
eval="[If(Eval('active_ids', []) == [Eval('active_id')], ('inventory', '=', Eval('active_id')), ('inventory', 'in', Eval('active_ids')))]"
|
||||
pyson="1"/>
|
||||
</record>
|
||||
<record model="ir.action.keyword" id="act_inventory_line_relate_keyword1">
|
||||
<field name="keyword">form_relate</field>
|
||||
<field name="model">stock.inventory,-1</field>
|
||||
<field name="action" ref="act_inventory_line_relate"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.rule.group" id="rule_group_inventory_companies">
|
||||
<field name="name">User in companies</field>
|
||||
<field name="model">stock.inventory</field>
|
||||
<field name="global_p" eval="True"/>
|
||||
</record>
|
||||
<record model="ir.rule" id="rule_inventory_companies">
|
||||
<field name="domain"
|
||||
eval="[('company', 'in', Eval('companies', []))]"
|
||||
pyson="1"/>
|
||||
<field name="rule_group" ref="rule_group_inventory_companies"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.access" id="access_inventory">
|
||||
<field name="model">stock.inventory</field>
|
||||
<field name="perm_read" eval="False"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
<field name="perm_create" eval="False"/>
|
||||
<field name="perm_delete" eval="False"/>
|
||||
</record>
|
||||
<record model="ir.model.access" id="access_inventory_group_stock">
|
||||
<field name="model">stock.inventory</field>
|
||||
<field name="group" ref="group_stock"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="True"/>
|
||||
<field name="perm_create" eval="True"/>
|
||||
<field name="perm_delete" eval="True"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.button" id="inventory_confirm_button">
|
||||
<field name="model">stock.inventory</field>
|
||||
<field name="name">confirm</field>
|
||||
<field name="string">Confirm</field>
|
||||
<field name="confirm">Are you sure you want to confirm the inventory?</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.button" id="inventory_cancel_button">
|
||||
<field name="model">stock.inventory</field>
|
||||
<field name="name">cancel</field>
|
||||
<field name="string">Cancel</field>
|
||||
<field name="confirm">Are you sure you want to cancel the inventory?</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.button" id="inventory_complete_lines_button">
|
||||
<field name="model">stock.inventory</field>
|
||||
<field name="name">complete_lines</field>
|
||||
<field name="string">Complete</field>
|
||||
<field name="help">Add an inventory line for each missing products</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.button" id="inventory_count_button">
|
||||
<field name="model">stock.inventory</field>
|
||||
<field name="name">do_count</field>
|
||||
<field name="string">Count</field>
|
||||
<field name="help">Launch the wizard to count products</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.action.wizard" id="wizard_inventory_count">
|
||||
<field name="name">Count</field>
|
||||
<field name="wiz_name">stock.inventory.count</field>
|
||||
<field name="model">stock.inventory</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="inventory_count_search_view_form">
|
||||
<field name="model">stock.inventory.count.search</field>
|
||||
<field name="type">form</field>
|
||||
<field name="name">inventory_count_search_form</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="inventory_count_quantity_view_form">
|
||||
<field name="model">stock.inventory.count.quantity</field>
|
||||
<field name="type">form</field>
|
||||
<field name="name">inventory_count_quantity_form</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.sequence.type" id="sequence_type_inventory">
|
||||
<field name="name">Inventory</field>
|
||||
</record>
|
||||
<record model="ir.sequence.type-res.group"
|
||||
id="sequence_type_inventory_group_admin">
|
||||
<field name="sequence_type" ref="sequence_type_inventory"/>
|
||||
<field name="group" ref="res.group_admin"/>
|
||||
</record>
|
||||
<record model="ir.sequence.type-res.group"
|
||||
id="sequence_type_inventory_group_stock_admin">
|
||||
<field name="sequence_type" ref="sequence_type_inventory"/>
|
||||
<field name="group" ref="group_stock_admin"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.sequence" id="sequence_inventory">
|
||||
<field name="name">Inventory</field>
|
||||
<field name="sequence_type" ref="sequence_type_inventory"/>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</tryton>
|
||||
57
modules/stock/ir.py
Normal file
57
modules/stock/ir.py
Normal file
@@ -0,0 +1,57 @@
|
||||
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
|
||||
from itertools import groupby
|
||||
from operator import attrgetter
|
||||
|
||||
from trytond.pool import Pool, PoolMeta
|
||||
from trytond.transaction import Transaction
|
||||
|
||||
from .shipment import ShipmentAssignMixin
|
||||
|
||||
|
||||
class Cron(metaclass=PoolMeta):
|
||||
__name__ = 'ir.cron'
|
||||
|
||||
@classmethod
|
||||
def __setup__(cls):
|
||||
super().__setup__()
|
||||
cls.method.selection.extend([
|
||||
('product.product|recompute_cost_price_from_moves',
|
||||
"Recompute Cost Price from Moves"),
|
||||
('stock.shipment.out|reschedule',
|
||||
"Reschedule Customer Shipments"),
|
||||
('stock.shipment.in.return|reschedule',
|
||||
"Reschedule Supplier Return Shipments"),
|
||||
('stock.shipment.internal|reschedule',
|
||||
"Reschedule Internal Shipments"),
|
||||
('ir.cron|stock_shipment_assign_try', "Assign Shipments"),
|
||||
])
|
||||
|
||||
@classmethod
|
||||
def __register__(cls, module):
|
||||
table = cls.__table__()
|
||||
cursor = Transaction().connection.cursor()
|
||||
|
||||
super().__register__(module)
|
||||
|
||||
# Migration from 7.0: replace assign_cron
|
||||
cursor.execute(*table.update(
|
||||
[table.method], ['ir.cron|stock_shipment_assign_try'],
|
||||
where=table.method.in_([
|
||||
'stock.shipment.out|assign_cron',
|
||||
'stock.shipment.internal|assign_cron',
|
||||
])))
|
||||
|
||||
@classmethod
|
||||
def stock_shipment_assign_try(cls):
|
||||
pool = Pool()
|
||||
records = []
|
||||
for _, kls in pool.iterobject():
|
||||
if issubclass(kls, ShipmentAssignMixin):
|
||||
records.extend(kls.to_assign())
|
||||
|
||||
records.sort(key=attrgetter('assign_order_key'))
|
||||
|
||||
for kls, records in groupby(records, key=attrgetter('__class__')):
|
||||
kls.assign_try(list(records))
|
||||
4151
modules/stock/locale/bg.po
Normal file
4151
modules/stock/locale/bg.po
Normal file
File diff suppressed because it is too large
Load Diff
3848
modules/stock/locale/ca.po
Normal file
3848
modules/stock/locale/ca.po
Normal file
File diff suppressed because it is too large
Load Diff
4051
modules/stock/locale/cs.po
Normal file
4051
modules/stock/locale/cs.po
Normal file
File diff suppressed because it is too large
Load Diff
3863
modules/stock/locale/de.po
Normal file
3863
modules/stock/locale/de.po
Normal file
File diff suppressed because it is too large
Load Diff
3848
modules/stock/locale/es.po
Normal file
3848
modules/stock/locale/es.po
Normal file
File diff suppressed because it is too large
Load Diff
3965
modules/stock/locale/es_419.po
Normal file
3965
modules/stock/locale/es_419.po
Normal file
File diff suppressed because it is too large
Load Diff
4086
modules/stock/locale/et.po
Normal file
4086
modules/stock/locale/et.po
Normal file
File diff suppressed because it is too large
Load Diff
4100
modules/stock/locale/fa.po
Normal file
4100
modules/stock/locale/fa.po
Normal file
File diff suppressed because it is too large
Load Diff
4049
modules/stock/locale/fi.po
Normal file
4049
modules/stock/locale/fi.po
Normal file
File diff suppressed because it is too large
Load Diff
3848
modules/stock/locale/fr.po
Normal file
3848
modules/stock/locale/fr.po
Normal file
File diff suppressed because it is too large
Load Diff
4044
modules/stock/locale/hu.po
Normal file
4044
modules/stock/locale/hu.po
Normal file
File diff suppressed because it is too large
Load Diff
3950
modules/stock/locale/id.po
Normal file
3950
modules/stock/locale/id.po
Normal file
File diff suppressed because it is too large
Load Diff
4079
modules/stock/locale/it.po
Normal file
4079
modules/stock/locale/it.po
Normal file
File diff suppressed because it is too large
Load Diff
4196
modules/stock/locale/lo.po
Normal file
4196
modules/stock/locale/lo.po
Normal file
File diff suppressed because it is too large
Load Diff
4052
modules/stock/locale/lt.po
Normal file
4052
modules/stock/locale/lt.po
Normal file
File diff suppressed because it is too large
Load Diff
3861
modules/stock/locale/nl.po
Normal file
3861
modules/stock/locale/nl.po
Normal file
File diff suppressed because it is too large
Load Diff
3952
modules/stock/locale/pl.po
Normal file
3952
modules/stock/locale/pl.po
Normal file
File diff suppressed because it is too large
Load Diff
4097
modules/stock/locale/pt.po
Normal file
4097
modules/stock/locale/pt.po
Normal file
File diff suppressed because it is too large
Load Diff
3956
modules/stock/locale/ro.po
Normal file
3956
modules/stock/locale/ro.po
Normal file
File diff suppressed because it is too large
Load Diff
4154
modules/stock/locale/ru.po
Normal file
4154
modules/stock/locale/ru.po
Normal file
File diff suppressed because it is too large
Load Diff
4114
modules/stock/locale/sl.po
Normal file
4114
modules/stock/locale/sl.po
Normal file
File diff suppressed because it is too large
Load Diff
4043
modules/stock/locale/tr.po
Normal file
4043
modules/stock/locale/tr.po
Normal file
File diff suppressed because it is too large
Load Diff
3779
modules/stock/locale/uk.po
Normal file
3779
modules/stock/locale/uk.po
Normal file
File diff suppressed because it is too large
Load Diff
3935
modules/stock/locale/zh_CN.po
Normal file
3935
modules/stock/locale/zh_CN.po
Normal file
File diff suppressed because it is too large
Load Diff
761
modules/stock/location.py
Normal file
761
modules/stock/location.py
Normal file
@@ -0,0 +1,761 @@
|
||||
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
import datetime
|
||||
import operator
|
||||
from decimal import Decimal
|
||||
|
||||
from sql import Column
|
||||
|
||||
from trytond.cache import Cache
|
||||
from trytond.i18n import gettext
|
||||
from trytond.model import (
|
||||
DeactivableMixin, Index, MatchMixin, Model, ModelSQL, ModelView, fields,
|
||||
sequence_ordered, tree)
|
||||
from trytond.modules.product import price_digits, round_price
|
||||
from trytond.pool import Pool
|
||||
from trytond.pyson import Eval, If, TimeDelta
|
||||
from trytond.tools import grouped_slice
|
||||
from trytond.transaction import (
|
||||
Transaction, inactive_records, without_check_access)
|
||||
|
||||
from .exceptions import LocationValidationError
|
||||
|
||||
|
||||
class WarehouseWasteLocation(ModelSQL):
|
||||
__name__ = 'stock.location.waste'
|
||||
|
||||
warehouse = fields.Many2One(
|
||||
'stock.location', "Warehouse", required=True, ondelete='CASCADE',
|
||||
domain=[('type', '=', 'warehouse')])
|
||||
location = fields.Many2One(
|
||||
'stock.location', "Waste Location", required=True, ondelete='CASCADE',
|
||||
domain=[('type', '=', 'lost_found')])
|
||||
|
||||
|
||||
class Location(DeactivableMixin, tree(), ModelSQL, ModelView):
|
||||
__name__ = 'stock.location'
|
||||
_default_warehouse_cache = Cache('stock.location.default_warehouse',
|
||||
context=False)
|
||||
|
||||
name = fields.Char("Name", size=None, required=True, translate=True)
|
||||
code = fields.Char(
|
||||
"Code",
|
||||
help="The internal identifier used for the location.")
|
||||
address = fields.Many2One(
|
||||
'party.address', "Address",
|
||||
states={
|
||||
'invisible': Eval('type') != 'warehouse',
|
||||
})
|
||||
type = fields.Selection([
|
||||
('supplier', 'Supplier'),
|
||||
('customer', 'Customer'),
|
||||
('lost_found', 'Lost and Found'),
|
||||
('warehouse', 'Warehouse'),
|
||||
('storage', 'Storage'),
|
||||
('production', 'Production'),
|
||||
('drop', 'Drop'),
|
||||
('rental', "Rental"),
|
||||
('view', 'View'),
|
||||
], "Type",
|
||||
help_selection={
|
||||
'supplier': "Used as the source of stock received from suppliers.",
|
||||
'customer': "Used as the destination for stock sent to customers.",
|
||||
'lost_found': "Used for damages, discrepancies and wastage.",
|
||||
'warehouse': (
|
||||
"Regroup storage locations under a logistics warehouse."),
|
||||
'storage': "Used to physically store goods.",
|
||||
'production': (
|
||||
"Used as the destination of components and the source of "
|
||||
"finished products."),
|
||||
'drop': "Used during the drop shipping process.",
|
||||
'view': "Group locations logically.",
|
||||
})
|
||||
type_string = type.translated('type')
|
||||
parent = fields.Many2One(
|
||||
"stock.location", "Parent", ondelete='CASCADE',
|
||||
left="left", right="right",
|
||||
help="Used to add structure above the location.")
|
||||
left = fields.Integer('Left', required=True)
|
||||
right = fields.Integer('Right', required=True)
|
||||
childs = fields.One2Many("stock.location", "parent", "Children",
|
||||
help="Used to add structure below the location.")
|
||||
flat_childs = fields.Boolean(
|
||||
"Flat Children",
|
||||
help="Check to enforce a single level of children with no "
|
||||
"grandchildren.")
|
||||
warehouse = fields.Function(fields.Many2One('stock.location', 'Warehouse'),
|
||||
'get_warehouse')
|
||||
input_location = fields.Many2One(
|
||||
"stock.location", "Input", states={
|
||||
'invisible': Eval('type') != 'warehouse',
|
||||
'required': Eval('type') == 'warehouse',
|
||||
},
|
||||
domain=[
|
||||
['OR',
|
||||
('type', '=', 'storage'),
|
||||
('id', '=', Eval('storage_location', -1)),
|
||||
],
|
||||
['OR',
|
||||
('parent', 'child_of', [Eval('id', -1)]),
|
||||
('parent', '=', None),
|
||||
],
|
||||
],
|
||||
help="Where incoming stock is received.")
|
||||
output_location = fields.Many2One(
|
||||
"stock.location", "Output", states={
|
||||
'invisible': Eval('type') != 'warehouse',
|
||||
'required': Eval('type') == 'warehouse',
|
||||
},
|
||||
domain=[
|
||||
['OR',
|
||||
('type', '=', 'storage'),
|
||||
('id', '=', Eval('storage_location', -1)),
|
||||
],
|
||||
['OR',
|
||||
('parent', 'child_of', [Eval('id', -1)]),
|
||||
('parent', '=', None)]],
|
||||
help="Where outgoing stock is sent from.")
|
||||
storage_location = fields.Many2One(
|
||||
"stock.location", "Storage", states={
|
||||
'invisible': Eval('type') != 'warehouse',
|
||||
'required': Eval('type') == 'warehouse',
|
||||
},
|
||||
domain=[
|
||||
('type', 'in', ['storage', 'view']),
|
||||
['OR',
|
||||
('parent', 'child_of', [Eval('id', -1)]),
|
||||
('parent', '=', None)]],
|
||||
help="The top level location where stock is stored.")
|
||||
picking_location = fields.Many2One(
|
||||
'stock.location', 'Picking', states={
|
||||
'invisible': Eval('type') != 'warehouse',
|
||||
},
|
||||
domain=[
|
||||
('type', '=', 'storage'),
|
||||
('parent', 'child_of', [Eval('storage_location', -1)]),
|
||||
],
|
||||
help="Where stock is picked from.\n"
|
||||
"Leave empty to use the storage location.")
|
||||
lost_found_location = fields.Many2One(
|
||||
'stock.location', "Lost and Found",
|
||||
states={
|
||||
'invisible': Eval('type') != 'warehouse',
|
||||
},
|
||||
domain=[
|
||||
('type', '=', 'lost_found'),
|
||||
],
|
||||
help="Used, by inventories, when correcting stock levels "
|
||||
"in the warehouse.")
|
||||
waste_locations = fields.Many2Many(
|
||||
'stock.location.waste', 'warehouse', 'location', "Waste Locations",
|
||||
states={
|
||||
'invisible': Eval('type') != 'warehouse',
|
||||
},
|
||||
domain=[
|
||||
('type', '=', 'lost_found'),
|
||||
],
|
||||
help="The locations used for waste products from the warehouse.")
|
||||
waste_warehouses = fields.Many2Many(
|
||||
'stock.location.waste', 'location', 'warehouse', "Waste Warehouses",
|
||||
states={
|
||||
'invisible': Eval('type') != 'lost_found',
|
||||
},
|
||||
domain=[
|
||||
('type', '=', 'warehouse'),
|
||||
],
|
||||
help="The warehouses that use the location for waste products.")
|
||||
|
||||
allow_pickup = fields.Boolean(
|
||||
"Allow Pickup",
|
||||
states={
|
||||
'invisible': (
|
||||
(Eval('type') != 'warehouse')
|
||||
& ~Eval('address')),
|
||||
})
|
||||
|
||||
quantity = fields.Function(
|
||||
fields.Float(
|
||||
"Quantity", digits='quantity_uom',
|
||||
help="The amount of stock in the location."),
|
||||
'get_quantity', searcher='search_quantity')
|
||||
forecast_quantity = fields.Function(
|
||||
fields.Float(
|
||||
"Forecast Quantity", digits='quantity_uom',
|
||||
help="The amount of stock expected to be in the location."),
|
||||
'get_quantity', searcher='search_quantity')
|
||||
quantity_uom = fields.Function(fields.Many2One(
|
||||
'product.uom', "Quantity UoM",
|
||||
help="The Unit of Measure for the quantities."),
|
||||
'get_quantity_uom')
|
||||
cost_value = fields.Function(fields.Numeric(
|
||||
"Cost Value", digits=price_digits,
|
||||
help="The value of the stock in the location."),
|
||||
'get_cost_value')
|
||||
|
||||
@classmethod
|
||||
def __setup__(cls):
|
||||
cls.code.search_unaccented = False
|
||||
super().__setup__()
|
||||
t = cls.__table__()
|
||||
cls._sql_indexes.update({
|
||||
Index(t, (t.code, Index.Similarity())),
|
||||
Index(
|
||||
t,
|
||||
(t.left, Index.Range(cardinality='high')),
|
||||
(t.right, Index.Range(cardinality='high'))),
|
||||
})
|
||||
cls._order.insert(0, ('name', 'ASC'))
|
||||
|
||||
parent_domain = [
|
||||
['OR',
|
||||
('parent.flat_childs', '=', False),
|
||||
('parent', '=', None),
|
||||
]
|
||||
]
|
||||
childs_domain = [
|
||||
If(Eval('flat_childs', False),
|
||||
('childs', '=', None),
|
||||
()),
|
||||
]
|
||||
childs_mapping = cls._childs_domain()
|
||||
for type_, allowed_parents in cls._parent_domain().items():
|
||||
parent_domain.append(If(Eval('type') == type_,
|
||||
('type', 'in', allowed_parents), ()))
|
||||
childs_domain.append(If(Eval('type') == type_,
|
||||
('type', 'in', childs_mapping[type_]), ()))
|
||||
cls.parent.domain = parent_domain
|
||||
cls.childs.domain = childs_domain
|
||||
|
||||
@classmethod
|
||||
def _parent_domain(cls):
|
||||
'''Returns a dict with location types as keys and a list of allowed
|
||||
parent location types as values'''
|
||||
return {
|
||||
'customer': ['customer'],
|
||||
'supplier': ['supplier'],
|
||||
'production': ['production'],
|
||||
'lost_found': ['lost_found'],
|
||||
'view': ['warehouse', 'view', 'storage'],
|
||||
'storage': ['warehouse', 'view', 'storage'],
|
||||
'warehouse': ['view'],
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def _childs_domain(cls):
|
||||
childs_domain = {}
|
||||
for type_, allowed_parents in cls._parent_domain().items():
|
||||
for parent in allowed_parents:
|
||||
childs_domain.setdefault(parent, [])
|
||||
childs_domain[parent].append(type_)
|
||||
return childs_domain
|
||||
|
||||
@classmethod
|
||||
def validate_fields(cls, locations, field_names):
|
||||
super().validate_fields(locations, field_names)
|
||||
inactives = []
|
||||
for location in locations:
|
||||
location.check_type_for_moves(field_names)
|
||||
if 'active' in field_names and not location.active:
|
||||
inactives.append(location)
|
||||
cls.check_inactive(inactives)
|
||||
|
||||
def check_type_for_moves(self, field_names=None):
|
||||
""" Check locations with moves have types compatible with moves. """
|
||||
pool = Pool()
|
||||
Move = pool.get('stock.move')
|
||||
if field_names and 'type' not in field_names:
|
||||
return
|
||||
invalid_move_types = ['warehouse', 'view']
|
||||
if self.type in invalid_move_types:
|
||||
moves = Move.search([
|
||||
['OR',
|
||||
('to_location', '=', self.id),
|
||||
('from_location', '=', self.id),
|
||||
],
|
||||
('state', 'not in', ['staging', 'draft']),
|
||||
],
|
||||
order=[], limit=1)
|
||||
if moves:
|
||||
raise LocationValidationError(
|
||||
gettext('stock.msg_location_invalid_type_for_moves',
|
||||
location=self.rec_name,
|
||||
type=self.type_string))
|
||||
|
||||
@classmethod
|
||||
def check_inactive(cls, locations):
|
||||
"Check inactive location are empty"
|
||||
assert all(not l.active for l in locations)
|
||||
empty = cls.get_empty_locations(locations)
|
||||
non_empty = set(locations) - set(empty)
|
||||
if non_empty:
|
||||
raise LocationValidationError(
|
||||
gettext('stock.msg_location_inactive_not_empty',
|
||||
location=next(iter(non_empty)).rec_name))
|
||||
|
||||
@classmethod
|
||||
def get_empty_locations(cls, locations=None):
|
||||
pool = Pool()
|
||||
Move = pool.get('stock.move')
|
||||
Product = pool.get('product.product')
|
||||
if locations is None:
|
||||
locations = cls.search([])
|
||||
if not locations:
|
||||
return []
|
||||
location_ids = list(map(int, locations))
|
||||
with without_check_access(), inactive_records():
|
||||
query = Move.compute_quantities_query(
|
||||
location_ids, with_childs=True)
|
||||
quantities = Move.compute_quantities(
|
||||
query, location_ids, with_childs=True)
|
||||
empty = set(location_ids)
|
||||
product_ids = [q[1] for q in quantities.keys()]
|
||||
consumables = {
|
||||
p.id for p in Product.browse(product_ids) if p.consumable}
|
||||
for (location_id, product), quantity in quantities.items():
|
||||
if quantity and product not in consumables:
|
||||
empty.discard(location_id)
|
||||
for sub_ids in grouped_slice(list(empty)):
|
||||
sub_ids = list(sub_ids)
|
||||
moves = Move.search([
|
||||
('state', 'not in', ['done', 'cancelled']),
|
||||
['OR',
|
||||
('from_location', 'in', sub_ids),
|
||||
('to_location', 'in', sub_ids),
|
||||
],
|
||||
])
|
||||
for move in moves:
|
||||
for location in [move.from_location, move.to_location]:
|
||||
empty.discard(location.id)
|
||||
return cls.browse(empty)
|
||||
|
||||
@staticmethod
|
||||
def default_left():
|
||||
return 0
|
||||
|
||||
@staticmethod
|
||||
def default_right():
|
||||
return 0
|
||||
|
||||
@classmethod
|
||||
def default_flat_childs(cls):
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def default_type():
|
||||
return 'storage'
|
||||
|
||||
def get_warehouse(self, name):
|
||||
# Order by descending left to get the first one in the tree
|
||||
with inactive_records():
|
||||
locations = self.search([
|
||||
('parent', 'parent_of', [self.id]),
|
||||
('type', '=', 'warehouse'),
|
||||
], order=[('left', 'DESC')])
|
||||
if locations:
|
||||
return locations[0].id
|
||||
|
||||
@classmethod
|
||||
def get_default_warehouse(cls):
|
||||
warehouse = Transaction().context.get('warehouse')
|
||||
if warehouse:
|
||||
return warehouse
|
||||
|
||||
warehouse = cls._default_warehouse_cache.get(None, -1)
|
||||
if warehouse == -1:
|
||||
warehouses = cls.search([
|
||||
('type', '=', 'warehouse'),
|
||||
], limit=2)
|
||||
if len(warehouses) == 1:
|
||||
warehouse = warehouses[0].id
|
||||
else:
|
||||
warehouse = None
|
||||
cls._default_warehouse_cache.set(None, warehouse)
|
||||
return warehouse
|
||||
|
||||
@property
|
||||
def lost_found_used(self):
|
||||
if self.warehouse:
|
||||
return self.warehouse.lost_found_location
|
||||
|
||||
def get_rec_name(self, name):
|
||||
if self.code:
|
||||
return f'[{self.code}] {self.name}'
|
||||
else:
|
||||
return self.name
|
||||
|
||||
@classmethod
|
||||
def search_rec_name(cls, name, clause):
|
||||
if clause[1].startswith('!') or clause[1].startswith('not '):
|
||||
bool_op = 'AND'
|
||||
else:
|
||||
bool_op = 'OR'
|
||||
return [bool_op,
|
||||
(cls._rec_name,) + tuple(clause[1:]),
|
||||
('code',) + tuple(clause[1:]),
|
||||
]
|
||||
|
||||
@classmethod
|
||||
def _get_quantity_grouping(cls):
|
||||
context = Transaction().context
|
||||
grouping, grouping_filter, key = (), (), []
|
||||
if context.get('product') is not None:
|
||||
grouping = ('product',)
|
||||
grouping_filter = ([context['product']],)
|
||||
key = (context['product'],)
|
||||
elif context.get('product_template') is not None:
|
||||
grouping = ('product.template',)
|
||||
grouping_filter = ([context['product_template']],)
|
||||
key = (context['product_template'],)
|
||||
return grouping, grouping_filter, key
|
||||
|
||||
@classmethod
|
||||
def get_quantity(cls, locations, name):
|
||||
pool = Pool()
|
||||
Product = pool.get('product.product')
|
||||
Date_ = pool.get('ir.date')
|
||||
trans_context = Transaction().context
|
||||
|
||||
def valid_context(name):
|
||||
return (trans_context.get(name) is not None
|
||||
and isinstance(trans_context[name], int))
|
||||
|
||||
context = {}
|
||||
if (name == 'quantity'
|
||||
and ((trans_context.get('stock_date_end') or datetime.date.max)
|
||||
> Date_.today())):
|
||||
context['stock_date_end'] = Date_.today()
|
||||
|
||||
if name == 'forecast_quantity':
|
||||
context['forecast'] = True
|
||||
if not trans_context.get('stock_date_end'):
|
||||
context['stock_date_end'] = datetime.date.max
|
||||
|
||||
grouping, grouping_filter, key = cls._get_quantity_grouping()
|
||||
if not grouping:
|
||||
return {loc.id: None for loc in locations}
|
||||
|
||||
pbl = {}
|
||||
for sub_locations in grouped_slice(locations):
|
||||
location_ids = [l.id for l in sub_locations]
|
||||
with Transaction().set_context(context):
|
||||
pbl.update(Product.products_by_location(
|
||||
location_ids,
|
||||
grouping=grouping,
|
||||
grouping_filter=grouping_filter,
|
||||
with_childs=trans_context.get('with_childs', True)))
|
||||
|
||||
return dict((loc.id, pbl.get((loc.id,) + key, 0)) for loc in locations)
|
||||
|
||||
@classmethod
|
||||
def search_quantity(cls, name, domain):
|
||||
_, operator_, operand = domain
|
||||
operator_ = {
|
||||
'=': operator.eq,
|
||||
'>=': operator.ge,
|
||||
'>': operator.gt,
|
||||
'<=': operator.le,
|
||||
'<': operator.lt,
|
||||
'!=': operator.ne,
|
||||
'in': lambda v, l: v in l,
|
||||
'not in': lambda v, l: v not in l,
|
||||
}.get(operator_, lambda v, l: False)
|
||||
|
||||
ids = []
|
||||
for location in cls.search([], order=[('left', 'ASC')]):
|
||||
if operator_(getattr(location, name), operand):
|
||||
ids.append(location.id)
|
||||
return [('id', 'in', ids)]
|
||||
|
||||
@classmethod
|
||||
def get_quantity_uom(cls, locations, name):
|
||||
pool = Pool()
|
||||
Product = pool.get('product.product')
|
||||
Template = pool.get('product.template')
|
||||
context = Transaction().context
|
||||
value = None
|
||||
uom = None
|
||||
if context.get('product') is not None:
|
||||
product = Product(context['product'])
|
||||
uom = product.default_uom
|
||||
elif context.get('product_template') is not None:
|
||||
template = Template(context['product_template'])
|
||||
uom = template.default_uom
|
||||
if uom:
|
||||
value = uom.id
|
||||
return {l.id: value for l in locations}
|
||||
|
||||
@classmethod
|
||||
def get_cost_value(cls, locations, name):
|
||||
pool = Pool()
|
||||
Product = pool.get('product.product')
|
||||
Template = pool.get('product.template')
|
||||
trans_context = Transaction().context
|
||||
cost_values = {l.id: None for l in locations}
|
||||
|
||||
def valid_context(name):
|
||||
return (trans_context.get(name) is not None
|
||||
and isinstance(trans_context[name], int))
|
||||
|
||||
if not any(map(valid_context, ['product', 'product_template'])):
|
||||
return cost_values
|
||||
|
||||
def get_record():
|
||||
if trans_context.get('product') is not None:
|
||||
return Product(trans_context['product'])
|
||||
else:
|
||||
return Template(trans_context['product_template'])
|
||||
|
||||
context = {}
|
||||
if trans_context.get('stock_date_end') is not None:
|
||||
# Use the last cost_price of the day
|
||||
context['_datetime'] = datetime.datetime.combine(
|
||||
trans_context['stock_date_end'], datetime.time.max)
|
||||
# The date could be before the product creation
|
||||
record = get_record()
|
||||
if record.create_date > context['_datetime']:
|
||||
return cost_values
|
||||
with Transaction().set_context(context):
|
||||
cost_price = get_record().cost_price
|
||||
# The template may have more than one product
|
||||
if cost_price is not None:
|
||||
for location in locations:
|
||||
cost_values[location.id] = round_price(
|
||||
Decimal(str(location.quantity)) * cost_price)
|
||||
return cost_values
|
||||
|
||||
@classmethod
|
||||
def _set_warehouse_parent(cls, locations):
|
||||
'''
|
||||
Set the parent of child location of warehouse if not set
|
||||
'''
|
||||
to_update = set()
|
||||
to_save = []
|
||||
for location in locations:
|
||||
if location.type == 'warehouse':
|
||||
if not location.input_location.parent:
|
||||
to_update.add(location.input_location)
|
||||
if not location.output_location.parent:
|
||||
to_update.add(location.output_location)
|
||||
if not location.storage_location.parent:
|
||||
to_update.add(location.storage_location)
|
||||
if to_update:
|
||||
for child_location in to_update:
|
||||
child_location.parent = location
|
||||
to_save.append(child_location)
|
||||
to_update.clear()
|
||||
cls.save(to_save)
|
||||
|
||||
@classmethod
|
||||
def on_modification(cls, mode, locations, field_names=None):
|
||||
super().on_modification(mode, locations, field_names=field_names)
|
||||
if mode in {'create', 'write'}:
|
||||
cls._set_warehouse_parent(locations)
|
||||
cls._default_warehouse_cache.clear()
|
||||
|
||||
@classmethod
|
||||
def check_modification(cls, mode, locations, values=None, external=False):
|
||||
super().check_modification(
|
||||
mode, locations, values=values, external=external)
|
||||
if mode == 'write' and 'parent' in values:
|
||||
warehouses = cls.search([
|
||||
('type', '=', 'warehouse'),
|
||||
])
|
||||
cls.validate_fields(
|
||||
warehouses,
|
||||
{'storage_location', 'input_location', 'output_location'})
|
||||
|
||||
@classmethod
|
||||
def delete(cls, locations):
|
||||
# Delete also required children as CASCADING is done separately
|
||||
extra_locations = []
|
||||
for location in locations:
|
||||
extra_locations.extend(filter(None, [
|
||||
location.input_location,
|
||||
location.output_location,
|
||||
location.storage_location,
|
||||
]))
|
||||
super().delete(locations + extra_locations)
|
||||
|
||||
@classmethod
|
||||
def copy(cls, locations, default=None):
|
||||
if default is None:
|
||||
default = {}
|
||||
else:
|
||||
default = default.copy()
|
||||
|
||||
res = []
|
||||
for location in locations:
|
||||
if location.type == 'warehouse':
|
||||
|
||||
wh_default = default.copy()
|
||||
wh_default['type'] = 'view'
|
||||
wh_default['input_location'] = None
|
||||
wh_default['output_location'] = None
|
||||
wh_default['storage_location'] = None
|
||||
wh_default['childs'] = None
|
||||
|
||||
new_location, = super().copy([location],
|
||||
default=wh_default)
|
||||
|
||||
with Transaction().set_context(
|
||||
cp_warehouse_locations={
|
||||
'input_location': location.input_location.id,
|
||||
'output_location': location.output_location.id,
|
||||
'storage_location': location.storage_location.id,
|
||||
},
|
||||
cp_warehouse_id=new_location.id):
|
||||
cls.copy(location.childs,
|
||||
default={'parent': new_location.id})
|
||||
cls.write([new_location], {
|
||||
'type': 'warehouse',
|
||||
})
|
||||
else:
|
||||
new_location, = super().copy([location],
|
||||
default=default)
|
||||
warehouse_locations = Transaction().context.get(
|
||||
'cp_warehouse_locations') or {}
|
||||
if location.id in warehouse_locations.values():
|
||||
cp_warehouse = cls(
|
||||
Transaction().context['cp_warehouse_id'])
|
||||
for field, loc_id in warehouse_locations.items():
|
||||
if loc_id == location.id:
|
||||
cls.write([cp_warehouse], {
|
||||
field: new_location.id,
|
||||
})
|
||||
|
||||
res.append(new_location)
|
||||
return res
|
||||
|
||||
@classmethod
|
||||
def view_attributes(cls):
|
||||
storage_types = Eval('type').in_(['storage', 'warehouse', 'view'])
|
||||
return super().view_attributes() + [
|
||||
('/tree/field[@name="quantity"]',
|
||||
'visual', If(
|
||||
storage_types & (Eval('quantity', 0) < 0), 'danger', ''),
|
||||
['type']),
|
||||
('/tree/field[@name="forecast_quantity"]',
|
||||
'visual', If(
|
||||
storage_types & (Eval('forecast_quantity', 0) < 0),
|
||||
'warning', ''),
|
||||
['type']),
|
||||
]
|
||||
|
||||
|
||||
class ProductsByLocationsContext(ModelView):
|
||||
__name__ = 'stock.products_by_locations.context'
|
||||
|
||||
company = fields.Many2One('company.company', "Company", required=True)
|
||||
forecast_date = fields.Date(
|
||||
'At Date',
|
||||
help="The date for which the stock quantity is calculated.\n"
|
||||
"* An empty value calculates as far ahead as possible.\n"
|
||||
"* A date in the past will provide historical values.")
|
||||
stock_date_end = fields.Function(fields.Date('At Date'),
|
||||
'on_change_with_stock_date_end')
|
||||
|
||||
@classmethod
|
||||
def default_company(cls):
|
||||
return Transaction().context.get('company')
|
||||
|
||||
@staticmethod
|
||||
def default_forecast_date():
|
||||
Date_ = Pool().get('ir.date')
|
||||
return Date_.today()
|
||||
|
||||
@fields.depends('forecast_date')
|
||||
def on_change_with_stock_date_end(self, name=None):
|
||||
if self.forecast_date is None:
|
||||
return datetime.date.max
|
||||
return self.forecast_date
|
||||
|
||||
|
||||
class ProductsByLocations(DeactivableMixin, ModelSQL, ModelView):
|
||||
__name__ = 'stock.products_by_locations'
|
||||
|
||||
product = fields.Many2One('product.product', "Product")
|
||||
quantity = fields.Function(
|
||||
fields.Float("Quantity", digits='default_uom'),
|
||||
'get_product', searcher='search_product')
|
||||
forecast_quantity = fields.Function(
|
||||
fields.Float("Forecast Quantity", digits='default_uom'),
|
||||
'get_product', searcher='search_product')
|
||||
default_uom = fields.Function(
|
||||
fields.Many2One(
|
||||
'product.uom', "Default UoM",
|
||||
help="The default Unit of Measure."),
|
||||
'get_product', searcher='search_product')
|
||||
cost_value = fields.Function(
|
||||
fields.Numeric("Cost Value"), 'get_product')
|
||||
consumable = fields.Function(
|
||||
fields.Boolean("Consumable"), 'get_product',
|
||||
searcher='search_product')
|
||||
|
||||
@classmethod
|
||||
def __setup__(cls):
|
||||
super().__setup__()
|
||||
cls._order.insert(0, ('product', 'ASC'))
|
||||
|
||||
@classmethod
|
||||
def table_query(cls):
|
||||
pool = Pool()
|
||||
Product = pool.get('product.product')
|
||||
product = Product.__table__()
|
||||
columns = []
|
||||
for fname, field in cls._fields.items():
|
||||
if not hasattr(field, 'set'):
|
||||
if (isinstance(field, fields.Many2One)
|
||||
and field.get_target() == Product):
|
||||
column = Column(product, 'id')
|
||||
else:
|
||||
column = Column(product, fname)
|
||||
columns.append(column.as_(fname))
|
||||
return product.select(*columns)
|
||||
|
||||
def get_rec_name(self, name):
|
||||
return self.product.rec_name
|
||||
|
||||
@classmethod
|
||||
def search_rec_name(cls, name, clause):
|
||||
return [('product.rec_name',) + tuple(clause[1:])]
|
||||
|
||||
def get_product(self, name):
|
||||
value = getattr(self.product, name)
|
||||
if isinstance(value, Model):
|
||||
value = value.id
|
||||
return value
|
||||
|
||||
@classmethod
|
||||
def search_product(cls, name, clause):
|
||||
nested = clause[0][len(name):]
|
||||
return [('product.' + name + nested, *clause[1:])]
|
||||
|
||||
|
||||
class LocationLeadTime(sequence_ordered(), ModelSQL, ModelView, MatchMixin):
|
||||
__name__ = 'stock.location.lead_time'
|
||||
|
||||
warehouse_from = fields.Many2One('stock.location', 'Warehouse From',
|
||||
ondelete='CASCADE',
|
||||
domain=[
|
||||
('type', '=', 'warehouse'),
|
||||
('id', '!=', Eval('warehouse_to', -1)),
|
||||
])
|
||||
warehouse_to = fields.Many2One('stock.location', 'Warehouse To',
|
||||
ondelete='CASCADE',
|
||||
domain=[
|
||||
('type', '=', 'warehouse'),
|
||||
('id', '!=', Eval('warehouse_from', -1)),
|
||||
])
|
||||
lead_time = fields.TimeDelta(
|
||||
"Lead Time",
|
||||
domain=['OR',
|
||||
('lead_time', '=', None),
|
||||
('lead_time', '>=', TimeDelta()),
|
||||
],
|
||||
help="The time it takes to move stock between the warehouses.")
|
||||
|
||||
@classmethod
|
||||
def get_lead_time(cls, pattern):
|
||||
for record in cls.search([]):
|
||||
if record.match(pattern):
|
||||
return record.lead_time
|
||||
273
modules/stock/location.xml
Normal file
273
modules/stock/location.xml
Normal file
@@ -0,0 +1,273 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
this repository contains the full copyright notices and license terms. -->
|
||||
<tryton>
|
||||
<data>
|
||||
<record model="ir.ui.view" id="location_view_form">
|
||||
<field name="model">stock.location</field>
|
||||
<field name="type">form</field>
|
||||
<field name="name">location_form</field>
|
||||
</record>
|
||||
<record model="ir.ui.view" id="location_view_tree">
|
||||
<field name="model">stock.location</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="priority" eval="20"/>
|
||||
<field name="field_childs">childs</field>
|
||||
<field name="name">location_tree</field>
|
||||
</record>
|
||||
<record model="ir.ui.view" id="location_view_list">
|
||||
<field name="model">stock.location</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="priority" eval="10"/>
|
||||
<field name="name">location_list</field>
|
||||
</record>
|
||||
<record model="ir.ui.view" id="location_view_list_warehouse">
|
||||
<field name="model">stock.location</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="priority" eval="20"/>
|
||||
<field name="name">location_tree</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.action.act_window" id="act_warehouse_list">
|
||||
<field name="name">Warehouses</field>
|
||||
<field name="res_model">stock.location</field>
|
||||
<field
|
||||
name="context"
|
||||
eval="{'with_childs': True, 'stock_skip_warehouse': False}"
|
||||
pyson="1"/>
|
||||
<field name="domain" eval="[('type', '=', 'warehouse')]" pyson="1"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_warehouse_list_view1">
|
||||
<field name="sequence" eval="10"/>
|
||||
<field name="view" ref="location_view_list_warehouse"/>
|
||||
<field name="act_window" ref="act_warehouse_list"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_warehouse_list_view2">
|
||||
<field name="sequence" eval="20"/>
|
||||
<field name="view" ref="location_view_form"/>
|
||||
<field name="act_window" ref="act_warehouse_list"/>
|
||||
</record>
|
||||
<menuitem
|
||||
parent="menu_stock"
|
||||
action="act_warehouse_list"
|
||||
sequence="30"
|
||||
id="menu_warehouse_list"/>
|
||||
|
||||
<record model="ir.action.act_window" id="act_location_tree">
|
||||
<field name="name">Locations</field>
|
||||
<field name="res_model">stock.location</field>
|
||||
<field name="search_value" eval="[('type', 'in', ['storage', 'view', 'warehouse'])]" pyson="1"/>
|
||||
<field name="domain" eval="[('parent', '=', None)]" pyson="1"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_location_tree_view1">
|
||||
<field name="sequence" eval="10"/>
|
||||
<field name="view" ref="location_view_tree"/>
|
||||
<field name="act_window" ref="act_location_tree"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_location_tree_view2">
|
||||
<field name="sequence" eval="20"/>
|
||||
<field name="view" ref="location_view_form"/>
|
||||
<field name="act_window" ref="act_location_tree"/>
|
||||
</record>
|
||||
<menuitem
|
||||
parent="menu_stock"
|
||||
action="act_location_tree"
|
||||
sequence="30"
|
||||
id="menu_location_tree"/>
|
||||
|
||||
<record model="ir.action.act_window" id="act_location_list">
|
||||
<field name="name">Locations</field>
|
||||
<field name="res_model">stock.location</field>
|
||||
<field name="search_value" eval="[('type', 'in', ['storage', 'view', 'warehouse'])]" pyson="1"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_location_list_view1">
|
||||
<field name="sequence" eval="10"/>
|
||||
<field name="view" ref="location_view_list_warehouse"/>
|
||||
<field name="act_window" ref="act_location_list"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_location_list_view2">
|
||||
<field name="sequence" eval="20"/>
|
||||
<field name="view" ref="location_view_form"/>
|
||||
<field name="act_window" ref="act_location_list"/>
|
||||
</record>
|
||||
<menuitem
|
||||
parent="menu_location_tree"
|
||||
action="act_location_list"
|
||||
sequence="10"
|
||||
id="menu_location_list"/>
|
||||
|
||||
<record model="ir.action.act_window" id="act_location_form">
|
||||
<field name="name">Locations</field>
|
||||
<field name="res_model">stock.location</field>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_location_form_view1">
|
||||
<field name="sequence" eval="10"/>
|
||||
<field name="view" ref="location_view_list"/>
|
||||
<field name="act_window" ref="act_location_form"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_location_form_view2">
|
||||
<field name="sequence" eval="20"/>
|
||||
<field name="view" ref="location_view_form"/>
|
||||
<field name="act_window" ref="act_location_form"/>
|
||||
</record>
|
||||
<menuitem
|
||||
parent="menu_configuration"
|
||||
action="act_location_form"
|
||||
sequence="20"
|
||||
id="menu_location_form"/>
|
||||
|
||||
<record model="ir.ui.view"
|
||||
id="products_by_locations_context_view_form">
|
||||
<field
|
||||
name="model">stock.products_by_locations.context</field>
|
||||
<field name="type">form</field>
|
||||
<field name="name">products_by_locations_context_form</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="products_by_locations_view_list">
|
||||
<field name="model">stock.products_by_locations</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="name">products_by_locations_list</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.action.act_window" id="act_products_by_locations_relate">
|
||||
<field name="name">Products</field>
|
||||
<field name="res_model">stock.products_by_locations</field>
|
||||
<field name="context" eval="{'locations': Eval('active_ids')}" pyson="1"/>
|
||||
<field name="domain"
|
||||
eval="['OR', ('quantity', '!=', 0.0), ('forecast_quantity', '!=', 0.0)]"
|
||||
pyson="1"/>
|
||||
<field name="search_value"
|
||||
eval="[('consumable', '=', False)]"
|
||||
pyson="1"/>
|
||||
<field name="context_model">stock.products_by_locations.context</field>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_products_by_locations_relate_view1">
|
||||
<field name="sequence" eval="10"/>
|
||||
<field name="view" ref="products_by_locations_view_list"/>
|
||||
<field name="act_window" ref="act_products_by_locations_relate"/>
|
||||
</record>
|
||||
<record model="ir.action.keyword" id="act_products_by_locations_relate_keyword1">
|
||||
<field name="keyword">tree_open</field>
|
||||
<field name="model">stock.location,-1</field>
|
||||
<field name="action" ref="act_products_by_locations_relate"/>
|
||||
</record>
|
||||
<record model="ir.action.keyword" id="act_products_by_locations_relate_keyword2">
|
||||
<field name="keyword">form_relate</field>
|
||||
<field name="model">stock.location,-1</field>
|
||||
<field name="action" ref="act_products_by_locations_relate"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.access" id="access_location">
|
||||
<field name="model">stock.location</field>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
<field name="perm_create" eval="False"/>
|
||||
<field name="perm_delete" eval="False"/>
|
||||
</record>
|
||||
<record model="ir.model.access" id="access_location_admin">
|
||||
<field name="model">stock.location</field>
|
||||
<field name="group" ref="group_stock_admin"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="True"/>
|
||||
<field name="perm_create" eval="True"/>
|
||||
<field name="perm_delete" eval="True"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="location_lead_time_view_list">
|
||||
<field name="model">stock.location.lead_time</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="name">location_lead_time_list</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="location_lead_time_view_form">
|
||||
<field name="model">stock.location.lead_time</field>
|
||||
<field name="type">form</field>
|
||||
<field name="name">location_lead_time_form</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.action.act_window" id="act_location_lead_time_form">
|
||||
<field name="name">Location Lead Times</field>
|
||||
<field name="res_model">stock.location.lead_time</field>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view"
|
||||
id="act_location_lead_time_form_view1">
|
||||
<field name="sequence" eval="10"/>
|
||||
<field name="view" ref="location_lead_time_view_list"/>
|
||||
<field name="act_window" ref="act_location_lead_time_form"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view"
|
||||
id="act_location_lead_time_form_view2">
|
||||
<field name="sequence" eval="20"/>
|
||||
<field name="view" ref="location_lead_time_view_form"/>
|
||||
<field name="act_window" ref="act_location_lead_time_form"/>
|
||||
</record>
|
||||
|
||||
<menuitem
|
||||
parent="menu_configuration"
|
||||
action="act_location_lead_time_form"
|
||||
sequence="50"
|
||||
id="menu_location_lead_time_form"/>
|
||||
|
||||
<record model="ir.model.access" id="access_location_lead_time">
|
||||
<field name="model">stock.location.lead_time</field>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
<field name="perm_create" eval="False"/>
|
||||
<field name="perm_delete" eval="False"/>
|
||||
</record>
|
||||
<record model="ir.model.access" id="access_location_lead_time_admin">
|
||||
<field name="model">stock.location.lead_time</field>
|
||||
<field name="group" ref="group_stock_admin"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="True"/>
|
||||
<field name="perm_create" eval="True"/>
|
||||
<field name="perm_delete" eval="True"/>
|
||||
</record>
|
||||
</data>
|
||||
<data noupdate="1">
|
||||
<!-- Default locations -->
|
||||
<record model="stock.location" id="location_input">
|
||||
<field name="name">Input Zone</field>
|
||||
<field name="code">IN</field>
|
||||
<field name="type">storage</field>
|
||||
</record>
|
||||
<record model="stock.location" id="location_output">
|
||||
<field name="name">Output Zone</field>
|
||||
<field name="code">OUT</field>
|
||||
<field name="type">storage</field>
|
||||
</record>
|
||||
<record model="stock.location" id="location_storage">
|
||||
<field name="name">Storage Zone</field>
|
||||
<field name="code">STO</field>
|
||||
<field name="type">storage</field>
|
||||
</record>
|
||||
<record model="stock.location" id="location_lost_found">
|
||||
<field name="name">Lost and Found</field>
|
||||
<field name="type">lost_found</field>
|
||||
</record>
|
||||
<record model="stock.location" id="location_warehouse">
|
||||
<field name="name">Warehouse</field>
|
||||
<field name="code">WH</field>
|
||||
<field name="type">warehouse</field>
|
||||
<field name="input_location" ref="location_input"/>
|
||||
<field name="output_location" ref="location_output"/>
|
||||
<field name="storage_location" ref="location_storage"/>
|
||||
<field name="lost_found_location" ref="location_lost_found"/>
|
||||
</record>
|
||||
<record model="stock.location" id="location_supplier">
|
||||
<field name="name">Supplier</field>
|
||||
<field name="code">SUP</field>
|
||||
<field name="type">supplier</field>
|
||||
</record>
|
||||
<record model="stock.location" id="location_customer">
|
||||
<field name="name">Customer</field>
|
||||
<field name="code">CUS</field>
|
||||
<field name="type">customer</field>
|
||||
</record>
|
||||
<record model="stock.location" id="location_transit">
|
||||
<field name="name">Transit</field>
|
||||
<field name="type">storage</field>
|
||||
</record>
|
||||
</data>
|
||||
</tryton>
|
||||
153
modules/stock/message.xml
Normal file
153
modules/stock/message.xml
Normal file
@@ -0,0 +1,153 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
this repository contains the full copyright notices and license terms. -->
|
||||
<tryton>
|
||||
<data grouped="1">
|
||||
<record model="ir.message" id="msg_product_change_default_uom">
|
||||
<field name="text">You cannot change the default unit of measure of a product which is associated with stock moves.</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_product_change_type">
|
||||
<field name="text">You cannot change the type of a product which is associated with stock moves.</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_product_change_cost_price">
|
||||
<field name="text">You cannot change the cost price of a product which is associated with stock moves.
|
||||
You must use the "Modify Cost Price" wizard.</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_product_quantities_max">
|
||||
<field name="text">You cannot select more than %(max)s products to compute quantities.</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_invalid_cost_price">
|
||||
<field name="text">Invalid cost price "%(cost_price)s" for product "%(product)s" with exception "%(exception)s".</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_invalid_cost_price_not_number">
|
||||
<field name="text">The value "%(value)s" of "%(cost_price)s" for product "%(product)s" is not a number.</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_location_invalid_type_for_moves">
|
||||
<field name="text">You cannot change the type of location "%(location)s" to "%(type)s"
|
||||
because the type does not support moves and location has existing moves.</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_location_inactive_not_empty">
|
||||
<field name="text">To inactivate location "%(location)s", you must empty it.</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_period_close_date">
|
||||
<field name="text">You cannot close periods with a date in the future or today.</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_period_close_assigned_move">
|
||||
<field name="text">To close the period "%(period)s", the assigned moves "%(moves)s" must be done or cancelled.</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_shipment_planned_date">
|
||||
<field name="text">Planned Date</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_shipment_planned_date_help">
|
||||
<field name="text">When the stock operation is expected to be completed.</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_shipment_origin_planned_date">
|
||||
<field name="text">Origin Planned Date</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_shipment_origin_planned_date_help">
|
||||
<field name="text">When the stock operation was initially expected to be completed.</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_shipment_effective_date">
|
||||
<field name="text">Effective Date</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_shipment_effective_date_help">
|
||||
<field name="text">When the stock operation was actually completed.</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_shipment_delay">
|
||||
<field name="text">Delay</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_shipment_pack_inventory_done">
|
||||
<field name="text">To pack shipment "%(shipment)s" you must do the inventory moves.</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_shipment_delete_cancel">
|
||||
<field name="text">To delete shipment "%(shipment)s" you must cancel it.</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_shipment_check_quantity">
|
||||
<field name="text">The quantities of shipment "%(shipment)s" are different by %(quantities)s.</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_inventory_delete_cancel">
|
||||
<field name="text">To delete inventory "%(inventory)s" you must cancel it.</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_inventory_missing_empty_quantity">
|
||||
<field name="text">To confirm the inventory "%(inventory)s" you must select an option for empty quantity.</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_inventory_location_missing_lost_found">
|
||||
<field name="text">To confirm the inventory "%(inventory)s" you must set a lost and found on a parent of location "%(location)s".</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_inventory_line_unique">
|
||||
<field name="text">Inventory line "%(line)s" is not unique on inventory "%(inventory)s".</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_inventory_line_quantity_positive">
|
||||
<field name="text">Inventory line quantity must be positive.</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_inventory_line_delete_cancel">
|
||||
<field name="text">To delete inventory line "%(line)s" you must cancel inventory "%(inventory)s".</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_inventory_count_create_line">
|
||||
<field name="text">No existing line found for "%(search)s".</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_erase_party_shipment">
|
||||
<field name="text">You cannot erase party "%(party)s" while they have pending shipments with company "%(company)s".</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_move_delete_draft_cancel">
|
||||
<field name="text">To delete stock move "%(move)s" you must cancel it or reset its state to draft.</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_move_modify_period_close">
|
||||
<field name="text">To modify stock move "%(move)s" you must reopen period "%(period)s".</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_move_modify_assigned">
|
||||
<field name="text">To modify stock move "%(move)s" you must reset its state to draft.</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_move_modify_done">
|
||||
<field name="text">You cannot modify stock move "%(move)s" because it is done.</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_move_modify_cancelled">
|
||||
<field name="text">You cannot modify stock move "%(move)s" because it is cancelled.</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_move_no_origin">
|
||||
<field name="text">Stock moves "%(moves)s" have no origin.</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_move_quantity_positive">
|
||||
<field name="text">Move quantity must be positive.</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_move_internal_quantity_positive">
|
||||
<field name="text">Internal move quantity must be positive.</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_move_from_to_location">
|
||||
<field name="text">The source and destination of stock move must be different.</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_move_effective_date_in_the_future">
|
||||
<field name="text">The moves "%(moves)s" have effective dates in the future.</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_stock_reporting_company">
|
||||
<field name="text">Company</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_stock_reporting_number">
|
||||
<field name="text">Number</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_stock_reporting_cost">
|
||||
<field name="text">Cost</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_stock_reporting_revenue">
|
||||
<field name="text">Revenue</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_stock_reporting_profit">
|
||||
<field name="text">Profit</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_stock_reporting_margin">
|
||||
<field name="text">Margin</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_stock_reporting_margin_trend">
|
||||
<field name="text">Margin Trend</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_stock_reporting_currency">
|
||||
<field name="text">Currency</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_product_location_quantity">
|
||||
<field name="text">The product "%(product)s" has still some quantities in locations "%(locations)s" for company "%(company)s".</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_product_location_quantity_description">
|
||||
<field name="text">It is recommended to clear the stock from the storage locations before deactivating the product.</field>
|
||||
</record>
|
||||
</data>
|
||||
</tryton>
|
||||
1842
modules/stock/move.py
Normal file
1842
modules/stock/move.py
Normal file
File diff suppressed because it is too large
Load Diff
175
modules/stock/move.xml
Normal file
175
modules/stock/move.xml
Normal file
@@ -0,0 +1,175 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
this repository contains the full copyright notices and license terms. -->
|
||||
<tryton>
|
||||
<data>
|
||||
<record model="ir.ui.view" id="move_view_form">
|
||||
<field name="model">stock.move</field>
|
||||
<field name="type">form</field>
|
||||
<field name="name">move_form</field>
|
||||
</record>
|
||||
<record model="ir.ui.view" id="move_view_tree">
|
||||
<field name="model">stock.move</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="priority" eval="10"/>
|
||||
<field name="name">move_tree</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="move_view_tree_simple">
|
||||
<field name="model">stock.move</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="priority" eval="20"/>
|
||||
<field name="name">move_tree_simple</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="move_view_list_shipment_in">
|
||||
<field name="model">stock.move</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="priority" eval="20"/>
|
||||
<field name="name">move_list_shipment_in</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="move_view_list_shipment">
|
||||
<field name="model">stock.move</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="priority" eval="20"/>
|
||||
<field name="name">move_list_shipment</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.action.act_window" id="act_move_form">
|
||||
<field name="name">Moves</field>
|
||||
<field name="res_model">stock.move</field>
|
||||
<field name="search_value"
|
||||
eval="[('create_date', '>=', DateTime(hour=0, minute=0, second=0, microsecond=0, delta_years=-1))]"
|
||||
pyson="1"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_move_form_view1">
|
||||
<field name="sequence" eval="1"/>
|
||||
<field name="view" ref="move_view_tree"/>
|
||||
<field name="act_window" ref="act_move_form"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_move_form_view2">
|
||||
<field name="sequence" eval="2"/>
|
||||
<field name="view" ref="move_view_form"/>
|
||||
<field name="act_window" ref="act_move_form"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.domain" id="act_move_form_domain_all">
|
||||
<field name="name">All</field>
|
||||
<field name="sequence" eval="10"/>
|
||||
<field name="domain"></field>
|
||||
<field name="act_window" ref="act_move_form"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.domain" id="act_move_form_domain_from_supplier">
|
||||
<field name="name">From Suppliers</field>
|
||||
<field name="sequence" eval="20"/>
|
||||
<field name="domain"
|
||||
eval="[('from_location.type', '=', 'supplier')]" pyson="1"/>
|
||||
<field name="act_window" ref="act_move_form"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.domain" id="act_move_form_domain_from_supplier_waiting">
|
||||
<field name="name">From Suppliers Waiting</field>
|
||||
<field name="sequence" eval="30"/>
|
||||
<field name="domain"
|
||||
eval="[('from_location.type', '=', 'supplier'), ('state', '=', 'draft'), ('shipment', '=', None)]"
|
||||
pyson="1"/>
|
||||
<field name="count" eval="True"/>
|
||||
<field name="act_window" ref="act_move_form"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.domain" id="act_move_form_domain_to_customer">
|
||||
<field name="name">To Customers</field>
|
||||
<field name="sequence" eval="40"/>
|
||||
<field name="domain"
|
||||
eval="[('to_location.type', '=', 'customer')]"
|
||||
pyson="1"/>
|
||||
<field name="act_window" ref="act_move_form"/>
|
||||
</record>
|
||||
<menuitem
|
||||
parent="menu_stock"
|
||||
action="act_move_form"
|
||||
sequence="50"
|
||||
id="menu_move_form"/>
|
||||
<record model="ir.ui.menu-res.group"
|
||||
id="menu_move_form_group_stock">
|
||||
<field name="menu" ref="menu_move_form"/>
|
||||
<field name="group" ref="group_stock_admin"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.rule.group" id="rule_group_move_companies">
|
||||
<field name="name">User in companies</field>
|
||||
<field name="model">stock.move</field>
|
||||
<field name="global_p" eval="True"/>
|
||||
</record>
|
||||
<record model="ir.rule" id="rule_move_companies">
|
||||
<field name="domain"
|
||||
eval="[('company', 'in', Eval('companies', []))]"
|
||||
pyson="1"/>
|
||||
<field name="rule_group" ref="rule_group_move_companies"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.access" id="access_move">
|
||||
<field name="model">stock.move</field>
|
||||
<field name="perm_read" eval="False"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
<field name="perm_create" eval="False"/>
|
||||
<field name="perm_delete" eval="False"/>
|
||||
</record>
|
||||
<record model="ir.model.access" id="access_move_group_stock">
|
||||
<field name="model">stock.move</field>
|
||||
<field name="group" ref="group_stock"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="True"/>
|
||||
<field name="perm_create" eval="True"/>
|
||||
<field name="perm_delete" eval="True"/>
|
||||
</record>
|
||||
<record model="ir.model.button" id="move_cancel_button">
|
||||
<field name="model">stock.move</field>
|
||||
<field name="name">cancel</field>
|
||||
<field name="string">Cancel</field>
|
||||
<field name="confirm">Are you sure you want to cancel the move?</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.button" id="move_draft_button">
|
||||
<field name="model">stock.move</field>
|
||||
<field name="name">draft</field>
|
||||
<field name="string">Reset to Draft</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.button" id="move_do_button">
|
||||
<field name="model">stock.move</field>
|
||||
<field name="name">do</field>
|
||||
<field name="string">Do</field>
|
||||
<field name="confirm">Are you sure you want to complete the move?</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.action.act_window" id="act_product_moves">
|
||||
<field name="name">Stock Moves</field>
|
||||
<field name="res_model">stock.move</field>
|
||||
<field
|
||||
name="domain"
|
||||
eval="[If(Eval('active_ids', []) == [Eval('active_id')], (If(Eval('active_model') == 'product.template', 'product.template', 'product'), '=', Eval('active_id', -1)), (If(Eval('active_model') == 'product.template', 'product.template', 'product'), 'in', Eval('active_ids', [])))]"
|
||||
pyson="1"/>
|
||||
<field name="order" eval="[('effective_date', 'DESC NULLS FIRST')]" pyson="1"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_product_moves_view1">
|
||||
<field name="sequence" eval="10"/>
|
||||
<field name="view" ref="move_view_tree"/>
|
||||
<field name="act_window" ref="act_product_moves"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_product_moves_view2">
|
||||
<field name="sequence" eval="20"/>
|
||||
<field name="view" ref="move_view_form"/>
|
||||
<field name="act_window" ref="act_product_moves"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.action.keyword" id="act_product_moves_keyword1">
|
||||
<field name="keyword">form_relate</field>
|
||||
<field name="model">product.product,-1</field>
|
||||
<field name="action" ref="act_product_moves"/>
|
||||
</record>
|
||||
<record model="ir.action.keyword" id="act_product_moves_keyword2">
|
||||
<field name="keyword">form_relate</field>
|
||||
<field name="model">product.template,-1</field>
|
||||
<field name="action" ref="act_product_moves"/>
|
||||
</record>
|
||||
</data>
|
||||
</tryton>
|
||||
165
modules/stock/party.py
Normal file
165
modules/stock/party.py
Normal file
@@ -0,0 +1,165 @@
|
||||
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
from trytond.i18n import gettext
|
||||
from trytond.model import ModelSQL, ValueMixin, fields
|
||||
from trytond.modules.party.exceptions import EraseError
|
||||
from trytond.pool import Pool, PoolMeta
|
||||
from trytond.transaction import Transaction
|
||||
|
||||
supplier_location = fields.Many2One(
|
||||
'stock.location', "Supplier Location",
|
||||
ondelete='RESTRICT', domain=[('type', '=', 'supplier')],
|
||||
help="The default source location for stock received from the party.")
|
||||
customer_location = fields.Many2One(
|
||||
'stock.location', "Customer Location",
|
||||
ondelete='RESTRICT', domain=[('type', '=', 'customer')],
|
||||
help="The default destination location for stock sent to the party.")
|
||||
|
||||
|
||||
class Party(metaclass=PoolMeta):
|
||||
__name__ = 'party.party'
|
||||
|
||||
supplier_location = fields.MultiValue(supplier_location)
|
||||
customer_location = fields.MultiValue(customer_location)
|
||||
locations = fields.One2Many(
|
||||
'party.party.location', 'party', "Locations")
|
||||
delivered_to_warehouses = fields.Many2Many(
|
||||
'party.party-delivered_to-stock.location', 'party', 'location',
|
||||
"Delivered to Warehouses",
|
||||
domain=[
|
||||
('type', '=', 'warehouse'),
|
||||
],
|
||||
filter=[
|
||||
('allow_pickup', '=', True),
|
||||
])
|
||||
|
||||
@classmethod
|
||||
def multivalue_model(cls, field):
|
||||
pool = Pool()
|
||||
if field in {'supplier_location', 'customer_location'}:
|
||||
return pool.get('party.party.location')
|
||||
return super().multivalue_model(field)
|
||||
|
||||
@classmethod
|
||||
def default_supplier_location(cls, **pattern):
|
||||
return cls.multivalue_model(
|
||||
'supplier_location').default_supplier_location()
|
||||
|
||||
@classmethod
|
||||
def default_customer_location(cls, **pattern):
|
||||
return cls.multivalue_model(
|
||||
'customer_location').default_customer_location()
|
||||
|
||||
def address_get(self, type=None):
|
||||
pool = Pool()
|
||||
Location = pool.get('stock.location')
|
||||
context = Transaction().context
|
||||
address = super().address_get(type=type)
|
||||
if (type == 'delivery'
|
||||
and context.get('warehouse')):
|
||||
warehouse = Location(context['warehouse'])
|
||||
if warehouse in self.delivered_to_warehouses:
|
||||
address = warehouse.address
|
||||
return address
|
||||
|
||||
|
||||
class PartyLocation(ModelSQL, ValueMixin):
|
||||
__name__ = 'party.party.location'
|
||||
party = fields.Many2One('party.party', "Party", ondelete='CASCADE')
|
||||
supplier_location = supplier_location
|
||||
customer_location = customer_location
|
||||
|
||||
@classmethod
|
||||
def default_supplier_location(cls):
|
||||
pool = Pool()
|
||||
ModelData = pool.get('ir.model.data')
|
||||
try:
|
||||
return ModelData.get_id('stock', 'location_supplier')
|
||||
except KeyError:
|
||||
return None
|
||||
|
||||
@classmethod
|
||||
def default_customer_location(cls):
|
||||
pool = Pool()
|
||||
ModelData = pool.get('ir.model.data')
|
||||
try:
|
||||
return ModelData.get_id('stock', 'location_customer')
|
||||
except KeyError:
|
||||
return None
|
||||
|
||||
|
||||
class PartyDeliveredToWarehouse(ModelSQL):
|
||||
__name__ = 'party.party-delivered_to-stock.location'
|
||||
|
||||
party = fields.Many2One(
|
||||
'party.party', "Party", required=True, ondelete='CASCADE')
|
||||
location = fields.Many2One(
|
||||
'stock.location', "Location", required=True, ondelete='CASCADE',
|
||||
domain=[
|
||||
('type', '=', 'warehouse'),
|
||||
])
|
||||
|
||||
|
||||
class Address(metaclass=PoolMeta):
|
||||
__name__ = 'party.address'
|
||||
delivery = fields.Boolean(
|
||||
'Delivery',
|
||||
help="Check to send deliveries to the address.")
|
||||
warehouses = fields.One2Many(
|
||||
'stock.location', 'address', "Warehouses", readonly=True)
|
||||
|
||||
|
||||
class ContactMechanism(metaclass=PoolMeta):
|
||||
__name__ = 'party.contact_mechanism'
|
||||
delivery = fields.Boolean(
|
||||
'Delivery',
|
||||
help="Check to use for delivery.")
|
||||
|
||||
@classmethod
|
||||
def usages(cls, _fields=None):
|
||||
if _fields is None:
|
||||
_fields = []
|
||||
_fields.append('delivery')
|
||||
return super().usages(_fields=_fields)
|
||||
|
||||
|
||||
class Replace(metaclass=PoolMeta):
|
||||
__name__ = 'party.replace'
|
||||
|
||||
@classmethod
|
||||
def fields_to_replace(cls):
|
||||
return super().fields_to_replace() + [
|
||||
('stock.shipment.in', 'supplier'),
|
||||
('stock.shipment.in.return', 'supplier'),
|
||||
('stock.shipment.out', 'customer'),
|
||||
('stock.shipment.out.return', 'customer'),
|
||||
]
|
||||
|
||||
|
||||
class Erase(metaclass=PoolMeta):
|
||||
__name__ = 'party.erase'
|
||||
|
||||
def check_erase_company(self, party, company):
|
||||
pool = Pool()
|
||||
ShipmentIn = pool.get('stock.shipment.in')
|
||||
ShipmentInReturn = pool.get('stock.shipment.in.return')
|
||||
ShipmentOut = pool.get('stock.shipment.out')
|
||||
ShipmentOutReturn = pool.get('stock.shipment.out.return')
|
||||
super().check_erase_company(party, company)
|
||||
|
||||
for Shipment, field in [
|
||||
(ShipmentIn, 'supplier'),
|
||||
(ShipmentInReturn, 'supplier'),
|
||||
(ShipmentOut, 'customer'),
|
||||
(ShipmentOutReturn, 'customer'),
|
||||
]:
|
||||
shipments = Shipment.search([
|
||||
(field, '=', party.id),
|
||||
('company', '=', company.id),
|
||||
('state', 'not in', ['done', 'cancelled']),
|
||||
])
|
||||
if shipments:
|
||||
raise EraseError(
|
||||
gettext('stock.msg_erase_party_shipment',
|
||||
party=party.rec_name,
|
||||
company=company.rec_name))
|
||||
81
modules/stock/party.xml
Normal file
81
modules/stock/party.xml
Normal file
@@ -0,0 +1,81 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
this repository contains the full copyright notices and license terms. -->
|
||||
<tryton>
|
||||
<data>
|
||||
<record model="ir.ui.view" id="party_party_view_form">
|
||||
<field name="model">party.party</field>
|
||||
<field name="inherit" ref="party.party_view_form"/>
|
||||
<field name="name">party_form</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="address_view_tree">
|
||||
<field name="model">party.address</field>
|
||||
<field name="inherit" ref="party.address_view_tree"/>
|
||||
<field name="name">party_address_tree</field>
|
||||
</record>
|
||||
<record model="ir.ui.view" id="address_view_form">
|
||||
<field name="model">party.address</field>
|
||||
<field name="inherit" ref="party.address_view_form"/>
|
||||
<field name="name">party_address_form</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="address_view_form_simple">
|
||||
<field name="model">party.address</field>
|
||||
<field name="inherit" ref="party.address_view_form_simple"/>
|
||||
<field name="name">party_address_form</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="address_view_tree_sequence">
|
||||
<field name="model">party.address</field>
|
||||
<field name="inherit" ref="party.address_view_tree_sequence"/>
|
||||
<field name="name">party_address_tree</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="contact_mechanism_view_tree">
|
||||
<field name="model">party.contact_mechanism</field>
|
||||
<field name="inherit" ref="party.contact_mechanism_view_tree"/>
|
||||
<field name="name">party_contact_mechanism_tree</field>
|
||||
</record>
|
||||
<record model="ir.ui.view" id="contact_mechanism_view_form">
|
||||
<field name="model">party.contact_mechanism</field>
|
||||
<field name="inherit" ref="party.contact_mechanism_view_form"/>
|
||||
<field name="name">party_contact_mechanism_form</field>
|
||||
</record>
|
||||
<record model="ir.ui.view" id="contact_mechanism_view_tree_sequence">
|
||||
<field name="model">party.contact_mechanism</field>
|
||||
<field name="inherit" ref="party.contact_mechanism_view_tree_sequence"/>
|
||||
<field name="name">party_contact_mechanism_tree</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.action.act_window" id="act_shipment_out_form2">
|
||||
<field name="name">Customer Shipments</field>
|
||||
<field name="res_model">stock.shipment.out</field>
|
||||
<field name="domain"
|
||||
eval="[If(Eval('active_ids', []) == [Eval('active_id')], ('customer', '=', Eval('active_id')), ('customer', 'in', Eval('active_ids')))]"
|
||||
pyson="1"/>
|
||||
<field name="search_value" eval="[('state', 'not in', ['done', 'cancelled'])]" pyson="1"/>
|
||||
</record>
|
||||
<record model="ir.action.keyword"
|
||||
id="act_open_purchase_keyword1">
|
||||
<field name="keyword">form_relate</field>
|
||||
<field name="model">party.party,-1</field>
|
||||
<field name="action" ref="act_shipment_out_form2"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.action.act_window" id="act_shipment_out_form3">
|
||||
<field name="name">Supplier Shipments</field>
|
||||
<field name="res_model">stock.shipment.in</field>
|
||||
<field name="domain"
|
||||
eval="[If(Eval('active_ids', []) == [Eval('active_id')], ('supplier', '=', Eval('active_id')), ('supplier', 'in', Eval('active_ids')))]"
|
||||
pyson="1"/>
|
||||
<field name="search_value" eval="[('state', 'not in', ['done', 'cancelled'])]" pyson="1"/>
|
||||
</record>
|
||||
<record model="ir.action.keyword"
|
||||
id="act_open_purchase_keyword2">
|
||||
<field name="keyword">form_relate</field>
|
||||
<field name="model">party.party,-1</field>
|
||||
<field name="action" ref="act_shipment_out_form3"/>
|
||||
</record>
|
||||
</data>
|
||||
</tryton>
|
||||
200
modules/stock/period.py
Normal file
200
modules/stock/period.py
Normal file
@@ -0,0 +1,200 @@
|
||||
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
from itertools import chain, groupby
|
||||
|
||||
from sql import For, Literal
|
||||
|
||||
from trytond.i18n import gettext
|
||||
from trytond.model import Index, ModelSQL, ModelView, Workflow, fields
|
||||
from trytond.pool import Pool
|
||||
from trytond.pyson import Eval
|
||||
from trytond.tools import grouped_slice
|
||||
from trytond.transaction import Transaction
|
||||
|
||||
from .exceptions import PeriodCloseError
|
||||
|
||||
|
||||
class Period(Workflow, ModelSQL, ModelView):
|
||||
__name__ = 'stock.period'
|
||||
date = fields.Date('Date', required=True, states={
|
||||
'readonly': Eval('state') == 'closed',
|
||||
},
|
||||
help="When the stock period ends.")
|
||||
company = fields.Many2One(
|
||||
'company.company', "Company", required=True,
|
||||
help="The company the stock period is associated with.")
|
||||
caches = fields.One2Many('stock.period.cache', 'period', 'Caches',
|
||||
readonly=True)
|
||||
state = fields.Selection([
|
||||
('draft', 'Draft'),
|
||||
('closed', 'Closed'),
|
||||
], "State", readonly=True, sort=False,
|
||||
help="The current state of the stock period.")
|
||||
|
||||
@classmethod
|
||||
def __setup__(cls):
|
||||
super().__setup__()
|
||||
t = cls.__table__()
|
||||
cls._sql_indexes.add(
|
||||
Index(
|
||||
t,
|
||||
(t.company, Index.Range()),
|
||||
(t.date, Index.Range(order='DESC')),
|
||||
where=t.state == 'closed'))
|
||||
cls._transitions |= set((
|
||||
('draft', 'closed'),
|
||||
('closed', 'draft'),
|
||||
))
|
||||
cls._buttons.update({
|
||||
'draft': {
|
||||
'invisible': Eval('state') == 'draft',
|
||||
'depends': ['state'],
|
||||
},
|
||||
'close': {
|
||||
'invisible': Eval('state') == 'closed',
|
||||
'depends': ['state'],
|
||||
},
|
||||
})
|
||||
|
||||
@staticmethod
|
||||
def default_company():
|
||||
return Transaction().context.get('company')
|
||||
|
||||
@staticmethod
|
||||
def default_state():
|
||||
return 'draft'
|
||||
|
||||
@staticmethod
|
||||
def groupings():
|
||||
return [('product',)]
|
||||
|
||||
@staticmethod
|
||||
def get_cache(grouping):
|
||||
pool = Pool()
|
||||
if all(g == 'product' or g.startswith('product.') for g in grouping):
|
||||
return pool.get('stock.period.cache')
|
||||
|
||||
def get_rec_name(self, name):
|
||||
return Pool().get('ir.lang').get().strftime(self.date)
|
||||
|
||||
@classmethod
|
||||
@ModelView.button
|
||||
@Workflow.transition('draft')
|
||||
def draft(cls, periods):
|
||||
for grouping in cls.groupings():
|
||||
Cache = cls.get_cache(grouping)
|
||||
caches = []
|
||||
for sub_periods in grouped_slice(periods):
|
||||
caches.append(Cache.search([
|
||||
('period', 'in',
|
||||
[p.id for p in sub_periods]),
|
||||
], order=[]))
|
||||
Cache.delete(list(chain(*caches)))
|
||||
|
||||
@classmethod
|
||||
@ModelView.button
|
||||
@Workflow.transition('closed')
|
||||
def close(cls, periods):
|
||||
pool = Pool()
|
||||
Product = pool.get('product.product')
|
||||
Location = pool.get('stock.location')
|
||||
Move = pool.get('stock.move')
|
||||
Date = pool.get('ir.date')
|
||||
transaction = Transaction()
|
||||
connection = transaction.connection
|
||||
database = transaction.database
|
||||
|
||||
Move.lock()
|
||||
if database.has_select_for():
|
||||
move = Move.__table__()
|
||||
query = move.select(Literal(1), for_=For('UPDATE', nowait=True))
|
||||
with connection.cursor() as cursor:
|
||||
cursor.execute(*query)
|
||||
|
||||
locations = Location.search([
|
||||
('type', 'not in', ['warehouse', 'view']),
|
||||
], order=[])
|
||||
|
||||
for company, c_periods in groupby(periods, key=lambda p: p.company):
|
||||
c_periods = list(c_periods)
|
||||
with Transaction().set_context(company=company.id):
|
||||
today = Date.today()
|
||||
recent_period = max(c_periods, key=lambda p: p.date)
|
||||
recent_date = recent_period.date
|
||||
if recent_date >= today:
|
||||
raise PeriodCloseError(
|
||||
gettext('stock.msg_period_close_date'))
|
||||
if assigned_moves := Move.search([
|
||||
('company', '=', company.id),
|
||||
('state', '=', 'assigned'),
|
||||
['OR', [
|
||||
('effective_date', '=', None),
|
||||
('planned_date', '<=', recent_date),
|
||||
],
|
||||
('effective_date', '<=', recent_date),
|
||||
]],
|
||||
limit=6):
|
||||
names = ', '.join(m.rec_name for m in assigned_moves[:5])
|
||||
if len(assigned_moves) > 5:
|
||||
names += '...'
|
||||
raise PeriodCloseError(
|
||||
gettext('stock.msg_period_close_assigned_move',
|
||||
period=recent_period.rec_name,
|
||||
moves=names))
|
||||
|
||||
for grouping in cls.groupings():
|
||||
Cache = cls.get_cache(grouping)
|
||||
to_create = []
|
||||
for period in periods:
|
||||
with Transaction().set_context(
|
||||
stock_date_end=period.date,
|
||||
stock_date_start=None,
|
||||
stock_assign=False,
|
||||
forecast=False,
|
||||
stock_destinations=None,
|
||||
):
|
||||
pbl = Product.products_by_location(
|
||||
[l.id for l in locations], grouping=grouping)
|
||||
for key, quantity in pbl.items():
|
||||
if quantity:
|
||||
values = {
|
||||
'location': key[0],
|
||||
'period': period.id,
|
||||
'internal_quantity': quantity,
|
||||
}
|
||||
for i, field in enumerate(grouping, 1):
|
||||
values[field] = key[i]
|
||||
to_create.append(values)
|
||||
if to_create:
|
||||
Cache.create(to_create)
|
||||
|
||||
|
||||
class Cache(ModelSQL, ModelView):
|
||||
"It is used to store cached computation of stock quantities"
|
||||
__name__ = 'stock.period.cache'
|
||||
period = fields.Many2One(
|
||||
'stock.period', "Period",
|
||||
required=True, readonly=True, ondelete='CASCADE')
|
||||
location = fields.Many2One(
|
||||
'stock.location', "Location",
|
||||
required=True, readonly=True, ondelete='CASCADE')
|
||||
product = fields.Many2One(
|
||||
'product.product', "Product",
|
||||
required=True, readonly=True, ondelete='CASCADE')
|
||||
internal_quantity = fields.Float('Internal Quantity', readonly=True)
|
||||
|
||||
@classmethod
|
||||
def __setup__(cls):
|
||||
super().__setup__()
|
||||
t = cls.__table__()
|
||||
cls._sql_indexes.update({
|
||||
Index(
|
||||
t,
|
||||
(t.period, Index.Range()),
|
||||
(t.location, Index.Range()),
|
||||
(t.product, Index.Range()),
|
||||
include=[t.internal_quantity]),
|
||||
Index(
|
||||
t,
|
||||
(t.location, Index.Range())),
|
||||
})
|
||||
120
modules/stock/period.xml
Normal file
120
modules/stock/period.xml
Normal file
@@ -0,0 +1,120 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
this repository contains the full copyright notices and license terms. -->
|
||||
<tryton>
|
||||
<data>
|
||||
<record model="ir.ui.view" id="period_view_form">
|
||||
<field name="model">stock.period</field>
|
||||
<field name="type">form</field>
|
||||
<field name="name">period_form</field>
|
||||
</record>
|
||||
<record model="ir.ui.view" id="period_view_list">
|
||||
<field name="model">stock.period</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="name">period_list</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.action.act_window" id="act_period_list">
|
||||
<field name="name">Periods</field>
|
||||
<field name="res_model">stock.period</field>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_period_list_view1">
|
||||
<field name="sequence" eval="10"/>
|
||||
<field name="view" ref="period_view_list"/>
|
||||
<field name="act_window" ref="act_period_list"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_period_list_view2">
|
||||
<field name="sequence" eval="20"/>
|
||||
<field name="view" ref="period_view_form"/>
|
||||
<field name="act_window" ref="act_period_list"/>
|
||||
</record>
|
||||
<menuitem
|
||||
parent="menu_configuration"
|
||||
action="act_period_list"
|
||||
sequence="30"
|
||||
id="menu_period_list"/>
|
||||
|
||||
<record model="ir.rule.group" id="rule_group_period_companies">
|
||||
<field name="name">User in companies</field>
|
||||
<field name="model">stock.period</field>
|
||||
<field name="global_p" eval="True"/>
|
||||
</record>
|
||||
<record model="ir.rule" id="rule_period_companies">
|
||||
<field name="domain"
|
||||
eval="[('company', 'in', Eval('companies', []))]"
|
||||
pyson="1"/>
|
||||
<field name="rule_group" ref="rule_group_period_companies"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.access" id="access_period">
|
||||
<field name="model">stock.period</field>
|
||||
<field name="perm_read" eval="False"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
<field name="perm_create" eval="False"/>
|
||||
<field name="perm_delete" eval="False"/>
|
||||
</record>
|
||||
<record model="ir.model.access" id="access_period_stock">
|
||||
<field name="model">stock.period</field>
|
||||
<field name="group" ref="group_stock"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
<field name="perm_create" eval="False"/>
|
||||
<field name="perm_delete" eval="False"/>
|
||||
</record>
|
||||
<record model="ir.model.access" id="access_period_admin">
|
||||
<field name="model">stock.period</field>
|
||||
<field name="group" ref="group_stock_admin"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="True"/>
|
||||
<field name="perm_create" eval="True"/>
|
||||
<field name="perm_delete" eval="True"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.button" id="period_draft_button">
|
||||
<field name="model">stock.period</field>
|
||||
<field name="name">draft</field>
|
||||
<field name="string">Draft</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.button" id="period_close_button">
|
||||
<field name="model">stock.period</field>
|
||||
<field name="name">close</field>
|
||||
<field name="string">Close</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="period_cache_view_form">
|
||||
<field name="model">stock.period.cache</field>
|
||||
<field name="type">form</field>
|
||||
<field name="name">period_cache_form</field>
|
||||
</record>
|
||||
<record model="ir.ui.view" id="period_cache_view_list">
|
||||
<field name="model">stock.period.cache</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="name">period_cache_list</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.access" id="access_period_cache_cache">
|
||||
<field name="model">stock.period.cache</field>
|
||||
<field name="perm_read" eval="False"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
<field name="perm_create" eval="False"/>
|
||||
<field name="perm_delete" eval="False"/>
|
||||
</record>
|
||||
<record model="ir.model.access" id="access_period_cache_cache_stock">
|
||||
<field name="model">stock.period.cache</field>
|
||||
<field name="group" ref="group_stock"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
<field name="perm_create" eval="False"/>
|
||||
<field name="perm_delete" eval="False"/>
|
||||
</record>
|
||||
<record model="ir.model.access" id="access_period_cache_admin">
|
||||
<field name="model">stock.period.cache</field>
|
||||
<field name="group" ref="group_stock_admin"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="True"/>
|
||||
<field name="perm_create" eval="True"/>
|
||||
<field name="perm_delete" eval="True"/>
|
||||
</record>
|
||||
</data>
|
||||
</tryton>
|
||||
612
modules/stock/picking_list.fodt
Normal file
612
modules/stock/picking_list.fodt
Normal file
@@ -0,0 +1,612 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<office:document xmlns:css3t="http://www.w3.org/TR/css3-text/" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:rpt="http://openoffice.org/2005/report" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:officeooo="http://openoffice.org/2009/office" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.text">
|
||||
<office:meta><meta:generator>LibreOffice/7.6.4.1$Linux_X86_64 LibreOffice_project/60$Build-1</meta:generator><meta:initial-creator>Bertrand Chenal</meta:initial-creator><meta:creation-date>2009-03-26T13:54:48</meta:creation-date><dc:date>2024-04-19T23:16:38.105151902</dc:date><meta:editing-cycles>55</meta:editing-cycles><meta:editing-duration>PT7H43M47S</meta:editing-duration><meta:document-statistic meta:table-count="1" meta:image-count="0" meta:object-count="0" meta:page-count="3" meta:paragraph-count="49" meta:word-count="117" meta:character-count="1209" meta:non-whitespace-character-count="1140"/><meta:user-defined meta:name="Info 1"/><meta:user-defined meta:name="Info 2"/><meta:user-defined meta:name="Info 3"/><meta:user-defined meta:name="Info 4"/></office:meta>
|
||||
<office:settings>
|
||||
<config:config-item-set config:name="ooo:view-settings">
|
||||
<config:config-item config:name="ViewAreaTop" config:type="long">0</config:config-item>
|
||||
<config:config-item config:name="ViewAreaLeft" config:type="long">0</config:config-item>
|
||||
<config:config-item config:name="ViewAreaWidth" config:type="long">25269</config:config-item>
|
||||
<config:config-item config:name="ViewAreaHeight" config:type="long">23973</config:config-item>
|
||||
<config:config-item config:name="ShowRedlineChanges" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="InBrowseMode" config:type="boolean">false</config:config-item>
|
||||
<config:config-item-map-indexed config:name="Views">
|
||||
<config:config-item-map-entry>
|
||||
<config:config-item config:name="ViewId" config:type="string">view2</config:config-item>
|
||||
<config:config-item config:name="ViewLeft" config:type="long">5955</config:config-item>
|
||||
<config:config-item config:name="ViewTop" config:type="long">10248</config:config-item>
|
||||
<config:config-item config:name="VisibleLeft" config:type="long">0</config:config-item>
|
||||
<config:config-item config:name="VisibleTop" config:type="long">0</config:config-item>
|
||||
<config:config-item config:name="VisibleRight" config:type="long">25268</config:config-item>
|
||||
<config:config-item config:name="VisibleBottom" config:type="long">23971</config:config-item>
|
||||
<config:config-item config:name="ZoomType" config:type="short">0</config:config-item>
|
||||
<config:config-item config:name="ViewLayoutColumns" config:type="short">0</config:config-item>
|
||||
<config:config-item config:name="ViewLayoutBookMode" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="ZoomFactor" config:type="short">100</config:config-item>
|
||||
<config:config-item config:name="IsSelectedFrame" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="KeepRatio" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="AnchoredTextOverflowLegacy" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="LegacySingleLineFontwork" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="ConnectorUseSnapRect" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="IgnoreBreakAfterMultilineField" config:type="boolean">false</config:config-item>
|
||||
</config:config-item-map-entry>
|
||||
</config:config-item-map-indexed>
|
||||
</config:config-item-set>
|
||||
<config:config-item-set config:name="ooo:configuration-settings">
|
||||
<config:config-item config:name="PrintRightPages" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="PrintProspectRTL" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="PrintLeftPages" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="PrintPaperFromSetup" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="PrintControls" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="PrintProspect" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="PrintBlackFonts" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="PrintAnnotationMode" config:type="short">0</config:config-item>
|
||||
<config:config-item config:name="PrintEmptyPages" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="PrintSingleJobs" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="AutoFirstLineIndentDisregardLineSpace" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="HeaderSpacingBelowLastPara" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="ProtectBookmarks" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="ContinuousEndnotes" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="DisableOffPagePositioning" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="PrintTables" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="SubtractFlysAnchoredAtFlys" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="ApplyParagraphMarkFormatToNumbering" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="PrintFaxName" config:type="string"/>
|
||||
<config:config-item config:name="SurroundTextWrapSmall" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="TreatSingleColumnBreakAsPageBreak" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="PropLineSpacingShrinksFirstLine" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="TabOverSpacing" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="TabOverMargin" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="EmbedComplexScriptFonts" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="EmbedLatinScriptFonts" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="EmbedOnlyUsedFonts" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="EmbedFonts" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="ClippedPictures" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="FrameAutowidthWithMorePara" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="FloattableNomargins" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="UnbreakableNumberings" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="AllowPrintJobCancel" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="UseFormerObjectPositioning" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="UseOldNumbering" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="RsidRoot" config:type="int">1812667</config:config-item>
|
||||
<config:config-item config:name="PrinterPaperFromSetup" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="CurrentDatabaseDataSource" config:type="string"/>
|
||||
<config:config-item config:name="UpdateFromTemplate" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="AddFrameOffsets" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="LoadReadonly" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="Rsid" config:type="int">2677670</config:config-item>
|
||||
<config:config-item config:name="FootnoteInColumnToPageEnd" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="ProtectFields" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="SaveGlobalDocumentLinks" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="ClipAsCharacterAnchoredWriterFlyFrames" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="LinkUpdateMode" config:type="short">1</config:config-item>
|
||||
<config:config-item config:name="AddExternalLeading" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="PrintGraphics" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="EmbedSystemFonts" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="IsLabelDocument" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="AddParaLineSpacingToTableCells" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="UseFormerTextWrapping" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="HyphenateURLs" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="AddParaTableSpacingAtStart" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="TabsRelativeToIndent" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="FieldAutoUpdate" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="SaveVersionOnClose" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="ChartAutoUpdate" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="ImagePreferredDPI" config:type="int">0</config:config-item>
|
||||
<config:config-item config:name="PrinterSetup" config:type="base64Binary"/>
|
||||
<config:config-item config:name="SmallCapsPercentage66" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="AlignTabStopPosition" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="DropCapPunctuation" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="MathBaselineAlignment" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="PrinterName" config:type="string"/>
|
||||
<config:config-item config:name="CharacterCompressionType" config:type="short">0</config:config-item>
|
||||
<config:config-item config:name="AddParaTableSpacing" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="DoNotJustifyLinesWithManualBreak" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="PrintHiddenText" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="IsKernAsianPunctuation" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="PrinterIndependentLayout" config:type="string">high-resolution</config:config-item>
|
||||
<config:config-item config:name="TabOverflow" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="AddParaSpacingToTableCells" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="AddVerticalFrameOffsets" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="TabAtLeftIndentForParagraphsInList" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="ApplyUserData" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="MsWordCompMinLineHeightByFly" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="PrintTextPlaceholder" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="IgnoreFirstLineIndentInNumbering" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="UseFormerLineSpacing" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="PrintPageBackground" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="RedlineProtectionKey" config:type="base64Binary"/>
|
||||
<config:config-item config:name="EmbedAsianScriptFonts" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="BackgroundParaOverDrawings" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="SaveThumbnail" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="ConsiderTextWrapOnObjPos" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="EmbeddedDatabaseName" config:type="string"/>
|
||||
<config:config-item config:name="ProtectForm" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="DoNotResetParaAttrsForNumFont" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="MsWordCompTrailingBlanks" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="EmptyDbFieldHidesPara" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="TableRowKeep" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="NoNumberingShowFollowBy" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="InvertBorderSpacing" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="IgnoreTabsAndBlanksForLineCalculation" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="DoNotCaptureDrawObjsOnPage" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="GutterAtTop" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="StylesNoDefault" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="UnxForceZeroExtLeading" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="PrintReversed" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="UseOldPrinterMetrics" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="CurrentDatabaseCommandType" config:type="int">0</config:config-item>
|
||||
<config:config-item config:name="PrintDrawings" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="OutlineLevelYieldsNumbering" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="CurrentDatabaseCommand" config:type="string"/>
|
||||
<config:config-item config:name="CollapseEmptyCellPara" config:type="boolean">true</config:config-item>
|
||||
</config:config-item-set>
|
||||
</office:settings>
|
||||
<office:scripts>
|
||||
<office:script script:language="ooo:Basic">
|
||||
<ooo:libraries xmlns:ooo="http://openoffice.org/2004/office" xmlns:xlink="http://www.w3.org/1999/xlink"/>
|
||||
</office:script>
|
||||
</office:scripts>
|
||||
<office:font-face-decls>
|
||||
<style:font-face style:name="Andale Sans UI" svg:font-family="'Andale Sans UI'" style:font-family-generic="system" style:font-pitch="variable"/>
|
||||
<style:font-face style:name="DejaVu Sans" svg:font-family="'DejaVu Sans'" style:font-family-generic="system" style:font-pitch="variable"/>
|
||||
<style:font-face style:name="Liberation Sans" svg:font-family="'Liberation Sans'" style:font-adornments="Regular" style:font-family-generic="swiss" style:font-pitch="variable"/>
|
||||
<style:font-face style:name="Liberation Serif" svg:font-family="'Liberation Serif'" style:font-family-generic="roman" style:font-pitch="variable"/>
|
||||
<style:font-face style:name="Liberation Serif1" svg:font-family="'Liberation Serif'" style:font-adornments="Bold" style:font-family-generic="roman" style:font-pitch="variable"/>
|
||||
<style:font-face style:name="Liberation Serif2" svg:font-family="'Liberation Serif'" style:font-adornments="Regular" style:font-family-generic="roman" style:font-pitch="variable"/>
|
||||
<style:font-face style:name="StarSymbol" svg:font-family="StarSymbol"/>
|
||||
<style:font-face style:name="Thorndale AMT" svg:font-family="'Thorndale AMT'" style:font-family-generic="roman" style:font-pitch="variable"/>
|
||||
</office:font-face-decls>
|
||||
<office:styles>
|
||||
<style:default-style style:family="graphic">
|
||||
<style:graphic-properties svg:stroke-color="#000000" draw:fill-color="#99ccff" fo:wrap-option="no-wrap" draw:shadow-offset-x="0.3cm" draw:shadow-offset-y="0.3cm" draw:start-line-spacing-horizontal="0.283cm" draw:start-line-spacing-vertical="0.283cm" draw:end-line-spacing-horizontal="0.283cm" draw:end-line-spacing-vertical="0.283cm" style:writing-mode="lr-tb" style:flow-with-text="false"/>
|
||||
<style:paragraph-properties style:text-autospace="ideograph-alpha" style:line-break="strict" loext:tab-stop-distance="0cm" style:writing-mode="lr-tb" style:font-independent-line-spacing="false">
|
||||
<style:tab-stops/>
|
||||
</style:paragraph-properties>
|
||||
<style:text-properties style:use-window-font-color="true" loext:opacity="0%" style:font-name="Thorndale AMT" fo:font-size="12pt" fo:language="en" fo:country="US" style:letter-kerning="true" style:font-name-asian="Andale Sans UI" style:font-size-asian="10.5pt" style:language-asian="zxx" style:country-asian="none" style:font-name-complex="Andale Sans UI" style:font-size-complex="12pt" style:language-complex="zxx" style:country-complex="none"/>
|
||||
</style:default-style>
|
||||
<style:default-style style:family="paragraph">
|
||||
<style:paragraph-properties fo:hyphenation-ladder-count="no-limit" style:text-autospace="ideograph-alpha" style:punctuation-wrap="hanging" style:line-break="strict" style:tab-stop-distance="1.251cm" style:writing-mode="lr-tb"/>
|
||||
<style:text-properties style:use-window-font-color="true" loext:opacity="0%" style:font-name="Thorndale AMT" fo:font-size="12pt" fo:language="en" fo:country="US" style:letter-kerning="true" style:font-name-asian="Andale Sans UI" style:font-size-asian="10.5pt" style:language-asian="zxx" style:country-asian="none" style:font-name-complex="Andale Sans UI" style:font-size-complex="12pt" style:language-complex="zxx" style:country-complex="none" fo:hyphenate="false" fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2" loext:hyphenation-no-caps="false" loext:hyphenation-no-last-word="false" loext:hyphenation-word-char-count="5" loext:hyphenation-zone="no-limit"/>
|
||||
</style:default-style>
|
||||
<style:default-style style:family="table">
|
||||
<style:table-properties table:border-model="collapsing"/>
|
||||
</style:default-style>
|
||||
<style:default-style style:family="table-row">
|
||||
<style:table-row-properties fo:keep-together="auto"/>
|
||||
</style:default-style>
|
||||
<style:style style:name="Standard" style:family="paragraph" style:class="text">
|
||||
<style:text-properties style:font-name="Liberation Sans" fo:font-family="'Liberation Sans'" style:font-style-name="Regular" style:font-family-generic="swiss" style:font-pitch="variable" style:font-size-asian="10.5pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="Heading" style:family="paragraph" style:parent-style-name="Standard" style:next-style-name="Text_20_body" style:class="text">
|
||||
<style:paragraph-properties fo:margin-top="0.423cm" fo:margin-bottom="0.212cm" style:contextual-spacing="false" fo:keep-with-next="always"/>
|
||||
<style:text-properties style:font-name="Liberation Serif2" fo:font-family="'Liberation Serif'" style:font-style-name="Regular" style:font-family-generic="roman" style:font-pitch="variable" fo:font-size="16pt" style:font-name-asian="DejaVu Sans" style:font-family-asian="'DejaVu Sans'" style:font-family-generic-asian="system" style:font-pitch-asian="variable" style:font-size-asian="14pt" style:font-name-complex="DejaVu Sans" style:font-family-complex="'DejaVu Sans'" style:font-family-generic-complex="system" style:font-pitch-complex="variable" style:font-size-complex="14pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="Text_20_body" style:display-name="Text body" style:family="paragraph" style:parent-style-name="Standard" style:class="text">
|
||||
<style:paragraph-properties fo:margin-top="0cm" fo:margin-bottom="0.212cm" style:contextual-spacing="false"/>
|
||||
<style:text-properties style:font-name="Liberation Sans" fo:font-family="'Liberation Sans'" style:font-style-name="Regular" style:font-family-generic="swiss" style:font-pitch="variable" style:font-size-asian="10.5pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="List" style:family="paragraph" style:parent-style-name="Text_20_body" style:class="list">
|
||||
<style:text-properties style:font-size-asian="12pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="Caption" style:family="paragraph" style:parent-style-name="Standard" style:class="extra">
|
||||
<style:paragraph-properties fo:margin-top="0.212cm" fo:margin-bottom="0.212cm" style:contextual-spacing="false" text:number-lines="false" text:line-number="0"/>
|
||||
<style:text-properties fo:font-size="12pt" fo:font-style="italic" style:font-size-asian="12pt" style:font-style-asian="italic" style:font-size-complex="12pt" style:font-style-complex="italic"/>
|
||||
</style:style>
|
||||
<style:style style:name="Index" style:family="paragraph" style:parent-style-name="Standard" style:class="index">
|
||||
<style:paragraph-properties text:number-lines="false" text:line-number="0"/>
|
||||
<style:text-properties style:font-size-asian="12pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="Heading_20_1" style:display-name="Heading 1" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:class="text">
|
||||
<style:text-properties fo:font-size="16pt" fo:font-weight="bold" style:font-size-asian="115%" style:font-weight-asian="bold" style:font-size-complex="115%" style:font-weight-complex="bold"/>
|
||||
</style:style>
|
||||
<style:style style:name="Table_20_Contents" style:display-name="Table Contents" style:family="paragraph" style:parent-style-name="Standard" style:class="extra">
|
||||
<style:paragraph-properties text:number-lines="false" text:line-number="0"/>
|
||||
<style:text-properties style:font-size-asian="10.5pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="Table_20_Heading" style:display-name="Table Heading" style:family="paragraph" style:parent-style-name="Table_20_Contents" style:class="extra" style:master-page-name="">
|
||||
<style:paragraph-properties fo:text-align="center" style:justify-single-word="false" style:page-number="auto" text:number-lines="false" text:line-number="0"/>
|
||||
<style:text-properties style:font-name="Liberation Serif1" fo:font-family="'Liberation Serif'" style:font-style-name="Bold" style:font-family-generic="roman" style:font-pitch="variable" fo:font-weight="bold" style:font-size-asian="10.5pt" style:font-weight-asian="bold" style:font-weight-complex="bold"/>
|
||||
</style:style>
|
||||
<style:style style:name="Header_20_and_20_Footer" style:display-name="Header and Footer" style:family="paragraph" style:parent-style-name="Standard" style:class="extra">
|
||||
<style:paragraph-properties text:number-lines="false" text:line-number="0">
|
||||
<style:tab-stops>
|
||||
<style:tab-stop style:position="8.795cm" style:type="center"/>
|
||||
<style:tab-stop style:position="17.59cm" style:type="right"/>
|
||||
</style:tab-stops>
|
||||
</style:paragraph-properties>
|
||||
</style:style>
|
||||
<style:style style:name="Header" style:family="paragraph" style:parent-style-name="Standard" style:class="extra">
|
||||
<style:paragraph-properties text:number-lines="false" text:line-number="0">
|
||||
<style:tab-stops>
|
||||
<style:tab-stop style:position="8.795cm" style:type="center"/>
|
||||
<style:tab-stop style:position="17.59cm" style:type="right"/>
|
||||
</style:tab-stops>
|
||||
</style:paragraph-properties>
|
||||
<style:text-properties fo:font-size="9pt" style:font-size-asian="10.5pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="Heading_20_2" style:display-name="Heading 2" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:class="text">
|
||||
<style:text-properties fo:font-size="14pt" fo:font-style="italic" fo:font-weight="bold" style:font-size-asian="14pt" style:font-style-asian="italic" style:font-weight-asian="bold" style:font-size-complex="14pt" style:font-style-complex="italic" style:font-weight-complex="bold"/>
|
||||
</style:style>
|
||||
<style:style style:name="Footer" style:family="paragraph" style:parent-style-name="Standard" style:class="extra">
|
||||
<style:paragraph-properties text:number-lines="false" text:line-number="0">
|
||||
<style:tab-stops>
|
||||
<style:tab-stop style:position="8.795cm" style:type="center"/>
|
||||
<style:tab-stop style:position="17.59cm" style:type="right"/>
|
||||
</style:tab-stops>
|
||||
</style:paragraph-properties>
|
||||
<style:text-properties fo:font-size="9pt" style:font-size-asian="10.5pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="Heading_20_3" style:display-name="Heading 3" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:class="text">
|
||||
<style:text-properties fo:font-size="14pt" fo:font-weight="bold" style:font-size-asian="14pt" style:font-weight-asian="bold" style:font-size-complex="14pt" style:font-weight-complex="bold"/>
|
||||
</style:style>
|
||||
<style:style style:name="Text_20_body_20_indent" style:display-name="Text body indent" style:family="paragraph" style:parent-style-name="Text_20_body" style:class="text">
|
||||
<style:paragraph-properties fo:margin-left="0.499cm" fo:margin-right="0cm" fo:margin-top="0cm" fo:margin-bottom="0cm" style:contextual-spacing="false" fo:text-indent="0cm" style:auto-text-indent="false"/>
|
||||
</style:style>
|
||||
<style:style style:name="Text" style:family="paragraph" style:parent-style-name="Caption" style:class="extra"/>
|
||||
<style:style style:name="Quotations" style:family="paragraph" style:parent-style-name="Standard" style:class="html">
|
||||
<style:paragraph-properties fo:margin-left="1cm" fo:margin-right="1cm" fo:margin-top="0cm" fo:margin-bottom="0.499cm" style:contextual-spacing="false" fo:text-indent="0cm" style:auto-text-indent="false"/>
|
||||
</style:style>
|
||||
<style:style style:name="Title" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:class="chapter">
|
||||
<style:paragraph-properties fo:text-align="center" style:justify-single-word="false"/>
|
||||
<style:text-properties fo:font-size="28pt" fo:font-weight="bold" style:font-size-asian="28pt" style:font-weight-asian="bold" style:font-size-complex="28pt" style:font-weight-complex="bold"/>
|
||||
</style:style>
|
||||
<style:style style:name="Subtitle" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:class="chapter">
|
||||
<style:paragraph-properties fo:margin-top="0.106cm" fo:margin-bottom="0.212cm" style:contextual-spacing="false" fo:text-align="center" style:justify-single-word="false"/>
|
||||
<style:text-properties fo:font-size="18pt" style:font-size-asian="18pt" style:font-size-complex="18pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="Frame_20_contents" style:display-name="Frame contents" style:family="paragraph" style:parent-style-name="Standard" style:class="extra"/>
|
||||
<style:style style:name="Placeholder" style:family="text">
|
||||
<style:text-properties fo:font-variant="small-caps" fo:color="#008080" loext:opacity="100%" style:text-underline-style="dotted" style:text-underline-width="auto" style:text-underline-color="font-color"/>
|
||||
</style:style>
|
||||
<style:style style:name="Bullet_20_Symbols" style:display-name="Bullet Symbols" style:family="text">
|
||||
<style:text-properties style:font-name="StarSymbol" fo:font-family="StarSymbol" fo:font-size="9pt" style:font-name-asian="StarSymbol" style:font-family-asian="StarSymbol" style:font-size-asian="9pt" style:font-name-complex="StarSymbol" style:font-family-complex="StarSymbol" style:font-size-complex="9pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="Frame" style:family="graphic">
|
||||
<style:graphic-properties text:anchor-type="paragraph" svg:x="0cm" svg:y="0cm" fo:margin-left="0.201cm" fo:margin-right="0.201cm" fo:margin-top="0.201cm" fo:margin-bottom="0.201cm" style:wrap="parallel" style:number-wrapped-paragraphs="no-limit" style:wrap-contour="false" style:vertical-pos="top" style:vertical-rel="paragraph-content" style:horizontal-pos="center" style:horizontal-rel="paragraph-content" fo:background-color="transparent" draw:fill="none" draw:fill-color="#99ccff" fo:padding="0.15cm" fo:border="0.06pt solid #000000"/>
|
||||
</style:style>
|
||||
<text:outline-style style:name="Outline">
|
||||
<text:outline-level-style text:level="1" loext:num-list-format="%1%" style:num-format="">
|
||||
<style:list-level-properties text:min-label-distance="0.381cm"/>
|
||||
</text:outline-level-style>
|
||||
<text:outline-level-style text:level="2" loext:num-list-format="%2%" style:num-format="">
|
||||
<style:list-level-properties text:min-label-distance="0.381cm"/>
|
||||
</text:outline-level-style>
|
||||
<text:outline-level-style text:level="3" loext:num-list-format="%3%" style:num-format="">
|
||||
<style:list-level-properties text:min-label-distance="0.381cm"/>
|
||||
</text:outline-level-style>
|
||||
<text:outline-level-style text:level="4" loext:num-list-format="%4%" style:num-format="">
|
||||
<style:list-level-properties text:min-label-distance="0.381cm"/>
|
||||
</text:outline-level-style>
|
||||
<text:outline-level-style text:level="5" loext:num-list-format="%5%" style:num-format="">
|
||||
<style:list-level-properties text:min-label-distance="0.381cm"/>
|
||||
</text:outline-level-style>
|
||||
<text:outline-level-style text:level="6" loext:num-list-format="%6%" style:num-format="">
|
||||
<style:list-level-properties text:min-label-distance="0.381cm"/>
|
||||
</text:outline-level-style>
|
||||
<text:outline-level-style text:level="7" loext:num-list-format="%7%" style:num-format="">
|
||||
<style:list-level-properties text:min-label-distance="0.381cm"/>
|
||||
</text:outline-level-style>
|
||||
<text:outline-level-style text:level="8" loext:num-list-format="%8%" style:num-format="">
|
||||
<style:list-level-properties text:min-label-distance="0.381cm"/>
|
||||
</text:outline-level-style>
|
||||
<text:outline-level-style text:level="9" loext:num-list-format="%9%" style:num-format="">
|
||||
<style:list-level-properties text:min-label-distance="0.381cm"/>
|
||||
</text:outline-level-style>
|
||||
<text:outline-level-style text:level="10" loext:num-list-format="%10%" style:num-format="">
|
||||
<style:list-level-properties text:min-label-distance="0.381cm"/>
|
||||
</text:outline-level-style>
|
||||
</text:outline-style>
|
||||
<text:notes-configuration text:note-class="footnote" style:num-format="1" text:start-value="0" text:footnotes-position="page" text:start-numbering-at="document"/>
|
||||
<text:notes-configuration text:note-class="endnote" style:num-format="i" text:start-value="0"/>
|
||||
<text:linenumbering-configuration text:number-lines="false" text:offset="0.499cm" style:num-format="1" text:number-position="left" text:increment="5"/>
|
||||
<loext:theme loext:name="Office Theme">
|
||||
<loext:theme-colors loext:name="LibreOffice">
|
||||
<loext:color loext:name="dark1" loext:color="#000000"/>
|
||||
<loext:color loext:name="light1" loext:color="#ffffff"/>
|
||||
<loext:color loext:name="dark2" loext:color="#000000"/>
|
||||
<loext:color loext:name="light2" loext:color="#ffffff"/>
|
||||
<loext:color loext:name="accent1" loext:color="#18a303"/>
|
||||
<loext:color loext:name="accent2" loext:color="#0369a3"/>
|
||||
<loext:color loext:name="accent3" loext:color="#a33e03"/>
|
||||
<loext:color loext:name="accent4" loext:color="#8e03a3"/>
|
||||
<loext:color loext:name="accent5" loext:color="#c99c00"/>
|
||||
<loext:color loext:name="accent6" loext:color="#c9211e"/>
|
||||
<loext:color loext:name="hyperlink" loext:color="#0000ee"/>
|
||||
<loext:color loext:name="followed-hyperlink" loext:color="#551a8b"/>
|
||||
</loext:theme-colors>
|
||||
</loext:theme>
|
||||
</office:styles>
|
||||
<office:automatic-styles>
|
||||
<style:style style:name="Table1" style:family="table">
|
||||
<style:table-properties style:width="16.999cm" fo:margin-left="0cm" fo:margin-right="0cm" fo:margin-top="0.381cm" fo:margin-bottom="0cm" table:align="margins"/>
|
||||
</style:style>
|
||||
<style:style style:name="Table1.A" style:family="table-column">
|
||||
<style:table-column-properties style:column-width="4.683cm" style:rel-column-width="18053*"/>
|
||||
</style:style>
|
||||
<style:style style:name="Table1.C" style:family="table-column">
|
||||
<style:table-column-properties style:column-width="4.685cm" style:rel-column-width="18060*"/>
|
||||
</style:style>
|
||||
<style:style style:name="Table1.D" style:family="table-column">
|
||||
<style:table-column-properties style:column-width="2.949cm" style:rel-column-width="11369*"/>
|
||||
</style:style>
|
||||
<style:style style:name="Table1.A1" style:family="table-cell">
|
||||
<style:table-cell-properties fo:background-color="#cccccc" fo:padding="0.097cm" fo:border-left="0.05pt solid #000000" fo:border-right="none" fo:border-top="0.05pt solid #000000" fo:border-bottom="0.05pt solid #000000">
|
||||
<style:background-image/>
|
||||
</style:table-cell-properties>
|
||||
</style:style>
|
||||
<style:style style:name="Table1.D1" style:family="table-cell">
|
||||
<style:table-cell-properties fo:background-color="#cccccc" fo:padding="0.097cm" fo:border="0.05pt solid #000000">
|
||||
<style:background-image/>
|
||||
</style:table-cell-properties>
|
||||
</style:style>
|
||||
<style:style style:name="Table1.A2" style:family="table-cell">
|
||||
<style:table-cell-properties fo:padding="0.097cm" fo:border-left="0.05pt solid #000000" fo:border-right="none" fo:border-top="none" fo:border-bottom="0.05pt solid #000000"/>
|
||||
</style:style>
|
||||
<style:style style:name="Table1.C2" style:family="table-cell">
|
||||
<style:table-cell-properties fo:padding="0.097cm" fo:border-left="0.05pt solid #000000" fo:border-right="none" fo:border-top="none" fo:border-bottom="0.05pt solid #000000"/>
|
||||
</style:style>
|
||||
<style:style style:name="Table1.D2" style:family="table-cell">
|
||||
<style:table-cell-properties fo:padding="0.097cm" fo:border-left="0.05pt solid #000000" fo:border-right="0.05pt solid #000000" fo:border-top="none" fo:border-bottom="0.05pt solid #000000"/>
|
||||
</style:style>
|
||||
<style:style style:name="Table1.A3" style:family="table-cell">
|
||||
<style:table-cell-properties fo:padding="0.097cm" fo:border-left="0.05pt solid #000000" fo:border-right="none" fo:border-top="none" fo:border-bottom="0.05pt solid #000000"/>
|
||||
</style:style>
|
||||
<style:style style:name="Table1.B3" style:family="table-cell">
|
||||
<style:table-cell-properties fo:padding="0.097cm" fo:border-left="0.05pt solid #000000" fo:border-right="none" fo:border-top="none" fo:border-bottom="0.05pt solid #000000"/>
|
||||
</style:style>
|
||||
<style:style style:name="Table1.C3" style:family="table-cell">
|
||||
<style:table-cell-properties fo:padding="0.097cm" fo:border-left="0.05pt solid #000000" fo:border-right="none" fo:border-top="none" fo:border-bottom="0.05pt solid #000000"/>
|
||||
</style:style>
|
||||
<style:style style:name="Table1.D3" style:family="table-cell">
|
||||
<style:table-cell-properties fo:padding="0.097cm" fo:border-left="0.05pt solid #000000" fo:border-right="0.05pt solid #000000" fo:border-top="none" fo:border-bottom="0.05pt solid #000000"/>
|
||||
</style:style>
|
||||
<style:style style:name="Table1.A4" style:family="table-cell">
|
||||
<style:table-cell-properties fo:padding="0.097cm" fo:border-left="0.05pt solid #000000" fo:border-right="none" fo:border-top="none" fo:border-bottom="0.05pt solid #000000"/>
|
||||
</style:style>
|
||||
<style:style style:name="Table1.C4" style:family="table-cell">
|
||||
<style:table-cell-properties fo:padding="0.097cm" fo:border-left="0.05pt solid #000000" fo:border-right="none" fo:border-top="none" fo:border-bottom="0.05pt solid #000000"/>
|
||||
</style:style>
|
||||
<style:style style:name="Table1.D4" style:family="table-cell">
|
||||
<style:table-cell-properties fo:padding="0.097cm" fo:border-left="0.05pt solid #000000" fo:border-right="0.05pt solid #000000" fo:border-top="none" fo:border-bottom="0.05pt solid #000000"/>
|
||||
</style:style>
|
||||
<style:style style:name="P1" style:family="paragraph" style:parent-style-name="Header">
|
||||
<style:paragraph-properties fo:text-align="center" style:justify-single-word="false"/>
|
||||
<style:text-properties officeooo:paragraph-rsid="00201d29"/>
|
||||
</style:style>
|
||||
<style:style style:name="P2" style:family="paragraph" style:parent-style-name="Footer">
|
||||
<style:paragraph-properties fo:text-align="center" style:justify-single-word="false"/>
|
||||
<style:text-properties officeooo:paragraph-rsid="00201d29"/>
|
||||
</style:style>
|
||||
<style:style style:name="P3" style:family="paragraph" style:parent-style-name="Header">
|
||||
<style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/>
|
||||
<style:text-properties fo:font-size="12pt" officeooo:paragraph-rsid="0028dba6" style:font-size-asian="12pt" style:font-size-complex="12pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="P4" style:family="paragraph" style:parent-style-name="Frame_20_contents">
|
||||
<style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/>
|
||||
</style:style>
|
||||
<style:style style:name="P5" style:family="paragraph" style:parent-style-name="Footer">
|
||||
<style:paragraph-properties fo:text-align="center" style:justify-single-word="false"/>
|
||||
<style:text-properties officeooo:paragraph-rsid="00215c08"/>
|
||||
</style:style>
|
||||
<style:style style:name="P6" style:family="paragraph" style:parent-style-name="Footer">
|
||||
<style:paragraph-properties fo:text-align="end" style:justify-single-word="false"/>
|
||||
</style:style>
|
||||
<style:style style:name="P7" style:family="paragraph" style:parent-style-name="Header">
|
||||
<style:paragraph-properties fo:text-align="center" style:justify-single-word="false"/>
|
||||
<style:text-properties officeooo:paragraph-rsid="00201d29"/>
|
||||
</style:style>
|
||||
<style:style style:name="P8" style:family="paragraph" style:parent-style-name="Footer">
|
||||
<style:paragraph-properties fo:text-align="center" style:justify-single-word="false"/>
|
||||
<style:text-properties officeooo:paragraph-rsid="00201d29"/>
|
||||
</style:style>
|
||||
<style:style style:name="P9" style:family="paragraph" style:parent-style-name="Footer">
|
||||
<style:paragraph-properties fo:text-align="center" style:justify-single-word="false"/>
|
||||
<style:text-properties officeooo:paragraph-rsid="00215c08"/>
|
||||
</style:style>
|
||||
<style:style style:name="P10" style:family="paragraph" style:parent-style-name="Footer">
|
||||
<style:paragraph-properties fo:text-align="center" style:justify-single-word="false"/>
|
||||
<style:text-properties officeooo:paragraph-rsid="00282b04"/>
|
||||
</style:style>
|
||||
<style:style style:name="P11" style:family="paragraph" style:parent-style-name="Header">
|
||||
<style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/>
|
||||
<style:text-properties fo:font-size="12pt" officeooo:paragraph-rsid="00282b04" style:font-size-asian="12pt" style:font-size-complex="12pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="P12" style:family="paragraph" style:parent-style-name="Header">
|
||||
<style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/>
|
||||
<style:text-properties fo:font-size="12pt" officeooo:paragraph-rsid="00201d29" style:font-size-asian="12pt" style:font-size-complex="12pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="P13" style:family="paragraph" style:parent-style-name="Frame_20_contents">
|
||||
<style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/>
|
||||
</style:style>
|
||||
<style:style style:name="P14" style:family="paragraph" style:parent-style-name="Footer">
|
||||
<style:paragraph-properties fo:text-align="end" style:justify-single-word="false"/>
|
||||
</style:style>
|
||||
<style:style style:name="P15" style:family="paragraph" style:parent-style-name="Table_20_Contents">
|
||||
<style:paragraph-properties fo:text-align="end" style:justify-single-word="false"/>
|
||||
</style:style>
|
||||
<style:style style:name="P16" style:family="paragraph" style:parent-style-name="Table_20_Heading">
|
||||
<style:paragraph-properties fo:text-align="center" style:justify-single-word="false"/>
|
||||
<style:text-properties style:font-name="Liberation Serif"/>
|
||||
</style:style>
|
||||
<style:style style:name="P17" style:family="paragraph" style:parent-style-name="Standard">
|
||||
<style:paragraph-properties fo:break-before="page"/>
|
||||
</style:style>
|
||||
<style:style style:name="P18" style:family="paragraph" style:parent-style-name="Heading_20_1">
|
||||
<style:paragraph-properties fo:text-align="center" style:justify-single-word="false" fo:break-before="page"/>
|
||||
<style:text-properties style:text-underline-style="solid" style:text-underline-width="auto" style:text-underline-color="font-color"/>
|
||||
</style:style>
|
||||
<style:style style:name="P19" style:family="paragraph" style:parent-style-name="Heading_20_1">
|
||||
<style:paragraph-properties fo:text-align="center" style:justify-single-word="false"/>
|
||||
<style:text-properties style:text-underline-style="solid" style:text-underline-width="auto" style:text-underline-color="font-color"/>
|
||||
</style:style>
|
||||
<style:style style:name="P20" style:family="paragraph" style:parent-style-name="Heading_20_1">
|
||||
<style:paragraph-properties fo:text-align="center" style:justify-single-word="false"/>
|
||||
<style:text-properties style:text-underline-style="solid" style:text-underline-width="auto" style:text-underline-color="font-color" officeooo:paragraph-rsid="00279246"/>
|
||||
</style:style>
|
||||
<style:style style:name="P21" style:family="paragraph" style:parent-style-name="Standard">
|
||||
<style:text-properties officeooo:paragraph-rsid="001d944d"/>
|
||||
</style:style>
|
||||
<style:style style:name="P22" style:family="paragraph" style:parent-style-name="Frame_20_contents">
|
||||
<style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/>
|
||||
</style:style>
|
||||
<style:style style:name="P23" style:family="paragraph" style:parent-style-name="Header">
|
||||
<style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/>
|
||||
<style:text-properties fo:font-size="12pt" officeooo:paragraph-rsid="0028dba6" style:font-size-asian="12pt" style:font-size-complex="12pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="T1" style:family="text">
|
||||
<style:text-properties fo:font-weight="bold" style:font-weight-asian="bold" style:font-weight-complex="bold"/>
|
||||
</style:style>
|
||||
<style:style style:name="T2" style:family="text">
|
||||
<style:text-properties fo:font-weight="bold" officeooo:rsid="00236359" style:font-weight-asian="bold" style:font-weight-complex="bold"/>
|
||||
</style:style>
|
||||
<style:style style:name="T3" style:family="text">
|
||||
<style:text-properties fo:font-weight="normal" style:font-weight-asian="normal" style:font-weight-complex="normal"/>
|
||||
</style:style>
|
||||
<style:style style:name="T4" style:family="text">
|
||||
<style:text-properties officeooo:rsid="00279246"/>
|
||||
</style:style>
|
||||
<style:style style:name="fr1" style:family="graphic" style:parent-style-name="Frame">
|
||||
<style:graphic-properties fo:margin-left="0cm" fo:margin-right="0cm" fo:margin-top="0cm" fo:margin-bottom="0cm" style:wrap="parallel" style:number-wrapped-paragraphs="no-limit" style:vertical-pos="middle" style:vertical-rel="baseline" style:horizontal-pos="left" style:horizontal-rel="paragraph" draw:opacity="100%" fo:padding="0cm" fo:border="none" draw:wrap-influence-on-position="once-concurrent" loext:allow-overlap="true">
|
||||
<style:columns fo:column-count="1" fo:column-gap="0cm"/>
|
||||
</style:graphic-properties>
|
||||
</style:style>
|
||||
<style:page-layout style:name="pm1">
|
||||
<style:page-layout-properties fo:page-width="20.999cm" fo:page-height="29.699cm" style:num-format="1" style:print-orientation="portrait" fo:margin-top="2cm" fo:margin-bottom="2cm" fo:margin-left="2cm" fo:margin-right="2cm" style:writing-mode="lr-tb" style:layout-grid-color="#c0c0c0" style:layout-grid-lines="20" style:layout-grid-base-height="0.706cm" style:layout-grid-ruby-height="0.353cm" style:layout-grid-mode="none" style:layout-grid-ruby-below="false" style:layout-grid-print="false" style:layout-grid-display="false" style:footnote-max-height="0cm" loext:margin-gutter="0cm">
|
||||
<style:footnote-sep style:width="0.018cm" style:distance-before-sep="0.101cm" style:distance-after-sep="0.101cm" style:line-style="none" style:adjustment="left" style:rel-width="25%" style:color="#000000"/>
|
||||
</style:page-layout-properties>
|
||||
<style:header-style>
|
||||
<style:header-footer-properties fo:min-height="0cm" fo:margin-left="0cm" fo:margin-right="0cm" fo:margin-bottom="0.499cm"/>
|
||||
</style:header-style>
|
||||
<style:footer-style>
|
||||
<style:header-footer-properties fo:min-height="0cm" fo:margin-left="0cm" fo:margin-right="0cm" fo:margin-top="0.499cm"/>
|
||||
</style:footer-style>
|
||||
</style:page-layout>
|
||||
<style:style style:name="dp1" style:family="drawing-page">
|
||||
<style:drawing-page-properties draw:background-size="full"/>
|
||||
</style:style>
|
||||
</office:automatic-styles>
|
||||
<office:master-styles>
|
||||
<style:master-page style:name="Standard" style:page-layout-name="pm1" draw:style-name="dp1">
|
||||
<style:header>
|
||||
<text:p text:style-name="P1"><text:placeholder text:placeholder-type="text"><if test="company and company.header"></text:placeholder></text:p>
|
||||
<text:p text:style-name="P1"><text:placeholder text:placeholder-type="text"><for each="line in company.header_used.split('\n')"></text:placeholder></text:p>
|
||||
<text:p text:style-name="P1"><text:placeholder text:placeholder-type="text"><line></text:placeholder></text:p>
|
||||
<text:p text:style-name="P1"><text:placeholder text:placeholder-type="text"></for></text:placeholder></text:p>
|
||||
<text:p text:style-name="P2"><text:placeholder text:placeholder-type="text"></if></text:placeholder></text:p>
|
||||
<text:p text:style-name="P3"><text:placeholder text:placeholder-type="text"><choose></text:placeholder></text:p>
|
||||
<text:p text:style-name="P3"><text:placeholder text:placeholder-type="text"><when test="company and company.logo"></text:placeholder></text:p>
|
||||
<text:p text:style-name="P3"><draw:frame draw:style-name="fr1" draw:name="image:company.get_logo_cm(7, 3.5)" text:anchor-type="as-char" svg:width="7.001cm" draw:z-index="2">
|
||||
<draw:text-box fo:min-height="3cm">
|
||||
<text:p text:style-name="P4"/>
|
||||
</draw:text-box>
|
||||
</draw:frame></text:p>
|
||||
<text:p text:style-name="P3"><text:placeholder text:placeholder-type="text"></when></text:placeholder></text:p>
|
||||
<text:p text:style-name="P3"><text:placeholder text:placeholder-type="text"><when test="company"></text:placeholder></text:p>
|
||||
<text:p text:style-name="P3"><text:placeholder text:placeholder-type="text"><company.rec_name></text:placeholder></text:p>
|
||||
<text:p text:style-name="P3"><text:placeholder text:placeholder-type="text"></when></text:placeholder></text:p>
|
||||
<text:p text:style-name="P3"><text:placeholder text:placeholder-type="text"></choose></text:placeholder></text:p>
|
||||
</style:header>
|
||||
<style:footer>
|
||||
<text:p text:style-name="P5"><text:placeholder text:placeholder-type="text"><if test="company and company.footer"></text:placeholder></text:p>
|
||||
<text:p text:style-name="P5"><text:placeholder text:placeholder-type="text"><for each="line in company.footer_used.split('\n')"></text:placeholder></text:p>
|
||||
<text:p text:style-name="P5"><text:placeholder text:placeholder-type="text"><line></text:placeholder></text:p>
|
||||
<text:p text:style-name="P5"><text:placeholder text:placeholder-type="text"></for></text:placeholder></text:p>
|
||||
<text:p text:style-name="P5"><text:placeholder text:placeholder-type="text"></if></text:placeholder></text:p>
|
||||
<text:p text:style-name="P6"><text:page-number text:select-page="current">3</text:page-number>/<text:page-count>3</text:page-count></text:p>
|
||||
</style:footer>
|
||||
</style:master-page>
|
||||
</office:master-styles>
|
||||
<office:body>
|
||||
<office:text text:use-soft-page-breaks="true">
|
||||
<office:forms form:automatic-focus="false" form:apply-design-mode="false"/>
|
||||
<text:sequence-decls>
|
||||
<text:sequence-decl text:display-outline-level="0" text:name="Illustration"/>
|
||||
<text:sequence-decl text:display-outline-level="0" text:name="Table"/>
|
||||
<text:sequence-decl text:display-outline-level="0" text:name="Text"/>
|
||||
<text:sequence-decl text:display-outline-level="0" text:name="Drawing"/>
|
||||
<text:sequence-decl text:display-outline-level="0" text:name="Figure"/>
|
||||
</text:sequence-decls>
|
||||
<text:p text:style-name="P17"><text:placeholder text:placeholder-type="text"><for each="shipment in records"></text:placeholder></text:p>
|
||||
<text:p text:style-name="P17"><text:placeholder text:placeholder-type="text"><choose></text:placeholder></text:p>
|
||||
<text:p text:style-name="Standard"><text:placeholder text:placeholder-type="text"><when test="shipment.state in ['draft', 'waiting']"></text:placeholder></text:p>
|
||||
<text:p text:style-name="P20"><text:span text:style-name="T4">Draft </text:span>Picking List</text:p>
|
||||
<text:p text:style-name="Standard"><text:placeholder text:placeholder-type="text"></when></text:placeholder></text:p>
|
||||
<text:p text:style-name="Standard"><text:placeholder text:placeholder-type="text"><when test="shipment.state == 'assigned'"></text:placeholder></text:p>
|
||||
<text:p text:style-name="P20">Picking List No: <text:span text:style-name="T4"><text:placeholder text:placeholder-type="text"><shipment.number></text:placeholder></text:span></text:p>
|
||||
<text:p text:style-name="Standard"><text:placeholder text:placeholder-type="text"></when></text:placeholder></text:p>
|
||||
<text:p text:style-name="Standard"><text:placeholder text:placeholder-type="text"><when test="shipment.state == 'cancelled'"></text:placeholder></text:p>
|
||||
<text:p text:style-name="P20"><text:span text:style-name="T4">Cancelled </text:span>Picking List</text:p>
|
||||
<text:p text:style-name="Standard"><text:placeholder text:placeholder-type="text"></when></text:placeholder></text:p>
|
||||
<text:p text:style-name="Standard"><text:placeholder text:placeholder-type="text"><otherwise></text:placeholder></text:p>
|
||||
<text:p text:style-name="P19"><text:span text:style-name="T4">Done </text:span>Picking List No: <text:span text:style-name="T4"><text:placeholder text:placeholder-type="text"><shipment.number></text:placeholder></text:span></text:p>
|
||||
<text:p text:style-name="Standard"><text:placeholder text:placeholder-type="text"></otherwise></text:placeholder></text:p>
|
||||
<text:p text:style-name="Standard"><text:placeholder text:placeholder-type="text"></choose></text:placeholder></text:p>
|
||||
<text:p text:style-name="Standard"><text:span text:style-name="T1">Reference:</text:span><text:span text:style-name="T3"> </text:span><text:span text:style-name="T3"><text:placeholder text:placeholder-type="text"><shipment.origins or ''></text:placeholder></text:span><text:span text:style-name="T3"><text:placeholder text:placeholder-type="text"><', ' if (shipment.origins and shipment.reference) else ''></text:placeholder></text:span><text:span text:style-name="T3"><text:placeholder text:placeholder-type="text"><shipment.reference or ''></text:placeholder></text:span></text:p>
|
||||
<text:p text:style-name="Standard"><text:span text:style-name="T1">Customer:</text:span><text:span text:style-name="T3"> </text:span><text:span text:style-name="T3"><text:placeholder text:placeholder-type="text"><shipment.customer.rec_name></text:placeholder></text:span></text:p>
|
||||
<text:p text:style-name="Standard"><text:span text:style-name="T1">Planned Date:</text:span><text:span text:style-name="T3"> </text:span><text:span text:style-name="T3"><text:placeholder text:placeholder-type="text"><shipment.planned_date and format_date(shipment.planned_date, user.language) or ''></text:placeholder></text:span></text:p>
|
||||
<text:p text:style-name="Standard"><text:span text:style-name="T1">Warehouse:</text:span><text:span text:style-name="T3"> </text:span><text:span text:style-name="T3"><text:placeholder text:placeholder-type="text"><shipment.warehouse.rec_name></text:placeholder></text:span></text:p>
|
||||
<table:table table:name="Table1" table:style-name="Table1">
|
||||
<table:table-column table:style-name="Table1.A" table:number-columns-repeated="2"/>
|
||||
<table:table-column table:style-name="Table1.C"/>
|
||||
<table:table-column table:style-name="Table1.D"/>
|
||||
<table:table-header-rows>
|
||||
<text:soft-page-break/>
|
||||
<table:table-row>
|
||||
<table:table-cell table:style-name="Table1.A1" office:value-type="string">
|
||||
<text:p text:style-name="P16">From Location</text:p>
|
||||
</table:table-cell>
|
||||
<table:table-cell table:style-name="Table1.A1" office:value-type="string">
|
||||
<text:p text:style-name="P16">To Location</text:p>
|
||||
</table:table-cell>
|
||||
<table:table-cell table:style-name="Table1.A1" office:value-type="string">
|
||||
<text:p text:style-name="P16">Product</text:p>
|
||||
</table:table-cell>
|
||||
<table:table-cell table:style-name="Table1.D1" office:value-type="string">
|
||||
<text:p text:style-name="P16">Quantity</text:p>
|
||||
</table:table-cell>
|
||||
</table:table-row>
|
||||
</table:table-header-rows>
|
||||
<table:table-row>
|
||||
<table:table-cell table:style-name="Table1.A2" table:number-columns-spanned="2" office:value-type="string">
|
||||
<text:p text:style-name="Table_20_Contents"><text:placeholder text:placeholder-type="text"><for each="move in moves(shipment)"></text:placeholder></text:p>
|
||||
</table:table-cell>
|
||||
<table:covered-table-cell/>
|
||||
<table:table-cell table:style-name="Table1.C2" office:value-type="string">
|
||||
<text:p text:style-name="Table_20_Contents"/>
|
||||
</table:table-cell>
|
||||
<table:table-cell table:style-name="Table1.D2" office:value-type="string">
|
||||
<text:p text:style-name="Table_20_Contents"/>
|
||||
</table:table-cell>
|
||||
</table:table-row>
|
||||
<table:table-row>
|
||||
<table:table-cell table:style-name="Table1.A3" office:value-type="string">
|
||||
<text:p text:style-name="Table_20_Contents"><text:placeholder text:placeholder-type="text"><move.from_location_name></text:placeholder></text:p>
|
||||
</table:table-cell>
|
||||
<table:table-cell table:style-name="Table1.A3" office:value-type="string">
|
||||
<text:p text:style-name="Table_20_Contents"><text:placeholder text:placeholder-type="text"><move.to_location_name></text:placeholder></text:p>
|
||||
</table:table-cell>
|
||||
<table:table-cell table:style-name="Table1.C2" office:value-type="string">
|
||||
<text:p text:style-name="Table_20_Contents"><text:placeholder text:placeholder-type="text"><move.product.rec_name></text:placeholder></text:p>
|
||||
</table:table-cell>
|
||||
<table:table-cell table:style-name="Table1.D2" office:value-type="string">
|
||||
<text:p text:style-name="P15"><text:placeholder text:placeholder-type="text"><format_number_symbol(move.quantity, user.language, move.unit, digits=move.unit.digits)></text:placeholder></text:p>
|
||||
</table:table-cell>
|
||||
</table:table-row>
|
||||
<table:table-row>
|
||||
<table:table-cell table:style-name="Table1.A2" table:number-columns-spanned="2" office:value-type="string">
|
||||
<text:p text:style-name="Table_20_Contents"><text:placeholder text:placeholder-type="text"></for></text:placeholder></text:p>
|
||||
</table:table-cell>
|
||||
<table:covered-table-cell/>
|
||||
<table:table-cell table:style-name="Table1.C2" office:value-type="string">
|
||||
<text:p text:style-name="Table_20_Contents"/>
|
||||
</table:table-cell>
|
||||
<table:table-cell table:style-name="Table1.D2" office:value-type="string">
|
||||
<text:p text:style-name="Table_20_Contents"/>
|
||||
</table:table-cell>
|
||||
</table:table-row>
|
||||
</table:table>
|
||||
<text:p text:style-name="Text_20_body"><text:placeholder text:placeholder-type="text"></for></text:placeholder></text:p>
|
||||
</office:text>
|
||||
</office:body>
|
||||
</office:document>
|
||||
1353
modules/stock/product.py
Normal file
1353
modules/stock/product.py
Normal file
File diff suppressed because it is too large
Load Diff
423
modules/stock/product.xml
Normal file
423
modules/stock/product.xml
Normal file
@@ -0,0 +1,423 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
this repository contains the full copyright notices and license terms. -->
|
||||
<tryton>
|
||||
<data>
|
||||
<record model="ir.ui.view" id="product_view_list_stock_move">
|
||||
<field name="model">product.product</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="priority" eval="20"/>
|
||||
<field name="name">product_list_stock_move</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.action.wizard" id="wizard_recompute_cost_price">
|
||||
<field name="name">Recompute Cost Price</field>
|
||||
<field name="wiz_name">product.recompute_cost_price</field>
|
||||
</record>
|
||||
<record model="ir.action.keyword"
|
||||
id="wizard_recompute_cost_price_product_keyword1">
|
||||
<field name="keyword">form_action</field>
|
||||
<field name="model">product.product,-1</field>
|
||||
<field name="action" ref="wizard_recompute_cost_price"/>
|
||||
</record>
|
||||
<record model="ir.action.keyword"
|
||||
id="wizard_recompute_cost_price_template_keyword1">
|
||||
<field name="keyword">form_action</field>
|
||||
<field name="model">product.template,-1</field>
|
||||
<field name="action" ref="wizard_recompute_cost_price"/>
|
||||
</record>
|
||||
<record model="ir.action-res.group"
|
||||
id="wizard_recompute_cost_price-group_product_admin">
|
||||
<field name="action" ref="wizard_recompute_cost_price"/>
|
||||
<field name="group" ref="product.group_product_admin"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="recompute_cost_price_start_view_form">
|
||||
<field name="model">product.recompute_cost_price.start</field>
|
||||
<field name="type">form</field>
|
||||
<field name="name">recompute_cost_price_start_form</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="product_cost_price_revision_view_form">
|
||||
<field name="model">product.cost_price.revision</field>
|
||||
<field name="type">form</field>
|
||||
<field name="name">product_cost_price_revision_form</field>
|
||||
</record>
|
||||
<record model="ir.ui.view" id="product_cost_price_revision_view_list">
|
||||
<field name="model">product.cost_price.revision</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="name">product_cost_price_revision_list</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.action.act_window" id="act_product_cost_price_revision">
|
||||
<field name="name">Cost Price Revision</field>
|
||||
<field name="res_model">product.cost_price.revision</field>
|
||||
<field
|
||||
name="domain"
|
||||
eval="[If(Eval('active_ids', []) == [Eval('active_id')], (If(Eval('active_model') == 'product.template', 'template', 'product'), '=', Eval('active_id', -1)), (If(Eval('active_model') == 'product.template', 'template', 'product'), 'in', Eval('active_ids', [])))]"
|
||||
pyson="1"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_product_cost_price_revision_list_view">
|
||||
<field name="sequence" eval="10"/>
|
||||
<field name="view" ref="product_cost_price_revision_view_list"/>
|
||||
<field name="act_window" ref="act_product_cost_price_revision"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_product_cost_price_revision_form_view">
|
||||
<field name="sequence" eval="20"/>
|
||||
<field name="view" ref="product_cost_price_revision_view_form"/>
|
||||
<field name="act_window" ref="act_product_cost_price_revision"/>
|
||||
</record>
|
||||
<record model="ir.action.keyword" id="act_product_cost_price_revision_keyword1">
|
||||
<field name="keyword">form_relate</field>
|
||||
<field name="model">product.template,-1</field>
|
||||
<field name="action" ref="act_product_cost_price_revision"/>
|
||||
</record>
|
||||
<record model="ir.action.keyword" id="act_product_cost_price_revision_keyword2">
|
||||
<field name="keyword">form_relate</field>
|
||||
<field name="model">product.product,-1</field>
|
||||
<field name="action" ref="act_product_cost_price_revision"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.rule.group" id="rule_group_product_cost_price_revision_companies">
|
||||
<field name="name">User in companies</field>
|
||||
<field name="model">product.cost_price.revision</field>
|
||||
<field name="global_p" eval="True"/>
|
||||
</record>
|
||||
<record model="ir.rule" id="rule_product_cost_price_revision_companies">
|
||||
<field name="domain"
|
||||
eval="[('company', 'in', Eval('companies', []))]"
|
||||
pyson="1"/>
|
||||
<field name="rule_group" ref="rule_group_product_cost_price_revision_companies"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.access" id="access_product_cost_price_revision">
|
||||
<field name="model">product.cost_price.revision</field>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
<field name="perm_create" eval="False"/>
|
||||
<field name="perm_delete" eval="False"/>
|
||||
</record>
|
||||
<record model="ir.model.access" id="access_product_cost_price_revision_admin">
|
||||
<field name="model">product.cost_price.revision</field>
|
||||
<field name="group" ref="product.group_product_admin"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="True"/>
|
||||
<field name="perm_create" eval="True"/>
|
||||
<field name="perm_delete" eval="True"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="product_modify_cost_price_start_form">
|
||||
<field name="model">product.modify_cost_price.start</field>
|
||||
<field name="type">form</field>
|
||||
<field name="name">product_modify_cost_price_start_form</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.action.wizard" id="wizard_product_modify_cost_price">
|
||||
<field name="name">Modify Cost Price</field>
|
||||
<field name="wiz_name">product.modify_cost_price</field>
|
||||
</record>
|
||||
<record model="ir.action.keyword" id="product_modify_cost_price_keyword1">
|
||||
<field name="keyword">form_action</field>
|
||||
<field name="model">product.product,-1</field>
|
||||
<field name="action" ref="wizard_product_modify_cost_price"/>
|
||||
</record>
|
||||
<record model="ir.action.keyword" id="product_modify_cost_price_keyword2">
|
||||
<field name="keyword">form_action</field>
|
||||
<field name="model">product.template,-1</field>
|
||||
<field name="action" ref="wizard_product_modify_cost_price"/>
|
||||
</record>
|
||||
<record model="ir.action-res.group" id="wizard_product_modify_cost_price-group_account">
|
||||
<field name="action" ref="wizard_product_modify_cost_price"/>
|
||||
<field name="group" ref="product.group_product_admin" />
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="location_quantity_view_tree">
|
||||
<field name="model">stock.location</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="field_childs">childs</field>
|
||||
<field name="priority" eval="20"/>
|
||||
<field name="name">location_quantity_tree</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="location_quantity_view_form">
|
||||
<field name="model">stock.location</field>
|
||||
<field name="type">form</field>
|
||||
<field name="priority" eval="20"/>
|
||||
<field name="name">location_quantity_form</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="location_quantity_view_list">
|
||||
<field name="model">stock.location</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="priority" eval="20"/>
|
||||
<field name="name">location_quantity_tree</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.action.act_window" id="act_location_quantity_tree">
|
||||
<field name="name">Stock Locations Tree</field>
|
||||
<field name="res_model">stock.location</field>
|
||||
<field name="domain" eval="[('parent', '=', None)]" pyson="1"/>
|
||||
<field name="search_value" eval="[('type', 'in', ['storage', 'view', 'warehouse'])]" pyson="1"/>
|
||||
<field name="context" pyson="1"
|
||||
eval="If(Eval('active_model') == 'product.template', {'product_template': Eval('active_id'), 'stock_skip_warehouse': False}, {'product': Eval('active_id'), 'stock_skip_warehouse': False})"/>
|
||||
<field name="context_model">product.by_location.context</field>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_location_quantity_tree_view1">
|
||||
<field name="sequence" eval="10"/>
|
||||
<field name="view" ref="location_quantity_view_tree"/>
|
||||
<field name="act_window" ref="act_location_quantity_tree"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_location_quantity_tree_view2">
|
||||
<field name="sequence" eval="20"/>
|
||||
<field name="view" ref="location_quantity_view_form"/>
|
||||
<field name="act_window" ref="act_location_quantity_tree"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.action.keyword"
|
||||
id="act_location_quantity_tree_keyword1">
|
||||
<field name="keyword">form_relate</field>
|
||||
<field name="model">product.product,-1</field>
|
||||
<field name="action" ref="act_location_quantity_tree"/>
|
||||
</record>
|
||||
<record model="ir.action.keyword"
|
||||
id="act_location_quantity_tree_keyword2">
|
||||
<field name="keyword">form_relate</field>
|
||||
<field name="model">product.template,-1</field>
|
||||
<field name="action" ref="act_location_quantity_tree"/>
|
||||
</record>
|
||||
<record model="ir.action-res.group"
|
||||
id="act_location-quantity_tree-group_stock">
|
||||
<field name="action" ref="act_location_quantity_tree"/>
|
||||
<field name="group" ref="group_stock"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.action.act_window" id="act_location_quantity_list">
|
||||
<field name="name">Stock Locations List</field>
|
||||
<field name="res_model">stock.location</field>
|
||||
<field name="search_value" eval="[('type', '=', 'storage'), ['OR', ('quantity', '!=', 0), ('forecast_quantity', '!=', 0)]]" pyson="1"/>
|
||||
<field name="context" pyson="1"
|
||||
eval="If(Eval('active_model') == 'product.template', {'product_template': Eval('active_id'), 'with_childs': False, 'stock_skip_warehouse': False}, {'product': Eval('active_id'), 'with_childs': False, 'stock_skip_warehouse': False})"/>
|
||||
<field name="context_model">product.by_location.context</field>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_location_quantity_list_view">
|
||||
<field name="sequence" eval="10"/>
|
||||
<field name="view" ref="location_quantity_view_list"/>
|
||||
<field name="act_window" ref="act_location_quantity_list"/>
|
||||
</record>
|
||||
<record model="ir.action.keyword"
|
||||
id="act_location_quantity_list_keyword1">
|
||||
<field name="keyword">form_relate</field>
|
||||
<field name="model">product.product,-1</field>
|
||||
<field name="action" ref="act_location_quantity_list"/>
|
||||
</record>
|
||||
<record model="ir.action.keyword"
|
||||
id="act_location_quantity_list_keyword2">
|
||||
<field name="keyword">form_relate</field>
|
||||
<field name="model">product.template,-1</field>
|
||||
<field name="action" ref="act_location_quantity_list"/>
|
||||
</record>
|
||||
<record model="ir.action-res.group"
|
||||
id="act_location-quantity_list-group_stock">
|
||||
<field name="action" ref="act_location_quantity_list"/>
|
||||
<field name="group" ref="group_stock"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="product_by_location_context_view_form">
|
||||
<field name="model">product.by_location.context</field>
|
||||
<field name="type">form</field>
|
||||
<field name="name">product_by_location_context_form</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.action.wizard" id="wizard_open_product_quantities_by_warehouse">
|
||||
<field name="name">Products Quantities By Warehouse</field>
|
||||
<field name="wiz_name">stock.product_quantities_warehouse.open</field>
|
||||
</record>
|
||||
<record model="ir.action.keyword" id="wizard_open_product_quantities_by_warehouse_keyword_shipment_in_return">
|
||||
<field name="keyword">form_relate</field>
|
||||
<field name="model">stock.shipment.in.return,-1</field>
|
||||
<field name="action" ref="wizard_open_product_quantities_by_warehouse"/>
|
||||
</record>
|
||||
<record model="ir.action.keyword" id="wizard_open_product_quantities_by_warehouse_keyword_shipment_out">
|
||||
<field name="keyword">form_relate</field>
|
||||
<field name="model">stock.shipment.out,-1</field>
|
||||
<field name="action" ref="wizard_open_product_quantities_by_warehouse"/>
|
||||
</record>
|
||||
<record model="ir.action.keyword" id="wizard_open_product_quantities_by_warehouse_keyword_shipment_internal">
|
||||
<field name="keyword">form_relate</field>
|
||||
<field name="model">stock.shipment.internal,-1</field>
|
||||
<field name="action" ref="wizard_open_product_quantities_by_warehouse"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="product_quantities_warehouse_view_graph">
|
||||
<field name="model">stock.product_quantities_warehouse</field>
|
||||
<field name="type">graph</field>
|
||||
<field name="name">product_quantities_warehouse_graph</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="product_quantities_warehouse_view_list">
|
||||
<field name="model">stock.product_quantities_warehouse</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="name">product_quantities_warehouse_list</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.action.act_window"
|
||||
id="act_product_quantities_warehouse">
|
||||
<field name="name">Stock Quantities By Warehouse</field>
|
||||
<field name="res_model">stock.product_quantities_warehouse</field>
|
||||
<field name="context" pyson="1"
|
||||
eval="If(Eval('active_model') == 'product.template', {'product_template': Eval('active_ids')}, {'product': Eval('active_ids')})"/>
|
||||
<field name="search_value" eval="[('date', '>=', Date())]"
|
||||
pyson="1"/>
|
||||
<field name="context_model">stock.product_quantities_warehouse.context</field>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view"
|
||||
id="act_product_quantities_warehouse_graph_view">
|
||||
<field name="sequence" eval="10"/>
|
||||
<field name="view" ref="product_quantities_warehouse_view_graph"/>
|
||||
<field name="act_window" ref="act_product_quantities_warehouse"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view"
|
||||
id="act_product_quantities_warehouse_list_view">
|
||||
<field name="sequence" eval="20"/>
|
||||
<field name="view" ref="product_quantities_warehouse_view_list"/>
|
||||
<field name="act_window" ref="act_product_quantities_warehouse"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.rule.group" id="rule_group_product_quantities_warehouse_companies">
|
||||
<field name="name">User in companies</field>
|
||||
<field name="model">stock.product_quantities_warehouse</field>
|
||||
<field name="global_p" eval="True"/>
|
||||
</record>
|
||||
<record model="ir.rule" id="rule_product_quantities_warehouse_companies">
|
||||
<field
|
||||
name="domain"
|
||||
eval="[('company', 'in', Eval('companies', []))]"
|
||||
pyson="1"/>
|
||||
<field name="rule_group" ref="rule_group_product_quantities_warehouse_companies"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.access" id="access_product_quantities_warehouse">
|
||||
<field name="model">stock.product_quantities_warehouse</field>
|
||||
<field name="perm_read" eval="False"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
<field name="perm_create" eval="False"/>
|
||||
<field name="perm_delete" eval="False"/>
|
||||
</record>
|
||||
<record model="ir.model.access" id="access_product_quantities_warehouse_group_stock">
|
||||
<field name="model">stock.product_quantities_warehouse</field>
|
||||
<field name="group" ref="group_stock"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
<field name="perm_create" eval="False"/>
|
||||
<field name="perm_delete" eval="False"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="product_quantities_warehouse_context_view_form">
|
||||
<field
|
||||
name="model">stock.product_quantities_warehouse.context</field>
|
||||
<field name="type">form</field>
|
||||
<field name="name">product_quantities_warehouse_context_form</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.action.keyword"
|
||||
id="act_product_quantities_warehouse_keyword1">
|
||||
<field name="keyword">form_relate</field>
|
||||
<field name="model">product.product,-1</field>
|
||||
<field name="action" ref="act_product_quantities_warehouse"/>
|
||||
</record>
|
||||
<record model="ir.action.keyword"
|
||||
id="act_product_quantities_warehouse_keyword2">
|
||||
<field name="keyword">form_relate</field>
|
||||
<field name="model">product.template,-1</field>
|
||||
<field name="action" ref="act_product_quantities_warehouse"/>
|
||||
</record>
|
||||
<record model="ir.action-res.group"
|
||||
id="act_product_quantities_warehouse-group_stock">
|
||||
<field name="action" ref="act_product_quantities_warehouse"/>
|
||||
<field name="group" ref="group_stock"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.action.wizard" id="wizard_open_product_quantities_by_warehouse_move">
|
||||
<field name="name">Stock Moves</field>
|
||||
<field name="wiz_name">stock.product_quantities_warehouse.move.open</field>
|
||||
</record>
|
||||
<record model="ir.action.keyword" id="wizard_open_product_quantities_by_warehouse_move_keyword1">
|
||||
<field name="keyword">tree_open</field>
|
||||
<field name="model">stock.product_quantities_warehouse,-1</field>
|
||||
<field name="action" ref="wizard_open_product_quantities_by_warehouse_move"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="product_quantities_warehouse_move_view_list">
|
||||
<field name="model">stock.product_quantities_warehouse.move</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="name">product_quantities_warehouse_move_list</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.action.act_window" id="act_product_quantities_warehouse_move">
|
||||
<field name="name">Stock Moves By Warehouse</field>
|
||||
<field name="res_model">stock.product_quantities_warehouse.move</field>
|
||||
<field
|
||||
name="context"
|
||||
eval="If(Eval('active_model') == 'product.template', {'product_template': Eval('active_ids')}, {'product': Eval('active_ids')})"
|
||||
pyson="1"/>
|
||||
<field name="search_value" eval="[('date', '>=', Date())]" pyson="1"/>
|
||||
<field name="context_model">stock.product_quantities_warehouse.context</field>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_product_quantities_warehouse_move_list_view">
|
||||
<field name="sequence" eval="10"/>
|
||||
<field name="view" ref="product_quantities_warehouse_move_view_list"/>
|
||||
<field name="act_window" ref="act_product_quantities_warehouse_move"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.action.keyword" id="act_product_quantities_warehouse_move_keyword1">
|
||||
<field name="keyword">form_relate</field>
|
||||
<field name="model">product.product,-1</field>
|
||||
<field name="action" ref="act_product_quantities_warehouse_move"/>
|
||||
</record>
|
||||
<record model="ir.action.keyword" id="act_product_quantities_warehouse_move_keyword2">
|
||||
<field name="keyword">form_relate</field>
|
||||
<field name="model">product.template,-1</field>
|
||||
<field name="action" ref="act_product_quantities_warehouse_move"/>
|
||||
</record>
|
||||
<record model="ir.action-res.group" id="act_product_quantities_warehouse_move-group_stock">
|
||||
<field name="action" ref="act_product_quantities_warehouse_move"/>
|
||||
<field name="group" ref="group_stock"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.rule.group" id="rule_group_product_quantities_warehouse_move_companies">
|
||||
<field name="name">User in companies</field>
|
||||
<field name="model">stock.product_quantities_warehouse.move</field>
|
||||
<field name="global_p" eval="True"/>
|
||||
</record>
|
||||
<record model="ir.rule" id="rule_product_quantities_warehouse_move_companies">
|
||||
<field
|
||||
name="domain"
|
||||
eval="[('company', 'in', Eval('companies', []))]"
|
||||
pyson="1"/>
|
||||
<field name="rule_group" ref="rule_group_product_quantities_warehouse_move_companies"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.access" id="access_product_quantities_warehouse_move">
|
||||
<field name="model">stock.product_quantities_warehouse.move</field>
|
||||
<field name="perm_read" eval="False"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
<field name="perm_create" eval="False"/>
|
||||
<field name="perm_delete" eval="False"/>
|
||||
</record>
|
||||
<record model="ir.model.access" id="access_product_quantities_warehouse_move_group_stock">
|
||||
<field name="model">stock.product_quantities_warehouse.move</field>
|
||||
<field name="group" ref="group_stock"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
<field name="perm_create" eval="False"/>
|
||||
<field name="perm_delete" eval="False"/>
|
||||
</record>
|
||||
</data>
|
||||
<data noupdate="1">
|
||||
<record model="ir.cron" id="cron_recompute_cost_price_from_moves">
|
||||
<field name="method">product.product|recompute_cost_price_from_moves</field>
|
||||
<field name="interval_number" eval="1"/>
|
||||
<field name="interval_type">days</field>
|
||||
</record>
|
||||
</data>
|
||||
</tryton>
|
||||
51
modules/stock/res.py
Normal file
51
modules/stock/res.py
Normal file
@@ -0,0 +1,51 @@
|
||||
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
from trytond.model import fields
|
||||
from trytond.pool import Pool, PoolMeta
|
||||
from trytond.transaction import Transaction
|
||||
|
||||
|
||||
class User(metaclass=PoolMeta):
|
||||
__name__ = 'res.user'
|
||||
|
||||
warehouse = fields.Many2One('stock.location',
|
||||
"Current Warehouse",
|
||||
domain=[('type', '=', 'warehouse')],
|
||||
help="The warehouse that the user works at.")
|
||||
|
||||
@classmethod
|
||||
def __setup__(cls):
|
||||
super().__setup__()
|
||||
cls._context_fields.insert(0, 'warehouse')
|
||||
|
||||
@classmethod
|
||||
def _get_preferences(cls, user, context_only=False):
|
||||
preferences = super()._get_preferences(user, context_only=context_only)
|
||||
if user.warehouse:
|
||||
preferences['warehouse'] = user.warehouse.id
|
||||
return preferences
|
||||
|
||||
def get_status_bar(self, name):
|
||||
pool = Pool()
|
||||
Location = pool.get('stock.location')
|
||||
status = super().get_status_bar(name)
|
||||
|
||||
if (self.warehouse
|
||||
and len(Location.search([('type', '=', 'warehouse')])) > 1):
|
||||
status += ' - %s' % self.warehouse.rec_name
|
||||
return status
|
||||
|
||||
@classmethod
|
||||
def read(cls, ids, fields_names):
|
||||
context = Transaction().context
|
||||
user_id = Transaction().user
|
||||
if user_id == 0 and 'user' in Transaction().context:
|
||||
user_id = Transaction().context['user']
|
||||
result = super().read(ids, fields_names)
|
||||
if ('warehouse' in fields_names
|
||||
and context.get('warehouse')
|
||||
and user_id in ids):
|
||||
for values in result:
|
||||
if values['id'] == user_id:
|
||||
values['warehouse'] = context['warehouse']
|
||||
return result
|
||||
17
modules/stock/res.xml
Normal file
17
modules/stock/res.xml
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
this repository contains the full copyright notices and license terms. -->
|
||||
<tryton>
|
||||
<data>
|
||||
<record model="ir.ui.view" id="user_view_form">
|
||||
<field name="model">res.user</field>
|
||||
<field name="inherit" ref="res.user_view_form"/>
|
||||
<field name="name">user_form</field>
|
||||
</record>
|
||||
<record model="ir.ui.view" id="user_view_form_preferences">
|
||||
<field name="model">res.user</field>
|
||||
<field name="inherit" ref="res.user_view_form_preferences"/>
|
||||
<field name="name">user_form_preferences</field>
|
||||
</record>
|
||||
</data>
|
||||
</tryton>
|
||||
3169
modules/stock/shipment.py
Normal file
3169
modules/stock/shipment.py
Normal file
File diff suppressed because it is too large
Load Diff
973
modules/stock/shipment.xml
Normal file
973
modules/stock/shipment.xml
Normal file
@@ -0,0 +1,973 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
this repository contains the full copyright notices and license terms. -->
|
||||
<tryton>
|
||||
<data>
|
||||
|
||||
<menuitem
|
||||
name="Shipments"
|
||||
parent="menu_stock"
|
||||
sequence="10"
|
||||
id="menu_shipment"/>
|
||||
|
||||
<record model="ir.ui.view" id="shipment_in_view_form">
|
||||
<field name="model">stock.shipment.in</field>
|
||||
<field name="type">form</field>
|
||||
<field name="name">shipment_in_form</field>
|
||||
</record>
|
||||
<record model="ir.ui.view" id="shipment_in_view_tree">
|
||||
<field name="model">stock.shipment.in</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="name">shipment_in_tree</field>
|
||||
</record>
|
||||
<record model="ir.action.act_window" id="act_shipment_in_form">
|
||||
<field name="name">Supplier Shipments</field>
|
||||
<field name="res_model">stock.shipment.in</field>
|
||||
<field name="search_value"></field>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view"
|
||||
id="act_shipment_in_form_view1">
|
||||
<field name="sequence" eval="1"/>
|
||||
<field name="view" ref="shipment_in_view_tree"/>
|
||||
<field name="act_window" ref="act_shipment_in_form"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view"
|
||||
id="act_shipment_in_form_view2">
|
||||
<field name="sequence" eval="2"/>
|
||||
<field name="view" ref="shipment_in_view_form"/>
|
||||
<field name="act_window" ref="act_shipment_in_form"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.domain" id="act_shipment_in_form_domain_draft">
|
||||
<field name="name">Draft</field>
|
||||
<field name="sequence" eval="10"/>
|
||||
<field name="domain" eval="[('state', '=', 'draft')]" pyson="1"/>
|
||||
<field name="count" eval="True"/>
|
||||
<field name="act_window" ref="act_shipment_in_form"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.domain" id="act_shipment_in_form_domain_received">
|
||||
<field name="name">Received</field>
|
||||
<field name="sequence" eval="20"/>
|
||||
<field name="domain" eval="[('state', '=', 'received')]" pyson="1"/>
|
||||
<field name="count" eval="True"/>
|
||||
<field name="act_window" ref="act_shipment_in_form"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.domain" id="act_shipment_in_form_domain_all">
|
||||
<field name="name">All</field>
|
||||
<field name="sequence" eval="9999"/>
|
||||
<field name="domain"></field>
|
||||
<field name="act_window" ref="act_shipment_in_form"/>
|
||||
</record>
|
||||
<menuitem
|
||||
parent="menu_shipment"
|
||||
action="act_shipment_in_form"
|
||||
sequence="10"
|
||||
id="menu_shipment_in_form"/>
|
||||
|
||||
<record model="ir.ui.view" id="shipment_in_return_view_form">
|
||||
<field name="model">stock.shipment.in.return</field>
|
||||
<field name="type">form</field>
|
||||
<field name="name">shipment_in_return_form</field>
|
||||
</record>
|
||||
<record model="ir.ui.view" id="shipment_in_return_view_tree">
|
||||
<field name="model">stock.shipment.in.return</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="name">shipment_in_return_tree</field>
|
||||
</record>
|
||||
<record model="ir.action.act_window" id="act_shipment_in_return_form">
|
||||
<field name="name">Supplier Returns</field>
|
||||
<field name="res_model">stock.shipment.in.return</field>
|
||||
<field name="search_value"></field>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view"
|
||||
id="act_shipment_in_return_form_view1">
|
||||
<field name="sequence" eval="1"/>
|
||||
<field name="view" ref="shipment_in_return_view_tree"/>
|
||||
<field name="act_window" ref="act_shipment_in_return_form"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view"
|
||||
id="act_shipment_in_return_form_view2">
|
||||
<field name="sequence" eval="2"/>
|
||||
<field name="view" ref="shipment_in_return_view_form"/>
|
||||
<field name="act_window" ref="act_shipment_in_return_form"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.domain"
|
||||
id="act_shipment_in_return_form_domain_draft">
|
||||
<field name="name">Draft</field>
|
||||
<field name="sequence" eval="10"/>
|
||||
<field name="domain" eval="[('state', '=', 'draft')]" pyson="1"/>
|
||||
<field name="count" eval="True"/>
|
||||
<field name="act_window" ref="act_shipment_in_return_form"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.domain"
|
||||
id="act_shipment_in_return_form_domain_waiting">
|
||||
<field name="name">Waiting</field>
|
||||
<field name="sequence" eval="20"/>
|
||||
<field name="domain" eval="[('state', '=', 'waiting')]" pyson="1"/>
|
||||
<field name="count" eval="True"/>
|
||||
<field name="act_window" ref="act_shipment_in_return_form"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.domain"
|
||||
id="act_shipment_in_return_form_domain_available">
|
||||
<field name="name">Partially Assigned</field>
|
||||
<field name="sequence" eval="30"/>
|
||||
<field name="domain" eval="[('partially_assigned', '=', 'True')]" pyson="1"/>
|
||||
<field name="count" eval="True"/>
|
||||
<field name="act_window" ref="act_shipment_in_return_form"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.domain"
|
||||
id="act_shipment_in_return_form_domain_assigned">
|
||||
<field name="name">Assigned</field>
|
||||
<field name="sequence" eval="40"/>
|
||||
<field name="domain" eval="[('state', '=', 'assigned')]" pyson="1"/>
|
||||
<field name="count" eval="True"/>
|
||||
<field name="act_window" ref="act_shipment_in_return_form"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.domain"
|
||||
id="act_shipment_in_return_form_domain_all">
|
||||
<field name="name">All</field>
|
||||
<field name="sequence" eval="9999"/>
|
||||
<field name="domain"></field>
|
||||
<field name="act_window" ref="act_shipment_in_return_form"/>
|
||||
</record>
|
||||
<menuitem
|
||||
parent="menu_shipment"
|
||||
action="act_shipment_in_return_form"
|
||||
sequence="10"
|
||||
id="menu_shipment_in_return_form"/>
|
||||
|
||||
<record model="ir.ui.view" id="shipment_out_view_form">
|
||||
<field name="model">stock.shipment.out</field>
|
||||
<field name="type">form</field>
|
||||
<field name="name">shipment_out_form</field>
|
||||
</record>
|
||||
<record model="ir.ui.view" id="shipment_out_view_tree">
|
||||
<field name="model">stock.shipment.out</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="name">shipment_out_tree</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.action.act_window" id="act_shipment_out_form">
|
||||
<field name="name">Customer Shipments</field>
|
||||
<field name="res_model">stock.shipment.out</field>
|
||||
<field name="search_value"></field>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view"
|
||||
id="act_shipment_out_form_view1">
|
||||
<field name="sequence" eval="1"/>
|
||||
<field name="view" ref="shipment_out_view_tree"/>
|
||||
<field name="act_window" ref="act_shipment_out_form"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view"
|
||||
id="act_shipment_out_form_view2">
|
||||
<field name="sequence" eval="2"/>
|
||||
<field name="view" ref="shipment_out_view_form"/>
|
||||
<field name="act_window" ref="act_shipment_out_form"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.domain" id="act_shipment_out_form_domain_draft">
|
||||
<field name="name">Draft</field>
|
||||
<field name="sequence" eval="10"/>
|
||||
<field name="domain" eval="[('state', '=', 'draft')]" pyson="1"/>
|
||||
<field name="count" eval="True"/>
|
||||
<field name="act_window" ref="act_shipment_out_form"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.domain" id="act_shipment_out_form_domain_waiting">
|
||||
<field name="name">Waiting</field>
|
||||
<field name="sequence" eval="20"/>
|
||||
<field name="domain" eval="[('state', '=', 'waiting')]" pyson="1"/>
|
||||
<field name="count" eval="True"/>
|
||||
<field name="act_window" ref="act_shipment_out_form"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.domain" id="act_shipment_out_form_domain_available">
|
||||
<field name="name">Partially Assigned</field>
|
||||
<field name="sequence" eval="30"/>
|
||||
<field name="domain" eval="[('partially_assigned', '=', True)]" pyson="1"/>
|
||||
<field name="count" eval="True"/>
|
||||
<field name="act_window" ref="act_shipment_out_form"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.domain" id="act_shipment_out_form_domain_assigned">
|
||||
<field name="name">Assigned</field>
|
||||
<field name="sequence" eval="40"/>
|
||||
<field name="domain" eval="[('state', '=', 'assigned')]" pyson="1"/>
|
||||
<field name="count" eval="True"/>
|
||||
<field name="act_window" ref="act_shipment_out_form"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.domain" id="act_shipment_out_form_domain_picked">
|
||||
<field name="name">Picked</field>
|
||||
<field name="sequence" eval="50"/>
|
||||
<field name="domain" eval="[('state', '=', 'picked')]" pyson="1"/>
|
||||
<field name="count" eval="True"/>
|
||||
<field name="act_window" ref="act_shipment_out_form"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.domain" id="act_shipment_out_form_domain_packed">
|
||||
<field name="name">Packed</field>
|
||||
<field name="sequence" eval="60"/>
|
||||
<field name="domain" eval="[('state', '=', 'packed')]" pyson="1"/>
|
||||
<field name="count" eval="True"/>
|
||||
<field name="act_window" ref="act_shipment_out_form"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.domain" id="act_shipment_out_form_domain_shipped">
|
||||
<field name="name">Shipped</field>
|
||||
<field name="sequence" eval="70"/>
|
||||
<field name="domain" eval="[('state', '=', 'shipped')]" pyson="1"/>
|
||||
<field name="count" eval="True"/>
|
||||
<field name="act_window" ref="act_shipment_out_form"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.domain" id="act_shipment_out_form_domain_all">
|
||||
<field name="name">All</field>
|
||||
<field name="sequence" eval="9999"/>
|
||||
<field name="domain"></field>
|
||||
<field name="act_window" ref="act_shipment_out_form"/>
|
||||
</record>
|
||||
<menuitem
|
||||
parent="menu_shipment"
|
||||
action="act_shipment_out_form"
|
||||
sequence="10"
|
||||
id="menu_shipment_out_form"/>
|
||||
|
||||
<record model="ir.ui.view" id="shipment_internal_view_form">
|
||||
<field name="model">stock.shipment.internal</field>
|
||||
<field name="type">form</field>
|
||||
<field name="name">shipment_internal_form</field>
|
||||
</record>
|
||||
<record model="ir.ui.view" id="shipment_internal_view_tree">
|
||||
<field name="model">stock.shipment.internal</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="name">shipment_internal_tree</field>
|
||||
</record>
|
||||
<record model="ir.action.act_window" id="act_shipment_internal_form">
|
||||
<field name="name">Internal Shipments</field>
|
||||
<field name="res_model">stock.shipment.internal</field>
|
||||
<field name="search_value"></field>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view"
|
||||
id="act_shipment_internal_form_view1">
|
||||
<field name="sequence" eval="1"/>
|
||||
<field name="view" ref="shipment_internal_view_tree"/>
|
||||
<field name="act_window" ref="act_shipment_internal_form"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view"
|
||||
id="act_shipment_internal_form_view2">
|
||||
<field name="sequence" eval="2"/>
|
||||
<field name="view" ref="shipment_internal_view_form"/>
|
||||
<field name="act_window" ref="act_shipment_internal_form"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.domain"
|
||||
id="act_shipment_internal_form_domain_requests">
|
||||
<field name="name">Requests</field>
|
||||
<field name="sequence" eval="5"/>
|
||||
<field name="domain" eval="[('state', '=', 'request')]" pyson="1"/>
|
||||
<field name="count" eval="True"/>
|
||||
<field name="act_window" ref="act_shipment_internal_form"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.domain"
|
||||
id="act_shipment_internal_form_domain_draft">
|
||||
<field name="name">Draft</field>
|
||||
<field name="sequence" eval="10"/>
|
||||
<field name="domain" eval="[('state', '=', 'draft')]" pyson="1"/>
|
||||
<field name="count" eval="True"/>
|
||||
<field name="act_window" ref="act_shipment_internal_form"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.domain"
|
||||
id="act_shipment_internal_form_domain_waiting">
|
||||
<field name="name">Waiting</field>
|
||||
<field name="sequence" eval="20"/>
|
||||
<field name="domain" eval="[('state', '=', 'waiting')]" pyson="1"/>
|
||||
<field name="count" eval="True"/>
|
||||
<field name="act_window" ref="act_shipment_internal_form"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.domain"
|
||||
id="act_shipment_internal_form_domain_available">
|
||||
<field name="name">Partially Assigned</field>
|
||||
<field name="sequence" eval="30"/>
|
||||
<field name="domain" eval="[('partially_assigned', '=', True)]" pyson="1"/>
|
||||
<field name="count" eval="True"/>
|
||||
<field name="act_window" ref="act_shipment_internal_form"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.domain"
|
||||
id="act_shipment_internal_form_domain_assigned">
|
||||
<field name="name">Assigned</field>
|
||||
<field name="sequence" eval="40"/>
|
||||
<field name="domain" eval="[('state', '=', 'assigned')]" pyson="1"/>
|
||||
<field name="count" eval="True"/>
|
||||
<field name="act_window" ref="act_shipment_internal_form"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.domain" id="act_shipment_internal_form_domain_packed">
|
||||
<field name="name">Packed</field>
|
||||
<field name="sequence" eval="50"/>
|
||||
<field name="domain" eval="[('state', '=', 'packed')]" pyson="1"/>
|
||||
<field name="count" eval="True"/>
|
||||
<field name="act_window" ref="act_shipment_internal_form"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.domain"
|
||||
id="act_shipment_internal_form_domain_shipped">
|
||||
<field name="name">Shipped</field>
|
||||
<field name="sequence" eval="60"/>
|
||||
<field name="domain" eval="[('state', '=', 'shipped')]" pyson="1"/>
|
||||
<field name="act_window" ref="act_shipment_internal_form"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.domain"
|
||||
id="act_shipment_internal_form_domain_all">
|
||||
<field name="name">All</field>
|
||||
<field name="sequence" eval="9999"/>
|
||||
<field name="domain"></field>
|
||||
<field name="act_window" ref="act_shipment_internal_form"/>
|
||||
</record>
|
||||
<menuitem
|
||||
parent="menu_shipment"
|
||||
action="act_shipment_internal_form"
|
||||
sequence="20"
|
||||
id="menu_shipment_internal_form"/>
|
||||
|
||||
<record model="ir.ui.view" id="shipment_out_return_view_form">
|
||||
<field name="model">stock.shipment.out.return</field>
|
||||
<field name="type">form</field>
|
||||
<field name="name">shipment_out_return_form</field>
|
||||
</record>
|
||||
<record model="ir.ui.view" id="shipment_out_return_view_tree">
|
||||
<field name="model">stock.shipment.out.return</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="name">shipment_out_return_tree</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.action.act_window" id="act_shipment_out_return_form">
|
||||
<field name="name">Customer Returns</field>
|
||||
<field name="res_model">stock.shipment.out.return</field>
|
||||
<field name="search_value"></field>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view"
|
||||
id="act_shipment_out_return_form_view1">
|
||||
<field name="sequence" eval="1"/>
|
||||
<field name="view" ref="shipment_out_return_view_tree"/>
|
||||
<field name="act_window" ref="act_shipment_out_return_form"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view"
|
||||
id="act_shipment_out_return_form_view2">
|
||||
<field name="sequence" eval="2"/>
|
||||
<field name="view" ref="shipment_out_return_view_form"/>
|
||||
<field name="act_window" ref="act_shipment_out_return_form"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.domain"
|
||||
id="act_shipment_out_return_form_domain_draft">
|
||||
<field name="name">Draft</field>
|
||||
<field name="sequence" eval="10"/>
|
||||
<field name="domain" eval="[('state', '=', 'draft')]" pyson="1"/>
|
||||
<field name="count" eval="True"/>
|
||||
<field name="act_window" ref="act_shipment_out_return_form"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.domain"
|
||||
id="act_shipment_out_return_form_domain_received">
|
||||
<field name="name">Received</field>
|
||||
<field name="sequence" eval="20"/>
|
||||
<field name="domain" eval="[('state', '=', 'received')]" pyson="1"/>
|
||||
<field name="count" eval="True"/>
|
||||
<field name="act_window" ref="act_shipment_out_return_form"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.domain"
|
||||
id="act_shipment_out_return_form_domain_all">
|
||||
<field name="name">All</field>
|
||||
<field name="sequence" eval="9999"/>
|
||||
<field name="domain"></field>
|
||||
<field name="act_window" ref="act_shipment_out_return_form"/>
|
||||
</record>
|
||||
<menuitem
|
||||
parent="menu_shipment"
|
||||
action="act_shipment_out_return_form"
|
||||
sequence="10"
|
||||
id="menu_shipment_out_return_form"/>
|
||||
|
||||
<record model="ir.action.report" id="report_shipment_out_delivery_note">
|
||||
<field name="name">Delivery Note</field>
|
||||
<field name="model">stock.shipment.out</field>
|
||||
<field name="report_name">stock.shipment.out.delivery_note</field>
|
||||
<field name="report">stock/delivery_note.fodt</field>
|
||||
</record>
|
||||
<record model="ir.action.keyword"
|
||||
id="report_shipment_out_delivery_note_keyword">
|
||||
<field name="keyword">form_print</field>
|
||||
<field name="model">stock.shipment.out,-1</field>
|
||||
<field name="action" ref="report_shipment_out_delivery_note"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.action.report" id="report_shipment_out_picking_list">
|
||||
<field name="name">Picking List</field>
|
||||
<field name="model">stock.shipment.out</field>
|
||||
<field name="report_name">stock.shipment.out.picking_list</field>
|
||||
<field name="report">stock/picking_list.fodt</field>
|
||||
</record>
|
||||
<record model="ir.action.keyword"
|
||||
id="report_shipment_out_picking_list_keyword">
|
||||
<field name="keyword">form_print</field>
|
||||
<field name="model">stock.shipment.out,-1</field>
|
||||
<field name="action" ref="report_shipment_out_picking_list"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.action.report" id="report_shipment_in_restocking_list">
|
||||
<field name="name">Restocking List</field>
|
||||
<field name="model">stock.shipment.in</field>
|
||||
<field name="report_name">stock.shipment.in.restocking_list</field>
|
||||
<field name="report">stock/supplier_restocking_list.fodt</field>
|
||||
</record>
|
||||
<record model="ir.action.keyword"
|
||||
id="report_shipment_in_restocking_list_keyword">
|
||||
<field name="keyword">form_print</field>
|
||||
<field name="model">stock.shipment.in,-1</field>
|
||||
<field name="action" ref="report_shipment_in_restocking_list"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.action.report" id="report_shipment_out_return_restocking_list">
|
||||
<field name="name">Restocking List</field>
|
||||
<field name="model">stock.shipment.out.return</field>
|
||||
<field name="report_name">stock.shipment.out.return.restocking_list</field>
|
||||
<field name="report">stock/customer_return_restocking_list.fodt</field>
|
||||
</record>
|
||||
<record model="ir.action.keyword"
|
||||
id="report_shipment_out_return_restocking_list_keyword">
|
||||
<field name="keyword">form_print</field>
|
||||
<field name="model">stock.shipment.out.return,-1</field>
|
||||
<field name="action" ref="report_shipment_out_return_restocking_list"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.action.report" id="report_shipment_internal">
|
||||
<field name="name">Internal Shipment</field>
|
||||
<field name="model">stock.shipment.internal</field>
|
||||
<field name="report_name">stock.shipment.internal.report</field>
|
||||
<field name="report">stock/internal_shipment.fodt</field>
|
||||
</record>
|
||||
<record model="ir.action.keyword"
|
||||
id="report_shipment_internal_keyword">
|
||||
<field name="keyword">form_print</field>
|
||||
<field name="model">stock.shipment.internal,-1</field>
|
||||
<field name="action" ref="report_shipment_internal"/>
|
||||
</record>
|
||||
|
||||
<!-- Sequence shipment out -->
|
||||
<record model="ir.sequence.type" id="sequence_type_shipment_out">
|
||||
<field name="name">Customer Shipment</field>
|
||||
</record>
|
||||
<record model="ir.sequence.type-res.group"
|
||||
id="sequence_type_shipment_out_group_admin">
|
||||
<field name="sequence_type" ref="sequence_type_shipment_out"/>
|
||||
<field name="group" ref="res.group_admin"/>
|
||||
</record>
|
||||
<record model="ir.sequence.type-res.group"
|
||||
id="sequence_type_shipment_out_group_stock_admin">
|
||||
<field name="sequence_type" ref="sequence_type_shipment_out"/>
|
||||
<field name="group" ref="group_stock_admin"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.sequence" id="sequence_shipment_out">
|
||||
<field name="name">Customer Shipment</field>
|
||||
<field name="sequence_type" ref="sequence_type_shipment_out"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.sequence.type" id="sequence_type_shipment_in">
|
||||
<field name="name">Supplier Shipment</field>
|
||||
</record>
|
||||
<record model="ir.sequence.type-res.group"
|
||||
id="sequence_type_shipment_in_group_admin">
|
||||
<field name="sequence_type" ref="sequence_type_shipment_in"/>
|
||||
<field name="group" ref="res.group_admin"/>
|
||||
</record>
|
||||
<record model="ir.sequence.type-res.group"
|
||||
id="sequence_type_shipment_in_group_stock_admin">
|
||||
<field name="sequence_type" ref="sequence_type_shipment_in"/>
|
||||
<field name="group" ref="group_stock_admin"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.sequence" id="sequence_shipment_in">
|
||||
<field name="name">Supplier Shipment</field>
|
||||
<field name="sequence_type" ref="sequence_type_shipment_in"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.sequence.type" id="sequence_type_shipment_internal">
|
||||
<field name="name">Internal Shipment</field>
|
||||
</record>
|
||||
<record model="ir.sequence.type-res.group"
|
||||
id="sequence_type_shipment_internal_group_admin">
|
||||
<field name="sequence_type" ref="sequence_type_shipment_internal"/>
|
||||
<field name="group" ref="res.group_admin"/>
|
||||
</record>
|
||||
<record model="ir.sequence.type-res.group"
|
||||
id="sequence_type_shipment_internal_group_stock_admin">
|
||||
<field name="sequence_type" ref="sequence_type_shipment_internal"/>
|
||||
<field name="group" ref="group_stock_admin"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.sequence" id="sequence_shipment_internal">
|
||||
<field name="name">Internal Shipment</field>
|
||||
<field name="sequence_type" ref="sequence_type_shipment_internal"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.sequence.type" id="sequence_type_shipment_out_return">
|
||||
<field name="name">Customer Return Shipment</field>
|
||||
</record>
|
||||
<record model="ir.sequence.type-res.group"
|
||||
id="sequence_type_shipment_out_return_group_admin">
|
||||
<field name="sequence_type" ref="sequence_type_shipment_out_return"/>
|
||||
<field name="group" ref="res.group_admin"/>
|
||||
</record>
|
||||
<record model="ir.sequence.type-res.group"
|
||||
id="sequence_type_shipment_out_return_group_stock_admin">
|
||||
<field name="sequence_type" ref="sequence_type_shipment_out_return"/>
|
||||
<field name="group" ref="group_stock_admin"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.sequence" id="sequence_shipment_out_return">
|
||||
<field name="name">Customer Return Shipment</field>
|
||||
<field name="sequence_type" ref="sequence_type_shipment_out_return"/>
|
||||
</record>
|
||||
|
||||
<!-- Sequence shipment in return -->
|
||||
<record model="ir.sequence.type" id="sequence_type_shipment_in_return">
|
||||
<field name="name">Supplier Return Shipment</field>
|
||||
</record>
|
||||
<record model="ir.sequence.type-res.group"
|
||||
id="sequence_type_shipment_in_return_group_admin">
|
||||
<field name="sequence_type" ref="sequence_type_shipment_in_return"/>
|
||||
<field name="group" ref="res.group_admin"/>
|
||||
</record>
|
||||
<record model="ir.sequence.type-res.group"
|
||||
id="sequence_type_shipment_in_return_group_stock_admin">
|
||||
<field name="sequence_type" ref="sequence_type_shipment_in_return"/>
|
||||
<field name="group" ref="group_stock_admin"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.sequence" id="sequence_shipment_in_return">
|
||||
<field name="name">Supplier Return Shipment</field>
|
||||
<field name="sequence_type" ref="sequence_type_shipment_in_return"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.access" id="access_shipment_in">
|
||||
<field name="model">stock.shipment.in</field>
|
||||
<field name="perm_read" eval="False"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
<field name="perm_create" eval="False"/>
|
||||
<field name="perm_delete" eval="False"/>
|
||||
</record>
|
||||
<record model="ir.model.access" id="access_shipment_in_group_stock">
|
||||
<field name="model">stock.shipment.in</field>
|
||||
<field name="group" ref="group_stock"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="True"/>
|
||||
<field name="perm_create" eval="True"/>
|
||||
<field name="perm_delete" eval="False"/>
|
||||
</record>
|
||||
<record model="ir.model.access" id="access_shipment_in_group_stock_admin">
|
||||
<field name="model">stock.shipment.in</field>
|
||||
<field name="group" ref="group_stock_admin"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="True"/>
|
||||
<field name="perm_create" eval="True"/>
|
||||
<field name="perm_delete" eval="True"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.button" id="shipment_in_cancel_button">
|
||||
<field name="model">stock.shipment.in</field>
|
||||
<field name="name">cancel</field>
|
||||
<field name="string">Cancel</field>
|
||||
<field name="confirm">Are you sure you want to cancel the shipment?</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.button" id="shipment_in_draft_button">
|
||||
<field name="model">stock.shipment.in</field>
|
||||
<field name="name">draft</field>
|
||||
<field name="string">Reset to Draft</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.button" id="shipment_in_receive_button">
|
||||
<field name="model">stock.shipment.in</field>
|
||||
<field name="name">receive</field>
|
||||
<field name="string">Receive</field>
|
||||
<field name="confirm">Are you sure you want to receive the shipment?</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.button" id="shipment_in_done_button">
|
||||
<field name="model">stock.shipment.in</field>
|
||||
<field name="name">do</field>
|
||||
<field name="string">Complete</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.access" id="access_shipment_out">
|
||||
<field name="model">stock.shipment.out</field>
|
||||
<field name="perm_read" eval="False"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
<field name="perm_create" eval="False"/>
|
||||
<field name="perm_delete" eval="False"/>
|
||||
</record>
|
||||
<record model="ir.model.access" id="access_shipment_out_group_stock">
|
||||
<field name="model">stock.shipment.out</field>
|
||||
<field name="group" ref="group_stock"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="True"/>
|
||||
<field name="perm_create" eval="True"/>
|
||||
<field name="perm_delete" eval="False"/>
|
||||
</record>
|
||||
<record model="ir.model.access" id="access_shipment_out_group_stock_admin">
|
||||
<field name="model">stock.shipment.out</field>
|
||||
<field name="group" ref="group_stock_admin"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="True"/>
|
||||
<field name="perm_create" eval="True"/>
|
||||
<field name="perm_delete" eval="True"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.button" id="shipment_out_cancel_button">
|
||||
<field name="model">stock.shipment.out</field>
|
||||
<field name="name">cancel</field>
|
||||
<field name="string">Cancel</field>
|
||||
<field name="confirm">Are you sure you want to cancel the shipment?</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.button" id="shipment_out_draft_button">
|
||||
<field name="model">stock.shipment.out</field>
|
||||
<field name="name">draft</field>
|
||||
<field name="string">Draft</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.button" id="shipment_out_wait_button">
|
||||
<field name="model">stock.shipment.out</field>
|
||||
<field name="name">wait</field>
|
||||
<field name="string">Wait</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.button" id="shipment_out_pick_button">
|
||||
<field name="model">stock.shipment.out</field>
|
||||
<field name="name">pick</field>
|
||||
<field name="string">Pick</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.button" id="shipment_out_pack_button">
|
||||
<field name="model">stock.shipment.out</field>
|
||||
<field name="name">pack</field>
|
||||
<field name="string">Pack</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.button" id="shipment_out_ship_button">
|
||||
<field name="model">stock.shipment.out</field>
|
||||
<field name="name">ship</field>
|
||||
<field name="string">Ship</field>
|
||||
<field name="confirm">Are you sure you want to ship the shipment?</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.button" id="shipment_out_done_button">
|
||||
<field name="model">stock.shipment.out</field>
|
||||
<field name="name">do</field>
|
||||
<field name="string">Complete</field>
|
||||
<field name="confirm">Are you sure you want to complete the shipment?</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.button" id="shipment_out_assign_try_button">
|
||||
<field name="model">stock.shipment.out</field>
|
||||
<field name="name">assign_try</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.button" id="shipment_out_assign_force_button">
|
||||
<field name="model">stock.shipment.out</field>
|
||||
<field name="name">assign_force</field>
|
||||
</record>
|
||||
<record model="ir.model.button-res.group"
|
||||
id="shipment_out_assign_force_button_group_stock_force_assignment">
|
||||
<field name="button" ref="shipment_out_assign_force_button"/>
|
||||
<field name="group" ref="group_stock_force_assignment"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.button" id="shipment_out_assign_wizard_button">
|
||||
<field name="model">stock.shipment.out</field>
|
||||
<field name="name">assign_wizard</field>
|
||||
<field name="string">Assign</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.access" id="access_shipment_internal">
|
||||
<field name="model">stock.shipment.internal</field>
|
||||
<field name="perm_read" eval="False"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
<field name="perm_create" eval="False"/>
|
||||
<field name="perm_delete" eval="False"/>
|
||||
</record>
|
||||
<record model="ir.model.access" id="access_shipment_internal_group_stock">
|
||||
<field name="model">stock.shipment.internal</field>
|
||||
<field name="group" ref="group_stock"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="True"/>
|
||||
<field name="perm_create" eval="True"/>
|
||||
<field name="perm_delete" eval="False"/>
|
||||
</record>
|
||||
<record model="ir.model.access" id="access_shipment_internal_group_stock_admin">
|
||||
<field name="model">stock.shipment.internal</field>
|
||||
<field name="group" ref="group_stock_admin"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="True"/>
|
||||
<field name="perm_create" eval="True"/>
|
||||
<field name="perm_delete" eval="True"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.button" id="shipment_internal_cancel_button">
|
||||
<field name="model">stock.shipment.internal</field>
|
||||
<field name="name">cancel</field>
|
||||
<field name="string">Cancel</field>
|
||||
<field name="confirm">Are you sure you want to cancel the shipment?</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.button" id="shipment_internal_draft_button">
|
||||
<field name="model">stock.shipment.internal</field>
|
||||
<field name="name">draft</field>
|
||||
<field name="string">Draft</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.button" id="shipment_internal_wait_button">
|
||||
<field name="model">stock.shipment.internal</field>
|
||||
<field name="name">wait</field>
|
||||
<field name="string">Wait</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.button" id="shipment_internal_done_button">
|
||||
<field name="model">stock.shipment.internal</field>
|
||||
<field name="name">do</field>
|
||||
<field name="string">Complete</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.button" id="shipment_internal_assign_try_button">
|
||||
<field name="model">stock.shipment.internal</field>
|
||||
<field name="name">assign_try</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.button" id="shipment_internal_assign_force_button">
|
||||
<field name="model">stock.shipment.internal</field>
|
||||
<field name="name">assign_force</field>
|
||||
</record>
|
||||
<record model="ir.model.button-res.group"
|
||||
id="shipment_internal_assign_force_button_group_stock_force_assignment">
|
||||
<field name="button" ref="shipment_internal_assign_force_button"/>
|
||||
<field name="group" ref="group_stock_force_assignment"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.button"
|
||||
id="shipment_internal_assign_wizard_button">
|
||||
<field name="model">stock.shipment.internal</field>
|
||||
<field name="name">assign_wizard</field>
|
||||
<field name="string">Assign</field>
|
||||
</record>
|
||||
<record model="ir.model.button-res.group"
|
||||
id="shipment_internal_assign_wizard_button_group_stock">
|
||||
<field name="button" ref="shipment_internal_assign_wizard_button"/>
|
||||
<field name="group" ref="group_stock"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.button" id="shipment_internal_pack_button">
|
||||
<field name="model">stock.shipment.internal</field>
|
||||
<field name="name">pack</field>
|
||||
<field name="string">Pack</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.button" id="shipment_internal_ship_button">
|
||||
<field name="model">stock.shipment.internal</field>
|
||||
<field name="name">ship</field>
|
||||
<field name="string">Ship</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.access" id="access_shipment_out_return">
|
||||
<field name="model">stock.shipment.out.return</field>
|
||||
<field name="perm_read" eval="False"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
<field name="perm_create" eval="False"/>
|
||||
<field name="perm_delete" eval="False"/>
|
||||
</record>
|
||||
<record model="ir.model.access" id="access_shipment_out_return_group_stock">
|
||||
<field name="model">stock.shipment.out.return</field>
|
||||
<field name="group" ref="group_stock"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="True"/>
|
||||
<field name="perm_create" eval="True"/>
|
||||
<field name="perm_delete" eval="False"/>
|
||||
</record>
|
||||
<record model="ir.model.access" id="access_shipment_out_return_group_stock_admin">
|
||||
<field name="model">stock.shipment.out.return</field>
|
||||
<field name="group" ref="group_stock_admin"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="True"/>
|
||||
<field name="perm_create" eval="True"/>
|
||||
<field name="perm_delete" eval="True"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.button" id="shipment_out_return_cancel_button">
|
||||
<field name="model">stock.shipment.out.return</field>
|
||||
<field name="name">cancel</field>
|
||||
<field name="string">Cancel</field>
|
||||
<field name="confirm">Are you sure you want to cancel the shipment?</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.button" id="shipment_out_return_draft_button">
|
||||
<field name="model">stock.shipment.out.return</field>
|
||||
<field name="name">draft</field>
|
||||
<field name="string">Draft</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.button" id="shipment_out_return_receive_button">
|
||||
<field name="model">stock.shipment.out.return</field>
|
||||
<field name="name">receive</field>
|
||||
<field name="string">Receive</field>
|
||||
<field name="confirm">Are you sure you want to receive the shipment?</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.button" id="shipment_out_return_done_button">
|
||||
<field name="model">stock.shipment.out.return</field>
|
||||
<field name="name">do</field>
|
||||
<field name="string">Complete</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.access" id="access_shipment_in_return">
|
||||
<field name="model">stock.shipment.in.return</field>
|
||||
<field name="perm_read" eval="False"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
<field name="perm_create" eval="False"/>
|
||||
<field name="perm_delete" eval="False"/>
|
||||
</record>
|
||||
<record model="ir.model.access" id="access_shipment_in_return_group_stock">
|
||||
<field name="model">stock.shipment.in.return</field>
|
||||
<field name="group" ref="group_stock"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="True"/>
|
||||
<field name="perm_create" eval="True"/>
|
||||
<field name="perm_delete" eval="False"/>
|
||||
</record>
|
||||
<record model="ir.model.access" id="access_shipment_in_return_group_stock_admin">
|
||||
<field name="model">stock.shipment.in.return</field>
|
||||
<field name="group" ref="group_stock_admin"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="True"/>
|
||||
<field name="perm_create" eval="True"/>
|
||||
<field name="perm_delete" eval="True"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.button" id="shipment_in_return_cancel_button">
|
||||
<field name="model">stock.shipment.in.return</field>
|
||||
<field name="name">cancel</field>
|
||||
<field name="string">Cancel</field>
|
||||
<field name="confirm">Are you sure you want to cancel the shipment?</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.button" id="shipment_in_return_draft_button">
|
||||
<field name="model">stock.shipment.in.return</field>
|
||||
<field name="name">draft</field>
|
||||
<field name="string">Draft</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.button" id="shipment_in_return_wait_button">
|
||||
<field name="model">stock.shipment.in.return</field>
|
||||
<field name="name">wait</field>
|
||||
<field name="string">Wait</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.button" id="shipment_in_return_done_button">
|
||||
<field name="model">stock.shipment.in.return</field>
|
||||
<field name="name">do</field>
|
||||
<field name="string">Complete</field>
|
||||
<field name="confirm">Are you sure you want to complete the shipment?</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.button" id="shipment_in_return_assign_try_button">
|
||||
<field name="model">stock.shipment.in.return</field>
|
||||
<field name="name">assign_try</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.button" id="shipment_in_return_assign_force_button">
|
||||
<field name="model">stock.shipment.in.return</field>
|
||||
<field name="name">assign_force</field>
|
||||
</record>
|
||||
<record model="ir.model.button-res.group"
|
||||
id="shipment_in_return_assign_force_button_group_stock_force_assignment">
|
||||
<field name="button" ref="shipment_in_return_assign_force_button"/>
|
||||
<field name="group" ref="group_stock_force_assignment"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.button"
|
||||
id="shipment_in_return_assign_wizard_button">
|
||||
<field name="model">stock.shipment.in.return</field>
|
||||
<field name="name">assign_wizard</field>
|
||||
<field name="string">Assign</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.rule.group" id="rule_group_shipment_in_companies">
|
||||
<field name="name">User in companies</field>
|
||||
<field name="model">stock.shipment.in</field>
|
||||
<field name="global_p" eval="True"/>
|
||||
</record>
|
||||
<record model="ir.rule" id="rule_shipment_in_companies">
|
||||
<field name="domain"
|
||||
eval="[('company', 'in', Eval('companies', []))]"
|
||||
pyson="1"/>
|
||||
<field name="rule_group" ref="rule_group_shipment_in_companies"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.rule.group" id="rule_group_shipment_in_return_companies">
|
||||
<field name="name">User in companies</field>
|
||||
<field name="model">stock.shipment.in.return</field>
|
||||
<field name="global_p" eval="True"/>
|
||||
</record>
|
||||
<record model="ir.rule" id="rule_shipment_in_return_companies">
|
||||
<field name="domain"
|
||||
eval="[('company', 'in', Eval('companies', []))]"
|
||||
pyson="1"/>
|
||||
<field name="rule_group" ref="rule_group_shipment_in_return_companies"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.rule.group" id="rule_group_shipment_out_companies">
|
||||
<field name="name">User in companies</field>
|
||||
<field name="model">stock.shipment.out</field>
|
||||
<field name="global_p" eval="True"/>
|
||||
</record>
|
||||
<record model="ir.rule" id="rule_shipment_out_companies">
|
||||
<field name="domain"
|
||||
eval="[('company', 'in', Eval('companies', []))]"
|
||||
pyson="1"/>
|
||||
<field name="rule_group" ref="rule_group_shipment_out_companies"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.rule.group" id="rule_group_shipment_out_return_companies">
|
||||
<field name="name">User in companies</field>
|
||||
<field name="model">stock.shipment.out.return</field>
|
||||
<field name="global_p" eval="True"/>
|
||||
</record>
|
||||
<record model="ir.rule" id="rule_shipment_out_return_companies">
|
||||
<field name="domain"
|
||||
eval="[('company', 'in', Eval('companies', []))]"
|
||||
pyson="1"/>
|
||||
<field name="rule_group" ref="rule_group_shipment_out_return_companies"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.rule.group" id="rule_group_shipment_internal_companies">
|
||||
<field name="name">User in companies</field>
|
||||
<field name="model">stock.shipment.internal</field>
|
||||
<field name="global_p" eval="True"/>
|
||||
</record>
|
||||
<record model="ir.rule" id="rule_shipment_internal_companies">
|
||||
<field name="domain"
|
||||
eval="[('company', 'in', Eval('companies', []))]"
|
||||
pyson="1"/>
|
||||
<field name="rule_group" ref="rule_group_shipment_internal_companies"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="shipment_assign_partial_view_form">
|
||||
<field name="model">stock.shipment.assign.partial</field>
|
||||
<field name="type">form</field>
|
||||
<field name="name">shipment_assign_partial_form</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.action.wizard" id="wizard_shipment_in_return_assign">
|
||||
<field name="name">Assign Supplier Return Shipment</field>
|
||||
<field name="wiz_name">stock.shipment.assign</field>
|
||||
<field name="model">stock.shipment.in.return</field>
|
||||
</record>
|
||||
<record model="ir.action.wizard" id="wizard_shipment_out_assign">
|
||||
<field name="name">Assign Customer Shipment</field>
|
||||
<field name="wiz_name">stock.shipment.assign</field>
|
||||
<field name="model">stock.shipment.out</field>
|
||||
</record>
|
||||
<record model="ir.action.wizard" id="wizard_shipment_internal_assign">
|
||||
<field name="name">Assign Internal Shipment</field>
|
||||
<field name="wiz_name">stock.shipment.assign</field>
|
||||
<field name="model">stock.shipment.internal</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</tryton>
|
||||
77
modules/stock/stock.xml
Normal file
77
modules/stock/stock.xml
Normal file
@@ -0,0 +1,77 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
this repository contains the full copyright notices and license terms. -->
|
||||
<tryton>
|
||||
<data>
|
||||
<record model="res.group" id="group_stock">
|
||||
<field name="name">Stock</field>
|
||||
</record>
|
||||
<record model="res.group" id="group_stock_admin">
|
||||
<field name="name">Stock Administration</field>
|
||||
<field name="parent" ref="group_stock"/>
|
||||
</record>
|
||||
<record model="res.group" id="group_stock_force_assignment">
|
||||
<field name="name">Stock Force Assignment</field>
|
||||
<field name="parent" ref="group_stock"/>
|
||||
</record>
|
||||
<record model="res.user-res.group"
|
||||
id="user_admin_group_stock_admin">
|
||||
<field name="user" ref="res.user_admin"/>
|
||||
<field name="group" ref="group_stock_admin"/>
|
||||
</record>
|
||||
<record model="res.user-res.group"
|
||||
id="user_admin_group_stock">
|
||||
<field name="user" ref="res.user_admin"/>
|
||||
<field name="group" ref="group_stock"/>
|
||||
</record>
|
||||
<record model="res.user-res.group"
|
||||
id="user_admin_group_stock_force_assignment">
|
||||
<field name="user" ref="res.user_admin"/>
|
||||
<field name="group" ref="group_stock_force_assignment"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.icon" id="stock_icon">
|
||||
<field name="name">tryton-stock</field>
|
||||
<field name="path">icons/tryton-stock.svg</field>
|
||||
</record>
|
||||
<record model="ir.ui.icon" id="stock_shipment_in">
|
||||
<field name="name">tryton-shipment-in</field>
|
||||
<field name="path">icons/tryton-shipment-in.svg</field>
|
||||
</record>
|
||||
<record model="ir.ui.icon" id="stock_shipment_out">
|
||||
<field name="name">tryton-shipment-out</field>
|
||||
<field name="path">icons/tryton-shipment-out.svg</field>
|
||||
</record>
|
||||
|
||||
<menuitem
|
||||
name="Inventory & Stock"
|
||||
sequence="60"
|
||||
id="menu_stock"
|
||||
icon="tryton-stock"/>
|
||||
<record model="ir.ui.menu-res.group"
|
||||
id="menu_stock_group_stock">
|
||||
<field name="menu" ref="menu_stock"/>
|
||||
<field name="group" ref="group_stock"/>
|
||||
</record>
|
||||
|
||||
<menuitem
|
||||
name="Configuration"
|
||||
parent="menu_stock"
|
||||
sequence="0"
|
||||
id="menu_configuration"
|
||||
icon="tryton-settings"/>
|
||||
<record model="ir.ui.menu-res.group"
|
||||
id="menu_configuration_group_stock_admin">
|
||||
<field name="menu" ref="menu_configuration"/>
|
||||
<field name="group" ref="group_stock_admin"/>
|
||||
</record>
|
||||
|
||||
<menuitem
|
||||
name="Reporting"
|
||||
parent="menu_stock"
|
||||
sequence="100"
|
||||
id="menu_reporting"
|
||||
active="1"/>
|
||||
|
||||
</data>
|
||||
</tryton>
|
||||
526
modules/stock/stock_reporting.py
Normal file
526
modules/stock/stock_reporting.py
Normal file
@@ -0,0 +1,526 @@
|
||||
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
|
||||
import datetime as dt
|
||||
|
||||
from dateutil.relativedelta import relativedelta
|
||||
from sql import Literal, Null, Window
|
||||
from sql.aggregate import Min, Sum
|
||||
from sql.conditionals import Case, Coalesce, Greatest, Least, NullIf
|
||||
from sql.functions import Function, NthValue, Round
|
||||
from sql.operators import Concat
|
||||
|
||||
from trytond import backend
|
||||
from trytond.model import ModelSQL, ModelView, fields
|
||||
from trytond.pool import Pool
|
||||
from trytond.pyson import Eval
|
||||
from trytond.transaction import Transaction
|
||||
|
||||
|
||||
class _SQLite_JulianDay(Function):
|
||||
__slots__ = ()
|
||||
_function = 'JULIANDAY'
|
||||
|
||||
|
||||
class _InventoryContextMixin(ModelView):
|
||||
|
||||
company = fields.Many2One('company.company', "Company", required=True)
|
||||
location = fields.Many2One(
|
||||
'stock.location', "Location", required=True,
|
||||
domain=[
|
||||
('type', 'in', ['warehouse', 'storage', 'view']),
|
||||
])
|
||||
|
||||
@classmethod
|
||||
def default_company(cls):
|
||||
return Transaction().context.get('company')
|
||||
|
||||
@classmethod
|
||||
def default_location(cls):
|
||||
pool = Pool()
|
||||
Location = pool.get('stock.location')
|
||||
return Transaction().context.get(
|
||||
'location', Location.get_default_warehouse())
|
||||
|
||||
|
||||
class _InventoryMixin:
|
||||
__slots__ = ()
|
||||
|
||||
company = fields.Many2One('company.company', "Company")
|
||||
product = fields.Reference("Product", [
|
||||
('product.product', "Variant"),
|
||||
('product.template', "Product"),
|
||||
])
|
||||
unit = fields.Function(
|
||||
fields.Many2One('product.uom', "Unit"),
|
||||
'on_change_with_unit')
|
||||
|
||||
input_quantity = fields.Float("Input Quantity")
|
||||
output_quantity = fields.Float("Output Quantity")
|
||||
quantity = fields.Float("Quantity")
|
||||
|
||||
@classmethod
|
||||
def table_query(cls):
|
||||
pool = Pool()
|
||||
Location = pool.get('stock.location')
|
||||
Move = pool.get('stock.move')
|
||||
Period = pool.get('stock.period')
|
||||
PeriodCache = pool.get('stock.period.cache')
|
||||
Product = pool.get('product.product')
|
||||
|
||||
transaction = Transaction()
|
||||
context = transaction.context
|
||||
move = Move.__table__()
|
||||
from_location = Location.__table__()
|
||||
to_location = Location.__table__()
|
||||
period_cache = PeriodCache.__table__()
|
||||
product_table = Product.__table__()
|
||||
|
||||
if location := context.get('location'):
|
||||
location = Location(location)
|
||||
left, right = location.left, location.right
|
||||
else:
|
||||
left = right = -1
|
||||
if date := context.get('date'):
|
||||
from_date = to_date = date
|
||||
else:
|
||||
from_date = context.get('from_date') or dt.date.min
|
||||
to_date = context.get('to_date') or dt.date.max
|
||||
company = context.get('company')
|
||||
|
||||
if periods := Period.search([
|
||||
('company', '=', company),
|
||||
('date', '<=', from_date),
|
||||
('state', '=', 'closed'),
|
||||
],
|
||||
order=[('date', 'DESC')],
|
||||
limit=1):
|
||||
period, = periods
|
||||
else:
|
||||
period = None
|
||||
|
||||
quantities = (
|
||||
move
|
||||
.join(from_location,
|
||||
condition=move.from_location == from_location.id)
|
||||
.join(to_location,
|
||||
condition=move.to_location == to_location.id)
|
||||
)
|
||||
|
||||
if context.get('product_type') == 'product.product':
|
||||
product = Concat('product.product,', move.product)
|
||||
else:
|
||||
product = Concat('product.template,', product_table.template)
|
||||
quantities = (
|
||||
quantities
|
||||
.join(product_table,
|
||||
condition=move.product == product_table.id)
|
||||
)
|
||||
|
||||
move_date = Coalesce(move.effective_date, move.planned_date)
|
||||
input_clause = (
|
||||
(to_location.left >= left) & (to_location.right <= right))
|
||||
output_clause = (
|
||||
(from_location.left >= left) & (from_location.right <= right))
|
||||
start_quantity = Sum(
|
||||
move.quantity * Case((output_clause, -1), else_=1),
|
||||
filter_=(move_date < from_date))
|
||||
input_quantity = Sum(
|
||||
move.quantity,
|
||||
filter_=input_clause & (move_date >= from_date))
|
||||
output_quantity = Sum(
|
||||
move.quantity,
|
||||
filter_=output_clause & (move_date >= from_date))
|
||||
|
||||
date_column = Greatest(move_date, from_date)
|
||||
if context.get('product_type') == 'product.product':
|
||||
partition = [move.product]
|
||||
else:
|
||||
partition = [product_table.template]
|
||||
|
||||
# Use NthValue instead of LastValue to get NULL for the last row
|
||||
next_date_column = NthValue(
|
||||
date_column, 2, window=Window(
|
||||
partition,
|
||||
order_by=[date_column.asc],
|
||||
frame='ROWS', start=0, end=1))
|
||||
|
||||
state_clause = cls._state_clause(move, to_date)
|
||||
|
||||
quantities = quantities.select(
|
||||
Min(move.id).as_('id'),
|
||||
product.as_('product'),
|
||||
date_column.as_('date'),
|
||||
next_date_column.as_('next_date'),
|
||||
start_quantity.as_('start_quantity'),
|
||||
input_quantity.as_('input_quantity'),
|
||||
output_quantity.as_('output_quantity'),
|
||||
*cls._quantities_columns(move, product_table),
|
||||
where=(((input_clause & ~output_clause)
|
||||
| (output_clause & ~input_clause))
|
||||
& (move_date <= to_date)
|
||||
& state_clause
|
||||
& (move.company == company)),
|
||||
group_by=[
|
||||
*partition,
|
||||
date_column,
|
||||
*cls._quantities_group_by(move, product_table),
|
||||
],
|
||||
)
|
||||
|
||||
quantity = Sum(
|
||||
Coalesce(quantities.start_quantity, 0)
|
||||
+ Coalesce(quantities.input_quantity, 0)
|
||||
- Coalesce(quantities.output_quantity, 0),
|
||||
window=Window(
|
||||
[quantities.product],
|
||||
order_by=[*cls._quantities_order_by(quantities)]))
|
||||
|
||||
if period:
|
||||
quantities.where &= move_date > period.date
|
||||
if context.get('product_type') != 'product.product':
|
||||
period_cache_product = Product.__table__()
|
||||
cache = (
|
||||
period_cache
|
||||
.join(period_cache_product,
|
||||
condition=period_cache.product
|
||||
== period_cache_product.id)
|
||||
.select(
|
||||
period_cache_product.template.as_('product'),
|
||||
Sum(period_cache.internal_quantity
|
||||
).as_('quantity'),
|
||||
group_by=[period_cache_product.template]))
|
||||
else:
|
||||
cache = (
|
||||
period_cache
|
||||
.select(
|
||||
period_cache.product.as_('product'),
|
||||
Sum(period_cache.internal_quantity).as_('quantity'),
|
||||
group_by=[period_cache.product]))
|
||||
location_cache = Location.__table__()
|
||||
cache.where = (
|
||||
(period_cache.period == period.id)
|
||||
& period_cache.location.in_(
|
||||
location_cache.select(
|
||||
location_cache.id,
|
||||
where=(location_cache.left >= left)
|
||||
& (location_cache.right <= right))))
|
||||
query = quantities.join(cache, 'LEFT',
|
||||
condition=(
|
||||
cache.product
|
||||
== cls.product.sql_id(quantities.product, cls)))
|
||||
quantity += Coalesce(cache.quantity, 0)
|
||||
else:
|
||||
query = quantities
|
||||
|
||||
return (query
|
||||
.select(
|
||||
quantities.id.as_('id'),
|
||||
Literal(company).as_('company'),
|
||||
quantities.product.as_('product'),
|
||||
quantities.input_quantity.as_('input_quantity'),
|
||||
quantities.output_quantity.as_('output_quantity'),
|
||||
quantity.as_('quantity'),
|
||||
*cls._columns(quantities),
|
||||
where=(
|
||||
(Coalesce(quantities.next_date, dt.date.max) >= from_date)
|
||||
| (quantities.date >= from_date))))
|
||||
|
||||
@classmethod
|
||||
def _quantities_columns(cls, move, product):
|
||||
yield from []
|
||||
|
||||
@classmethod
|
||||
def _quantities_group_by(cls, move, product):
|
||||
yield from []
|
||||
|
||||
@classmethod
|
||||
def _quantities_order_by(cls, quantities):
|
||||
yield quantities.date.asc
|
||||
|
||||
@classmethod
|
||||
def _columns(cls, quantities):
|
||||
yield from []
|
||||
|
||||
@classmethod
|
||||
def _where(cls, quantities):
|
||||
return Literal(True)
|
||||
|
||||
@classmethod
|
||||
def _state_clause(cls, move, date):
|
||||
pool = Pool()
|
||||
Date = pool.get('ir.date')
|
||||
today = Date.today()
|
||||
forcast = date > today
|
||||
|
||||
move_date = Coalesce(move.effective_date, move.planned_date)
|
||||
state_clause = (
|
||||
(move_date <= today) & (move.state == 'done'))
|
||||
state_clause |= (
|
||||
((move_date >= today) if forcast else (move_date > today))
|
||||
& (move.state.in_(['done', 'assigned', 'draft'])))
|
||||
return state_clause
|
||||
|
||||
@fields.depends('product')
|
||||
def on_change_with_unit(self, name=None):
|
||||
if self.product:
|
||||
return self.product.default_uom
|
||||
|
||||
|
||||
class InventoryContext(_InventoryContextMixin):
|
||||
__name__ = 'stock.reporting.inventory.context'
|
||||
|
||||
date = fields.Date("Date", required=True)
|
||||
product_type = fields.Selection([
|
||||
('product.product', "Variant"),
|
||||
('product.template', "Product"),
|
||||
], "Product Type", required=True)
|
||||
|
||||
@classmethod
|
||||
def default_date(cls):
|
||||
return Pool().get('ir.date').today()
|
||||
|
||||
@classmethod
|
||||
def default_product_type(cls):
|
||||
return Transaction().context.get('product_type') or 'product.template'
|
||||
|
||||
|
||||
class Inventory(_InventoryMixin, ModelSQL, ModelView):
|
||||
__name__ = 'stock.reporting.inventory'
|
||||
|
||||
|
||||
class _InventoryRangeContextMixin(_InventoryContextMixin):
|
||||
|
||||
from_date = fields.Date(
|
||||
"From Date", required=True,
|
||||
domain=[
|
||||
('from_date', '<=', Eval('to_date')),
|
||||
])
|
||||
to_date = fields.Date(
|
||||
"To Date", required=True,
|
||||
domain=[
|
||||
('to_date', '>=', Eval('from_date')),
|
||||
])
|
||||
|
||||
@classmethod
|
||||
def default_from_date(cls):
|
||||
pool = Pool()
|
||||
Date = pool.get('ir.date')
|
||||
context = Transaction().context
|
||||
if 'from_date' in context:
|
||||
return context['from_date']
|
||||
return Date.today() - relativedelta(day=1, months=6)
|
||||
|
||||
@classmethod
|
||||
def default_to_date(cls):
|
||||
pool = Pool()
|
||||
Date = pool.get('ir.date')
|
||||
context = Transaction().context
|
||||
if 'to_date' in context:
|
||||
return context['to_date']
|
||||
return Date.today() + relativedelta(day=1, months=6)
|
||||
|
||||
|
||||
class InventoryRangeContext(_InventoryRangeContextMixin):
|
||||
__name__ = 'stock.reporting.inventory.range.context'
|
||||
|
||||
|
||||
class InventoryMove(_InventoryMixin, ModelSQL, ModelView):
|
||||
__name__ = 'stock.reporting.inventory.move'
|
||||
|
||||
date = fields.Date("Date")
|
||||
move = fields.Many2One('stock.move', "Move")
|
||||
origin = fields.Reference("Origin", selection='get_origin')
|
||||
document = fields.Function(
|
||||
fields.Reference("Document", selection='get_documents'),
|
||||
'get_document')
|
||||
|
||||
@classmethod
|
||||
def __setup__(cls):
|
||||
super().__setup__()
|
||||
cls._order = [
|
||||
('date', 'DESC'),
|
||||
('move', 'DESC NULLS LAST'),
|
||||
('id', 'DESC'),
|
||||
]
|
||||
|
||||
@classmethod
|
||||
def _quantities_columns(cls, move, product):
|
||||
from_date = Transaction().context.get('from_date') or dt.date.min
|
||||
move_date = Coalesce(move.effective_date, move.planned_date)
|
||||
yield from super()._quantities_columns(move, product)
|
||||
yield Case(
|
||||
(move_date < from_date, Null),
|
||||
else_=move.id).as_('move')
|
||||
yield Case(
|
||||
(move_date < from_date, Null),
|
||||
else_=move.origin).as_('origin')
|
||||
|
||||
@classmethod
|
||||
def _quantities_order_by(cls, quantities):
|
||||
yield from super()._quantities_order_by(quantities)
|
||||
yield quantities.move.asc.nulls_first
|
||||
|
||||
@classmethod
|
||||
def _quantities_group_by(cls, move, product):
|
||||
from_date = Transaction().context.get('from_date') or dt.date.min
|
||||
move_date = Coalesce(move.effective_date, move.planned_date)
|
||||
yield from super()._quantities_group_by(move, product)
|
||||
yield Case(
|
||||
(move_date < from_date, Null),
|
||||
else_=move.id)
|
||||
yield Case(
|
||||
(move_date < from_date, Null),
|
||||
else_=move.origin)
|
||||
|
||||
@classmethod
|
||||
def _columns(cls, quantities):
|
||||
yield from super()._columns(quantities)
|
||||
yield quantities.date.as_('date')
|
||||
yield quantities.move.as_('move')
|
||||
yield quantities.origin.as_('origin')
|
||||
|
||||
@classmethod
|
||||
def get_origin(cls):
|
||||
pool = Pool()
|
||||
Move = pool.get('stock.move')
|
||||
return Move.get_origin()
|
||||
|
||||
@classmethod
|
||||
def _get_document_models(cls):
|
||||
pool = Pool()
|
||||
Move = pool.get('stock.move')
|
||||
return [m for m, _ in Move.get_shipment() if m]
|
||||
|
||||
@classmethod
|
||||
def get_documents(cls):
|
||||
pool = Pool()
|
||||
Model = pool.get('ir.model')
|
||||
get_name = Model.get_name
|
||||
models = cls._get_document_models()
|
||||
return [(None, '')] + [(m, get_name(m)) for m in models]
|
||||
|
||||
def get_document(self, name):
|
||||
if self.move and self.move.shipment:
|
||||
return str(self.move.shipment)
|
||||
|
||||
def get_rec_name(self, name):
|
||||
name = super().get_rec_name(name)
|
||||
if self.move:
|
||||
name = self.move.rec_name
|
||||
return name
|
||||
|
||||
|
||||
class InventoryDaily(_InventoryMixin, ModelSQL, ModelView):
|
||||
__name__ = 'stock.reporting.inventory.daily'
|
||||
|
||||
from_date = fields.Date("From Date")
|
||||
to_date = fields.Date("To Date")
|
||||
|
||||
@classmethod
|
||||
def __setup__(cls):
|
||||
super().__setup__()
|
||||
cls._order = [
|
||||
('from_date', 'DESC'),
|
||||
('id', 'DESC'),
|
||||
]
|
||||
|
||||
@classmethod
|
||||
def _quantities_order_by(cls, quantities):
|
||||
yield from []
|
||||
yield quantities.date.asc
|
||||
|
||||
@classmethod
|
||||
def _columns(cls, quantities):
|
||||
transaction = Transaction()
|
||||
context = transaction.context
|
||||
to_date = context.get('to_date') or dt.date.max
|
||||
|
||||
yield from super()._columns(quantities)
|
||||
|
||||
yield quantities.date.as_('from_date')
|
||||
yield Least(quantities.next_date, to_date).as_('to_date')
|
||||
|
||||
|
||||
class InventoryTurnoverContext(_InventoryRangeContextMixin):
|
||||
__name__ = 'stock.reporting.inventory.turnover.context'
|
||||
|
||||
product_type = fields.Selection([
|
||||
('product.product', "Variant"),
|
||||
('product.template', "Product"),
|
||||
], "Product Type", required=True)
|
||||
|
||||
@classmethod
|
||||
def default_product_type(cls):
|
||||
return Transaction().context.get('product_type') or 'product.template'
|
||||
|
||||
|
||||
class InventoryTurnover(ModelSQL, ModelView):
|
||||
__name__ = 'stock.reporting.inventory.turnover'
|
||||
|
||||
company = fields.Many2One('company.company', "Company")
|
||||
product = fields.Reference("Product", [
|
||||
('product.product', "Variant"),
|
||||
('product.template', "Product"),
|
||||
])
|
||||
unit = fields.Function(
|
||||
fields.Many2One('product.uom', "Unit"),
|
||||
'on_change_with_unit')
|
||||
|
||||
output_quantity = fields.Float("Output Quantity", digits=(None, 3))
|
||||
average_quantity = fields.Float("Average Quantity", digits=(None, 3))
|
||||
turnover = fields.Float("Turnover", digits=(None, 3))
|
||||
|
||||
@classmethod
|
||||
def table_query(cls):
|
||||
pool = Pool()
|
||||
Inventory = pool.get('stock.reporting.inventory.daily')
|
||||
|
||||
transaction = Transaction()
|
||||
context = transaction.context
|
||||
inventory = Inventory.__table__()
|
||||
|
||||
from_date = context.get('from_date') or dt.date.min
|
||||
to_date = context.get('to_date') or dt.date.max
|
||||
company = context.get('company')
|
||||
|
||||
days = (to_date - from_date).days + 1
|
||||
|
||||
output_quantity = Sum(inventory.output_quantity) / days
|
||||
inventory_from_date = inventory.from_date
|
||||
inventory_to_date = inventory.to_date
|
||||
if backend.name == 'sqlite':
|
||||
inventory_from_date = _SQLite_JulianDay(inventory_from_date)
|
||||
inventory_to_date = _SQLite_JulianDay(inventory_to_date)
|
||||
average_quantity = (
|
||||
Sum(Case(
|
||||
(inventory.quantity >= 0, inventory.quantity),
|
||||
else_=0)
|
||||
* (inventory_to_date - inventory_from_date
|
||||
+ Case((inventory.to_date == to_date, 1), else_=0)))
|
||||
/ days)
|
||||
|
||||
def round_sql(expression, digits=2):
|
||||
factor = 10 ** digits
|
||||
return Round(expression * factor) / factor
|
||||
|
||||
return (inventory
|
||||
.select(
|
||||
cls.product.sql_id(inventory.product, cls).as_('id'),
|
||||
Literal(company).as_('company'),
|
||||
inventory.product.as_('product'),
|
||||
round_sql(
|
||||
output_quantity,
|
||||
cls.output_quantity.digits[1]).as_('output_quantity'),
|
||||
round_sql(
|
||||
average_quantity,
|
||||
cls.average_quantity.digits[1]).as_('average_quantity'),
|
||||
round_sql(
|
||||
output_quantity / NullIf(average_quantity, 0),
|
||||
cls.turnover.digits[1]).as_('turnover'),
|
||||
group_by=[inventory.product]))
|
||||
|
||||
@fields.depends('product')
|
||||
def on_change_with_unit(self, name=None):
|
||||
if self.product:
|
||||
return self.product.default_uom
|
||||
315
modules/stock/stock_reporting.xml
Normal file
315
modules/stock/stock_reporting.xml
Normal file
@@ -0,0 +1,315 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
this repository contains the full copyright notices and license terms. -->
|
||||
<tryton>
|
||||
<data>
|
||||
<record model="ir.ui.view" id="reporting_inventory_context_view_form">
|
||||
<field name="model">stock.reporting.inventory.context</field>
|
||||
<field name="type">form</field>
|
||||
<field name="name">reporting_inventory_context_form</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="reporting_inventory_view_list">
|
||||
<field name="model">stock.reporting.inventory</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="name">reporting_inventory_list</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="reporting_inventory_view_form">
|
||||
<field name="model">stock.reporting.inventory</field>
|
||||
<field name="type">form</field>
|
||||
<field name="name">reporting_inventory_form</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.action.act_window" id="act_reporting_inventory">
|
||||
<field name="name">Inventory</field>
|
||||
<field name="res_model">stock.reporting.inventory</field>
|
||||
<field name="context_model">stock.reporting.inventory.context</field>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_reporting_inventory_view1">
|
||||
<field name="sequence" eval="10"/>
|
||||
<field name="view" ref="reporting_inventory_view_list"/>
|
||||
<field name="act_window" ref="act_reporting_inventory"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_reporting_inventory_view2">
|
||||
<field name="sequence" eval="20"/>
|
||||
<field name="view" ref="reporting_inventory_view_form"/>
|
||||
<field name="act_window" ref="act_reporting_inventory"/>
|
||||
</record>
|
||||
|
||||
<menuitem
|
||||
parent="menu_reporting"
|
||||
action="act_reporting_inventory"
|
||||
sequence="20"
|
||||
id="menu_reporting_inventory"/>
|
||||
|
||||
<record model="ir.rule.group" id="rule_group_reporting_inventory_companies">
|
||||
<field name="name">User in companies</field>
|
||||
<field name="model">stock.reporting.inventory</field>
|
||||
<field name="global_p" eval="True"/>
|
||||
</record>
|
||||
<record model="ir.rule" id="rule_reporting_inventory_companies">
|
||||
<field
|
||||
name="domain"
|
||||
eval="[('company', 'in', Eval('companies', []))]"
|
||||
pyson="1"/>
|
||||
<field name="rule_group" ref="rule_group_reporting_inventory_companies"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.access" id="access_reporting_inventory">
|
||||
<field name="model">stock.reporting.inventory</field>
|
||||
<field name="perm_read" eval="False"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
<field name="perm_create" eval="False"/>
|
||||
<field name="perm_delete" eval="False"/>
|
||||
</record>
|
||||
<record model="ir.model.access" id="access_reporting_inventory_group_stock">
|
||||
<field name="model">stock.reporting.inventory</field>
|
||||
<field name="group" ref="group_stock"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
<field name="perm_create" eval="False"/>
|
||||
<field name="perm_delete" eval="False"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="reporting_inventory_range_context_view_form">
|
||||
<field name="model">stock.reporting.inventory.range.context</field>
|
||||
<field name="type">form</field>
|
||||
<field name="name">reporting_inventory_range_context_form</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="reporting_inventory_move_view_list">
|
||||
<field name="model">stock.reporting.inventory.move</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="name">reporting_inventory_move_list</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="reporting_inventory_move_view_form">
|
||||
<field name="model">stock.reporting.inventory.move</field>
|
||||
<field name="type">form</field>
|
||||
<field name="name">reporting_inventory_move_form</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.action.act_window" id="act_reporting_inventory_move">
|
||||
<field name="name">Stock Inventory Moves</field>
|
||||
<field name="res_model">stock.reporting.inventory.move</field>
|
||||
<field name="context_model">stock.reporting.inventory.range.context</field>
|
||||
<field
|
||||
name="domain"
|
||||
eval="[('product', '=', (Eval('active_model', 'product.template'), Eval('active_id', -1)))]"
|
||||
pyson="1"/>
|
||||
<field
|
||||
name="context"
|
||||
eval="{'product_type': Eval('active_model', 'product.template'), 'date': None}"
|
||||
pyson="1"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_reporting_inventory_move_view1">
|
||||
<field name="sequence" eval="10"/>
|
||||
<field name="view" ref="reporting_inventory_move_view_list"/>
|
||||
<field name="act_window" ref="act_reporting_inventory_move"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_reporting_inventory_move_view2">
|
||||
<field name="sequence" eval="20"/>
|
||||
<field name="view" ref="reporting_inventory_move_view_form"/>
|
||||
<field name="act_window" ref="act_reporting_inventory_move"/>
|
||||
</record>
|
||||
<record model="ir.action.keyword" id="act_reporting_inventory_move_keyword_product">
|
||||
<field name="keyword">form_relate</field>
|
||||
<field name="model">product.product,-1</field>
|
||||
<field name="action" ref="act_reporting_inventory_move"/>
|
||||
</record>
|
||||
<record model="ir.action.keyword" id="act_reporting_inventory_move_keyword_template">
|
||||
<field name="keyword">form_relate</field>
|
||||
<field name="model">product.template,-1</field>
|
||||
<field name="action" ref="act_reporting_inventory_move"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.rule.group" id="rule_group_reporting_inventory_move_companies">
|
||||
<field name="name">User in companies</field>
|
||||
<field name="model">stock.reporting.inventory.move</field>
|
||||
<field name="global_p" eval="True"/>
|
||||
</record>
|
||||
<record model="ir.rule" id="rule_reporting_inventory_move_companies">
|
||||
<field
|
||||
name="domain"
|
||||
eval="[('company', 'in', Eval('companies', []))]"
|
||||
pyson="1"/>
|
||||
<field name="rule_group" ref="rule_group_reporting_inventory_move_companies"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.access" id="access_reporting_inventory_move">
|
||||
<field name="model">stock.reporting.inventory.move</field>
|
||||
<field name="perm_read" eval="False"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
<field name="perm_create" eval="False"/>
|
||||
<field name="perm_delete" eval="False"/>
|
||||
</record>
|
||||
<record model="ir.model.access" id="access_reporting_inventory_move_group_stock">
|
||||
<field name="model">stock.reporting.inventory.move</field>
|
||||
<field name="group" ref="group_stock"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
<field name="perm_create" eval="False"/>
|
||||
<field name="perm_delete" eval="False"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="reporting_inventory_daily_view_list">
|
||||
<field name="model">stock.reporting.inventory.daily</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="name">reporting_inventory_daily_list</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="reporting_inventory_daily_view_form">
|
||||
<field name="model">stock.reporting.inventory.daily</field>
|
||||
<field name="type">form</field>
|
||||
<field name="name">reporting_inventory_daily_form</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="reporting_inventory_daily_view_graph">
|
||||
<field name="model">stock.reporting.inventory.daily</field>
|
||||
<field name="type">graph</field>
|
||||
<field name="name">reporting_inventory_daily_graph</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.action.act_window" id="act_reporting_inventory_daily">
|
||||
<field name="name">Stock Inventory Daily</field>
|
||||
<field name="res_model">stock.reporting.inventory.daily</field>
|
||||
<field name="context_model">stock.reporting.inventory.range.context</field>
|
||||
<field
|
||||
name="domain"
|
||||
eval="[('product', '=', (Eval('active_model', 'product.template'), Eval('active_id', -1)))]"
|
||||
pyson="1"/>
|
||||
<field
|
||||
name="context"
|
||||
eval="{'product_type': Eval('active_model', 'product.template'), 'date': None}"
|
||||
pyson="1"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_reporting_inventory_daily_view1">
|
||||
<field name="sequence" eval="10"/>
|
||||
<field name="view" ref="reporting_inventory_daily_view_list"/>
|
||||
<field name="act_window" ref="act_reporting_inventory_daily"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_reporting_inventory_daily_view2">
|
||||
<field name="sequence" eval="20"/>
|
||||
<field name="view" ref="reporting_inventory_daily_view_graph"/>
|
||||
<field name="act_window" ref="act_reporting_inventory_daily"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_reporting_inventory_daily_view3">
|
||||
<field name="sequence" eval="30"/>
|
||||
<field name="view" ref="reporting_inventory_daily_view_form"/>
|
||||
<field name="act_window" ref="act_reporting_inventory_daily"/>
|
||||
</record>
|
||||
<record model="ir.action.keyword" id="act_reporting_inventory_daily_keyword_product">
|
||||
<field name="keyword">form_relate</field>
|
||||
<field name="model">product.product,-1</field>
|
||||
<field name="action" ref="act_reporting_inventory_daily"/>
|
||||
</record>
|
||||
<record model="ir.action.keyword" id="act_reporting_inventory_daily_keyword_template">
|
||||
<field name="keyword">form_relate</field>
|
||||
<field name="model">product.template,-1</field>
|
||||
<field name="action" ref="act_reporting_inventory_daily"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.rule.group" id="rule_group_reporting_inventory_daily_companies">
|
||||
<field name="name">User in companies</field>
|
||||
<field name="model">stock.reporting.inventory.daily</field>
|
||||
<field name="global_p" eval="True"/>
|
||||
</record>
|
||||
<record model="ir.rule" id="rule_reporting_inventory_daily_companies">
|
||||
<field
|
||||
name="domain"
|
||||
eval="[('company', 'in', Eval('companies', []))]"
|
||||
pyson="1"/>
|
||||
<field name="rule_group" ref="rule_group_reporting_inventory_daily_companies"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.access" id="access_reporting_inventory_daily">
|
||||
<field name="model">stock.reporting.inventory.daily</field>
|
||||
<field name="perm_read" eval="False"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
<field name="perm_create" eval="False"/>
|
||||
<field name="perm_delete" eval="False"/>
|
||||
</record>
|
||||
<record model="ir.model.access" id="access_reporting_inventory_daily_group_stock">
|
||||
<field name="model">stock.reporting.inventory.daily</field>
|
||||
<field name="group" ref="group_stock"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
<field name="perm_create" eval="False"/>
|
||||
<field name="perm_delete" eval="False"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="reporting_inventory_turnover_context_view_form">
|
||||
<field name="model">stock.reporting.inventory.turnover.context</field>
|
||||
<field name="type">form</field>
|
||||
<field name="name">reporting_inventory_turnover_context_form</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="reporting_inventory_turnover_view_list">
|
||||
<field name="model">stock.reporting.inventory.turnover</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="name">reporting_inventory_turnover_list</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="reporting_inventory_turnover_view_form">
|
||||
<field name="model">stock.reporting.inventory.turnover</field>
|
||||
<field name="type">form</field>
|
||||
<field name="name">reporting_inventory_turnover_form</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.action.act_window" id="act_reporting_inventory_turnover">
|
||||
<field name="name">Inventory Turnover</field>
|
||||
<field name="res_model">stock.reporting.inventory.turnover</field>
|
||||
<field name="context_model">stock.reporting.inventory.turnover.context</field>
|
||||
<field
|
||||
name="context"
|
||||
eval="{'from_date': Date(delta_years=-1), 'to_date': Date()}"
|
||||
pyson="1"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_reporting_inventory_turnover_view1">
|
||||
<field name="sequence" eval="10"/>
|
||||
<field name="view" ref="reporting_inventory_turnover_view_list"/>
|
||||
<field name="act_window" ref="act_reporting_inventory_turnover"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_reporting_inventory_turnover_view2">
|
||||
<field name="sequence" eval="20"/>
|
||||
<field name="view" ref="reporting_inventory_turnover_view_form"/>
|
||||
<field name="act_window" ref="act_reporting_inventory_turnover"/>
|
||||
</record>
|
||||
|
||||
<menuitem
|
||||
parent="menu_reporting"
|
||||
action="act_reporting_inventory_turnover"
|
||||
sequence="30"
|
||||
id="menu_reporting_inventory_turnover"/>
|
||||
|
||||
<record model="ir.rule.group" id="rule_group_reporting_inventory_turnover_companies">
|
||||
<field name="name">User in companies</field>
|
||||
<field name="model">stock.reporting.inventory.turnover</field>
|
||||
<field name="global_p" eval="True"/>
|
||||
</record>
|
||||
<record model="ir.rule" id="rule_reporting_inventory_turnover_companies">
|
||||
<field
|
||||
name="domain"
|
||||
eval="[('company', 'in', Eval('companies', []))]"
|
||||
pyson="1"/>
|
||||
<field name="rule_group" ref="rule_group_reporting_inventory_turnover_companies"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.access" id="access_reporting_inventory_turnover">
|
||||
<field name="model">stock.reporting.inventory.turnover</field>
|
||||
<field name="perm_read" eval="False"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
<field name="perm_create" eval="False"/>
|
||||
<field name="perm_delete" eval="False"/>
|
||||
</record>
|
||||
<record model="ir.model.access" id="access_reporting_inventory_turnover_group_stock">
|
||||
<field name="model">stock.reporting.inventory.turnover</field>
|
||||
<field name="group" ref="group_stock"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
<field name="perm_create" eval="False"/>
|
||||
<field name="perm_delete" eval="False"/>
|
||||
</record>
|
||||
</data>
|
||||
</tryton>
|
||||
633
modules/stock/stock_reporting_margin.py
Normal file
633
modules/stock/stock_reporting_margin.py
Normal file
@@ -0,0 +1,633 @@
|
||||
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
|
||||
from collections import defaultdict
|
||||
from decimal import Decimal
|
||||
|
||||
from dateutil.relativedelta import relativedelta
|
||||
from sql import Literal, Null, With
|
||||
from sql.aggregate import Max, Min, Sum
|
||||
from sql.conditionals import Case, Coalesce
|
||||
from sql.functions import Ceil, DateTrunc, Log, Power, Round
|
||||
|
||||
from trytond.i18n import lazy_gettext
|
||||
from trytond.model import ModelSQL, ModelView, fields, sum_tree
|
||||
from trytond.modules.currency.fields import Monetary
|
||||
from trytond.pool import Pool
|
||||
from trytond.pyson import Eval, If
|
||||
from trytond.tools import grouped_slice, pairwise_longest, reduce_ids
|
||||
from trytond.tools.chart import sparkline
|
||||
from trytond.transaction import Transaction
|
||||
|
||||
|
||||
class Abstract(ModelSQL, ModelView):
|
||||
|
||||
company = fields.Many2One(
|
||||
'company.company', lazy_gettext('stock.msg_stock_reporting_company'))
|
||||
cost = Monetary(
|
||||
lazy_gettext('stock.msg_stock_reporting_cost'),
|
||||
currency='currency', digits='currency')
|
||||
revenue = Monetary(
|
||||
lazy_gettext('stock.msg_stock_reporting_revenue'),
|
||||
currency='currency', digits='currency')
|
||||
profit = Monetary(
|
||||
lazy_gettext('stock.msg_stock_reporting_profit'),
|
||||
currency='currency', digits='currency')
|
||||
margin = fields.Numeric(
|
||||
lazy_gettext('stock.msg_stock_reporting_margin'),
|
||||
digits=(None, 4),
|
||||
states={
|
||||
'invisible': ~Eval('margin'),
|
||||
})
|
||||
margin_trend = fields.Function(fields.Char(
|
||||
lazy_gettext('stock.msg_stock_reporting_margin_trend')),
|
||||
'get_trend')
|
||||
time_series = None
|
||||
|
||||
currency = fields.Many2One(
|
||||
'currency.currency',
|
||||
lazy_gettext('stock.msg_stock_reporting_currency'))
|
||||
|
||||
@classmethod
|
||||
def table_query(cls):
|
||||
from_item, tables, withs = cls._joins()
|
||||
return from_item.select(*cls._columns(tables, withs),
|
||||
where=cls._where(tables, withs),
|
||||
group_by=cls._group_by(tables, withs),
|
||||
with_=withs.values())
|
||||
|
||||
@classmethod
|
||||
def _joins(cls):
|
||||
pool = Pool()
|
||||
Company = pool.get('company.company')
|
||||
Currency = pool.get('currency.currency')
|
||||
Move = pool.get('stock.move')
|
||||
Location = pool.get('stock.location')
|
||||
|
||||
tables = {}
|
||||
tables['move'] = move = Move.__table__()
|
||||
tables['move.company'] = company = Company.__table__()
|
||||
tables['move.company.currency'] = currency = Currency.__table__()
|
||||
tables['move.from_location'] = from_location = Location.__table__()
|
||||
tables['move.to_location'] = to_location = Location.__table__()
|
||||
withs = {}
|
||||
withs['currency_rate'] = currency_rate = With(
|
||||
query=Currency.currency_rate_sql())
|
||||
withs['currency_rate_company'] = currency_rate_company = With(
|
||||
query=Currency.currency_rate_sql())
|
||||
|
||||
from_item = (move
|
||||
.join(currency_rate, type_='LEFT',
|
||||
condition=(move.currency == currency_rate.currency)
|
||||
& (currency_rate.start_date <= move.effective_date)
|
||||
& ((currency_rate.end_date == Null)
|
||||
| (currency_rate.end_date > move.effective_date))
|
||||
)
|
||||
.join(company,
|
||||
condition=move.company == company.id)
|
||||
.join(currency,
|
||||
condition=company.currency == currency.id)
|
||||
.join(currency_rate_company,
|
||||
condition=(company.currency == currency_rate_company.currency)
|
||||
& (currency_rate_company.start_date <= move.effective_date)
|
||||
& ((currency_rate_company.end_date == Null)
|
||||
| (currency_rate_company.end_date > move.effective_date))
|
||||
)
|
||||
.join(from_location,
|
||||
condition=(move.from_location == from_location.id))
|
||||
.join(to_location,
|
||||
condition=(move.to_location == to_location.id)))
|
||||
return from_item, tables, withs
|
||||
|
||||
@classmethod
|
||||
def _columns(cls, tables, withs):
|
||||
move = tables['move']
|
||||
from_location = tables['move.from_location']
|
||||
to_location = tables['move.to_location']
|
||||
currency = tables['move.company.currency']
|
||||
|
||||
sign = Case(
|
||||
(from_location.type.in_(cls._to_location_types())
|
||||
& to_location.type.in_(cls._from_location_types()),
|
||||
-1),
|
||||
else_=1)
|
||||
cost = cls._column_cost(tables, withs, sign)
|
||||
revenue = cls._column_revenue(tables, withs, sign)
|
||||
profit = revenue - cost
|
||||
margin = Case(
|
||||
(revenue != 0, profit / revenue),
|
||||
else_=Null)
|
||||
return [
|
||||
cls._column_id(tables, withs).as_('id'),
|
||||
move.company.as_('company'),
|
||||
cls.cost.sql_cast(
|
||||
Round(cost, currency.digits)).as_('cost'),
|
||||
cls.revenue.sql_cast(
|
||||
Round(revenue, currency.digits)).as_('revenue'),
|
||||
cls.profit.sql_cast(
|
||||
Round(profit, currency.digits)).as_('profit'),
|
||||
cls.margin.sql_cast(
|
||||
Round(margin, cls.margin.digits[1])).as_('margin'),
|
||||
currency.id.as_('currency'),
|
||||
]
|
||||
|
||||
@classmethod
|
||||
def _column_id(cls, tables, withs):
|
||||
move = tables['move']
|
||||
return Min(move.id)
|
||||
|
||||
@classmethod
|
||||
def _column_cost(cls, tables, withs, sign):
|
||||
move = tables['move']
|
||||
return Sum(
|
||||
sign * cls.cost.sql_cast(move.internal_quantity)
|
||||
* Coalesce(move.cost_price, 0))
|
||||
|
||||
@classmethod
|
||||
def _column_revenue(cls, tables, withs, sign):
|
||||
move = tables['move']
|
||||
currency = withs['currency_rate']
|
||||
currency_company = withs['currency_rate_company']
|
||||
return Sum(
|
||||
sign * cls.revenue.sql_cast(move.quantity)
|
||||
* Coalesce(move.unit_price, 0)
|
||||
* Coalesce(currency_company.rate / currency.rate, 0))
|
||||
|
||||
@classmethod
|
||||
def _group_by(cls, tables, withs):
|
||||
move = tables['move']
|
||||
currency = tables['move.company.currency']
|
||||
return [move.company, currency.id, currency.digits]
|
||||
|
||||
@classmethod
|
||||
def _where(cls, tables, withs):
|
||||
context = Transaction().context
|
||||
move = tables['move']
|
||||
from_location = tables['move.from_location']
|
||||
to_location = tables['move.to_location']
|
||||
|
||||
where = move.company == context.get('company')
|
||||
where &= ((
|
||||
from_location.type.in_(cls._from_location_types())
|
||||
& to_location.type.in_(cls._to_location_types()))
|
||||
| (
|
||||
from_location.type.in_(cls._to_location_types())
|
||||
& to_location.type.in_(cls._from_location_types())))
|
||||
where &= move.state == 'done'
|
||||
from_date = context.get('from_date')
|
||||
if from_date:
|
||||
where &= move.effective_date >= from_date
|
||||
to_date = context.get('to_date')
|
||||
if to_date:
|
||||
where &= move.effective_date <= to_date
|
||||
return where
|
||||
|
||||
@classmethod
|
||||
def _from_location_types(cls):
|
||||
return ['storage', 'drop']
|
||||
|
||||
@classmethod
|
||||
def _to_location_types(cls):
|
||||
types = ['customer']
|
||||
if Transaction().context.get('include_lost'):
|
||||
types += ['lost_found']
|
||||
return types
|
||||
|
||||
@property
|
||||
def time_series_all(self):
|
||||
delta = self._period_delta()
|
||||
for ts, next_ts in pairwise_longest(self.time_series or []):
|
||||
yield ts
|
||||
if delta and next_ts:
|
||||
date = ts.date + delta
|
||||
while date < next_ts.date:
|
||||
yield None
|
||||
date += delta
|
||||
|
||||
@classmethod
|
||||
def _period_delta(cls):
|
||||
context = Transaction().context
|
||||
return {
|
||||
'year': relativedelta(years=1),
|
||||
'month': relativedelta(months=1),
|
||||
'day': relativedelta(days=1),
|
||||
}.get(context.get('period'))
|
||||
|
||||
def get_trend(self, name):
|
||||
name = name[:-len('_trend')]
|
||||
return sparkline(
|
||||
[getattr(ts, name) or 0 if ts else 0
|
||||
for ts in self.time_series_all])
|
||||
|
||||
@classmethod
|
||||
def view_attributes(cls):
|
||||
return super().view_attributes() + [
|
||||
('/tree/field[@name="profit"]', 'visual',
|
||||
If(Eval('profit', 0) < 0, 'danger', '')),
|
||||
('/tree/field[@name="margin"]', 'visual',
|
||||
If(Eval('margin', 0) < 0, 'danger', '')),
|
||||
]
|
||||
|
||||
|
||||
class AbstractTimeseries(Abstract):
|
||||
|
||||
date = fields.Date("Date")
|
||||
|
||||
@classmethod
|
||||
def __setup__(cls):
|
||||
super().__setup__()
|
||||
cls._order.insert(0, ('date', 'ASC'))
|
||||
|
||||
@classmethod
|
||||
def _columns(cls, tables, withs):
|
||||
return super()._columns(tables, withs) + [
|
||||
cls._column_date(tables, withs).as_('date')]
|
||||
|
||||
@classmethod
|
||||
def _column_date(cls, tables, withs):
|
||||
context = Transaction().context
|
||||
move = tables['move']
|
||||
date = DateTrunc(context.get('period'), move.effective_date)
|
||||
date = cls.date.sql_cast(date)
|
||||
return date
|
||||
|
||||
@classmethod
|
||||
def _group_by(cls, tables, withs):
|
||||
return super()._group_by(tables, withs) + [
|
||||
cls._column_date(tables, withs)]
|
||||
|
||||
|
||||
class Context(ModelView):
|
||||
__name__ = 'stock.reporting.margin.context'
|
||||
|
||||
company = fields.Many2One('company.company', "Company", required=True)
|
||||
from_date = fields.Date("From Date",
|
||||
domain=[
|
||||
If(Eval('to_date') & Eval('from_date'),
|
||||
('from_date', '<=', Eval('to_date')),
|
||||
()),
|
||||
])
|
||||
to_date = fields.Date("To Date",
|
||||
domain=[
|
||||
If(Eval('from_date') & Eval('to_date'),
|
||||
('to_date', '>=', Eval('from_date')),
|
||||
()),
|
||||
])
|
||||
period = fields.Selection([
|
||||
('year', "Year"),
|
||||
('month', "Month"),
|
||||
('day', "Day"),
|
||||
], "Period", required=True)
|
||||
include_lost = fields.Boolean(
|
||||
"Include Lost",
|
||||
help="If checked, the cost of product moved "
|
||||
"to a lost and found location is included.")
|
||||
|
||||
@classmethod
|
||||
def default_company(cls):
|
||||
return Transaction().context.get('company')
|
||||
|
||||
@classmethod
|
||||
def default_from_date(cls):
|
||||
pool = Pool()
|
||||
Date = pool.get('ir.date')
|
||||
context = Transaction().context
|
||||
if 'from_date' in context:
|
||||
return context['from_date']
|
||||
return Date.today() - relativedelta(years=1)
|
||||
|
||||
@classmethod
|
||||
def default_to_date(cls):
|
||||
pool = Pool()
|
||||
Date = pool.get('ir.date')
|
||||
context = Transaction().context
|
||||
if 'to_date' in context:
|
||||
return context['to_date']
|
||||
return Date.today()
|
||||
|
||||
@classmethod
|
||||
def default_period(cls):
|
||||
return Transaction().context.get('period', 'month')
|
||||
|
||||
@classmethod
|
||||
def default_include_lost(cls):
|
||||
return Transaction().context.get('include_lost', False)
|
||||
|
||||
|
||||
class Main(Abstract, ModelView):
|
||||
__name__ = 'stock.reporting.margin.main'
|
||||
|
||||
time_series = fields.Function(fields.Many2Many(
|
||||
'stock.reporting.margin.main.time_series', None, None,
|
||||
"Time Series"),
|
||||
'get_time_series')
|
||||
|
||||
def get_rec_name(self, name):
|
||||
return ''
|
||||
|
||||
def get_time_series(self, name):
|
||||
pool = Pool()
|
||||
Timeseries = pool.get('stock.reporting.margin.main.time_series')
|
||||
return [t.id for t in Timeseries.search([])]
|
||||
|
||||
|
||||
class MainTimeseries(AbstractTimeseries, ModelView):
|
||||
__name__ = 'stock.reporting.margin.main.time_series'
|
||||
|
||||
|
||||
class ProductMixin:
|
||||
__slots__ = ()
|
||||
|
||||
product = fields.Many2One(
|
||||
'product.product', "Product",
|
||||
context={
|
||||
'company': Eval('company', -1),
|
||||
},
|
||||
depends={'company'})
|
||||
internal_quantity = fields.Float("Internal Quantity")
|
||||
quantity = fields.Function(fields.Float(
|
||||
"Quantity", digits='unit'), 'get_quantity')
|
||||
unit = fields.Many2One('product.uom', "Unit")
|
||||
|
||||
@classmethod
|
||||
def _joins(cls):
|
||||
pool = Pool()
|
||||
Product = pool.get('product.product')
|
||||
Template = pool.get('product.template')
|
||||
from_item, tables, withs = super()._joins()
|
||||
if 'move.product' not in tables:
|
||||
product = Product.__table__()
|
||||
tables['move.product'] = product
|
||||
move = tables['move']
|
||||
from_item = (from_item
|
||||
.join(product, condition=move.product == product.id))
|
||||
if 'move.product.template' not in tables:
|
||||
template = Template.__table__()
|
||||
tables['move.product.template'] = template
|
||||
product = tables['move.product']
|
||||
from_item = (from_item
|
||||
.join(template, condition=product.template == template.id))
|
||||
return from_item, tables, withs
|
||||
|
||||
@classmethod
|
||||
def _columns(cls, tables, withs):
|
||||
move = tables['move']
|
||||
from_location = tables['move.from_location']
|
||||
to_location = tables['move.to_location']
|
||||
template = tables['move.product.template']
|
||||
sign = Case(
|
||||
(from_location.type.in_(cls._to_location_types())
|
||||
& to_location.type.in_(cls._from_location_types()),
|
||||
-1),
|
||||
else_=1)
|
||||
return super()._columns(tables, withs) + [
|
||||
move.product.as_('product'),
|
||||
Sum(sign * move.internal_quantity).as_('internal_quantity'),
|
||||
template.default_uom.as_('unit'),
|
||||
]
|
||||
|
||||
@classmethod
|
||||
def _group_by(cls, tables, withs):
|
||||
move = tables['move']
|
||||
template = tables['move.product.template']
|
||||
return super()._group_by(tables, withs) + [
|
||||
move.product, template.default_uom]
|
||||
|
||||
def get_rec_name(self, name):
|
||||
return self.product.rec_name
|
||||
|
||||
@classmethod
|
||||
def search_rec_name(cls, name, clause):
|
||||
return [('product.rec_name', *clause[1:])]
|
||||
|
||||
def get_quantity(self, name):
|
||||
return self.unit.round(self.internal_quantity)
|
||||
|
||||
|
||||
class Product(ProductMixin, Abstract, ModelView):
|
||||
__name__ = 'stock.reporting.margin.product'
|
||||
|
||||
time_series = fields.One2Many(
|
||||
'stock.reporting.margin.product.time_series', 'product', "Time Series")
|
||||
|
||||
@classmethod
|
||||
def __setup__(cls):
|
||||
super().__setup__()
|
||||
cls._order.insert(0, ('product', 'ASC'))
|
||||
|
||||
@classmethod
|
||||
def _column_id(cls, tables, withs):
|
||||
move = tables['move']
|
||||
return move.product
|
||||
|
||||
|
||||
class ProductTimeseries(ProductMixin, AbstractTimeseries, ModelView):
|
||||
__name__ = 'stock.reporting.margin.product.time_series'
|
||||
|
||||
|
||||
class CategoryMixin:
|
||||
__slots__ = ()
|
||||
|
||||
category = fields.Many2One('product.category', "Category")
|
||||
|
||||
@classmethod
|
||||
def _joins(cls):
|
||||
pool = Pool()
|
||||
Product = pool.get('product.product')
|
||||
TemplateCategory = pool.get('product.template-product.category.all')
|
||||
from_item, tables, withs = super()._joins()
|
||||
if 'move.product' not in tables:
|
||||
product = Product.__table__()
|
||||
tables['move.product'] = product
|
||||
move = tables['move']
|
||||
from_item = (from_item
|
||||
.join(product, condition=move.product == product.id))
|
||||
if 'move.product.template_category' not in tables:
|
||||
template_category = TemplateCategory.__table__()
|
||||
tables['move.product.template_category'] = template_category
|
||||
product = tables['move.product']
|
||||
from_item = (from_item
|
||||
.join(template_category,
|
||||
condition=product.template == template_category.template))
|
||||
return from_item, tables, withs
|
||||
|
||||
@classmethod
|
||||
def _columns(cls, tables, withs):
|
||||
template_category = tables['move.product.template_category']
|
||||
return super()._columns(tables, withs) + [
|
||||
template_category.category.as_('category')]
|
||||
|
||||
@classmethod
|
||||
def _column_id(cls, tables, withs):
|
||||
pool = Pool()
|
||||
Category = pool.get('product.category')
|
||||
category = Category.__table__()
|
||||
move = tables['move']
|
||||
template_category = tables['move.product.template_category']
|
||||
# Get a stable number of category over time
|
||||
# by using number one order bigger.
|
||||
nb_category = category.select(
|
||||
Power(10, (Ceil(Log(Max(category.id))) + Literal(1))))
|
||||
return Min(move.id * nb_category + template_category.id)
|
||||
|
||||
@classmethod
|
||||
def _group_by(cls, tables, withs):
|
||||
template_category = tables['move.product.template_category']
|
||||
return super()._group_by(tables, withs) + [template_category.category]
|
||||
|
||||
@classmethod
|
||||
def _where(cls, tables, withs):
|
||||
template_category = tables['move.product.template_category']
|
||||
where = super()._where(tables, withs)
|
||||
where &= template_category.category != Null
|
||||
return where
|
||||
|
||||
def get_rec_name(self, name):
|
||||
return self.category.rec_name if self.category else None
|
||||
|
||||
@classmethod
|
||||
def search_rec_name(cls, name, clause):
|
||||
return [('category.rec_name', *clause[1:])]
|
||||
|
||||
|
||||
class Category(CategoryMixin, Abstract, ModelView):
|
||||
__name__ = 'stock.reporting.margin.category'
|
||||
|
||||
time_series = fields.One2Many(
|
||||
'stock.reporting.margin.category.time_series', 'category',
|
||||
"Time Series")
|
||||
|
||||
@classmethod
|
||||
def __setup__(cls):
|
||||
super().__setup__()
|
||||
cls._order.insert(0, ('category', 'ASC'))
|
||||
|
||||
@classmethod
|
||||
def _column_id(cls, tables, withs):
|
||||
template_category = tables['move.product.template_category']
|
||||
return template_category.category
|
||||
|
||||
|
||||
class CategoryTimeseries(CategoryMixin, AbstractTimeseries, ModelView):
|
||||
__name__ = 'stock.reporting.margin.category.time_series'
|
||||
|
||||
|
||||
class CategoryTree(ModelSQL, ModelView):
|
||||
__name__ = 'stock.reporting.margin.category.tree'
|
||||
|
||||
name = fields.Function(
|
||||
fields.Char("Name"), 'get_name', searcher='search_name')
|
||||
parent = fields.Many2One('stock.reporting.margin.category.tree', "Parent")
|
||||
children = fields.One2Many(
|
||||
'stock.reporting.margin.category.tree', 'parent', "Children")
|
||||
cost = fields.Function(Monetary(
|
||||
lazy_gettext('stock.msg_stock_reporting_cost'),
|
||||
currency='currency', digits='currency'),
|
||||
'get_total')
|
||||
revenue = fields.Function(Monetary(
|
||||
lazy_gettext('stock.msg_stock_reporting_revenue'),
|
||||
currency='currency', digits='currency'),
|
||||
'get_total')
|
||||
profit = fields.Function(Monetary(
|
||||
lazy_gettext('stock.msg_stock_reporting_profit'),
|
||||
currency='currency', digits='currency'),
|
||||
'get_total')
|
||||
margin = fields.Function(Monetary(
|
||||
lazy_gettext('stock.msg_stock_reporting_margin'),
|
||||
digits=(None, 4)),
|
||||
'get_margin')
|
||||
|
||||
currency = fields.Function(fields.Many2One(
|
||||
'currency.currency',
|
||||
lazy_gettext('stock.msg_stock_reporting_currency')),
|
||||
'get_currency')
|
||||
|
||||
@classmethod
|
||||
def __setup__(cls):
|
||||
super().__setup__()
|
||||
cls._order.insert(0, ('name', 'ASC'))
|
||||
|
||||
@classmethod
|
||||
def table_query(cls):
|
||||
pool = Pool()
|
||||
Category = pool.get('product.category')
|
||||
return Category.__table__()
|
||||
|
||||
@classmethod
|
||||
def get_name(cls, categories, name):
|
||||
pool = Pool()
|
||||
Category = pool.get('product.category')
|
||||
categories = Category.browse(categories)
|
||||
return {c.id: c.name for c in categories}
|
||||
|
||||
@classmethod
|
||||
def search_name(cls, name, clause):
|
||||
pool = Pool()
|
||||
Category = pool.get('product.category')
|
||||
return [('id', 'in', Category.search([clause], query=True))]
|
||||
|
||||
@classmethod
|
||||
def order_name(cls, tables):
|
||||
pool = Pool()
|
||||
Category = pool.get('product.category')
|
||||
table, _ = tables[None]
|
||||
if 'category' not in tables:
|
||||
category = Category.__table__()
|
||||
tables['category'] = {
|
||||
None: (category, table.id == category.id),
|
||||
}
|
||||
return Category.name.convert_order(
|
||||
'name', tables['category'], Category)
|
||||
|
||||
def time_series_all(self):
|
||||
return []
|
||||
|
||||
@classmethod
|
||||
def get_total(cls, categories, names):
|
||||
pool = Pool()
|
||||
ReportingCategory = pool.get('stock.reporting.margin.category')
|
||||
reporting_category = ReportingCategory.__table__()
|
||||
cursor = Transaction().connection.cursor()
|
||||
|
||||
categories = cls.search([
|
||||
('parent', 'child_of', [c.id for c in categories]),
|
||||
])
|
||||
ids = [c.id for c in categories]
|
||||
reporting_categories = []
|
||||
for sub_ids in grouped_slice(ids):
|
||||
sub_ids = list(sub_ids)
|
||||
where = reduce_ids(reporting_category.id, sub_ids)
|
||||
cursor.execute(
|
||||
*reporting_category.select(reporting_category.id, where=where))
|
||||
reporting_categories.extend(r for r, in cursor)
|
||||
|
||||
result = {}
|
||||
reporting_categories = ReportingCategory.browse(reporting_categories)
|
||||
for name in names:
|
||||
values = defaultdict(
|
||||
Decimal,
|
||||
{c.id: getattr(c, name) for c in reporting_categories})
|
||||
result[name] = sum_tree(categories, values)
|
||||
return result
|
||||
|
||||
def get_margin(self, name):
|
||||
digits = self.__class__.margin.digits
|
||||
if self.profit is not None and self.revenue:
|
||||
return (self.profit / self.revenue).quantize(
|
||||
Decimal(1) / 10 ** digits[1])
|
||||
|
||||
def get_currency(self, name):
|
||||
pool = Pool()
|
||||
Company = pool.get('company.company')
|
||||
company = Transaction().context.get('company')
|
||||
if company is not None and company >= 0:
|
||||
return Company(company).currency.id
|
||||
|
||||
@classmethod
|
||||
def view_attributes(cls):
|
||||
return super().view_attributes() + [
|
||||
('/tree/field[@name="profit"]', 'visual',
|
||||
If(Eval('profit', 0) < 0, 'danger', '')),
|
||||
('/tree/field[@name="margin"]', 'visual',
|
||||
If(Eval('margin', 0) < 0, 'danger', '')),
|
||||
]
|
||||
591
modules/stock/stock_reporting_margin.xml
Normal file
591
modules/stock/stock_reporting_margin.xml
Normal file
@@ -0,0 +1,591 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
this repository contains the full copyright notices and license terms. -->
|
||||
<tryton>
|
||||
<data>
|
||||
<menuitem
|
||||
name="Margins"
|
||||
parent="product.menu_reporting"
|
||||
sequence="50"
|
||||
id="menu_reporting_margin"
|
||||
icon="tryton-graph"/>
|
||||
<record model="ir.ui.menu-res.group" id="menu_reporting_margin_group_product_admin">
|
||||
<field name="menu" ref="menu_reporting_margin"/>
|
||||
<field name="group" ref="product.group_product_admin"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="reporting_margin_context_view_form">
|
||||
<field name="model">stock.reporting.margin.context</field>
|
||||
<field name="type">form</field>
|
||||
<field name="name">reporting_margin_context_form</field>
|
||||
</record>
|
||||
|
||||
<!-- Main -->
|
||||
|
||||
<record model="ir.ui.view" id="reporting_margin_main_view_list">
|
||||
<field name="model">stock.reporting.margin.main</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="name">reporting_margin_main_list</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="reporting_margin_main_view_graph_margin">
|
||||
<field name="model">stock.reporting.margin.main</field>
|
||||
<field name="type">graph</field>
|
||||
<field name="name">reporting_margin_main_graph_margin</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="reporting_margin_main_view_graph_profit">
|
||||
<field name="model">stock.reporting.margin.main</field>
|
||||
<field name="type">graph</field>
|
||||
<field name="name">reporting_margin_main_graph_profit</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="reporting_margin_main_view_graph_amount">
|
||||
<field name="model">stock.reporting.margin.main</field>
|
||||
<field name="type">graph</field>
|
||||
<field name="name">reporting_margin_main_graph_amount</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.action.act_window" id="act_reporting_margin_main">
|
||||
<field name="name">Margins</field>
|
||||
<field name="res_model">stock.reporting.margin.main</field>
|
||||
<field name="context_model">stock.reporting.margin.context</field>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_reporting_margin_main_view1">
|
||||
<field name="sequence" eval="10"/>
|
||||
<field name="view" ref="reporting_margin_main_view_list"/>
|
||||
<field name="act_window" ref="act_reporting_margin_main"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_reporting_margin_main_view2">
|
||||
<field name="sequence" eval="20"/>
|
||||
<field name="view" ref="reporting_margin_main_view_graph_margin"/>
|
||||
<field name="act_window" ref="act_reporting_margin_main"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_reporting_margin_main_view3">
|
||||
<field name="sequence" eval="30"/>
|
||||
<field name="view" ref="reporting_margin_main_view_graph_profit"/>
|
||||
<field name="act_window" ref="act_reporting_margin_main"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_reporting_margin_main_view4">
|
||||
<field name="sequence" eval="40"/>
|
||||
<field name="view" ref="reporting_margin_main_view_graph_amount"/>
|
||||
<field name="act_window" ref="act_reporting_margin_main"/>
|
||||
</record>
|
||||
<record model="ir.action.keyword" id="act_reporting_margin_main_keyword1">
|
||||
<field name="keyword">tree_open</field>
|
||||
<field name="model" ref="menu_reporting_margin"/>
|
||||
<field name="action" ref="act_reporting_margin_main"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.rule.group" id="rule_group_reporting_margin_main_companies">
|
||||
<field name="name">User in companies</field>
|
||||
<field name="model">stock.reporting.margin.main</field>
|
||||
<field name="global_p" eval="True"/>
|
||||
</record>
|
||||
<record model="ir.rule" id="rule_reporting_margin_main_companies">
|
||||
<field name="domain"
|
||||
eval="[('company', 'in', Eval('companies', []))]"
|
||||
pyson="1"/>
|
||||
<field name="rule_group" ref="rule_group_reporting_margin_main_companies"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.access" id="access_reporting_margin_main">
|
||||
<field name="model">stock.reporting.margin.main</field>
|
||||
<field name="perm_read" eval="False"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
<field name="perm_create" eval="False"/>
|
||||
<field name="perm_delete" eval="False"/>
|
||||
</record>
|
||||
<record model="ir.model.access" id="access_reporting_margin_main_product_admin">
|
||||
<field name="model">stock.reporting.margin.main</field>
|
||||
<field name="group" ref="product.group_product_admin"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
<field name="perm_create" eval="False"/>
|
||||
<field name="perm_delete" eval="False"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="reporting_margin_main_time_series_view_list">
|
||||
<field name="model">stock.reporting.margin.main.time_series</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="name">reporting_margin_main_time_series_list</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="reporting_margin_main_time_series_view_graph_margin">
|
||||
<field name="model">stock.reporting.margin.main.time_series</field>
|
||||
<field name="type">graph</field>
|
||||
<field name="name">reporting_margin_main_time_series_graph_margin</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="reporting_margin_main_time_series_view_graph_profit">
|
||||
<field name="model">stock.reporting.margin.main.time_series</field>
|
||||
<field name="type">graph</field>
|
||||
<field name="name">reporting_margin_main_time_series_graph_profit</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="reporting_margin_main_time_series_view_graph_amount">
|
||||
<field name="model">stock.reporting.margin.main.time_series</field>
|
||||
<field name="type">graph</field>
|
||||
<field name="name">reporting_margin_main_time_series_graph_amount</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.action.act_window" id="act_reporting_margin_main_time_series">
|
||||
<field name="name">Margins</field>
|
||||
<field name="res_model">stock.reporting.margin.main.time_series</field>
|
||||
<field name="context_model">stock.reporting.margin.context</field>
|
||||
<field name="order" eval="[('date', 'DESC')]" pyson="1"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_reporting_margin_main_time_series_view1">
|
||||
<field name="sequence" eval="10"/>
|
||||
<field name="view" ref="reporting_margin_main_time_series_view_list"/>
|
||||
<field name="act_window" ref="act_reporting_margin_main_time_series"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_reporting_margin_main_time_series_view2">
|
||||
<field name="sequence" eval="20"/>
|
||||
<field name="view" ref="reporting_margin_main_time_series_view_graph_margin"/>
|
||||
<field name="act_window" ref="act_reporting_margin_main_time_series"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_reporting_margin_main_time_series_view3">
|
||||
<field name="sequence" eval="30"/>
|
||||
<field name="view" ref="reporting_margin_main_time_series_view_graph_profit"/>
|
||||
<field name="act_window" ref="act_reporting_margin_main_time_series"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_reporting_margin_main_time_series_view4">
|
||||
<field name="sequence" eval="40"/>
|
||||
<field name="view" ref="reporting_margin_main_time_series_view_graph_amount"/>
|
||||
<field name="act_window" ref="act_reporting_margin_main_time_series"/>
|
||||
</record>
|
||||
<record model="ir.action.keyword" id="act_reporting_margin_main_time_series_keyword1">
|
||||
<field name="keyword">tree_open</field>
|
||||
<field name="model">stock.reporting.margin.main,-1</field>
|
||||
<field name="action" ref="act_reporting_margin_main_time_series"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.rule.group" id="rule_group_reporting_margin_main_time_series_companies">
|
||||
<field name="name">User in companies</field>
|
||||
<field name="model">stock.reporting.margin.main.time_series</field>
|
||||
<field name="global_p" eval="True"/>
|
||||
</record>
|
||||
<record model="ir.rule" id="rule_reporting_margin_main_time_series_companies">
|
||||
<field name="domain"
|
||||
eval="[('company', 'in', Eval('companies', []))]"
|
||||
pyson="1"/>
|
||||
<field name="rule_group" ref="rule_group_reporting_margin_main_time_series_companies"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.access" id="access_reporting_margin_main_time_series">
|
||||
<field name="model">stock.reporting.margin.main.time_series</field>
|
||||
<field name="perm_read" eval="False"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
<field name="perm_create" eval="False"/>
|
||||
<field name="perm_delete" eval="False"/>
|
||||
</record>
|
||||
<record model="ir.model.access" id="access_reporting_margin_main_time_series_main_admin">
|
||||
<field name="model">stock.reporting.margin.main.time_series</field>
|
||||
<field name="group" ref="product.group_product_admin"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
<field name="perm_create" eval="False"/>
|
||||
<field name="perm_delete" eval="False"/>
|
||||
</record>
|
||||
|
||||
<!-- Product -->
|
||||
|
||||
<record model="ir.ui.view" id="reporting_margin_product_view_list">
|
||||
<field name="model">stock.reporting.margin.product</field>
|
||||
<field name="type" eval="None"/>
|
||||
<field name="inherit" ref="reporting_margin_main_view_list"/>
|
||||
<field name="name">reporting_margin_product_list</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="reporting_margin_product_view_graph_margin">
|
||||
<field name="model">stock.reporting.margin.product</field>
|
||||
<field name="type" eval="None"/>
|
||||
<field name="inherit" ref="reporting_margin_main_view_graph_margin"/>
|
||||
<field name="name">reporting_margin_product_graph_margin</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="reporting_margin_product_view_graph_profit">
|
||||
<field name="model">stock.reporting.margin.product</field>
|
||||
<field name="type" eval="None"/>
|
||||
<field name="inherit" ref="reporting_margin_main_view_graph_profit"/>
|
||||
<field name="name">reporting_margin_product_graph_profit</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="reporting_margin_product_view_graph_amount">
|
||||
<field name="model">stock.reporting.margin.product</field>
|
||||
<field name="type" eval="None"/>
|
||||
<field name="inherit" ref="reporting_margin_main_view_graph_amount"/>
|
||||
<field name="name">reporting_margin_product_graph_amount</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.action.act_window" id="act_reporting_margin_product">
|
||||
<field name="name">Margins per Product</field>
|
||||
<field name="res_model">stock.reporting.margin.product</field>
|
||||
<field name="context_model">stock.reporting.margin.context</field>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_reporting_margin_product_view1">
|
||||
<field name="sequence" eval="10"/>
|
||||
<field name="view" ref="reporting_margin_product_view_list"/>
|
||||
<field name="act_window" ref="act_reporting_margin_product"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_reporting_margin_product_view2">
|
||||
<field name="sequence" eval="20"/>
|
||||
<field name="view" ref="reporting_margin_product_view_graph_margin"/>
|
||||
<field name="act_window" ref="act_reporting_margin_product"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_reporting_margin_product_view3">
|
||||
<field name="sequence" eval="30"/>
|
||||
<field name="view" ref="reporting_margin_product_view_graph_profit"/>
|
||||
<field name="act_window" ref="act_reporting_margin_product"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_reporting_margin_product_view4">
|
||||
<field name="sequence" eval="40"/>
|
||||
<field name="view" ref="reporting_margin_product_view_graph_amount"/>
|
||||
<field name="act_window" ref="act_reporting_margin_product"/>
|
||||
</record>
|
||||
<record model="ir.action.keyword" id="act_reporting_margin_product_keyword1">
|
||||
<field name="keyword">tree_open</field>
|
||||
<field name="model" ref="menu_reporting_margin"/>
|
||||
<field name="action" ref="act_reporting_margin_product"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.rule.group" id="rule_group_reporting_margin_product_companies">
|
||||
<field name="name">User in companies</field>
|
||||
<field name="model">stock.reporting.margin.product</field>
|
||||
<field name="global_p" eval="True"/>
|
||||
</record>
|
||||
<record model="ir.rule" id="rule_reporting_margin_product_companies">
|
||||
<field name="domain"
|
||||
eval="[('company', 'in', Eval('companies', []))]"
|
||||
pyson="1"/>
|
||||
<field name="rule_group" ref="rule_group_reporting_margin_product_companies"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.access" id="access_reporting_margin_product">
|
||||
<field name="model">stock.reporting.margin.product</field>
|
||||
<field name="perm_read" eval="False"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
<field name="perm_create" eval="False"/>
|
||||
<field name="perm_delete" eval="False"/>
|
||||
</record>
|
||||
<record model="ir.model.access" id="access_reporting_margin_product_product_admin">
|
||||
<field name="model">stock.reporting.margin.product</field>
|
||||
<field name="group" ref="product.group_product_admin"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
<field name="perm_create" eval="False"/>
|
||||
<field name="perm_delete" eval="False"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="reporting_margin_product_time_series_view_list">
|
||||
<field name="model">stock.reporting.margin.product.time_series</field>
|
||||
<field name="type" eval="None"/>
|
||||
<field name="inherit" ref="reporting_margin_main_time_series_view_list"/>
|
||||
<field name="name">reporting_margin_product_time_series_list</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="reporting_margin_product_time_series_view_graph_margin">
|
||||
<field name="model">stock.reporting.margin.product.time_series</field>
|
||||
<field name="type">graph</field>
|
||||
<field name="name">reporting_margin_main_time_series_graph_margin</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="reporting_margin_product_time_series_view_graph_profit">
|
||||
<field name="model">stock.reporting.margin.product.time_series</field>
|
||||
<field name="type">graph</field>
|
||||
<field name="name">reporting_margin_main_time_series_graph_profit</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="reporting_margin_product_time_series_view_graph_amount">
|
||||
<field name="model">stock.reporting.margin.product.time_series</field>
|
||||
<field name="type">graph</field>
|
||||
<field name="name">reporting_margin_main_time_series_graph_amount</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.action.act_window" id="act_reporting_margin_product_time_series">
|
||||
<field name="name">Margins per Product</field>
|
||||
<field name="res_model">stock.reporting.margin.product.time_series</field>
|
||||
<field name="context_model">stock.reporting.margin.context</field>
|
||||
<field
|
||||
name="domain"
|
||||
eval="[('product', '=', Eval('active_id', -1))]"
|
||||
pyson="1"/>
|
||||
<field name="order" eval="[('date', 'DESC')]" pyson="1"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_reporting_margin_product_time_series_view1">
|
||||
<field name="sequence" eval="10"/>
|
||||
<field name="view" ref="reporting_margin_product_time_series_view_list"/>
|
||||
<field name="act_window" ref="act_reporting_margin_product_time_series"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_reporting_margin_product_time_series_view2">
|
||||
<field name="sequence" eval="20"/>
|
||||
<field name="view" ref="reporting_margin_product_time_series_view_graph_margin"/>
|
||||
<field name="act_window" ref="act_reporting_margin_product_time_series"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_reporting_margin_product_time_series_view3">
|
||||
<field name="sequence" eval="30"/>
|
||||
<field name="view" ref="reporting_margin_product_time_series_view_graph_profit"/>
|
||||
<field name="act_window" ref="act_reporting_margin_product_time_series"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_reporting_margin_product_time_series_view4">
|
||||
<field name="sequence" eval="40"/>
|
||||
<field name="view" ref="reporting_margin_product_time_series_view_graph_amount"/>
|
||||
<field name="act_window" ref="act_reporting_margin_product_time_series"/>
|
||||
</record>
|
||||
<record model="ir.action.keyword" id="act_reporting_margin_product_time_series_keyword1">
|
||||
<field name="keyword">tree_open</field>
|
||||
<field name="model">stock.reporting.margin.product,-1</field>
|
||||
<field name="action" ref="act_reporting_margin_product_time_series"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.rule.group" id="rule_group_reporting_margin_product_time_series_companies">
|
||||
<field name="name">User in companies</field>
|
||||
<field name="model">stock.reporting.margin.product.time_series</field>
|
||||
<field name="global_p" eval="True"/>
|
||||
</record>
|
||||
<record model="ir.rule" id="rule_reporting_margin_product_time_series_companies">
|
||||
<field name="domain"
|
||||
eval="[('company', 'in', Eval('companies', []))]"
|
||||
pyson="1"/>
|
||||
<field name="rule_group" ref="rule_group_reporting_margin_product_time_series_companies"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.access" id="access_reporting_margin_product_time_series">
|
||||
<field name="model">stock.reporting.margin.product.time_series</field>
|
||||
<field name="perm_read" eval="False"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
<field name="perm_create" eval="False"/>
|
||||
<field name="perm_delete" eval="False"/>
|
||||
</record>
|
||||
<record model="ir.model.access" id="access_reporting_margin_product_time_series_product_admin">
|
||||
<field name="model">stock.reporting.margin.product.time_series</field>
|
||||
<field name="group" ref="product.group_product_admin"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
<field name="perm_create" eval="False"/>
|
||||
<field name="perm_delete" eval="False"/>
|
||||
</record>
|
||||
|
||||
<!-- Category -->
|
||||
|
||||
<record model="ir.ui.view" id="reporting_margin_category_tree_view_tree">
|
||||
<field name="model">stock.reporting.margin.category.tree</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="field_childs">children</field>
|
||||
<field name="name">reporting_margin_category_tree</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.action.act_window" id="act_reporting_margin_category_tree">
|
||||
<field name="name">Margins per Category</field>
|
||||
<field name="res_model">stock.reporting.margin.category.tree</field>
|
||||
<field name="context_model">stock.reporting.margin.context</field>
|
||||
<field name="domain" eval="[('parent', '=', None)]" pyson="1"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_reporting_margin_category_tree_view1">
|
||||
<field name="sequence" eval="10"/>
|
||||
<field name="view" ref="reporting_margin_category_tree_view_tree"/>
|
||||
<field name="act_window" ref="act_reporting_margin_category_tree"/>
|
||||
</record>
|
||||
<record model="ir.action.keyword" id="act_reporting_margin_category_tree_keyword1">
|
||||
<field name="keyword">tree_open</field>
|
||||
<field name="model" ref="menu_reporting_margin"/>
|
||||
<field name="action" ref="act_reporting_margin_category_tree"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.access" id="access_reporting_margin_category_tree">
|
||||
<field name="model">stock.reporting.margin.category.tree</field>
|
||||
<field name="perm_read" eval="False"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
<field name="perm_create" eval="False"/>
|
||||
<field name="perm_delete" eval="False"/>
|
||||
</record>
|
||||
<record model="ir.model.access" id="access_reporting_margin_category_tree_product_admin">
|
||||
<field name="model">stock.reporting.margin.category.tree</field>
|
||||
<field name="group" ref="product.group_product_admin"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
<field name="perm_create" eval="False"/>
|
||||
<field name="perm_delete" eval="False"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="reporting_margin_category_view_list">
|
||||
<field name="model">stock.reporting.margin.category</field>
|
||||
<field name="type" eval="None"/>
|
||||
<field name="inherit" ref="reporting_margin_main_view_list"/>
|
||||
<field name="name">reporting_margin_category_list</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="reporting_margin_category_view_graph_margin">
|
||||
<field name="model">stock.reporting.margin.category</field>
|
||||
<field name="type" eval="None"/>
|
||||
<field name="inherit" ref="reporting_margin_main_view_graph_margin"/>
|
||||
<field name="name">reporting_margin_category_graph_margin</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="reporting_margin_category_view_graph_profit">
|
||||
<field name="model">stock.reporting.margin.category</field>
|
||||
<field name="type" eval="None"/>
|
||||
<field name="inherit" ref="reporting_margin_main_view_graph_profit"/>
|
||||
<field name="name">reporting_margin_category_graph_profit</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="reporting_margin_category_view_graph_amount">
|
||||
<field name="model">stock.reporting.margin.category</field>
|
||||
<field name="type" eval="None"/>
|
||||
<field name="inherit" ref="reporting_margin_main_view_graph_amount"/>
|
||||
<field name="name">reporting_margin_category_graph_amount</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.action.act_window" id="act_reporting_margin_category">
|
||||
<field name="name">Margins per Category</field>
|
||||
<field name="res_model">stock.reporting.margin.category</field>
|
||||
<field name="context_model">stock.reporting.margin.context</field>
|
||||
<field
|
||||
name="domain"
|
||||
eval="[('category', 'child_of', Eval('active_ids', []), 'parent')]"
|
||||
pyson="1"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_reporting_margin_category_view1">
|
||||
<field name="sequence" eval="10"/>
|
||||
<field name="view" ref="reporting_margin_category_view_list"/>
|
||||
<field name="act_window" ref="act_reporting_margin_category"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_reporting_margin_category_view2">
|
||||
<field name="sequence" eval="20"/>
|
||||
<field name="view" ref="reporting_margin_category_view_graph_margin"/>
|
||||
<field name="act_window" ref="act_reporting_margin_category"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_reporting_margin_category_view3">
|
||||
<field name="sequence" eval="30"/>
|
||||
<field name="view" ref="reporting_margin_category_view_graph_profit"/>
|
||||
<field name="act_window" ref="act_reporting_margin_category"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_reporting_margin_category_view4">
|
||||
<field name="sequence" eval="40"/>
|
||||
<field name="view" ref="reporting_margin_category_view_graph_amount"/>
|
||||
<field name="act_window" ref="act_reporting_margin_category"/>
|
||||
</record>
|
||||
<record model="ir.action.keyword" id="act_reporting_margin_category_keyword1">
|
||||
<field name="keyword">tree_open</field>
|
||||
<field name="model">stock.reporting.margin.category.tree,-1</field>
|
||||
<field name="action" ref="act_reporting_margin_category"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.rule.group" id="rule_group_reporting_margin_category_companies">
|
||||
<field name="name">User in companies</field>
|
||||
<field name="model">stock.reporting.margin.category</field>
|
||||
<field name="global_p" eval="True"/>
|
||||
</record>
|
||||
<record model="ir.rule" id="rule_reporting_margin_category_companies">
|
||||
<field name="domain"
|
||||
eval="[('company', 'in', Eval('companies', []))]"
|
||||
pyson="1"/>
|
||||
<field name="rule_group" ref="rule_group_reporting_margin_category_companies"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.access" id="access_reporting_margin_category">
|
||||
<field name="model">stock.reporting.margin.category</field>
|
||||
<field name="perm_read" eval="False"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
<field name="perm_create" eval="False"/>
|
||||
<field name="perm_delete" eval="False"/>
|
||||
</record>
|
||||
<record model="ir.model.access" id="access_reporting_margin_category_product_admin">
|
||||
<field name="model">stock.reporting.margin.category</field>
|
||||
<field name="group" ref="product.group_product_admin"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
<field name="perm_create" eval="False"/>
|
||||
<field name="perm_delete" eval="False"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="reporting_margin_category_time_series_view_list">
|
||||
<field name="model">stock.reporting.margin.category.time_series</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="name">reporting_margin_main_time_series_list</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="reporting_margin_category_time_series_view_graph_margin">
|
||||
<field name="model">stock.reporting.margin.category.time_series</field>
|
||||
<field name="type">graph</field>
|
||||
<field name="name">reporting_margin_main_time_series_graph_margin</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="reporting_margin_category_time_series_view_graph_profit">
|
||||
<field name="model">stock.reporting.margin.category.time_series</field>
|
||||
<field name="type">graph</field>
|
||||
<field name="name">reporting_margin_main_time_series_graph_profit</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="reporting_margin_category_time_series_view_graph_amount">
|
||||
<field name="model">stock.reporting.margin.category.time_series</field>
|
||||
<field name="type">graph</field>
|
||||
<field name="name">reporting_margin_main_time_series_graph_amount</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.action.act_window" id="act_reporting_margin_category_time_series">
|
||||
<field name="name">Margins per Category</field>
|
||||
<field name="res_model">stock.reporting.margin.category.time_series</field>
|
||||
<field name="context_model">stock.reporting.margin.context</field>
|
||||
<field
|
||||
name="domain"
|
||||
eval="[('category', '=', Eval('active_id', -1))]"
|
||||
pyson="1"/>
|
||||
<field name="order" eval="[('date', 'DESC')]" pyson="1"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_reporting_margin_category_time_series_view1">
|
||||
<field name="sequence" eval="10"/>
|
||||
<field name="view" ref="reporting_margin_category_time_series_view_list"/>
|
||||
<field name="act_window" ref="act_reporting_margin_category_time_series"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_reporting_margin_category_time_series_view2">
|
||||
<field name="sequence" eval="20"/>
|
||||
<field name="view" ref="reporting_margin_category_time_series_view_graph_margin"/>
|
||||
<field name="act_window" ref="act_reporting_margin_category_time_series"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_reporting_margin_category_time_series_view3">
|
||||
<field name="sequence" eval="30"/>
|
||||
<field name="view" ref="reporting_margin_category_time_series_view_graph_profit"/>
|
||||
<field name="act_window" ref="act_reporting_margin_category_time_series"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_reporting_margin_category_time_series_view4">
|
||||
<field name="sequence" eval="40"/>
|
||||
<field name="view" ref="reporting_margin_category_time_series_view_graph_amount"/>
|
||||
<field name="act_window" ref="act_reporting_margin_category_time_series"/>
|
||||
</record>
|
||||
<record model="ir.action.keyword" id="act_reporting_margin_category_time_series_keyword1">
|
||||
<field name="keyword">tree_open</field>
|
||||
<field name="model">stock.reporting.margin.category,-1</field>
|
||||
<field name="action" ref="act_reporting_margin_category_time_series"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.rule.group" id="rule_group_reporting_margin_category_time_series_companies">
|
||||
<field name="name">User in companies</field>
|
||||
<field name="model">stock.reporting.margin.category.time_series</field>
|
||||
<field name="global_p" eval="True"/>
|
||||
</record>
|
||||
<record model="ir.rule" id="rule_reporting_margin_category_time_series_companies">
|
||||
<field name="domain"
|
||||
eval="[('company', 'in', Eval('companies', []))]"
|
||||
pyson="1"/>
|
||||
<field name="rule_group" ref="rule_group_reporting_margin_category_time_series_companies"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.access" id="access_reporting_margin_category_time_series">
|
||||
<field name="model">stock.reporting.margin.category.time_series</field>
|
||||
<field name="perm_read" eval="False"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
<field name="perm_create" eval="False"/>
|
||||
<field name="perm_delete" eval="False"/>
|
||||
</record>
|
||||
<record model="ir.model.access" id="access_reporting_margin_category_time_series_product_admin">
|
||||
<field name="model">stock.reporting.margin.category.time_series</field>
|
||||
<field name="group" ref="product.group_product_admin"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
<field name="perm_create" eval="False"/>
|
||||
<field name="perm_delete" eval="False"/>
|
||||
</record>
|
||||
</data>
|
||||
</tryton>
|
||||
603
modules/stock/supplier_restocking_list.fodt
Normal file
603
modules/stock/supplier_restocking_list.fodt
Normal file
@@ -0,0 +1,603 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<office:document xmlns:css3t="http://www.w3.org/TR/css3-text/" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:rpt="http://openoffice.org/2005/report" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:officeooo="http://openoffice.org/2009/office" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.text">
|
||||
<office:meta><meta:generator>LibreOffice/7.6.4.1$Linux_X86_64 LibreOffice_project/60$Build-1</meta:generator><meta:initial-creator>Bertrand Chenal</meta:initial-creator><meta:creation-date>2009-03-26T13:54:48</meta:creation-date><dc:date>2024-04-19T23:16:55.104218033</dc:date><meta:editing-cycles>55</meta:editing-cycles><meta:editing-duration>PT7H1M30S</meta:editing-duration><meta:document-statistic meta:table-count="1" meta:image-count="0" meta:object-count="0" meta:page-count="3" meta:paragraph-count="46" meta:word-count="103" meta:character-count="1103" meta:non-whitespace-character-count="1045"/><meta:user-defined meta:name="Info 1"/><meta:user-defined meta:name="Info 2"/><meta:user-defined meta:name="Info 3"/><meta:user-defined meta:name="Info 4"/></office:meta>
|
||||
<office:settings>
|
||||
<config:config-item-set config:name="ooo:view-settings">
|
||||
<config:config-item config:name="ViewAreaTop" config:type="long">0</config:config-item>
|
||||
<config:config-item config:name="ViewAreaLeft" config:type="long">0</config:config-item>
|
||||
<config:config-item config:name="ViewAreaWidth" config:type="long">25269</config:config-item>
|
||||
<config:config-item config:name="ViewAreaHeight" config:type="long">23973</config:config-item>
|
||||
<config:config-item config:name="ShowRedlineChanges" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="InBrowseMode" config:type="boolean">false</config:config-item>
|
||||
<config:config-item-map-indexed config:name="Views">
|
||||
<config:config-item-map-entry>
|
||||
<config:config-item config:name="ViewId" config:type="string">view2</config:config-item>
|
||||
<config:config-item config:name="ViewLeft" config:type="long">5955</config:config-item>
|
||||
<config:config-item config:name="ViewTop" config:type="long">10248</config:config-item>
|
||||
<config:config-item config:name="VisibleLeft" config:type="long">0</config:config-item>
|
||||
<config:config-item config:name="VisibleTop" config:type="long">0</config:config-item>
|
||||
<config:config-item config:name="VisibleRight" config:type="long">25268</config:config-item>
|
||||
<config:config-item config:name="VisibleBottom" config:type="long">23971</config:config-item>
|
||||
<config:config-item config:name="ZoomType" config:type="short">0</config:config-item>
|
||||
<config:config-item config:name="ViewLayoutColumns" config:type="short">0</config:config-item>
|
||||
<config:config-item config:name="ViewLayoutBookMode" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="ZoomFactor" config:type="short">100</config:config-item>
|
||||
<config:config-item config:name="IsSelectedFrame" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="KeepRatio" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="AnchoredTextOverflowLegacy" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="LegacySingleLineFontwork" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="ConnectorUseSnapRect" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="IgnoreBreakAfterMultilineField" config:type="boolean">false</config:config-item>
|
||||
</config:config-item-map-entry>
|
||||
</config:config-item-map-indexed>
|
||||
</config:config-item-set>
|
||||
<config:config-item-set config:name="ooo:configuration-settings">
|
||||
<config:config-item config:name="PrintRightPages" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="PrintProspectRTL" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="PrintLeftPages" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="PrintPaperFromSetup" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="PrintControls" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="PrintProspect" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="PrintBlackFonts" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="PrintAnnotationMode" config:type="short">0</config:config-item>
|
||||
<config:config-item config:name="PrintEmptyPages" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="PrintSingleJobs" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="AutoFirstLineIndentDisregardLineSpace" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="HeaderSpacingBelowLastPara" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="ProtectBookmarks" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="ContinuousEndnotes" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="DisableOffPagePositioning" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="PrintTables" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="SubtractFlysAnchoredAtFlys" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="ApplyParagraphMarkFormatToNumbering" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="PrintFaxName" config:type="string"/>
|
||||
<config:config-item config:name="SurroundTextWrapSmall" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="TreatSingleColumnBreakAsPageBreak" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="PropLineSpacingShrinksFirstLine" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="TabOverSpacing" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="TabOverMargin" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="EmbedComplexScriptFonts" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="EmbedLatinScriptFonts" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="EmbedOnlyUsedFonts" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="EmbedFonts" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="ClippedPictures" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="FrameAutowidthWithMorePara" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="FloattableNomargins" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="UnbreakableNumberings" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="AllowPrintJobCancel" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="UseFormerObjectPositioning" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="UseOldNumbering" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="RsidRoot" config:type="int">1289861</config:config-item>
|
||||
<config:config-item config:name="PrinterPaperFromSetup" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="CurrentDatabaseDataSource" config:type="string"/>
|
||||
<config:config-item config:name="UpdateFromTemplate" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="AddFrameOffsets" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="LoadReadonly" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="Rsid" config:type="int">2119093</config:config-item>
|
||||
<config:config-item config:name="FootnoteInColumnToPageEnd" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="ProtectFields" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="SaveGlobalDocumentLinks" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="ClipAsCharacterAnchoredWriterFlyFrames" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="LinkUpdateMode" config:type="short">1</config:config-item>
|
||||
<config:config-item config:name="AddExternalLeading" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="PrintGraphics" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="EmbedSystemFonts" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="IsLabelDocument" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="AddParaLineSpacingToTableCells" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="UseFormerTextWrapping" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="HyphenateURLs" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="AddParaTableSpacingAtStart" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="TabsRelativeToIndent" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="FieldAutoUpdate" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="SaveVersionOnClose" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="ChartAutoUpdate" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="ImagePreferredDPI" config:type="int">0</config:config-item>
|
||||
<config:config-item config:name="PrinterSetup" config:type="base64Binary"/>
|
||||
<config:config-item config:name="SmallCapsPercentage66" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="AlignTabStopPosition" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="DropCapPunctuation" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="MathBaselineAlignment" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="PrinterName" config:type="string"/>
|
||||
<config:config-item config:name="CharacterCompressionType" config:type="short">0</config:config-item>
|
||||
<config:config-item config:name="AddParaTableSpacing" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="DoNotJustifyLinesWithManualBreak" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="PrintHiddenText" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="IsKernAsianPunctuation" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="PrinterIndependentLayout" config:type="string">high-resolution</config:config-item>
|
||||
<config:config-item config:name="TabOverflow" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="AddParaSpacingToTableCells" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="AddVerticalFrameOffsets" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="TabAtLeftIndentForParagraphsInList" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="ApplyUserData" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="MsWordCompMinLineHeightByFly" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="PrintTextPlaceholder" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="IgnoreFirstLineIndentInNumbering" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="UseFormerLineSpacing" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="PrintPageBackground" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="RedlineProtectionKey" config:type="base64Binary"/>
|
||||
<config:config-item config:name="EmbedAsianScriptFonts" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="BackgroundParaOverDrawings" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="SaveThumbnail" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="ConsiderTextWrapOnObjPos" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="EmbeddedDatabaseName" config:type="string"/>
|
||||
<config:config-item config:name="ProtectForm" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="DoNotResetParaAttrsForNumFont" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="MsWordCompTrailingBlanks" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="EmptyDbFieldHidesPara" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="TableRowKeep" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="NoNumberingShowFollowBy" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="InvertBorderSpacing" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="IgnoreTabsAndBlanksForLineCalculation" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="DoNotCaptureDrawObjsOnPage" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="GutterAtTop" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="StylesNoDefault" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="UnxForceZeroExtLeading" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="PrintReversed" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="UseOldPrinterMetrics" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="CurrentDatabaseCommandType" config:type="int">0</config:config-item>
|
||||
<config:config-item config:name="PrintDrawings" config:type="boolean">true</config:config-item>
|
||||
<config:config-item config:name="OutlineLevelYieldsNumbering" config:type="boolean">false</config:config-item>
|
||||
<config:config-item config:name="CurrentDatabaseCommand" config:type="string"/>
|
||||
<config:config-item config:name="CollapseEmptyCellPara" config:type="boolean">true</config:config-item>
|
||||
</config:config-item-set>
|
||||
</office:settings>
|
||||
<office:scripts>
|
||||
<office:script script:language="ooo:Basic">
|
||||
<ooo:libraries xmlns:ooo="http://openoffice.org/2004/office" xmlns:xlink="http://www.w3.org/1999/xlink"/>
|
||||
</office:script>
|
||||
</office:scripts>
|
||||
<office:font-face-decls>
|
||||
<style:font-face style:name="Andale Sans UI" svg:font-family="'Andale Sans UI'" style:font-family-generic="system" style:font-pitch="variable"/>
|
||||
<style:font-face style:name="DejaVu Sans" svg:font-family="'DejaVu Sans'" style:font-family-generic="system" style:font-pitch="variable"/>
|
||||
<style:font-face style:name="Liberation Sans" svg:font-family="'Liberation Sans'" style:font-adornments="Regular" style:font-family-generic="swiss" style:font-pitch="variable"/>
|
||||
<style:font-face style:name="Liberation Serif" svg:font-family="'Liberation Serif'" style:font-family-generic="roman" style:font-pitch="variable"/>
|
||||
<style:font-face style:name="Liberation Serif1" svg:font-family="'Liberation Serif'" style:font-adornments="Bold" style:font-family-generic="roman" style:font-pitch="variable"/>
|
||||
<style:font-face style:name="Liberation Serif2" svg:font-family="'Liberation Serif'" style:font-adornments="Regular" style:font-family-generic="roman" style:font-pitch="variable"/>
|
||||
<style:font-face style:name="StarSymbol" svg:font-family="StarSymbol"/>
|
||||
<style:font-face style:name="Thorndale AMT" svg:font-family="'Thorndale AMT'" style:font-family-generic="roman" style:font-pitch="variable"/>
|
||||
</office:font-face-decls>
|
||||
<office:styles>
|
||||
<style:default-style style:family="graphic">
|
||||
<style:graphic-properties svg:stroke-color="#000000" draw:fill-color="#99ccff" fo:wrap-option="no-wrap" draw:shadow-offset-x="0.3cm" draw:shadow-offset-y="0.3cm" draw:start-line-spacing-horizontal="0.283cm" draw:start-line-spacing-vertical="0.283cm" draw:end-line-spacing-horizontal="0.283cm" draw:end-line-spacing-vertical="0.283cm" style:writing-mode="lr-tb" style:flow-with-text="false"/>
|
||||
<style:paragraph-properties style:text-autospace="ideograph-alpha" style:line-break="strict" loext:tab-stop-distance="0cm" style:writing-mode="lr-tb" style:font-independent-line-spacing="false">
|
||||
<style:tab-stops/>
|
||||
</style:paragraph-properties>
|
||||
<style:text-properties style:use-window-font-color="true" loext:opacity="0%" style:font-name="Thorndale AMT" fo:font-size="12pt" fo:language="en" fo:country="US" style:letter-kerning="true" style:font-name-asian="Andale Sans UI" style:font-size-asian="10.5pt" style:language-asian="zxx" style:country-asian="none" style:font-name-complex="Andale Sans UI" style:font-size-complex="12pt" style:language-complex="zxx" style:country-complex="none"/>
|
||||
</style:default-style>
|
||||
<style:default-style style:family="paragraph">
|
||||
<style:paragraph-properties fo:hyphenation-ladder-count="no-limit" style:text-autospace="ideograph-alpha" style:punctuation-wrap="hanging" style:line-break="strict" style:tab-stop-distance="1.251cm" style:writing-mode="lr-tb"/>
|
||||
<style:text-properties style:use-window-font-color="true" loext:opacity="0%" style:font-name="Thorndale AMT" fo:font-size="12pt" fo:language="en" fo:country="US" style:letter-kerning="true" style:font-name-asian="Andale Sans UI" style:font-size-asian="10.5pt" style:language-asian="zxx" style:country-asian="none" style:font-name-complex="Andale Sans UI" style:font-size-complex="12pt" style:language-complex="zxx" style:country-complex="none" fo:hyphenate="false" fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2" loext:hyphenation-no-caps="false" loext:hyphenation-no-last-word="false" loext:hyphenation-word-char-count="5" loext:hyphenation-zone="no-limit"/>
|
||||
</style:default-style>
|
||||
<style:default-style style:family="table">
|
||||
<style:table-properties table:border-model="collapsing"/>
|
||||
</style:default-style>
|
||||
<style:default-style style:family="table-row">
|
||||
<style:table-row-properties fo:keep-together="auto"/>
|
||||
</style:default-style>
|
||||
<style:style style:name="Standard" style:family="paragraph" style:class="text">
|
||||
<style:text-properties style:font-name="Liberation Sans" fo:font-family="'Liberation Sans'" style:font-style-name="Regular" style:font-family-generic="swiss" style:font-pitch="variable" style:font-size-asian="10.5pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="Heading" style:family="paragraph" style:parent-style-name="Standard" style:next-style-name="Text_20_body" style:class="text">
|
||||
<style:paragraph-properties fo:margin-top="0.423cm" fo:margin-bottom="0.212cm" style:contextual-spacing="false" fo:keep-with-next="always"/>
|
||||
<style:text-properties style:font-name="Liberation Serif2" fo:font-family="'Liberation Serif'" style:font-style-name="Regular" style:font-family-generic="roman" style:font-pitch="variable" fo:font-size="16pt" style:font-name-asian="DejaVu Sans" style:font-family-asian="'DejaVu Sans'" style:font-family-generic-asian="system" style:font-pitch-asian="variable" style:font-size-asian="14pt" style:font-name-complex="DejaVu Sans" style:font-family-complex="'DejaVu Sans'" style:font-family-generic-complex="system" style:font-pitch-complex="variable" style:font-size-complex="14pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="Text_20_body" style:display-name="Text body" style:family="paragraph" style:parent-style-name="Standard" style:class="text">
|
||||
<style:paragraph-properties fo:margin-top="0cm" fo:margin-bottom="0.212cm" style:contextual-spacing="false"/>
|
||||
<style:text-properties style:font-name="Liberation Sans" fo:font-family="'Liberation Sans'" style:font-style-name="Regular" style:font-family-generic="swiss" style:font-pitch="variable" style:font-size-asian="10.5pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="List" style:family="paragraph" style:parent-style-name="Text_20_body" style:class="list">
|
||||
<style:text-properties style:font-size-asian="12pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="Caption" style:family="paragraph" style:parent-style-name="Standard" style:class="extra">
|
||||
<style:paragraph-properties fo:margin-top="0.212cm" fo:margin-bottom="0.212cm" style:contextual-spacing="false" text:number-lines="false" text:line-number="0"/>
|
||||
<style:text-properties fo:font-size="12pt" fo:font-style="italic" style:font-size-asian="12pt" style:font-style-asian="italic" style:font-size-complex="12pt" style:font-style-complex="italic"/>
|
||||
</style:style>
|
||||
<style:style style:name="Index" style:family="paragraph" style:parent-style-name="Standard" style:class="index">
|
||||
<style:paragraph-properties text:number-lines="false" text:line-number="0"/>
|
||||
<style:text-properties style:font-size-asian="12pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="Heading_20_1" style:display-name="Heading 1" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:class="text">
|
||||
<style:text-properties fo:font-size="16pt" fo:font-weight="bold" style:font-size-asian="115%" style:font-weight-asian="bold" style:font-size-complex="115%" style:font-weight-complex="bold"/>
|
||||
</style:style>
|
||||
<style:style style:name="Table_20_Contents" style:display-name="Table Contents" style:family="paragraph" style:parent-style-name="Standard" style:class="extra">
|
||||
<style:paragraph-properties text:number-lines="false" text:line-number="0"/>
|
||||
<style:text-properties style:font-size-asian="10.5pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="Table_20_Heading" style:display-name="Table Heading" style:family="paragraph" style:parent-style-name="Table_20_Contents" style:class="extra" style:master-page-name="">
|
||||
<style:paragraph-properties fo:text-align="center" style:justify-single-word="false" style:page-number="auto" text:number-lines="false" text:line-number="0"/>
|
||||
<style:text-properties style:font-name="Liberation Serif1" fo:font-family="'Liberation Serif'" style:font-style-name="Bold" style:font-family-generic="roman" style:font-pitch="variable" fo:font-weight="bold" style:font-size-asian="10.5pt" style:font-weight-asian="bold" style:font-weight-complex="bold"/>
|
||||
</style:style>
|
||||
<style:style style:name="Header_20_and_20_Footer" style:display-name="Header and Footer" style:family="paragraph" style:parent-style-name="Standard" style:class="extra">
|
||||
<style:paragraph-properties text:number-lines="false" text:line-number="0">
|
||||
<style:tab-stops>
|
||||
<style:tab-stop style:position="8.795cm" style:type="center"/>
|
||||
<style:tab-stop style:position="17.59cm" style:type="right"/>
|
||||
</style:tab-stops>
|
||||
</style:paragraph-properties>
|
||||
</style:style>
|
||||
<style:style style:name="Header" style:family="paragraph" style:parent-style-name="Standard" style:class="extra">
|
||||
<style:paragraph-properties text:number-lines="false" text:line-number="0">
|
||||
<style:tab-stops>
|
||||
<style:tab-stop style:position="8.795cm" style:type="center"/>
|
||||
<style:tab-stop style:position="17.59cm" style:type="right"/>
|
||||
</style:tab-stops>
|
||||
</style:paragraph-properties>
|
||||
<style:text-properties fo:font-size="9pt" style:font-size-asian="10.5pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="Heading_20_2" style:display-name="Heading 2" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:class="text">
|
||||
<style:text-properties fo:font-size="14pt" fo:font-style="italic" fo:font-weight="bold" style:font-size-asian="14pt" style:font-style-asian="italic" style:font-weight-asian="bold" style:font-size-complex="14pt" style:font-style-complex="italic" style:font-weight-complex="bold"/>
|
||||
</style:style>
|
||||
<style:style style:name="Footer" style:family="paragraph" style:parent-style-name="Standard" style:class="extra">
|
||||
<style:paragraph-properties text:number-lines="false" text:line-number="0">
|
||||
<style:tab-stops>
|
||||
<style:tab-stop style:position="8.795cm" style:type="center"/>
|
||||
<style:tab-stop style:position="17.59cm" style:type="right"/>
|
||||
</style:tab-stops>
|
||||
</style:paragraph-properties>
|
||||
<style:text-properties fo:font-size="9pt" style:font-size-asian="10.5pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="Heading_20_3" style:display-name="Heading 3" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:class="text">
|
||||
<style:text-properties fo:font-size="14pt" fo:font-weight="bold" style:font-size-asian="14pt" style:font-weight-asian="bold" style:font-size-complex="14pt" style:font-weight-complex="bold"/>
|
||||
</style:style>
|
||||
<style:style style:name="Text_20_body_20_indent" style:display-name="Text body indent" style:family="paragraph" style:parent-style-name="Text_20_body" style:class="text">
|
||||
<style:paragraph-properties fo:margin-left="0.499cm" fo:margin-right="0cm" fo:margin-top="0cm" fo:margin-bottom="0cm" style:contextual-spacing="false" fo:text-indent="0cm" style:auto-text-indent="false"/>
|
||||
</style:style>
|
||||
<style:style style:name="Text" style:family="paragraph" style:parent-style-name="Caption" style:class="extra"/>
|
||||
<style:style style:name="Quotations" style:family="paragraph" style:parent-style-name="Standard" style:class="html">
|
||||
<style:paragraph-properties fo:margin-left="1cm" fo:margin-right="1cm" fo:margin-top="0cm" fo:margin-bottom="0.499cm" style:contextual-spacing="false" fo:text-indent="0cm" style:auto-text-indent="false"/>
|
||||
</style:style>
|
||||
<style:style style:name="Title" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:class="chapter">
|
||||
<style:paragraph-properties fo:text-align="center" style:justify-single-word="false"/>
|
||||
<style:text-properties fo:font-size="28pt" fo:font-weight="bold" style:font-size-asian="28pt" style:font-weight-asian="bold" style:font-size-complex="28pt" style:font-weight-complex="bold"/>
|
||||
</style:style>
|
||||
<style:style style:name="Subtitle" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:class="chapter">
|
||||
<style:paragraph-properties fo:margin-top="0.106cm" fo:margin-bottom="0.212cm" style:contextual-spacing="false" fo:text-align="center" style:justify-single-word="false"/>
|
||||
<style:text-properties fo:font-size="18pt" style:font-size-asian="18pt" style:font-size-complex="18pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="Frame_20_contents" style:display-name="Frame contents" style:family="paragraph" style:parent-style-name="Standard" style:class="extra"/>
|
||||
<style:style style:name="Placeholder" style:family="text">
|
||||
<style:text-properties fo:font-variant="small-caps" fo:color="#008080" loext:opacity="100%" style:text-underline-style="dotted" style:text-underline-width="auto" style:text-underline-color="font-color"/>
|
||||
</style:style>
|
||||
<style:style style:name="Bullet_20_Symbols" style:display-name="Bullet Symbols" style:family="text">
|
||||
<style:text-properties style:font-name="StarSymbol" fo:font-family="StarSymbol" fo:font-size="9pt" style:font-name-asian="StarSymbol" style:font-family-asian="StarSymbol" style:font-size-asian="9pt" style:font-name-complex="StarSymbol" style:font-family-complex="StarSymbol" style:font-size-complex="9pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="Frame" style:family="graphic">
|
||||
<style:graphic-properties text:anchor-type="paragraph" svg:x="0cm" svg:y="0cm" fo:margin-left="0.201cm" fo:margin-right="0.201cm" fo:margin-top="0.201cm" fo:margin-bottom="0.201cm" style:wrap="parallel" style:number-wrapped-paragraphs="no-limit" style:wrap-contour="false" style:vertical-pos="top" style:vertical-rel="paragraph-content" style:horizontal-pos="center" style:horizontal-rel="paragraph-content" fo:background-color="transparent" draw:fill="none" draw:fill-color="#99ccff" fo:padding="0.15cm" fo:border="0.06pt solid #000000"/>
|
||||
</style:style>
|
||||
<text:outline-style style:name="Outline">
|
||||
<text:outline-level-style text:level="1" loext:num-list-format="%1%" style:num-format="">
|
||||
<style:list-level-properties text:min-label-distance="0.381cm"/>
|
||||
</text:outline-level-style>
|
||||
<text:outline-level-style text:level="2" loext:num-list-format="%2%" style:num-format="">
|
||||
<style:list-level-properties text:min-label-distance="0.381cm"/>
|
||||
</text:outline-level-style>
|
||||
<text:outline-level-style text:level="3" loext:num-list-format="%3%" style:num-format="">
|
||||
<style:list-level-properties text:min-label-distance="0.381cm"/>
|
||||
</text:outline-level-style>
|
||||
<text:outline-level-style text:level="4" loext:num-list-format="%4%" style:num-format="">
|
||||
<style:list-level-properties text:min-label-distance="0.381cm"/>
|
||||
</text:outline-level-style>
|
||||
<text:outline-level-style text:level="5" loext:num-list-format="%5%" style:num-format="">
|
||||
<style:list-level-properties text:min-label-distance="0.381cm"/>
|
||||
</text:outline-level-style>
|
||||
<text:outline-level-style text:level="6" loext:num-list-format="%6%" style:num-format="">
|
||||
<style:list-level-properties text:min-label-distance="0.381cm"/>
|
||||
</text:outline-level-style>
|
||||
<text:outline-level-style text:level="7" loext:num-list-format="%7%" style:num-format="">
|
||||
<style:list-level-properties text:min-label-distance="0.381cm"/>
|
||||
</text:outline-level-style>
|
||||
<text:outline-level-style text:level="8" loext:num-list-format="%8%" style:num-format="">
|
||||
<style:list-level-properties text:min-label-distance="0.381cm"/>
|
||||
</text:outline-level-style>
|
||||
<text:outline-level-style text:level="9" loext:num-list-format="%9%" style:num-format="">
|
||||
<style:list-level-properties text:min-label-distance="0.381cm"/>
|
||||
</text:outline-level-style>
|
||||
<text:outline-level-style text:level="10" loext:num-list-format="%10%" style:num-format="">
|
||||
<style:list-level-properties text:min-label-distance="0.381cm"/>
|
||||
</text:outline-level-style>
|
||||
</text:outline-style>
|
||||
<text:notes-configuration text:note-class="footnote" style:num-format="1" text:start-value="0" text:footnotes-position="page" text:start-numbering-at="document"/>
|
||||
<text:notes-configuration text:note-class="endnote" style:num-format="i" text:start-value="0"/>
|
||||
<text:linenumbering-configuration text:number-lines="false" text:offset="0.499cm" style:num-format="1" text:number-position="left" text:increment="5"/>
|
||||
<loext:theme loext:name="Office Theme">
|
||||
<loext:theme-colors loext:name="LibreOffice">
|
||||
<loext:color loext:name="dark1" loext:color="#000000"/>
|
||||
<loext:color loext:name="light1" loext:color="#ffffff"/>
|
||||
<loext:color loext:name="dark2" loext:color="#000000"/>
|
||||
<loext:color loext:name="light2" loext:color="#ffffff"/>
|
||||
<loext:color loext:name="accent1" loext:color="#18a303"/>
|
||||
<loext:color loext:name="accent2" loext:color="#0369a3"/>
|
||||
<loext:color loext:name="accent3" loext:color="#a33e03"/>
|
||||
<loext:color loext:name="accent4" loext:color="#8e03a3"/>
|
||||
<loext:color loext:name="accent5" loext:color="#c99c00"/>
|
||||
<loext:color loext:name="accent6" loext:color="#c9211e"/>
|
||||
<loext:color loext:name="hyperlink" loext:color="#0000ee"/>
|
||||
<loext:color loext:name="followed-hyperlink" loext:color="#551a8b"/>
|
||||
</loext:theme-colors>
|
||||
</loext:theme>
|
||||
</office:styles>
|
||||
<office:automatic-styles>
|
||||
<style:style style:name="Table1" style:family="table">
|
||||
<style:table-properties style:width="16.999cm" fo:margin-left="0cm" fo:margin-right="0cm" fo:margin-top="0.381cm" fo:margin-bottom="0cm" table:align="margins"/>
|
||||
</style:style>
|
||||
<style:style style:name="Table1.A" style:family="table-column">
|
||||
<style:table-column-properties style:column-width="4.683cm" style:rel-column-width="18053*"/>
|
||||
</style:style>
|
||||
<style:style style:name="Table1.C" style:family="table-column">
|
||||
<style:table-column-properties style:column-width="4.685cm" style:rel-column-width="18060*"/>
|
||||
</style:style>
|
||||
<style:style style:name="Table1.D" style:family="table-column">
|
||||
<style:table-column-properties style:column-width="2.949cm" style:rel-column-width="11369*"/>
|
||||
</style:style>
|
||||
<style:style style:name="Table1.A1" style:family="table-cell">
|
||||
<style:table-cell-properties fo:background-color="#cccccc" fo:padding="0.097cm" fo:border-left="0.05pt solid #000000" fo:border-right="none" fo:border-top="0.05pt solid #000000" fo:border-bottom="0.05pt solid #000000">
|
||||
<style:background-image/>
|
||||
</style:table-cell-properties>
|
||||
</style:style>
|
||||
<style:style style:name="Table1.D1" style:family="table-cell">
|
||||
<style:table-cell-properties fo:background-color="#cccccc" fo:padding="0.097cm" fo:border="0.05pt solid #000000">
|
||||
<style:background-image/>
|
||||
</style:table-cell-properties>
|
||||
</style:style>
|
||||
<style:style style:name="Table1.A2" style:family="table-cell">
|
||||
<style:table-cell-properties fo:padding="0.097cm" fo:border-left="0.05pt solid #000000" fo:border-right="none" fo:border-top="none" fo:border-bottom="0.05pt solid #000000"/>
|
||||
</style:style>
|
||||
<style:style style:name="Table1.C2" style:family="table-cell">
|
||||
<style:table-cell-properties fo:padding="0.097cm" fo:border-left="0.05pt solid #000000" fo:border-right="none" fo:border-top="none" fo:border-bottom="0.05pt solid #000000"/>
|
||||
</style:style>
|
||||
<style:style style:name="Table1.D2" style:family="table-cell">
|
||||
<style:table-cell-properties fo:padding="0.097cm" fo:border-left="0.05pt solid #000000" fo:border-right="0.05pt solid #000000" fo:border-top="none" fo:border-bottom="0.05pt solid #000000"/>
|
||||
</style:style>
|
||||
<style:style style:name="Table1.A3" style:family="table-cell">
|
||||
<style:table-cell-properties fo:padding="0.097cm" fo:border-left="0.05pt solid #000000" fo:border-right="none" fo:border-top="none" fo:border-bottom="0.05pt solid #000000"/>
|
||||
</style:style>
|
||||
<style:style style:name="Table1.B3" style:family="table-cell">
|
||||
<style:table-cell-properties fo:padding="0.097cm" fo:border-left="0.05pt solid #000000" fo:border-right="none" fo:border-top="none" fo:border-bottom="0.05pt solid #000000"/>
|
||||
</style:style>
|
||||
<style:style style:name="Table1.C3" style:family="table-cell">
|
||||
<style:table-cell-properties fo:padding="0.097cm" fo:border-left="0.05pt solid #000000" fo:border-right="none" fo:border-top="none" fo:border-bottom="0.05pt solid #000000"/>
|
||||
</style:style>
|
||||
<style:style style:name="Table1.D3" style:family="table-cell">
|
||||
<style:table-cell-properties fo:padding="0.097cm" fo:border-left="0.05pt solid #000000" fo:border-right="0.05pt solid #000000" fo:border-top="none" fo:border-bottom="0.05pt solid #000000"/>
|
||||
</style:style>
|
||||
<style:style style:name="Table1.A4" style:family="table-cell">
|
||||
<style:table-cell-properties fo:padding="0.097cm" fo:border-left="0.05pt solid #000000" fo:border-right="none" fo:border-top="none" fo:border-bottom="0.05pt solid #000000"/>
|
||||
</style:style>
|
||||
<style:style style:name="Table1.C4" style:family="table-cell">
|
||||
<style:table-cell-properties fo:padding="0.097cm" fo:border-left="0.05pt solid #000000" fo:border-right="none" fo:border-top="none" fo:border-bottom="0.05pt solid #000000"/>
|
||||
</style:style>
|
||||
<style:style style:name="Table1.D4" style:family="table-cell">
|
||||
<style:table-cell-properties fo:padding="0.097cm" fo:border-left="0.05pt solid #000000" fo:border-right="0.05pt solid #000000" fo:border-top="none" fo:border-bottom="0.05pt solid #000000"/>
|
||||
</style:style>
|
||||
<style:style style:name="P1" style:family="paragraph" style:parent-style-name="Header">
|
||||
<style:paragraph-properties fo:text-align="center" style:justify-single-word="false"/>
|
||||
<style:text-properties officeooo:paragraph-rsid="0018924f"/>
|
||||
</style:style>
|
||||
<style:style style:name="P2" style:family="paragraph" style:parent-style-name="Footer">
|
||||
<style:paragraph-properties fo:text-align="center" style:justify-single-word="false"/>
|
||||
<style:text-properties officeooo:paragraph-rsid="0018924f"/>
|
||||
</style:style>
|
||||
<style:style style:name="P3" style:family="paragraph" style:parent-style-name="Header">
|
||||
<style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/>
|
||||
<style:text-properties fo:font-size="12pt" officeooo:paragraph-rsid="002055b5" style:font-size-asian="12pt" style:font-size-complex="12pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="P4" style:family="paragraph" style:parent-style-name="Frame_20_contents">
|
||||
<style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/>
|
||||
</style:style>
|
||||
<style:style style:name="P5" style:family="paragraph" style:parent-style-name="Footer">
|
||||
<style:paragraph-properties fo:text-align="end" style:justify-single-word="false"/>
|
||||
</style:style>
|
||||
<style:style style:name="P6" style:family="paragraph" style:parent-style-name="Header">
|
||||
<style:paragraph-properties fo:text-align="center" style:justify-single-word="false"/>
|
||||
<style:text-properties officeooo:paragraph-rsid="0018924f"/>
|
||||
</style:style>
|
||||
<style:style style:name="P7" style:family="paragraph" style:parent-style-name="Footer">
|
||||
<style:paragraph-properties fo:text-align="center" style:justify-single-word="false"/>
|
||||
<style:text-properties officeooo:paragraph-rsid="0018924f"/>
|
||||
</style:style>
|
||||
<style:style style:name="P8" style:family="paragraph" style:parent-style-name="Footer">
|
||||
<style:paragraph-properties fo:text-align="center" style:justify-single-word="false"/>
|
||||
<style:text-properties officeooo:paragraph-rsid="001db22b"/>
|
||||
</style:style>
|
||||
<style:style style:name="P9" style:family="paragraph" style:parent-style-name="Header">
|
||||
<style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/>
|
||||
<style:text-properties fo:font-size="12pt" officeooo:paragraph-rsid="001db22b" style:font-size-asian="12pt" style:font-size-complex="12pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="P10" style:family="paragraph" style:parent-style-name="Header">
|
||||
<style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/>
|
||||
<style:text-properties fo:font-size="12pt" officeooo:paragraph-rsid="0018924f" style:font-size-asian="12pt" style:font-size-complex="12pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="P11" style:family="paragraph" style:parent-style-name="Frame_20_contents">
|
||||
<style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/>
|
||||
</style:style>
|
||||
<style:style style:name="P12" style:family="paragraph" style:parent-style-name="Footer">
|
||||
<style:paragraph-properties fo:text-align="end" style:justify-single-word="false"/>
|
||||
</style:style>
|
||||
<style:style style:name="P13" style:family="paragraph" style:parent-style-name="Table_20_Contents">
|
||||
<style:paragraph-properties fo:text-align="end" style:justify-single-word="false"/>
|
||||
</style:style>
|
||||
<style:style style:name="P14" style:family="paragraph" style:parent-style-name="Table_20_Heading">
|
||||
<style:paragraph-properties fo:text-align="center" style:justify-single-word="false"/>
|
||||
<style:text-properties style:font-name="Liberation Serif"/>
|
||||
</style:style>
|
||||
<style:style style:name="P15" style:family="paragraph" style:parent-style-name="Standard">
|
||||
<style:paragraph-properties fo:break-before="page"/>
|
||||
</style:style>
|
||||
<style:style style:name="P16" style:family="paragraph" style:parent-style-name="Standard">
|
||||
<style:text-properties officeooo:paragraph-rsid="0014daa2"/>
|
||||
</style:style>
|
||||
<style:style style:name="P17" style:family="paragraph" style:parent-style-name="Heading_20_1" style:master-page-name="">
|
||||
<style:paragraph-properties fo:text-align="center" style:justify-single-word="false" style:page-number="auto" fo:break-before="page"/>
|
||||
<style:text-properties style:text-underline-style="solid" style:text-underline-width="auto" style:text-underline-color="font-color"/>
|
||||
</style:style>
|
||||
<style:style style:name="P18" style:family="paragraph" style:parent-style-name="Heading_20_1">
|
||||
<style:paragraph-properties fo:text-align="center" style:justify-single-word="false"/>
|
||||
<style:text-properties style:text-underline-style="solid" style:text-underline-width="auto" style:text-underline-color="font-color"/>
|
||||
</style:style>
|
||||
<style:style style:name="P19" style:family="paragraph" style:parent-style-name="Heading_20_1">
|
||||
<style:paragraph-properties fo:text-align="center" style:justify-single-word="false"/>
|
||||
<style:text-properties style:text-underline-style="solid" style:text-underline-width="auto" style:text-underline-color="font-color" officeooo:paragraph-rsid="001c0678"/>
|
||||
</style:style>
|
||||
<style:style style:name="P20" style:family="paragraph" style:parent-style-name="Standard">
|
||||
<style:text-properties officeooo:paragraph-rsid="001c0678"/>
|
||||
</style:style>
|
||||
<style:style style:name="P21" style:family="paragraph" style:parent-style-name="Frame_20_contents">
|
||||
<style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/>
|
||||
</style:style>
|
||||
<style:style style:name="P22" style:family="paragraph" style:parent-style-name="Header">
|
||||
<style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/>
|
||||
<style:text-properties fo:font-size="12pt" officeooo:paragraph-rsid="002055b5" style:font-size-asian="12pt" style:font-size-complex="12pt"/>
|
||||
</style:style>
|
||||
<style:style style:name="T1" style:family="text">
|
||||
<style:text-properties fo:font-weight="bold" style:font-weight-asian="bold" style:font-weight-complex="bold"/>
|
||||
</style:style>
|
||||
<style:style style:name="T2" style:family="text">
|
||||
<style:text-properties fo:font-weight="bold" officeooo:rsid="001a23ce" style:font-weight-asian="bold" style:font-weight-complex="bold"/>
|
||||
</style:style>
|
||||
<style:style style:name="T3" style:family="text">
|
||||
<style:text-properties fo:font-weight="normal" style:font-weight-asian="normal" style:font-weight-complex="normal"/>
|
||||
</style:style>
|
||||
<style:style style:name="T4" style:family="text">
|
||||
<style:text-properties officeooo:rsid="001c0678"/>
|
||||
</style:style>
|
||||
<style:style style:name="fr1" style:family="graphic" style:parent-style-name="Frame">
|
||||
<style:graphic-properties fo:margin-left="0cm" fo:margin-right="0cm" fo:margin-top="0cm" fo:margin-bottom="0cm" style:wrap="parallel" style:number-wrapped-paragraphs="no-limit" style:vertical-pos="middle" style:vertical-rel="baseline" style:horizontal-pos="left" style:horizontal-rel="paragraph" draw:opacity="100%" fo:padding="0cm" fo:border="none" draw:wrap-influence-on-position="once-concurrent" loext:allow-overlap="true">
|
||||
<style:columns fo:column-count="1" fo:column-gap="0cm"/>
|
||||
</style:graphic-properties>
|
||||
</style:style>
|
||||
<style:page-layout style:name="pm1">
|
||||
<style:page-layout-properties fo:page-width="20.999cm" fo:page-height="29.699cm" style:num-format="1" style:print-orientation="portrait" fo:margin-top="2cm" fo:margin-bottom="2cm" fo:margin-left="2cm" fo:margin-right="2cm" style:writing-mode="lr-tb" style:layout-grid-color="#c0c0c0" style:layout-grid-lines="20" style:layout-grid-base-height="0.706cm" style:layout-grid-ruby-height="0.353cm" style:layout-grid-mode="none" style:layout-grid-ruby-below="false" style:layout-grid-print="false" style:layout-grid-display="false" style:footnote-max-height="0cm" loext:margin-gutter="0cm">
|
||||
<style:footnote-sep style:width="0.018cm" style:distance-before-sep="0.101cm" style:distance-after-sep="0.101cm" style:line-style="none" style:adjustment="left" style:rel-width="25%" style:color="#000000"/>
|
||||
</style:page-layout-properties>
|
||||
<style:header-style>
|
||||
<style:header-footer-properties fo:min-height="0cm" fo:margin-left="0cm" fo:margin-right="0cm" fo:margin-bottom="0.499cm"/>
|
||||
</style:header-style>
|
||||
<style:footer-style>
|
||||
<style:header-footer-properties fo:min-height="0cm" fo:margin-left="0cm" fo:margin-right="0cm" fo:margin-top="0.499cm"/>
|
||||
</style:footer-style>
|
||||
</style:page-layout>
|
||||
<style:style style:name="dp1" style:family="drawing-page">
|
||||
<style:drawing-page-properties draw:background-size="full"/>
|
||||
</style:style>
|
||||
</office:automatic-styles>
|
||||
<office:master-styles>
|
||||
<style:master-page style:name="Standard" style:page-layout-name="pm1" draw:style-name="dp1">
|
||||
<style:header>
|
||||
<text:p text:style-name="P1"><text:placeholder text:placeholder-type="text"><if test="company and company.header"></text:placeholder></text:p>
|
||||
<text:p text:style-name="P1"><text:placeholder text:placeholder-type="text"><for each="line in company.header_used.split('\n')"></text:placeholder></text:p>
|
||||
<text:p text:style-name="P1"><text:placeholder text:placeholder-type="text"><line></text:placeholder></text:p>
|
||||
<text:p text:style-name="P1"><text:placeholder text:placeholder-type="text"></for></text:placeholder></text:p>
|
||||
<text:p text:style-name="P2"><text:placeholder text:placeholder-type="text"></if></text:placeholder></text:p>
|
||||
<text:p text:style-name="P3"><text:placeholder text:placeholder-type="text"><choose></text:placeholder></text:p>
|
||||
<text:p text:style-name="P3"><text:placeholder text:placeholder-type="text"><when test="company and company.logo"></text:placeholder></text:p>
|
||||
<text:p text:style-name="P3"><draw:frame draw:style-name="fr1" draw:name="image:company.get_logo_cm(7, 3.5)" text:anchor-type="as-char" svg:width="7.001cm" draw:z-index="2">
|
||||
<draw:text-box fo:min-height="3cm">
|
||||
<text:p text:style-name="P4"/>
|
||||
</draw:text-box>
|
||||
</draw:frame></text:p>
|
||||
<text:p text:style-name="P3"><text:placeholder text:placeholder-type="text"></when></text:placeholder></text:p>
|
||||
<text:p text:style-name="P3"><text:placeholder text:placeholder-type="text"><when test="company"></text:placeholder></text:p>
|
||||
<text:p text:style-name="P3"><text:placeholder text:placeholder-type="text"><company.rec_name></text:placeholder></text:p>
|
||||
<text:p text:style-name="P3"><text:placeholder text:placeholder-type="text"></when></text:placeholder></text:p>
|
||||
<text:p text:style-name="P3"><text:placeholder text:placeholder-type="text"></choose></text:placeholder></text:p>
|
||||
</style:header>
|
||||
<style:footer>
|
||||
<text:p text:style-name="P2"><text:placeholder text:placeholder-type="text"><if test="company and company.footer"></text:placeholder></text:p>
|
||||
<text:p text:style-name="P2"><text:placeholder text:placeholder-type="text"><for each="line in company.footer_used.split('\n')"></text:placeholder></text:p>
|
||||
<text:p text:style-name="P2"><text:placeholder text:placeholder-type="text"><line></text:placeholder></text:p>
|
||||
<text:p text:style-name="P2"><text:placeholder text:placeholder-type="text"></for></text:placeholder></text:p>
|
||||
<text:p text:style-name="P2"><text:placeholder text:placeholder-type="text"></if></text:placeholder></text:p>
|
||||
<text:p text:style-name="P5"><text:page-number text:select-page="current">3</text:page-number>/<text:page-count>3</text:page-count></text:p>
|
||||
</style:footer>
|
||||
</style:master-page>
|
||||
</office:master-styles>
|
||||
<office:body>
|
||||
<office:text text:use-soft-page-breaks="true">
|
||||
<office:forms form:automatic-focus="false" form:apply-design-mode="false"/>
|
||||
<text:sequence-decls>
|
||||
<text:sequence-decl text:display-outline-level="0" text:name="Illustration"/>
|
||||
<text:sequence-decl text:display-outline-level="0" text:name="Table"/>
|
||||
<text:sequence-decl text:display-outline-level="0" text:name="Text"/>
|
||||
<text:sequence-decl text:display-outline-level="0" text:name="Drawing"/>
|
||||
<text:sequence-decl text:display-outline-level="0" text:name="Figure"/>
|
||||
</text:sequence-decls>
|
||||
<text:p text:style-name="P15"><text:placeholder text:placeholder-type="text"><for each="shipment in records"></text:placeholder></text:p>
|
||||
<text:p text:style-name="P15"><text:placeholder text:placeholder-type="text"><choose test="shipment.state"></text:placeholder></text:p>
|
||||
<text:p text:style-name="Standard"><text:placeholder text:placeholder-type="text"><when test="'draft'"></text:placeholder></text:p>
|
||||
<text:p text:style-name="P19"><text:span text:style-name="T4">Draft </text:span>Restocking List</text:p>
|
||||
<text:p text:style-name="Standard"><text:placeholder text:placeholder-type="text"></when></text:placeholder></text:p>
|
||||
<text:p text:style-name="P20"><text:placeholder text:placeholder-type="text"><when test="'cancelled'"></text:placeholder></text:p>
|
||||
<text:p text:style-name="P19"><text:span text:style-name="T4">Cancelled </text:span>Restocking List</text:p>
|
||||
<text:p text:style-name="P20"><text:placeholder text:placeholder-type="text"></when></text:placeholder></text:p>
|
||||
<text:p text:style-name="Standard"><text:placeholder text:placeholder-type="text"><otherwise></text:placeholder></text:p>
|
||||
<text:p text:style-name="P18">Restocking List No: <text:span text:style-name="T4"><text:placeholder text:placeholder-type="text"><shipment.number></text:placeholder></text:span></text:p>
|
||||
<text:p text:style-name="Standard"><text:placeholder text:placeholder-type="text"></otherwise></text:placeholder></text:p>
|
||||
<text:p text:style-name="Standard"><text:placeholder text:placeholder-type="text"></choose></text:placeholder></text:p>
|
||||
<text:p text:style-name="Standard"><text:span text:style-name="T1">Reference:</text:span><text:span text:style-name="T3"> </text:span><text:span text:style-name="T3"><text:placeholder text:placeholder-type="text"><shipment.origins or ''></text:placeholder></text:span><text:span text:style-name="T3"><text:placeholder text:placeholder-type="text"><', ' if (shipment.origins and shipment.reference) else ''></text:placeholder></text:span><text:span text:style-name="T3"><text:placeholder text:placeholder-type="text"><shipment.reference or ''></text:placeholder></text:span></text:p>
|
||||
<text:p text:style-name="Standard"><text:span text:style-name="T1">Supplier:</text:span><text:span text:style-name="T3"> </text:span><text:span text:style-name="T3"><text:placeholder text:placeholder-type="text"><shipment.supplier.rec_name></text:placeholder></text:span></text:p>
|
||||
<text:p text:style-name="Standard"><text:span text:style-name="T1">Planned Date:</text:span><text:span text:style-name="T3"> </text:span><text:span text:style-name="T3"><text:placeholder text:placeholder-type="text"><shipment.planned_date and format_date(shipment.planned_date, user.language) or ''></text:placeholder></text:span></text:p>
|
||||
<text:p text:style-name="Standard"><text:span text:style-name="T1">Warehouse:</text:span><text:span text:style-name="T3"> </text:span><text:span text:style-name="T3"><text:placeholder text:placeholder-type="text"><shipment.warehouse.rec_name></text:placeholder></text:span></text:p>
|
||||
<table:table table:name="Table1" table:style-name="Table1">
|
||||
<table:table-column table:style-name="Table1.A" table:number-columns-repeated="2"/>
|
||||
<table:table-column table:style-name="Table1.C"/>
|
||||
<table:table-column table:style-name="Table1.D"/>
|
||||
<table:table-header-rows>
|
||||
<table:table-row>
|
||||
<table:table-cell table:style-name="Table1.A1" office:value-type="string">
|
||||
<text:p text:style-name="P14">From Location</text:p>
|
||||
</table:table-cell>
|
||||
<table:table-cell table:style-name="Table1.A1" office:value-type="string">
|
||||
<text:p text:style-name="P14">To Location</text:p>
|
||||
</table:table-cell>
|
||||
<table:table-cell table:style-name="Table1.A1" office:value-type="string">
|
||||
<text:p text:style-name="P14">Product</text:p>
|
||||
</table:table-cell>
|
||||
<table:table-cell table:style-name="Table1.D1" office:value-type="string">
|
||||
<text:p text:style-name="P14">Quantity</text:p>
|
||||
</table:table-cell>
|
||||
</table:table-row>
|
||||
</table:table-header-rows>
|
||||
<table:table-row>
|
||||
<table:table-cell table:style-name="Table1.A2" table:number-columns-spanned="2" office:value-type="string">
|
||||
<text:p text:style-name="Table_20_Contents"><text:placeholder text:placeholder-type="text"><for each="move in moves(shipment)"></text:placeholder></text:p>
|
||||
</table:table-cell>
|
||||
<table:covered-table-cell/>
|
||||
<table:table-cell table:style-name="Table1.C2" office:value-type="string">
|
||||
<text:p text:style-name="Table_20_Contents"/>
|
||||
</table:table-cell>
|
||||
<table:table-cell table:style-name="Table1.D2" office:value-type="string">
|
||||
<text:p text:style-name="Table_20_Contents"/>
|
||||
</table:table-cell>
|
||||
</table:table-row>
|
||||
<table:table-row>
|
||||
<table:table-cell table:style-name="Table1.A3" office:value-type="string">
|
||||
<text:p text:style-name="Table_20_Contents"><text:placeholder text:placeholder-type="text"><move.from_location_name></text:placeholder></text:p>
|
||||
</table:table-cell>
|
||||
<table:table-cell table:style-name="Table1.A3" office:value-type="string">
|
||||
<text:p text:style-name="Table_20_Contents"><text:placeholder text:placeholder-type="text"><move.to_location_name></text:placeholder></text:p>
|
||||
</table:table-cell>
|
||||
<table:table-cell table:style-name="Table1.C2" office:value-type="string">
|
||||
<text:p text:style-name="Table_20_Contents"><text:placeholder text:placeholder-type="text"><move.product.rec_name></text:placeholder></text:p>
|
||||
</table:table-cell>
|
||||
<table:table-cell table:style-name="Table1.D2" office:value-type="string">
|
||||
<text:p text:style-name="P13"><text:placeholder text:placeholder-type="text"><format_number_symbol(move.quantity, user.language, move.unit, digits=move.unit.digits)></text:placeholder><text:soft-page-break/></text:p>
|
||||
</table:table-cell>
|
||||
</table:table-row>
|
||||
<table:table-row>
|
||||
<table:table-cell table:style-name="Table1.A2" table:number-columns-spanned="2" office:value-type="string">
|
||||
<text:p text:style-name="Table_20_Contents"><text:placeholder text:placeholder-type="text"></for></text:placeholder></text:p>
|
||||
</table:table-cell>
|
||||
<table:covered-table-cell/>
|
||||
<table:table-cell table:style-name="Table1.C2" office:value-type="string">
|
||||
<text:p text:style-name="Table_20_Contents"/>
|
||||
</table:table-cell>
|
||||
<table:table-cell table:style-name="Table1.D2" office:value-type="string">
|
||||
<text:p text:style-name="Table_20_Contents"/>
|
||||
</table:table-cell>
|
||||
</table:table-row>
|
||||
</table:table>
|
||||
<text:p text:style-name="Text_20_body"><text:placeholder text:placeholder-type="text"></for></text:placeholder></text:p>
|
||||
</office:text>
|
||||
</office:body>
|
||||
</office:document>
|
||||
2
modules/stock/tests/__init__.py
Normal file
2
modules/stock/tests/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
BIN
modules/stock/tests/__pycache__/__init__.cpython-311.pyc
Normal file
BIN
modules/stock/tests/__pycache__/__init__.cpython-311.pyc
Normal file
Binary file not shown.
BIN
modules/stock/tests/__pycache__/test_module.cpython-311.pyc
Normal file
BIN
modules/stock/tests/__pycache__/test_module.cpython-311.pyc
Normal file
Binary file not shown.
BIN
modules/stock/tests/__pycache__/test_scenario.cpython-311.pyc
Normal file
BIN
modules/stock/tests/__pycache__/test_scenario.cpython-311.pyc
Normal file
Binary file not shown.
246
modules/stock/tests/scenario_stock_average_cost_price.rst
Normal file
246
modules/stock/tests/scenario_stock_average_cost_price.rst
Normal file
@@ -0,0 +1,246 @@
|
||||
========================
|
||||
Stock Average Cost Price
|
||||
========================
|
||||
|
||||
Imports::
|
||||
|
||||
>>> import datetime as dt
|
||||
>>> from decimal import Decimal
|
||||
|
||||
>>> from proteus import Model, Wizard
|
||||
>>> from trytond.modules.company.tests.tools import create_company
|
||||
>>> from trytond.modules.currency.tests.tools import get_currency
|
||||
>>> from trytond.tests.tools import activate_modules
|
||||
|
||||
>>> today = dt.date.today()
|
||||
>>> next_day = today + dt.timedelta(days=1)
|
||||
|
||||
Activate modules::
|
||||
|
||||
>>> config = activate_modules('stock', create_company)
|
||||
|
||||
Get currency::
|
||||
|
||||
>>> currency = get_currency()
|
||||
|
||||
Create product::
|
||||
|
||||
>>> ProductUom = Model.get('product.uom')
|
||||
>>> ProductTemplate = Model.get('product.template')
|
||||
>>> Product = Model.get('product.product')
|
||||
>>> unit, = ProductUom.find([('name', '=', 'Unit')])
|
||||
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = 'Product'
|
||||
>>> template.default_uom = unit
|
||||
>>> template.type = 'goods'
|
||||
>>> template.list_price = Decimal('300')
|
||||
>>> template.cost_price_method = 'average'
|
||||
>>> product, = template.products
|
||||
>>> product.cost_price = Decimal('80')
|
||||
>>> template.save()
|
||||
>>> product, = template.products
|
||||
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = 'Negative Product'
|
||||
>>> template.default_uom = unit
|
||||
>>> template.type = 'goods'
|
||||
>>> template.list_price = Decimal('28')
|
||||
>>> template.cost_price_method = 'average'
|
||||
>>> negative_product, = template.products
|
||||
>>> negative_product.cost_price = Decimal('5.0000')
|
||||
>>> template.save()
|
||||
>>> negative_product, = template.products
|
||||
|
||||
Get stock locations::
|
||||
|
||||
>>> Location = Model.get('stock.location')
|
||||
>>> supplier_loc, = Location.find([('code', '=', 'SUP')])
|
||||
>>> storage_loc, = Location.find([('code', '=', 'STO')])
|
||||
>>> storage_sub_loc = Location(
|
||||
... name="Storage Sub", type='storage', parent=storage_loc)
|
||||
>>> storage_sub_loc.save()
|
||||
>>> customer_loc, = Location.find([('code', '=', 'CUS')])
|
||||
|
||||
Make 1 unit of the product available @ 100 ::
|
||||
|
||||
>>> StockMove = Model.get('stock.move')
|
||||
>>> incoming_move = StockMove()
|
||||
>>> incoming_move.product = product
|
||||
>>> incoming_move.unit = unit
|
||||
>>> incoming_move.quantity = 1
|
||||
>>> incoming_move.from_location = supplier_loc
|
||||
>>> incoming_move.to_location = storage_sub_loc
|
||||
>>> incoming_move.planned_date = today
|
||||
>>> incoming_move.effective_date = today
|
||||
>>> incoming_move.unit_price = Decimal('100')
|
||||
>>> incoming_move.currency = currency
|
||||
>>> incoming_move.click('do')
|
||||
|
||||
Check Cost Price is 100::
|
||||
|
||||
>>> product.reload()
|
||||
>>> product.cost_price
|
||||
Decimal('100.0000')
|
||||
|
||||
Add 1 more unit @ 200::
|
||||
|
||||
>>> incoming_move = StockMove()
|
||||
>>> incoming_move.product = product
|
||||
>>> incoming_move.unit = unit
|
||||
>>> incoming_move.quantity = 1
|
||||
>>> incoming_move.from_location = supplier_loc
|
||||
>>> incoming_move.to_location = storage_loc
|
||||
>>> incoming_move.planned_date = today
|
||||
>>> incoming_move.effective_date = today
|
||||
>>> incoming_move.unit_price = Decimal('200')
|
||||
>>> incoming_move.currency = currency
|
||||
>>> incoming_move.click('do')
|
||||
|
||||
Check Cost Price Average is 150::
|
||||
|
||||
>>> product.reload()
|
||||
>>> product.cost_price
|
||||
Decimal('150.0000')
|
||||
|
||||
Add twice 1 more unit @ 200::
|
||||
|
||||
>>> incoming_moves = []
|
||||
>>> incoming_move = StockMove()
|
||||
>>> incoming_move.product = product
|
||||
>>> incoming_move.unit = unit
|
||||
>>> incoming_move.quantity = 1
|
||||
>>> incoming_move.from_location = supplier_loc
|
||||
>>> incoming_move.to_location = storage_loc
|
||||
>>> incoming_move.planned_date = today
|
||||
>>> incoming_move.effective_date = today
|
||||
>>> incoming_move.unit_price = Decimal('200')
|
||||
>>> incoming_move.currency = currency
|
||||
>>> incoming_move.save()
|
||||
>>> incoming_moves.append(incoming_move)
|
||||
|
||||
>>> incoming_move = StockMove()
|
||||
>>> incoming_move.product = product
|
||||
>>> incoming_move.unit = unit
|
||||
>>> incoming_move.quantity = 1
|
||||
>>> incoming_move.from_location = supplier_loc
|
||||
>>> incoming_move.to_location = storage_loc
|
||||
>>> incoming_move.planned_date = today
|
||||
>>> incoming_move.effective_date = today
|
||||
>>> incoming_move.unit_price = Decimal('200')
|
||||
>>> incoming_move.currency = currency
|
||||
>>> incoming_move.save()
|
||||
>>> incoming_moves.append(incoming_move)
|
||||
|
||||
>>> StockMove.click(incoming_moves, 'do')
|
||||
|
||||
Check Cost Price Average is 175::
|
||||
|
||||
>>> product.reload()
|
||||
>>> product.cost_price
|
||||
Decimal('175.0000')
|
||||
|
||||
Reduce Cost Price by 80%, to force to write recomputed price later::
|
||||
|
||||
>>> modify_cost_price = Wizard('product.modify_cost_price', [product])
|
||||
>>> modify_cost_price.form.cost_price = 'cost_price * 0.8'
|
||||
>>> modify_cost_price.form.date = next_day
|
||||
>>> modify_cost_price.execute('modify')
|
||||
>>> product.cost_price
|
||||
Decimal('140.0000')
|
||||
|
||||
Increase Cost Price by 10% using Template wizard::
|
||||
|
||||
>>> modify_cost_price = Wizard(
|
||||
... 'product.modify_cost_price', [product.template])
|
||||
>>> modify_cost_price.form.cost_price = 'cost_price * 1.1'
|
||||
>>> modify_cost_price.form.date = next_day
|
||||
>>> modify_cost_price.execute('modify')
|
||||
>>> product.reload()
|
||||
>>> product.cost_price
|
||||
Decimal('154.0000')
|
||||
|
||||
Send one product we don't have in stock::
|
||||
|
||||
>>> outgoing_move = StockMove()
|
||||
>>> outgoing_move.product = negative_product
|
||||
>>> outgoing_move.unit = unit
|
||||
>>> outgoing_move.quantity = 1
|
||||
>>> outgoing_move.unit_price = Decimal('28')
|
||||
>>> outgoing_move.from_location = storage_loc
|
||||
>>> outgoing_move.to_location = customer_loc
|
||||
>>> outgoing_move.planned_date = today
|
||||
>>> outgoing_move.effective_date = today
|
||||
>>> outgoing_move.currency = currency
|
||||
>>> outgoing_move.click('do')
|
||||
|
||||
Cost price should stay 5::
|
||||
|
||||
>>> negative_product.cost_price
|
||||
Decimal('5.0000')
|
||||
|
||||
Return one product to the supplier::
|
||||
|
||||
>>> outgoing_move = StockMove()
|
||||
>>> outgoing_move.product = negative_product
|
||||
>>> outgoing_move.unit = unit
|
||||
>>> outgoing_move.quantity = 1
|
||||
>>> outgoing_move.unit_price = Decimal('28')
|
||||
>>> outgoing_move.currency = currency
|
||||
>>> outgoing_move.from_location = storage_loc
|
||||
>>> outgoing_move.to_location = supplier_loc
|
||||
>>> outgoing_move.planned_date = today
|
||||
>>> outgoing_move.effective_date = today
|
||||
>>> outgoing_move.click('do')
|
||||
|
||||
Cost price should stay 5::
|
||||
|
||||
>>> negative_product.cost_price
|
||||
Decimal('5.0000')
|
||||
|
||||
Receive one unit of the product with negative stock so the stock stays negative::
|
||||
|
||||
>>> incoming_move = StockMove()
|
||||
>>> incoming_move.product = negative_product
|
||||
>>> incoming_move.unit = unit
|
||||
>>> incoming_move.quantity = 1
|
||||
>>> incoming_move.from_location = supplier_loc
|
||||
>>> incoming_move.to_location = storage_loc
|
||||
>>> incoming_move.planned_date = today
|
||||
>>> incoming_move.effective_date = today
|
||||
>>> incoming_move.unit_price = Decimal('3')
|
||||
>>> incoming_move.currency = currency
|
||||
>>> incoming_move.click('do')
|
||||
|
||||
Cost price should be set to last unit price::
|
||||
|
||||
>>> negative_product.reload()
|
||||
>>> negative_product.cost_price
|
||||
Decimal('3.0000')
|
||||
|
||||
Receive two units of the product so the stock becomes positive::
|
||||
|
||||
>>> incoming_move = StockMove()
|
||||
>>> incoming_move.product = negative_product
|
||||
>>> incoming_move.unit = unit
|
||||
>>> incoming_move.quantity = 2
|
||||
>>> incoming_move.from_location = supplier_loc
|
||||
>>> incoming_move.to_location = storage_loc
|
||||
>>> incoming_move.planned_date = today
|
||||
>>> incoming_move.effective_date = today
|
||||
>>> incoming_move.unit_price = Decimal('2')
|
||||
>>> incoming_move.currency = currency
|
||||
>>> incoming_move.click('do')
|
||||
|
||||
Cost price should be set to last unit price::
|
||||
|
||||
>>> negative_product.reload()
|
||||
>>> negative_product.cost_price
|
||||
Decimal('2.0000')
|
||||
|
||||
Recompute Cost Price::
|
||||
|
||||
>>> recompute = Wizard('product.recompute_cost_price', [negative_product])
|
||||
>>> recompute.execute('recompute')
|
||||
>>> negative_product.cost_price
|
||||
Decimal('2.0000')
|
||||
250
modules/stock/tests/scenario_stock_inventory.rst
Normal file
250
modules/stock/tests/scenario_stock_inventory.rst
Normal file
@@ -0,0 +1,250 @@
|
||||
========================
|
||||
Stock Inventory Scenario
|
||||
========================
|
||||
|
||||
Imports::
|
||||
|
||||
>>> import datetime as dt
|
||||
>>> from decimal import Decimal
|
||||
|
||||
>>> from proteus import Model
|
||||
>>> from trytond.modules.company.tests.tools import create_company
|
||||
>>> from trytond.modules.currency.tests.tools import get_currency
|
||||
>>> from trytond.tests.tools import activate_modules, assertEqual
|
||||
|
||||
>>> today = dt.date.today()
|
||||
|
||||
Activate modules::
|
||||
|
||||
>>> config = activate_modules('stock', create_company)
|
||||
|
||||
Get currency::
|
||||
|
||||
>>> currency = get_currency()
|
||||
|
||||
Get stock locations::
|
||||
|
||||
>>> Location = Model.get('stock.location')
|
||||
>>> supplier_loc, = Location.find([('code', '=', 'SUP')])
|
||||
>>> storage_loc, = Location.find([('code', '=', 'STO')])
|
||||
>>> customer_loc, = Location.find([('code', '=', 'CUS')])
|
||||
>>> lost_found_loc, = Location.find([('type', '=', 'lost_found')])
|
||||
|
||||
Create products::
|
||||
|
||||
>>> ProductUom = Model.get('product.uom')
|
||||
>>> ProductTemplate = Model.get('product.template')
|
||||
|
||||
>>> unit, = ProductUom.find([('name', '=', 'Unit')])
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = 'Product'
|
||||
>>> template.default_uom = unit
|
||||
>>> template.type = 'goods'
|
||||
>>> template.list_price = Decimal('300')
|
||||
>>> template.cost_price_method = 'average'
|
||||
>>> product, = template.products
|
||||
>>> product.cost_price = Decimal('80')
|
||||
>>> template.save()
|
||||
>>> product, = template.products
|
||||
|
||||
>>> kg, = ProductUom.find([('name', '=', 'Kilogram')])
|
||||
>>> template2 = ProductTemplate()
|
||||
>>> template2.name = 'Product'
|
||||
>>> template2.default_uom = kg
|
||||
>>> template2.type = 'goods'
|
||||
>>> template2.list_price = Decimal('140')
|
||||
>>> template2.cost_price_method = 'average'
|
||||
>>> product2, = template2.products
|
||||
>>> product2.cost_price = Decimal('60')
|
||||
>>> template2.save()
|
||||
>>> product2, = template2.products
|
||||
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = 'Product'
|
||||
>>> template.default_uom = unit
|
||||
>>> template.type = 'goods'
|
||||
>>> template.consumable = True
|
||||
>>> template.list_price = Decimal('300')
|
||||
>>> template.cost_price_method = 'average'
|
||||
>>> consumable, = template.products
|
||||
>>> consumable.cost_price = Decimal('80')
|
||||
>>> template.save()
|
||||
>>> consumable, = template.products
|
||||
|
||||
Fill storage::
|
||||
|
||||
>>> StockMove = Model.get('stock.move')
|
||||
>>> incoming_move = StockMove()
|
||||
>>> incoming_move.product = product
|
||||
>>> incoming_move.unit = unit
|
||||
>>> incoming_move.quantity = 1
|
||||
>>> incoming_move.from_location = supplier_loc
|
||||
>>> incoming_move.to_location = storage_loc
|
||||
>>> incoming_move.planned_date = today
|
||||
>>> incoming_move.effective_date = today
|
||||
>>> incoming_move.unit_price = Decimal('100')
|
||||
>>> incoming_move.currency = currency
|
||||
>>> incoming_moves = [incoming_move]
|
||||
|
||||
>>> incoming_move = StockMove()
|
||||
>>> incoming_move.product = product2
|
||||
>>> incoming_move.unit = kg
|
||||
>>> incoming_move.quantity = 2.5
|
||||
>>> incoming_move.from_location = supplier_loc
|
||||
>>> incoming_move.to_location = storage_loc
|
||||
>>> incoming_move.planned_date = today
|
||||
>>> incoming_move.effective_date = today
|
||||
>>> incoming_move.unit_price = Decimal('70')
|
||||
>>> incoming_move.currency = currency
|
||||
>>> incoming_moves.append(incoming_move)
|
||||
>>> StockMove.click(incoming_moves, 'do')
|
||||
|
||||
Create an inventory::
|
||||
|
||||
>>> Inventory = Model.get('stock.inventory')
|
||||
>>> inventory = Inventory()
|
||||
>>> inventory.location = storage_loc
|
||||
>>> inventory.empty_quantity = 'keep'
|
||||
>>> inventory.save()
|
||||
>>> inventory.click('complete_lines')
|
||||
>>> line_by_product = {l.product.id: l for l in inventory.lines}
|
||||
>>> line_p1 = line_by_product[product.id]
|
||||
>>> line_p1.expected_quantity
|
||||
1.0
|
||||
>>> line_p1.quantity = 3
|
||||
>>> line_p2 = line_by_product[product2.id]
|
||||
>>> line_p2.expected_quantity
|
||||
2.5
|
||||
>>> inventory.save()
|
||||
|
||||
Fill storage with more quantities::
|
||||
|
||||
>>> incoming_move = StockMove()
|
||||
>>> incoming_move.product = product
|
||||
>>> incoming_move.unit = unit
|
||||
>>> incoming_move.quantity = 1
|
||||
>>> incoming_move.from_location = supplier_loc
|
||||
>>> incoming_move.to_location = storage_loc
|
||||
>>> incoming_move.planned_date = today
|
||||
>>> incoming_move.effective_date = today
|
||||
>>> incoming_move.unit_price = Decimal('100')
|
||||
>>> incoming_move.currency = currency
|
||||
>>> incoming_moves = [incoming_move]
|
||||
|
||||
>>> incoming_move = StockMove()
|
||||
>>> incoming_move.product = product2
|
||||
>>> incoming_move.unit = kg
|
||||
>>> incoming_move.quantity = 1.3
|
||||
>>> incoming_move.from_location = supplier_loc
|
||||
>>> incoming_move.to_location = storage_loc
|
||||
>>> incoming_move.planned_date = today
|
||||
>>> incoming_move.effective_date = today
|
||||
>>> incoming_move.unit_price = Decimal('70')
|
||||
>>> incoming_move.currency = currency
|
||||
>>> incoming_moves.append(incoming_move)
|
||||
>>> StockMove.click(incoming_moves, 'do')
|
||||
|
||||
Update the inventory::
|
||||
|
||||
>>> inventory.click('complete_lines')
|
||||
>>> line_p1.reload()
|
||||
>>> line_p1.expected_quantity
|
||||
2.0
|
||||
>>> line_p1.quantity
|
||||
3.0
|
||||
>>> line_p2.reload()
|
||||
>>> line_p2.expected_quantity
|
||||
3.8
|
||||
>>> line_p2.quantity = 3.8
|
||||
>>> line_p2.save()
|
||||
|
||||
Confirm the inventory::
|
||||
|
||||
>>> inventory.click('confirm')
|
||||
>>> line_p1.reload()
|
||||
>>> line_p1.expected_quantity
|
||||
2.0
|
||||
>>> move, = line_p1.moves
|
||||
>>> move.quantity
|
||||
1.0
|
||||
>>> assertEqual(move.from_location, lost_found_loc)
|
||||
>>> assertEqual(move.to_location, inventory.location)
|
||||
>>> line_p2.reload()
|
||||
>>> len(line_p2.moves)
|
||||
0
|
||||
|
||||
Creating an inventory with empty quantities::
|
||||
|
||||
>>> inventory = Inventory()
|
||||
>>> inventory.location = storage_loc
|
||||
>>> inventory.empty_quantity = 'keep'
|
||||
>>> line = inventory.lines.new()
|
||||
>>> line.product = product
|
||||
>>> inventory.click('confirm')
|
||||
>>> line, = inventory.lines
|
||||
>>> len(line.moves)
|
||||
0
|
||||
|
||||
Empty storage::
|
||||
|
||||
>>> Inventory = Model.get('stock.inventory')
|
||||
>>> inventory = Inventory()
|
||||
>>> inventory.location = storage_loc
|
||||
>>> inventory.empty_quantity = 'keep'
|
||||
>>> line = inventory.lines.new()
|
||||
>>> line.product = product
|
||||
>>> line.quantity = 0
|
||||
>>> line = inventory.lines.new()
|
||||
>>> line.product = product2
|
||||
>>> line.quantity = 0
|
||||
>>> inventory.save()
|
||||
>>> line_p1, line_p2 = inventory.lines
|
||||
>>> line_p1.quantity
|
||||
0.0
|
||||
>>> line_p1.expected_quantity
|
||||
3.0
|
||||
>>> line_p2.quantity
|
||||
0.0
|
||||
>>> line_p2.expected_quantity
|
||||
3.8
|
||||
>>> inventory.click('confirm')
|
||||
|
||||
Add quantity of consumable product::
|
||||
|
||||
>>> inventory = Inventory()
|
||||
>>> inventory.location = storage_loc
|
||||
>>> inventory.empty_quantity = 'keep'
|
||||
>>> line = inventory.lines.new()
|
||||
>>> line.product = consumable
|
||||
>>> line.quantity = 5.0
|
||||
>>> inventory.click('complete_lines')
|
||||
>>> len(inventory.lines)
|
||||
1
|
||||
>>> inventory.click('confirm')
|
||||
>>> line, = inventory.lines
|
||||
>>> move, = line.moves
|
||||
>>> move.quantity
|
||||
5.0
|
||||
>>> assertEqual(move.from_location, lost_found_loc)
|
||||
>>> assertEqual(move.to_location, inventory.location)
|
||||
|
||||
Create an inventory that should be empty after completion::
|
||||
|
||||
>>> Inventory = Model.get('stock.inventory')
|
||||
>>> inventory = Inventory()
|
||||
>>> inventory.location = storage_loc
|
||||
>>> inventory.empty_quantity = 'keep'
|
||||
>>> inventory.click('complete_lines')
|
||||
>>> len(inventory.lines)
|
||||
0
|
||||
|
||||
Create an inventory and check rec_name::
|
||||
|
||||
>>> Inventory = Model.get('stock.inventory')
|
||||
>>> inventory = Inventory()
|
||||
>>> inventory.date = dt.date(2023, 1, 31)
|
||||
>>> inventory.location = storage_loc
|
||||
>>> inventory.empty_quantity = 'keep'
|
||||
>>> inventory.save()
|
||||
>>> inventory.rec_name
|
||||
'[6] [STO] Storage Zone @ 01/31/2023'
|
||||
111
modules/stock/tests/scenario_stock_inventory_count.rst
Normal file
111
modules/stock/tests/scenario_stock_inventory_count.rst
Normal file
@@ -0,0 +1,111 @@
|
||||
==============================
|
||||
Stock Inventory Count Scenario
|
||||
==============================
|
||||
|
||||
Imports::
|
||||
|
||||
>>> from decimal import Decimal
|
||||
|
||||
>>> from proteus import Model
|
||||
>>> from trytond.modules.company.tests.tools import create_company
|
||||
>>> from trytond.tests.tools import activate_modules
|
||||
|
||||
Activate modules::
|
||||
|
||||
>>> config = activate_modules('stock', create_company)
|
||||
|
||||
Get stock locations::
|
||||
|
||||
>>> Location = Model.get('stock.location')
|
||||
>>> supplier_loc, = Location.find([('code', '=', 'SUP')])
|
||||
>>> storage_loc, = Location.find([('code', '=', 'STO')])
|
||||
>>> customer_loc, = Location.find([('code', '=', 'CUS')])
|
||||
|
||||
Create products::
|
||||
|
||||
>>> ProductUom = Model.get('product.uom')
|
||||
>>> ProductTemplate = Model.get('product.template')
|
||||
|
||||
>>> unit, = ProductUom.find([('name', '=', 'Unit')])
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = 'Product'
|
||||
>>> template.default_uom = unit
|
||||
>>> template.type = 'goods'
|
||||
>>> template.list_price = Decimal('300')
|
||||
>>> template.cost_price_method = 'average'
|
||||
>>> product, = template.products
|
||||
>>> product.cost_price = Decimal('80')
|
||||
>>> template.save()
|
||||
>>> product, = template.products
|
||||
|
||||
>>> kg, = ProductUom.find([('name', '=', 'Kilogram')])
|
||||
>>> template2 = ProductTemplate()
|
||||
>>> template2.name = 'Product'
|
||||
>>> template2.default_uom = kg
|
||||
>>> template2.type = 'goods'
|
||||
>>> template2.list_price = Decimal('140')
|
||||
>>> template2.cost_price_method = 'average'
|
||||
>>> product2, = template2.products
|
||||
>>> product2.cost_price = Decimal('60')
|
||||
>>> template2.save()
|
||||
>>> product2, = template2.products
|
||||
|
||||
Create an inventory::
|
||||
|
||||
>>> Inventory = Model.get('stock.inventory')
|
||||
>>> inventory = Inventory()
|
||||
>>> inventory.location = storage_loc
|
||||
>>> inventory.empty_quantity = 'keep'
|
||||
>>> inventory.save()
|
||||
|
||||
Count inventory::
|
||||
|
||||
>>> count = inventory.click('do_count')
|
||||
|
||||
>>> count.form.search = product
|
||||
|
||||
>>> count.execute('quantity')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
InventoryCountWarning: ...
|
||||
|
||||
>>> Model.get('res.user.warning')(user=config.user,
|
||||
... name='stock.inventory,%s.product.product,%s.count_create' % (
|
||||
... inventory.id, product.id)).save()
|
||||
>>> count.execute('quantity')
|
||||
>>> count.form.quantity
|
||||
1.0
|
||||
>>> count.form.total_quantity
|
||||
1.0
|
||||
>>> count.execute('add')
|
||||
|
||||
>>> count.form.search = product
|
||||
>>> count.execute('quantity')
|
||||
>>> count.form.total_quantity
|
||||
2.0
|
||||
>>> count.execute('add')
|
||||
|
||||
>>> count.form.search = product2
|
||||
>>> Model.get('res.user.warning')(user=config.user,
|
||||
... name='stock.inventory,%s.product.product,%s.count_create' % (
|
||||
... inventory.id, product2.id)).save()
|
||||
>>> count.execute('quantity')
|
||||
>>> count.form.quantity
|
||||
>>> count.form.total_quantity
|
||||
>>> count.form.quantity = 10
|
||||
>>> count.form.total_quantity
|
||||
10.0
|
||||
>>> count.execute('add')
|
||||
|
||||
>>> count.execute('end')
|
||||
|
||||
Check inventory::
|
||||
|
||||
>>> len(inventory.lines)
|
||||
2
|
||||
>>> line1, = [l for l in inventory.lines if l.product == product]
|
||||
>>> line1.quantity
|
||||
2.0
|
||||
>>> line2, = [l for l in inventory.lines if l.product == product2]
|
||||
>>> line2.quantity
|
||||
10.0
|
||||
@@ -0,0 +1,81 @@
|
||||
=======================================
|
||||
Stock Inventory Scenario Empty Quantity
|
||||
=======================================
|
||||
|
||||
Imports::
|
||||
|
||||
>>> import datetime as dt
|
||||
>>> from decimal import Decimal
|
||||
|
||||
>>> from proteus import Model
|
||||
>>> from trytond.modules.company.tests.tools import create_company
|
||||
>>> from trytond.modules.currency.tests.tools import get_currency
|
||||
>>> from trytond.tests.tools import activate_modules, assertEqual
|
||||
|
||||
>>> today = dt.date.today()
|
||||
|
||||
Activate modules::
|
||||
|
||||
>>> config = activate_modules('stock', create_company)
|
||||
|
||||
Get stock locations::
|
||||
|
||||
>>> Location = Model.get('stock.location')
|
||||
>>> supplier_loc, = Location.find([('code', '=', 'SUP')])
|
||||
>>> storage_loc, = Location.find([('code', '=', 'STO')])
|
||||
>>> customer_loc, = Location.find([('code', '=', 'CUS')])
|
||||
>>> lost_found_loc, = Location.find([('type', '=', 'lost_found')])
|
||||
|
||||
Create product::
|
||||
|
||||
>>> ProductUom = Model.get('product.uom')
|
||||
>>> ProductTemplate = Model.get('product.template')
|
||||
|
||||
>>> unit, = ProductUom.find([('name', '=', 'Unit')])
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = 'Product'
|
||||
>>> template.default_uom = unit
|
||||
>>> template.type = 'goods'
|
||||
>>> template.list_price = Decimal('300')
|
||||
>>> template.cost_price_method = 'average'
|
||||
>>> product, = template.products
|
||||
>>> product.cost_price = Decimal('80')
|
||||
>>> template.save()
|
||||
>>> product, = template.products
|
||||
|
||||
Fill storage::
|
||||
|
||||
>>> StockMove = Model.get('stock.move')
|
||||
>>> incoming_move = StockMove()
|
||||
>>> incoming_move.product = product
|
||||
>>> incoming_move.unit = unit
|
||||
>>> incoming_move.quantity = 1
|
||||
>>> incoming_move.from_location = supplier_loc
|
||||
>>> incoming_move.to_location = storage_loc
|
||||
>>> incoming_move.planned_date = today
|
||||
>>> incoming_move.effective_date = today
|
||||
>>> incoming_move.unit_price = Decimal('100')
|
||||
>>> incoming_move.currency = get_currency()
|
||||
>>> incoming_move.click('do')
|
||||
|
||||
Creating an inventory with empty quantities creates and empty move::
|
||||
|
||||
>>> Inventory = Model.get('stock.inventory')
|
||||
>>> inventory = Inventory()
|
||||
>>> inventory.location = storage_loc
|
||||
>>> inventory.empty_quantity = 'empty'
|
||||
>>> inventory.save()
|
||||
>>> inventory.click('complete_lines')
|
||||
>>> line, = inventory.lines
|
||||
>>> line.expected_quantity
|
||||
1.0
|
||||
>>> line.quantity
|
||||
>>> inventory.click('confirm')
|
||||
>>> line.reload()
|
||||
>>> line.expected_quantity
|
||||
1.0
|
||||
>>> move, = line.moves
|
||||
>>> move.quantity
|
||||
1.0
|
||||
>>> assertEqual(move.from_location, inventory.location)
|
||||
>>> assertEqual(move.to_location, lost_found_loc)
|
||||
67
modules/stock/tests/scenario_stock_move_in_future.rst
Normal file
67
modules/stock/tests/scenario_stock_move_in_future.rst
Normal file
@@ -0,0 +1,67 @@
|
||||
=============================
|
||||
Stock Move In Future Scenario
|
||||
=============================
|
||||
|
||||
Imports::
|
||||
|
||||
>>> import datetime as dt
|
||||
>>> from decimal import Decimal
|
||||
|
||||
>>> from proteus import Model
|
||||
>>> from trytond.modules.company.tests.tools import create_company
|
||||
>>> from trytond.modules.currency.tests.tools import get_currency
|
||||
>>> from trytond.tests.tools import activate_modules
|
||||
|
||||
>>> today = dt.date.today()
|
||||
>>> tomorrow = today + dt.timedelta(days=1)
|
||||
|
||||
Activate modules::
|
||||
|
||||
>>> config = activate_modules('stock', create_company)
|
||||
|
||||
Create product::
|
||||
|
||||
>>> ProductUom = Model.get('product.uom')
|
||||
>>> ProductTemplate = Model.get('product.template')
|
||||
>>> Product = Model.get('product.product')
|
||||
>>> unit, = ProductUom.find([('name', '=', 'Unit')])
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = 'Product'
|
||||
>>> template.default_uom = unit
|
||||
>>> template.type = 'goods'
|
||||
>>> template.list_price = Decimal('20')
|
||||
>>> template.save()
|
||||
>>> product, = template.products
|
||||
>>> product.cost_price = Decimal('1')
|
||||
>>> product.save()
|
||||
|
||||
Get stock locations::
|
||||
|
||||
>>> Location = Model.get('stock.location')
|
||||
>>> supplier_loc, = Location.find([('code', '=', 'SUP')])
|
||||
>>> storage_loc, = Location.find([('code', '=', 'STO')])
|
||||
|
||||
A warning is raised when doing a move in the future::
|
||||
|
||||
>>> Move = Model.get('stock.move')
|
||||
>>> move = Move()
|
||||
>>> move.product = product
|
||||
>>> move.quantity = 1
|
||||
>>> move.from_location = supplier_loc
|
||||
>>> move.to_location = storage_loc
|
||||
>>> move.currency = get_currency()
|
||||
>>> move.effective_date = tomorrow
|
||||
>>> move.quantity = 2
|
||||
>>> move.unit_price = Decimal('1')
|
||||
>>> move.save()
|
||||
>>> move.click('do')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
MoveFutureWarning: ...
|
||||
|
||||
But it can be done for today::
|
||||
|
||||
>>> move.effective_date = today
|
||||
>>> move.click('do')
|
||||
>>> move.state
|
||||
'done'
|
||||
110
modules/stock/tests/scenario_stock_period.rst
Normal file
110
modules/stock/tests/scenario_stock_period.rst
Normal file
@@ -0,0 +1,110 @@
|
||||
=====================
|
||||
Stock Period Scenario
|
||||
=====================
|
||||
|
||||
Imports::
|
||||
|
||||
>>> import datetime as dt
|
||||
>>> from decimal import Decimal
|
||||
|
||||
>>> from proteus import Model
|
||||
>>> from trytond.modules.company.tests.tools import create_company
|
||||
>>> from trytond.modules.currency.tests.tools import get_currency
|
||||
>>> from trytond.tests.tools import activate_modules
|
||||
|
||||
>>> today = dt.date.today()
|
||||
>>> yesterday = today - dt.timedelta(days=1)
|
||||
|
||||
Activate modules::
|
||||
|
||||
>>> config = activate_modules('stock', create_company)
|
||||
|
||||
>>> Location = Model.get('stock.location')
|
||||
>>> Move = Model.get('stock.move')
|
||||
>>> Period = Model.get('stock.period')
|
||||
>>> Product = Model.get('product.product')
|
||||
>>> ProductTemplate = Model.get('product.template')
|
||||
>>> ProductUom = Model.get('product.uom')
|
||||
|
||||
>>> currency = get_currency()
|
||||
|
||||
Create product::
|
||||
|
||||
>>> unit, = ProductUom.find([('name', '=', 'Unit')])
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = 'Product'
|
||||
>>> template.default_uom = unit
|
||||
>>> template.type = 'goods'
|
||||
>>> template.save()
|
||||
>>> product, = template.products
|
||||
|
||||
Get stock locations::
|
||||
|
||||
>>> storage_loc, = Location.find([('code', '=', 'STO')])
|
||||
>>> customer_loc, = Location.find([('code', '=', 'CUS')])
|
||||
|
||||
Create a period::
|
||||
|
||||
>>> period = Period(date=yesterday)
|
||||
>>> period.save()
|
||||
|
||||
Close the period::
|
||||
|
||||
>>> period.click('close')
|
||||
>>> period.state
|
||||
'closed'
|
||||
|
||||
Try to create a move::
|
||||
|
||||
>>> move = Move()
|
||||
>>> move.product = product
|
||||
>>> move.quantity = 1
|
||||
>>> move.from_location = storage_loc
|
||||
>>> move.to_location = customer_loc
|
||||
>>> move.planned_date = yesterday
|
||||
>>> move.unit_price = Decimal('42.0000')
|
||||
>>> move.currency = currency
|
||||
>>> move.save()
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
AccessError: ...
|
||||
|
||||
Reopen the period::
|
||||
|
||||
>>> period.click('draft')
|
||||
>>> period.state
|
||||
'draft'
|
||||
|
||||
Close the period with draft move::
|
||||
|
||||
>>> move.save()
|
||||
>>> period.click('close')
|
||||
>>> period.state
|
||||
'closed'
|
||||
|
||||
Reopen the period::
|
||||
|
||||
>>> period.click('draft')
|
||||
>>> period.state
|
||||
'draft'
|
||||
|
||||
Create an assigned move::
|
||||
|
||||
>>> Move.write([move], {'state': 'assigned'}, config._context)
|
||||
>>> move.state
|
||||
'assigned'
|
||||
|
||||
Close the period with assigned move::
|
||||
|
||||
>>> period.click('close')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
PeriodCloseError: ...
|
||||
|
||||
Try to close a period on today::
|
||||
|
||||
>>> period = Period(date=today)
|
||||
>>> period.click('close')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
PeriodCloseError: ...
|
||||
@@ -0,0 +1,126 @@
|
||||
=====================================
|
||||
Stock Product Quantities by Warehouse
|
||||
=====================================
|
||||
|
||||
Imports::
|
||||
|
||||
>>> import datetime as dt
|
||||
>>> from decimal import Decimal
|
||||
|
||||
>>> from proteus import Model
|
||||
>>> from trytond.modules.company.tests.tools import create_company
|
||||
>>> from trytond.modules.currency.tests.tools import get_currency
|
||||
>>> from trytond.tests.tools import activate_modules, assertEqual
|
||||
|
||||
>>> today = dt.date.today()
|
||||
>>> yesterday = today - dt.timedelta(days=1)
|
||||
>>> tomorrow = today + dt.timedelta(days=1)
|
||||
|
||||
Activate modules::
|
||||
|
||||
>>> config = activate_modules('stock', create_company)
|
||||
|
||||
Get currency::
|
||||
|
||||
>>> currency = get_currency()
|
||||
|
||||
Create product::
|
||||
|
||||
>>> ProductUom = Model.get('product.uom')
|
||||
>>> ProductTemplate = Model.get('product.template')
|
||||
>>> unit, = ProductUom.find([('name', '=', 'Unit')])
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = 'Product'
|
||||
>>> template.default_uom = unit
|
||||
>>> template.type = 'goods'
|
||||
>>> template.list_price = Decimal('20')
|
||||
>>> template.save()
|
||||
>>> product, = template.products
|
||||
|
||||
Get stock locations::
|
||||
|
||||
>>> Location = Model.get('stock.location')
|
||||
>>> warehouse_loc, = Location.find([('code', '=', 'WH')])
|
||||
>>> supplier_loc, = Location.find([('code', '=', 'SUP')])
|
||||
>>> customer_loc, = Location.find([('code', '=', 'CUS')])
|
||||
>>> storage_loc, = Location.find([('code', '=', 'STO')])
|
||||
|
||||
Fill warehouse::
|
||||
|
||||
>>> Move = Model.get('stock.move')
|
||||
>>> move = Move()
|
||||
>>> move.product = product
|
||||
>>> move.from_location = supplier_loc
|
||||
>>> move.to_location = storage_loc
|
||||
>>> move.unit = unit
|
||||
>>> move.quantity = 10
|
||||
>>> move.effective_date = yesterday
|
||||
>>> move.unit_price = Decimal('10')
|
||||
>>> move.currency = currency
|
||||
>>> move.click('do')
|
||||
|
||||
Forecast some moves::
|
||||
|
||||
>>> move = Move()
|
||||
>>> move.product = product
|
||||
>>> move.from_location = storage_loc
|
||||
>>> move.to_location = customer_loc
|
||||
>>> move.unit = unit
|
||||
>>> move.quantity = 6
|
||||
>>> move.planned_date = tomorrow
|
||||
>>> move.unit_price = Decimal('20')
|
||||
>>> move.currency = currency
|
||||
>>> move.save()
|
||||
|
||||
>>> move = Move()
|
||||
>>> move.product = product
|
||||
>>> move.from_location = supplier_loc
|
||||
>>> move.to_location = storage_loc
|
||||
>>> move.unit = unit
|
||||
>>> move.quantity = 5
|
||||
>>> move.planned_date = tomorrow
|
||||
>>> move.unit_price = Decimal('10')
|
||||
>>> move.currency = currency
|
||||
>>> move.save()
|
||||
|
||||
>>> move = Move()
|
||||
>>> move.product = product
|
||||
>>> move.from_location = storage_loc
|
||||
>>> move.to_location = customer_loc
|
||||
>>> move.unit = unit
|
||||
>>> move.quantity = 3
|
||||
>>> move.planned_date = tomorrow
|
||||
>>> move.unit_price = Decimal('20')
|
||||
>>> move.currency = currency
|
||||
>>> move.save()
|
||||
|
||||
|
||||
Check Product Quantities by Warehouse::
|
||||
|
||||
>>> ProductQuantitiesByWarehouse = Model.get('stock.product_quantities_warehouse')
|
||||
>>> with config.set_context(
|
||||
... product_template=template.id, warehouse=warehouse_loc.id):
|
||||
... records = ProductQuantitiesByWarehouse.find([])
|
||||
>>> len(records)
|
||||
3
|
||||
>>> assertEqual([(r.date, r.quantity) for r in records],
|
||||
... [(yesterday, 10), (today, 10), (tomorrow, 6)])
|
||||
|
||||
Check Product Quantities by Warehouse Moves::
|
||||
|
||||
>>> ProductQuantitiesByWarehouseMove = Model.get(
|
||||
... 'stock.product_quantities_warehouse.move')
|
||||
>>> with config.set_context(
|
||||
... product_template=template.id, warehouse=warehouse_loc.id):
|
||||
... records = ProductQuantitiesByWarehouseMove.find([])
|
||||
>>> len(records)
|
||||
4
|
||||
>>> assertEqual([
|
||||
... (r.date, r.cumulative_quantity_start, r.quantity,
|
||||
... r.cumulative_quantity_end)
|
||||
... for r in records],
|
||||
... [
|
||||
... (yesterday, 0, 10, 10),
|
||||
... (tomorrow, 10, -6, 4),
|
||||
... (tomorrow, 4, 5, 9),
|
||||
... (tomorrow, 9, -3, 6)])
|
||||
115
modules/stock/tests/scenario_stock_product_replace.rst
Normal file
115
modules/stock/tests/scenario_stock_product_replace.rst
Normal file
@@ -0,0 +1,115 @@
|
||||
==============================
|
||||
Stock Product Replace Scenario
|
||||
==============================
|
||||
|
||||
Imports::
|
||||
|
||||
>>> from decimal import Decimal
|
||||
|
||||
>>> from proteus import Model, Wizard
|
||||
>>> from trytond.modules.company.tests.tools import create_company, get_company
|
||||
>>> from trytond.tests.tools import (
|
||||
... activate_modules, assertEqual, assertFalse, assertTrue)
|
||||
|
||||
Activate modules::
|
||||
|
||||
>>> config = activate_modules('stock')
|
||||
|
||||
>>> Cron = Model.get('ir.cron')
|
||||
>>> Location = Model.get('stock.location')
|
||||
>>> Move = Model.get('stock.move')
|
||||
>>> ProductTemplate = Model.get('product.template')
|
||||
>>> UoM = Model.get('product.uom')
|
||||
|
||||
Create company::
|
||||
|
||||
>>> _ = create_company()
|
||||
>>> company = get_company()
|
||||
|
||||
Get stock locations::
|
||||
|
||||
>>> supplier_loc, = Location.find([('code', '=', "SUP")])
|
||||
>>> storage_loc, = Location.find([('code', '=', "STO")])
|
||||
>>> customer_loc, = Location.find([('code', '=', "CUS")])
|
||||
|
||||
Create a product::
|
||||
|
||||
>>> unit, = UoM.find([('name', '=', "Unit")])
|
||||
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = "Product"
|
||||
>>> template.type = 'goods'
|
||||
>>> template.default_uom = unit
|
||||
>>> template.save()
|
||||
>>> product1, = template.products
|
||||
|
||||
Create a second product::
|
||||
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = "Product"
|
||||
>>> template.type = 'goods'
|
||||
>>> template.default_uom = unit
|
||||
>>> template.save()
|
||||
>>> product2, = template.products
|
||||
|
||||
Fill storage location::
|
||||
|
||||
>>> move = Move(product=product1)
|
||||
>>> move.quantity = 1
|
||||
>>> move.from_location = supplier_loc
|
||||
>>> move.to_location = storage_loc
|
||||
>>> move.unit_price = Decimal('10.0000')
|
||||
>>> move.currency = company.currency
|
||||
>>> move.click('do')
|
||||
>>> move.state
|
||||
'done'
|
||||
|
||||
Replace the product::
|
||||
|
||||
>>> replace = Wizard('product.product.replace', models=[product1])
|
||||
>>> replace.form.destination = product2
|
||||
>>> replace.execute('replace')
|
||||
>>> assertEqual(product1.replaced_by, product2)
|
||||
>>> assertTrue(product1.active)
|
||||
|
||||
Create a draft move::
|
||||
|
||||
>>> move = Move(product=product1)
|
||||
>>> move.quantity = 1
|
||||
>>> move.from_location = storage_loc
|
||||
>>> move.to_location = customer_loc
|
||||
>>> move.unit_price = Decimal('20.0000')
|
||||
>>> move.currency = company.currency
|
||||
>>> move.save()
|
||||
>>> move.state
|
||||
'draft'
|
||||
|
||||
Empty storage location::
|
||||
|
||||
>>> move = Move(product=product1)
|
||||
>>> move.quantity = 1
|
||||
>>> move.from_location = storage_loc
|
||||
>>> move.to_location = customer_loc
|
||||
>>> move.unit_price = Decimal('20.0000')
|
||||
>>> move.currency = company.currency
|
||||
>>> move.click('do')
|
||||
>>> move.state
|
||||
'done'
|
||||
|
||||
Check replaced product is deactivated and draft move is deleted::
|
||||
|
||||
>>> product1.reload()
|
||||
>>> assertFalse(product1.active)
|
||||
>>> Move.find([('state', '=', 'draft')])
|
||||
[]
|
||||
|
||||
Create a move for replaced product change the product::
|
||||
|
||||
>>> move = Move(product=product1)
|
||||
>>> move.quantity = 1
|
||||
>>> move.from_location = storage_loc
|
||||
>>> move.to_location = customer_loc
|
||||
>>> move.unit_price = Decimal('20.0000')
|
||||
>>> move.currency = company.currency
|
||||
>>> move.save()
|
||||
>>> assertEqual(move.product, product2)
|
||||
@@ -0,0 +1,161 @@
|
||||
==================================
|
||||
Stock Recompute Average Cost Price
|
||||
==================================
|
||||
|
||||
Imports::
|
||||
|
||||
>>> import datetime as dt
|
||||
>>> from decimal import Decimal
|
||||
|
||||
>>> from proteus import Model, Wizard
|
||||
>>> from trytond.modules.company.tests.tools import create_company, get_company
|
||||
>>> from trytond.tests.tools import activate_modules, assertEqual, assertFalse
|
||||
|
||||
>>> today = dt.date.today()
|
||||
|
||||
Activate modules::
|
||||
|
||||
>>> config = activate_modules('stock', create_company)
|
||||
|
||||
Get company::
|
||||
|
||||
>>> company = get_company()
|
||||
|
||||
Create product::
|
||||
|
||||
>>> ProductUom = Model.get('product.uom')
|
||||
>>> ProductTemplate = Model.get('product.template')
|
||||
>>> unit, = ProductUom.find([('name', '=', 'Unit')])
|
||||
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = 'Product'
|
||||
>>> template.default_uom = unit
|
||||
>>> template.type = 'goods'
|
||||
>>> template.list_price = Decimal('300')
|
||||
>>> template.cost_price_method = 'average'
|
||||
>>> product, = template.products
|
||||
>>> product.cost_price = Decimal('80')
|
||||
>>> template.save()
|
||||
>>> product, = template.products
|
||||
|
||||
Get stock locations::
|
||||
|
||||
>>> Location = Model.get('stock.location')
|
||||
>>> supplier_loc, = Location.find([('code', '=', 'SUP')])
|
||||
>>> storage_loc, = Location.find([('code', '=', 'STO')])
|
||||
>>> customer_loc, = Location.find([('code', '=', 'CUS')])
|
||||
|
||||
Create some moves::
|
||||
|
||||
>>> StockMove = Model.get('stock.move')
|
||||
>>> StockMove(
|
||||
... product=product,
|
||||
... quantity=1,
|
||||
... from_location=supplier_loc,
|
||||
... to_location=storage_loc,
|
||||
... unit_price=Decimal('100'),
|
||||
... currency=company.currency,
|
||||
... effective_date=today - dt.timedelta(days=2)).click('do')
|
||||
>>> StockMove(
|
||||
... product=product,
|
||||
... quantity=2,
|
||||
... from_location=storage_loc,
|
||||
... to_location=customer_loc,
|
||||
... unit_price=Decimal('300'),
|
||||
... currency=company.currency,
|
||||
... effective_date=today - dt.timedelta(days=1)).click('do')
|
||||
>>> StockMove(
|
||||
... product=product,
|
||||
... quantity=2,
|
||||
... from_location=supplier_loc,
|
||||
... to_location=storage_loc,
|
||||
... unit_price=Decimal('120'),
|
||||
... currency=company.currency,
|
||||
... effective_date=today - dt.timedelta(days=1)).click('do')
|
||||
>>> StockMove(
|
||||
... product=product,
|
||||
... quantity=3,
|
||||
... from_location=supplier_loc,
|
||||
... to_location=storage_loc,
|
||||
... unit_price=Decimal('100'),
|
||||
... currency=company.currency,
|
||||
... effective_date=today).click('do')
|
||||
|
||||
>>> [m.cost_price for m in StockMove.find([])]
|
||||
[Decimal('105.0000'), Decimal('120.0000'), Decimal('100.0000'), Decimal('100.0000')]
|
||||
|
||||
>>> product.reload()
|
||||
>>> product.cost_price
|
||||
Decimal('105.0000')
|
||||
|
||||
Recompute cost price::
|
||||
|
||||
>>> recompute = Wizard('product.recompute_cost_price', [product])
|
||||
>>> recompute.execute('recompute')
|
||||
|
||||
>>> [m.cost_price for m in StockMove.find([])]
|
||||
[Decimal('105.0000'), Decimal('120.0000'), Decimal('120.0000'), Decimal('100.0000')]
|
||||
|
||||
>>> product.reload()
|
||||
>>> product.cost_price
|
||||
Decimal('105.0000')
|
||||
|
||||
Recompute cost price from a date::
|
||||
|
||||
>>> recompute = Wizard('product.recompute_cost_price', [product])
|
||||
>>> recompute.form.from_ = today - dt.timedelta(days=1)
|
||||
>>> recompute.execute('recompute')
|
||||
|
||||
>>> [m.cost_price for m in StockMove.find([])]
|
||||
[Decimal('105.0000'), Decimal('120.0000'), Decimal('120.0000'), Decimal('100.0000')]
|
||||
|
||||
>>> product.reload()
|
||||
>>> product.cost_price
|
||||
Decimal('105.0000')
|
||||
|
||||
Update unit price of a move::
|
||||
|
||||
>>> move, = StockMove.find([
|
||||
... ('from_location', '=', supplier_loc.id),
|
||||
... ('effective_date', '=', today - dt.timedelta(days=1)),
|
||||
... ])
|
||||
>>> bool(move.unit_price_updated)
|
||||
False
|
||||
>>> move.unit_price = Decimal('130')
|
||||
>>> move.save()
|
||||
>>> bool(move.unit_price_updated)
|
||||
True
|
||||
|
||||
>>> recompute = Wizard('product.recompute_cost_price', [product])
|
||||
>>> recompute.form.from_ = move.effective_date + dt.timedelta(days=1)
|
||||
>>> recompute.execute('recompute')
|
||||
>>> move.reload()
|
||||
>>> bool(move.unit_price_updated)
|
||||
True
|
||||
|
||||
>>> recompute = Wizard('product.recompute_cost_price', [product])
|
||||
>>> assertEqual(recompute.form.from_, move.effective_date)
|
||||
>>> recompute.execute('recompute')
|
||||
>>> move.reload()
|
||||
>>> assertFalse(move.unit_price_updated)
|
||||
>>> [m.cost_price for m in StockMove.find([])]
|
||||
[Decimal('107.5000'), Decimal('130.0000'), Decimal('130.0000'), Decimal('100.0000')]
|
||||
|
||||
Launch cron task::
|
||||
|
||||
>>> move.unit_price = Decimal('120')
|
||||
>>> move.save()
|
||||
|
||||
>>> Cron = Model.get('ir.cron')
|
||||
>>> Company = Model.get('company.company')
|
||||
>>> cron_recompute, = Cron.find([
|
||||
... ('method', '=', 'product.product|recompute_cost_price_from_moves'),
|
||||
... ])
|
||||
>>> cron_recompute.companies.append(Company(company.id))
|
||||
>>> cron_recompute.click('run_once')
|
||||
|
||||
>>> move.reload()
|
||||
>>> bool(move.unit_price_updated)
|
||||
False
|
||||
>>> [m.cost_price for m in StockMove.find([])]
|
||||
[Decimal('105.0000'), Decimal('120.0000'), Decimal('120.0000'), Decimal('100.0000')]
|
||||
@@ -0,0 +1,106 @@
|
||||
=============================================
|
||||
Stock Recompute Average Cost Price Production
|
||||
=============================================
|
||||
|
||||
Imports::
|
||||
|
||||
>>> import datetime as dt
|
||||
>>> from decimal import Decimal
|
||||
|
||||
>>> from proteus import Model, Wizard
|
||||
>>> from trytond.modules.company.tests.tools import create_company
|
||||
>>> from trytond.modules.currency.tests.tools import get_currency
|
||||
>>> from trytond.tests.tools import activate_modules
|
||||
|
||||
>>> today = dt.date.today()
|
||||
>>> yesterday = today - dt.timedelta(days=1)
|
||||
|
||||
Activate modules::
|
||||
|
||||
>>> config = activate_modules('stock', create_company)
|
||||
|
||||
>>> Location = Model.get('stock.location')
|
||||
>>> ProductTemplate = Model.get('product.template')
|
||||
>>> ProductUom = Model.get('product.uom')
|
||||
>>> StockMove = Model.get('stock.move')
|
||||
|
||||
Get currency::
|
||||
|
||||
>>> currency = get_currency()
|
||||
|
||||
Create product::
|
||||
|
||||
>>> unit, = ProductUom.find([('name', '=', 'Unit')])
|
||||
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = 'Product'
|
||||
>>> template.default_uom = unit
|
||||
>>> template.type = 'goods'
|
||||
>>> template.list_price = Decimal('50.0000')
|
||||
>>> template.cost_price_method = 'average'
|
||||
>>> product, = template.products
|
||||
>>> product.cost_price = Decimal('40.0000')
|
||||
>>> template.save()
|
||||
>>> product, = template.products
|
||||
|
||||
Get stock locations::
|
||||
|
||||
>>> supplier_loc, = Location.find([('code', '=', 'SUP')])
|
||||
>>> storage_loc, = Location.find([('code', '=', 'STO')])
|
||||
>>> production_loc = Location(name="Production", type='production')
|
||||
>>> production_loc.save()
|
||||
|
||||
Consume product for production and reverse some::
|
||||
|
||||
>>> StockMove(
|
||||
... product=product,
|
||||
... quantity=10,
|
||||
... from_location=storage_loc,
|
||||
... to_location=production_loc,
|
||||
... effective_date=today).click('do')
|
||||
>>> StockMove(
|
||||
... product=product,
|
||||
... quantity=2,
|
||||
... from_location=production_loc,
|
||||
... to_location=storage_loc,
|
||||
... unit_price=Decimal('40.0000'),
|
||||
... currency=currency,
|
||||
... effective_date=today).click('do')
|
||||
|
||||
>>> [m.cost_price for m in StockMove.find([])]
|
||||
[Decimal('40.0000'), Decimal('40.0000')]
|
||||
|
||||
Recompute cost price::
|
||||
|
||||
>>> recompute = Wizard('product.recompute_cost_price', [product])
|
||||
>>> recompute.execute('recompute')
|
||||
|
||||
>>> [m.cost_price for m in StockMove.find([])]
|
||||
[Decimal('0.0000'), Decimal('0.0000')]
|
||||
|
||||
>>> product.reload()
|
||||
>>> product.cost_price
|
||||
Decimal('0.0000')
|
||||
|
||||
Receive product yesterday at new cost::
|
||||
|
||||
>>> StockMove(
|
||||
... product=product,
|
||||
... quantity=16,
|
||||
... from_location=supplier_loc,
|
||||
... to_location=storage_loc,
|
||||
... unit_price=Decimal('20.0000'),
|
||||
... currency=currency,
|
||||
... effective_date=yesterday).click('do')
|
||||
|
||||
Recompute cost price::
|
||||
|
||||
>>> recompute = Wizard('product.recompute_cost_price', [product])
|
||||
>>> recompute.execute('recompute')
|
||||
|
||||
>>> [m.cost_price for m in StockMove.find([])]
|
||||
[Decimal('20.0000'), Decimal('20.0000'), Decimal('20.0000')]
|
||||
|
||||
>>> product.reload()
|
||||
>>> product.cost_price
|
||||
Decimal('20.0000')
|
||||
157
modules/stock/tests/scenario_stock_reporting.rst
Normal file
157
modules/stock/tests/scenario_stock_reporting.rst
Normal file
@@ -0,0 +1,157 @@
|
||||
=================================
|
||||
Stock Shipment Reporting Scenario
|
||||
=================================
|
||||
|
||||
Imports::
|
||||
|
||||
>>> import datetime as dt
|
||||
>>> from decimal import Decimal
|
||||
|
||||
>>> from proteus import Model, Report
|
||||
>>> from trytond.modules.company.tests.tools import create_company
|
||||
>>> from trytond.modules.currency.tests.tools import get_currency
|
||||
>>> from trytond.tests.tools import activate_modules
|
||||
|
||||
>>> today = dt.date.today()
|
||||
>>> yesterday = today - dt.timedelta(days=1)
|
||||
|
||||
Activate modules::
|
||||
|
||||
>>> config = activate_modules('stock', create_company)
|
||||
|
||||
Get currency::
|
||||
|
||||
>>> currency = get_currency()
|
||||
|
||||
Create customer & supplier::
|
||||
|
||||
>>> Party = Model.get('party.party')
|
||||
>>> customer = Party(name='Customer')
|
||||
>>> customer.save()
|
||||
>>> supplier = Party(name='Supplier')
|
||||
>>> supplier.save()
|
||||
|
||||
Create product::
|
||||
|
||||
>>> ProductUom = Model.get('product.uom')
|
||||
>>> ProductTemplate = Model.get('product.template')
|
||||
>>> Product = Model.get('product.product')
|
||||
>>> unit, = ProductUom.find([('name', '=', 'Unit')])
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = 'Product'
|
||||
>>> template.default_uom = unit
|
||||
>>> template.type = 'goods'
|
||||
>>> template.list_price = Decimal('20')
|
||||
>>> template.save()
|
||||
>>> product, = template.products
|
||||
|
||||
Get stock locations::
|
||||
|
||||
>>> Location = Model.get('stock.location')
|
||||
>>> warehouse_loc, = Location.find([('code', '=', 'WH')])
|
||||
>>> supplier_loc, = Location.find([('code', '=', 'SUP')])
|
||||
>>> customer_loc, = Location.find([('code', '=', 'CUS')])
|
||||
>>> input_loc, = Location.find([('code', '=', 'IN')])
|
||||
>>> output_loc, = Location.find([('code', '=', 'OUT')])
|
||||
>>> storage_loc, = Location.find([('code', '=', 'STO')])
|
||||
>>> lost_loc, = Location.find([('type', '=', 'lost_found')])
|
||||
|
||||
Create Shipment In::
|
||||
|
||||
>>> ShipmentIn = Model.get('stock.shipment.in')
|
||||
>>> shipment_in = ShipmentIn()
|
||||
>>> shipment_in.planned_date = today
|
||||
>>> shipment_in.supplier = supplier
|
||||
>>> shipment_in.warehouse = warehouse_loc
|
||||
|
||||
Receive a bunch of products::
|
||||
|
||||
>>> move = shipment_in.incoming_moves.new()
|
||||
>>> move.product = product
|
||||
>>> move.unit = unit
|
||||
>>> move.quantity = 100
|
||||
>>> move.from_location = supplier_loc
|
||||
>>> move.to_location = input_loc
|
||||
>>> move.unit_price = Decimal('1')
|
||||
>>> move.currency = currency
|
||||
>>> shipment_in.save()
|
||||
>>> shipment_in.click('receive')
|
||||
>>> shipment_in.click('do')
|
||||
|
||||
Testing the report::
|
||||
|
||||
>>> supplier_restocking_list = Report('stock.shipment.in.restocking_list')
|
||||
>>> ext, _, _, name = supplier_restocking_list.execute([shipment_in], {})
|
||||
>>> ext
|
||||
'odt'
|
||||
>>> name
|
||||
'Restocking List-1'
|
||||
|
||||
Create Shipment Out::
|
||||
|
||||
>>> ShipmentOut = Model.get('stock.shipment.out')
|
||||
>>> shipment_out = ShipmentOut()
|
||||
>>> shipment_out.planned_date = today
|
||||
>>> shipment_out.customer = customer
|
||||
>>> shipment_out.warehouse = warehouse_loc
|
||||
|
||||
Add two shipment lines of same product and go through the workflow::
|
||||
|
||||
>>> move = shipment_out.outgoing_moves.new()
|
||||
>>> move.product = product
|
||||
>>> move.unit = unit
|
||||
>>> move.quantity = 1
|
||||
>>> move.from_location = output_loc
|
||||
>>> move.to_location = customer_loc
|
||||
>>> move.unit_price = Decimal('1')
|
||||
>>> move.currency = currency
|
||||
>>> shipment_out.save()
|
||||
>>> shipment_out.click('wait')
|
||||
>>> shipment_out.click('assign_try')
|
||||
>>> shipment_out.click('pick')
|
||||
>>> shipment_out.click('pack')
|
||||
>>> shipment_out.click('do')
|
||||
|
||||
Testing the reports::
|
||||
|
||||
>>> delivery_note = Report('stock.shipment.out.delivery_note')
|
||||
>>> ext, _, _, name = delivery_note.execute([shipment_out], {})
|
||||
>>> ext
|
||||
'odt'
|
||||
>>> name
|
||||
'Delivery Note-1'
|
||||
|
||||
>>> picking_list = Report('stock.shipment.out.picking_list')
|
||||
>>> ext, _, _, name = picking_list.execute([shipment_out], {})
|
||||
>>> ext
|
||||
'odt'
|
||||
>>> name
|
||||
'Picking List-1'
|
||||
|
||||
Create an internal shipment::
|
||||
|
||||
>>> ShipmentInternal = Model.get('stock.shipment.internal')
|
||||
>>> shipment_internal = ShipmentInternal()
|
||||
>>> shipment_internal.planned_date = today
|
||||
>>> shipment_internal.from_location = storage_loc
|
||||
>>> shipment_internal.to_location = lost_loc
|
||||
>>> move = shipment_internal.moves.new()
|
||||
>>> move.product = product
|
||||
>>> move.unit = unit
|
||||
>>> move.quantity = 1
|
||||
>>> move.from_location = storage_loc
|
||||
>>> move.to_location = lost_loc
|
||||
>>> shipment_internal.save()
|
||||
>>> shipment_internal.click('wait')
|
||||
>>> shipment_internal.click('assign_try')
|
||||
>>> shipment_internal.click('do')
|
||||
|
||||
Testing the report::
|
||||
|
||||
>>> internal_report = Report('stock.shipment.internal.report')
|
||||
>>> ext, _, _, name = internal_report.execute([shipment_internal], {})
|
||||
>>> ext
|
||||
'odt'
|
||||
>>> name
|
||||
'Internal Shipment-1'
|
||||
|
||||
239
modules/stock/tests/scenario_stock_reporting_inventory.rst
Normal file
239
modules/stock/tests/scenario_stock_reporting_inventory.rst
Normal file
@@ -0,0 +1,239 @@
|
||||
==================================
|
||||
Stock Reporting Inventory Scenario
|
||||
==================================
|
||||
|
||||
Imports::
|
||||
|
||||
>>> import datetime as dt
|
||||
>>> from decimal import Decimal
|
||||
>>> from unittest.mock import patch
|
||||
|
||||
>>> from proteus import Model
|
||||
>>> from trytond.ir.date import Date
|
||||
>>> from trytond.modules.company.tests.tools import create_company
|
||||
>>> from trytond.modules.currency.tests.tools import get_currency
|
||||
>>> from trytond.tests.tools import activate_modules, assertEqual
|
||||
|
||||
>>> period_close = globals().get('period_close', False)
|
||||
>>> product_type = globals().get('product_type', 'product.template')
|
||||
|
||||
Patch today::
|
||||
|
||||
>>> mock = patch.object(Date, 'today', return_value=dt.date(2025, 1, 15))
|
||||
>>> _ = mock.start()
|
||||
|
||||
Activate modules::
|
||||
|
||||
>>> config = activate_modules('stock', create_company)
|
||||
|
||||
>>> Inventory = Model.get('stock.reporting.inventory')
|
||||
>>> InventoryMove = Model.get('stock.reporting.inventory.move')
|
||||
>>> InventoryDaily = Model.get('stock.reporting.inventory.daily')
|
||||
>>> InventoryTurnover = Model.get('stock.reporting.inventory.turnover')
|
||||
>>> Location = Model.get('stock.location')
|
||||
>>> Move = Model.get('stock.move')
|
||||
>>> Period = Model.get('stock.period')
|
||||
>>> ProductTemplate = Model.get('product.template')
|
||||
>>> ProductUom = Model.get('product.uom')
|
||||
|
||||
Get currency::
|
||||
|
||||
>>> currency = get_currency()
|
||||
|
||||
Create product::
|
||||
|
||||
>>> unit, = ProductUom.find([('name', '=', 'Unit')])
|
||||
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = 'Product'
|
||||
>>> template.default_uom = unit
|
||||
>>> template.type = 'goods'
|
||||
>>> template.save()
|
||||
>>> product, = template.products
|
||||
|
||||
Get stock locations::
|
||||
|
||||
>>> warehouse_loc, = Location.find([('code', '=', 'WH')])
|
||||
>>> supplier_loc, = Location.find([('code', '=', 'SUP')])
|
||||
>>> customer_loc, = Location.find([('code', '=', 'CUS')])
|
||||
>>> storage_loc, = Location.find([('code', '=', 'STO')])
|
||||
|
||||
Fill warehouse::
|
||||
|
||||
>>> move = Move()
|
||||
>>> move.product = product
|
||||
>>> move.from_location = supplier_loc
|
||||
>>> move.to_location = storage_loc
|
||||
>>> move.quantity = 10
|
||||
>>> move.effective_date = dt.date(2025, 1, 1)
|
||||
>>> move.unit_price = Decimal('10.0000')
|
||||
>>> move.currency = currency
|
||||
>>> move.click('do')
|
||||
>>> move.state
|
||||
'done'
|
||||
|
||||
>>> move = Move()
|
||||
>>> move.product = product
|
||||
>>> move.from_location = storage_loc
|
||||
>>> move.to_location = customer_loc
|
||||
>>> move.unit = unit
|
||||
>>> move.quantity = 1
|
||||
>>> move.effective_date = dt.date(2025, 1, 1)
|
||||
>>> move.unit_price = Decimal('20.0000')
|
||||
>>> move.currency = currency
|
||||
>>> move.click('do')
|
||||
>>> move.state
|
||||
'done'
|
||||
|
||||
>>> move = Move()
|
||||
>>> move.product = product
|
||||
>>> move.from_location = storage_loc
|
||||
>>> move.to_location = customer_loc
|
||||
>>> move.unit = unit
|
||||
>>> move.quantity = 2
|
||||
>>> move.effective_date = dt.date(2025, 1, 10)
|
||||
>>> move.unit_price = Decimal('20.0000')
|
||||
>>> move.currency = currency
|
||||
>>> move.click('do')
|
||||
>>> move.state
|
||||
'done'
|
||||
|
||||
Forecast some moves::
|
||||
|
||||
>>> move = Move()
|
||||
>>> move.product = product
|
||||
>>> move.from_location = supplier_loc
|
||||
>>> move.to_location = storage_loc
|
||||
>>> move.quantity = 10
|
||||
>>> move.effective_date = dt.date(2025, 1, 5)
|
||||
>>> move.unit_price = Decimal('10.0000')
|
||||
>>> move.currency = currency
|
||||
>>> move.save()
|
||||
>>> move.state
|
||||
'draft'
|
||||
|
||||
>>> move = Move()
|
||||
>>> move.product = product
|
||||
>>> move.from_location = storage_loc
|
||||
>>> move.to_location = customer_loc
|
||||
>>> move.unit = unit
|
||||
>>> move.quantity = 3
|
||||
>>> move.planned_date = dt.date(2025, 1, 20)
|
||||
>>> move.unit_price = Decimal('20.0000')
|
||||
>>> move.currency = currency
|
||||
>>> move.save()
|
||||
>>> move.state
|
||||
'draft'
|
||||
|
||||
Close period::
|
||||
|
||||
>>> period = Period(date=dt.date(2025, 1, 5))
|
||||
>>> if period_close:
|
||||
... period.click('close')
|
||||
|
||||
|
||||
Check inventory::
|
||||
|
||||
>>> with config.set_context(
|
||||
... location=warehouse_loc.id,
|
||||
... product_type=product_type,
|
||||
... date=dt.date(2024, 1, 1)):
|
||||
... Inventory.find([])
|
||||
[]
|
||||
|
||||
>>> with config.set_context(
|
||||
... location=warehouse_loc.id,
|
||||
... product_type=product_type,
|
||||
... date=dt.date(2025, 1, 1)):
|
||||
... inventory, = Inventory.find([])
|
||||
>>> inventory.quantity
|
||||
9.0
|
||||
>>> assertEqual(inventory.product.__class__.__name__, product_type)
|
||||
|
||||
>>> with config.set_context(
|
||||
... location=warehouse_loc.id,
|
||||
... product_type=product_type,
|
||||
... date=dt.date(2025, 1, 15)):
|
||||
... inventory, = Inventory.find([])
|
||||
>>> inventory.quantity
|
||||
7.0
|
||||
|
||||
>>> with config.set_context(
|
||||
... location=warehouse_loc.id,
|
||||
... product_type=product_type,
|
||||
... date=dt.date(2025, 1, 20)):
|
||||
... inventory, = Inventory.find([])
|
||||
>>> inventory.quantity
|
||||
4.0
|
||||
|
||||
>>> with config.set_context(
|
||||
... location=warehouse_loc.id,
|
||||
... product_type=product_type):
|
||||
... inventory_moves = InventoryMove.find([])
|
||||
... inventories_daily = InventoryDaily.find([])
|
||||
|
||||
>>> [i.quantity for i in inventory_moves]
|
||||
[4.0, 7.0, 9.0, 10.0]
|
||||
>>> [(i.input_quantity, i.output_quantity) for i in inventory_moves]
|
||||
[(None, 3.0), (None, 2.0), (None, 1.0), (10.0, None)]
|
||||
|
||||
>>> [i.quantity for i in inventories_daily]
|
||||
[4.0, 7.0, 9.0]
|
||||
>>> [(i.input_quantity, i.output_quantity) for i in inventories_daily]
|
||||
[(None, 3.0), (None, 2.0), (10.0, 1.0)]
|
||||
|
||||
>>> with config.set_context(
|
||||
... location=warehouse_loc.id,
|
||||
... from_date=dt.date(2025, 1, 15),
|
||||
... to_date=dt.date(2025, 1, 29),
|
||||
... product_type=product_type):
|
||||
... inventory_moves = InventoryMove.find([])
|
||||
... inventories_daily = InventoryDaily.find([])
|
||||
|
||||
>>> [i.quantity for i in inventory_moves]
|
||||
[4.0, 7.0]
|
||||
>>> [(i.input_quantity, i.output_quantity) for i in inventory_moves]
|
||||
[(None, 3.0), (None, None)]
|
||||
|
||||
>>> [i.quantity for i in inventories_daily]
|
||||
[4.0, 7.0]
|
||||
>>> [(i.input_quantity, i.output_quantity) for i in inventories_daily]
|
||||
[(None, 3.0), (None, None)]
|
||||
|
||||
>>> with config.set_context(
|
||||
... location=warehouse_loc.id,
|
||||
... from_date=dt.date(2025, 1, 10),
|
||||
... to_date=dt.date(2025, 1, 29),
|
||||
... product_type=product_type):
|
||||
... inventory_moves = InventoryMove.find([])
|
||||
... inventories_daily = InventoryDaily.find([])
|
||||
|
||||
>>> assertEqual(
|
||||
... [i.quantity for i in inventory_moves],
|
||||
... [4.0, 7.0] if period_close else [4.0, 7.0, 9.0])
|
||||
>>> assertEqual(
|
||||
... [(i.input_quantity, i.output_quantity) for i in inventory_moves],
|
||||
... [(None, 3.0), (None, 2.0)] if period_close
|
||||
... else [(None, 3.0), (None, 2.0), (None, None)])
|
||||
|
||||
>>> [i.quantity for i in inventories_daily]
|
||||
[4.0, 7.0]
|
||||
>>> [(i.input_quantity, i.output_quantity) for i in inventories_daily]
|
||||
[(None, 3.0), (None, 2.0)]
|
||||
|
||||
Check Inventory turnover::
|
||||
|
||||
>>> with config.set_context(
|
||||
... location=warehouse_loc.id,
|
||||
... from_date=dt.date(2025, 1, 10),
|
||||
... to_date=dt.date(2025, 1, 29),
|
||||
... product_type=product_type):
|
||||
... turnover, = InventoryTurnover.find([])
|
||||
|
||||
>>> turnover.output_quantity
|
||||
0.25
|
||||
>>> turnover.average_quantity
|
||||
5.5
|
||||
>>> turnover.turnover
|
||||
0.045
|
||||
>>> assertEqual(turnover.product.__class__.__name__, product_type)
|
||||
217
modules/stock/tests/scenario_stock_reporting_margin.rst
Normal file
217
modules/stock/tests/scenario_stock_reporting_margin.rst
Normal file
@@ -0,0 +1,217 @@
|
||||
===============================
|
||||
Stock Reporting Margin Scenario
|
||||
===============================
|
||||
|
||||
Imports::
|
||||
|
||||
>>> import datetime as dt
|
||||
>>> from decimal import Decimal
|
||||
|
||||
>>> from proteus import Model
|
||||
>>> from trytond.modules.company.tests.tools import create_company
|
||||
>>> from trytond.modules.currency.tests.tools import get_currency
|
||||
>>> from trytond.tests.tools import activate_modules, assertEqual
|
||||
|
||||
>>> today = dt.date.today()
|
||||
>>> yesterday = today - dt.timedelta(days=1)
|
||||
|
||||
Activate modules::
|
||||
|
||||
>>> config = activate_modules('stock', create_company)
|
||||
|
||||
Get currency::
|
||||
|
||||
>>> currency = get_currency()
|
||||
|
||||
Create product::
|
||||
|
||||
>>> ProductUom = Model.get('product.uom')
|
||||
>>> ProductTemplate = Model.get('product.template')
|
||||
>>> unit, = ProductUom.find([('name', '=', 'Unit')])
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = 'Product'
|
||||
>>> template.default_uom = unit
|
||||
>>> template.type = 'goods'
|
||||
>>> template.list_price = Decimal('40')
|
||||
>>> template.save()
|
||||
>>> product, = template.products
|
||||
>>> product.cost_price = Decimal('20')
|
||||
>>> product.save()
|
||||
>>> template2, = template.duplicate()
|
||||
>>> product2, = template2.products
|
||||
|
||||
>>> Category = Model.get('product.category')
|
||||
>>> category_root = Category(name="Root")
|
||||
>>> category_root.save()
|
||||
>>> category1 = Category(name="Child1", parent=category_root)
|
||||
>>> category1.save()
|
||||
>>> category2 = Category(name="Child2", parent=category_root)
|
||||
>>> category2.save()
|
||||
|
||||
>>> template.categories.append(Category(category1.id))
|
||||
>>> template.save()
|
||||
>>> template2.categories.append(Category(category2.id))
|
||||
>>> template2.save()
|
||||
|
||||
|
||||
Get stock locations::
|
||||
|
||||
>>> Location = Model.get('stock.location')
|
||||
>>> supplier_loc, = Location.find([('code', '=', 'SUP')])
|
||||
>>> customer_loc, = Location.find([('code', '=', 'CUS')])
|
||||
>>> storage_loc, = Location.find([('code', '=', 'STO')])
|
||||
>>> lost_loc, = Location.find([('type', '=', 'lost_found')])
|
||||
|
||||
Create some moves::
|
||||
|
||||
>>> Move = Model.get('stock.move')
|
||||
>>> move = Move()
|
||||
>>> move.product = product
|
||||
>>> move.from_location = supplier_loc
|
||||
>>> move.to_location = storage_loc
|
||||
>>> move.quantity = 8
|
||||
>>> move.unit_price = Decimal('20')
|
||||
>>> move.currency = currency
|
||||
>>> move.effective_date = yesterday
|
||||
>>> move.click('do')
|
||||
|
||||
>>> move = Move()
|
||||
>>> move.product = product
|
||||
>>> move.from_location = storage_loc
|
||||
>>> move.to_location = customer_loc
|
||||
>>> move.quantity = 2
|
||||
>>> move.unit_price = Decimal('40')
|
||||
>>> move.currency = currency
|
||||
>>> move.effective_date = yesterday
|
||||
>>> move.click('do')
|
||||
|
||||
>>> move = Move()
|
||||
>>> move.product = product
|
||||
>>> move.from_location = storage_loc
|
||||
>>> move.to_location = customer_loc
|
||||
>>> move.quantity = 4
|
||||
>>> move.unit_price = Decimal('30')
|
||||
>>> move.currency = currency
|
||||
>>> move.effective_date = today
|
||||
>>> move.click('do')
|
||||
|
||||
>>> move = Move()
|
||||
>>> move.product = product
|
||||
>>> move.from_location = customer_loc
|
||||
>>> move.to_location = storage_loc
|
||||
>>> move.quantity = 1
|
||||
>>> move.unit_price = Decimal('30')
|
||||
>>> move.currency = currency
|
||||
>>> move.effective_date = today
|
||||
>>> move.click('do')
|
||||
|
||||
>>> move = Move()
|
||||
>>> move.product = product2
|
||||
>>> move.from_location = storage_loc
|
||||
>>> move.to_location = customer_loc
|
||||
>>> move.quantity = 2
|
||||
>>> move.unit_price = Decimal('50')
|
||||
>>> move.currency = currency
|
||||
>>> move.effective_date = today
|
||||
>>> move.click('do')
|
||||
|
||||
>>> move = Move()
|
||||
>>> move.product = product
|
||||
>>> move.from_location = storage_loc
|
||||
>>> move.to_location = lost_loc
|
||||
>>> move.quantity = 1
|
||||
>>> move.effective_date = today
|
||||
>>> move.click('do')
|
||||
|
||||
Check reporting margin per product::
|
||||
|
||||
>>> MarginProduct = Model.get('stock.reporting.margin.product')
|
||||
>>> MarginProductTimeseries = Model.get(
|
||||
... 'stock.reporting.margin.product.time_series')
|
||||
>>> context = {
|
||||
... 'from_date': yesterday,
|
||||
... 'to_date': today,
|
||||
... 'period': 'day',
|
||||
... }
|
||||
>>> with config.set_context(context=context):
|
||||
... reports = MarginProduct.find([])
|
||||
... time_series = MarginProductTimeseries.find([])
|
||||
>>> len(reports)
|
||||
2
|
||||
>>> report, = [r for r in reports if r.product == product]
|
||||
>>> (report.quantity, report.cost, report.revenue, report.profit, report.margin)
|
||||
(5.0, Decimal('100.00'), Decimal('170.00'), Decimal('70.00'), Decimal('0.4118'))
|
||||
>>> len(time_series)
|
||||
3
|
||||
>>> with config.set_context(context=context):
|
||||
... assertEqual({(
|
||||
... r.product.id, str(r.date), r.quantity, r.cost, r.revenue,
|
||||
... r.profit, r.margin)
|
||||
... for r in time_series},
|
||||
... {
|
||||
... (product.id, str(yesterday), 2, Decimal('40.00'),
|
||||
... Decimal('80.00'), Decimal('40.00'), Decimal('0.5000')),
|
||||
... (product.id, str(today), 3, Decimal('60.00'),
|
||||
... Decimal('90.00'), Decimal('30.00'), Decimal('0.3333')),
|
||||
... (product2.id, str(today), 2, Decimal('40.00'),
|
||||
... Decimal('100.00'), Decimal('60.00'), Decimal('0.6000'))})
|
||||
|
||||
Check reporting margin per categories::
|
||||
|
||||
>>> MarginCategory = Model.get('stock.reporting.margin.category')
|
||||
>>> MarginCategoryTimeseries = Model.get(
|
||||
... 'stock.reporting.margin.category.time_series')
|
||||
>>> MarginCategoryTree = Model.get(
|
||||
... 'stock.reporting.margin.category.tree')
|
||||
>>> with config.set_context(context=context):
|
||||
... reports = MarginCategory.find([])
|
||||
... time_series = MarginCategoryTimeseries.find([])
|
||||
... tree = MarginCategoryTree.find([])
|
||||
>>> len(reports)
|
||||
2
|
||||
>>> with config.set_context(context=context):
|
||||
... assertEqual({(r.category.id, r.cost, r.revenue, r.profit, r.margin)
|
||||
... for r in reports},
|
||||
... {(category1.id, Decimal('100.00'), Decimal('170.00'),
|
||||
... Decimal('70.00'), Decimal('0.4118')),
|
||||
... (category2.id, Decimal('40.00'), Decimal('100.00'),
|
||||
... Decimal('60.00'), Decimal('0.6000'))})
|
||||
>>> len(time_series)
|
||||
3
|
||||
>>> with config.set_context(context=context):
|
||||
... assertEqual({
|
||||
... (r.category.id, str(r.date), r.cost, r.revenue, r.profit, r.margin)
|
||||
... for r in time_series},
|
||||
... {
|
||||
... (category1.id, str(yesterday), Decimal('40.00'), Decimal('80.00'),
|
||||
... Decimal('40.00'), Decimal('0.5000')),
|
||||
... (category1.id, str(today), Decimal('60.00'), Decimal('90.00'),
|
||||
... Decimal('30.00'), Decimal('0.3333')),
|
||||
... (category2.id, str(today), Decimal('40.00'), Decimal('100.00'),
|
||||
... Decimal('60.00'), Decimal('0.6000'))})
|
||||
>>> len(tree)
|
||||
3
|
||||
>>> with config.set_context(context=context):
|
||||
... assertEqual({(r.name, r.cost, r.revenue, r.profit, r.margin)
|
||||
... for r in tree},
|
||||
... {("Root", Decimal('140.00'), Decimal('270.00'),
|
||||
... Decimal('130.00'), Decimal('0.4815')),
|
||||
... ("Child1", Decimal('100.00'), Decimal('170.00'),
|
||||
... Decimal('70.00'), Decimal('0.4118')),
|
||||
... ('Child2', Decimal('40.00'), Decimal('100.00'),
|
||||
... Decimal('60.00'), Decimal('0.6000'))})
|
||||
>>> child1, = MarginCategoryTree.find([('rec_name', '=', 'Child1')])
|
||||
>>> child1.rec_name
|
||||
'Child1'
|
||||
|
||||
Check reporting margin including lost::
|
||||
|
||||
>>> context['include_lost'] = True
|
||||
|
||||
>>> with config.set_context(context=context):
|
||||
... reports = MarginProduct.find([])
|
||||
>>> len(reports)
|
||||
2
|
||||
>>> report, = [r for r in reports if r.product == product]
|
||||
>>> (report.quantity, report.cost, report.revenue, report.profit, report.margin)
|
||||
(6.0, Decimal('120.00'), Decimal('170.00'), Decimal('50.00'), Decimal('0.2941'))
|
||||
137
modules/stock/tests/scenario_stock_shipment_cron_assign.rst
Normal file
137
modules/stock/tests/scenario_stock_shipment_cron_assign.rst
Normal file
@@ -0,0 +1,137 @@
|
||||
==========================
|
||||
Stock Shipment Cron Assign
|
||||
==========================
|
||||
|
||||
Imports::
|
||||
|
||||
>>> import datetime as dt
|
||||
>>> from decimal import Decimal
|
||||
|
||||
>>> from proteus import Model
|
||||
>>> from trytond.modules.company.tests.tools import create_company
|
||||
>>> from trytond.modules.currency.tests.tools import get_currency
|
||||
>>> from trytond.tests.tools import activate_modules
|
||||
|
||||
>>> today = dt.date.today()
|
||||
>>> yesterday = today - dt.timedelta(days=1)
|
||||
|
||||
Activate modules::
|
||||
|
||||
>>> config = activate_modules('stock', create_company)
|
||||
|
||||
>>> Cron = Model.get('ir.cron')
|
||||
>>> Location = Model.get('stock.location')
|
||||
>>> Move = Model.get('stock.move')
|
||||
>>> Party = Model.get('party.party')
|
||||
>>> ProductTemplate = Model.get('product.template')
|
||||
>>> ShipmentInternal = Model.get('stock.shipment.internal')
|
||||
>>> ShipmentOut = Model.get('stock.shipment.out')
|
||||
>>> UoM = Model.get('product.uom')
|
||||
|
||||
Get currency::
|
||||
|
||||
>>> currency = get_currency()
|
||||
|
||||
Create a product::
|
||||
|
||||
>>> unit, = UoM.find([('name', '=', "Unit")])
|
||||
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = "Product"
|
||||
>>> template.type = 'goods'
|
||||
>>> template.default_uom = unit
|
||||
>>> template.save()
|
||||
>>> product, = template.products
|
||||
|
||||
Create customer::
|
||||
|
||||
>>> customer = Party(name="Customer")
|
||||
>>> customer.save()
|
||||
|
||||
Get locations::
|
||||
|
||||
>>> storage_loc, = Location.find([('code', '=', "STO")])
|
||||
>>> supplier_loc, = Location.find([('code', '=', "SUP")])
|
||||
>>> lost_loc, = Location.find([('type', '=', 'lost_found')], limit=1)
|
||||
|
||||
Fill storage::
|
||||
|
||||
>>> move = Move()
|
||||
>>> move.product = product
|
||||
>>> move.quantity = 5
|
||||
>>> move.from_location = supplier_loc
|
||||
>>> move.to_location = storage_loc
|
||||
>>> move.unit_price = Decimal('10.0000')
|
||||
>>> move.currency = currency
|
||||
>>> move.effective_date = yesterday
|
||||
>>> move.click('do')
|
||||
>>> move.state
|
||||
'done'
|
||||
|
||||
Create different shipments with different planned dates::
|
||||
|
||||
>>> shipment_int_1 = ShipmentInternal()
|
||||
>>> shipment_int_1.planned_date = today
|
||||
>>> shipment_int_1.from_location = storage_loc
|
||||
>>> shipment_int_1.to_location = lost_loc
|
||||
>>> move = shipment_int_1.moves.new()
|
||||
>>> move.from_location = shipment_int_1.from_location
|
||||
>>> move.to_location = shipment_int_1.to_location
|
||||
>>> move.product = product
|
||||
>>> move.quantity = 2
|
||||
>>> shipment_int_1.click('wait')
|
||||
>>> shipment_int_1.state
|
||||
'waiting'
|
||||
|
||||
>>> shipment_out_1 = ShipmentOut()
|
||||
>>> shipment_out_1.planned_date = today
|
||||
>>> shipment_out_1.customer = customer
|
||||
>>> move = shipment_out_1.outgoing_moves.new()
|
||||
>>> move.from_location = shipment_out_1.warehouse_output
|
||||
>>> move.to_location = shipment_out_1.customer_location
|
||||
>>> move.product = product
|
||||
>>> move.quantity = 2
|
||||
>>> move.unit_price = Decimal('10.0000')
|
||||
>>> move.currency = currency
|
||||
>>> shipment_out_1.click('wait')
|
||||
>>> shipment_out_1.state
|
||||
'waiting'
|
||||
|
||||
>>> shipment_int_2, = shipment_int_1.duplicate()
|
||||
>>> shipment_int_2.click('wait')
|
||||
>>> shipment_int_2.state
|
||||
'waiting'
|
||||
|
||||
>>> shipment_out_2, = shipment_out_1.duplicate()
|
||||
>>> shipment_out_2.click('wait')
|
||||
>>> shipment_out_2.state
|
||||
'waiting'
|
||||
|
||||
Run assignation cron::
|
||||
|
||||
>>> cron = Cron(method='ir.cron|stock_shipment_assign_try')
|
||||
>>> cron.interval_number = 1
|
||||
>>> cron.interval_type = 'days'
|
||||
>>> cron.click('run_once')
|
||||
|
||||
Check assignations::
|
||||
|
||||
>>> shipment_int_1.reload()
|
||||
>>> shipment_int_1.state
|
||||
'assigned'
|
||||
|
||||
>>> shipment_out_1.reload()
|
||||
>>> shipment_out_1.state
|
||||
'assigned'
|
||||
|
||||
>>> shipment_int_2.reload()
|
||||
>>> shipment_int_2.state
|
||||
'waiting'
|
||||
>>> shipment_int_2.partially_assigned
|
||||
True
|
||||
|
||||
>>> shipment_out_2.reload()
|
||||
>>> shipment_out_2.state
|
||||
'waiting'
|
||||
>>> shipment_out_2.partially_assigned
|
||||
False
|
||||
115
modules/stock/tests/scenario_stock_shipment_in.rst
Normal file
115
modules/stock/tests/scenario_stock_shipment_in.rst
Normal file
@@ -0,0 +1,115 @@
|
||||
==========================
|
||||
Stock Shipment In Scenario
|
||||
==========================
|
||||
|
||||
Imports::
|
||||
|
||||
>>> from decimal import Decimal
|
||||
|
||||
>>> from proteus import Model, Report
|
||||
>>> from trytond.modules.company.tests.tools import create_company
|
||||
>>> from trytond.modules.currency.tests.tools import get_currency
|
||||
>>> from trytond.tests.tools import activate_modules, assertNotEqual
|
||||
|
||||
Activate modules::
|
||||
|
||||
>>> config = activate_modules('stock', create_company)
|
||||
|
||||
>>> Location = Model.get('stock.location')
|
||||
>>> Party = Model.get('party.party')
|
||||
>>> ProductTemplate = Model.get('product.template')
|
||||
>>> ProductUom = Model.get('product.uom')
|
||||
>>> ShipmentIn = Model.get('stock.shipment.in')
|
||||
|
||||
Create supplier::
|
||||
|
||||
>>> supplier = Party(name='Supplier')
|
||||
>>> supplier.save()
|
||||
|
||||
Create product::
|
||||
|
||||
>>> unit, = ProductUom.find([('name', '=', "Unit")])
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = "Product"
|
||||
>>> template.default_uom = unit
|
||||
>>> template.type = 'goods'
|
||||
>>> template.list_price = Decimal('20')
|
||||
>>> template.save()
|
||||
>>> product, = template.products
|
||||
|
||||
Get stock locations::
|
||||
|
||||
>>> supplier_loc, = Location.find([('code', '=', 'SUP')])
|
||||
>>> input_loc, = Location.find([('code', '=', 'IN')])
|
||||
>>> storage_loc, = Location.find([('code', '=', 'STO')])
|
||||
|
||||
Create a shipment::
|
||||
|
||||
>>> shipment = ShipmentIn()
|
||||
>>> shipment.supplier = supplier
|
||||
>>> move = shipment.incoming_moves.new()
|
||||
>>> move.product = product
|
||||
>>> move.quantity = 10
|
||||
>>> move.from_location = supplier_loc
|
||||
>>> move.to_location = input_loc
|
||||
>>> move.unit_price = Decimal('5')
|
||||
>>> move.currency = get_currency()
|
||||
>>> shipment.save()
|
||||
>>> assertNotEqual(shipment.number, None)
|
||||
|
||||
>>> len(shipment.incoming_moves)
|
||||
1
|
||||
>>> len(shipment.inventory_moves)
|
||||
0
|
||||
|
||||
Receive the shipment::
|
||||
|
||||
>>> shipment.click('receive')
|
||||
>>> shipment.state
|
||||
'received'
|
||||
>>> [m.state for m in shipment.incoming_moves]
|
||||
['done']
|
||||
>>> [m.state for m in shipment.inventory_moves]
|
||||
['draft']
|
||||
|
||||
>>> restocking_list = Report('stock.shipment.in.restocking_list')
|
||||
>>> _ = restocking_list.execute([shipment])
|
||||
|
||||
Change inventory quantity and try to finish::
|
||||
|
||||
>>> inventory_move, = shipment.inventory_moves
|
||||
>>> inventory_move.quantity = 11
|
||||
>>> shipment.click('do')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ShipmentCheckQuantityWarning: ...
|
||||
>>> inventory_move.reload()
|
||||
>>> inventory_move.quantity = 10
|
||||
>>> inventory_move.save()
|
||||
|
||||
Add extra product to inventory and try to finish::
|
||||
|
||||
>>> product2, = product.duplicate()
|
||||
|
||||
>>> move = shipment.inventory_moves.new()
|
||||
>>> move.product = product2
|
||||
>>> move.quantity = 1
|
||||
>>> move.from_location = input_loc
|
||||
>>> move.to_location = storage_loc
|
||||
>>> shipment.click('do')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ShipmentCheckQuantityWarning: ...
|
||||
>>> move = shipment.inventory_moves[-1]
|
||||
>>> shipment.inventory_moves.remove(move)
|
||||
>>> shipment.save()
|
||||
|
||||
Finish the shipment::
|
||||
|
||||
>>> shipment.click('do')
|
||||
>>> shipment.state
|
||||
'done'
|
||||
>>> len(shipment.incoming_moves)
|
||||
1
|
||||
>>> [m.state for m in shipment.inventory_moves]
|
||||
['done']
|
||||
78
modules/stock/tests/scenario_stock_shipment_in_return.rst
Normal file
78
modules/stock/tests/scenario_stock_shipment_in_return.rst
Normal file
@@ -0,0 +1,78 @@
|
||||
=================================
|
||||
Stock Shipment In Return Scenario
|
||||
=================================
|
||||
|
||||
Imports::
|
||||
|
||||
>>> import datetime as dt
|
||||
>>> from decimal import Decimal
|
||||
|
||||
>>> from proteus import Model
|
||||
>>> from trytond.modules.company.tests.tools import create_company
|
||||
>>> from trytond.modules.currency.tests.tools import get_currency
|
||||
>>> from trytond.tests.tools import activate_modules, assertEqual, assertNotEqual
|
||||
|
||||
>>> today = dt.date.today()
|
||||
>>> yesterday = today - dt.timedelta(days=1)
|
||||
|
||||
Activate modules::
|
||||
|
||||
>>> config = activate_modules('stock', create_company)
|
||||
|
||||
Create supplier::
|
||||
|
||||
>>> Party = Model.get('party.party')
|
||||
>>> supplier = Party(name='Supplier')
|
||||
>>> supplier.save()
|
||||
|
||||
Create product::
|
||||
|
||||
>>> ProductUom = Model.get('product.uom')
|
||||
>>> ProductTemplate = Model.get('product.template')
|
||||
>>> Product = Model.get('product.product')
|
||||
>>> unit, = ProductUom.find([('name', '=', 'Unit')])
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = 'Product'
|
||||
>>> template.default_uom = unit
|
||||
>>> template.type = 'goods'
|
||||
>>> template.list_price = Decimal('20')
|
||||
>>> template.save()
|
||||
>>> product, = template.products
|
||||
|
||||
Get stock locations::
|
||||
|
||||
>>> Location = Model.get('stock.location')
|
||||
>>> storage_loc, = Location.find([('code', '=', 'STO')])
|
||||
>>> supplier_loc, = Location.find([('code', '=', 'SUP')])
|
||||
|
||||
Create Shipment In::
|
||||
|
||||
>>> ShipmentInReturn = Model.get('stock.shipment.in.return')
|
||||
>>> shipment_return = ShipmentInReturn()
|
||||
>>> shipment_return.planned_date = yesterday
|
||||
>>> shipment_return.supplier = supplier
|
||||
>>> shipment_return.from_location = storage_loc
|
||||
>>> move = shipment_return.moves.new()
|
||||
>>> move.product = product
|
||||
>>> move.unit = unit
|
||||
>>> move.quantity = 1
|
||||
>>> move.from_location = storage_loc
|
||||
>>> move.to_location = supplier_loc
|
||||
>>> move.unit_price = Decimal('1')
|
||||
>>> move.currency = get_currency()
|
||||
>>> shipment_return.save()
|
||||
>>> shipment_return.number
|
||||
>>> shipment_return.click('wait')
|
||||
>>> shipment_return.state
|
||||
'waiting'
|
||||
>>> assertNotEqual(shipment_return.number, None)
|
||||
|
||||
Reschedule shipment::
|
||||
|
||||
>>> Cron = Model.get('ir.cron')
|
||||
>>> cron = Cron(method='stock.shipment.in.return|reschedule')
|
||||
>>> cron.interval_number = 1
|
||||
>>> cron.interval_type = 'months'
|
||||
>>> cron.click('run_once')
|
||||
>>> shipment_return.reload()
|
||||
>>> assertEqual(shipment_return.planned_date, today)
|
||||
@@ -0,0 +1,81 @@
|
||||
=================================================
|
||||
Stock Shipment In Same Storage and Input Scenario
|
||||
=================================================
|
||||
|
||||
Imports::
|
||||
|
||||
>>> from decimal import Decimal
|
||||
|
||||
>>> from proteus import Model
|
||||
>>> from trytond.modules.company.tests.tools import create_company
|
||||
>>> from trytond.modules.currency.tests.tools import get_currency
|
||||
>>> from trytond.tests.tools import activate_modules
|
||||
|
||||
Activate modules::
|
||||
|
||||
>>> config = activate_modules('stock', create_company)
|
||||
|
||||
Create supplier::
|
||||
|
||||
>>> Party = Model.get('party.party')
|
||||
>>> supplier = Party(name='Supplier')
|
||||
>>> supplier.save()
|
||||
|
||||
Create product::
|
||||
|
||||
>>> ProductUom = Model.get('product.uom')
|
||||
>>> ProductTemplate = Model.get('product.template')
|
||||
>>> unit, = ProductUom.find([('name', '=', 'Unit')])
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = 'Product'
|
||||
>>> template.default_uom = unit
|
||||
>>> template.type = 'goods'
|
||||
>>> template.list_price = Decimal('20')
|
||||
>>> template.save()
|
||||
>>> product, = template.products
|
||||
|
||||
Get stock locations::
|
||||
|
||||
>>> Location = Model.get('stock.location')
|
||||
>>> warehouse_loc, = Location.find([('code', '=', 'WH')])
|
||||
>>> supplier_loc, = Location.find([('code', '=', 'SUP')])
|
||||
>>> storage_loc, = Location.find([('code', '=', 'STO')])
|
||||
>>> storage1 = Location(name="Storage 1", parent=storage_loc)
|
||||
>>> storage1.save()
|
||||
|
||||
Use storage location as input location::
|
||||
|
||||
>>> warehouse_loc.input_location = storage_loc
|
||||
>>> warehouse_loc.save()
|
||||
|
||||
Create Shipment In::
|
||||
|
||||
>>> ShipmentIn = Model.get('stock.shipment.in')
|
||||
>>> shipment_in = ShipmentIn()
|
||||
>>> shipment_in.supplier = supplier
|
||||
>>> shipment_in.warehouse = warehouse_loc
|
||||
>>> move = shipment_in.incoming_moves.new()
|
||||
>>> move.product = product
|
||||
>>> move.unit = unit
|
||||
>>> move.quantity = 1
|
||||
>>> move.unit_price = Decimal('5')
|
||||
>>> move.currency = get_currency()
|
||||
>>> move.from_location = supplier_loc
|
||||
>>> move.to_location = storage1
|
||||
>>> shipment_in.save()
|
||||
|
||||
>>> len(shipment_in.incoming_moves)
|
||||
1
|
||||
>>> len(shipment_in.inventory_moves)
|
||||
0
|
||||
|
||||
Incoming moves are done when receiving the shipment::
|
||||
|
||||
>>> shipment_in.click('receive')
|
||||
>>> shipment_in.state
|
||||
'done'
|
||||
>>> move, = shipment_in.incoming_moves
|
||||
>>> move.state
|
||||
'done'
|
||||
>>> len(shipment_in.inventory_moves)
|
||||
0
|
||||
141
modules/stock/tests/scenario_stock_shipment_internal.rst
Normal file
141
modules/stock/tests/scenario_stock_shipment_internal.rst
Normal file
@@ -0,0 +1,141 @@
|
||||
================================
|
||||
Stock Shipment Internal Scenario
|
||||
================================
|
||||
|
||||
Imports::
|
||||
|
||||
>>> import datetime as dt
|
||||
>>> from decimal import Decimal
|
||||
|
||||
>>> from proteus import Model, Report
|
||||
>>> from trytond.modules.company.tests.tools import create_company
|
||||
>>> from trytond.tests.tools import (
|
||||
... activate_modules, assertEqual, assertNotEqual, set_user)
|
||||
|
||||
>>> today = dt.date.today()
|
||||
>>> yesterday = today - dt.timedelta(days=1)
|
||||
>>> tomorrow = today + dt.timedelta(days=1)
|
||||
|
||||
Activate modules::
|
||||
|
||||
>>> config = activate_modules('stock', create_company)
|
||||
|
||||
>>> Employee = Model.get('company.employee')
|
||||
>>> Party = Model.get('party.party')
|
||||
>>> User = Model.get('res.user')
|
||||
|
||||
Set employee::
|
||||
|
||||
>>> employee_party = Party(name="Employee")
|
||||
>>> employee_party.save()
|
||||
>>> employee = Employee(party=employee_party)
|
||||
>>> employee.save()
|
||||
>>> user = User(config.user)
|
||||
>>> user.employees.append(employee)
|
||||
>>> user.employee = employee
|
||||
>>> user.save()
|
||||
>>> set_user(user.id)
|
||||
|
||||
Create product::
|
||||
|
||||
>>> ProductUom = Model.get('product.uom')
|
||||
>>> ProductTemplate = Model.get('product.template')
|
||||
>>> Product = Model.get('product.product')
|
||||
>>> unit, = ProductUom.find([('name', '=', 'Unit')])
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = 'Product'
|
||||
>>> template.default_uom = unit
|
||||
>>> template.type = 'goods'
|
||||
>>> template.list_price = Decimal('20')
|
||||
>>> template.save()
|
||||
>>> product, = template.products
|
||||
|
||||
Get stock locations::
|
||||
|
||||
>>> Location = Model.get('stock.location')
|
||||
>>> lost_found_loc, = Location.find([('type', '=', 'lost_found')])
|
||||
>>> storage_loc, = Location.find([('code', '=', 'STO')])
|
||||
>>> internal_loc = Location(
|
||||
... name="Internal", type='storage', parent=storage_loc.parent)
|
||||
>>> internal_loc.save()
|
||||
|
||||
Create Internal Shipment::
|
||||
|
||||
>>> Shipment = Model.get('stock.shipment.internal')
|
||||
>>> StockMove = Model.get('stock.move')
|
||||
>>> shipment = Shipment()
|
||||
>>> shipment.planned_date = today
|
||||
>>> shipment.from_location = internal_loc
|
||||
>>> shipment.to_location = storage_loc
|
||||
>>> move = shipment.moves.new()
|
||||
>>> move.product = product
|
||||
>>> move.quantity = 1
|
||||
>>> move.from_location = internal_loc
|
||||
>>> move.to_location = storage_loc
|
||||
>>> shipment.save()
|
||||
>>> shipment.number
|
||||
>>> shipment.assigned_by
|
||||
>>> shipment.done_by
|
||||
|
||||
>>> shipment.click('wait')
|
||||
>>> shipment.state
|
||||
'waiting'
|
||||
>>> assertNotEqual(shipment.number, None)
|
||||
>>> shipment.click('assign_try')
|
||||
>>> shipment.state
|
||||
'waiting'
|
||||
>>> shipment.assigned_by
|
||||
>>> shipment.done_by
|
||||
|
||||
>>> report = Report('stock.shipment.internal.report')
|
||||
>>> _ = report.execute([shipment])
|
||||
|
||||
Create Internal Shipment from lost_found location::
|
||||
|
||||
>>> lost_found_shipment = Shipment()
|
||||
>>> lost_found_shipment.planned_date = today
|
||||
>>> lost_found_shipment.from_location = lost_found_loc
|
||||
>>> lost_found_shipment.to_location = internal_loc
|
||||
>>> move = StockMove()
|
||||
>>> move = lost_found_shipment.moves.new()
|
||||
>>> move.product = product
|
||||
>>> move.unit = unit
|
||||
>>> move.quantity = 2
|
||||
>>> move.from_location = lost_found_loc
|
||||
>>> move.to_location = internal_loc
|
||||
>>> lost_found_shipment.click('wait')
|
||||
>>> lost_found_shipment.click('assign_try')
|
||||
>>> lost_found_shipment.state
|
||||
'assigned'
|
||||
>>> lost_found_shipment.click('do')
|
||||
>>> lost_found_shipment.state
|
||||
'done'
|
||||
|
||||
Check that now we can finish the older shipment::
|
||||
|
||||
>>> shipment.click('assign_try')
|
||||
>>> assertEqual(shipment.assigned_by, employee)
|
||||
>>> shipment.done_by
|
||||
|
||||
>>> shipment.click('do')
|
||||
>>> shipment.state
|
||||
'done'
|
||||
>>> assertEqual(shipment.done_by, employee)
|
||||
|
||||
Duplicate Internal Shipment::
|
||||
|
||||
>>> shipment_copy, = shipment.duplicate()
|
||||
>>> len(shipment_copy.moves)
|
||||
1
|
||||
|
||||
Reschedule shipment::
|
||||
|
||||
>>> shipment_copy.planned_date = yesterday
|
||||
>>> shipment_copy.click('wait')
|
||||
>>> Cron = Model.get('ir.cron')
|
||||
>>> cron = Cron(method='stock.shipment.internal|reschedule')
|
||||
>>> cron.interval_number = 1
|
||||
>>> cron.interval_type = 'months'
|
||||
>>> cron.click('run_once')
|
||||
>>> shipment_copy.reload()
|
||||
>>> assertEqual(shipment_copy.planned_date, today)
|
||||
@@ -0,0 +1,98 @@
|
||||
=============================================
|
||||
Stock Shipment Internal with Transit Scenario
|
||||
=============================================
|
||||
|
||||
Imports::
|
||||
|
||||
>>> import datetime as dt
|
||||
>>> from decimal import Decimal
|
||||
|
||||
>>> from proteus import Model
|
||||
>>> from trytond.modules.company.tests.tools import create_company
|
||||
>>> from trytond.tests.tools import activate_modules, assertEqual
|
||||
|
||||
>>> today = dt.date.today()
|
||||
>>> yesterday = today - dt.timedelta(days=1)
|
||||
>>> tomorrow = today + dt.timedelta(days=1)
|
||||
|
||||
Activate modules::
|
||||
|
||||
>>> config = activate_modules('stock', create_company)
|
||||
|
||||
>>> ProductTemplate = Model.get('product.template')
|
||||
>>> ProductUom = Model.get('product.uom')
|
||||
>>> Shipment = Model.get('stock.shipment.internal')
|
||||
|
||||
Create product::
|
||||
|
||||
>>> unit, = ProductUom.find([('name', '=', 'Unit')])
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = "Product"
|
||||
>>> template.default_uom = unit
|
||||
>>> template.type = 'goods'
|
||||
>>> template.list_price = Decimal('20')
|
||||
>>> template.save()
|
||||
>>> product, = template.products
|
||||
|
||||
Get stock locations::
|
||||
|
||||
>>> Location = Model.get('stock.location')
|
||||
>>> warehouse1, = Location.find([('type', '=', 'warehouse')])
|
||||
>>> warehouse2, = warehouse1.duplicate()
|
||||
|
||||
Add lead time between warehouses::
|
||||
|
||||
>>> LeadTime = Model.get('stock.location.lead_time')
|
||||
>>> lead_time = LeadTime()
|
||||
>>> lead_time.warehouse_from = warehouse1
|
||||
>>> lead_time.warehouse_to = warehouse2
|
||||
>>> lead_time.lead_time = dt.timedelta(1)
|
||||
>>> lead_time.save()
|
||||
|
||||
Create Internal Shipment with lead time::
|
||||
|
||||
>>> shipment = Shipment()
|
||||
>>> shipment.planned_date = tomorrow
|
||||
>>> shipment.from_location = warehouse1.storage_location
|
||||
>>> shipment.to_location = warehouse2.storage_location
|
||||
>>> bool(shipment.transit_location)
|
||||
True
|
||||
>>> assertEqual(shipment.planned_start_date, today)
|
||||
>>> move = shipment.moves.new()
|
||||
>>> move.product = product
|
||||
>>> move.quantity = 2
|
||||
>>> move.from_location = shipment.from_location
|
||||
>>> move.to_location = shipment.to_location
|
||||
>>> shipment.click('wait')
|
||||
>>> len(shipment.moves)
|
||||
2
|
||||
>>> outgoing_move, = shipment.outgoing_moves
|
||||
>>> outgoing_move.quantity
|
||||
2.0
|
||||
>>> assertEqual(outgoing_move.from_location, shipment.from_location)
|
||||
>>> assertEqual(outgoing_move.to_location, shipment.transit_location)
|
||||
>>> assertEqual(outgoing_move.planned_date, today)
|
||||
>>> incoming_move, = shipment.incoming_moves
|
||||
>>> incoming_move.quantity
|
||||
2.0
|
||||
>>> assertEqual(incoming_move.from_location, shipment.transit_location)
|
||||
>>> assertEqual(incoming_move.to_location, shipment.to_location)
|
||||
>>> assertEqual(incoming_move.planned_date, tomorrow)
|
||||
|
||||
>>> outgoing_move.quantity = 1
|
||||
>>> outgoing_move.save()
|
||||
|
||||
>>> shipment.click('assign_force')
|
||||
>>> shipment.effective_start_date = yesterday
|
||||
>>> shipment.click('pack')
|
||||
>>> shipment.click('ship')
|
||||
>>> incoming_move, = shipment.incoming_moves
|
||||
>>> incoming_move.quantity
|
||||
1.0
|
||||
>>> shipment.outgoing_moves[0].state
|
||||
'done'
|
||||
>>> assertEqual(shipment.outgoing_moves[0].effective_date, yesterday)
|
||||
>>> shipment.click('do')
|
||||
>>> shipment.incoming_moves[0].state
|
||||
'done'
|
||||
>>> assertEqual(shipment.incoming_moves[0].effective_date, today)
|
||||
284
modules/stock/tests/scenario_stock_shipment_out.rst
Normal file
284
modules/stock/tests/scenario_stock_shipment_out.rst
Normal file
@@ -0,0 +1,284 @@
|
||||
===========================
|
||||
Stock Shipment Out Scenario
|
||||
===========================
|
||||
|
||||
Imports::
|
||||
|
||||
>>> import datetime as dt
|
||||
>>> from decimal import Decimal
|
||||
|
||||
>>> from proteus import Model, Report
|
||||
>>> from trytond.modules.company.tests.tools import create_company
|
||||
>>> from trytond.modules.currency.tests.tools import get_currency
|
||||
>>> from trytond.tests.tools import (
|
||||
... activate_modules, assertEqual, assertNotEqual, set_user)
|
||||
|
||||
>>> today = dt.date.today()
|
||||
>>> yesterday = today - dt.timedelta(days=1)
|
||||
|
||||
Activate modules::
|
||||
|
||||
>>> config = activate_modules('stock', create_company)
|
||||
|
||||
>>> Employee = Model.get('company.employee')
|
||||
>>> Party = Model.get('party.party')
|
||||
>>> User = Model.get('res.user')
|
||||
|
||||
Set employee::
|
||||
|
||||
>>> employee_party = Party(name="Employee")
|
||||
>>> employee_party.save()
|
||||
>>> employee = Employee(party=employee_party)
|
||||
>>> employee.save()
|
||||
>>> user = User(config.user)
|
||||
>>> user.employees.append(employee)
|
||||
>>> user.employee = employee
|
||||
>>> user.save()
|
||||
>>> set_user(user.id)
|
||||
|
||||
Get currency::
|
||||
|
||||
>>> currency = get_currency()
|
||||
|
||||
Create customer::
|
||||
|
||||
>>> Party = Model.get('party.party')
|
||||
>>> customer = Party(name='Customer')
|
||||
>>> customer.save()
|
||||
|
||||
Create product::
|
||||
|
||||
>>> ProductUom = Model.get('product.uom')
|
||||
>>> ProductTemplate = Model.get('product.template')
|
||||
>>> Product = Model.get('product.product')
|
||||
>>> unit, = ProductUom.find([('name', '=', 'Unit')])
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = 'Product'
|
||||
>>> template.default_uom = unit
|
||||
>>> template.type = 'goods'
|
||||
>>> template.list_price = Decimal('20')
|
||||
>>> template.save()
|
||||
>>> product, = template.products
|
||||
|
||||
Get stock locations::
|
||||
|
||||
>>> Location = Model.get('stock.location')
|
||||
>>> warehouse_loc, = Location.find([('code', '=', 'WH')])
|
||||
>>> supplier_loc, = Location.find([('code', '=', 'SUP')])
|
||||
>>> customer_loc, = Location.find([('code', '=', 'CUS')])
|
||||
>>> output_loc, = Location.find([('code', '=', 'OUT')])
|
||||
>>> storage_loc, = Location.find([('code', '=', 'STO')])
|
||||
|
||||
Create Shipment Out::
|
||||
|
||||
>>> ShipmentOut = Model.get('stock.shipment.out')
|
||||
>>> shipment_out = ShipmentOut()
|
||||
>>> shipment_out.planned_date = today
|
||||
>>> shipment_out.customer = customer
|
||||
>>> shipment_out.warehouse = warehouse_loc
|
||||
|
||||
Add two shipment lines of same product::
|
||||
|
||||
>>> StockMove = Model.get('stock.move')
|
||||
>>> shipment_out.outgoing_moves.extend([StockMove(), StockMove()])
|
||||
>>> for move in shipment_out.outgoing_moves:
|
||||
... move.product = product
|
||||
... move.unit = unit
|
||||
... move.quantity = 1
|
||||
... move.from_location = output_loc
|
||||
... move.to_location = customer_loc
|
||||
... move.unit_price = Decimal('1')
|
||||
... move.currency = currency
|
||||
>>> shipment_out.save()
|
||||
>>> shipment_out.number
|
||||
>>> shipment_out.picked_by
|
||||
>>> shipment_out.packed_by
|
||||
>>> shipment_out.shipped_by
|
||||
>>> shipment_out.done_by
|
||||
|
||||
Set the shipment state to waiting::
|
||||
|
||||
>>> shipment_out.click('wait')
|
||||
>>> shipment_out.state
|
||||
'waiting'
|
||||
>>> assertNotEqual(shipment_out.number, None)
|
||||
>>> len(shipment_out.outgoing_moves)
|
||||
2
|
||||
>>> len(shipment_out.inventory_moves)
|
||||
2
|
||||
>>> assertEqual(
|
||||
... {m.origin for m in shipment_out.inventory_moves},
|
||||
... {m for m in shipment_out.outgoing_moves})
|
||||
|
||||
Make 1 unit of the product available::
|
||||
|
||||
>>> incoming_move = StockMove()
|
||||
>>> incoming_move.product = product
|
||||
>>> incoming_move.unit = unit
|
||||
>>> incoming_move.quantity = 1
|
||||
>>> incoming_move.from_location = supplier_loc
|
||||
>>> incoming_move.to_location = storage_loc
|
||||
>>> incoming_move.planned_date = today
|
||||
>>> incoming_move.effective_date = today
|
||||
>>> incoming_move.unit_price = Decimal('1')
|
||||
>>> incoming_move.currency = currency
|
||||
>>> incoming_move.click('do')
|
||||
|
||||
Assign the shipment now::
|
||||
|
||||
>>> shipment_assign = shipment_out.click('assign_wizard')
|
||||
>>> len(shipment_assign.form.moves)
|
||||
1
|
||||
>>> shipment_assign.execute('end')
|
||||
>>> shipment_out.reload()
|
||||
>>> len(shipment_out.outgoing_moves)
|
||||
2
|
||||
>>> len(shipment_out.inventory_moves)
|
||||
2
|
||||
>>> states = [m.state for m in shipment_out.inventory_moves]
|
||||
>>> states.sort()
|
||||
>>> states
|
||||
['assigned', 'draft']
|
||||
>>> effective_dates = [m.effective_date for m in
|
||||
... shipment_out.inventory_moves]
|
||||
>>> len(set(effective_dates))
|
||||
1
|
||||
>>> planned_dates = [m.planned_date for m in
|
||||
... shipment_out.outgoing_moves]
|
||||
>>> len(set(planned_dates))
|
||||
1
|
||||
|
||||
Ignore non assigned moves and pack shipment::
|
||||
|
||||
>>> shipment_assign = shipment_out.click('assign_wizard')
|
||||
>>> shipment_assign.execute('ignore')
|
||||
>>> sorted([m.quantity for m in shipment_out.inventory_moves])
|
||||
[0.0, 1.0]
|
||||
>>> shipment_out.picked_by
|
||||
>>> shipment_out.packed_by
|
||||
>>> shipment_out.shipped_by
|
||||
>>> shipment_out.done_by
|
||||
|
||||
>>> picking_list = Report('stock.shipment.out.picking_list')
|
||||
>>> _ = picking_list.execute([shipment_out])
|
||||
|
||||
>>> shipment_out.click('pick')
|
||||
>>> assertEqual(shipment_out.picked_by, employee)
|
||||
>>> shipment_out.packed_by
|
||||
>>> shipment_out.shipped_by
|
||||
>>> shipment_out.done_by
|
||||
|
||||
>>> shipment_out.click('pack')
|
||||
>>> assertEqual(shipment_out.packed_by, employee)
|
||||
>>> shipment_out.shipped_by
|
||||
>>> shipment_out.done_by
|
||||
>>> [m.state for m in shipment_out.outgoing_moves]
|
||||
['assigned']
|
||||
>>> len(shipment_out.inventory_moves)
|
||||
1
|
||||
>>> shipment_out.inventory_moves[0].state
|
||||
'done'
|
||||
>>> assertEqual(sum([m.quantity for m in shipment_out.inventory_moves]),
|
||||
... sum([m.quantity for m in shipment_out.outgoing_moves]))
|
||||
|
||||
>>> delivery_note = Report('stock.shipment.out.delivery_note')
|
||||
>>> _ = delivery_note.execute([shipment_out])
|
||||
|
||||
Set the state as Shipped::
|
||||
|
||||
>>> shipment_out.click('ship')
|
||||
>>> assertEqual(shipment_out.shipped_by, employee)
|
||||
>>> shipment_out.done_by
|
||||
|
||||
Set the state as Done::
|
||||
|
||||
>>> shipment_out.click('do')
|
||||
>>> assertEqual(shipment_out.done_by, employee)
|
||||
>>> [m.state for m in shipment_out.outgoing_moves]
|
||||
['done']
|
||||
>>> planned_dates = [m.planned_date for m in
|
||||
... shipment_out.outgoing_moves]
|
||||
>>> assertEqual(planned_dates, [today])
|
||||
>>> effective_dates = [m.effective_date for m in
|
||||
... shipment_out.outgoing_moves]
|
||||
>>> len(set(effective_dates))
|
||||
1
|
||||
>>> len(shipment_out.outgoing_moves)
|
||||
1
|
||||
>>> len(shipment_out.inventory_moves)
|
||||
1
|
||||
>>> shipment_out.inventory_moves[0].state
|
||||
'done'
|
||||
>>> assertEqual(sum([m.quantity for m in shipment_out.inventory_moves]),
|
||||
... sum([m.quantity for m in shipment_out.outgoing_moves]))
|
||||
|
||||
Create Shipment Out with effective date::
|
||||
|
||||
>>> ShipmentOut = Model.get('stock.shipment.out')
|
||||
>>> shipment_out = ShipmentOut()
|
||||
>>> shipment_out.planned_date = yesterday
|
||||
>>> shipment_out.effective_date = yesterday
|
||||
>>> shipment_out.customer = customer
|
||||
>>> shipment_out.warehouse = warehouse_loc
|
||||
>>> move = shipment_out.outgoing_moves.new()
|
||||
>>> move.product = product
|
||||
>>> move.unit = unit
|
||||
>>> move.quantity = 1
|
||||
>>> move.from_location = output_loc
|
||||
>>> move.to_location = customer_loc
|
||||
>>> move.unit_price = Decimal('1')
|
||||
>>> move.currency = currency
|
||||
>>> shipment_out.click('wait')
|
||||
|
||||
Make 1 unit of the product available::
|
||||
|
||||
>>> incoming_move = StockMove()
|
||||
>>> incoming_move.product = product
|
||||
>>> incoming_move.unit = unit
|
||||
>>> incoming_move.quantity = 1
|
||||
>>> incoming_move.from_location = supplier_loc
|
||||
>>> incoming_move.to_location = storage_loc
|
||||
>>> incoming_move.planned_date = yesterday
|
||||
>>> incoming_move.effective_date = yesterday
|
||||
>>> incoming_move.unit_price = Decimal('1')
|
||||
>>> incoming_move.currency = currency
|
||||
>>> incoming_move.click('do')
|
||||
|
||||
Finish the shipment::
|
||||
|
||||
>>> shipment_out.click('assign_try')
|
||||
>>> shipment_out.click('pick')
|
||||
>>> len(shipment_out.inventory_moves)
|
||||
1
|
||||
>>> len(shipment_out.outgoing_moves)
|
||||
1
|
||||
>>> shipment_out.click('pack')
|
||||
>>> shipment_out.click('pick')
|
||||
>>> len(shipment_out.inventory_moves)
|
||||
1
|
||||
>>> len(shipment_out.outgoing_moves)
|
||||
1
|
||||
>>> shipment_out.click('pack')
|
||||
|
||||
Finish the shipment::
|
||||
|
||||
>>> shipment_out.click('do')
|
||||
>>> shipment_out.state
|
||||
'done'
|
||||
>>> outgoing_move, = shipment_out.outgoing_moves
|
||||
>>> assertEqual(outgoing_move.effective_date, yesterday)
|
||||
>>> inventory_move, = shipment_out.inventory_moves
|
||||
>>> assertEqual(inventory_move.effective_date, yesterday)
|
||||
|
||||
Reschedule shipment::
|
||||
|
||||
>>> shipment_copy, = shipment_out.duplicate()
|
||||
>>> shipment_copy.planned_date = yesterday
|
||||
>>> shipment_copy.click('wait')
|
||||
>>> Cron = Model.get('ir.cron')
|
||||
>>> cron = Cron(method='stock.shipment.out|reschedule')
|
||||
>>> cron.interval_number = 1
|
||||
>>> cron.interval_type = 'months'
|
||||
>>> cron.click('run_once')
|
||||
>>> shipment_copy.reload()
|
||||
>>> assertEqual(shipment_copy.planned_date, today)
|
||||
89
modules/stock/tests/scenario_stock_shipment_out_return.rst
Normal file
89
modules/stock/tests/scenario_stock_shipment_out_return.rst
Normal file
@@ -0,0 +1,89 @@
|
||||
==================================
|
||||
Stock Shipment Out Return Scenario
|
||||
==================================
|
||||
|
||||
Imports::
|
||||
|
||||
>>> from decimal import Decimal
|
||||
|
||||
>>> from proteus import Model, Report
|
||||
>>> from trytond.modules.company.tests.tools import create_company
|
||||
>>> from trytond.modules.currency.tests.tools import get_currency
|
||||
>>> from trytond.tests.tools import activate_modules, assertNotEqual
|
||||
|
||||
Activate modules::
|
||||
|
||||
>>> config = activate_modules('stock', create_company)
|
||||
|
||||
>>> Party = Model.get('party.party')
|
||||
>>> ProductUom = Model.get('product.uom')
|
||||
>>> ProductTemplate = Model.get('product.template')
|
||||
|
||||
Create customer::
|
||||
|
||||
>>> customer = Party(name='Customer')
|
||||
>>> customer.save()
|
||||
|
||||
Create product::
|
||||
|
||||
>>> unit, = ProductUom.find([('name', '=', 'Unit')])
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = "Product"
|
||||
>>> template.default_uom = unit
|
||||
>>> template.type = 'goods'
|
||||
>>> template.list_price = Decimal('20')
|
||||
>>> template.save()
|
||||
>>> product, = template.products
|
||||
|
||||
Get stock locations::
|
||||
|
||||
>>> Location = Model.get('stock.location')
|
||||
>>> warehouse_loc, = Location.find([('code', '=', 'WH')])
|
||||
>>> customer_loc, = Location.find([('code', '=', 'CUS')])
|
||||
>>> storage_loc, = Location.find([('code', '=', 'STO')])
|
||||
|
||||
Create Shipment Out Return::
|
||||
|
||||
>>> ShipmentOutReturn = Model.get('stock.shipment.out.return')
|
||||
>>> shipment = ShipmentOutReturn()
|
||||
>>> shipment.customer = customer
|
||||
>>> shipment.warehouse = warehouse_loc
|
||||
>>> move = shipment.incoming_moves.new()
|
||||
>>> move.product = product
|
||||
>>> move.unit = unit
|
||||
>>> move.quantity = 1
|
||||
>>> move.from_location = customer_loc
|
||||
>>> move.to_location = warehouse_loc.input_location
|
||||
>>> move.unit_price = Decimal('20')
|
||||
>>> move.currency = get_currency()
|
||||
>>> shipment.save()
|
||||
>>> assertNotEqual(shipment.number, None)
|
||||
|
||||
>>> len(shipment.incoming_moves)
|
||||
1
|
||||
>>> len(shipment.inventory_moves)
|
||||
0
|
||||
|
||||
Receive shipment::
|
||||
|
||||
>>> shipment.click('receive')
|
||||
>>> shipment.state
|
||||
'received'
|
||||
|
||||
>>> [m.state for m in shipment.incoming_moves]
|
||||
['done']
|
||||
>>> [m.state for m in shipment.inventory_moves]
|
||||
['draft']
|
||||
|
||||
>>> restocking_list = Report('stock.shipment.out.return.restocking_list')
|
||||
>>> _ = restocking_list.execute([shipment])
|
||||
|
||||
Finish the shipment::
|
||||
|
||||
>>> shipment.click('do')
|
||||
>>> shipment.state
|
||||
'done'
|
||||
>>> len(shipment.incoming_moves)
|
||||
1
|
||||
>>> [m.state for m in shipment.inventory_moves]
|
||||
['done']
|
||||
@@ -0,0 +1,82 @@
|
||||
=========================================================
|
||||
Stock Shipment Out Return Same Storage and Input Scenario
|
||||
=========================================================
|
||||
|
||||
Imports::
|
||||
|
||||
>>> from decimal import Decimal
|
||||
|
||||
>>> from proteus import Model
|
||||
>>> from trytond.modules.company.tests.tools import create_company
|
||||
>>> from trytond.modules.currency.tests.tools import get_currency
|
||||
>>> from trytond.tests.tools import activate_modules
|
||||
|
||||
Activate modules::
|
||||
|
||||
>>> config = activate_modules('stock', create_company)
|
||||
|
||||
Create customer::
|
||||
|
||||
>>> Party = Model.get('party.party')
|
||||
>>> customer = Party(name='Customer')
|
||||
>>> customer.save()
|
||||
|
||||
Create product::
|
||||
|
||||
>>> ProductUom = Model.get('product.uom')
|
||||
>>> ProductTemplate = Model.get('product.template')
|
||||
>>> Product = Model.get('product.product')
|
||||
>>> unit, = ProductUom.find([('name', '=', 'Unit')])
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = 'Product'
|
||||
>>> template.default_uom = unit
|
||||
>>> template.type = 'goods'
|
||||
>>> template.list_price = Decimal('20')
|
||||
>>> template.save()
|
||||
>>> product, = template.products
|
||||
|
||||
Get stock locations::
|
||||
|
||||
>>> Location = Model.get('stock.location')
|
||||
>>> warehouse_loc, = Location.find([('code', '=', 'WH')])
|
||||
>>> customer_loc, = Location.find([('code', '=', 'CUS')])
|
||||
>>> storage_loc, = Location.find([('code', '=', 'STO')])
|
||||
>>> storage1 = Location(name="Storage 1", parent=storage_loc)
|
||||
>>> storage1.save()
|
||||
|
||||
Use storage location as input location::
|
||||
|
||||
>>> warehouse_loc.input_location = storage_loc
|
||||
>>> warehouse_loc.save()
|
||||
|
||||
Create Shipment Out Return::
|
||||
|
||||
>>> ShipmentOutReturn = Model.get('stock.shipment.out.return')
|
||||
>>> shipment = ShipmentOutReturn()
|
||||
>>> shipment.customer = customer
|
||||
>>> shipment.warehouse = warehouse_loc
|
||||
>>> move = shipment.incoming_moves.new()
|
||||
>>> move.product = product
|
||||
>>> move.unit = unit
|
||||
>>> move.quantity = 1
|
||||
>>> move.from_location = customer_loc
|
||||
>>> move.to_location = storage1
|
||||
>>> move.unit_price = Decimal('20')
|
||||
>>> move.currency = get_currency()
|
||||
>>> shipment.save()
|
||||
|
||||
>>> len(shipment.incoming_moves)
|
||||
1
|
||||
>>> len(shipment.inventory_moves)
|
||||
0
|
||||
|
||||
Shipment is done when receiving::
|
||||
|
||||
>>> shipment.click('receive')
|
||||
>>> shipment.state
|
||||
'done'
|
||||
>>> move, = shipment.incoming_moves
|
||||
>>> move.state
|
||||
'done'
|
||||
>>> len(shipment.inventory_moves)
|
||||
0
|
||||
@@ -0,0 +1,117 @@
|
||||
===================================================
|
||||
Stock Shipment Out Same Storage and Output Scenario
|
||||
===================================================
|
||||
|
||||
Imports::
|
||||
|
||||
>>> from decimal import Decimal
|
||||
|
||||
>>> from proteus import Model
|
||||
>>> from trytond.modules.company.tests.tools import create_company
|
||||
>>> from trytond.modules.currency.tests.tools import get_currency
|
||||
>>> from trytond.tests.tools import activate_modules
|
||||
|
||||
Activate modules::
|
||||
|
||||
>>> config = activate_modules('stock', create_company)
|
||||
|
||||
>>> Move = Model.get('stock.move')
|
||||
|
||||
Create customer::
|
||||
|
||||
>>> Party = Model.get('party.party')
|
||||
>>> customer = Party(name='Customer')
|
||||
>>> customer.save()
|
||||
|
||||
Create product::
|
||||
|
||||
>>> ProductUom = Model.get('product.uom')
|
||||
>>> ProductTemplate = Model.get('product.template')
|
||||
>>> Product = Model.get('product.product')
|
||||
>>> unit, = ProductUom.find([('name', '=', 'Unit')])
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = 'Product'
|
||||
>>> template.default_uom = unit
|
||||
>>> template.type = 'goods'
|
||||
>>> template.list_price = Decimal('20')
|
||||
>>> template.save()
|
||||
>>> product, = template.products
|
||||
|
||||
Get stock locations::
|
||||
|
||||
>>> Location = Model.get('stock.location')
|
||||
>>> warehouse_loc, = Location.find([('code', '=', 'WH')])
|
||||
>>> customer_loc, = Location.find([('code', '=', 'CUS')])
|
||||
>>> storage_loc, = Location.find([('code', '=', 'STO')])
|
||||
>>> warehouse_loc.output_location = storage_loc
|
||||
>>> warehouse_loc.save()
|
||||
|
||||
Create Shipment Out::
|
||||
|
||||
>>> ShipmentOut = Model.get('stock.shipment.out')
|
||||
>>> shipment_out = ShipmentOut()
|
||||
>>> shipment_out.customer = customer
|
||||
>>> shipment_out.warehouse = warehouse_loc
|
||||
>>> move = shipment_out.outgoing_moves.new()
|
||||
>>> move.product = product
|
||||
>>> move.unit = unit
|
||||
>>> move.quantity = 1
|
||||
>>> move.unit_price = Decimal('5')
|
||||
>>> move.currency = get_currency()
|
||||
>>> move.from_location = storage_loc
|
||||
>>> move.to_location = customer_loc
|
||||
>>> shipment_out.save()
|
||||
|
||||
>>> len(shipment_out.outgoing_moves)
|
||||
1
|
||||
>>> len(shipment_out.inventory_moves)
|
||||
0
|
||||
|
||||
Set the shipment state to waiting::
|
||||
|
||||
>>> shipment_out.click('wait')
|
||||
>>> shipment_out.state
|
||||
'waiting'
|
||||
>>> len(shipment_out.outgoing_moves)
|
||||
1
|
||||
>>> len(shipment_out.inventory_moves)
|
||||
0
|
||||
|
||||
Try to assign::
|
||||
|
||||
>>> shipment_out.click('assign_try')
|
||||
>>> shipment_out.state
|
||||
'waiting'
|
||||
>>> move, = shipment_out.outgoing_moves
|
||||
>>> move.state
|
||||
'draft'
|
||||
|
||||
Fill storage location::
|
||||
|
||||
>>> move = Move()
|
||||
>>> move.from_location = warehouse_loc.lost_found_location
|
||||
>>> move.to_location = storage_loc
|
||||
>>> move.product = product
|
||||
>>> move.quantity = 1
|
||||
>>> move.click('do')
|
||||
>>> move.state
|
||||
'done'
|
||||
|
||||
Try to assign again::
|
||||
|
||||
>>> shipment_out.click('assign_try')
|
||||
>>> shipment_out.state
|
||||
'assigned'
|
||||
>>> move, = shipment_out.outgoing_moves
|
||||
>>> move.state
|
||||
'assigned'
|
||||
|
||||
Pack the shipment::
|
||||
|
||||
>>> shipment_out.click('pack')
|
||||
>>> shipment_out.state
|
||||
'packed'
|
||||
>>> len(shipment_out.outgoing_moves)
|
||||
1
|
||||
>>> len(shipment_out.inventory_moves)
|
||||
0
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user